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