usb-bug-fixes.patch (applied cleanly)
[pintos-anon] / src / devices / usb_storage.c
1 /**
2  * USB mass storage driver - just like the one Elvis used!
3  */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <kernel/list.h>
9 #include <endian.h>
10 #include <debug.h>
11 #include "threads/malloc.h"
12 #include "threads/palloc.h"
13 #include "threads/thread.h"
14 #include "devices/timer.h"
15 #include "threads/synch.h"
16 #include "threads/pte.h"
17 #include "devices/usb.h"
18 #include "devices/block.h"
19 #include "devices/partition.h"
20 #include "devices/usb_storage.h"
21
22 //http://www.usb.org/developers/defined_class
23 #define USB_CLASS_MASS_STORAGE  0x08
24
25 #define USB_SUBCLASS_RBC        0x01    /* reduced block commands */
26 #define USB_SUBCLASS_ATAPI      0x02    /* ATAPI - CD's */
27 #define USB_SUBCLASS_TAPE       0x03    
28 #define USB_SUBCLASS_UFI        0x04    /* floppy disk */
29 #define USB_SUBCLASS_SFF8070    0x05    
30 #define USB_SUBCLASS_SCSI       0x06    /* scsi transparent command set */
31
32 #define USB_PROTO_COMPLETE      0x00
33 #define USB_PROTO_NO_COMPLETE   0x01
34 #define USB_PROTO_BULK          0x50
35
36 #pragma pack(1)
37
38 #define CBW_SIG_MAGIC   0x43425355
39
40 #define CBW_FL_IN               (1 << 7)
41 #define CBW_FL_OUT              0
42
43 /** usbmassbulk_10.pdf - pg 13 */
44 /* command block wrapper */
45 struct msc_cbw
46 {
47   uint32_t sig;
48   uint32_t tag;
49   uint32_t tx_len;
50   uint8_t flags;
51   uint8_t lun;
52   uint8_t cb_len;               /* command block length */
53   uint8_t cb[16];               /* command block */
54 };
55
56 #define CSW_SIG_MAGIC           0x53425355
57 #define CSW_STATUS_PASSED       0
58 #define CSW_STATUS_FAILED       1
59 #define CSW_STATUS_PHASE        2       /* phase error */
60 /* command status wrapper */
61 struct msc_csw
62 {
63   uint32_t sig;
64   uint32_t tag;
65   uint32_t residue;
66   uint8_t status;
67 };
68
69 struct scsi_cdb6
70 {
71   uint8_t op;
72   uint8_t lba[3];
73   uint8_t len;
74   uint8_t control;
75 };
76
77 struct scsi_cdb10
78 {
79   uint8_t op;
80   uint8_t action;
81   uint32_t lba;
82   uint8_t resv;
83   uint16_t len;
84   uint8_t control;
85 };
86
87 struct scsi_cdb12
88 {
89   uint8_t op;
90   uint8_t action;
91   uint32_t lba;
92   uint32_t len;
93   uint8_t resv;
94   uint8_t control;
95 };
96
97 struct scsi_cdb16
98 {
99   uint8_t op;
100   uint8_t action;
101   uint32_t lba;
102   uint32_t data;
103   uint32_t len;
104   uint8_t resv;
105   uint8_t control;
106 };
107
108 struct scsi_capacity10
109 {
110   uint32_t blocks;
111   uint32_t block_len;
112 };
113
114 #define SCSI_OP_WRITE6                  0xa
115 #define SCSI_OP_READ6                   0x8
116 #define SCSI_OP_TEST_READY              0x00
117 #define SCSI_OP_SEEK8                   0x0b
118 #define SCSI_OP_MODE_SENSE8             0x1a
119 #define SCSI_OP_MODE_SELECT8            0x15
120 #define SCSI_OP_READ_CAPACITY10         0x25
121 #define SCSI_OP_READ_CAPACITY16         0x9e
122 #define SCSI_OP_WRITE10                 0x2a
123 #define SCSI_OP_READ10                  0x28
124 #define SCSI_OP_SEEK10                  0x2b
125 #define SCSI_OP_MODE_SENSE10            0x5a
126 #define SCSI_OP_MODE_SELECT10           0x55
127
128
129 #pragma pack()
130
131 static void *msc_attached (struct usb_iface *);
132 static void msc_detached (class_info);
133
134 static void msc_reset_endpoint (struct usb_endpoint *eop);
135
136 static struct usb_class storage_class = {
137   .attached = msc_attached,
138   .detached = msc_detached,
139   .name = "Mass Storage",
140   .class_id = USB_CLASS_MASS_STORAGE
141 };
142
143 #define mci_lock(x)             lock_acquire(&(x)->lock)
144 #define mci_unlock(x)           lock_release(&(x)->lock)
145
146 struct msc_class_info
147 {
148   int refs;
149   struct lock lock;
150   struct usb_iface *ui;
151   int blk_size;
152   int blk_count;
153   bool retrying;
154   uint32_t tag;
155   void *bounce_buffer;
156
157   struct usb_endpoint *eop_in;
158   struct usb_endpoint *eop_out;
159   struct list_elem peers;
160 };
161 static void msc_get_geometry (struct msc_class_info *);
162 static void msc_io (struct msc_class_info *, block_sector_t, void *buf, bool wr);
163 static void msc_reset_recovery(struct msc_class_info* mci);
164 static void msc_bulk_reset(struct msc_class_info* mci);
165
166 struct msc_blk_info
167 {
168   struct msc_class_info *mci;
169 };
170
171 static struct list device_list;
172 static struct block_operations msc_operations;
173
174 void usb_storage_init (void);
175
176 void
177 usb_storage_init (void)
178 {
179   list_init (&device_list);
180   usb_register_class (&storage_class);
181 }
182
183
184 static class_info
185 msc_attached (struct usb_iface *ui)
186 {
187   static int dev_no;
188
189   struct msc_class_info *mci;
190   struct msc_blk_info *mbi;
191   struct list_elem *li;
192   struct block *block;
193   char name[16];
194
195   if (ui->subclass_id != USB_SUBCLASS_SCSI)
196     {
197       printf ("usb_storage: Only support SCSI-type devices\n");
198       return NULL;
199     }
200
201   mci = malloc (sizeof (struct msc_class_info));
202
203   mci->refs = 0;
204   mci->retrying = false;
205   lock_init (&mci->lock);
206   mci->ui = ui;
207   list_push_back (&device_list, &mci->peers);
208
209   /* grab endpoints */
210   li = list_begin (&ui->endpoints);
211   mci->eop_in = NULL;
212   mci->eop_out = NULL;
213   while (li != list_end (&ui->endpoints))
214     {
215       struct usb_endpoint *ue;
216
217       ue = list_entry (li, struct usb_endpoint, peers);
218       li = list_next (li);
219
220       if (ue->attr == USB_EOP_ATTR_BULK)
221         {
222           if (ue->direction == 0)
223             mci->eop_out = ue;
224           else
225             mci->eop_in = ue;
226         }
227     }
228
229   ASSERT (mci->eop_in != NULL && mci->eop_out != NULL);
230
231   msc_get_geometry (mci);
232
233   if (mci->blk_size != 512)
234     {
235       printf ("ignoring device with %d-byte sectors\n", mci->blk_size);
236       return NULL;
237     }
238
239   mci->bounce_buffer = palloc_get_multiple (PAL_ASSERT,
240                                             DIV_ROUND_UP (mci->blk_size,
241                                                           PGSIZE));
242   mbi = malloc (sizeof (struct msc_blk_info));
243   mbi->mci = mci;
244   snprintf (name, sizeof name, "ud%c", 'a' + dev_no++);
245   block = block_register (name, BLOCK_RAW, "USB", mci->blk_count,
246                           &msc_operations, mbi);
247   partition_scan (block);
248                           
249   return mci;
250 }
251
252 static void
253 msc_detached (class_info ci UNUSED)
254 {
255   PANIC ("msc_detached: STUB");
256 }
257
258 static void
259 msc_read (void *mbi_, block_sector_t sector, void *buffer) 
260 {
261   struct msc_blk_info *mbi = mbi_;
262
263   mci_lock (mbi->mci);
264   msc_io (mbi->mci, sector, buffer, false);
265   mci_unlock (mbi->mci);
266 }
267
268 static void
269 msc_write (void *mbi_, block_sector_t sector, const void *buffer)
270 {
271   struct msc_blk_info *mbi = mbi_;
272
273   mci_lock (mbi->mci);
274   msc_io (mbi->mci, sector, (void *) buffer, true);
275   mci_unlock (mbi->mci);
276 }
277
278 static struct block_operations msc_operations = 
279   {
280     msc_read,
281     msc_write,
282   };
283
284 static void
285 msc_get_geometry (struct msc_class_info *mci)
286 {
287   struct msc_cbw cbw;
288   struct scsi_capacity10 cap;
289   struct scsi_cdb10 *cdb;
290   struct msc_csw csw;
291   int tx;
292
293   memset (&cbw, 0, sizeof cbw);
294   cbw.sig = CBW_SIG_MAGIC;
295   cbw.tag = mci->tag++;
296   cbw.tx_len = sizeof (struct scsi_capacity10);
297   cbw.flags = CBW_FL_IN;
298   cbw.lun = 0;
299   cbw.cb_len = sizeof (struct scsi_cdb10);
300   cdb = (void *) (&cbw.cb);
301   cdb->op = SCSI_OP_READ_CAPACITY10;
302
303   usb_dev_bulk (mci->eop_out, &cbw, sizeof cbw, &tx);
304   if (tx != sizeof cbw)
305     PANIC ("send cbw");
306   usb_dev_bulk (mci->eop_in, &cap, sizeof cap, &tx);
307   if (tx != sizeof cap)
308     PANIC ("recv cap");
309   usb_dev_bulk (mci->eop_in, &csw, sizeof csw, &tx);
310   if (tx != sizeof csw)
311     PANIC ("recv csw");
312
313   mci->blk_count = be32_to_machine (cap.blocks) + 1;
314   mci->blk_size = be32_to_machine (cap.block_len);
315
316 #if 0
317   /* did CSW stall?  */
318   if (tx == sizeof (struct scsi_capacity10))
319     {
320       PANIC ("foo");
321       msc_reset_endpoint (mci->eop_in);
322       usb_dev_bulk (mci->eop_in, csw, sizeof (*csw), &tx);
323     }
324 #endif
325
326   ASSERT (csw.sig == CSW_SIG_MAGIC);
327
328   if (csw.status != CSW_STATUS_PASSED)
329     {
330       PANIC ("USB storage geometry read failure!\n");
331     }
332
333 }
334
335 static void
336 msc_io (struct msc_class_info *mci, block_sector_t bn, void *buf, bool wr)
337 {
338   struct msc_cbw cbw;
339   struct msc_csw csw;
340   struct scsi_cdb10 *cdb;
341   int tx;
342   int err;
343
344   if (wr)
345     memcpy (mci->bounce_buffer, buf, mci->blk_size);
346
347   memset (&cbw, 0, sizeof (cbw));
348   cbw.sig = CBW_SIG_MAGIC;
349   cbw.tag = mci->tag++;
350   cbw.tx_len = mci->blk_size;
351   cbw.flags = (wr) ? CBW_FL_OUT : CBW_FL_IN;
352   cbw.lun = 0;
353   cbw.cb_len = sizeof (struct scsi_cdb10);
354
355   cdb = (void *) (&cbw.cb);
356   cdb->op = (wr) ? SCSI_OP_WRITE10 : SCSI_OP_READ10;
357   *((uint32_t *) ((uint8_t *) (&cdb->lba) + 1)) = machine_to_be24 (bn);
358   cdb->len = machine_to_be16 (1);
359
360 //  msc_reset_endpoint (mci->eop_in);
361 //  msc_reset_endpoint (mci->eop_out);
362
363   /* set it up */
364   err = usb_dev_bulk (mci->eop_out, &cbw, sizeof (cbw), &tx);
365   if (err != 0)
366     {
367       msc_reset_endpoint (mci->eop_out);
368       err = usb_dev_bulk (mci->eop_out, &cbw, sizeof (cbw), &tx);
369     }
370
371   /* do storage io */
372   err = usb_dev_bulk ((wr) ? mci->eop_out : mci->eop_in,
373                       mci->bounce_buffer, mci->blk_size, &tx);
374   memset (&csw, 0, sizeof (csw));
375   ASSERT (tx == mci->blk_size);
376
377
378   /* get command status */
379   err = usb_dev_bulk (mci->eop_in, &csw, sizeof (csw), &tx);
380   if (err != 0)
381     {
382       msc_reset_endpoint (mci->eop_in);
383       msc_reset_endpoint (mci->eop_out);
384       err = usb_dev_bulk (mci->eop_in, &csw, sizeof (csw), &tx);
385       if (err != 0)
386         PANIC ("msc_io: error %d\n", err);
387     }
388
389   if (csw.sig != CSW_SIG_MAGIC)
390     {
391       if (mci->retrying == true)
392         PANIC ("usb_msd: CSW still missing. Bail out\n");
393       printf ("usb_msd: no command status, resetting. Buggy device?\n");
394       msc_reset_recovery(mci);
395       printf ("reset complete\n");
396       mci->retrying = true;
397       msc_io (mci, bn, buf, wr);
398       return;
399     }
400   mci->retrying = false;
401
402   if (csw.status != CSW_STATUS_PASSED)
403     {
404       PANIC ("USB storage IO failure! - error %d\n", csw.status);
405     }
406   if (!wr)
407     memcpy (buf, mci->bounce_buffer, mci->blk_size);
408 }
409
410 static void
411 msc_reset_endpoint (struct usb_endpoint *eop)
412 {
413   struct usb_setup_pkt sp;
414
415   printf ("*** reset endpoint\n");
416   sp.recipient = USB_SETUP_RECIP_ENDPT;
417   sp.type = USB_SETUP_TYPE_STD;
418   sp.direction = 0;
419   sp.request = REQ_STD_CLR_FEAT;
420   sp.value = 0;                 /* 0 is ENDPOINT_HALT */
421   sp.index = eop->eop;
422   sp.length = 0;
423   usb_dev_control (eop, &sp, NULL, NULL);
424 }
425
426 static void
427 msc_reset_recovery(struct msc_class_info* mci)
428 {
429   msc_bulk_reset (mci);
430   msc_reset_endpoint (mci->eop_in);
431   msc_reset_endpoint (mci->eop_out);
432 }
433
434 static void msc_bulk_reset(struct msc_class_info* mci)
435 {
436   struct usb_setup_pkt sp;
437
438   sp.recipient = USB_SETUP_RECIP_DEV;
439   sp.type = USB_SETUP_TYPE_CLASS;
440   sp.direction = 0;
441   sp.request = 0xff;
442   sp.value = 0;          
443   sp.index = mci->ui->iface_num;
444   sp.length = 0;
445   usb_dev_control (&mci->ui->dev->cfg_eop, &sp, NULL, NULL);
446 }