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

📄 storage.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * storage_fd/storage.c * * Copyright (c) 2000, 2001, 2002 Lineo * Copyright (c) 2001 Hewlett Packard * * By:  *      Stuart Lynne <sl@lineo.com>,  *      Tom Rushworth <tbr@lineo.com>,  *      Bruce Balden <balden@lineo.com> * * Copyright (C) 2002 Toshiba Corporation * * Changes copyright (C) 2003 MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *//* * This module implements USB Mass Storage Class * (SubClass: RBC, Transport: Bulk-Only) * * Usage: */#include <linux/config.h>#include <linux/module.h>#include "../usbd-export.h"#include "../usbd-build.h"#include "../usbd-module.h"MODULE_AUTHOR("sl@lineo.com, tbr@lineo.com, TOSHIBA Corporation");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("USB Device Mass Storage Function");#define STORAGE_MOD_NAME	"storage_fd"USBD_MODULE_INFO(STORAGE_MOD_NAME " 0.1-beta");#ifndef MODULE#undef GET_USE_COUNT#define GET_USE_COUNT(foo) 1#endif#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <asm/uaccess.h>#include <asm/unaligned.h>#include <linux/netdevice.h>#include <linux/smp_lock.h>#include <linux/ctype.h>#include <linux/timer.h>#include <linux/string.h>#include <linux/proc_fs.h>#include <scsi/scsi.h>#define __KERNEL_SYSCALLS__static int errno;#include <asm/unistd.h>#include "../usbd.h"#include "../usbd-func.h"#include "../usbd-bus.h"#include "../usbd-debug.h"#include "../usbd-inline.h"#include "../usbd-arch.h"#define MAX_STORAGES	1#define STORAGE_DEFAULT_FILENAME	"/dev/ram0"#define STORAGE_BLOCK_SIZE	512#define STORAGE_PROC_NAME	"driver/" STORAGE_MOD_NAME#define USB_REQ_BO_MASS_STORAGE_RESET	0xFF#define USB_REQ_GET_MAX_LUN		0xFE#if 0/* RBC 6.1 states "RBC devices are identified by a PERIPHERAL DEVICE * TYPE 0Eh" */#define PERIPHERAL_DEVICE_TYPE	0x0e#else/* XXX: Linux sd,scsi stack seems to expect this value... */#define PERIPHERAL_DEVICE_TYPE	0x00#endif#if !defined (CONFIG_USBD_VENDORID) && !defined(CONFIG_USBD_STORAGE_VENDORID)        #error No Vendor ID#endif#if !defined (CONFIG_USBD_PRODUCTID) && !defined(CONFIG_USBD_STORAGE_PRODUCTID)        #error No Product ID#endif#if CONFIG_USBD_STORAGE_VENDORID        #undef CONFIG_USBD_VENDORID        #define CONFIG_USBD_VENDORID CONFIG_USBD_STORAGE_VENDORID#endif#if CONFIG_USBD_STORAGE_PRODUCTID        #undef CONFIG_USBD_PRODUCTID        #define CONFIG_USBD_PRODUCTID CONFIG_USBD_STORAGE_PRODUCTID#endif#ifndef CONFIG_USBD_SERIAL_NUMBER_STR        #define CONFIG_USBD_SERIAL_NUMBER_STR	"000000000000"#endif#ifdef CONFIG_USBD_SELFPOWERED        #define BMATTRIBUTE BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED        #define BMAXPOWER 0#else        #define BMATTRIBUTE BMATTRIBUTE_RESERVED        #define BMAXPOWER CONFIG_USBD_MAXPOWER#endif/* * setup some default values for pktsizes and endpoint addresses. */#ifndef CONFIG_USBD_STORAGE_OUT_PKTSIZE        #define CONFIG_USBD_STORAGE_OUT_PKTSIZE             64#endif#ifndef CONFIG_USBD_STORAGE_IN_PKTSIZE        #define CONFIG_USBD_STORAGE_IN_PKTSIZE              64#endif#ifndef CONFIG_USBD_STORAGE_OUT_ENDPOINT    #define CONFIG_USBD_STORAGE_OUT_ENDPOINT                1#endif#ifndef CONFIG_USBD_STORAGE_IN_ENDPOINT    #define CONFIG_USBD_STORAGE_IN_ENDPOINT                 2#endif/* * check for architecture specific endpoint configurations */#if     defined(ABS_OUT_ADDR)         #warning        #warning USING ABS ENDPOINT OUT ADDRESS        #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT         #if     ABS_OUT_ADDR                #define CONFIG_USBD_STORAGE_OUT_ENDPOINT        ABS_OUT_ADDR        #endif#if     defined(ABS_IN_ADDR)         #warning        #warning USING ABS ENDPOINT IN ADDRESS        #undef CONFIG_USBD_STORAGE_IN_ENDPOINT         #if     ABS_IN_ADDR                #define CONFIG_USBD_STORAGE_IN_ENDPOINT         ABS_IN_ADDR        #endif#elif   defined(MAX_OUT_ADDR) && defined(CONFIG_USBD_STORAGE_OUT_ENDPOINT) && (CONFIG_USBD_STORAGE_OUT_ENDPOINT > MAX_OUT_ADDR)        #warning        #warning USING DEFAULT ENDPOINT OUT ADDRESS        #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT         #define CONFIG_USBD_STORAGE_OUT_ENDPOINT            DFL_OUT_ADDR#endif#elif   defined(MAX_IN_ADDR) && defined(CONFIG_USBD_STORAGE_IN_ENDPOINT) && (CONFIG_USBD_STORAGE_IN_ENDPOINT > MAX_IN_ADDR)        #warning        #warning USING DEFAULT ENDPOINT IN ADDRESS        #undef CONFIG_USBD_STORAGE_IN_ENDPOINT         #define CONFIG_USBD_STORAGE_IN_ENDPOINT             DFL_IN_ADDR#endif#if     defined(MAX_OUT_PKTSIZE) && defined(CONFIG_USBD_STORAGE_OUT_PKTSIZE) && CONFIG_USBD_STORAGE_OUT_PKTSIZE > MAX_OUT_PKTSIZE        #warning        #warning OVERIDING ENDPOINT OUT PKTSIZE        #undef CONFIG_USBD_STORAGE_OUT_PKTSIZE        #define CONFIG_USBD_STORAGE_OUT_PKTSIZE             MAX_OUT_PKTSIZE#endif#if     defined(MAX_IN_PKTSIZE) && defined(CONFIG_USBD_STORAGE_IN_PKTSIZE) && CONFIG_USBD_STORAGE_IN_PKTSIZE > MAX_IN_PKTSIZE        #warning        #warning OVERIDING ENDPOINT IN PKTSIZE        #undef CONFIG_USBD_STORAGE_IN_PKTSIZE        #define CONFIG_USBD_STORAGE_IN_PKTSIZE              MAX_IN_PKTSIZE#endifenum usb_storage_device_state {    STATE_INVALID,    STATE_IDLE,	/* Device intends to receive command */    STATE_DN,	/* Device intends to transfer no data */    STATE_DI,	/* Device intends to send data to the host */    STATE_DO,	/* Device intends to receive data from the host */};#define CSW_STAT_GOOD	0x00#define CSW_STAT_FAILED	0x01#define CSW_STAT_PERR	0x02	/* Phase Error *//* Command Block Wrapper */#define MAX_CBLENGTH	16struct CBW {    u32	dSignature;    u32 dTag;    u32 dDataTransferLength;    u8	bmFlags;    u8	bLUN;    u8	bCBLength;    u8	CB[MAX_CBLENGTH];} __attribute__((packed));#define CBW_SIGNATURE	0x43425355/* Command Status Wrapper */struct CSW {    u32	dSignature;    u32	dTag;    u32	dDataResidue;    u8	bStatus;} __attribute__((packed));#define CSW_SIGNATURE	0x53425355struct usb_storage_threaddata {    int busy;    struct CBW cbw;	/* cpu endian */    struct CSW csw;	/* cpu endian */    u8 *data_buf;    /* NOTE: data_len CAN exceed cbw.dDataTransferLength */    unsigned int data_len;    unsigned int data_alloclen;    /* sense data */    struct {	u8 key;	u32 info;	u32 cmdinfo;	u8 code;    } sense;    /* real storage */    struct file  *real_fd;    char filename[128];    unsigned int num_blocks;    /* statistics */    struct {	/* transmit statistics */	unsigned int read_blocks;	unsigned int write_blocks;	/* command statictics */	unsigned int inquiry;	unsigned int mode_select;	unsigned int mode_sense;	unsigned int read_10;	unsigned int read_capacity;	unsigned int request_sense;	unsigned int start_stop;	unsigned int test_unit_ready;	unsigned int verify;	unsigned int write_10;	unsigned int write_buffer;	unsigned int unsupported;    } stat;};struct usb_storage_private {    struct usb_device_instance *device;    enum usb_storage_device_state devstate;    struct usb_storage_threaddata tdata;};static spinlock_t storage_lock;static struct usb_storage_private storage_private;	// one and only storagestatic DECLARE_MUTEX_LOCKED(storage_sem_start);static DECLARE_MUTEX_LOCKED(storage_sem_work);static int storage_thread_terminating;static void storage_thread_poke(void){    up(&storage_sem_work);}/* SCSI related definitions *//* *	Sense codes */ #define SENCODE_NO_SENSE                        0x00#define SENCODE_END_OF_DATA                     0x00#define SENCODE_BECOMING_READY                  0x04#define SENCODE_INIT_CMD_REQUIRED               0x04#define SENCODE_PARAM_LIST_LENGTH_ERROR         0x1A#define SENCODE_INVALID_COMMAND                 0x20#define SENCODE_LBA_OUT_OF_RANGE                0x21#define SENCODE_INVALID_CDB_FIELD               0x24#define SENCODE_LUN_NOT_SUPPORTED               0x25#define SENCODE_INVALID_PARAM_FIELD             0x26#define SENCODE_PARAM_NOT_SUPPORTED             0x26#define SENCODE_PARAM_VALUE_INVALID             0x26#define SENCODE_RESET_OCCURRED                  0x29#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET     0x3E#define SENCODE_INQUIRY_DATA_CHANGED            0x3F#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED     0x39#define SENCODE_DIAGNOSTIC_FAILURE              0x40#define SENCODE_INTERNAL_TARGET_FAILURE         0x44#define SENCODE_INVALID_MESSAGE_ERROR           0x49#define SENCODE_LUN_FAILED_SELF_CONFIG          0x4c#define SENCODE_OVERLAPPED_COMMAND              0x4E/* Module Parameters ************************************************************************* */static char *dbg = NULL;static u32 vendor_id;static u32 product_id;static char *serial_number = NULL;static char *filename = NULL;MODULE_PARM(dbg, "s");MODULE_PARM(vendor_id, "i");MODULE_PARM(product_id, "i");MODULE_PARM(serial_number, "s");MODULE_PARM(filename, "s");MODULE_PARM_DESC(dbg, "USB Device Debug options");MODULE_PARM_DESC(vendor_id, "USB Device Vendor ID");MODULE_PARM_DESC(product_id, "USB Device Product ID");MODULE_PARM_DESC(serial_number, "USB Device Serial Number");MODULE_PARM_DESC(filename, "USB Device Storage Filename");/* Debug switches (module parameter "dbg=...") *********************************************** */extern int dbgflg_usbdfd_init;int      dbgflg_usbdfd_ep0;int      dbgflg_usbdfd_usbe;int      dbgflg_usbdfd_tx;int      dbgflg_usbdfd_rx;static debug_option dbg_table[] = {    {&dbgflg_usbdfd_init,NULL,"init","initialization and termination"},    {&dbgflg_usbdfd_ep0,NULL,"ep0","End Point 0 (setup) packet handling"},    {&dbgflg_usbdfd_usbe,NULL,"usbe","USB events"},    {&dbgflg_usbdfd_tx,NULL,"tx","transmit (to host)"},    {&dbgflg_usbdfd_rx,NULL,"rx","receive (from host)"},    {NULL,NULL,NULL,NULL}};#define dbg_init(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_init,lvl,fmt,##args)#define dbg_ep0(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_ep0,lvl,fmt,##args)#define dbg_usbe(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_usbe,lvl,fmt,##args)#define dbg_tx(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_tx,lvl,fmt,##args)#define dbg_rx(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_rx,lvl,fmt,##args)/* ******************************************************************************************* *//* Mass Storage Class descriptions  */#define STORAGE_TRANSFER_SIZE	2048	/* XXX max 0xfff. why? (see usbd-bi.c) */static struct usb_endpoint_description storage_default[] = {    { bEndpointAddress: CONFIG_USBD_STORAGE_OUT_ENDPOINT,        bmAttributes: BULK,        wMaxPacketSize: CONFIG_USBD_STORAGE_OUT_PKTSIZE,        bInterval: 0,        direction: OUT,        transferSize: STORAGE_TRANSFER_SIZE, },    { bEndpointAddress: CONFIG_USBD_STORAGE_IN_ENDPOINT,        bmAttributes: BULK,        wMaxPacketSize: CONFIG_USBD_STORAGE_IN_PKTSIZE,        bInterval: 0,        direction: IN,        transferSize: STORAGE_TRANSFER_SIZE, },};/* Data Interface Alternate description(s) */static __initdata struct usb_alternate_description storage_data_alternate_descriptions[] = {    {   iInterface: "Simple Mass Storage Data Interface - Bulk-Only",         bAlternateSetting: 0,	classes: 0,	class_list: NULL,        endpoints: sizeof(storage_default)/sizeof(struct usb_endpoint_description),        endpoint_list: storage_default, },};/* Interface description(s) */static __initdata struct usb_interface_description storage_interfaces[] = {    {   iInterface: "Simple Mass Storage Data Interface",         bInterfaceClass: USB_CLASS_MASS_STORAGE,	bInterfaceSubClass: 0x05, /*removeble*/        bInterfaceProtocol: 0x50, /* Bulk-Only Transport */        alternates: sizeof(storage_data_alternate_descriptions)/sizeof(struct usb_alternate_description),        alternate_list: storage_data_alternate_descriptions, },};/* Configuration description(s) */struct __initdata usb_configuration_description storage_description[] = {    {   iConfiguration: "USB Simple Mass Storage Configuration",         bmAttributes: BMATTRIBUTE,        bMaxPower: BMAXPOWER,        interfaces: sizeof(storage_interfaces)/sizeof(struct usb_interface_description),        interface_list: storage_interfaces, },};/* Device Description */struct __initdata usb_device_description storage_device_description = {    bDeviceClass:       0,     bDeviceSubClass:    0,    bDeviceProtocol:    0,    idVendor:           CONFIG_USBD_VENDORID,    idProduct:          CONFIG_USBD_PRODUCTID,    iManufacturer:      CONFIG_USBD_MANUFACTURER,    iProduct:           CONFIG_USBD_PRODUCT_NAME,    iSerialNumber:      CONFIG_USBD_SERIAL_NUMBER_STR,};static int storage_receive_CBW(struct usb_storage_private *private,			       u8 *buf, unsigned int len){    struct CBW *cbwp = (struct CBW *)buf;    struct usb_storage_threaddata *tdata = &private->tdata;#if 0	/* bad bi driver */    if (len < sizeof(struct CBW)) {	printk(KERN_ERR STORAGE_MOD_NAME ": bad CBW length (%d)\n", len);	return -1;    }#else    if (len != sizeof(struct CBW)) {	printk(KERN_ERR STORAGE_MOD_NAME ": bad CBW length (%d)\n", len);	return -1;    }#endif    if (le32_to_cpu(cbwp->dSignature) != CBW_SIGNATURE) {	printk(KERN_ERR STORAGE_MOD_NAME ": bad CBW signature (%x)\n",	       le32_to_cpu(cbwp->dSignature));	return -1;    }    if (cbwp->bLUN != 0) {	printk(KERN_ERR STORAGE_MOD_NAME ": bad CBW LUN (%x)\n", cbwp->bLUN);	return -1;    }    tdata->cbw = *cbwp;    tdata->cbw.dSignature = le32_to_cpu(tdata->cbw.dSignature);    tdata->cbw.dTag = le32_to_cpu(tdata->cbw.dTag);    tdata->cbw.dDataTransferLength = le32_to_cpu(tdata->cbw.dDataTransferLength);    tdata->csw.dSignature = CSW_SIGNATURE;    tdata->csw.dTag = tdata->cbw.dTag;    tdata->csw.dDataResidue = tdata->cbw.dDataTransferLength;    tdata->csw.bStatus = CSW_STAT_GOOD;    return len - sizeof(struct CBW);}static int storage_send_CSW(struct usb_storage_private *private){    struct urb *urb;    int port = 0; // XXX compound device    struct usb_storage_threaddata *tdata = &private->tdata;    urb = usbd_alloc_urb(private->device,			 private->device->function_instance_array+port,			 CONFIG_USBD_STORAGE_IN_ENDPOINT | IN, sizeof (struct CSW));    if (!urb) {	printk(KERN_ERR STORAGE_MOD_NAME ": failed to alloc CSW urb\n");	return -EINVAL;    }    tdata->csw.dSignature = cpu_to_le32(tdata->csw.dSignature);    tdata->csw.dTag = cpu_to_le32(tdata->csw.dTag);    tdata->csw.dDataResidue = cpu_to_le32(tdata->csw.dDataResidue);    memcpy(urb->buffer, &tdata->csw, sizeof(struct CSW));    urb->actual_length = sizeof(struct CSW);    dbg_rx(3,"CSW (length %d)", urb->actual_length);    dbgPRINTmem(dbgflg_usbdfd_tx,3,urb->buffer,min(urb->actual_length, 32u));    if (usbd_send_urb(urb))	return -EINVAL;    return 0;}/* storage_urb_sent - called to indicate URB transmit finished * @urb: pointer to struct urb * @rc: result

⌨️ 快捷键说明

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