1 diff -Nur linux-2.4.18/drivers/usb/device/bi/sa1100.c linux-2.4.18-usb-storage/drivers/usb/device/bi/sa1100.c
2 --- linux-2.4.18/drivers/usb/device/bi/sa1100.c 2003-05-13 13:18:44.000000000 +0400
3 +++ linux-2.4.18-usb-storage/drivers/usb/device/bi/sa1100.c 2004-03-01 07:20:38.000000000 +0300
5 udc_interrupts, *(UDCSR), *(UDCCS0), *(UDCAR));
7 usbd_device_event (udc_device, DEVICE_RESET, 0);
8 + usbd_device_event (udc_device, DEVICE_ADDRESS_ASSIGNED,0);
11 if (status & UDCSR_SUSIR) {
12 diff -Nur linux-2.4.18/drivers/usb/device/Config.in linux-2.4.18-usb-storage/drivers/usb/device/Config.in
13 --- linux-2.4.18/drivers/usb/device/Config.in 2003-05-13 13:18:45.000000000 +0400
14 +++ linux-2.4.18-usb-storage/drivers/usb/device/Config.in 2003-11-07 05:35:14.000000000 +0300
16 comment 'USB Device functions'
17 source drivers/usb/device/net_fd/Config.in
18 source drivers/usb/device/serial_fd/Config.in
19 + source drivers/usb/device/storage_fd/Config.in
21 comment 'USB Device bus interfaces'
22 source drivers/usb/device/bi/Config.in
23 diff -Nur linux-2.4.18/drivers/usb/device/Makefile linux-2.4.18-usb-storage/drivers/usb/device/Makefile
24 --- linux-2.4.18/drivers/usb/device/Makefile 2003-05-13 13:18:45.000000000 +0400
25 +++ linux-2.4.18-usb-storage/drivers/usb/device/Makefile 2003-11-07 05:35:01.000000000 +0300
28 subdir-$(CONFIG_USBD_NET) += net_fd
29 subdir-$(CONFIG_USBD_SERIAL) += serial_fd
30 +subdir-$(CONFIG_USBD_STORAGE) += storage_fd
32 #subdir-$(CONFIG_USBD_GENERIC_BUS) += gen_bi
33 #subdir-$(CONFIG_USBD_L7205_BUS) += l7205_bi
34 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/Config.help linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Config.help
35 --- linux-2.4.18/drivers/usb/device/storage_fd/Config.help 1970-01-01 03:00:00.000000000 +0300
36 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Config.help 2003-11-07 05:34:43.000000000 +0300
39 + Enable the generic mass storage function driver. This function is
40 + used emulating a Linux block driver.
42 +CONFIG_USBD_STORAGE_VENDORID
43 + Optionally specify the mass storage USB Device Vendor ID. The top
44 + level Vendor ID will be used if this is not specified.
46 +CONFIG_USBD_STORAGE_PRODUCTID
47 + Optionally specify the mass storage USB Device Product ID. The top
48 + level Vendor ID will be used if this is not specified.
50 +CONFIG_USBD_STORAGE_OUT_ENDPOINT
51 + Specify the preferred OUT (received data) endpoint number. This is a
52 + number from 0-15 and must be allowed by the bus interface device.
54 + Some devices such as the SA-1110 or L7205/L7210 may override this
55 + value with a fixed value.
57 +CONFIG_USBD_STORAGE_IN_ENDPOINT
58 + Specify the preferred IN (transmit data) endpoint number. This is a
59 + number from 0-15 and must be allowed by the bus interface device.
61 + Some devices such as the SA-1110 or L7205/L7210 may override this
62 + value with a fixed value.
64 +CONFIG_USBD_STORAGE_INT_ENDPOINT
65 + Specify the preferred INT (interrupt) endpoint number. This is a
66 + number from 0-15 and must be allowed by the bus interface device.
68 + Some devices such as the L7205/L7210 may override this value with a
69 + fixed value. Others such as the SA-1110 do not allow an interrupt
72 +CONFIG_USBD_STORAGE_OUT_PKTSIZE
73 + Specify the maximum packet size for the OUT endpoint. This allowable
74 + values are normally 16, 32 and 64.
76 + Some devices such as the Linkup L7205/L7210 may override this value
77 + with a lower maximum value (such as 32).
79 +CONFIG_USBD_STORAGE_IN_PKTSIZE
80 + Specify the maximum packet size for the IN endpoint. This allowable
81 + values are normally 16, 32 and 64.
83 + Some devices such as the Linkup L7205/L7210 may override this value
84 + with a lower maximum value (such as 32).
86 +CONFIG_USBD_STORAGE_INT_PKTSIZE
87 + Specify the maximum packet size for the INT endpoint. This allowable
88 + values are normally 8 and 16. Some bus interface devices may not
91 +CONFIG_USBD_STORAGE_DEF_DEVICE_NAME
92 + Specify the default block device name to used on mass storage.
93 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/Config.in linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Config.in
94 --- linux-2.4.18/drivers/usb/device/storage_fd/Config.in 1970-01-01 03:00:00.000000000 +0300
95 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Config.in 2003-11-07 05:34:43.000000000 +0300
98 +# Generic Mass Storage Function Driver
100 +# Copyright (c) 2003 Communication Technology Inc.
101 +# Copyright (C) 2001 Lineo, Inc.
102 +# Copyright (C) 2001 Hewlett-Packard Co.
103 +mainmenu_option next_comment
104 +comment "Mass Storage Function"
106 +dep_tristate ' Mass Storage Function Driver' CONFIG_USBD_STORAGE $CONFIG_USBD
107 +if [ "$CONFIG_USBD_STORAGE" = "y" -o "$CONFIG_USBD_STORAGE" = "m" ]; then
108 + hex ' Overide VendorID (hex value)' CONFIG_USBD_STORAGE_VENDORID "0000"
109 + hex ' Overide ProductID (hex value)' CONFIG_USBD_STORAGE_PRODUCTID "0000"
111 + # allow setting of endpoint configurations for some architectures
112 + int ' OUT Endpoint (0-15)' CONFIG_USBD_STORAGE_OUT_ENDPOINT "1"
113 + int ' OUT PacketSize (16, 32, 64)' CONFIG_USBD_STORAGE_OUT_PKTSIZE "64"
114 + int ' IN Endpoint (0-15)' CONFIG_USBD_STORAGE_IN_ENDPOINT "2"
115 + int ' IN PacketSize (16, 32, 64)' CONFIG_USBD_STORAGE_IN_PKTSIZE "64"
117 + if [ ! "$CONFIG_ARCH_SA1100" = "y" -a ! "$CONFIG_ARCH_L7200" = "y" ]; then
118 + int ' INT Endpoint (0-15)' CONFIG_USBD_STORAGE_INT_ENDPOINT "3"
119 + int ' INT PacketSize (8, 16)' CONFIG_USBD_STORAGE_INT_PKTSIZE "16"
122 + string ' Default Mass Storage device name' CONFIG_USBD_STORAGE_DEF_DEVICE_NAME ""
126 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/Makefile linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Makefile
127 --- linux-2.4.18/drivers/usb/device/storage_fd/Makefile 1970-01-01 03:00:00.000000000 +0300
128 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/Makefile 2003-11-07 05:34:43.000000000 +0300
131 +# SA1100 Function driver for a network USB Device
133 +# Copyright (C) 2001 Lineo, Inc.
134 +# Copyright (C) 2001 Hewlett-Packard Co.
137 +O_TARGET := storage_fd_drv.o
138 +list-multi := storage_fd.o
140 +storage_fd-objs := storage-fd.o storageproto.o schedule_task.o # netproto.o crc32.o
142 +# Object file lists.
149 +# Each configuration option enables a list of files.
151 +obj-$(CONFIG_USBD_STORAGE) += storage_fd.o
153 +# Extract lists of the multi-part drivers.
154 +# The 'int-*' lists are the intermediate files used to build the multi's.
156 +multi-y := $(filter $(list-multi), $(obj-y))
157 +multi-m := $(filter $(list-multi), $(obj-m))
158 +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
159 +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
161 +# Files that are both resident and modular: remove from modular.
163 +obj-m := $(filter-out $(obj-y), $(obj-m))
164 +int-m := $(filter-out $(int-y), $(int-m))
166 +# Translate to Rules.make lists.
168 +O_OBJS := $(filter-out $(export-objs), $(obj-y))
169 +OX_OBJS := $(filter $(export-objs), $(obj-y))
170 +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
171 +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
172 +MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
173 +MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
175 +# The global Rules.make.
177 +include $(TOPDIR)/Rules.make
179 +# Link rules for multi-part drivers.
181 +storage_fd.o: $(storage_fd-objs)
182 + $(LD) -r -o $@ $(storage_fd-objs)
186 +storage-fd.o: ../usbd.h ../usbd-bus.h ../usbd-func.h
188 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/schedule_task.c linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/schedule_task.c
189 --- linux-2.4.18/drivers/usb/device/storage_fd/schedule_task.c 1970-01-01 03:00:00.000000000 +0300
190 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/schedule_task.c 2003-11-07 05:34:43.000000000 +0300
193 + * linux/drivers/usb/device/storage_fd/schedule_task.c - schedule task library
195 + * Copyright (c) 2003 Lineo Solutions, Inc.
197 + * Written by Shunnosuke kabata
199 + * This program is free software; you can redistribute it and/or modify
200 + * it under the terms of the GNU General Public License as published by
201 + * the Free Software Foundation; either version 2 of the License, or
202 + * (at your option) any later version.
204 + * This program is distributed in the hope that it will be useful,
205 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
206 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
207 + * GNU General Public License for more details.
209 + * You should have received a copy of the GNU General Public License
210 + * along with this program; if not, write to the Free Software
211 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
215 +/******************************************************************************
217 +******************************************************************************/
218 +#include <linux/config.h>
219 +#include <linux/fs.h>
220 +#include <linux/string.h>
221 +#include <linux/mm.h>
222 +#include <linux/dcache.h>
223 +#include <linux/init.h>
224 +#include <linux/quotaops.h>
225 +#include <linux/slab.h>
226 +#include <linux/cache.h>
227 +#include <linux/swap.h>
228 +#include <linux/swapctl.h>
229 +#include <linux/prefetch.h>
230 +#include <linux/locks.h>
231 +#include <asm/uaccess.h>
233 +#include "schedule_task.h"
235 +/******************************************************************************
237 +******************************************************************************/
238 +#define TASK_DESC_NUM (512)
240 +/******************************************************************************
242 +******************************************************************************/
244 +/**************************************
246 +**************************************/
247 +typedef struct _TASK_DESC{
248 + struct _TASK_DESC* next;
249 + SCHEDULE_TASK_FUNC task_entry;
259 +/**************************************
261 +**************************************/
263 + volatile TASK_DESC* read_desc;
264 + volatile TASK_DESC* write_desc;
265 + TASK_DESC desc_pool[TASK_DESC_NUM];
266 + spinlock_t spin_lock;
267 + struct tq_struct task_que;
268 + unsigned long use_num;
269 + unsigned long max_num;
272 +/******************************************************************************
273 +** Variable Declaration
274 +******************************************************************************/
275 +static TASK_DATA TaskData;
277 +/******************************************************************************
278 +** Local Function Prototype
279 +******************************************************************************/
280 +static void task_entry(void*);
282 +/******************************************************************************
284 +******************************************************************************/
285 +void schedule_task_init(void)
290 + memset(&TaskData, 0x00, sizeof(TaskData));
292 + /* Read/write pointer initialize */
293 + TaskData.read_desc = TaskData.write_desc = &TaskData.desc_pool[0];
295 + /* Ling buffer initialize */
296 + for(i=0; i<(TASK_DESC_NUM-1); i++){
297 + TaskData.desc_pool[i].next = &TaskData.desc_pool[i+1];
299 + TaskData.desc_pool[i].next = &TaskData.desc_pool[0];
301 + /* Spin lock initialize */
302 + spin_lock_init(&TaskData.spin_lock);
304 + /* Task queue initialize */
305 + PREPARE_TQUEUE(&TaskData.task_que, task_entry, &TaskData);
310 +int schedule_task_register(SCHEDULE_TASK_FUNC entry, int param1, int param2,
311 + int param3, int param4, int param5)
313 + unsigned long flags = 0;
315 + spin_lock_irqsave(&TaskData.spin_lock, flags);
317 + /* Free descriptor check */
318 + if(TaskData.write_desc->next == TaskData.read_desc){
319 + printk(KERN_INFO "storage_fd: schedule task no descriptor.\n");
320 + spin_unlock_irqrestore(&TaskData.spin_lock, flags);
324 + /* Descriptor set */
325 + TaskData.write_desc->task_entry = entry;
326 + TaskData.write_desc->task_param1 = param1;
327 + TaskData.write_desc->task_param2 = param2;
328 + TaskData.write_desc->task_param3 = param3;
329 + TaskData.write_desc->task_param4 = param4;
330 + TaskData.write_desc->task_param5 = param5;
332 + /* Pointer update */
333 + TaskData.write_desc = TaskData.write_desc->next;
335 + /* Statistics set */
336 + TaskData.use_num++;
337 + if(TaskData.use_num > TaskData.max_num){
338 + TaskData.max_num = TaskData.use_num;
341 + spin_unlock_irqrestore(&TaskData.spin_lock, flags);
343 + /* Task queue register */
344 + schedule_task(&TaskData.task_que);
349 +void schedule_task_all_unregister(void)
351 + unsigned long flags = 0;
353 + spin_lock_irqsave(&TaskData.spin_lock, flags);
354 + TaskData.read_desc = TaskData.write_desc;
355 + TaskData.use_num = 0;
356 + spin_unlock_irqrestore(&TaskData.spin_lock, flags);
359 +ssize_t schedule_task_proc_read(struct file* file, char* buf, size_t count,
365 + len += sprintf(string + len, "Schedule task max num:0x%d\n",
368 + len += sprintf(string + len, "Schedule task use num:0x%ld\n",
371 + len += sprintf(string + len, "Schedule task max use num:0x%ld\n",
379 + if(len > 0 && copy_to_user(buf, string, len)) {
386 +/******************************************************************************
388 +******************************************************************************/
389 +static void task_entry(void* data)
392 + unsigned long flags = 0;
393 + volatile TASK_DESC* desc;
397 + spin_lock_irqsave(&TaskData.spin_lock, flags);
398 + desc = TaskData.read_desc;
399 + cond = (TaskData.read_desc == TaskData.write_desc);
400 + spin_unlock_irqrestore(&TaskData.spin_lock, flags);
405 + desc->task_entry(desc->task_param1, desc->task_param2,
406 + desc->task_param3, desc->task_param4, desc->task_param5);
408 + spin_lock_irqsave(&TaskData.spin_lock, flags);
410 + /* Pointer update */
411 + TaskData.read_desc = TaskData.read_desc->next;
413 + /* Statistics set */
414 + TaskData.use_num--;
416 + spin_unlock_irqrestore(&TaskData.spin_lock, flags);
422 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/schedule_task.h linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/schedule_task.h
423 --- linux-2.4.18/drivers/usb/device/storage_fd/schedule_task.h 1970-01-01 03:00:00.000000000 +0300
424 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/schedule_task.h 2003-11-07 05:34:43.000000000 +0300
427 + * linux/drivers/usb/device/storage_fd/schedule_task.h - schedule task library header
429 + * Copyright (c) 2003 Lineo Solutions, Inc.
431 + * Written by Shunnosuke kabata
433 + * This program is free software; you can redistribute it and/or modify
434 + * it under the terms of the GNU General Public License as published by
435 + * the Free Software Foundation; either version 2 of the License, or
436 + * (at your option) any later version.
438 + * This program is distributed in the hope that it will be useful,
439 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
440 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
441 + * GNU General Public License for more details.
443 + * You should have received a copy of the GNU General Public License
444 + * along with this program; if not, write to the Free Software
445 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
449 +#ifndef _SCHEDULE_TASK_H_
450 +#define _SCHEDULE_TASK_H_
452 +/******************************************************************************
454 +******************************************************************************/
455 +typedef int (*SCHEDULE_TASK_FUNC)(int, int, int, int, int);
457 +/******************************************************************************
458 +** Global Function Prototype
459 +******************************************************************************/
460 +void schedule_task_init(void);
461 +int schedule_task_register(SCHEDULE_TASK_FUNC, int, int, int, int, int);
462 +void schedule_task_all_unregister(void);
463 +ssize_t schedule_task_proc_read(struct file*, char*, size_t, loff_t*);
465 +#endif /* _SCHEDULE_TASK_H_ */
467 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/storage-fd.c linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storage-fd.c
468 --- linux-2.4.18/drivers/usb/device/storage_fd/storage-fd.c 1970-01-01 03:00:00.000000000 +0300
469 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storage-fd.c 2003-11-07 05:34:43.000000000 +0300
472 + * linux/drivers/usb/device/storage_fd/storage-fd.c - mass storage function driver
474 + * Copyright (c) 2003 Lineo Solutions, Inc.
476 + * Written by Shunnosuke kabata
478 + * This program is free software; you can redistribute it and/or modify
479 + * it under the terms of the GNU General Public License as published by
480 + * the Free Software Foundation; either version 2 of the License, or
481 + * (at your option) any later version.
483 + * This program is distributed in the hope that it will be useful,
484 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
485 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
486 + * GNU General Public License for more details.
488 + * You should have received a copy of the GNU General Public License
489 + * along with this program; if not, write to the Free Software
490 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
494 + * linux/drivers/usbd/net_fd/net-fd.c - network function driver
496 + * Copyright (c) 2000, 2001, 2002 Lineo
497 + * Copyright (c) 2001 Hewlett Packard
500 + * Stuart Lynne <sl@lineo.com>,
501 + * Tom Rushworth <tbr@lineo.com>,
502 + * Bruce Balden <balden@lineo.com>
504 + * This program is free software; you can redistribute it and/or modify
505 + * it under the terms of the GNU General Public License as published by
506 + * the Free Software Foundation; either version 2 of the License, or
507 + * (at your option) any later version.
509 + * This program is distributed in the hope that it will be useful,
510 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
511 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
512 + * GNU General Public License for more details.
514 + * You should have received a copy of the GNU General Public License
515 + * along with this program; if not, write to the Free Software
516 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
520 +/******************************************************************************
522 +******************************************************************************/
523 +#include <linux/config.h>
524 +#include <linux/module.h>
526 +#include "../usbd-export.h"
527 +#include "../usbd-build.h"
528 +#include "../usbd-module.h"
530 +#include <linux/init.h>
531 +#include <linux/kernel.h>
532 +#include <linux/list.h>
533 +#include <linux/netdevice.h>
534 +#include <linux/skbuff.h>
535 +#include <linux/etherdevice.h>
536 +#include <linux/rtnetlink.h>
537 +#include <linux/smp_lock.h>
538 +#include <linux/ctype.h>
539 +#include <linux/timer.h>
540 +#include <linux/string.h>
541 +#include <linux/atmdev.h>
542 +#include <linux/pkt_sched.h>
543 +#include <linux/delay.h>
544 +#include <asm/uaccess.h>
545 +#include <asm/system.h>
546 +#include <net/arp.h>
548 +#include <linux/autoconf.h>
550 +#include "../usbd.h"
551 +#include "../usbd-func.h"
552 +#include "../usbd-bus.h"
553 +#include "../usbd-inline.h"
554 +#include "../usbd-arch.h"
555 +#include "../hotplug.h"
557 +#include "schedule_task.h"
558 +#include "storageproto.h"
560 +/******************************************************************************
562 +******************************************************************************/
564 +/**************************************
565 +** Module Information
566 +**************************************/
568 +MODULE_AUTHOR("Shunnosuke kabata");
569 +MODULE_DESCRIPTION("USB Device Mass Storage Function");
570 +USBD_MODULE_INFO("storage_fd 0.1");
572 +/**************************************
573 +** Configration Check
574 +**************************************/
576 +#if !defined (CONFIG_USBD_VENDORID) && !defined(CONFIG_USBD_STORAGE_VENDORID)
579 +#if !defined (CONFIG_USBD_PRODUCTID) && !defined(CONFIG_USBD_STORAGE_PRODUCTID)
580 +#error No Product ID
583 +#if defined(CONFIG_USBD_STORAGE_VENDORID) && (CONFIG_USBD_STORAGE_VENDORID > 0)
584 +#undef CONFIG_USBD_VENDORID
585 +#define CONFIG_USBD_VENDORID CONFIG_USBD_STORAGE_VENDORID
588 +#if defined(CONFIG_USBD_STORAGE_PRODUCTID) && (CONFIG_USBD_STORAGE_PRODUCTID > 0)
589 +#undef CONFIG_USBD_PRODUCTID
590 +#define CONFIG_USBD_PRODUCTID CONFIG_USBD_STORAGE_PRODUCTID
593 +#ifndef CONFIG_USBD_MAXPOWER
594 +#define CONFIG_USBD_MAXPOWER 0
597 +#ifndef CONFIG_USBD_MANUFACTURER
598 +#define CONFIG_USBD_MANUFACTURER "Sharp"
601 +#define MAXTRANSFER (512)
603 +#ifndef CONFIG_USBD_VENDORID
604 +#error "CONFIG_USBD_VENDORID not defined"
607 +#ifndef CONFIG_USBD_PRODUCTID
608 +#error "CONFIG_USBD_PRODUCTID not defined"
611 +#ifndef CONFIG_USBD_PRODUCT_NAME
612 +#define CONFIG_USBD_PRODUCT_NAME "Linux Mass Storage Driver"
615 +#ifndef CONFIG_USBD_SERIAL_NUMBER_STR
616 +#define CONFIG_USBD_SERIAL_NUMBER_STR ""
620 + * USB 2.0 spec does not mention it, but MaxPower is expected to be at least one
621 + * and is tested for in USB configuration tests.
624 +#ifdef CONFIG_USBD_SELFPOWERED
625 +#define BMATTRIBUTE BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED
628 +#define BMATTRIBUTE BMATTRIBUTE_RESERVED
629 +#define BMAXPOWER CONFIG_USBD_MAXPOWER
633 + * setup some default values for pktsizes and endpoint addresses.
636 +#ifndef CONFIG_USBD_STORAGE_OUT_PKTSIZE
637 +#define CONFIG_USBD_STORAGE_OUT_PKTSIZE 64
640 +#ifndef CONFIG_USBD_STORAGE_IN_PKTSIZE
641 +#define CONFIG_USBD_STORAGE_IN_PKTSIZE 64
644 +#ifndef CONFIG_USBD_STORAGE_INT_PKTSIZE
645 +#define CONFIG_USBD_STORAGE_INT_PKTSIZE 16
648 +#ifndef CONFIG_USBD_STORAGE_OUT_ENDPOINT
649 +#define CONFIG_USBD_STORAGE_OUT_ENDPOINT 1
652 +#ifndef CONFIG_USBD_STORAGE_IN_ENDPOINT
653 +#define CONFIG_USBD_STORAGE_IN_ENDPOINT 2
656 +#ifndef CONFIG_USBD_STORAGE_INT_ENDPOINT
657 +#define CONFIG_USBD_STORAGE_INT_ENDPOINT 3
661 + * check for architecture specific endpoint configurations
664 +#if defined(ABS_OUT_ADDR)
666 + //#warning USING ABS ENDPOINT OUT ADDRESS
667 + #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT
669 + #if ABS_OUT_ADDR > 0
670 + #define CONFIG_USBD_STORAGE_OUT_ENDPOINT ABS_OUT_ADDR
673 +#elif defined(MAX_OUT_ADDR) && defined(CONFIG_USBD_STORAGE_OUT_ENDPOINT) && (CONFIG_USBD_STORAGE_OUT_ENDPOINT > MAX_OUT_ADDR)
675 + //#warning USING DEFAULT ENDPOINT OUT ADDRESS
676 + #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT
677 + #define CONFIG_USBD_STORAGE_OUT_ENDPOINT DFL_OUT_ADDR
681 +#if defined(ABS_IN_ADDR)
683 + //#warning USING ABS ENDPOINT IN ADDRESS
684 + #undef CONFIG_USBD_STORAGE_IN_ENDPOINT
686 + #if ABS_IN_ADDR > 0
687 + #define CONFIG_USBD_STORAGE_IN_ENDPOINT ABS_IN_ADDR
690 +#elif defined(MAX_IN_ADDR) && defined(CONFIG_USBD_STORAGE_IN_ENDPOINT) && (CONFIG_USBD_STORAGE_IN_ENDPOINT > MAX_IN_ADDR)
692 + //#warning USING DEFAULT ENDPOINT IN ADDRESS
693 + #undef CONFIG_USBD_STORAGE_IN_ENDPOINT
694 + #define CONFIG_USBD_STORAGE_IN_ENDPOINT DFL_IN_ADDR
698 +#if defined(ABS_INT_ADDR)
700 + //#warning USING ABS ENDPOINT INT ADDRESS
701 + #undef CONFIG_USBD_STORAGE_INT_ENDPOINT
704 + #define CONFIG_USBD_STORAGE_INT_ENDPOINT ABS_INT_ADDR
707 +#elif defined(MAX_INT_ADDR) && defined(CONFIG_USBD_STORAGE_INT_ENDPOINT) && (CONFIG_USBD_STORAGE_INT_ENDPOINT > MAX_INT_ADDR)
709 + //#warning USING DEFAULT ENDPOINT INT ADDRESS
710 + #undef CONFIG_USBD_STORAGE_INT_ENDPOINT
711 + #define CONFIG_USBD_STORAGE_INT_ENDPOINT DFL_INT_ADDR
715 +#if defined(MAX_OUT_PKTSIZE) && defined(CONFIG_USBD_STORAGE_OUT_PKTSIZE) && CONFIG_USBD_STORAGE_OUT_PKTSIZE > MAX_OUT_PKTSIZE
717 + //#warning OVERIDING ENDPOINT OUT PKTSIZE
718 + #undef CONFIG_USBD_STORAGE_OUT_PKTSIZE
719 + #define CONFIG_USBD_STORAGE_OUT_PKTSIZE MAX_OUT_PKTSIZE
722 +#if defined(MAX_IN_PKTSIZE) && defined(CONFIG_USBD_STORAGE_IN_PKTSIZE) && CONFIG_USBD_STORAGE_IN_PKTSIZE > MAX_IN_PKTSIZE
724 + //#warning OVERIDING ENDPOINT IN PKTSIZE
725 + #undef CONFIG_USBD_STORAGE_IN_PKTSIZE
726 + #define CONFIG_USBD_STORAGE_IN_PKTSIZE MAX_IN_PKTSIZE
729 +#if defined(MAX_INT_PKTSIZE) && defined(CONFIG_USBD_STORAGE_INT_PKTSIZE) && CONFIG_USBD_STORAGE_INT_PKTSIZE > MAX_INT_PKTSIZE
731 + //#warning OVERIDING ENDPOINT INT PKTSIZE
732 + #undef CONFIG_USBD_STORAGE_INT_PKTSIZE
733 + #define CONFIG_USBD_STORAGE_INT_PKTSIZE MAX_INT_PKTSIZE
736 +/******************************************************************************
737 +** Variable Declaration
738 +******************************************************************************/
740 +/**************************************
741 +** Module Parameters
742 +**************************************/
744 +static u32 vendor_id;
745 +static u32 product_id;
746 +static int out_pkt_sz = CONFIG_USBD_STORAGE_OUT_PKTSIZE;
747 +static int in_pkt_sz = CONFIG_USBD_STORAGE_IN_PKTSIZE;
749 +MODULE_PARM(vendor_id, "i");
750 +MODULE_PARM(product_id, "i");
751 +MODULE_PARM(out_pkt_sz, "i");
752 +MODULE_PARM(in_pkt_sz, "i");
754 +MODULE_PARM_DESC(vendor_id, "vendor id");
755 +MODULE_PARM_DESC(product_id, "product id");
757 +/**************************************
758 +** Mass Storage Configuration
759 +**************************************/
762 + * Data Interface Alternate 1 endpoints
764 +static __initdata struct usb_endpoint_description StorageAlt1Endpoints[] = {
766 + bEndpointAddress:CONFIG_USBD_STORAGE_OUT_ENDPOINT,
768 + wMaxPacketSize:CONFIG_USBD_STORAGE_OUT_PKTSIZE,
771 + transferSize:MAXTRANSFER,
775 + bEndpointAddress:CONFIG_USBD_STORAGE_IN_ENDPOINT,
777 + wMaxPacketSize:CONFIG_USBD_STORAGE_IN_PKTSIZE,
780 + transferSize:MAXTRANSFER,
783 +#if defined(CONFIG_USBD_STORAGE_INT_ENDPOINT) && (CONFIG_USBD_STORAGE_INT_ENDPOINT > 0)
785 + bEndpointAddress:CONFIG_USBD_STORAGE_INT_ENDPOINT,
786 + bmAttributes:INTERRUPT,
787 + wMaxPacketSize:CONFIG_USBD_STORAGE_INT_PKTSIZE,
790 + transferSize:CONFIG_USBD_STORAGE_INT_PKTSIZE,
797 + * Data Interface Alternate description(s)
799 +static __initdata struct usb_alternate_description StorageAlternateDescriptions[] = {
801 + #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
804 + iInterface:"Mass Storage Interface",
806 + bAlternateSetting:0,
809 + endpoints:sizeof (StorageAlt1Endpoints) / sizeof (struct usb_endpoint_description),
810 + endpoint_list:StorageAlt1Endpoints,
815 + * Interface description(s)
817 +static __initdata struct usb_interface_description StorageInterfaces[] = {
819 + #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
822 + iInterface:"Mass Storage Interface",
824 + bInterfaceClass:MASS_STORAGE_CLASS,
825 + bInterfaceSubClass:MASS_STORAGE_SUBCLASS_SCSI,
826 + bInterfaceProtocol:MASS_STORAGE_PROTO_BULK_ONLY,
827 + alternates:sizeof (StorageAlternateDescriptions) / sizeof (struct usb_alternate_description),
828 + alternate_list:StorageAlternateDescriptions,
832 +/******************************************************************************
833 +** USB Configuration
834 +******************************************************************************/
837 + * Configuration description(s)
839 +struct __initdata usb_configuration_description StorageDescription[] = {
841 + #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
844 + iConfiguration:"Mass Storage Configuration",
846 + bmAttributes:BMATTRIBUTE,
847 + bMaxPower:BMAXPOWER,
848 + interfaces:sizeof (StorageInterfaces) / sizeof (struct usb_interface_description),
849 + interface_list:StorageInterfaces,
854 + * Device Description
856 +struct __initdata usb_device_description StorageDeviceDescription = {
858 + bDeviceSubClass:0, // XXX
859 + bDeviceProtocol:0, // XXX
860 + idVendor:CONFIG_USBD_VENDORID,
861 + idProduct:CONFIG_USBD_PRODUCTID,
862 + iManufacturer:CONFIG_USBD_MANUFACTURER,
863 + iProduct:CONFIG_USBD_PRODUCT_NAME,
864 + iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
867 +/**************************************
869 +**************************************/
870 +static int storage_exit_flag = 0;
871 +static pid_t storage_pid = 0;
872 +static struct semaphore storage_sem;
873 +struct timer_list storage_usb_event_tim;
876 +/******************************************************************************
878 +******************************************************************************/
880 +void storage_urb_send(struct usb_device_instance* device, void* buffer,
886 + if(!(urb = usbd_alloc_urb(device,
887 + device->function_instance_array + port,
888 + CONFIG_USBD_STORAGE_IN_ENDPOINT,
889 + length + 5 + in_pkt_sz))){
890 + printk(KERN_INFO "storage_fd: usbd_alloc_urb failed. length '%d'.\n", length);
895 + memcpy(urb->buffer, buffer, length);
898 + memset(urb->buffer, 0x00, length);
900 + urb->actual_length = length;
902 + if(usbd_send_urb(urb)){
903 + printk(KERN_INFO "storage_fd: usbd_send_urb failed.\n");
904 + usbd_dealloc_urb(urb);
911 +/******************************************************************************
913 +******************************************************************************/
915 +/**************************************
916 +** Called when a USB Device is created or destroyed
917 +**************************************/
919 +static int storage_thread(void *_c)
922 + unsigned long signr;
925 + /* current status set */
929 + storage_pid = current->pid;
931 + /* thread name set */
932 + sprintf(current->comm, STORAGE_THREAD_NAME);
933 + (current)->nice = 10;
935 + /* signal register */
936 + spin_lock_irq(¤t->sigmask_lock);
937 + siginitsetinv(¤t->blocked,
938 + sigmask(SIGUSR1) | sigmask(SIGHUP) | sigmask(SIGKILL) |
939 + sigmask(SIGSTOP) | sigmask(SIGCONT) | sigmask(SIGTERM) |
941 + recalc_sigpending(current);
942 + spin_unlock_irq(¤t->sigmask_lock);
945 + schedule_task_register(
946 + (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_STORAGE,
949 + /* thread active indicate */
950 + sprintf(buff, "%d\n", storage_pid);
951 + hotplug("usbdstorage", buff, "active");
954 + set_current_state(TASK_INTERRUPTIBLE);
956 + if (!signal_pending(current)) {
961 + spin_lock_irq(¤t->sigmask_lock);
962 + signr = dequeue_signal(¤t->blocked, &info);
963 + spin_unlock_irq(¤t->sigmask_lock);
967 + /* media signal indicate */
968 + schedule_task_register(
969 + (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_STORAGE,
972 + DBG_STORAGE_FD(KERN_INFO "storage_fd: signal receive 'SIGHUP'.\n");
976 + DBG_STORAGE_FD(KERN_INFO "storage_fd: signal receive '%ld'\n", signr);
980 + if(storage_exit_flag) break;
982 + /* current status set */
983 + current->state = TASK_RUNNING;
988 + /* thread inactive indicate */
989 + hotplug("usbdstorage", buff, "inactive");
996 +static void storage_function_init(struct usb_bus_instance* bus,
997 + struct usb_device_instance* device,
998 + struct usb_function_driver* function_driver)
1000 + /* schedule task init */
1001 + schedule_task_init();
1003 + /* storage protocol initialize */
1004 + storageproto_init();
1006 + /* semaphore init */
1007 + sema_init(&storage_sem, 0);
1009 + /* timer initialize */
1010 + init_timer(&storage_usb_event_tim);
1012 + /* thread create */
1013 + storage_pid = kernel_thread(storage_thread, NULL, 0);
1018 +static void storage_function_exit(struct usb_device_instance* device)
1021 + storage_exit_flag = 1;
1022 + kill_proc(storage_pid, SIGKILL, 1);
1023 + down(&storage_sem);
1025 + /* delete timer */
1026 + del_timer(&storage_usb_event_tim);
1028 + /* storage protocol exit */
1029 + storageproto_exit();
1031 + /* schedule task delete */
1032 + schedule_task_all_unregister();
1038 +/**************************************
1039 +** Called to handle USB Events
1040 +**************************************/
1042 +static void storage_usb_event_delay_timeout(unsigned long param)
1044 + /* media signal indicate */
1045 + schedule_task_register(
1046 + (SCHEDULE_TASK_FUNC)storageproto_usb_status_check, (int)param,
1053 + * storage_event - process a device event
1054 + * @device: usb device
1055 + * @event: the event that happened
1057 + * Called by the usb device core layer to respond to various USB events.
1059 + * This routine IS called at interrupt time. Please use the usual precautions.
1062 +void storage_event(struct usb_device_instance* device,
1063 + usb_device_event_t event, int data)
1067 + usb_device_event_t event;
1070 + {DEVICE_UNKNOWN, "DEVICE_UNKNOWN"},
1071 + {DEVICE_INIT, "DEVICE_INIT"},
1072 + {DEVICE_CREATE, "DEVICE_CREATE"},
1073 + {DEVICE_HUB_CONFIGURED, "DEVICE_HUB_CONFIGURED"},
1074 + {DEVICE_RESET, "DEVICE_RESET"},
1075 + {DEVICE_ADDRESS_ASSIGNED, "DEVICE_ADDRESS_ASSIGNED"},
1076 + {DEVICE_CONFIGURED, "DEVICE_CONFIGURED"},
1077 + {DEVICE_SET_INTERFACE, "DEVICE_SET_INTERFACE"},
1078 + {DEVICE_SET_FEATURE, "DEVICE_SET_FEATURE"},
1079 + {DEVICE_CLEAR_FEATURE, "DEVICE_CLEAR_FEATURE"},
1080 + {DEVICE_DE_CONFIGURED, "DEVICE_DE_CONFIGURED"},
1081 + {DEVICE_BUS_INACTIVE, "DEVICE_BUS_INACTIVE"},
1082 + {DEVICE_BUS_ACTIVITY, "DEVICE_BUS_ACTIVITY"},
1083 + {DEVICE_POWER_INTERRUPTION, "DEVICE_POWER_INTERRUPTION"},
1084 + {DEVICE_HUB_RESET, "DEVICE_HUB_RESET"},
1085 + {DEVICE_DESTROY, "DEVICE_DESTROY"},
1086 + {DEVICE_FUNCTION_PRIVATE, "DEVICE_FUNCTION_PRIVATE"}
1090 + for(i=0; i<(sizeof(eventAnal)/sizeof(eventAnal[0])); i++){
1091 + if(event == eventAnal[i].event){
1092 + DBG_STORAGE_FD(KERN_INFO "storage_fd: event receive '%s'.\n",
1093 + eventAnal[i].string);
1097 + if(i == (sizeof(eventAnal)/sizeof(eventAnal[0]))){
1098 + DBG_STORAGE_FD(KERN_INFO "storage_fd: unknown event receive.\n");
1103 + case DEVICE_ADDRESS_ASSIGNED:
1105 + static int Is1stCheck = 1;
1109 + /* delay timer set */
1110 + del_timer(&storage_usb_event_tim);
1111 + storage_usb_event_tim.expires = jiffies + ((USB_EVENT_DELAY_TIM * HZ) / 1000);
1112 + storage_usb_event_tim.data = USB_DISCONNECT;
1113 + storage_usb_event_tim.function = storage_usb_event_delay_timeout;
1114 + add_timer(&storage_usb_event_tim);
1118 + case DEVICE_BUS_ACTIVITY:
1119 + /* delay timer set */
1120 + del_timer(&storage_usb_event_tim);
1121 + storage_usb_event_tim.expires = jiffies + ((USB_EVENT_DELAY_TIM * HZ) / 1000);
1122 + storage_usb_event_tim.data = USB_CONNECT;
1123 + storage_usb_event_tim.function = storage_usb_event_delay_timeout;
1124 + add_timer(&storage_usb_event_tim);
1127 + case DEVICE_BUS_INACTIVE:
1128 + /* delay timer set */
1129 + del_timer(&storage_usb_event_tim);
1130 + storage_usb_event_tim.expires = jiffies + ((USB_EVENT_DELAY_TIM * HZ) / 1000);
1131 + storage_usb_event_tim.data = USB_DISCONNECT;
1132 + storage_usb_event_tim.function = storage_usb_event_delay_timeout;
1133 + add_timer(&storage_usb_event_tim);
1136 + case DEVICE_RESET:
1137 + schedule_task_register(
1138 + (SCHEDULE_TASK_FUNC)storageproto_usb_reset_ind,
1150 + * storage_recv_setup - called with a control URB
1151 + * @urb - pointer to struct urb
1153 + * Check if this is a setup packet, process the device request, put results
1154 + * back into the urb and return zero or non-zero to indicate success (DATA)
1155 + * or failure (STALL).
1157 + * This routine IS called at interrupt time. Please use the usual precautions.
1160 +int storage_recv_setup(struct urb* urb)
1166 + * storage_recv_urb - called with a received URB
1167 + * @urb - pointer to struct urb
1169 + * Return non-zero if we failed and urb is still valid (not disposed)
1171 + * This routine IS called at interrupt time. Please use the usual precautions.
1174 +int storage_recv_urb(struct urb* urb)
1176 + int port = 0; // XXX compound device
1177 + struct usb_device_instance* device;
1178 + struct usb_function_instance* function;
1180 + if(!urb || !(device = urb->device) ||
1181 + !(function = device->function_instance_array + port)){
1185 + if(urb->status != RECV_OK){
1189 + /* URB urb_analysis */
1190 + schedule_task_register(
1191 + (SCHEDULE_TASK_FUNC)storageproto_urb_analysis, (int)urb,
1198 + * storage_urb_sent - called to indicate URB transmit finished
1199 + * @urb: pointer to struct urb
1202 + * The usb device core layer will use this to let us know when an URB has
1203 + * been finished with.
1205 + * This routine IS called at interrupt time. Please use the usual precautions.
1208 +int storage_urb_sent(struct urb* urb, int rc)
1210 + int port = 0; // XXX compound device
1211 + struct usb_device_instance* device;
1212 + struct usb_function_instance* function;
1214 + if(!urb || !(device = urb->device) ||
1215 + !(function = device->function_instance_array + port)){
1219 + usbd_dealloc_urb (urb);
1224 +/**************************************
1225 +** Proc file system
1226 +**************************************/
1228 +static ssize_t storage_proc_read(struct file* file, char* buf, size_t count,
1233 + if(*pos > 0) return 0;
1235 + if((ret = storageproto_proc_read(file, buf + len, count - len, pos)) < 0){
1240 + if((ret = schedule_task_proc_read(file, buf + len, count - len, pos)) < 0){
1248 +static struct file_operations StorageProcOps = {
1249 + read:storage_proc_read,
1252 +/**************************************
1253 +** Module init and exit
1254 +**************************************/
1256 +struct usb_function_operations StorageFunctionOps = {
1257 + event:storage_event,
1258 + recv_urb:storage_recv_urb,
1259 + recv_setup:storage_recv_setup,
1260 + urb_sent:storage_urb_sent,
1261 + function_init:storage_function_init,
1262 + function_exit:storage_function_exit,
1265 +struct usb_function_driver StorageFunctionDriver = {
1266 + name:"Mass Storage",
1267 + ops:&StorageFunctionOps,
1268 + device_description:&StorageDeviceDescription,
1269 + configurations:sizeof (StorageDescription) / sizeof (struct usb_configuration_description),
1270 + configuration_description:StorageDescription,
1271 + this_module:THIS_MODULE,
1275 + * net_modinit - module init
1278 +static int __init net_modinit(void)
1280 + struct proc_dir_entry* proc_entry;
1282 + printk(KERN_INFO "storage_fd: %s (OUT=%d,IN=%d)\n",
1283 + __usbd_module_info, out_pkt_sz, in_pkt_sz);
1285 + printk(KERN_INFO "storage_fd: vendorID: %x productID: %x\n",
1286 + CONFIG_USBD_VENDORID, CONFIG_USBD_PRODUCTID);
1288 + // verify pkt sizes not too small
1289 + if (out_pkt_sz < 3 || in_pkt_sz < 3){
1290 + printk(KERN_INFO "storage_fd: Rx pkt size %d or Tx pkt size %d too small\n",
1291 + out_pkt_sz, in_pkt_sz);
1296 + StorageDeviceDescription.idVendor = vendor_id;
1299 + StorageDeviceDescription.idProduct = product_id;
1302 + // register us with the usb device support layer
1303 + if(usbd_register_function(&StorageFunctionDriver)){
1304 + printk(KERN_INFO "storage_fd: usbd_register_function failed.\n");
1308 + // create proc entry
1309 + if ((proc_entry = create_proc_entry("usb-storage", 0, 0)) == NULL) {
1310 + usbd_deregister_function (&StorageFunctionDriver);
1311 + printk(KERN_INFO "storage_fd: create_proc_entry failed.\n");
1314 + proc_entry->proc_fops = &StorageProcOps;
1320 + * function_exit - module cleanup
1323 +static void __exit net_modexit (void)
1325 + // de-register us with the usb device support layer
1326 + usbd_deregister_function (&StorageFunctionDriver);
1328 + // remove proc entry
1329 + remove_proc_entry("usb-storage", NULL);
1334 +module_init (net_modinit);
1335 +module_exit (net_modexit);
1336 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/storageproto.c linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storageproto.c
1337 --- linux-2.4.18/drivers/usb/device/storage_fd/storageproto.c 1970-01-01 03:00:00.000000000 +0300
1338 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storageproto.c 2003-11-07 05:34:43.000000000 +0300
1341 + * linux/drivers/usb/device/storage_fd/storageproto.c - mass storage protocol library
1343 + * Copyright (c) 2003 Lineo Solutions, Inc.
1345 + * Written by Shunnosuke kabata
1347 + * This program is free software; you can redistribute it and/or modify
1348 + * it under the terms of the GNU General Public License as published by
1349 + * the Free Software Foundation; either version 2 of the License, or
1350 + * (at your option) any later version.
1352 + * This program is distributed in the hope that it will be useful,
1353 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1354 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1355 + * GNU General Public License for more details.
1357 + * You should have received a copy of the GNU General Public License
1358 + * along with this program; if not, write to the Free Software
1359 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1363 +/******************************************************************************
1365 +******************************************************************************/
1366 +#include <linux/config.h>
1367 +#include <linux/module.h>
1369 +#include "../usbd-export.h"
1370 +#include "../usbd-build.h"
1371 +#include "../usbd-module.h"
1373 +#include <linux/init.h>
1374 +#include <linux/kernel.h>
1375 +#include <linux/list.h>
1376 +#include <linux/netdevice.h>
1377 +#include <linux/skbuff.h>
1378 +#include <linux/etherdevice.h>
1379 +#include <linux/rtnetlink.h>
1380 +#include <linux/smp_lock.h>
1381 +#include <linux/ctype.h>
1382 +#include <linux/timer.h>
1383 +#include <linux/string.h>
1384 +#include <linux/atmdev.h>
1385 +#include <linux/pkt_sched.h>
1386 +#include <linux/delay.h>
1387 +#include <linux/blkdev.h>
1388 +#include <linux/file.h>
1389 +#include <asm/uaccess.h>
1390 +#include <asm/system.h>
1391 +#include <net/arp.h>
1393 +#include <linux/autoconf.h>
1395 +#include "../usbd.h"
1396 +#include "../usbd-func.h"
1397 +#include "../usbd-bus.h"
1398 +#include "../usbd-inline.h"
1399 +#include "../usbd-arch.h"
1400 +#include "../hotplug.h"
1402 +#include "schedule_task.h"
1403 +#include "storageproto.h"
1405 +/******************************************************************************
1407 +******************************************************************************/
1409 +#define DEVICE_BLOCK_SIZE 512
1411 +#define BLOCK_BUFFER_SIZE (1024 * 64)
1413 +#define DEF_NUMBER_OF_HEADS 0x10
1414 +#define DEF_SECTORS_PER_TRACK 0x20
1416 +/******************************************************************************
1417 +** Structure Define
1418 +******************************************************************************/
1421 + unsigned char scsi_command;
1422 + unsigned char* command_name;
1423 + void (*scsi_func)(struct usb_device_instance*,
1424 + COMMAND_BLOCK_WRAPPER*);
1425 +} SCSI_ANALYSIS_TBL;
1428 + unsigned char scsi_command;
1429 + unsigned char* command_name;
1430 + void (*bulkout_func)(struct usb_device_instance*,
1432 +} SCSI_BULKOUT_ANALYSIS_TBL;
1434 +/******************************************************************************
1435 +** Variable Declaration
1436 +******************************************************************************/
1438 +/**************************************
1439 +** Module Parameters
1440 +**************************************/
1442 +static char* storage_device = CONFIG_USBD_STORAGE_DEF_DEVICE_NAME;
1443 +MODULE_PARM(storage_device, "s");
1445 +/**************************************
1446 +** Device Information
1447 +**************************************/
1449 +static struct file* DeviceFile = NULL;
1450 +static int DeviceSize = 0;
1451 +static int DeviceBlockSize = DEVICE_BLOCK_SIZE;
1452 +static int DeviceWrProtect = WR_PROTECT_OFF;
1454 +/**************************************
1456 +**************************************/
1458 +static int StorageStatus = STORAGE_IDLE;
1459 +static int UsbStatus = USB_DISCONNECT;
1460 +static int MediaStatus = MEDIA_EJECT;
1461 +static int MediaChange = MEDIA_CHANGE_OFF;
1463 +/**************************************
1464 +** Keep Information
1465 +**************************************/
1467 +static SCSI_REQUEST_SENSE_DATA RequestSenseData;
1468 +static COMMAND_BLOCK_WRAPPER KeepCBW;
1469 +static unsigned long BulkOutLength = 0;
1470 +static unsigned char BlockBuffer[BLOCK_BUFFER_SIZE];
1472 +/**************************************
1474 +**************************************/
1475 +static unsigned long StatMaxBulkInSize = 0;
1476 +static unsigned long StatMaxBulkOutSize = 0;
1477 +static unsigned long StatDevWriteError = 0;
1478 +static unsigned long StatDevReadError = 0;
1479 +static unsigned long StatDevFlushError = 0;
1480 +static unsigned long StatWriteTimout = 0;
1481 +static unsigned long StatMaxWriteTime = 0;
1483 +/**************************************
1485 +**************************************/
1486 +static struct timer_list BulkOutTim;
1487 +static struct timer_list MediaCheckTim;
1489 +/******************************************************************************
1491 +******************************************************************************/
1493 +static void storage_bulkout_timeout(unsigned long param)
1495 + /* statistics update */
1496 + StatWriteTimout++;
1497 + printk(KERN_INFO "storage_fd: write bulk out timeout. length '%ld/%ld'.\n",
1498 + BulkOutLength, KeepCBW.dCBWDataTransferLength);
1503 +static void media_check_timeout(unsigned long param)
1506 + schedule_task_register(
1507 + (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_TIMER,
1513 +static void request_sense_data_set(unsigned char sense_key, unsigned char asc,
1514 + unsigned char ascq, unsigned long info)
1517 + * set REQUEST SENSE DATA
1520 + memset(&RequestSenseData, 0x00, sizeof(RequestSenseData));
1522 + RequestSenseData.ErrorCode = 0x70;
1523 + RequestSenseData.Valid = (info) ? 1 : 0;
1524 + RequestSenseData.SenseKey = sense_key;
1525 + memcpy(RequestSenseData.Information, &info, sizeof(info));
1526 + RequestSenseData.AdditionalSenseLength = 0x0a;
1527 + RequestSenseData.AdditionalSenseCode = asc;
1528 + RequestSenseData.AdditionalSenseCodeQualifier = ascq;
1533 +static void scsi_inquiry_analysis(struct usb_device_instance* device,
1534 + COMMAND_BLOCK_WRAPPER* cbw)
1536 + SCSI_INQUIRY_DATA data;
1537 + COMMAND_STATUS_WRAPPER csw;
1538 + unsigned long data_len;
1544 + memset(&data, 0x00, sizeof(data));
1546 + data.PeripheralDeviceType = 0x00;
1548 + data.ResponseDataFormat = 0x01;
1549 + data.AdditionalLength = 0x1f;
1550 + strncpy(data.VendorInformation, CONFIG_USBD_MANUFACTURER,
1551 + sizeof(data.VendorInformation));
1552 + strncpy(data.ProductIdentification, CONFIG_USBD_PRODUCT_NAME,
1553 + sizeof(data.ProductIdentification));
1554 + strncpy(data.ProductRevisionLevel, PRODUCT_REVISION_LEVEL,
1555 + sizeof(data.ProductRevisionLevel));
1557 + data_len = sizeof(data);
1558 + if(cbw->dCBWDataTransferLength < data_len){
1559 + data_len = cbw->dCBWDataTransferLength;
1562 + storage_urb_send(device, &data, data_len);
1565 + * status transport
1568 + memset(&csw, 0x00, sizeof(csw));
1570 + csw.dCSWSignature = CSW_SIGNATURE;
1571 + csw.dCSWTag = cbw->dCBWTag;
1572 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1573 + csw.bCSWStatus = 0;
1575 + storage_urb_send(device, &csw, sizeof(csw));
1580 +static void scsi_read_format_capacity_analysis(struct usb_device_instance* device,
1581 + COMMAND_BLOCK_WRAPPER* cbw)
1583 + SCSI_READ_FORMAT_CAPACITY_DATA data;
1584 + COMMAND_STATUS_WRAPPER csw;
1585 + unsigned long block_num, data_len;
1586 + unsigned short block_len;
1592 + block_num = 0xffffffff;
1593 + block_len = (unsigned short)DeviceBlockSize;
1594 + block_num = htonl(block_num);
1595 + block_len = htons(block_len);
1597 + memset(&data, 0x00, sizeof(data));
1599 + data.CapacityListHeader.CapacityListLength =
1600 + sizeof(data.CurrentMaximumCapacityDescriptor);
1601 + memcpy(data.CurrentMaximumCapacityDescriptor.NumberofBlocks, &block_num,
1602 + sizeof(block_num));
1603 + data.CurrentMaximumCapacityDescriptor.DescriptorCode = 0x03;
1604 + memcpy(data.CurrentMaximumCapacityDescriptor.BlockLength + 1, &block_len,
1605 + sizeof(block_len));
1607 + data_len = sizeof(data);
1608 + if(cbw->dCBWDataTransferLength < data_len){
1609 + data_len = cbw->dCBWDataTransferLength;
1612 + storage_urb_send(device, &data, data_len);
1615 + * status transport
1618 + memset(&csw, 0x00, sizeof(csw));
1620 + csw.dCSWSignature = CSW_SIGNATURE;
1621 + csw.dCSWTag = cbw->dCBWTag;
1622 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1623 + csw.bCSWStatus = 0;
1625 + storage_urb_send(device, &csw, sizeof(csw));
1630 +static void scsi_read_capacity_analysis(struct usb_device_instance* device,
1631 + COMMAND_BLOCK_WRAPPER* cbw)
1633 + SCSI_READ_CAPACITY_DATA data;
1634 + COMMAND_STATUS_WRAPPER csw;
1635 + unsigned char data_len, status = 0;
1637 + if(DeviceFile == NULL){
1639 + memset(&data, 0x00, sizeof(data));
1641 + /* data length set */
1642 + data_len = cbw->dCBWDataTransferLength;
1647 + /* error code save REQUEST SENSE */
1648 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1651 + if(MediaChange == MEDIA_CHANGE_ON){
1653 + memset(&data, 0x00, sizeof(data));
1655 + /* data length set */
1656 + data_len = cbw->dCBWDataTransferLength;
1661 + /* error code save REQUEST SENSE */
1662 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
1664 + /* media change flag off */
1665 + MediaChange = MEDIA_CHANGE_OFF;
1668 + unsigned long last_lba, block_len;
1671 + memset(&data, 0x00, sizeof(data));
1674 + last_lba = (DeviceSize / DeviceBlockSize) - 1;
1675 + block_len = DeviceBlockSize;
1676 + last_lba = htonl(last_lba);
1677 + block_len = htonl(block_len);
1679 + memcpy(data.LastLogicalBlockAddress, &last_lba, sizeof(last_lba));
1680 + memcpy(data.BlockLengthInBytes, &block_len, sizeof(block_len));
1682 + /* data length set */
1683 + data_len = sizeof(data);
1693 + if(cbw->dCBWDataTransferLength < data_len){
1694 + data_len = cbw->dCBWDataTransferLength;
1697 + storage_urb_send(device, &data, data_len);
1700 + * status transport
1703 + memset(&csw, 0x00, sizeof(csw));
1705 + csw.dCSWSignature = CSW_SIGNATURE;
1706 + csw.dCSWTag = cbw->dCBWTag;
1707 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1708 + csw.bCSWStatus = status;
1710 + storage_urb_send(device, &csw, sizeof(csw));
1715 +static void scsi_request_sense_analysis(struct usb_device_instance* device,
1716 + COMMAND_BLOCK_WRAPPER* cbw)
1718 + COMMAND_STATUS_WRAPPER csw;
1719 + unsigned long data_len;
1725 + data_len = sizeof(RequestSenseData);
1726 + if(cbw->dCBWDataTransferLength < data_len){
1727 + data_len = cbw->dCBWDataTransferLength;
1730 + storage_urb_send(device, &RequestSenseData, data_len);
1733 + * status transport
1736 + memset(&csw, 0x00, sizeof(csw));
1738 + csw.dCSWSignature = CSW_SIGNATURE;
1739 + csw.dCSWTag = cbw->dCBWTag;
1740 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1741 + csw.bCSWStatus = 0;
1743 + storage_urb_send(device, &csw, sizeof(csw));
1748 +static void scsi_read_10_analysis(struct usb_device_instance* device,
1749 + COMMAND_BLOCK_WRAPPER* cbw)
1751 + SCSI_READ_10_COMMAND* command = (SCSI_READ_10_COMMAND*)cbw->CBWCB;
1752 + COMMAND_STATUS_WRAPPER csw;
1753 + unsigned char status = 0;
1754 + unsigned short len;
1755 + unsigned long lba, size, offset;
1757 + memcpy(&lba, command->LogicalBlockAddress, sizeof(lba));
1758 + memcpy(&len, command->TransferLength, sizeof(len));
1761 + offset = lba * DeviceBlockSize;
1762 + size = cbw->dCBWDataTransferLength;
1764 + if(DeviceFile == NULL){
1765 + /* command fail */
1768 + /* error code save REQUEST SENSE */
1769 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1775 + storage_urb_send(device, NULL, size);
1778 + if(MediaChange == MEDIA_CHANGE_ON){
1779 + /* command fail */
1782 + /* error code save REQUEST SENSE */
1783 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
1785 + /* media change flag off */
1786 + MediaChange = MEDIA_CHANGE_OFF;
1792 + storage_urb_send(device, NULL, size);
1795 + unsigned long count, read_size;
1802 + DeviceFile->f_op->llseek(DeviceFile, offset, 0);
1805 + for(count = size; count; count -= read_size){
1806 + read_size = (count > sizeof(BlockBuffer)) ?
1807 + sizeof(BlockBuffer) : count;
1809 + DeviceFile->f_op->read(DeviceFile, BlockBuffer, read_size,
1810 + &DeviceFile->f_pos) != read_size){
1812 + /* command fail */
1815 + /* error code save REQUEST SENSE */
1816 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1818 + /* statistics update */
1819 + StatDevReadError++;
1820 + printk(KERN_INFO "storage_fd: device read error. length '%ld'.\n", read_size);
1823 + storage_urb_send(device, BlockBuffer, read_size);
1828 + * status transport
1831 + memset(&csw, 0x00, sizeof(csw));
1833 + csw.dCSWSignature = CSW_SIGNATURE;
1834 + csw.dCSWTag = cbw->dCBWTag;
1835 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - size;
1836 + csw.bCSWStatus = status;
1838 + storage_urb_send(device, &csw, sizeof(csw));
1843 +static void scsi_mode_sense_analysis(struct usb_device_instance* device,
1844 + COMMAND_BLOCK_WRAPPER* cbw)
1846 + static READ_WRITE_ERROR_RECOVERY_PAGE page_01 = {
1849 + ReadRetryCount:0x03,
1850 + WriteRetryCount:0x80,
1852 + static FLEXIBLE_DISK_PAGE page_05 = {
1855 + TransferRate:{0x00, 0xFA},
1856 + NumberofHeads:0xA0,
1857 + SectorsperTrack:0x00,
1858 + DataBytesperSector:{0x02, 0x00},
1859 + NumberofCylinders:{0x00, 0x00},
1860 + MotorOnDelay:0x05,
1861 + MotorOffDelay:0x1E,
1862 + MediumRotationRate:{0x01, 0x68},
1864 + static REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE page_1b = {
1869 + static TIMER_AND_PROTECT_PAGE page_1c = {
1872 + InactivityTimeMultiplier:0x0A,
1876 + SCSI_MODE_SENSE_COMMAND* command = (SCSI_MODE_SENSE_COMMAND*)cbw->CBWCB;
1877 + SCSI_MODE_SENSE_DATA data;
1878 + COMMAND_STATUS_WRAPPER csw;
1879 + unsigned char data_len, status = 0;
1880 + unsigned short cylinder, sector;
1881 + unsigned long size;
1887 + memset(&data, 0x00, sizeof(data));
1889 + /* set write protect */
1890 + data.ModeParameterHeader.WP = DeviceWrProtect;
1892 + /* set Flexible Disk Page */
1893 + if(DeviceFile == NULL){
1894 + sector = (unsigned short)DeviceBlockSize;
1896 + sector = htons(sector);
1897 + cylinder = htons(cylinder);
1899 + page_05.NumberofHeads = 0;
1900 + page_05.SectorsperTrack = 0;
1901 + memcpy(page_05.DataBytesperSector, §or, sizeof(sector));
1902 + memcpy(page_05.NumberofCylinders, &cylinder, sizeof(cylinder));
1905 + sector = (unsigned short)DeviceBlockSize;
1906 + size = DEF_NUMBER_OF_HEADS * DEF_SECTORS_PER_TRACK * sector;
1907 + cylinder = DeviceSize / size;
1908 + sector = htons(sector);
1909 + cylinder = htons(cylinder);
1911 + page_05.NumberofHeads = DEF_NUMBER_OF_HEADS;
1912 + page_05.SectorsperTrack = DEF_SECTORS_PER_TRACK;
1913 + memcpy(page_05.DataBytesperSector, §or, sizeof(sector));
1914 + memcpy(page_05.NumberofCylinders, &cylinder, sizeof(cylinder));
1917 + if(command->PC == 0 && command->PageCode == 0x01){
1918 + data_len = sizeof(MODE_PARAMETER_HEADER) + sizeof(page_01);
1919 + data.ModeParameterHeader.ModeDataLength = data_len - 1;
1920 + memcpy(&data.ModePages, &page_01, sizeof(page_01));
1923 + if(command->PC == 0 && command->PageCode == 0x05){
1924 + data_len = sizeof(MODE_PARAMETER_HEADER) + sizeof(page_05);
1925 + data.ModeParameterHeader.ModeDataLength = data_len - 1;
1926 + memcpy(&data.ModePages, &page_05, sizeof(page_05));
1929 + if(command->PC == 0 && command->PageCode == 0x1b){
1930 + data_len = sizeof(MODE_PARAMETER_HEADER) + sizeof(page_1b);
1931 + data.ModeParameterHeader.ModeDataLength = data_len - 1;
1932 + memcpy(&data.ModePages, &page_1b, sizeof(page_1b));
1935 + if(command->PC == 0 && command->PageCode == 0x1c){
1936 + data_len = sizeof(MODE_PARAMETER_HEADER) + sizeof(page_1c);
1937 + data.ModeParameterHeader.ModeDataLength = data_len - 1;
1938 + memcpy(&data.ModePages, &page_1c, sizeof(page_1c));
1941 + if(command->PC == 0 && command->PageCode == 0x3f){
1942 + data_len = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_ALL_PAGES);
1943 + data.ModeParameterHeader.ModeDataLength = data_len - 1;
1944 + memcpy(&data.ModePages.ModeAllPages.ReadWriteErrorRecoveryPage,
1945 + &page_01, sizeof(page_01));
1946 + memcpy(&data.ModePages.ModeAllPages.FlexibleDiskPage,
1947 + &page_05, sizeof(page_05));
1948 + memcpy(&data.ModePages.ModeAllPages.RemovableBlockAccessCapabilitiesPage,
1949 + &page_1b, sizeof(page_1b));
1950 + memcpy(&data.ModePages.ModeAllPages.TimerAndProtectPage,
1951 + &page_1c, sizeof(page_1c));
1954 + /* command fail */
1956 + data_len = cbw->dCBWDataTransferLength;
1958 + /* error code save REQUEST SENSE */
1959 + request_sense_data_set(0x05, 0x24, 0x00, 0x00);
1962 + if(cbw->dCBWDataTransferLength < data_len){
1963 + data_len = cbw->dCBWDataTransferLength;
1966 + storage_urb_send(device, &data, data_len);
1969 + * status transport
1972 + memset(&csw, 0x00, sizeof(csw));
1974 + csw.dCSWSignature = CSW_SIGNATURE;
1975 + csw.dCSWTag = cbw->dCBWTag;
1976 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1977 + csw.bCSWStatus = status;
1979 + storage_urb_send(device, &csw, sizeof(csw));
1984 +static void scsi_test_unit_ready_analysis(struct usb_device_instance* device,
1985 + COMMAND_BLOCK_WRAPPER* cbw)
1987 + COMMAND_STATUS_WRAPPER csw;
1988 + unsigned char status = 0;
1990 + if(DeviceFile == NULL){
1991 + /* command fail */
1994 + /* error code save REQUEST SENSE */
1995 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1998 + if(MediaChange == MEDIA_CHANGE_ON){
1999 + /* command fail */
2002 + /* error code save REQUEST SENSE */
2003 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2005 + /* media change flag off */
2006 + MediaChange = MEDIA_CHANGE_OFF;
2010 + * status transport
2013 + memset(&csw, 0x00, sizeof(csw));
2015 + csw.dCSWSignature = CSW_SIGNATURE;
2016 + csw.dCSWTag = cbw->dCBWTag;
2017 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2018 + csw.bCSWStatus = status;
2020 + storage_urb_send(device, &csw, sizeof(csw));
2025 +static void scsi_prevent_allow_medium_removal_analysis(struct usb_device_instance* device,
2026 + COMMAND_BLOCK_WRAPPER* cbw)
2028 + SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL_COMMAND* command = (SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL_COMMAND*)cbw->CBWCB;
2029 + COMMAND_STATUS_WRAPPER csw;
2030 + unsigned char status = 0;
2032 + if(command->Prevent){
2033 + /* command fail */
2036 + /* error code save REQUEST SENSE */
2037 + request_sense_data_set(0x05, 0x24, 0x00, 0x00);
2041 + * status transport
2044 + memset(&csw, 0x00, sizeof(csw));
2046 + csw.dCSWSignature = CSW_SIGNATURE;
2047 + csw.dCSWTag = cbw->dCBWTag;
2048 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2049 + csw.bCSWStatus = status;
2051 + storage_urb_send(device, &csw, sizeof(csw));
2056 +static void scsi_start_stop_analysis(struct usb_device_instance* device,
2057 + COMMAND_BLOCK_WRAPPER* cbw)
2059 + SCSI_START_STOP_COMMAND* command = (SCSI_START_STOP_COMMAND*)cbw->CBWCB;
2060 + COMMAND_STATUS_WRAPPER csw;
2061 + unsigned char status = 0;
2063 + if(DeviceFile == NULL){
2064 + /* command fail */
2067 + /* error code save REQUEST SENSE */
2068 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2071 + if(MediaChange == MEDIA_CHANGE_ON){
2072 + /* command fail */
2075 + /* error code save REQUEST SENSE */
2076 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2078 + /* media change flag off */
2079 + MediaChange = MEDIA_CHANGE_OFF;
2082 + if(command->Start && command->LoEj){
2083 + /* command fail */
2086 + /* error code save REQUEST SENSE */
2087 + request_sense_data_set(0x05, 0x24, 0x00, 0x00);
2090 + /* device buffer flush */
2091 + if(DeviceFile && DeviceFile->f_op->ioctl(DeviceFile->f_dentry->d_inode,
2092 + DeviceFile, BLKFLSBUF, 0) != 0){
2093 + /* statistics update */
2094 + StatDevFlushError++;
2095 + printk(KERN_INFO "storage_fd: device flush error.\n");
2099 + * status transport
2102 + memset(&csw, 0x00, sizeof(csw));
2104 + csw.dCSWSignature = CSW_SIGNATURE;
2105 + csw.dCSWTag = cbw->dCBWTag;
2106 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2107 + csw.bCSWStatus = status;
2109 + storage_urb_send(device, &csw, sizeof(csw));
2114 +static void scsi_write_10_analysis(struct usb_device_instance* device,
2115 + COMMAND_BLOCK_WRAPPER* cbw)
2118 + BulkOutLength = 0;
2119 + StorageStatus = STORAGE_BULKOUT;
2122 + del_timer(&BulkOutTim);
2123 + BulkOutTim.expires = jiffies + ((WR_BULKOUT_CHK_TIM * HZ) / 1000);
2124 + BulkOutTim.data = 0;
2125 + BulkOutTim.function = storage_bulkout_timeout;
2126 + add_timer(&BulkOutTim);
2131 +static void scsi_verify_analysis(struct usb_device_instance* device,
2132 + COMMAND_BLOCK_WRAPPER* cbw)
2134 + COMMAND_STATUS_WRAPPER csw;
2135 + unsigned char status = 0;
2137 + if(DeviceFile == NULL){
2138 + /* command fail */
2141 + /* error code save REQUEST SENSE */
2142 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2145 + if(MediaChange == MEDIA_CHANGE_ON){
2146 + /* command fail */
2149 + /* error code save REQUEST SENSE */
2150 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2152 + /* media change flag off */
2153 + MediaChange = MEDIA_CHANGE_OFF;
2157 + * status transport
2160 + memset(&csw, 0x00, sizeof(csw));
2162 + csw.dCSWSignature = CSW_SIGNATURE;
2163 + csw.dCSWTag = cbw->dCBWTag;
2164 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2165 + csw.bCSWStatus = status;
2167 + storage_urb_send(device, &csw, sizeof(csw));
2172 +static void scsi_unsupport_analysis(struct usb_device_instance* device,
2173 + COMMAND_BLOCK_WRAPPER* cbw)
2175 + COMMAND_STATUS_WRAPPER csw;
2176 + unsigned char data_len = 0;
2178 + if(((cbw->bmCBWFlags & 0x80) == 0x00) && (cbw->dCBWDataTransferLength)){
2182 + BulkOutLength = 0;
2183 + StorageStatus = STORAGE_BULKOUT;
2188 + if(cbw->dCBWDataTransferLength){
2189 + data_len = cbw->dCBWDataTransferLength;
2190 + storage_urb_send(device, NULL, data_len);
2194 + * status transport
2197 + memset(&csw, 0x00, sizeof(csw));
2199 + csw.dCSWSignature = CSW_SIGNATURE;
2200 + csw.dCSWTag = cbw->dCBWTag;
2201 + csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
2202 + csw.bCSWStatus = 0x01;
2203 + storage_urb_send(device, &csw, sizeof(csw));
2207 + /* error code save REQUEST SENSE */
2208 + request_sense_data_set(0x05, 0x20, 0x00, 0x00);
2213 +static void scsi_bulkout_write_10_analysis(struct usb_device_instance* device,
2214 + void* buffer, int length)
2216 + COMMAND_STATUS_WRAPPER csw;
2217 + unsigned char status = 0;
2218 + unsigned long buff_used_len, buff_offset;
2219 + unsigned long s_tick, e_tick, wr_tick;
2221 + buff_offset = BulkOutLength % sizeof(BlockBuffer);
2223 + memcpy(BlockBuffer + buff_offset, buffer, length);
2224 + BulkOutLength += length;
2226 + buff_used_len = BulkOutLength % sizeof(BlockBuffer);
2227 + if(buff_used_len == 0) buff_used_len = sizeof(BlockBuffer);
2229 + /* delete timer */
2230 + if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2231 + del_timer(&BulkOutTim);
2234 + if(buff_used_len >= sizeof(BlockBuffer) ||
2235 + BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2238 + SCSI_WRITE_10_COMMAND* command = (SCSI_WRITE_10_COMMAND*)&KeepCBW.CBWCB;
2239 + unsigned short len;
2240 + unsigned long lba, offset;
2242 + memcpy(&lba, command->LogicalBlockAddress, sizeof(lba));
2243 + memcpy(&len, command->TransferLength, sizeof(len));
2247 + offset = (lba * DeviceBlockSize) +
2248 + (sizeof(BlockBuffer) * ((BulkOutLength - 1) / sizeof(BlockBuffer)));
2250 + /* device check */
2252 + MediaChange != MEDIA_CHANGE_ON &&
2253 + DeviceWrProtect != WR_PROTECT_ON){
2255 + /* write before jiffies get */
2259 + DeviceFile->f_op->llseek(DeviceFile, offset, 0);
2261 + /* device write */
2262 + if(DeviceFile->f_op->write(DeviceFile, BlockBuffer, buff_used_len,
2263 + &DeviceFile->f_pos) != buff_used_len){
2264 + /* statistics update */
2265 + StatDevWriteError++;
2266 + printk(KERN_INFO "storage_fd: device write error. length '%ld'.\n", buff_used_len);
2269 + /* write after jiffies get */
2272 + /* statistics update */
2273 + wr_tick = e_tick - s_tick;
2274 + if(wr_tick > StatMaxWriteTime){
2275 + StatMaxWriteTime = wr_tick;
2280 + if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2281 + if(DeviceFile == NULL){
2282 + /* command fail */
2285 + /* error code save REQUEST SENSE */
2286 + request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2289 + if(MediaChange == MEDIA_CHANGE_ON){
2290 + /* command fail */
2293 + /* error code save REQUEST SENSE */
2294 + request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2296 + /* media change flag off */
2297 + MediaChange = MEDIA_CHANGE_OFF;
2300 + if(DeviceWrProtect == WR_PROTECT_ON){
2301 + /* command fail */
2304 + /* error code save REQUEST SENSE */
2305 + request_sense_data_set(0x07, 0x27, 0x00, 0x00);
2307 + /* media change flag off */
2308 + MediaChange = MEDIA_CHANGE_OFF;
2312 + * status transport
2315 + memset(&csw, 0x00, sizeof(csw));
2317 + csw.dCSWSignature = CSW_SIGNATURE;
2318 + csw.dCSWTag = KeepCBW.dCBWTag;
2319 + csw.dCSWDataResidue = KeepCBW.dCBWDataTransferLength - BulkOutLength;
2320 + csw.bCSWStatus = status;
2322 + storage_urb_send(device, &csw, sizeof(csw));
2324 + /* status reset */
2325 + BulkOutLength = 0;
2326 + StorageStatus = STORAGE_IDLE;
2328 + /* flush before jiffies get */
2331 + /* device buffer flush */
2332 + if(DeviceFile && DeviceFile->f_op->ioctl(DeviceFile->f_dentry->d_inode,
2333 + DeviceFile, BLKFLSBUF, 0) != 0){
2334 + /* statistics update */
2335 + StatDevFlushError++;
2336 + printk(KERN_INFO "storage_fd: device flush error.\n");
2339 + /* flush after jiffies get */
2342 + /* statistics update */
2343 + wr_tick = e_tick - s_tick;
2344 + if(wr_tick > StatMaxWriteTime){
2345 + StatMaxWriteTime = wr_tick;
2353 +static void scsi_bulkout_unsupport_analysis(struct usb_device_instance* device,
2354 + void* buffer, int length)
2356 + COMMAND_STATUS_WRAPPER csw;
2358 + BulkOutLength += length;
2360 + if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2362 + * status transport
2365 + memset(&csw, 0x00, sizeof(csw));
2367 + csw.dCSWSignature = CSW_SIGNATURE;
2368 + csw.dCSWTag = KeepCBW.dCBWTag;
2369 + csw.dCSWDataResidue = KeepCBW.dCBWDataTransferLength - BulkOutLength;
2370 + csw.bCSWStatus = 1;
2372 + storage_urb_send(device, &csw, sizeof(csw));
2374 + /* error code save REQUEST SENSE */
2375 + request_sense_data_set(0x05, 0x20, 0x00, 0x00);
2377 + /* status reset */
2378 + BulkOutLength = 0;
2379 + StorageStatus = STORAGE_IDLE;
2385 +/******************************************************************************
2387 +******************************************************************************/
2389 +static SCSI_ANALYSIS_TBL ScsiAnalysisTbl[] = {
2390 + {SCSI_FORMAT_UNT, "SCSI_FORMAT_UNT", NULL},
2391 + {SCSI_INQUIRY, "SCSI_INQUIRY", scsi_inquiry_analysis},
2392 + {SCSI_START_STOP, "SCSI_START_STOP", scsi_start_stop_analysis},
2393 + {SCSI_MODE_SELECT, "SCSI_MODE_SELECT", NULL},
2394 + {SCSI_MODE_SENSE, "SCSI_MODE_SENSE", scsi_mode_sense_analysis},
2395 + {SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, "SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL", scsi_prevent_allow_medium_removal_analysis},
2396 + {SCSI_READ_10, "SCSI_READ_10", scsi_read_10_analysis},
2397 + {SCSI_READ_12, "SCSI_READ_12", NULL},
2398 + {SCSI_READ_CAPACITY, "SCSI_READ_CAPACITY", scsi_read_capacity_analysis},
2399 + {SCSI_READ_FORMAT_CAPACITY, "SCSI_READ_FORMAT_CAPACITY", scsi_read_format_capacity_analysis},
2400 + {SCSI_REQUEST_SENSE, "SCSI_REQUEST_SENSE", scsi_request_sense_analysis},
2401 + {SCSI_REZERO_UNIT, "SCSI_REZERO_UNIT", NULL},
2402 + {SCSI_SEEK_10, "SCSI_SEEK_10", NULL},
2403 + {SCSI_SEND_DIAGNOSTIC, "SCSI_SEND_DIAGNOSTIC", NULL},
2404 + {SCSI_TEST_UNIT_READY, "SCSI_TEST_UNIT_READY", scsi_test_unit_ready_analysis},
2405 + {SCSI_VERIFY, "SCSI_VERIFY", scsi_verify_analysis},
2406 + {SCSI_WRITE_10, "SCSI_WRITE_10", scsi_write_10_analysis},
2407 + {SCSI_WRITE_12, "SCSI_WRITE_12", NULL},
2408 + {SCSI_WRITE_AND_VERIFY, "SCSI_WRITE_AND_VERIFY", NULL}
2411 +static SCSI_BULKOUT_ANALYSIS_TBL ScsiBlkOutAnalysisTbl[] = {
2412 + {SCSI_WRITE_10, "SCSI_WRITE_10", scsi_bulkout_write_10_analysis},
2415 +void storageproto_urb_analysis(struct urb* urb)
2417 + COMMAND_BLOCK_WRAPPER* cbw = (COMMAND_BLOCK_WRAPPER*)urb->buffer;
2420 + /* status BLKOUT check */
2421 + if(StorageStatus == STORAGE_BULKOUT){
2423 + i < sizeof(ScsiBlkOutAnalysisTbl) / sizeof(SCSI_ANALYSIS_TBL);
2425 + if(ScsiBlkOutAnalysisTbl[i].scsi_command == KeepCBW.CBWCB[0]){
2426 + if(ScsiBlkOutAnalysisTbl[i].bulkout_func){
2427 + ScsiBlkOutAnalysisTbl[i].bulkout_func(urb->device,
2429 + urb->actual_length);
2430 + goto RETURN_LABEL;
2435 + scsi_bulkout_unsupport_analysis(urb->device, urb->buffer, urb->actual_length);
2436 + goto RETURN_LABEL;
2439 + /* signature check */
2440 + if(cbw->dCBWSignature != CBW_SIGNATURE){
2441 + printk(KERN_INFO "storage_fd: signature error. '0x%08lx'.\n",
2442 + cbw->dCBWSignature);
2443 + goto RETURN_LABEL;
2446 + /* statistics set */
2447 + if(cbw->dCBWDataTransferLength){
2448 + if(((cbw->bmCBWFlags & 0x80) == 0x00) && (cbw->dCBWDataTransferLength)){
2450 + if(StatMaxBulkOutSize < cbw->dCBWDataTransferLength){
2451 + StatMaxBulkOutSize = cbw->dCBWDataTransferLength;
2456 + if(StatMaxBulkInSize < cbw->dCBWDataTransferLength){
2457 + StatMaxBulkInSize = cbw->dCBWDataTransferLength;
2462 + /* save CBW and set storage status */
2463 + memcpy(&KeepCBW, cbw, sizeof(KeepCBW));
2465 + /* UFI command analysis */
2466 + for(i = 0; i < sizeof(ScsiAnalysisTbl) / sizeof(SCSI_ANALYSIS_TBL); i++){
2467 + if(ScsiAnalysisTbl[i].scsi_command == cbw->CBWCB[0]){
2468 + if(ScsiAnalysisTbl[i].scsi_func){
2469 + ScsiAnalysisTbl[i].scsi_func(urb->device, cbw);
2470 + goto RETURN_LABEL;
2476 + scsi_unsupport_analysis(urb->device, cbw);
2477 + printk(KERN_INFO "storage_fd: SCSI command error. '0x%02x'.\n",
2479 + goto RETURN_LABEL;
2484 + usbd_recycle_urb(urb);
2489 +int storageproto_device_open_check(void)
2491 + struct file* file;
2492 + struct inode* inode;
2496 + /* device already open check */
2498 + storageproto_device_close();
2502 + file = filp_open(storage_device, O_RDWR, 0000);
2504 + file = filp_open(storage_device, O_RDONLY, 0000);
2506 + storageproto_device_close();
2507 + return MEDIA_EJECT;
2509 + DeviceWrProtect = WR_PROTECT_ON;
2512 + file->f_op->llseek(file, 0, 0);
2513 + if(file->f_op->read(file, (void*)&read_org, sizeof(read_org), &file->f_pos)
2514 + != sizeof(read_org)){
2515 + filp_close(file, NULL);
2516 + storageproto_device_close();
2517 + return MEDIA_EJECT;
2520 + /* struct file pointer save */
2521 + DeviceFile = file;
2523 + /* device information */
2524 + inode = file->f_dentry->d_inode;
2525 + dev = inode->i_rdev;
2527 + if (blk_size[MAJOR(dev)]){
2528 + DeviceSize = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
2531 + DeviceSize = INT_MAX << BLOCK_SIZE_BITS;
2534 + if(blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)]){
2535 + DeviceBlockSize = DEVICE_BLOCK_SIZE;
2538 + DeviceBlockSize = DEVICE_BLOCK_SIZE;
2541 + return MEDIA_INSERT;
2544 +void storageproto_device_close(void)
2547 + filp_close(DeviceFile, NULL);
2548 + DeviceFile = NULL;
2550 + DeviceBlockSize = DEVICE_BLOCK_SIZE;
2551 + DeviceWrProtect = WR_PROTECT_OFF;
2557 +void storageproto_usb_status_check(int status)
2559 + static int Is1stCheck = 1;
2561 + /* USB status check */
2566 + if(UsbStatus == status) goto RETURN_LABEL;
2570 + UsbStatus = status;
2572 + switch(UsbStatus){
2574 + /* media status check */
2575 + storageproto_media_status_check(CONTEXT_SCHEDULE);
2577 + switch(MediaStatus){
2581 + case MEDIA_INSERT:
2582 + hotplug("usbdstorage", storage_device, "umount");
2588 + hotplug("usbdstorage", storage_device, "connect");
2591 + case USB_DISCONNECT:
2592 + /* device close */
2593 + storageproto_device_close();
2595 + switch(MediaStatus){
2599 + case MEDIA_INSERT:
2600 + hotplug("usbdstorage", storage_device, "mount");
2606 + hotplug("usbdstorage", storage_device, "disconnect");
2614 + DBG_STORAGE_FD(KERN_INFO "storage_fd: USB check '%s' '%s' 'file:%p'.\n",
2615 + (UsbStatus) ? "USB_CONNECT" : "USB_DISCONNECT",
2616 + (MediaStatus) ? "MEDIA_INSERT" : "MEDIA_EJECT", DeviceFile);
2621 +void storageproto_media_status_check(int call_context)
2623 + static unsigned long RetryCount = 0;
2626 + /* media open check */
2627 + status = storageproto_device_open_check();
2629 + /* media status check retry */
2630 + if(status == MEDIA_EJECT){
2631 + switch(call_context){
2632 + case CONTEXT_STORAGE:
2634 + /* retry counter init */
2638 + del_timer(&MediaCheckTim);
2639 + MediaCheckTim.expires = jiffies + ((MEDIA_CHECK_TIM * HZ) / 1000);
2640 + MediaCheckTim.data = 0;
2641 + MediaCheckTim.function = media_check_timeout;
2642 + add_timer(&MediaCheckTim);
2646 + case CONTEXT_TIMER:
2648 + /* retry counter update */
2651 + /* retry counter check */
2652 + if(RetryCount >= MEDIA_CHECK_RETRY) break;
2655 + del_timer(&MediaCheckTim);
2656 + MediaCheckTim.expires = jiffies + ((MEDIA_CHECK_TIM * HZ) / 1000);
2657 + MediaCheckTim.data = 0;
2658 + MediaCheckTim.function = media_check_timeout;
2659 + add_timer(&MediaCheckTim);
2668 + if(status == MEDIA_INSERT){
2669 + /* delete timer */
2670 + del_timer(&MediaCheckTim);
2673 + /* media status check */
2674 + if(status == MediaStatus){
2675 + if(UsbStatus == USB_DISCONNECT){
2676 + storageproto_device_close();
2678 + if(MediaStatus == MEDIA_INSERT){
2679 + if(call_context == CONTEXT_STORAGE || call_context == CONTEXT_TIMER){
2680 + MediaChange = MEDIA_CHANGE_ON;
2683 + goto RETURN_LABEL;
2687 + MediaStatus = status;
2689 + switch(MediaStatus){
2690 + case MEDIA_INSERT:
2692 + MediaChange = MEDIA_CHANGE_ON;
2694 + switch(UsbStatus){
2695 + case USB_DISCONNECT:
2696 + storageproto_device_close();
2705 + hotplug("usbdstorage", storage_device, "insert");
2709 + switch(UsbStatus){
2710 + case USB_DISCONNECT:
2711 + storageproto_device_close();
2720 + hotplug("usbdstorage", storage_device, "eject");
2728 + DBG_STORAGE_FD(KERN_INFO "storage_fd: media check. '%s' '%s' 'file:%p' '%s'.\n",
2729 + (UsbStatus) ? "USB_CONNECT" : "USB_DISCONNECT",
2730 + (MediaStatus) ? "MEDIA_INSERT" : "MEDIA_EJECT", DeviceFile,
2731 + (call_context == CONTEXT_SCHEDULE) ? "CONTEXT_SCHEDULE" :
2732 + (call_context == CONTEXT_STORAGE) ? "CONTEXT_STORAGE" : "CONTEXT_TIMER");
2737 +void storageproto_usb_reset_ind(void)
2739 + /* status reset */
2740 + BulkOutLength = 0;
2741 + StorageStatus = STORAGE_IDLE;
2743 + DBG_STORAGE_FD(KERN_INFO "storage_fd: storage protocol reset.\n");
2748 +void storageproto_init(void)
2751 + init_timer(&BulkOutTim);
2754 + init_timer(&MediaCheckTim);
2759 +void storageproto_exit(void)
2761 + /* device close */
2762 + storageproto_device_close();
2764 + /* delete timer */
2765 + del_timer(&BulkOutTim);
2767 + /* delete timer */
2768 + del_timer(&MediaCheckTim);
2773 +ssize_t storageproto_proc_read(struct file* file, char* buf, size_t count,
2776 + char string[1024];
2779 + len += sprintf(string + len, "Protocol status:%s\n",
2780 + (StorageStatus == STORAGE_IDLE) ? "STORAGE_IDLE" :
2781 + (StorageStatus == STORAGE_BULKIN) ? "STORAGE_BULKIN" :
2782 + "STORAGE_BULKOUT");
2784 + len += sprintf(string + len, "USB status:%s\n",
2785 + (UsbStatus == USB_DISCONNECT) ? "USB_DISCONNECT" :
2788 + len += sprintf(string + len, "Media status:%s\n",
2789 + (MediaStatus == MEDIA_EJECT) ? "MEDIA_EJECT" :
2792 + len += sprintf(string + len, "Media chage:%s\n",
2793 + (MediaChange == MEDIA_CHANGE_OFF) ? "MEDIA_CHANGE_OFF" :
2794 + "MEDIA_CHANGE_ON");
2796 + len += sprintf(string + len, "Device name:%s\n",
2799 + len += sprintf(string + len, "Device file descriptor:0x%p\n",
2802 + len += sprintf(string + len, "Device size:0x%d\n",
2805 + len += sprintf(string + len, "Device block size:0x%d\n",
2808 + len += sprintf(string + len, "Device write protect:%s\n",
2809 + (DeviceWrProtect == WR_PROTECT_OFF) ? "WR_PROTECT_OFF":
2812 + len += sprintf(string + len, "Bulk in max size:%ld\n",
2813 + StatMaxBulkInSize);
2815 + len += sprintf(string + len, "Bulk out max size:%ld\n",
2816 + StatMaxBulkOutSize);
2818 + len += sprintf(string + len, "device write error:%ld\n",
2819 + StatDevWriteError);
2821 + len += sprintf(string + len, "device read error:%ld\n",
2822 + StatDevReadError);
2824 + len += sprintf(string + len, "device flush error:%ld\n",
2825 + StatDevFlushError);
2827 + len += sprintf(string + len, "write data bulk out timout:%ld\n",
2830 + len += sprintf(string + len, "device write max time:%ld msec\n",
2831 + (StatMaxWriteTime * 1000) / HZ);
2838 + if(len > 0 && copy_to_user(buf, string, len)) {
2845 diff -Nur linux-2.4.18/drivers/usb/device/storage_fd/storageproto.h linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storageproto.h
2846 --- linux-2.4.18/drivers/usb/device/storage_fd/storageproto.h 1970-01-01 03:00:00.000000000 +0300
2847 +++ linux-2.4.18-usb-storage/drivers/usb/device/storage_fd/storageproto.h 2003-11-07 05:34:43.000000000 +0300
2850 + * linux/drivers/usb/device/storage_fd/storageproto.h - mass storage protocol library header
2852 + * Copyright (c) 2003 Lineo Solutions, Inc.
2854 + * Written by Shunnosuke kabata
2856 + * This program is free software; you can redistribute it and/or modify
2857 + * it under the terms of the GNU General Public License as published by
2858 + * the Free Software Foundation; either version 2 of the License, or
2859 + * (at your option) any later version.
2861 + * This program is distributed in the hope that it will be useful,
2862 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2863 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2864 + * GNU General Public License for more details.
2866 + * You should have received a copy of the GNU General Public License
2867 + * along with this program; if not, write to the Free Software
2868 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2872 +#ifndef _STORAGEPROTO_H_
2873 +#define _STORAGEPROTO_H_
2875 +/******************************************************************************
2877 +******************************************************************************/
2879 +/**************************************
2881 +**************************************/
2887 +#define MASS_STORAGE_CLASS 0x08
2893 +#define MASS_STORAGE_SUBCLASS_RBC 0x01
2894 +#define MASS_STORAGE_SUBCLASS_SFF8020I 0x02
2895 +#define MASS_STORAGE_SUBCLASS_QIC157 0x03
2896 +#define MASS_STORAGE_SUBCLASS_UFI 0x04
2897 +#define MASS_STORAGE_SUBCLASS_SFF8070I 0x05
2898 +#define MASS_STORAGE_SUBCLASS_SCSI 0x06
2904 +#define MASS_STORAGE_PROTO_CBI_WITH_COMP 0x00
2905 +#define MASS_STORAGE_PROTO_CBI_NO_COMP 0x01
2906 +#define MASS_STORAGE_PROTO_BULK_ONLY 0x50
2908 +/**************************************
2910 +**************************************/
2912 +#define SCSI_FORMAT_UNT 0x04
2913 +#define SCSI_INQUIRY 0x12
2914 +#define SCSI_START_STOP 0x1b
2915 +#define SCSI_MODE_SELECT 0x55
2916 +#define SCSI_MODE_SENSE 0x1a
2917 +#define SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
2918 +#define SCSI_READ_10 0x28
2919 +#define SCSI_READ_12 0xa8
2920 +#define SCSI_READ_CAPACITY 0x25
2921 +#define SCSI_READ_FORMAT_CAPACITY 0x23
2922 +#define SCSI_REQUEST_SENSE 0x03
2923 +#define SCSI_REZERO_UNIT 0x01
2924 +#define SCSI_SEEK_10 0x2b
2925 +#define SCSI_SEND_DIAGNOSTIC 0x1d
2926 +#define SCSI_TEST_UNIT_READY 0x00
2927 +#define SCSI_VERIFY 0x2f
2928 +#define SCSI_WRITE_10 0x2a
2929 +#define SCSI_WRITE_12 0xaa
2930 +#define SCSI_WRITE_AND_VERIFY 0x2e
2932 +/**************************************
2933 +** SCSI Command Parameter
2934 +**************************************/
2936 +#define CBW_SIGNATURE 0x43425355 /* USBC */
2937 +#define CSW_SIGNATURE 0x53425355 /* USBS */
2939 +#define PRODUCT_REVISION_LEVEL "1.00"
2941 +/**************************************
2943 +**************************************/
2945 +#define WR_PROTECT_OFF 0
2946 +#define WR_PROTECT_ON 1
2948 +#define STORAGE_IDLE 0
2949 +#define STORAGE_BULKIN 1
2950 +#define STORAGE_BULKOUT 2
2952 +#define USB_DISCONNECT 0
2953 +#define USB_CONNECT 1
2955 +#define MEDIA_EJECT 0
2956 +#define MEDIA_INSERT 1
2958 +#define MEDIA_CHANGE_OFF 0
2959 +#define MEDIA_CHANGE_ON 1
2961 +/**************************************
2962 +** Mass Storage Thread Name
2963 +**************************************/
2965 +#define STORAGE_THREAD_NAME "usbdstorage"
2967 +/**************************************
2968 +** Media Signal Delay Time(ms)
2969 +**************************************/
2971 +#define USB_EVENT_DELAY_TIM 1000
2973 +/**************************************
2974 +** Write Bulk Out Check Time(ms)
2975 +**************************************/
2977 +#define WR_BULKOUT_CHK_TIM 1000
2979 +/**************************************
2980 +** Media Check Time(ms)
2981 +**************************************/
2983 +#define MEDIA_CHECK_TIM 3000
2984 +#define MEDIA_CHECK_RETRY 3
2986 +/**************************************
2988 +**************************************/
2990 +#define CONTEXT_SCHEDULE 0
2991 +#define CONTEXT_STORAGE 1
2992 +#define CONTEXT_TIMER 2
2994 +/**************************************
2996 +**************************************/
2998 +#define DBG_STORAGE_FD(fmt, args...) printk(fmt, ##args)
3000 +#define DBG_STORAGE_FD(fmt, args...)
3003 +/******************************************************************************
3004 +** Structure Define
3005 +******************************************************************************/
3007 +/**************************************
3008 +** Command Block Wrapper / Command Status Wrapper
3009 +**************************************/
3012 + * Command Block Wrapper
3015 + unsigned long dCBWSignature;
3016 + unsigned long dCBWTag;
3017 + unsigned long dCBWDataTransferLength;
3018 + unsigned char bmCBWFlags;
3019 + unsigned char bCBWLUN:4,
3021 + unsigned char bCBWCBLength:5,
3023 + unsigned char CBWCB[16];
3024 +} __attribute__((packed)) COMMAND_BLOCK_WRAPPER;
3027 + * Command Status Wrapper
3030 + unsigned long dCSWSignature;
3031 + unsigned long dCSWTag;
3032 + unsigned long dCSWDataResidue;
3033 + unsigned char bCSWStatus;
3034 +} __attribute__((packed)) COMMAND_STATUS_WRAPPER;
3036 +/**************************************
3038 +**************************************/
3045 + unsigned char OperationCode;
3046 + unsigned char EVPD:1,
3048 + LogicalUnitNumber:3;
3049 + unsigned char PageCode;
3050 + unsigned char Reserved2;
3051 + unsigned char AllocationLength;
3052 + unsigned char Reserved3;
3053 + unsigned char Reserved4;
3054 + unsigned char Reserved5;
3055 + unsigned char Reserved6;
3056 + unsigned char Reserved7;
3057 + unsigned char Reserved8;
3058 + unsigned char Reserved9;
3059 +} __attribute__((packed)) SCSI_INQUIRY_COMMAND;
3062 + unsigned char PeripheralDeviceType:5,
3064 + unsigned char Reserved2:7,
3066 + unsigned char ANSIVersion:3,
3069 + unsigned char ResponseDataFormat:4,
3071 + unsigned char AdditionalLength;
3072 + unsigned char Reserved4;
3073 + unsigned char Reserved5;
3074 + unsigned char Reserved6;
3075 + unsigned char VendorInformation[8];
3076 + unsigned char ProductIdentification[16];
3077 + unsigned char ProductRevisionLevel[4];
3078 +} __attribute__((packed)) SCSI_INQUIRY_DATA;
3081 + * READ FORMAT CAPACITY
3085 + unsigned char OperationCode;
3086 + unsigned char Reserved1:5,
3087 + LogicalUnitNumber:3;
3088 + unsigned char Reserved2;
3089 + unsigned char Reserved3;
3090 + unsigned char Reserved4;
3091 + unsigned char Reserved5;
3092 + unsigned char Reserved6;
3093 + unsigned char AllocationLength[2];
3094 + unsigned char Reserved7;
3095 + unsigned char Reserved8;
3096 + unsigned char Reserved9;
3097 +} __attribute__((packed)) SCSI_READ_FORMAT_CAPACITY_COMMAND;
3101 + unsigned char Reserved1;
3102 + unsigned char Reserved2;
3103 + unsigned char Reserved3;
3104 + unsigned char CapacityListLength;
3105 + } __attribute__((packed)) CapacityListHeader;
3107 + unsigned char NumberofBlocks[4];
3108 + unsigned char DescriptorCode:2,
3110 + unsigned char BlockLength[3];
3111 + } __attribute__((packed)) CurrentMaximumCapacityDescriptor;
3112 +} __attribute__((packed)) SCSI_READ_FORMAT_CAPACITY_DATA;
3115 + * READ FORMAT CAPACITY
3119 + unsigned char OperationCode;
3120 + unsigned char RelAdr:1,
3122 + LogicalUnitNumber:3;
3123 + unsigned char LogicalBlockAddress[4];
3124 + unsigned char Reserved2;
3125 + unsigned char Reserved3;
3126 + unsigned char PMI:1,
3128 + unsigned char Reserved5;
3129 + unsigned char Reserved6;
3130 + unsigned char Reserved7;
3131 +} __attribute__((packed)) SCSI_READ_CAPACITY_COMMAND;
3134 + unsigned char LastLogicalBlockAddress[4];
3135 + unsigned char BlockLengthInBytes[4];
3136 +} __attribute__((packed)) SCSI_READ_CAPACITY_DATA;
3143 + unsigned char OperationCode;
3144 + unsigned char Reserved1:5,
3145 + LogicalUnitNumber:3;
3146 + unsigned char Reserved2;
3147 + unsigned char Reserved3;
3148 + unsigned char AllocationLength;
3149 + unsigned char Reserved4;
3150 + unsigned char Reserved5;
3151 + unsigned char Reserved6;
3152 + unsigned char Reserved7;
3153 + unsigned char Reserved8;
3154 + unsigned char Reserved9;
3155 + unsigned char Reserved10;
3156 +} __attribute__((packed)) SCSI_REQUEST_SENSE_COMMAND;
3159 + unsigned char ErrorCode:7,
3161 + unsigned char Reserved1;
3162 + unsigned char SenseKey:4,
3164 + unsigned char Information[4];
3165 + unsigned char AdditionalSenseLength;
3166 + unsigned char Reserved3[4];
3167 + unsigned char AdditionalSenseCode;
3168 + unsigned char AdditionalSenseCodeQualifier;
3169 + unsigned char Reserved4;
3170 + unsigned char Reserved5[3];
3171 +} __attribute__((packed)) SCSI_REQUEST_SENSE_DATA;
3178 + unsigned char OperationCode;
3179 + unsigned char RelAdr:1,
3183 + LogicalUnitNumber:3;
3184 + unsigned char LogicalBlockAddress[4];
3185 + unsigned char Reserved2;
3186 + unsigned char TransferLength[2];
3187 + unsigned char Reserved3;
3188 + unsigned char Reserved4;
3189 + unsigned char Reserved5;
3190 +} __attribute__((packed)) SCSI_READ_10_COMMAND;
3197 + unsigned char OperationCode;
3198 + unsigned char Reserved1:3,
3201 + LogicalUnitNumber:3;
3202 + unsigned char PageCode:6,
3204 + unsigned char Reserved3;
3205 + unsigned char Reserved4;
3206 + unsigned char Reserved5;
3207 + unsigned char Reserved6;
3208 + unsigned char ParameterListLength[2];
3209 + unsigned char Reserved7;
3210 + unsigned char Reserved8;
3211 + unsigned char Reserved9;
3212 +} __attribute__((packed)) SCSI_MODE_SENSE_COMMAND;
3215 + unsigned char ModeDataLength;
3216 + unsigned char MediumTypeCode;
3217 + unsigned char Reserved1:4,
3221 + unsigned char Reserved3;
3222 +} __attribute__((packed)) MODE_PARAMETER_HEADER;
3225 + unsigned char PageCode:6,
3228 + unsigned char PageLength;
3229 + unsigned char DCR:1,
3237 + unsigned char ReadRetryCount;
3238 + unsigned char Reserved6[4];
3239 + unsigned char WriteRetryCount;
3240 + unsigned char Reserved7[3];
3241 +} __attribute__((packed)) READ_WRITE_ERROR_RECOVERY_PAGE;
3244 + unsigned char PageCode:6,
3247 + unsigned char PageLength;
3248 + unsigned char TransferRate[2];
3249 + unsigned char NumberofHeads;
3250 + unsigned char SectorsperTrack;
3251 + unsigned char DataBytesperSector[2];
3252 + unsigned char NumberofCylinders[2];
3253 + unsigned char Reserved2[9];
3254 + unsigned char MotorOnDelay;
3255 + unsigned char MotorOffDelay;
3256 + unsigned char Reserved3[7];
3257 + unsigned char MediumRotationRate[2];
3258 + unsigned char Reserved4;
3259 + unsigned char Reserved5;
3260 +} __attribute__((packed)) FLEXIBLE_DISK_PAGE;
3263 + unsigned char PageCode:6,
3266 + unsigned char PageLength;
3267 + unsigned char Reserved2:6,
3270 + unsigned char TLUN:3,
3274 + unsigned char Reserved4[8];
3275 +} __attribute__((packed)) REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE;
3278 + unsigned char PageCode:6,
3281 + unsigned char PageLength;
3282 + unsigned char Reserved2;
3283 + unsigned char InactivityTimeMultiplier:4,
3285 + unsigned char SWPP:1,
3288 + unsigned char Reserved5;
3289 + unsigned char Reserved6;
3290 + unsigned char Reserved7;
3291 +} __attribute__((packed)) TIMER_AND_PROTECT_PAGE;
3294 + READ_WRITE_ERROR_RECOVERY_PAGE ReadWriteErrorRecoveryPage;
3295 + FLEXIBLE_DISK_PAGE FlexibleDiskPage;
3296 + REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE RemovableBlockAccessCapabilitiesPage;
3297 + TIMER_AND_PROTECT_PAGE TimerAndProtectPage;
3298 +} __attribute__((packed)) MODE_ALL_PAGES;
3301 + MODE_PARAMETER_HEADER ModeParameterHeader;
3303 + READ_WRITE_ERROR_RECOVERY_PAGE ReadWriteErrorRecoveryPage;
3304 + FLEXIBLE_DISK_PAGE FlexibleDiskPage;
3305 + REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE RemovableBlockAccessCapabilitiesPage;
3306 + TIMER_AND_PROTECT_PAGE TimerAndProtectPage;
3307 + MODE_ALL_PAGES ModeAllPages;
3308 + } __attribute__((packed)) ModePages;
3309 +} __attribute__((packed)) SCSI_MODE_SENSE_DATA;
3316 + unsigned char OperationCode;
3317 + unsigned char Reserved1:5,
3318 + LogicalUnitNumber:3;
3319 + unsigned char Reserved2;
3320 + unsigned char Reserved3;
3321 + unsigned char Reserved4;
3322 + unsigned char Reserved5;
3323 + unsigned char Reserved6;
3324 + unsigned char Reserved7;
3325 + unsigned char Reserved8;
3326 + unsigned char Reserved9;
3327 + unsigned char Reserved10;
3328 + unsigned char Reserved11;
3329 +} __attribute__((packed)) SCSI_TEST_UNIT_READY_COMMAND;
3332 + * PREVENT-ALLOW MEDIUM REMOVAL
3336 + unsigned char OperationCode;
3337 + unsigned char Reserved1:5,
3338 + LogicalUnitNumber:3;
3339 + unsigned char Reserved2;
3340 + unsigned char Reserved3;
3341 + unsigned char Prevent:1,
3343 + unsigned char Reserved5;
3344 + unsigned char Reserved6;
3345 + unsigned char Reserved7;
3346 + unsigned char Reserved8;
3347 + unsigned char Reserved9;
3348 + unsigned char Reserved10;
3349 + unsigned char Reserved11;
3350 +} __attribute__((packed)) SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL_COMMAND;
3357 + unsigned char OperationCode;
3358 + unsigned char IMMED:1,
3360 + LogicalUnitNumber:3;
3361 + unsigned char Reserved2;
3362 + unsigned char Reserved3;
3363 + unsigned char Start:1,
3366 + unsigned char Reserved5;
3367 + unsigned char Reserved6;
3368 + unsigned char Reserved7;
3369 + unsigned char Reserved8;
3370 + unsigned char Reserved9;
3371 + unsigned char Reserved10;
3372 + unsigned char Reserved11;
3373 +} __attribute__((packed)) SCSI_START_STOP_COMMAND;
3380 + unsigned char OperationCode;
3381 + unsigned char RelAdr:1,
3385 + LogicalUnitNumber:3;
3386 + unsigned char LogicalBlockAddress[4];
3387 + unsigned char Reserved2;
3388 + unsigned char TransferLength[2];
3389 + unsigned char Reserved3;
3390 + unsigned char Reserved4;
3391 + unsigned char Reserved5;
3392 +} __attribute__((packed)) SCSI_WRITE_10_COMMAND;
3399 + unsigned char OperationCode;
3400 + unsigned char RelAdr:1,
3405 + LogicalUnitNumber:3;
3406 + unsigned char LogicalBlockAddress[4];
3407 + unsigned char Reserved3;
3408 + unsigned char VerificationLength[2];
3409 + unsigned char Reserved4;
3410 + unsigned char Reserved5;
3411 + unsigned char Reserved6;
3412 +} __attribute__((packed)) SCSI_VERIFY_COMMAND;
3414 +/******************************************************************************
3415 +** Global Function Prototype
3416 +******************************************************************************/
3419 +void storage_urb_send(struct usb_device_instance*, void*, int);
3421 +/* storageproto.c */
3422 +void storageproto_urb_analysis(struct urb*);
3423 +int storageproto_device_open_check(void);
3424 +void storageproto_device_close(void);
3425 +void storageproto_usb_status_check(int);
3426 +void storageproto_media_status_check(int);
3427 +void storageproto_usb_reset_ind(void);
3428 +ssize_t storageproto_proc_read(struct file*, char*, size_t, loff_t* pos);
3429 +void storageproto_init(void);
3430 +void storageproto_exit(void);
3432 +#endif /* _STORAGEPROTO_H_ */