📄 devmscd.c
字号:
func_debug(("devmscd_read_urb_complete(%p)\n",urb))
switch(dev->state) {
case DEVMSCD_IDLE:
/* This is a CBW packet */
dev->tx_residue = (dev->cbw[8] | (dev->cbw[9] << 8));
dev->tx_residue |= ((dev->cbw[10] << 16) | (dev->cbw[11] << 24));
/* Copy the CBW tag to the CSW tag */
dev->csw[4] = dev->cbw[4];
dev->csw[5] = dev->cbw[5];
dev->csw[6] = dev->cbw[6];
dev->csw[7] = dev->cbw[7];
devmscd_change_state(dev, DEVMSCD_CBW);
/* send this command to the mass storage bridge */
mscd_fill_req( (&bridge_req), MSCD_COMMAND,
(&dev->cbw[DEVMSCD_CBW_WRAPPER]),
(DEVMSCD_CBW_LENGTH - DEVMSCD_CBW_WRAPPER),
devmscd_set_command_res, NULL);
mscdbridge_submit_req(&bridge_req);
if(dev->cbw[12] & DEVMSCD_CBWFLAG_IN) {
/* Data to Host, so Data out from Device */
devmscd_change_state(dev, DEVMSCD_DATA_OUT);
} else {
/* Data from Host, so Data in to Device */
devmscd_change_state(dev, DEVMSCD_DATA_IN);
}
break;
case DEVMSCD_DATA_IN:
dev->tx_residue -= urb->actual_length;
req = bridge_read_req;
if(req) {
/* Call the call back function */
req->res_data_len = urb->actual_length;
req->status = MSCD_SUCCESS;
bridge_read_req = NULL;
if(req->complete) req->complete(req);
}
break;
}
urb->status = PDC_URB_COMPLETE;
} /* End of devmscd_read_urb_complete */
/*
* Call the call back function of the bridge request
* If the status stage is already sent by the bridge, finish the status
* stage
*/
void devmscd_write_urb_complete(struct pdc_urb *urb)
{
struct devmscd_device *dev = &devmscd_dev;
mscd_req_t *req;
struct pdc_pipe_opr bulk_pipe_opr;
func_debug(("devmscd_write_urb_complete(%p)\n",urb))
dev->tx_residue -= urb->actual_length;
if(dev->status_queue) {
if(dev->tx_residue) {
/* Send a stall */
bulk_pipe_opr.handle = dev->data_out_pipe;
bulk_pipe_opr.context = (unsigned long) dev;
bulk_pipe_opr.opr = PDC_PIPE_STALL;
mdelay(3);
pdc_pipe_operation(&bulk_pipe_opr);
dev->csw[8] = dev->tx_residue & 0xFF;
dev->csw[9] = (dev->tx_residue >> 8) & 0xFF;
dev->csw[10] = (dev->tx_residue >> 16) & 0xFF;
dev->csw[11] = (dev->tx_residue >> 24) & 0xFF;
}
/* Already status is received, so send the status */
devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH);
devmscd_write_data(dev->csw, DEVMSCD_CSW_LENGTH);
devmscd_change_state(dev, DEVMSCD_IDLE);
dev->status_queue = 0;
}
if(devmscd_dev.state != DEVMSCD_CSW) {
/* Update the transfer residue */
// devmscd_dev.tx_residue -= urb->actual_length;
req = bridge_write_req;
if(req) {
/* call the bridge call back function */
req->res_data_len = urb->actual_length;
req->status = MSCD_SUCCESS;
bridge_write_req = NULL;
if(req->complete) req->complete(req);
}
}
urb->status = PDC_URB_COMPLETE;
} /* End of devmscd_write_urb_complete */
/*
* Bulk Only Trnasport, Mass storage reset.
* Go back to Idle state, no transfer residue.
*/
void devmscd_reset(struct devmscd_device *dev)
{
func_debug(("devmscd_reset(%p)\n",dev))
devmscd_change_state(dev, DEVMSCD_IDLE);
dev->tx_residue = 0x00;
dev->status_queue = 0;
read_urb.status = PDC_URB_COMPLETE;
write_urb.status = PDC_URB_COMPLETE;
/* Initialize the CSW signature */
dev->csw[0] = 0x55;
dev->csw[1] = 0x53;
dev->csw[2] = 0x42;
dev->csw[3] = 0x53;
} /* End of devmscd_reset */
int devmscd_configure(void *__dev, unsigned char cfg)
{
struct devmscd_device *dev = (struct devmscd_device *)__dev;
if(dev) {
if(cfg == 1) {
/* Un configure the device first */
if(dev->config) devmscd_configure(__dev, 0);
devmscd_reset(dev);
dev->data_in_pipe = PDC_INV_PIPE_HANDLE;
dev->data_out_pipe = PDC_INV_PIPE_HANDLE;
/* Configure the device */
dev->data_in_pipe = pdc_open_pipe(&bulk_pipe_desc[0]);
if(dev->data_in_pipe != PDC_INV_PIPE_HANDLE) {
dev->data_out_pipe = pdc_open_pipe(&bulk_pipe_desc[1]);
if(dev->data_out_pipe != PDC_INV_PIPE_HANDLE) {
/* Start waiting for CBW data */
devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH);
} else {
pdc_close_pipe(dev->data_in_pipe);
dev->data_in_pipe = PDC_INV_PIPE_HANDLE;
}
}
dev->config = cfg;
} else if(cfg == 0) {
/* Cancel all data requests to the device */
if(read_urb.status == PDC_URB_PENDING) pdc_cancel_urb(&read_urb);
/* Un configure the device */
if(dev->data_in_pipe != PDC_INV_PIPE_HANDLE) {
pdc_close_pipe(dev->data_in_pipe);
dev->data_in_pipe = PDC_INV_PIPE_HANDLE;
}
if(dev->data_out_pipe != PDC_INV_PIPE_HANDLE) {
pdc_close_pipe(dev->data_out_pipe);
dev->data_out_pipe = PDC_INV_PIPE_HANDLE;
}
devmscd_reset(dev);
dev->config = cfg;
}
}
return 0;
}
/*
* The class request can have the following return values
* == 0 success and no data to send/receive
* > 0 success data stage is needed through dev urb
* < 0 failure of the command, send stall
*
*/
int devmscd_class_req(void *__dev, __u8 *req)
{
int result;
struct devmscd_device *dev = (struct devmscd_device *)__dev;
struct pdc_bus_ctrlrequest *usb_req = (struct pdc_bus_ctrlrequest*)req;
func_debug(("devmscd_class_req(%p)\n",req))
switch(usb_req->bRequest) {
case DEVMSCD_MS_RESET:
detail_debug(("DEVMSCD_RESET\n"))
if((usb_req->wValue != 0x00) || (usb_req->wIndex != 0x00) || (usb_req->wLength != 0x00)) {
result = -1;
break;
}
/* Inform the mass storage bridge about the reset */
mscd_fill_req(&bridge_req, MSCDBRIDGE_RESET, NULL, 0x00, NULL, NULL);
mscdbridge_submit_req(&bridge_req);
/* Reset internal variables */
devmscd_reset(dev);
result = 0;
break;
case DEVMSCD_GET_MAX_LUN:
/*
* This command is not supported by this class driver
*/
result = -1;
break;
default:
result = -1;
break;
}
return result;
} /* devmscd_class_req */
struct pdc_class_drv devmscd_drv = {
name: DRIVER_NAME,
class_vendor: devmscd_class_req,
set_config: devmscd_configure,
set_intf: NULL,
priv_data: &devmscd_dev,
};
/*
* module initialization function
* Initialize the physical disk.
* Register the class driver with the functional interface to the
* peripheral controller driver and wait for the it to call connect
* function
*/
static int __init devmscd_module_init (void)
{
int result;
func_debug(("devmscd_module_init(void)\n"))
bridge_read_req = NULL;
bridge_write_req = NULL;
bulk_pipe_desc[0].ep = 1;
bulk_pipe_desc[0].ep_dir = PDC_EP_DIR_OUT;
bulk_pipe_desc[0].context = (unsigned long)(&devmscd_drv);
bulk_pipe_desc[0].priv = (void*)(&devmscd_drv);
bulk_pipe_desc[0].notify = NULL;
bulk_pipe_desc[1].ep = 2;
bulk_pipe_desc[1].ep_dir = PDC_EP_DIR_IN;
bulk_pipe_desc[1].context = (unsigned long)(&devmscd_drv);
bulk_pipe_desc[1].priv = (void*)(&devmscd_drv);
bulk_pipe_desc[1].notify = NULL;
/* Initialize mass storage bridge */
mscd_fill_req(&bridge_req, MSCDBRIDGE_INIT, NULL, 0x00, NULL, NULL);
result = mscdbridge_submit_req(&bridge_req);
if(result < 0) return result;
devmscd_dev.data_in_pipe = PDC_INV_PIPE_HANDLE;
devmscd_dev.data_out_pipe = PDC_INV_PIPE_HANDLE;
/* register to the device controller driver */
result = pdc_register_class_drv(&devmscd_drv);
if(result == 0) {
isp1362_printk(KERN_INFO __FILE__ ": %s Initialization Success \n",devmscd_drv.name);
} else {
isp1362_printk(KERN_INFO __FILE__ ": %s Iinitialization Failed (error = %d)\n",devmscd_drv.name,result);
}
return result;
} /* End of devmscd_module_init */
/*
* module close function
* shutdown the physical disk
* unregister the class driver from the peripheral controller driver.
*/
static void __exit devmscd_module_cleanup (void)
{
func_debug(("devmscd_module_cleanup(void)\n"))
/* de-register to the device controller driver */
pdc_deregister_class_drv(&devmscd_drv);
/* Notify the bridge that we are going off */
mscd_fill_req(&bridge_req, MSCDBRIDGE_DEINIT, NULL, 0x00, NULL, NULL);
mscdbridge_submit_req(&bridge_req);
return;
} /* End of devmscd_module_cleanup */
module_init (devmscd_module_init);
module_exit (devmscd_module_cleanup);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR(DRIVER_AUTHOR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -