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

📄 msbridge.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
字号:
/*************************************************************
 * Philips USB Mass Storage Class driver Interface
 *
 * (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:	msbridge.c
 *
 * History:	
 *
 *	Version	Date		Author		Comments
 * -------------------------------------------------
 * 	1.0		09/23/02	SYARRA		Initial Creation
 *
 * Note: use tab space 4
 *************************************************************/

#include <linux/config.h>
#define MODULE
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>  /* for in_interrupt() */
#undef DEBUG
#include <linux/usb.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>


#include "pdc_intf.h"
#include "devmscd.h"
#include "msbridge.h"

#define		MODULE_NAME			"msbridge"


typedef struct devmscd_intf_info {
	
	__u8					notif;			/* Notification type */
	__u8					use;			
	__u8					notif_pending;
	__u8					*cmd;			/* mass storage command */

	wait_queue_head_t 		read_wq;		/* read wait queue */
	__u8					read_lock;		/* read lock */
	__u32					read_bytes;		/* read response (from device) bytes */

	wait_queue_head_t 		write_wq;		/* Write wait queue (TODO) */
	__u8					write_lock;		/* Write lock */
	__u32					write_bytes;	/* Write response bytes */

	struct fasync_struct 	*fasync_q;		/* Asynchronous notification */
	
} devmscd_intf_info_t;




/*------------------------------------------------------------------*
 *                 local function declerations                      *
 *------------------------------------------------------------------*/

static ssize_t devmscd_intf_read(struct file *fp, char *dest, size_t count, loff_t *ppos);
static ssize_t devmscd_intf_write(struct file *fp, const char *buf, size_t count, loff_t *ppos);
static	int	devmscd_intf_open( struct inode *inode, struct file *fp);
static	int	devmscd_intf_close( struct inode *inode, struct file *fp);
static	int devmscd_intf_fasync( int	fd, struct file *fp, int mode);
static	int	devmscd_intf_ioctl(struct inode *inode, struct file *fp, 
					unsigned int	cmd, unsigned long arg);
static void devmscd_disk_write(mscd_req_t *req);
static void devmscd_disk_read(mscd_req_t *req);


/*------------------------------------------------------------------*
 *                 global variable declerations                     *
 *------------------------------------------------------------------*/

static struct file_operations devmscd_intf_fops = {
	owner:		THIS_MODULE,
	read:		devmscd_intf_read,
	write:		devmscd_intf_write,
	poll:		NULL,
	ioctl:		devmscd_intf_ioctl,
	open:		devmscd_intf_open,
	release:	devmscd_intf_close,
	fasync:		devmscd_intf_fasync,
};

struct devmscd_intf_info	intf_info;
struct devmscd_intf_info	*devmscd_intf;
__u8	rcvd_data[0x20000];
__u8	send_data[0x20000];
mscd_req_t		mscd_read_req, mscd_write_req;
mscdbridge_req_t	*mscd_req = NULL;









/*------------------------------------------------------------------*
 *                 local function definitions                       *
 *------------------------------------------------------------------*/

/* 
 * Send read command to the class driver.
 */
ssize_t devmscd_intf_read(struct file *fp, char *dest, size_t count, loff_t *ppos) {
	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;

	intf->read_lock = 1;

//	devmscd_read_data(rcvd_data, count);
	mscd_fill_req((&mscd_read_req), MSCD_READ, 
			rcvd_data, count, 
			devmscd_disk_write, NULL);
	devmscd_submit_req(&mscd_read_req);

	while(intf->read_lock) {
		interruptible_sleep_on(&intf->read_wq);
        if (signal_pending(current))
         	return -ERESTARTSYS;    
	}

	memcpy(dest, rcvd_data, intf->read_bytes);
	return intf->read_bytes;

}

/* 
 * Send read command to the class driver.
 */
ssize_t devmscd_intf_write(struct file *fp, const char *buf, size_t count, loff_t *ppos)
{
	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;

	memcpy(send_data,buf, count);
	intf->write_lock = 1;
//	devmscd_write_data(send_data, count);
	mscd_fill_req((&mscd_write_req), MSCD_WRITE, 
			send_data, count, 
			devmscd_disk_read, NULL);
	devmscd_submit_req(&mscd_write_req);

	while(intf->write_lock) {
		interruptible_sleep_on(&intf->write_wq);
        if (signal_pending(current))
         	return -ERESTARTSYS;    
	}

	return intf->write_bytes;
}

/*
 * Intialize the wait queues
 */
