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

📄 devmscd.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************
 * Philips USB Mass Storage Class driver (Device side)
 *
 * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved
 * 
 * This  source code and any compilation or derivative thereof is the
 * proprietary information of Koninklijke Philips Electronics N.V.
 * and is confidential in nature.
 * Under no circumstances is this software to be exposed to or placed
 * under an Open Source License of any type without the expressed
 * written permission of Koninklijke Philips Electronics N.V.
 *
 * File Name:	devmscd.c
 *
 * History:	
 *
 *	Version	Date		Author		Comments
 * -------------------------------------------------
 * 	1.0		09/23/02	SYARRA		Initial Creation
 * 	1.21	08/04/03	SYARRA		Stict checking of 
 * 									usb commands
 *
 * Note: use tab space 4
 *************************************************************/

#include <linux/config.h>
#define	MODULE
#include <linux/types.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/tqueue.h>

#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/segment.h>
#include <asm/io.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>


#include "pdc_intf.h"
#include "devmscd.h"
#include "mscdbridge.h"
#include "pdc_bus.h"


#define		devmscd_change_state(dev, new_state)	dev->state = new_state


/*--------------------------------------------------------------*
 *               local variables declerations
 *--------------------------------------------------------------*/
struct devmscd_device	devmscd_dev;
struct pdc_urb			read_urb, write_urb, csw_urb;
mscdbridge_req_t		bridge_req;
mscd_req_t				*bridge_read_req, *bridge_write_req;

struct pdc_pipe_desc	bulk_pipe_desc[2];

#if 0
static	char	devmscd_state_name[DEVMSCD_DATA_OUT+1][20] = {
		"DEVMSCD_IDLE    ",
		"DEVMSCD_CBW     ",
		"DEVMSCD_CSW     ",
		"DEVMSCD_DATA_IN ",
		"DEVMSCD_DATA_OUT"
};
#endif



/*--------------------------------------------------------------*
 *               local function declerations
 *--------------------------------------------------------------*/
static	int devmscd_class_req(void *__dev, __u8	*req);
static	int devmscd_configure(void *__dev, unsigned char cfg);
static	void devmscd_reset(struct devmscd_device *dev);
static	void devmscd_read_urb_complete(struct pdc_urb *urb);
static	void devmscd_write_urb_complete(struct pdc_urb *urb);
static	void devmscd_set_command_res(mscdbridge_req_t *req);
static int devmscd_read_data(__u8 *buff, __u32 bytes);
static int devmscd_write_data(__u8 *buff, __u32 bytes);



/*--------------------------------------------------------------*
 *               external function definitions
 *--------------------------------------------------------------*/

/* 
 * This function currently supports read, write operations.
 * Stores the request and calls the corresponding read or write function
 * Currently queueing is not implemented
 */
int devmscd_submit_req(mscd_req_t	*req)
{
	int result = MSCD_SUCCESS;

	func_debug(("devmscd_submit_req(%p)\n",req))

	switch(req->req_type) {

		case MSCD_READ:
			/* Bridge wants to receive data from the USB Host */
			if(!bridge_read_req) {
				req->status = MSCD_PENDING;
				bridge_read_req = req;
				return devmscd_read_data(req->data_buff, req->req_data_len);
			}
			break;
		
		case MSCD_WRITE:	
			/* Bridge wants to send data to the USB Host */
			if(!bridge_write_req) {
				req->status = MSCD_PENDING;
				bridge_write_req = req;
				return devmscd_write_data(req->data_buff, req->req_data_len);
			}
			break;

		default:

			result = MSCD_FAILED;
			break;
	}

	return result;
} /* End of devmscd_submit_req */

/* 
 * This function currently supports read, write operations.
 * rears the request and calls the corresponding usb device cancel operation
 * Currently queueing is not implemented
 */
int devmscd_cancel_req(mscd_req_t	*req)
{
	int result = MSCD_SUCCESS;

	func_debug(("devmscd_cancel_req(%p)\n",req))

	switch(req->req_type) {

		case MSCD_READ:

			if(bridge_read_req) {
				/* There is a read request pending, so clear this */
				bridge_read_req = NULL;
				if(read_urb.status != PDC_URB_COMPLETE)
					return pdc_cancel_urb(&read_urb);
				else return MSCD_SUCCESS;
			}
			break;
		
		case MSCD_WRITE:	

			if(bridge_write_req) {
				/* There is a write request pending, so clear this */
				bridge_read_req = NULL;
				if(write_urb.status != PDC_URB_COMPLETE)
					return pdc_cancel_urb(&write_urb);
				else return MSCD_SUCCESS;
			}
			break;

		default:

			/* Not supported */
			result = MSCD_FAILED;
			break;
	}

	return result;
} /* End of devmscd_cancel_req */


