⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devmscd.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:

	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 + -