int	devmscd_intf_open( struct inode *inode, struct file *fp) 
{
	
	fp->private_data = devmscd_intf;	/* set the OTG controller data in file */

	init_waitqueue_head(&devmscd_intf->read_wq);
	init_waitqueue_head(&devmscd_intf->write_wq);

	devmscd_intf->use++;

	MOD_INC_USE_COUNT;					/* Increment the module count */

	return 0;
}

/*
 * cancel any asynchronous notification
 */
int	devmscd_intf_close( struct inode *inode, struct file *fp) 
{
	
	MOD_DEC_USE_COUNT;					/* Decrement module count */

	if(devmscd_intf->use) devmscd_intf->use--;

	devmscd_intf_fasync(-1,fp, 0);	/* cancel asynchronous notification to application */
	return 0;
}

/*
 *  Set/reset asynchronous notification to the application
 */
int devmscd_intf_fasync( int	fd, struct file *fp, int mode) 
{
	int result;

	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;


	result =  fasync_helper(fd, fp, mode, &intf->fasync_q);

	if(result >= 0 && intf->notif_pending) {
		if(intf->fasync_q) {
				kill_fasync( &intf->fasync_q, SIGIO, POLL_IN);
				intf->notif_pending = 0;
		}
	}

	return result;
}

/*
 *  perform the IO control operations for the application
 */
int	devmscd_intf_ioctl(struct inode *inode, struct file *fp, 
					unsigned int	cmd, unsigned long arg) {

	devmscd_intf_info_t	*intf = (devmscd_intf_info_t*)fp->private_data;
	int				ret = 0;
	mscd_cmd_res_t	cmd_res;

	switch(cmd) {
		case MSCD_IOC_GET_NOTIF:			

			copy_to_user((mscd_notif_t *)arg, &intf->notif, sizeof(mscd_notif_t));
		break;

		case MSCD_IOC_GET_COMMAND:			

			if(mscd_req) {
				copy_to_user((mscd_command_t *)arg, intf->cmd, sizeof(mscd_command_t));
			} else {
				return -EINVAL;
			}
		break;

		case MSCD_IOC_SET_CMD_RES:
			copy_from_user(&cmd_res, (mscd_cmd_res_t *)arg, sizeof(mscd_cmd_res_t));

			if(mscd_req && mscd_req->complete) {
				mscd_req_t	*req = mscd_req;
				req->status = cmd_res.status;
				mscd_req = NULL;
				req->complete(req);
			}
//			devmscd_set_command_res(cmd_res.status);

			break;

	}

	return ret;
}

/*
 * Wake up any pending read requests
 */
void devmscd_disk_read(mscd_req_t *req)
{

	devmscd_intf->write_bytes = req->res_data_len;
	devmscd_intf->write_lock = 0;

	wake_up_interruptible(&devmscd_intf->write_wq);

	return;
}

/*
 * Wake up any pending write requests
 */
void devmscd_disk_write(mscd_req_t *req)
{

	devmscd_intf->read_bytes = req->res_data_len;
	devmscd_intf->read_lock = 0;

	wake_up_interruptible(&devmscd_intf->read_wq);

	return;
}

int mscdbridge_submit_req(mscdbridge_req_t *req)
{
	int	result = MSCD_SUCCESS;

	switch(req->req_type) {
		
		case MSCDBRIDGE_DEINIT:
			req->status = MSCD_SUCCESS;
			devfs_unregister_chrdev(DEVMSCD_MAJOR,DRIVER_NAME);
			devmscd_intf  = NULL;
			break;
		case MSCDBRIDGE_INIT:
			req->status = MSCD_SUCCESS;
			devmscd_intf  = &intf_info;

			devmscd_intf->use = 0;
			devmscd_intf->notif_pending = 0;

			result = devfs_register_chrdev(DEVMSCD_MAJOR, DRIVER_NAME, &devmscd_intf_fops);
			break;

		case MSCD_COMMAND:
			/* Store the request */
			mscd_req = req;
			devmscd_intf->cmd = req->data_buff;
		case MSCDBRIDGE_RESET:
			/*
			 * Send notification to the mass storage device
			 */
			req->status = MSCD_SUCCESS;
			devmscd_intf->notif = req->req_type;

			if(devmscd_intf->fasync_q) {
				kill_fasync( &devmscd_intf->fasync_q, SIGIO, POLL_IN);
			} else {
				devmscd_intf->notif_pending = 1;
			}
			break;

	}

	return result;
}

⌨️ 快捷键说明

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