/*--------------------------------------------------------------*
 *               local function definitions
 *--------------------------------------------------------------*/
/* 
 * Make the URB req and call the Peripheral controller driver
 * read function
 */
int devmscd_read_data(__u8 *buff, __u32 bytes)
{
	func_debug(("devmscd_read_data(%p,%x)\n",buff,bytes))
	
	/* Fill the read URB */
	read_urb.next = NULL;
	read_urb.pipe = devmscd_dev.data_in_pipe;
	read_urb.pipe_type = PDC_PIPE_BULK;
	read_urb.operation = PDC_OPR_READ;
	read_urb.status = PDC_URB_PENDING;
	read_urb.transfer_buffer = buff;
	read_urb.transfer_buffer_length = bytes;
	read_urb.actual_length = 0x00;
	read_urb.complete = devmscd_read_urb_complete;	/* call back function */

	return pdc_submit_urb(&read_urb);
} /* End of devmscd_read_data */

/* 
 * Make the URB req and call the Peripheral controller driver
 * write function.
 */
int devmscd_write_data(__u8 *buff, __u32 bytes)
{
	struct pdc_urb	*urb;

	func_debug(("devmscd_write_data(%p,%x)\n",buff,bytes))
	
	if(bytes == DEVMSCD_CSW_LENGTH)	urb = &csw_urb;
	else urb = &write_urb;
	
	/* Fill the wrtite URB */
	urb->next = NULL;
	urb->pipe = devmscd_dev.data_out_pipe;
	read_urb.pipe_type = PDC_PIPE_BULK;
	urb->operation = PDC_OPR_WRITE;
	urb->status = PDC_URB_PENDING;
	urb->transfer_buffer = buff;
	urb->transfer_buffer_length = bytes;
	urb->actual_length = 0x00;
	urb->complete = devmscd_write_urb_complete;

	/* transfer residue will be updated in the call back function */

	return pdc_submit_urb(urb);

} /* End of devmscd_write_data */

/* 
 * If the command response is not success, stall the endpoint.
 * Fill the CSW and send it to the host. Go back to IDLE state.
 */
void devmscd_set_command_res(mscdbridge_req_t *req)
{

	struct devmscd_device	*dev = &devmscd_dev;
	__u8	status = req->status;
	struct pdc_pipe_opr		bulk_pipe_opr;

	func_debug(("devmscd_set_command_res(%p)\n",req))

	if(dev->state != DEVMSCD_IDLE) {

		if((status != MSCD_SUCCESS) && (dev->cbw[12]&0x80)) {
				/* Stall Bulk In End Point */
				bulk_pipe_opr.handle = dev->data_out_pipe;
				bulk_pipe_opr.context = (unsigned long) dev;
				bulk_pipe_opr.opr = PDC_PIPE_STALL;
				pdc_pipe_operation(&bulk_pipe_opr);

		} else if(status == MSCD_SUCCESS && dev->tx_residue) {
			if(read_urb.status == PDC_URB_COMPLETE && write_urb.status == PDC_URB_COMPLETE) {
				mdelay(3);
				bulk_pipe_opr.handle = dev->data_out_pipe;
				bulk_pipe_opr.context = (unsigned long) dev;
				bulk_pipe_opr.opr = PDC_PIPE_STALL;
				pdc_pipe_operation(&bulk_pipe_opr);
			} else {
				dev->status_queue = 1;
			}
		}
		
		
		/*
		 * Copy the transfer residue to the Command status Word 
		 */
		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;
       	dev->csw[12] = status;

		devmscd_change_state(dev, DEVMSCD_CSW);

		/* If no read or write operations are not in progress
		 * send the status to the host, else wait for the read, 
		 * or write operation to finish
		 */
		if((read_urb.status == PDC_URB_COMPLETE && write_urb.status == PDC_URB_COMPLETE) && (dev->status_queue == 0)) {
			devmscd_read_data(dev->cbw,DEVMSCD_CBW_LENGTH);
			devmscd_change_state(dev, DEVMSCD_IDLE);
			devmscd_write_data(dev->csw, DEVMSCD_CSW_LENGTH);
		} else {
			/* Wait for the  data stage to finish */
			dev->status_queue = 1;
		}
	} else {
		/* 
		 * Command response received in idle state , Might be a reset has done
		 * or .... Ignore this
		 */
		detail_debug(("Command response received in Invalid state, Ignored\n"))
	}
	
} /* End of devmscd_set_command_res */




/* 
 * read URB complete function. 
 * In case of IDLE state, this is a CBW. Other cases it is a data request
 * reurn
 */
void devmscd_read_urb_complete(struct pdc_urb *urb)
{
	struct devmscd_device	*dev = &devmscd_dev;
	mscd_req_t				*req;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -