#include "scsi_raw.h"
#include <string.h>
#include <scsi.h>
#include <malloc.h>
#include <pnp_devfs.h>
#include <stdio.h>
device_manager_info *pnp;
static status_t
raw_open(void *device_cookie, uint32 flags, void **handle_cookie)
{
*handle_cookie = device_cookie;
return B_OK;
}
static status_t
raw_close(void *cookie)
{
return B_OK;
}
static status_t
raw_free(void *cookie)
{
return B_OK;
}
#if 0
static status_t
raw_control(void *cookie, uint32 op, void *data, size_t len)
{
return B_OK;
}
#endif
static status_t
raw_read(void *cookie, off_t position, void *data, size_t *numBytes)
{
return B_ERROR;
}
static status_t
raw_write(void *cookie, off_t position, const void *data, size_t *numBytes)
{
return B_ERROR;
}
static status_t
raw_command(raw_device_info *device, raw_device_command *cmd)
{
scsi_ccb *request;
SHOW_FLOW0(3, "");
request = device->scsi->alloc_ccb(device->scsi_device);
if (request == NULL)
return B_NO_MEMORY;
request->flags = 0;
if (cmd->flags & B_RAW_DEVICE_DATA_IN)
request->flags |= SCSI_DIR_IN;
else if (cmd->data_length)
request->flags |= SCSI_DIR_OUT;
else
request->flags |= SCSI_DIR_NONE;
request->data = cmd->data;
request->sg_list = NULL;
request->data_len = cmd->data_length;
request->sort = -1;
request->timeout = cmd->timeout;
memcpy(request->cdb, cmd->command, SCSI_MAX_CDB_SIZE);
request->cdb_len = cmd->command_length;
device->scsi->sync_io(request);
cmd->cam_status = request->subsys_status;
cmd->scsi_status = request->device_status;
if ((request->subsys_status & SCSI_AUTOSNS_VALID) != 0 && cmd->sense_data) {
memcpy(cmd->sense_data, request->sense,
min((int32)cmd->sense_data_length, SCSI_MAX_SENSE_SIZE - request->sense_resid));
}
if ((cmd->flags & B_RAW_DEVICE_REPORT_RESIDUAL) != 0) {
cmd->data_length = cmd->data_length - request->data_resid;
cmd->sense_data_length = SCSI_MAX_SENSE_SIZE - request->sense_resid;
}
device->scsi->free_ccb(request);
return B_OK;
}
static status_t
raw_ioctl(raw_device_info *device, int op, void *buffer, size_t length)
{
status_t res;
switch (op) {
case B_RAW_DEVICE_COMMAND:
res = raw_command(device, buffer);
break;
default:
res = B_DEV_INVALID_IOCTL;
}
SHOW_FLOW(4, "%x: %s", op, strerror(res));
return res;
}
static status_t
raw_init_device(device_node_handle node, void *user_cookie, void **cookie)
{
raw_device_info *device;
status_t res;
SHOW_FLOW0(3, "");
device = (raw_device_info *)calloc(1, sizeof(*device));
if (device == NULL)
return B_NO_MEMORY;
device->node = node;
res = pnp->init_driver(pnp->get_parent(node), NULL,
(driver_module_info **)&device->scsi, (void **)&device->scsi_device);
if (res != B_OK)
goto err;
SHOW_FLOW0(3, "done");
*cookie = device;
return B_OK;
err:
free(device);
return res;
}
static status_t
raw_uninit_device(raw_device_info *device)
{
pnp->uninit_driver(pnp->get_parent(device->node));
free(device);
return B_OK;
}
static status_t
raw_device_added(device_node_handle node)
{
uint8 path_id, target_id, target_lun;
char name[100];
SHOW_FLOW0(3, "");
if (pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &path_id, true) != B_OK
|| pnp->get_attr_uint8(node, SCSI_DEVICE_TARGET_ID_ITEM, &target_id, true) != B_OK
|| pnp->get_attr_uint8(node, SCSI_DEVICE_TARGET_LUN_ITEM, &target_lun, true) != B_OK)
return B_ERROR;
sprintf(name, "bus/scsi/%d/%d/%d/raw",
path_id, target_id, target_lun);
SHOW_FLOW(3, "name=%s", name);
{
device_attr attrs[] = {
{ B_DRIVER_MODULE, B_STRING_TYPE, { .string = SCSI_RAW_MODULE_NAME }},
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { .string = "raw" }},
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { .string = PNP_DEVFS_MODULE_NAME }},
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { .string = name }},
{ NULL }
};
return pnp->register_device(node, attrs, NULL, &node);
}
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
{}
};
pnp_devfs_driver_info scsi_raw_module = {
{
{
SCSI_RAW_MODULE_NAME,
0,
std_ops
},
NULL,
raw_device_added,
raw_init_device,
(status_t (*) (void *))raw_uninit_device,
NULL
},
(status_t (*)(void *, uint32, void **)) &raw_open,
raw_close,
raw_free,
(status_t (*)(void *, uint32, void *, size_t)) &raw_ioctl,
raw_read,
raw_write,
NULL,
NULL,
NULL,
NULL
};
module_info *modules[] = {
(module_info *)&scsi_raw_module,
NULL
};