]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/usb-storage.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / linux / openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107 / usb-storage.patch
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
4 @@ -440,6 +440,7 @@
5                                          udc_interrupts, *(UDCSR), *(UDCCS0), *(UDCAR));
6  
7                         usbd_device_event (udc_device, DEVICE_RESET, 0);
8 +                       usbd_device_event (udc_device, DEVICE_ADDRESS_ASSIGNED,0);
9                 }
10  
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
15 @@ -34,6 +34,7 @@
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
20         
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
26 @@ -20,6 +20,7 @@
27  
28  subdir-$(CONFIG_USBD_NET) += net_fd
29  subdir-$(CONFIG_USBD_SERIAL) += serial_fd
30 +subdir-$(CONFIG_USBD_STORAGE) += storage_fd
31  
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
37 @@ -0,0 +1,55 @@
38 +CONFIG_USBD_STORAGE
39 +  Enable the generic mass storage function driver. This function is
40 +  used emulating a Linux block driver.
41 +
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.
45 +
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.
49 +
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.
53 +
54 +  Some devices such as the SA-1110 or L7205/L7210 may override this
55 +  value with a fixed value.
56 +
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.
60 +
61 +  Some devices such as the SA-1110 or L7205/L7210 may override this
62 +  value with a fixed value.
63 +
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.
67 +
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
70 +  value.
71 +
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. 
75 +
76 +  Some devices such as the Linkup L7205/L7210 may override this value
77 +  with a lower maximum value (such as 32).
78 +
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. 
82 +
83 +  Some devices such as the Linkup L7205/L7210 may override this value
84 +  with a lower maximum value (such as 32).
85 +
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
89 +  support all values.
90 +
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
96 @@ -0,0 +1,29 @@
97 +#
98 +#  Generic Mass Storage Function Driver
99 +#
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"
105 +
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"
110 +
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"
116 +
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"
120 +   fi
121 +
122 +   string  '   Default Mass Storage device name' CONFIG_USBD_STORAGE_DEF_DEVICE_NAME ""
123 +fi
124 +
125 +endmenu
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
129 @@ -0,0 +1,58 @@
130 +#
131 +# SA1100 Function driver for a network USB Device
132 +#
133 +# Copyright (C) 2001 Lineo, Inc.
134 +# Copyright (C) 2001 Hewlett-Packard Co.
135 +
136 +
137 +O_TARGET       := storage_fd_drv.o
138 +list-multi     := storage_fd.o
139 +
140 +storage_fd-objs        := storage-fd.o storageproto.o schedule_task.o # netproto.o crc32.o 
141 +
142 +# Object file lists.
143 +
144 +obj-y          :=
145 +obj-m          :=
146 +obj-n          :=
147 +obj-           :=
148 +
149 +# Each configuration option enables a list of files.
150 +
151 +obj-$(CONFIG_USBD_STORAGE)   += storage_fd.o
152 +
153 +# Extract lists of the multi-part drivers.
154 +# The 'int-*' lists are the intermediate files used to build the multi's.
155 +
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)))
160 +
161 +# Files that are both resident and modular: remove from modular.
162 +
163 +obj-m          := $(filter-out $(obj-y), $(obj-m))
164 +int-m          := $(filter-out $(int-y), $(int-m))
165 +
166 +# Translate to Rules.make lists.
167 +
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)))
174 +
175 +# The global Rules.make.
176 +
177 +include $(TOPDIR)/Rules.make
178 +
179 +# Link rules for multi-part drivers.
180 +
181 +storage_fd.o: $(storage_fd-objs)
182 +       $(LD) -r -o $@ $(storage_fd-objs)
183 +
184 +# dependencies:
185 +
186 +storage-fd.o: ../usbd.h ../usbd-bus.h ../usbd-func.h
187 +
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
191 @@ -0,0 +1,230 @@
192 +/*
193 + * linux/drivers/usb/device/storage_fd/schedule_task.c - schedule task library
194 + *
195 + * Copyright (c) 2003 Lineo Solutions, Inc.
196 + *
197 + * Written by Shunnosuke kabata
198 + *
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.
203 + *
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.
208 + *
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.
212 + *
213 + */
214 +
215 +/******************************************************************************
216 +** Include File
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>
232 +
233 +#include "schedule_task.h"
234 +
235 +/******************************************************************************
236 +** Macro Define
237 +******************************************************************************/
238 +#define TASK_DESC_NUM   (512)
239 +
240 +/******************************************************************************
241 +** Structure Define
242 +******************************************************************************/
243 +
244 +/**************************************
245 +** TASK_DESC
246 +**************************************/
247 +typedef struct _TASK_DESC{
248 +    struct _TASK_DESC*  next;
249 +    SCHEDULE_TASK_FUNC  task_entry;
250 +    int                 task_param1;
251 +    int                 task_param2;
252 +    int                 task_param3;
253 +    int                 task_param4;
254 +    int                 task_param5;
255 +    char*               file;
256 +    int                 line;
257 +} TASK_DESC;
258 +
259 +/**************************************
260 +** OS_WRP_TASK_DATA
261 +**************************************/
262 +typedef struct{
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;
270 +} TASK_DATA;
271 +
272 +/******************************************************************************
273 +** Variable Declaration
274 +******************************************************************************/
275 +static TASK_DATA    TaskData;
276 +
277 +/******************************************************************************
278 +** Local Function Prototype
279 +******************************************************************************/
280 +static void task_entry(void*);
281 +
282 +/******************************************************************************
283 +** Global Function
284 +******************************************************************************/
285 +void schedule_task_init(void)
286 +{
287 +    int i;
288 +    
289 +    /* 0 clear */
290 +    memset(&TaskData, 0x00, sizeof(TaskData));
291 +    
292 +    /* Read/write pointer initialize */
293 +    TaskData.read_desc = TaskData.write_desc = &TaskData.desc_pool[0];
294 +    
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];
298 +    }
299 +    TaskData.desc_pool[i].next = &TaskData.desc_pool[0];
300 +    
301 +    /* Spin lock initialize */
302 +    spin_lock_init(&TaskData.spin_lock);
303 +    
304 +    /* Task queue initialize */
305 +    PREPARE_TQUEUE(&TaskData.task_que, task_entry, &TaskData);
306 +    
307 +    return;
308 +}
309 +
310 +int schedule_task_register(SCHEDULE_TASK_FUNC entry, int param1, int param2,
311 +                           int param3, int param4, int param5)
312 +{
313 +    unsigned long   flags = 0;
314 +    
315 +    spin_lock_irqsave(&TaskData.spin_lock, flags);
316 +    
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);
321 +        return -1;
322 +    }
323 +    
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;
331 +    
332 +    /* Pointer update */
333 +    TaskData.write_desc = TaskData.write_desc->next;
334 +    
335 +    /* Statistics set */
336 +    TaskData.use_num++;
337 +    if(TaskData.use_num > TaskData.max_num){
338 +        TaskData.max_num = TaskData.use_num;
339 +    }
340 +    
341 +    spin_unlock_irqrestore(&TaskData.spin_lock, flags);
342 +    
343 +    /* Task queue register */
344 +    schedule_task(&TaskData.task_que);
345 +    
346 +    return 0;
347 +}
348 +
349 +void schedule_task_all_unregister(void)
350 +{
351 +    unsigned long   flags = 0;
352 +    
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);
357 +}
358 +
359 +ssize_t schedule_task_proc_read(struct file* file, char* buf, size_t count,
360 +                                loff_t* pos)
361 +{
362 +    char    string[1024];
363 +    int     len = 0;
364 +
365 +    len += sprintf(string + len, "Schedule task max num:0x%d\n",
366 +            TASK_DESC_NUM);
367 +
368 +    len += sprintf(string + len, "Schedule task use num:0x%ld\n",
369 +            TaskData.use_num);
370 +
371 +    len += sprintf(string + len, "Schedule task max use num:0x%ld\n",
372 +            TaskData.max_num);
373 +    
374 +    *pos += len;
375 +    if(len > count){
376 +        len = -EINVAL;
377 +    }
378 +    else
379 +    if(len > 0 && copy_to_user(buf, string, len)) {
380 +        len = -EFAULT;
381 +    }
382 +
383 +    return len;
384 +}
385 +
386 +/******************************************************************************
387 +** Local Function
388 +******************************************************************************/
389 +static void task_entry(void* data)
390 +{
391 +    int                 cond;
392 +    unsigned long       flags = 0;
393 +    volatile TASK_DESC* desc;
394 +    
395 +    for(;;){
396 +        
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);
401 +        
402 +        if(cond) break;
403 +        
404 +        /* Task call */
405 +        desc->task_entry(desc->task_param1, desc->task_param2,
406 +                      desc->task_param3, desc->task_param4, desc->task_param5);
407 +        
408 +        spin_lock_irqsave(&TaskData.spin_lock, flags);
409 +        
410 +        /* Pointer update */
411 +        TaskData.read_desc = TaskData.read_desc->next;
412 +        
413 +        /* Statistics set */
414 +        TaskData.use_num--;
415 +        
416 +        spin_unlock_irqrestore(&TaskData.spin_lock, flags);
417 +    }
418 +    
419 +    return;
420 +}
421 +
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
425 @@ -0,0 +1,41 @@
426 +/*
427 + * linux/drivers/usb/device/storage_fd/schedule_task.h - schedule task library header
428 + *
429 + * Copyright (c) 2003 Lineo Solutions, Inc.
430 + *
431 + * Written by Shunnosuke kabata
432 + *
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.
437 + *
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.
442 + *
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.
446 + *
447 + */
448 +
449 +#ifndef _SCHEDULE_TASK_H_
450 +#define _SCHEDULE_TASK_H_
451 +
452 +/******************************************************************************
453 +** Macro Define
454 +******************************************************************************/
455 +typedef int (*SCHEDULE_TASK_FUNC)(int, int, int, int, int);
456 +
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*);
464 +
465 +#endif  /* _SCHEDULE_TASK_H_ */
466 +
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
470 @@ -0,0 +1,865 @@
471 +/*
472 + * linux/drivers/usb/device/storage_fd/storage-fd.c - mass storage function driver
473 + *
474 + * Copyright (c) 2003 Lineo Solutions, Inc.
475 + *
476 + * Written by Shunnosuke kabata
477 + *
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.
482 + *
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.
487 + *
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.
491 + *
492 + * Based on
493 + *
494 + * linux/drivers/usbd/net_fd/net-fd.c - network function driver
495 + *
496 + * Copyright (c) 2000, 2001, 2002 Lineo
497 + * Copyright (c) 2001 Hewlett Packard
498 + *
499 + * By: 
500 + *      Stuart Lynne <sl@lineo.com>, 
501 + *      Tom Rushworth <tbr@lineo.com>, 
502 + *      Bruce Balden <balden@lineo.com>
503 + *
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.
508 + *
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.
513 + *
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.
517 + *
518 + */
519 +
520 +/******************************************************************************
521 +** Include File
522 +******************************************************************************/
523 +#include <linux/config.h>
524 +#include <linux/module.h>
525 +
526 +#include "../usbd-export.h"
527 +#include "../usbd-build.h"
528 +#include "../usbd-module.h"
529 +
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>
547 +
548 +#include <linux/autoconf.h>
549 +
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"
556 +
557 +#include "schedule_task.h"
558 +#include "storageproto.h"
559 +
560 +/******************************************************************************
561 +** Macro Define
562 +******************************************************************************/
563 +
564 +/**************************************
565 +** Module Information
566 +**************************************/
567 +
568 +MODULE_AUTHOR("Shunnosuke kabata");
569 +MODULE_DESCRIPTION("USB Device Mass Storage Function");
570 +USBD_MODULE_INFO("storage_fd 0.1");
571 +
572 +/**************************************
573 +** Configration Check
574 +**************************************/
575 +
576 +#if !defined (CONFIG_USBD_VENDORID) && !defined(CONFIG_USBD_STORAGE_VENDORID)
577 +#error No Vendor ID
578 +#endif
579 +#if !defined (CONFIG_USBD_PRODUCTID) && !defined(CONFIG_USBD_STORAGE_PRODUCTID)
580 +#error No Product ID
581 +#endif
582 +
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
586 +#endif
587 +
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
591 +#endif
592 +
593 +#ifndef CONFIG_USBD_MAXPOWER
594 +#define CONFIG_USBD_MAXPOWER            0
595 +#endif
596 +
597 +#ifndef CONFIG_USBD_MANUFACTURER
598 +#define CONFIG_USBD_MANUFACTURER        "Sharp"
599 +#endif
600 +
601 +#define MAXTRANSFER                     (512)
602 +
603 +#ifndef CONFIG_USBD_VENDORID
604 +#error "CONFIG_USBD_VENDORID not defined"
605 +#endif
606 +
607 +#ifndef CONFIG_USBD_PRODUCTID
608 +#error "CONFIG_USBD_PRODUCTID not defined"
609 +#endif
610 +
611 +#ifndef CONFIG_USBD_PRODUCT_NAME
612 +#define CONFIG_USBD_PRODUCT_NAME        "Linux Mass Storage Driver"
613 +#endif
614 +
615 +#ifndef CONFIG_USBD_SERIAL_NUMBER_STR
616 +#define CONFIG_USBD_SERIAL_NUMBER_STR   ""
617 +#endif
618 +
619 +/*
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.
622 + */
623 +
624 +#ifdef CONFIG_USBD_SELFPOWERED
625 +#define BMATTRIBUTE BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED
626 +#define BMAXPOWER   1
627 +#else
628 +#define BMATTRIBUTE BMATTRIBUTE_RESERVED
629 +#define BMAXPOWER   CONFIG_USBD_MAXPOWER
630 +#endif
631 +
632 +/*
633 + * setup some default values for pktsizes and endpoint addresses.
634 + */
635 +
636 +#ifndef CONFIG_USBD_STORAGE_OUT_PKTSIZE
637 +#define CONFIG_USBD_STORAGE_OUT_PKTSIZE     64
638 +#endif
639 +
640 +#ifndef CONFIG_USBD_STORAGE_IN_PKTSIZE
641 +#define CONFIG_USBD_STORAGE_IN_PKTSIZE      64
642 +#endif
643 +
644 +#ifndef CONFIG_USBD_STORAGE_INT_PKTSIZE
645 +#define CONFIG_USBD_STORAGE_INT_PKTSIZE     16
646 +#endif
647 +
648 +#ifndef CONFIG_USBD_STORAGE_OUT_ENDPOINT
649 +#define CONFIG_USBD_STORAGE_OUT_ENDPOINT    1
650 +#endif
651 +
652 +#ifndef CONFIG_USBD_STORAGE_IN_ENDPOINT
653 +#define CONFIG_USBD_STORAGE_IN_ENDPOINT     2
654 +#endif
655 +
656 +#ifndef CONFIG_USBD_STORAGE_INT_ENDPOINT
657 +#define CONFIG_USBD_STORAGE_INT_ENDPOINT    3
658 +#endif
659 +
660 +/*
661 + * check for architecture specific endpoint configurations
662 + */
663 +
664 +#if defined(ABS_OUT_ADDR)
665 +    //#warning
666 +    //#warning USING ABS ENDPOINT OUT ADDRESS
667 +    #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT
668 +
669 +    #if ABS_OUT_ADDR > 0
670 +        #define CONFIG_USBD_STORAGE_OUT_ENDPOINT    ABS_OUT_ADDR
671 +    #endif
672 +
673 +#elif defined(MAX_OUT_ADDR) && defined(CONFIG_USBD_STORAGE_OUT_ENDPOINT) && (CONFIG_USBD_STORAGE_OUT_ENDPOINT > MAX_OUT_ADDR)
674 +    //#warning
675 +    //#warning USING DEFAULT ENDPOINT OUT ADDRESS
676 +    #undef CONFIG_USBD_STORAGE_OUT_ENDPOINT
677 +    #define CONFIG_USBD_STORAGE_OUT_ENDPOINT        DFL_OUT_ADDR
678 +
679 +#endif  /* elif */
680 +
681 +#if defined(ABS_IN_ADDR)
682 +    //#warning
683 +    //#warning USING ABS ENDPOINT IN ADDRESS
684 +    #undef CONFIG_USBD_STORAGE_IN_ENDPOINT
685 +
686 +    #if ABS_IN_ADDR > 0
687 +        #define CONFIG_USBD_STORAGE_IN_ENDPOINT     ABS_IN_ADDR
688 +    #endif
689 +
690 +#elif defined(MAX_IN_ADDR) && defined(CONFIG_USBD_STORAGE_IN_ENDPOINT) && (CONFIG_USBD_STORAGE_IN_ENDPOINT > MAX_IN_ADDR)
691 +    //#warning
692 +    //#warning USING DEFAULT ENDPOINT IN ADDRESS
693 +    #undef CONFIG_USBD_STORAGE_IN_ENDPOINT
694 +    #define CONFIG_USBD_STORAGE_IN_ENDPOINT         DFL_IN_ADDR
695 +
696 +#endif  /* elif */
697 +
698 +#if defined(ABS_INT_ADDR)
699 +    //#warning
700 +    //#warning USING ABS ENDPOINT INT ADDRESS
701 +    #undef CONFIG_USBD_STORAGE_INT_ENDPOINT
702 +
703 +    #if ABS_INT_ADDR
704 +        #define CONFIG_USBD_STORAGE_INT_ENDPOINT    ABS_INT_ADDR
705 +    #endif
706 +
707 +#elif defined(MAX_INT_ADDR) && defined(CONFIG_USBD_STORAGE_INT_ENDPOINT) && (CONFIG_USBD_STORAGE_INT_ENDPOINT > MAX_INT_ADDR)
708 +    //#warning
709 +    //#warning USING DEFAULT ENDPOINT INT ADDRESS
710 +    #undef CONFIG_USBD_STORAGE_INT_ENDPOINT
711 +    #define CONFIG_USBD_STORAGE_INT_ENDPOINT        DFL_INT_ADDR
712 +
713 +#endif  /* elif */
714 +
715 +#if defined(MAX_OUT_PKTSIZE) && defined(CONFIG_USBD_STORAGE_OUT_PKTSIZE) && CONFIG_USBD_STORAGE_OUT_PKTSIZE > MAX_OUT_PKTSIZE
716 +    //#warning
717 +    //#warning OVERIDING ENDPOINT OUT PKTSIZE 
718 +    #undef CONFIG_USBD_STORAGE_OUT_PKTSIZE
719 +    #define CONFIG_USBD_STORAGE_OUT_PKTSIZE         MAX_OUT_PKTSIZE
720 +#endif
721 +
722 +#if defined(MAX_IN_PKTSIZE) && defined(CONFIG_USBD_STORAGE_IN_PKTSIZE) && CONFIG_USBD_STORAGE_IN_PKTSIZE > MAX_IN_PKTSIZE
723 +    //#warning
724 +    //#warning OVERIDING ENDPOINT IN PKTSIZE 
725 +    #undef CONFIG_USBD_STORAGE_IN_PKTSIZE
726 +    #define CONFIG_USBD_STORAGE_IN_PKTSIZE          MAX_IN_PKTSIZE
727 +#endif
728 +
729 +#if defined(MAX_INT_PKTSIZE) && defined(CONFIG_USBD_STORAGE_INT_PKTSIZE) && CONFIG_USBD_STORAGE_INT_PKTSIZE > MAX_INT_PKTSIZE
730 +    //#warning
731 +    //#warning OVERIDING ENDPOINT INT PKTSIZE
732 +    #undef CONFIG_USBD_STORAGE_INT_PKTSIZE
733 +    #define CONFIG_USBD_STORAGE_INT_PKTSIZE         MAX_INT_PKTSIZE
734 +#endif
735 +
736 +/******************************************************************************
737 +** Variable Declaration
738 +******************************************************************************/
739 +
740 +/**************************************
741 +** Module Parameters
742 +**************************************/
743 +
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;
748 +
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");
753 +
754 +MODULE_PARM_DESC(vendor_id, "vendor id");
755 +MODULE_PARM_DESC(product_id, "product id");
756 +
757 +/**************************************
758 +** Mass Storage Configuration
759 +**************************************/
760 +
761 +/*
762 + * Data Interface Alternate 1 endpoints
763 + */
764 +static __initdata struct usb_endpoint_description StorageAlt1Endpoints[] = {
765 +    {
766 +        bEndpointAddress:CONFIG_USBD_STORAGE_OUT_ENDPOINT,
767 +        bmAttributes:BULK,
768 +        wMaxPacketSize:CONFIG_USBD_STORAGE_OUT_PKTSIZE,
769 +        bInterval:0,
770 +        direction:OUT,
771 +        transferSize:MAXTRANSFER,
772 +    },
773 +
774 +    {
775 +        bEndpointAddress:CONFIG_USBD_STORAGE_IN_ENDPOINT,
776 +        bmAttributes:BULK,
777 +        wMaxPacketSize:CONFIG_USBD_STORAGE_IN_PKTSIZE,
778 +        bInterval:0,
779 +        direction:IN,
780 +        transferSize:MAXTRANSFER,
781 +    },
782 +
783 +#if defined(CONFIG_USBD_STORAGE_INT_ENDPOINT) && (CONFIG_USBD_STORAGE_INT_ENDPOINT > 0)
784 +    {
785 +        bEndpointAddress:CONFIG_USBD_STORAGE_INT_ENDPOINT,
786 +        bmAttributes:INTERRUPT,
787 +        wMaxPacketSize:CONFIG_USBD_STORAGE_INT_PKTSIZE,
788 +        bInterval:10,
789 +        direction:IN,
790 +        transferSize:CONFIG_USBD_STORAGE_INT_PKTSIZE,
791 +    },
792 +#endif
793 +};
794 +
795 +
796 +/*
797 + * Data Interface Alternate description(s)
798 + */
799 +static __initdata struct usb_alternate_description StorageAlternateDescriptions[] = {
800 +    {
801 +        #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
802 +        iInterface:"",
803 +        #else
804 +        iInterface:"Mass Storage Interface",
805 +        #endif
806 +        bAlternateSetting:0,
807 +        classes:0,
808 +        class_list:NULL,
809 +        endpoints:sizeof (StorageAlt1Endpoints) / sizeof (struct usb_endpoint_description),
810 +        endpoint_list:StorageAlt1Endpoints,
811 +    },
812 +};
813 +
814 +/*
815 + * Interface description(s)
816 + */
817 +static __initdata struct usb_interface_description StorageInterfaces[] = {
818 +    {
819 +        #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
820 +        iInterface:"",
821 +        #else
822 +        iInterface:"Mass Storage Interface",
823 +        #endif
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,
829 +    },
830 +};
831 +
832 +/******************************************************************************
833 +** USB Configuration
834 +******************************************************************************/
835 +
836 +/*
837 + * Configuration description(s)
838 + */
839 +struct __initdata usb_configuration_description StorageDescription[] = {
840 +    {
841 +        #if defined(CONFIG_USBD_STORAGE_NO_STRINGS)
842 +        iConfiguration:"",
843 +        #else
844 +        iConfiguration:"Mass Storage Configuration",
845 +        #endif
846 +        bmAttributes:BMATTRIBUTE,
847 +        bMaxPower:BMAXPOWER,
848 +        interfaces:sizeof (StorageInterfaces) / sizeof (struct usb_interface_description),
849 +        interface_list:StorageInterfaces,
850 +    },
851 +};
852 +
853 +/*
854 + * Device Description
855 + */
856 +struct __initdata usb_device_description StorageDeviceDescription = {
857 +    bDeviceClass:0,
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,
865 +};
866 +
867 +/**************************************
868 +** Other Variable
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;
874 +
875 +
876 +/******************************************************************************
877 +** Global Function
878 +******************************************************************************/
879 +
880 +void storage_urb_send(struct usb_device_instance* device, void* buffer,
881 +                      int length)
882 +{
883 +    int         port = 0;
884 +    struct urb* urb;
885 +
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);
891 +        return;
892 +    }
893 +
894 +    if(buffer){
895 +        memcpy(urb->buffer, buffer, length);
896 +    }
897 +    else{
898 +        memset(urb->buffer, 0x00, length);
899 +    }
900 +    urb->actual_length = length;
901 +
902 +    if(usbd_send_urb(urb)){
903 +        printk(KERN_INFO "storage_fd: usbd_send_urb failed.\n");
904 +        usbd_dealloc_urb(urb);
905 +        return;
906 +    }
907 +
908 +    return;
909 +}
910 +
911 +/******************************************************************************
912 +** Local Function
913 +******************************************************************************/
914 +
915 +/**************************************
916 +** Called when a USB Device is created or destroyed
917 +**************************************/
918 +
919 +static int storage_thread(void *_c)
920 +{
921 +    siginfo_t           info;
922 +    unsigned long       signr;
923 +    char                buff[32];
924 +
925 +    /* current status set */
926 +    daemonize();
927 +
928 +    /* PID set */
929 +    storage_pid = current->pid;
930 +
931 +    /* thread name set */
932 +    sprintf(current->comm, STORAGE_THREAD_NAME);
933 +    (current)->nice = 10;
934 +
935 +    /* signal register */
936 +    spin_lock_irq(&current->sigmask_lock);
937 +    siginitsetinv(&current->blocked,
938 +                  sigmask(SIGUSR1) | sigmask(SIGHUP) | sigmask(SIGKILL) |
939 +                  sigmask(SIGSTOP) | sigmask(SIGCONT) | sigmask(SIGTERM) |
940 +                  sigmask(SIGALRM));
941 +    recalc_sigpending(current);
942 +    spin_unlock_irq(&current->sigmask_lock);
943 +
944 +    /* media open */
945 +    schedule_task_register(
946 +        (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_STORAGE,
947 +        0, 0, 0, 0);
948 +
949 +    /* thread active indicate */
950 +    sprintf(buff, "%d\n", storage_pid);
951 +    hotplug("usbdstorage", buff, "active");
952 +
953 +    for(;;){
954 +        set_current_state(TASK_INTERRUPTIBLE);
955 +
956 +        if (!signal_pending(current)) {
957 +            schedule();
958 +            continue;
959 +        }
960 +
961 +        spin_lock_irq(&current->sigmask_lock);
962 +        signr = dequeue_signal(&current->blocked, &info);
963 +        spin_unlock_irq(&current->sigmask_lock);
964 +
965 +        switch(signr) {
966 +        case SIGHUP:
967 +            /* media signal indicate */
968 +            schedule_task_register(
969 +                (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_STORAGE,
970 +                0, 0, 0, 0);
971 +
972 +            DBG_STORAGE_FD(KERN_INFO "storage_fd: signal receive 'SIGHUP'.\n");
973 +            break;
974 +
975 +        default:
976 +            DBG_STORAGE_FD(KERN_INFO "storage_fd: signal receive '%ld'\n", signr);
977 +            break;
978 +        }
979 +
980 +        if(storage_exit_flag) break;
981 +    }
982 +    /* current status set */
983 +    current->state = TASK_RUNNING;
984 +
985 +    /* PID clear */
986 +    storage_pid = 0;
987 +
988 +    /* thread inactive indicate */
989 +    hotplug("usbdstorage", buff, "inactive");
990 +
991 +    up(&storage_sem);
992 +
993 +    return 0;
994 +}
995 +
996 +static void storage_function_init(struct usb_bus_instance* bus,
997 +                              struct usb_device_instance* device,
998 +                              struct usb_function_driver* function_driver)
999 +{
1000 +    /* schedule task init */
1001 +    schedule_task_init();
1002 +
1003 +    /* storage protocol initialize */
1004 +    storageproto_init();
1005 +
1006 +    /* semaphore init */
1007 +    sema_init(&storage_sem, 0);
1008 +
1009 +    /* timer initialize */
1010 +    init_timer(&storage_usb_event_tim);
1011 +
1012 +    /* thread create */
1013 +    storage_pid = kernel_thread(storage_thread, NULL, 0);
1014 +
1015 +    return;
1016 +}
1017 +
1018 +static void storage_function_exit(struct usb_device_instance* device)
1019 +{
1020 +    /* thread kill */
1021 +    storage_exit_flag = 1;
1022 +    kill_proc(storage_pid, SIGKILL, 1);
1023 +    down(&storage_sem);
1024 +
1025 +    /* delete timer */
1026 +    del_timer(&storage_usb_event_tim);
1027 +
1028 +    /* storage protocol exit */
1029 +    storageproto_exit();
1030 +
1031 +    /* schedule task delete */
1032 +    schedule_task_all_unregister();
1033 +
1034 +    return;
1035 +}
1036 +
1037 +
1038 +/**************************************
1039 +** Called to handle USB Events
1040 +**************************************/
1041 +
1042 +static void storage_usb_event_delay_timeout(unsigned long param)
1043 +{
1044 +    /* media signal indicate */
1045 +    schedule_task_register(
1046 +        (SCHEDULE_TASK_FUNC)storageproto_usb_status_check, (int)param,
1047 +        0, 0, 0, 0);
1048 +
1049 +    return;
1050 +}
1051 +
1052 +/*
1053 + * storage_event - process a device event
1054 + * @device: usb device 
1055 + * @event: the event that happened
1056 + *
1057 + * Called by the usb device core layer to respond to various USB events.
1058 + *
1059 + * This routine IS called at interrupt time. Please use the usual precautions.
1060 + *
1061 + */
1062 +void storage_event(struct usb_device_instance* device,
1063 +                   usb_device_event_t event, int data)
1064 +{
1065 +#if 0
1066 +    static struct {
1067 +        usb_device_event_t  event;
1068 +        char*               string;
1069 +    } eventAnal[] = {
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"}
1087 +    };
1088 +    int i;
1089 +
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);
1094 +            break;
1095 +        }
1096 +    }
1097 +    if(i == (sizeof(eventAnal)/sizeof(eventAnal[0]))){
1098 +        DBG_STORAGE_FD(KERN_INFO "storage_fd: unknown event receive.\n");
1099 +    }
1100 +#endif
1101 +
1102 +    switch(event){
1103 +    case DEVICE_ADDRESS_ASSIGNED:
1104 +        {
1105 +        static int  Is1stCheck = 1;
1106 +        if(Is1stCheck){
1107 +            Is1stCheck = 0;
1108 +
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);
1115 +            break;
1116 +        }
1117 +        }
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);
1125 +        break;
1126 +
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);
1134 +        break;
1135 +
1136 +    case DEVICE_RESET:
1137 +        schedule_task_register(
1138 +            (SCHEDULE_TASK_FUNC)storageproto_usb_reset_ind,
1139 +            0, 0, 0, 0, 0);
1140 +        break;
1141 +
1142 +    default:
1143 +        break;
1144 +    }
1145 +
1146 +    return;
1147 +}
1148 +
1149 +/*
1150 + * storage_recv_setup - called with a control URB 
1151 + * @urb - pointer to struct urb
1152 + *
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).
1156 + *
1157 + * This routine IS called at interrupt time. Please use the usual precautions.
1158 + *
1159 + */
1160 +int storage_recv_setup(struct urb* urb)
1161 +{
1162 +    return 0;
1163 +}
1164 +
1165 +/*
1166 + * storage_recv_urb - called with a received URB 
1167 + * @urb - pointer to struct urb
1168 + *
1169 + * Return non-zero if we failed and urb is still valid (not disposed)
1170 + *
1171 + * This routine IS called at interrupt time. Please use the usual precautions.
1172 + *
1173 + */
1174 +int storage_recv_urb(struct urb* urb)
1175 +{
1176 +    int                             port = 0;   // XXX compound device
1177 +    struct usb_device_instance*     device;
1178 +    struct usb_function_instance*   function;
1179 +
1180 +    if(!urb || !(device = urb->device) ||
1181 +       !(function = device->function_instance_array + port)){
1182 +        return -EINVAL;
1183 +    }
1184 +
1185 +    if(urb->status != RECV_OK){
1186 +        return -EINVAL;
1187 +    }
1188 +
1189 +    /* URB urb_analysis */
1190 +    schedule_task_register(
1191 +        (SCHEDULE_TASK_FUNC)storageproto_urb_analysis, (int)urb,
1192 +        0, 0, 0, 0);
1193 +
1194 +    return 0;
1195 +}
1196 +
1197 +/*
1198 + * storage_urb_sent - called to indicate URB transmit finished
1199 + * @urb: pointer to struct urb
1200 + * @rc: result
1201 + *
1202 + * The usb device core layer will use this to let us know when an URB has
1203 + * been finished with.
1204 + *
1205 + * This routine IS called at interrupt time. Please use the usual precautions.
1206 + *
1207 + */
1208 +int storage_urb_sent(struct urb* urb, int rc)
1209 +{
1210 +    int                             port = 0;   // XXX compound device
1211 +    struct usb_device_instance*     device;
1212 +    struct usb_function_instance*   function;
1213 +
1214 +    if(!urb || !(device = urb->device) ||
1215 +       !(function = device->function_instance_array + port)){
1216 +        return -EINVAL;
1217 +    }
1218 +
1219 +    usbd_dealloc_urb (urb);
1220 +
1221 +    return 0;
1222 +}
1223 +
1224 +/**************************************
1225 +** Proc file system
1226 +**************************************/
1227 +
1228 +static ssize_t storage_proc_read(struct file* file, char* buf, size_t count,
1229 +                                 loff_t* pos)
1230 +{
1231 +    int len = 0, ret;
1232 +
1233 +    if(*pos > 0) return 0;
1234 +
1235 +    if((ret = storageproto_proc_read(file, buf + len, count - len, pos)) < 0){
1236 +        return ret;
1237 +    }
1238 +    len += ret;
1239 +
1240 +    if((ret = schedule_task_proc_read(file, buf + len, count - len, pos)) < 0){
1241 +        return ret;
1242 +    }
1243 +    len += ret;
1244 +
1245 +    return len;
1246 +}
1247 +
1248 +static struct file_operations StorageProcOps = {
1249 +    read:storage_proc_read,
1250 +};
1251 +
1252 +/**************************************
1253 +** Module init and exit
1254 +**************************************/
1255 +
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,
1263 +};
1264 +
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,
1272 +};
1273 +
1274 +/*
1275 + * net_modinit - module init
1276 + *
1277 + */
1278 +static int __init net_modinit(void)
1279 +{
1280 +    struct proc_dir_entry*  proc_entry;
1281 +
1282 +    printk(KERN_INFO "storage_fd: %s (OUT=%d,IN=%d)\n",
1283 +        __usbd_module_info, out_pkt_sz, in_pkt_sz);
1284 +
1285 +    printk(KERN_INFO "storage_fd: vendorID: %x productID: %x\n",
1286 +        CONFIG_USBD_VENDORID, CONFIG_USBD_PRODUCTID);
1287 +
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);
1292 +        return (-EINVAL);
1293 +    }
1294 +
1295 +    if(vendor_id){
1296 +        StorageDeviceDescription.idVendor = vendor_id;
1297 +    }
1298 +    if(product_id){
1299 +        StorageDeviceDescription.idProduct = product_id;
1300 +    }
1301 +
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");
1305 +        return -EINVAL;
1306 +    }
1307 +
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");
1312 +        return -ENOMEM;
1313 +    }
1314 +    proc_entry->proc_fops = &StorageProcOps;
1315 +
1316 +    return 0;
1317 +}
1318 +
1319 +/*
1320 + * function_exit - module cleanup
1321 + *
1322 + */
1323 +static void __exit net_modexit (void)
1324 +{
1325 +    // de-register us with the usb device support layer
1326 +    usbd_deregister_function (&StorageFunctionDriver);
1327 +
1328 +    // remove proc entry
1329 +    remove_proc_entry("usb-storage", NULL);
1330 +
1331 +    return;
1332 +}
1333 +
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
1339 @@ -0,0 +1,1505 @@
1340 +/*
1341 + * linux/drivers/usb/device/storage_fd/storageproto.c - mass storage protocol library
1342 + *
1343 + * Copyright (c) 2003 Lineo Solutions, Inc.
1344 + *
1345 + * Written by Shunnosuke kabata
1346 + *
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.
1351 + *
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.
1356 + *
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.
1360 + *
1361 + */
1362 +
1363 +/******************************************************************************
1364 +** Include File
1365 +******************************************************************************/
1366 +#include <linux/config.h>
1367 +#include <linux/module.h>
1368 +
1369 +#include "../usbd-export.h"
1370 +#include "../usbd-build.h"
1371 +#include "../usbd-module.h"
1372 +
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>
1392 +
1393 +#include <linux/autoconf.h>
1394 +
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"
1401 +
1402 +#include "schedule_task.h"
1403 +#include "storageproto.h"
1404 +
1405 +/******************************************************************************
1406 +** macro define
1407 +******************************************************************************/
1408 +
1409 +#define DEVICE_BLOCK_SIZE       512
1410 +
1411 +#define BLOCK_BUFFER_SIZE       (1024 * 64)
1412 +
1413 +#define DEF_NUMBER_OF_HEADS     0x10
1414 +#define DEF_SECTORS_PER_TRACK   0x20
1415 +
1416 +/******************************************************************************
1417 +** Structure Define
1418 +******************************************************************************/
1419 +
1420 +typedef struct{
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;
1426 +
1427 +typedef struct{
1428 +    unsigned char   scsi_command;
1429 +    unsigned char*  command_name;
1430 +    void            (*bulkout_func)(struct usb_device_instance*,
1431 +                                    void*, int);
1432 +} SCSI_BULKOUT_ANALYSIS_TBL;
1433 +
1434 +/******************************************************************************
1435 +** Variable Declaration
1436 +******************************************************************************/
1437 +
1438 +/**************************************
1439 +** Module Parameters
1440 +**************************************/
1441 +
1442 +static char*    storage_device = CONFIG_USBD_STORAGE_DEF_DEVICE_NAME;
1443 +MODULE_PARM(storage_device, "s");
1444 +
1445 +/**************************************
1446 +** Device Information
1447 +**************************************/
1448 +
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;
1453 +
1454 +/**************************************
1455 +** Status
1456 +**************************************/
1457 +
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;
1462 +
1463 +/**************************************
1464 +** Keep Information
1465 +**************************************/
1466 +
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];
1471 +
1472 +/**************************************
1473 +** Statistics
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;
1482 +
1483 +/**************************************
1484 +** Timer
1485 +**************************************/
1486 +static struct timer_list    BulkOutTim;
1487 +static struct timer_list    MediaCheckTim;
1488 +
1489 +/******************************************************************************
1490 +** Local Function
1491 +******************************************************************************/
1492 +
1493 +static void storage_bulkout_timeout(unsigned long param)
1494 +{
1495 +    /* statistics update */
1496 +    StatWriteTimout++;
1497 +    printk(KERN_INFO "storage_fd: write bulk out timeout. length '%ld/%ld'.\n",
1498 +        BulkOutLength, KeepCBW.dCBWDataTransferLength);
1499 +
1500 +    return;
1501 +}
1502 +
1503 +static void media_check_timeout(unsigned long param)
1504 +{
1505 +    /* media check */
1506 +    schedule_task_register(
1507 +        (SCHEDULE_TASK_FUNC)storageproto_media_status_check, CONTEXT_TIMER,
1508 +        0, 0, 0, 0);
1509 +
1510 +    return;
1511 +}
1512 +
1513 +static void request_sense_data_set(unsigned char sense_key, unsigned char asc,
1514 +                                   unsigned char ascq, unsigned long info)
1515 +{
1516 +    /*
1517 +     * set REQUEST SENSE DATA
1518 +     */
1519 +
1520 +    memset(&RequestSenseData, 0x00, sizeof(RequestSenseData));
1521 +
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;
1529 +
1530 +    return;
1531 +}
1532 +
1533 +static void scsi_inquiry_analysis(struct usb_device_instance* device,
1534 +                                  COMMAND_BLOCK_WRAPPER* cbw)
1535 +{
1536 +    SCSI_INQUIRY_DATA       data;
1537 +    COMMAND_STATUS_WRAPPER  csw;
1538 +    unsigned long           data_len;
1539 +
1540 +    /*
1541 +     * data transport
1542 +     */
1543 +
1544 +    memset(&data, 0x00, sizeof(data));
1545 +
1546 +    data.PeripheralDeviceType = 0x00;
1547 +    data.RMB                  = 1;
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));
1556 +
1557 +    data_len = sizeof(data);
1558 +    if(cbw->dCBWDataTransferLength < data_len){
1559 +        data_len = cbw->dCBWDataTransferLength;
1560 +    }
1561 +
1562 +    storage_urb_send(device, &data, data_len);
1563 +
1564 +    /*
1565 +     * status transport
1566 +     */
1567 +
1568 +    memset(&csw, 0x00, sizeof(csw));
1569 +
1570 +    csw.dCSWSignature   = CSW_SIGNATURE;
1571 +    csw.dCSWTag         = cbw->dCBWTag;
1572 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1573 +    csw.bCSWStatus      = 0;
1574 +
1575 +    storage_urb_send(device, &csw, sizeof(csw));
1576 +
1577 +    return;
1578 +}
1579 +
1580 +static void scsi_read_format_capacity_analysis(struct usb_device_instance* device,
1581 +                                               COMMAND_BLOCK_WRAPPER* cbw)
1582 +{
1583 +    SCSI_READ_FORMAT_CAPACITY_DATA  data;
1584 +    COMMAND_STATUS_WRAPPER          csw;
1585 +    unsigned long                   block_num, data_len;
1586 +    unsigned short                  block_len;
1587 +
1588 +    /*
1589 +     * data transport
1590 +     */
1591 +
1592 +    block_num = 0xffffffff;
1593 +    block_len = (unsigned short)DeviceBlockSize;
1594 +    block_num = htonl(block_num);
1595 +    block_len = htons(block_len);
1596 +
1597 +    memset(&data, 0x00, sizeof(data));
1598 +
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));
1606 +
1607 +    data_len = sizeof(data);
1608 +    if(cbw->dCBWDataTransferLength < data_len){
1609 +        data_len = cbw->dCBWDataTransferLength;
1610 +    }
1611 +
1612 +    storage_urb_send(device, &data, data_len);
1613 +
1614 +    /*
1615 +     * status transport
1616 +     */
1617 +
1618 +    memset(&csw, 0x00, sizeof(csw));
1619 +
1620 +    csw.dCSWSignature   = CSW_SIGNATURE;
1621 +    csw.dCSWTag         = cbw->dCBWTag;
1622 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1623 +    csw.bCSWStatus      = 0;
1624 +
1625 +    storage_urb_send(device, &csw, sizeof(csw));
1626 +
1627 +    return;
1628 +}
1629 +
1630 +static void scsi_read_capacity_analysis(struct usb_device_instance* device,
1631 +                                        COMMAND_BLOCK_WRAPPER* cbw)
1632 +{
1633 +    SCSI_READ_CAPACITY_DATA data;
1634 +    COMMAND_STATUS_WRAPPER  csw;
1635 +    unsigned char           data_len, status = 0;
1636 +
1637 +    if(DeviceFile == NULL){
1638 +        /* 0 clear */
1639 +        memset(&data, 0x00, sizeof(data));
1640 +
1641 +        /* data length set */
1642 +        data_len = cbw->dCBWDataTransferLength;
1643 +
1644 +        /* status set */
1645 +        status = 1;
1646 +
1647 +        /* error code save REQUEST SENSE */
1648 +        request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1649 +    }
1650 +    else
1651 +    if(MediaChange == MEDIA_CHANGE_ON){
1652 +        /* 0 clear */
1653 +        memset(&data, 0x00, sizeof(data));
1654 +
1655 +        /* data length set */
1656 +        data_len = cbw->dCBWDataTransferLength;
1657 +
1658 +        /* status set */
1659 +        status = 1;
1660 +
1661 +        /* error code save REQUEST SENSE */
1662 +        request_sense_data_set(0x06, 0x28, 0x00, 0x00);
1663 +
1664 +        /* media change flag off */
1665 +        MediaChange = MEDIA_CHANGE_OFF;
1666 +    }
1667 +    else{
1668 +        unsigned long   last_lba, block_len;
1669 +
1670 +        /* 0 clear */
1671 +        memset(&data, 0x00, sizeof(data));
1672 +
1673 +        /* data set */
1674 +        last_lba  = (DeviceSize / DeviceBlockSize) - 1;
1675 +        block_len = DeviceBlockSize;
1676 +        last_lba  = htonl(last_lba);
1677 +        block_len = htonl(block_len);
1678 +
1679 +        memcpy(data.LastLogicalBlockAddress, &last_lba, sizeof(last_lba));
1680 +        memcpy(data.BlockLengthInBytes, &block_len, sizeof(block_len));
1681 +
1682 +        /* data length set */
1683 +        data_len = sizeof(data);
1684 +
1685 +        /* status set */
1686 +        status = 0;
1687 +    }
1688 +
1689 +    /*
1690 +     * data transport
1691 +     */
1692 +
1693 +    if(cbw->dCBWDataTransferLength < data_len){
1694 +        data_len = cbw->dCBWDataTransferLength;
1695 +    }
1696 +
1697 +    storage_urb_send(device, &data, data_len);
1698 +
1699 +    /*
1700 +     * status transport
1701 +     */
1702 +
1703 +    memset(&csw, 0x00, sizeof(csw));
1704 +
1705 +    csw.dCSWSignature   = CSW_SIGNATURE;
1706 +    csw.dCSWTag         = cbw->dCBWTag;
1707 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1708 +    csw.bCSWStatus      = status;
1709 +
1710 +    storage_urb_send(device, &csw, sizeof(csw));
1711 +
1712 +    return;
1713 +}
1714 +
1715 +static void scsi_request_sense_analysis(struct usb_device_instance* device,
1716 +                                        COMMAND_BLOCK_WRAPPER* cbw)
1717 +{
1718 +    COMMAND_STATUS_WRAPPER  csw;
1719 +    unsigned long           data_len;
1720 +
1721 +    /*
1722 +     * data transport
1723 +     */
1724 +
1725 +    data_len = sizeof(RequestSenseData);
1726 +    if(cbw->dCBWDataTransferLength < data_len){
1727 +        data_len = cbw->dCBWDataTransferLength;
1728 +    }
1729 +
1730 +    storage_urb_send(device, &RequestSenseData, data_len);
1731 +
1732 +    /*
1733 +     * status transport
1734 +     */
1735 +
1736 +    memset(&csw, 0x00, sizeof(csw));
1737 +
1738 +    csw.dCSWSignature   = CSW_SIGNATURE;
1739 +    csw.dCSWTag         = cbw->dCBWTag;
1740 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1741 +    csw.bCSWStatus      = 0;
1742 +
1743 +    storage_urb_send(device, &csw, sizeof(csw));
1744 +
1745 +    return;
1746 +}
1747 +
1748 +static void scsi_read_10_analysis(struct usb_device_instance* device,
1749 +                                  COMMAND_BLOCK_WRAPPER* cbw)
1750 +{
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;
1756 +
1757 +    memcpy(&lba, command->LogicalBlockAddress, sizeof(lba));
1758 +    memcpy(&len, command->TransferLength, sizeof(len));
1759 +    lba    = ntohl(lba);
1760 +    len    = ntohs(len);
1761 +    offset = lba * DeviceBlockSize;
1762 +    size   = cbw->dCBWDataTransferLength;
1763 +
1764 +    if(DeviceFile == NULL){
1765 +        /* command fail */
1766 +        status = 1;
1767 +
1768 +        /* error code save REQUEST SENSE */
1769 +        request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1770 +
1771 +        /*
1772 +         * data transport
1773 +         */
1774 +
1775 +        storage_urb_send(device, NULL, size);
1776 +    }
1777 +    else
1778 +    if(MediaChange == MEDIA_CHANGE_ON){
1779 +        /* command fail */
1780 +        status = 1;
1781 +
1782 +        /* error code save REQUEST SENSE */
1783 +        request_sense_data_set(0x06, 0x28, 0x00, 0x00);
1784 +
1785 +        /* media change flag off */
1786 +        MediaChange = MEDIA_CHANGE_OFF;
1787 +
1788 +        /*
1789 +         * data transport
1790 +         */
1791 +
1792 +        storage_urb_send(device, NULL, size);
1793 +    }
1794 +    else{
1795 +        unsigned long   count, read_size;
1796 +
1797 +        /*
1798 +         * data transport
1799 +         */
1800 +
1801 +        /* device seek */
1802 +        DeviceFile->f_op->llseek(DeviceFile, offset, 0);
1803 +
1804 +        /* device read */
1805 +        for(count = size; count; count -= read_size){
1806 +            read_size = (count > sizeof(BlockBuffer)) ?
1807 +                            sizeof(BlockBuffer) : count;
1808 +            if(DeviceFile &&
1809 +               DeviceFile->f_op->read(DeviceFile, BlockBuffer, read_size,
1810 +                                      &DeviceFile->f_pos) != read_size){
1811 +
1812 +                /* command fail */
1813 +                status = 1;
1814 +
1815 +                /* error code save REQUEST SENSE */
1816 +                request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1817 +
1818 +                /* statistics update */
1819 +                StatDevReadError++;
1820 +                printk(KERN_INFO "storage_fd: device read error. length '%ld'.\n", read_size);
1821 +            }
1822 +
1823 +            storage_urb_send(device, BlockBuffer, read_size);
1824 +        }
1825 +    }
1826 +
1827 +    /*
1828 +     * status transport
1829 +     */
1830 +
1831 +    memset(&csw, 0x00, sizeof(csw));
1832 +
1833 +    csw.dCSWSignature   = CSW_SIGNATURE;
1834 +    csw.dCSWTag         = cbw->dCBWTag;
1835 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - size;
1836 +    csw.bCSWStatus      = status;
1837 +
1838 +    storage_urb_send(device, &csw, sizeof(csw));
1839 +
1840 +    return;
1841 +}
1842 +
1843 +static void scsi_mode_sense_analysis(struct usb_device_instance* device,
1844 +                                     COMMAND_BLOCK_WRAPPER* cbw)
1845 +{
1846 +    static READ_WRITE_ERROR_RECOVERY_PAGE           page_01 = {
1847 +        PageCode:0x01,
1848 +        PageLength:0x0A,
1849 +        ReadRetryCount:0x03,
1850 +        WriteRetryCount:0x80,
1851 +    };
1852 +    static FLEXIBLE_DISK_PAGE                       page_05 = {
1853 +        PageCode:0x05,
1854 +        PageLength:0x1E,
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},
1863 +    };
1864 +    static REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE page_1b = {
1865 +        PageCode:0x1B,
1866 +        PageLength:0x0A,
1867 +        TLUN:0x01,
1868 +    };
1869 +    static TIMER_AND_PROTECT_PAGE                   page_1c = {
1870 +        PageCode:0x1c,
1871 +        PageLength:0x06,
1872 +        InactivityTimeMultiplier:0x0A,
1873 +    };
1874 +
1875 +
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;
1882 +
1883 +    /*
1884 +     * data transport
1885 +     */
1886 +
1887 +    memset(&data, 0x00, sizeof(data));
1888 +
1889 +    /* set write protect */
1890 +    data.ModeParameterHeader.WP = DeviceWrProtect;
1891 +
1892 +    /* set Flexible Disk Page */
1893 +    if(DeviceFile == NULL){
1894 +        sector   = (unsigned short)DeviceBlockSize;
1895 +        cylinder = 0;
1896 +        sector   = htons(sector);
1897 +        cylinder = htons(cylinder);
1898 +
1899 +        page_05.NumberofHeads      = 0;
1900 +        page_05.SectorsperTrack    = 0;
1901 +        memcpy(page_05.DataBytesperSector, &sector, sizeof(sector));
1902 +        memcpy(page_05.NumberofCylinders, &cylinder, sizeof(cylinder));
1903 +    }
1904 +    else{
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);
1910 +
1911 +        page_05.NumberofHeads      = DEF_NUMBER_OF_HEADS;
1912 +        page_05.SectorsperTrack    = DEF_SECTORS_PER_TRACK;
1913 +        memcpy(page_05.DataBytesperSector, &sector, sizeof(sector));
1914 +        memcpy(page_05.NumberofCylinders, &cylinder, sizeof(cylinder));
1915 +    }
1916 +
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));
1921 +    }
1922 +    else
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));
1927 +    }
1928 +    else
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));
1933 +    }
1934 +    else
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));
1939 +    }
1940 +    else
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));
1952 +    }
1953 +    else{
1954 +        /* command fail */
1955 +        status = 1;
1956 +        data_len = cbw->dCBWDataTransferLength;
1957 +
1958 +        /* error code save REQUEST SENSE */
1959 +        request_sense_data_set(0x05, 0x24, 0x00, 0x00);
1960 +    }
1961 +
1962 +    if(cbw->dCBWDataTransferLength < data_len){
1963 +        data_len = cbw->dCBWDataTransferLength;
1964 +    }
1965 +
1966 +    storage_urb_send(device, &data, data_len);
1967 +
1968 +    /*
1969 +     * status transport
1970 +     */
1971 +
1972 +    memset(&csw, 0x00, sizeof(csw));
1973 +
1974 +    csw.dCSWSignature   = CSW_SIGNATURE;
1975 +    csw.dCSWTag         = cbw->dCBWTag;
1976 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength - data_len;
1977 +    csw.bCSWStatus      = status;
1978 +
1979 +    storage_urb_send(device, &csw, sizeof(csw));
1980 +
1981 +    return;
1982 +}
1983 +
1984 +static void scsi_test_unit_ready_analysis(struct usb_device_instance* device,
1985 +                                          COMMAND_BLOCK_WRAPPER* cbw)
1986 +{
1987 +    COMMAND_STATUS_WRAPPER      csw;
1988 +    unsigned char               status = 0;
1989 +
1990 +    if(DeviceFile == NULL){
1991 +        /* command fail */
1992 +        status = 1;
1993 +
1994 +        /* error code save REQUEST SENSE */
1995 +        request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
1996 +    }
1997 +    else
1998 +    if(MediaChange == MEDIA_CHANGE_ON){
1999 +        /* command fail */
2000 +        status = 1;
2001 +
2002 +        /* error code save REQUEST SENSE */
2003 +        request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2004 +
2005 +        /* media change flag off */
2006 +        MediaChange = MEDIA_CHANGE_OFF;
2007 +    }
2008 +
2009 +    /*
2010 +     * status transport
2011 +     */
2012 +
2013 +    memset(&csw, 0x00, sizeof(csw));
2014 +
2015 +    csw.dCSWSignature   = CSW_SIGNATURE;
2016 +    csw.dCSWTag         = cbw->dCBWTag;
2017 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2018 +    csw.bCSWStatus      = status;
2019 +
2020 +    storage_urb_send(device, &csw, sizeof(csw));
2021 +
2022 +    return;
2023 +}
2024 +
2025 +static void scsi_prevent_allow_medium_removal_analysis(struct usb_device_instance* device,
2026 +                                                       COMMAND_BLOCK_WRAPPER* cbw)
2027 +{
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;
2031 +
2032 +    if(command->Prevent){
2033 +        /* command fail */
2034 +        status = 1;
2035 +
2036 +        /* error code save REQUEST SENSE */
2037 +        request_sense_data_set(0x05, 0x24, 0x00, 0x00);
2038 +    }
2039 +
2040 +    /*
2041 +     * status transport
2042 +     */
2043 +
2044 +    memset(&csw, 0x00, sizeof(csw));
2045 +
2046 +    csw.dCSWSignature   = CSW_SIGNATURE;
2047 +    csw.dCSWTag         = cbw->dCBWTag;
2048 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2049 +    csw.bCSWStatus      = status;
2050 +
2051 +    storage_urb_send(device, &csw, sizeof(csw));
2052 +
2053 +    return;
2054 +}
2055 +
2056 +static void scsi_start_stop_analysis(struct usb_device_instance* device,
2057 +                                     COMMAND_BLOCK_WRAPPER* cbw)
2058 +{
2059 +    SCSI_START_STOP_COMMAND*    command = (SCSI_START_STOP_COMMAND*)cbw->CBWCB;
2060 +    COMMAND_STATUS_WRAPPER      csw;
2061 +    unsigned char               status = 0;
2062 +
2063 +    if(DeviceFile == NULL){
2064 +        /* command fail */
2065 +        status = 1;
2066 +
2067 +        /* error code save REQUEST SENSE */
2068 +        request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2069 +    }
2070 +    else
2071 +    if(MediaChange == MEDIA_CHANGE_ON){
2072 +        /* command fail */
2073 +        status = 1;
2074 +
2075 +        /* error code save REQUEST SENSE */
2076 +        request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2077 +
2078 +        /* media change flag off */
2079 +        MediaChange = MEDIA_CHANGE_OFF;
2080 +    }
2081 +    else
2082 +    if(command->Start && command->LoEj){
2083 +        /* command fail */
2084 +        status = 1;
2085 +
2086 +        /* error code save REQUEST SENSE */
2087 +        request_sense_data_set(0x05, 0x24, 0x00, 0x00);
2088 +    }
2089 +
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");
2096 +    }
2097 +
2098 +    /*
2099 +     * status transport
2100 +     */
2101 +
2102 +    memset(&csw, 0x00, sizeof(csw));
2103 +
2104 +    csw.dCSWSignature   = CSW_SIGNATURE;
2105 +    csw.dCSWTag         = cbw->dCBWTag;
2106 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2107 +    csw.bCSWStatus      = status;
2108 +
2109 +    storage_urb_send(device, &csw, sizeof(csw));
2110 +
2111 +    return;
2112 +}
2113 +
2114 +static void scsi_write_10_analysis(struct usb_device_instance* device,
2115 +                                   COMMAND_BLOCK_WRAPPER* cbw)
2116 +{
2117 +    /* status set */
2118 +    BulkOutLength = 0;
2119 +    StorageStatus = STORAGE_BULKOUT;
2120 +
2121 +    /* timer set */
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);
2127 +
2128 +    return;
2129 +}
2130 +
2131 +static void scsi_verify_analysis(struct usb_device_instance* device,
2132 +                                 COMMAND_BLOCK_WRAPPER* cbw)
2133 +{
2134 +    COMMAND_STATUS_WRAPPER      csw;
2135 +    unsigned char               status = 0;
2136 +
2137 +    if(DeviceFile == NULL){
2138 +        /* command fail */
2139 +        status = 1;
2140 +
2141 +        /* error code save REQUEST SENSE */
2142 +        request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2143 +    }
2144 +    else
2145 +    if(MediaChange == MEDIA_CHANGE_ON){
2146 +        /* command fail */
2147 +        status = 1;
2148 +
2149 +        /* error code save REQUEST SENSE */
2150 +        request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2151 +
2152 +        /* media change flag off */
2153 +        MediaChange = MEDIA_CHANGE_OFF;
2154 +    }
2155 +
2156 +    /*
2157 +     * status transport
2158 +     */
2159 +
2160 +    memset(&csw, 0x00, sizeof(csw));
2161 +
2162 +    csw.dCSWSignature   = CSW_SIGNATURE;
2163 +    csw.dCSWTag         = cbw->dCBWTag;
2164 +    csw.dCSWDataResidue = cbw->dCBWDataTransferLength;
2165 +    csw.bCSWStatus      = status;
2166 +
2167 +    storage_urb_send(device, &csw, sizeof(csw));
2168 +
2169 +    return;
2170 +}
2171 +
2172 +static void scsi_unsupport_analysis(struct usb_device_instance* device,
2173 +                                    COMMAND_BLOCK_WRAPPER* cbw)
2174 +{
2175 +    COMMAND_STATUS_WRAPPER csw;
2176 +    unsigned char          data_len = 0;
2177 +
2178 +    if(((cbw->bmCBWFlags & 0x80) == 0x00) && (cbw->dCBWDataTransferLength)){
2179 +        /* BLKOUT */
2180 +
2181 +        /* status set */
2182 +        BulkOutLength = 0;
2183 +        StorageStatus = STORAGE_BULKOUT;
2184 +    }
2185 +    else{
2186 +        /* BLKIN */
2187 +
2188 +        if(cbw->dCBWDataTransferLength){
2189 +            data_len = cbw->dCBWDataTransferLength;
2190 +            storage_urb_send(device, NULL, data_len);
2191 +        }
2192 +
2193 +        /*
2194 +         * status transport
2195 +         */
2196 +
2197 +        memset(&csw, 0x00, sizeof(csw));
2198 +
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));
2204 +
2205 +    }
2206 +
2207 +    /* error code save REQUEST SENSE */
2208 +    request_sense_data_set(0x05, 0x20, 0x00, 0x00);
2209 +
2210 +    return;
2211 +}
2212 +
2213 +static void scsi_bulkout_write_10_analysis(struct usb_device_instance* device,
2214 +                                           void* buffer, int length)
2215 +{
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;
2220 +
2221 +    buff_offset = BulkOutLength % sizeof(BlockBuffer);
2222 +
2223 +    memcpy(BlockBuffer + buff_offset, buffer, length);
2224 +    BulkOutLength += length;
2225 +
2226 +    buff_used_len = BulkOutLength % sizeof(BlockBuffer);
2227 +    if(buff_used_len == 0) buff_used_len = sizeof(BlockBuffer);
2228 +
2229 +    /* delete timer */
2230 +    if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2231 +        del_timer(&BulkOutTim);
2232 +    }
2233 +
2234 +    if(buff_used_len >= sizeof(BlockBuffer) ||
2235 +       BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2236 +
2237 +        /* buffer full */
2238 +        SCSI_WRITE_10_COMMAND*  command = (SCSI_WRITE_10_COMMAND*)&KeepCBW.CBWCB;
2239 +        unsigned short          len;
2240 +        unsigned long           lba, offset;
2241 +
2242 +        memcpy(&lba, command->LogicalBlockAddress, sizeof(lba));
2243 +        memcpy(&len, command->TransferLength, sizeof(len));
2244 +        lba = ntohl(lba);
2245 +        len = ntohs(len);
2246 +
2247 +        offset = (lba * DeviceBlockSize) +
2248 +                 (sizeof(BlockBuffer) * ((BulkOutLength - 1) / sizeof(BlockBuffer)));
2249 +
2250 +        /* device check */
2251 +        if(DeviceFile &&
2252 +           MediaChange != MEDIA_CHANGE_ON &&
2253 +           DeviceWrProtect != WR_PROTECT_ON){
2254 +
2255 +            /* write before jiffies get */
2256 +            s_tick = jiffies;
2257 +
2258 +            /* device seek */
2259 +            DeviceFile->f_op->llseek(DeviceFile, offset, 0);
2260 +
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);
2267 +            }
2268 +
2269 +            /* write after jiffies get */
2270 +            e_tick = jiffies;
2271 +
2272 +            /* statistics update */
2273 +            wr_tick = e_tick - s_tick;
2274 +            if(wr_tick > StatMaxWriteTime){
2275 +                StatMaxWriteTime = wr_tick;
2276 +            }
2277 +        }
2278 +    }
2279 +
2280 +    if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2281 +        if(DeviceFile == NULL){
2282 +            /* command fail */
2283 +            status = 1;
2284 +
2285 +            /* error code save REQUEST SENSE */
2286 +            request_sense_data_set(0x02, 0x3a, 0x00, 0x00);
2287 +        }
2288 +        else
2289 +        if(MediaChange == MEDIA_CHANGE_ON){
2290 +            /* command fail */
2291 +            status = 1;
2292 +
2293 +            /* error code save REQUEST SENSE */
2294 +            request_sense_data_set(0x06, 0x28, 0x00, 0x00);
2295 +
2296 +            /* media change flag off */
2297 +            MediaChange = MEDIA_CHANGE_OFF;
2298 +        }
2299 +        else
2300 +        if(DeviceWrProtect == WR_PROTECT_ON){
2301 +            /* command fail */
2302 +            status = 1;
2303 +
2304 +            /* error code save REQUEST SENSE */
2305 +            request_sense_data_set(0x07, 0x27, 0x00, 0x00);
2306 +
2307 +            /* media change flag off */
2308 +            MediaChange = MEDIA_CHANGE_OFF;
2309 +        }
2310 +
2311 +        /*
2312 +         * status transport
2313 +         */
2314 +
2315 +        memset(&csw, 0x00, sizeof(csw));
2316 +
2317 +        csw.dCSWSignature   = CSW_SIGNATURE;
2318 +        csw.dCSWTag         = KeepCBW.dCBWTag;
2319 +        csw.dCSWDataResidue = KeepCBW.dCBWDataTransferLength - BulkOutLength;
2320 +        csw.bCSWStatus      = status;
2321 +
2322 +        storage_urb_send(device, &csw, sizeof(csw));
2323 +
2324 +        /* status reset */
2325 +        BulkOutLength = 0;
2326 +        StorageStatus = STORAGE_IDLE;
2327 +
2328 +        /* flush before jiffies get */
2329 +        s_tick = jiffies;
2330 +
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");
2337 +        }
2338 +
2339 +        /* flush after jiffies get */
2340 +        e_tick = jiffies;
2341 +
2342 +        /* statistics update */
2343 +        wr_tick = e_tick - s_tick;
2344 +        if(wr_tick > StatMaxWriteTime){
2345 +            StatMaxWriteTime = wr_tick;
2346 +        }
2347 +
2348 +    }
2349 +
2350 +    return;
2351 +}
2352 +
2353 +static void scsi_bulkout_unsupport_analysis(struct usb_device_instance* device,
2354 +                                            void* buffer, int length)
2355 +{
2356 +    COMMAND_STATUS_WRAPPER  csw;
2357 +
2358 +    BulkOutLength += length;
2359 +
2360 +    if(BulkOutLength >= KeepCBW.dCBWDataTransferLength){
2361 +        /*
2362 +         * status transport
2363 +         */
2364 +
2365 +        memset(&csw, 0x00, sizeof(csw));
2366 +
2367 +        csw.dCSWSignature   = CSW_SIGNATURE;
2368 +        csw.dCSWTag         = KeepCBW.dCBWTag;
2369 +        csw.dCSWDataResidue = KeepCBW.dCBWDataTransferLength - BulkOutLength;
2370 +        csw.bCSWStatus      = 1;
2371 +
2372 +        storage_urb_send(device, &csw, sizeof(csw));
2373 +
2374 +        /* error code save REQUEST SENSE */
2375 +        request_sense_data_set(0x05, 0x20, 0x00, 0x00);
2376 +
2377 +        /* status reset */
2378 +        BulkOutLength = 0;
2379 +        StorageStatus = STORAGE_IDLE;
2380 +    }
2381 +
2382 +    return;
2383 +}
2384 +
2385 +/******************************************************************************
2386 +** Global Function
2387 +******************************************************************************/
2388 +
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}
2409 +};
2410 +
2411 +static SCSI_BULKOUT_ANALYSIS_TBL    ScsiBlkOutAnalysisTbl[] = {
2412 +    {SCSI_WRITE_10,                     "SCSI_WRITE_10",                     scsi_bulkout_write_10_analysis},
2413 +};
2414 +
2415 +void storageproto_urb_analysis(struct urb* urb)
2416 +{
2417 +    COMMAND_BLOCK_WRAPPER*  cbw = (COMMAND_BLOCK_WRAPPER*)urb->buffer;
2418 +    int                     i;
2419 +
2420 +    /* status BLKOUT check */
2421 +    if(StorageStatus == STORAGE_BULKOUT){
2422 +        for(i = 0;
2423 +            i < sizeof(ScsiBlkOutAnalysisTbl) / sizeof(SCSI_ANALYSIS_TBL);
2424 +            i++){
2425 +            if(ScsiBlkOutAnalysisTbl[i].scsi_command == KeepCBW.CBWCB[0]){
2426 +                if(ScsiBlkOutAnalysisTbl[i].bulkout_func){
2427 +                    ScsiBlkOutAnalysisTbl[i].bulkout_func(urb->device,
2428 +                                                          urb->buffer,
2429 +                                                          urb->actual_length);
2430 +                    goto RETURN_LABEL;
2431 +                }
2432 +                break;
2433 +            }
2434 +        }
2435 +        scsi_bulkout_unsupport_analysis(urb->device, urb->buffer, urb->actual_length);
2436 +        goto RETURN_LABEL;
2437 +    }
2438 +
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;
2444 +    }
2445 +
2446 +    /* statistics set */
2447 +    if(cbw->dCBWDataTransferLength){
2448 +        if(((cbw->bmCBWFlags & 0x80) == 0x00) && (cbw->dCBWDataTransferLength)){
2449 +            /* BULK OUT */
2450 +            if(StatMaxBulkOutSize < cbw->dCBWDataTransferLength){
2451 +                StatMaxBulkOutSize = cbw->dCBWDataTransferLength;
2452 +            }
2453 +        }
2454 +        else{
2455 +            /* BULK IN */
2456 +            if(StatMaxBulkInSize < cbw->dCBWDataTransferLength){
2457 +                StatMaxBulkInSize = cbw->dCBWDataTransferLength;
2458 +            }
2459 +        }
2460 +    }
2461 +
2462 +    /* save CBW and set storage status */
2463 +    memcpy(&KeepCBW, cbw, sizeof(KeepCBW));
2464 +
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;
2471 +            }
2472 +            break;
2473 +        }
2474 +    }
2475 +
2476 +    scsi_unsupport_analysis(urb->device, cbw);
2477 +    printk(KERN_INFO "storage_fd: SCSI command error. '0x%02x'.\n",
2478 +        cbw->CBWCB[0]);
2479 +    goto RETURN_LABEL;
2480 +
2481 +RETURN_LABEL:
2482 +
2483 +    /* URB free */
2484 +    usbd_recycle_urb(urb);
2485 +
2486 +    return;
2487 +}
2488 +
2489 +int storageproto_device_open_check(void)
2490 +{
2491 +    struct file*    file;
2492 +    struct inode*   inode;
2493 +    kdev_t          dev;
2494 +    int             read_org;
2495 +
2496 +    /* device already open check */
2497 +    if(DeviceFile){
2498 +        storageproto_device_close();
2499 +    }
2500 +
2501 +    /* device open */
2502 +    file = filp_open(storage_device, O_RDWR, 0000);
2503 +    if(IS_ERR(file)){
2504 +        file = filp_open(storage_device, O_RDONLY, 0000);
2505 +        if(IS_ERR(file)){
2506 +            storageproto_device_close();
2507 +            return MEDIA_EJECT;
2508 +        }
2509 +        DeviceWrProtect = WR_PROTECT_ON;
2510 +    }
2511 +
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;
2518 +    }
2519 +
2520 +    /* struct file pointer save */
2521 +    DeviceFile = file;
2522 +
2523 +    /* device information */
2524 +    inode = file->f_dentry->d_inode;
2525 +    dev = inode->i_rdev;
2526 +
2527 +    if (blk_size[MAJOR(dev)]){
2528 +        DeviceSize = blk_size[MAJOR(dev)][MINOR(dev)] << BLOCK_SIZE_BITS;
2529 +    }
2530 +    else{
2531 +        DeviceSize = INT_MAX << BLOCK_SIZE_BITS;
2532 +    }
2533 +
2534 +    if(blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)]){
2535 +        DeviceBlockSize = DEVICE_BLOCK_SIZE;
2536 +    }
2537 +    else{
2538 +        DeviceBlockSize = DEVICE_BLOCK_SIZE;
2539 +    }
2540 +
2541 +    return MEDIA_INSERT;
2542 +}
2543 +
2544 +void storageproto_device_close(void)
2545 +{
2546 +    if(DeviceFile){
2547 +        filp_close(DeviceFile, NULL);
2548 +        DeviceFile      = NULL;
2549 +        DeviceSize      = 0;
2550 +        DeviceBlockSize = DEVICE_BLOCK_SIZE;
2551 +        DeviceWrProtect = WR_PROTECT_OFF;
2552 +    }
2553 +
2554 +    return;
2555 +}
2556 +
2557 +void storageproto_usb_status_check(int status)
2558 +{
2559 +    static int  Is1stCheck = 1;
2560 +
2561 +    /* USB status check */
2562 +    if(Is1stCheck){
2563 +        Is1stCheck = 0;
2564 +    }
2565 +    else{
2566 +        if(UsbStatus == status) goto RETURN_LABEL;
2567 +    }
2568 +
2569 +    /* set status */
2570 +    UsbStatus = status;
2571 +
2572 +    switch(UsbStatus){
2573 +    case USB_CONNECT:
2574 +        /* media status check */
2575 +        storageproto_media_status_check(CONTEXT_SCHEDULE);
2576 +
2577 +        switch(MediaStatus){
2578 +        case MEDIA_EJECT:
2579 +            break;
2580 +
2581 +        case MEDIA_INSERT:
2582 +            hotplug("usbdstorage", storage_device, "umount");
2583 +            break;
2584 +
2585 +        default:
2586 +            break;
2587 +        }
2588 +        hotplug("usbdstorage", storage_device, "connect");
2589 +        break;
2590 +
2591 +    case USB_DISCONNECT:
2592 +        /* device close */
2593 +        storageproto_device_close();
2594 +
2595 +        switch(MediaStatus){
2596 +        case MEDIA_EJECT:
2597 +            break;
2598 +
2599 +        case MEDIA_INSERT:
2600 +            hotplug("usbdstorage", storage_device, "mount");
2601 +            break;
2602 +
2603 +        default:
2604 +            break;
2605 +        }
2606 +        hotplug("usbdstorage", storage_device, "disconnect");
2607 +        break;
2608 +
2609 +    default:
2610 +        break;
2611 +    }
2612 +
2613 +RETURN_LABEL:
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);
2617 +
2618 +    return;
2619 +}
2620 +
2621 +void storageproto_media_status_check(int call_context)
2622 +{
2623 +    static unsigned long    RetryCount = 0;
2624 +    int status;
2625 +
2626 +    /* media open check */
2627 +    status = storageproto_device_open_check();
2628 +
2629 +    /* media status check retry */
2630 +    if(status == MEDIA_EJECT){
2631 +        switch(call_context){
2632 +        case CONTEXT_STORAGE:
2633 +
2634 +            /* retry counter init */
2635 +            RetryCount = 0;
2636 +
2637 +            /* timer set */
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);
2643 +
2644 +            break;
2645 +
2646 +        case CONTEXT_TIMER:
2647 +
2648 +            /* retry counter update */
2649 +            RetryCount++;
2650 +
2651 +            /* retry counter check */
2652 +            if(RetryCount >= MEDIA_CHECK_RETRY) break;
2653 +
2654 +            /* timer set */
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);
2660 +
2661 +            break;
2662 +
2663 +        default:
2664 +            break;
2665 +        }
2666 +    }
2667 +    else
2668 +    if(status == MEDIA_INSERT){
2669 +        /* delete timer */
2670 +        del_timer(&MediaCheckTim);
2671 +    }
2672 +
2673 +    /* media status check */
2674 +    if(status == MediaStatus){
2675 +        if(UsbStatus == USB_DISCONNECT){
2676 +            storageproto_device_close();
2677 +        }
2678 +        if(MediaStatus == MEDIA_INSERT){
2679 +            if(call_context == CONTEXT_STORAGE || call_context == CONTEXT_TIMER){
2680 +                MediaChange = MEDIA_CHANGE_ON;
2681 +            }
2682 +        }
2683 +        goto RETURN_LABEL;
2684 +    }
2685 +
2686 +    /* set status */
2687 +    MediaStatus = status;
2688 +
2689 +    switch(MediaStatus){
2690 +    case MEDIA_INSERT:
2691 +        /* set status */
2692 +        MediaChange = MEDIA_CHANGE_ON;
2693 +
2694 +        switch(UsbStatus){
2695 +        case USB_DISCONNECT:
2696 +            storageproto_device_close();
2697 +            break;
2698 +
2699 +        case USB_CONNECT:
2700 +            break;
2701 +
2702 +        default:
2703 +            break;
2704 +        }
2705 +        hotplug("usbdstorage", storage_device, "insert");
2706 +        break;
2707 +
2708 +    case MEDIA_EJECT:
2709 +        switch(UsbStatus){
2710 +        case USB_DISCONNECT:
2711 +            storageproto_device_close();
2712 +            break;
2713 +
2714 +        case USB_CONNECT:
2715 +            break;
2716 +
2717 +        default:
2718 +            break;
2719 +        }
2720 +        hotplug("usbdstorage", storage_device, "eject");
2721 +        break;
2722 +
2723 +    default:
2724 +        break;
2725 +    }
2726 +
2727 +RETURN_LABEL:
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");
2733 +
2734 +    return;
2735 +}
2736 +
2737 +void storageproto_usb_reset_ind(void)
2738 +{
2739 +    /* status reset */
2740 +    BulkOutLength = 0;
2741 +    StorageStatus = STORAGE_IDLE;
2742 +
2743 +    DBG_STORAGE_FD(KERN_INFO "storage_fd: storage protocol reset.\n");
2744 +
2745 +    return;
2746 +}
2747 +
2748 +void storageproto_init(void)
2749 +{
2750 +    /* timer init */
2751 +    init_timer(&BulkOutTim);
2752 +
2753 +    /* timer init */
2754 +    init_timer(&MediaCheckTim);
2755 +
2756 +    return;
2757 +}
2758 +
2759 +void storageproto_exit(void)
2760 +{
2761 +    /* device close */
2762 +    storageproto_device_close();
2763 +
2764 +    /* delete timer */
2765 +    del_timer(&BulkOutTim);
2766 +
2767 +    /* delete timer */
2768 +    del_timer(&MediaCheckTim);
2769 +
2770 +    return;
2771 +}
2772 +
2773 +ssize_t storageproto_proc_read(struct file* file, char* buf, size_t count,
2774 +                               loff_t* pos)
2775 +{
2776 +    char    string[1024];
2777 +    int     len = 0;
2778 +
2779 +    len += sprintf(string + len, "Protocol status:%s\n",
2780 +            (StorageStatus == STORAGE_IDLE)   ? "STORAGE_IDLE" :
2781 +            (StorageStatus == STORAGE_BULKIN) ? "STORAGE_BULKIN" :
2782 +                                                "STORAGE_BULKOUT");
2783 +
2784 +    len += sprintf(string + len, "USB status:%s\n",
2785 +            (UsbStatus == USB_DISCONNECT) ? "USB_DISCONNECT" :
2786 +                                            "USB_CONNECT");
2787 +
2788 +    len += sprintf(string + len, "Media status:%s\n",
2789 +            (MediaStatus == MEDIA_EJECT) ? "MEDIA_EJECT" :
2790 +                                           "MEDIA_INSERT");
2791 +
2792 +    len += sprintf(string + len, "Media chage:%s\n",
2793 +            (MediaChange == MEDIA_CHANGE_OFF) ? "MEDIA_CHANGE_OFF" :
2794 +                                                "MEDIA_CHANGE_ON");
2795 +
2796 +    len += sprintf(string + len, "Device name:%s\n",
2797 +            storage_device);
2798 +
2799 +    len += sprintf(string + len, "Device file descriptor:0x%p\n",
2800 +            DeviceFile);
2801 +
2802 +    len += sprintf(string + len, "Device size:0x%d\n",
2803 +            DeviceSize);
2804 +
2805 +    len += sprintf(string + len, "Device block size:0x%d\n",
2806 +            DeviceBlockSize);
2807 +
2808 +    len += sprintf(string + len, "Device write protect:%s\n",
2809 +            (DeviceWrProtect == WR_PROTECT_OFF) ? "WR_PROTECT_OFF":
2810 +                                                  "WR_PROTECT_ON");
2811 +
2812 +    len += sprintf(string + len, "Bulk in max size:%ld\n",
2813 +            StatMaxBulkInSize);
2814 +
2815 +    len += sprintf(string + len, "Bulk out max size:%ld\n",
2816 +            StatMaxBulkOutSize);
2817 +
2818 +    len += sprintf(string + len, "device write error:%ld\n",
2819 +            StatDevWriteError);
2820 +
2821 +    len += sprintf(string + len, "device read error:%ld\n",
2822 +            StatDevReadError);
2823 +
2824 +    len += sprintf(string + len, "device flush error:%ld\n",
2825 +            StatDevFlushError);
2826 +
2827 +    len += sprintf(string + len, "write data bulk out timout:%ld\n",
2828 +            StatWriteTimout);
2829 +
2830 +    len += sprintf(string + len, "device write max time:%ld msec\n",
2831 +            (StatMaxWriteTime * 1000) / HZ);
2832 +
2833 +    *pos += len;
2834 +    if(len > count){
2835 +        len = -EINVAL;
2836 +    }
2837 +    else
2838 +    if(len > 0 && copy_to_user(buf, string, len)) {
2839 +        len = -EFAULT;
2840 +    }
2841 +
2842 +    return len;
2843 +}
2844 +
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
2848 @@ -0,0 +1,585 @@
2849 +/*
2850 + * linux/drivers/usb/device/storage_fd/storageproto.h - mass storage protocol library header
2851 + *
2852 + * Copyright (c) 2003 Lineo Solutions, Inc.
2853 + *
2854 + * Written by Shunnosuke kabata
2855 + *
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.
2860 + *
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.
2865 + *
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.
2869 + *
2870 + */
2871 +
2872 +#ifndef _STORAGEPROTO_H_
2873 +#define _STORAGEPROTO_H_
2874 +
2875 +/******************************************************************************
2876 +** Macro Define
2877 +******************************************************************************/
2878 +
2879 +/**************************************
2880 +** Class Code
2881 +**************************************/
2882 +
2883 +/*
2884 + * Class
2885 + */
2886 +
2887 +#define MASS_STORAGE_CLASS                  0x08
2888 +
2889 +/*
2890 + * SubClass
2891 + */
2892 +
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
2899 +
2900 +/*
2901 + * Protocol
2902 + */
2903 +
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
2907 +
2908 +/**************************************
2909 +** SCSI Command
2910 +**************************************/
2911 +
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
2931 +
2932 +/**************************************
2933 +** SCSI Command Parameter
2934 +**************************************/
2935 +
2936 +#define CBW_SIGNATURE           0x43425355  /* USBC */
2937 +#define CSW_SIGNATURE           0x53425355  /* USBS */
2938 +
2939 +#define PRODUCT_REVISION_LEVEL  "1.00"
2940 +
2941 +/**************************************
2942 +** Status
2943 +**************************************/
2944 +
2945 +#define WR_PROTECT_OFF      0
2946 +#define WR_PROTECT_ON       1
2947 +
2948 +#define STORAGE_IDLE        0
2949 +#define STORAGE_BULKIN      1
2950 +#define STORAGE_BULKOUT     2
2951 +
2952 +#define USB_DISCONNECT      0
2953 +#define USB_CONNECT         1
2954 +
2955 +#define MEDIA_EJECT         0
2956 +#define MEDIA_INSERT        1
2957 +
2958 +#define MEDIA_CHANGE_OFF    0
2959 +#define MEDIA_CHANGE_ON     1
2960 +
2961 +/**************************************
2962 +** Mass Storage Thread Name
2963 +**************************************/
2964 +
2965 +#define STORAGE_THREAD_NAME "usbdstorage"
2966 +
2967 +/**************************************
2968 +** Media Signal Delay Time(ms)
2969 +**************************************/
2970 +
2971 +#define USB_EVENT_DELAY_TIM 1000
2972 +
2973 +/**************************************
2974 +** Write Bulk Out Check Time(ms)
2975 +**************************************/
2976 +
2977 +#define WR_BULKOUT_CHK_TIM  1000
2978 +
2979 +/**************************************
2980 +** Media Check Time(ms)
2981 +**************************************/
2982 +
2983 +#define MEDIA_CHECK_TIM     3000
2984 +#define MEDIA_CHECK_RETRY   3
2985 +
2986 +/**************************************
2987 +** Context
2988 +**************************************/
2989 +
2990 +#define CONTEXT_SCHEDULE    0
2991 +#define CONTEXT_STORAGE     1
2992 +#define CONTEXT_TIMER       2
2993 +
2994 +/**************************************
2995 +** Debug Message
2996 +**************************************/
2997 +#if 0
2998 +#define DBG_STORAGE_FD(fmt, args...)    printk(fmt, ##args)
2999 +#else
3000 +#define DBG_STORAGE_FD(fmt, args...)
3001 +#endif
3002 +
3003 +/******************************************************************************
3004 +** Structure Define
3005 +******************************************************************************/
3006 +
3007 +/**************************************
3008 +** Command Block Wrapper / Command Status Wrapper
3009 +**************************************/
3010 +
3011 +/*
3012 + * Command Block Wrapper
3013 + */
3014 +typedef struct{
3015 +    unsigned long   dCBWSignature;
3016 +    unsigned long   dCBWTag;
3017 +    unsigned long   dCBWDataTransferLength;
3018 +    unsigned char   bmCBWFlags;
3019 +    unsigned char   bCBWLUN:4,
3020 +                    Reserved:4;
3021 +    unsigned char   bCBWCBLength:5,
3022 +                    Reserved2:3;
3023 +    unsigned char   CBWCB[16];
3024 +} __attribute__((packed)) COMMAND_BLOCK_WRAPPER;
3025 +
3026 +/*
3027 + * Command Status Wrapper
3028 + */
3029 +typedef struct{
3030 +    unsigned long   dCSWSignature;
3031 +    unsigned long   dCSWTag;
3032 +    unsigned long   dCSWDataResidue;
3033 +    unsigned char   bCSWStatus;
3034 +} __attribute__((packed)) COMMAND_STATUS_WRAPPER;
3035 +
3036 +/**************************************
3037 +** SCSI Command
3038 +**************************************/
3039 +
3040 +/*
3041 + * INQUIRY
3042 + */
3043 +
3044 +typedef struct{
3045 +    unsigned char   OperationCode;
3046 +    unsigned char   EVPD:1,
3047 +                    Reserved1:4,
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;
3060 +
3061 +typedef struct{
3062 +    unsigned char   PeripheralDeviceType:5,
3063 +                    Reserved1:3;
3064 +    unsigned char   Reserved2:7,
3065 +                    RMB:1;
3066 +    unsigned char   ANSIVersion:3,
3067 +                    ECMAVersion:3,
3068 +                    ISOVersion:2;
3069 +    unsigned char   ResponseDataFormat:4,
3070 +                    Reserved3: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;
3079 +
3080 +/*
3081 + * READ FORMAT CAPACITY
3082 + */
3083 +
3084 +typedef struct{
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;
3098 +
3099 +typedef struct{
3100 +    struct{
3101 +        unsigned char   Reserved1;
3102 +        unsigned char   Reserved2;
3103 +        unsigned char   Reserved3;
3104 +        unsigned char   CapacityListLength;
3105 +    } __attribute__((packed)) CapacityListHeader;
3106 +    struct{
3107 +        unsigned char   NumberofBlocks[4];
3108 +        unsigned char   DescriptorCode:2,
3109 +                        Reserved1:6;
3110 +        unsigned char   BlockLength[3];
3111 +    } __attribute__((packed)) CurrentMaximumCapacityDescriptor;
3112 +} __attribute__((packed)) SCSI_READ_FORMAT_CAPACITY_DATA;
3113 +
3114 +/*
3115 + * READ FORMAT CAPACITY
3116 + */
3117 +
3118 +typedef struct{
3119 +    unsigned char   OperationCode;
3120 +    unsigned char   RelAdr:1,
3121 +                    Reserved1:4,
3122 +                    LogicalUnitNumber:3;
3123 +    unsigned char   LogicalBlockAddress[4];
3124 +    unsigned char   Reserved2;
3125 +    unsigned char   Reserved3;
3126 +    unsigned char   PMI:1,
3127 +                    Reserved4:7;
3128 +    unsigned char   Reserved5;
3129 +    unsigned char   Reserved6;
3130 +    unsigned char   Reserved7;
3131 +} __attribute__((packed)) SCSI_READ_CAPACITY_COMMAND;
3132 +
3133 +typedef struct{
3134 +    unsigned char   LastLogicalBlockAddress[4];
3135 +    unsigned char   BlockLengthInBytes[4];
3136 +} __attribute__((packed)) SCSI_READ_CAPACITY_DATA;
3137 +
3138 +/*
3139 + * REQUEST SENSE
3140 + */
3141 +
3142 +typedef struct{
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;
3157 +
3158 +typedef struct{
3159 +    unsigned char   ErrorCode:7,
3160 +                    Valid:1;
3161 +    unsigned char   Reserved1;
3162 +    unsigned char   SenseKey:4,
3163 +                    Reserved2: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;
3172 +
3173 +/*
3174 + * READ(10)
3175 + */
3176 +
3177 +typedef struct{
3178 +    unsigned char   OperationCode;
3179 +    unsigned char   RelAdr:1,
3180 +                    Reserved1:2,
3181 +                    FUA:1,
3182 +                    DPO: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;
3191 +
3192 +/*
3193 + * MODE SENSE
3194 + */
3195 +
3196 +typedef struct{
3197 +    unsigned char   OperationCode;
3198 +    unsigned char   Reserved1:3,
3199 +                    DBD:1,
3200 +                    Reserved2:1,
3201 +                    LogicalUnitNumber:3;
3202 +    unsigned char   PageCode:6,
3203 +                    PC:2;
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;
3213 +
3214 +typedef struct{
3215 +    unsigned char   ModeDataLength;
3216 +    unsigned char   MediumTypeCode;
3217 +    unsigned char   Reserved1:4,
3218 +                    DPOFUA:1,
3219 +                    Reserved2:2,
3220 +                    WP:1;
3221 +    unsigned char   Reserved3;
3222 +} __attribute__((packed)) MODE_PARAMETER_HEADER;
3223 +
3224 +typedef struct{
3225 +    unsigned char   PageCode:6,
3226 +                    Reserved1:1,
3227 +                    PS:1;
3228 +    unsigned char   PageLength;
3229 +    unsigned char   DCR:1,
3230 +                    Reserved2:1,
3231 +                    PER:1,
3232 +                    Reserved3:1,
3233 +                    RC:1,
3234 +                    Reserved4:1,
3235 +                    Reserved5:1,
3236 +                    AWRE: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;
3242 +
3243 +typedef struct{
3244 +    unsigned char   PageCode:6,
3245 +                    Reserved1:1,
3246 +                    PS:1;
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;
3261 +
3262 +typedef struct{
3263 +    unsigned char   PageCode:6,
3264 +                    Reserved1:1,
3265 +                    PS:1;
3266 +    unsigned char   PageLength;
3267 +    unsigned char   Reserved2:6,
3268 +                    SRFP:1,
3269 +                    SFLP:1;
3270 +    unsigned char   TLUN:3,
3271 +                    Reserved3:3,
3272 +                    SML:1,
3273 +                    NCD:1;
3274 +    unsigned char   Reserved4[8];
3275 +} __attribute__((packed)) REMOVABLE_BLOCK_ACCESS_CAPABILITIES_PAGE;
3276 +
3277 +typedef struct{
3278 +    unsigned char   PageCode:6,
3279 +                    Reserved1:1,
3280 +                    PS:1;
3281 +    unsigned char   PageLength;
3282 +    unsigned char   Reserved2;
3283 +    unsigned char   InactivityTimeMultiplier:4,
3284 +                    Reserved3:4;
3285 +    unsigned char   SWPP:1,
3286 +                    DISP:1,
3287 +                    Reserved4:6;
3288 +    unsigned char   Reserved5;
3289 +    unsigned char   Reserved6;
3290 +    unsigned char   Reserved7;
3291 +} __attribute__((packed)) TIMER_AND_PROTECT_PAGE;
3292 +
3293 +typedef struct{
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;
3299 +
3300 +typedef struct{
3301 +    MODE_PARAMETER_HEADER   ModeParameterHeader;
3302 +    union{
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;
3310 +
3311 +/*
3312 + * TEST UNIT READY
3313 + */
3314 +
3315 +typedef struct{
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;
3330 +
3331 +/*
3332 + * PREVENT-ALLOW MEDIUM REMOVAL
3333 + */
3334 +
3335 +typedef struct{
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,
3342 +                    Reserved4:7;
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;
3351 +
3352 +/*
3353 + * START-STOP UNIT
3354 + */
3355 +
3356 +typedef struct{
3357 +    unsigned char   OperationCode;
3358 +    unsigned char   IMMED:1,
3359 +                    Reserved1:4,
3360 +                    LogicalUnitNumber:3;
3361 +    unsigned char   Reserved2;
3362 +    unsigned char   Reserved3;
3363 +    unsigned char   Start:1,
3364 +                    LoEj:1,
3365 +                    Reserved4:6;
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;
3374 +
3375 +/*
3376 + * WRITE(10)
3377 + */
3378 +
3379 +typedef struct{
3380 +    unsigned char   OperationCode;
3381 +    unsigned char   RelAdr:1,
3382 +                    Reserved1:2,
3383 +                    FUA:1,
3384 +                    DPO: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;
3393 +
3394 +/*
3395 + * VERIFY
3396 + */
3397 +
3398 +typedef struct{
3399 +    unsigned char   OperationCode;
3400 +    unsigned char   RelAdr:1,
3401 +                    ByteChk:1,
3402 +                    Reserved1:1,
3403 +                    Reserved2:1,
3404 +                    DPO: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;
3413 +
3414 +/******************************************************************************
3415 +** Global Function Prototype
3416 +******************************************************************************/
3417 +
3418 +/* storage-fd.c */
3419 +void    storage_urb_send(struct usb_device_instance*, void*, int);
3420 +
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);
3431 +
3432 +#endif  /* _STORAGEPROTO_H_ */
3433 +