LibXenon
Bare-metal Xbox 360 homebrew library
Loading...
Searching...
No Matches
usbmass.c
Go to the documentation of this file.
1/* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * USB Mass-Storage driver File: usbmass.c
5 *
6 * This driver deals with mass-storage devices that support
7 * the SCSI Transparent command set and USB Bulk-Only protocol
8 *
9 * Author: Mitch Lichtenberg
10 *
11 *********************************************************************
12 *
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
15 *
16 * This software is furnished under license and may be used and
17 * copied only in accordance with the following terms and
18 * conditions. Subject to these conditions, you may download,
19 * copy, install, use, modify and distribute modified or unmodified
20 * copies of this software in source and/or binary form. No title
21 * or ownership is transferred hereby.
22 *
23 * 1) Any source code used, modified or distributed must reproduce
24 * and retain this copyright notice and list of conditions
25 * as they appear in the source file.
26 *
27 * 2) No right is granted to use any trade name, trademark, or
28 * logo of Broadcom Corporation. The "Broadcom Corporation"
29 * name may not be used to endorse or promote products derived
30 * from this software without the prior written permission of
31 * Broadcom Corporation.
32 *
33 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
34 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
35 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
37 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
38 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
39 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
40 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
41 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
42 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
43 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
44 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
45 * THE POSSIBILITY OF SUCH DAMAGE.
46 ********************************************************************* */
47
48#ifdef USB11_MASS_STORAGE
49
50#ifndef _CFE_
51#include <stdio.h>
52#include <time.h>
53#include <memory.h>
54#include <stdint.h>
55#include "usbhack.h"
56#include "lib_malloc.h"
57#include "lib_queue.h"
58#else
59#include "cfe.h"
60#endif
61
62#include "usbchap9.h"
63#include "usbd.h"
64
65/* *********************************************************************
66 * USB Mass-Storage class Constants
67 ********************************************************************* */
68
69#define USBMASS_CBI_PROTOCOL 0
70#define USBMASS_CBI_NOCOMPLETE_PROTOCOL 1
71#define USBMASS_BULKONLY_PROTOCOL 0x50
72
73#define USBMASS_SUBCLASS_RBC 0x01
74#define USBMASS_SUBCLASS_SFF8020 0x02
75#define USBMASS_SUBCLASS_QIC157 0x03
76#define USBMASS_SUBCLASS_UFI 0x04
77#define USBMASS_SUBCLASS_SFF8070 0x05
78#define USBMASS_SUBCLASS_SCSI 0x06
79
80#define USBMASS_CSW_PASS 0x00
81#define USBMASS_CSW_FAILED 0x01
82#define USBMASS_CSW_PHASEERR 0x02
83
84#define USBMASS_CBW_SIGNATURE 0x43425355
85#define USBMASS_CSW_SIGNATURE 0x53425355
86
87/* *********************************************************************
88 * USB Mass-Storage class Structures
89 ********************************************************************* */
90
91typedef struct usbmass_cbw_s {
92 uint8_t dCBWSignature0,dCBWSignature1,dCBWSignature2,dCBWSignature3;
93 uint8_t dCBWTag0,dCBWTag1,dCBWTag2,dCBWTag3;
94 uint8_t dCBWDataTransferLength0,dCBWDataTransferLength1,
95 dCBWDataTransferLength2,dCBWDataTransferLength3;
96 uint8_t bmCBWFlags;
97 uint8_t bCBWLUN;
98 uint8_t bCBWCBLength;
99 uint8_t CBWCB[16];
100} usbmass_cbw_t;
101
102typedef struct usbmass_csw_s {
103 uint8_t dCSWSignature0,dCSWSignature1,dCSWSignature2,dCSWSignature3;
104 uint8_t dCSWTag0,dCSWTag1,dCSWTag2,dCSWTag3;
105 uint8_t dCSWDataResidue0,dCSWDataResidue1,dCSWDataResidue2,dCSWDataResidue3;
106 uint8_t bCSWStatus;
107} usbmass_csw_t;
108
109#define GETCBWFIELD(s,f) ((uint32_t)((s)->f##0) | ((uint32_t)((s)->f##1) << 8) | \
110 ((uint32_t)((s)->f##2) << 16) | ((uint32_t)((s)->f##3) << 24))
111#define PUTCBWFIELD(s,f,v) (s)->f##0 = (v & 0xFF); \
112 (s)->f##1 = ((v)>>8 & 0xFF); \
113 (s)->f##2 = ((v)>>16 & 0xFF); \
114 (s)->f##3 = ((v)>>24 & 0xFF);
115
116
117int usbmass_request_sense(usbdev_t *dev);
118
119/* *********************************************************************
120 * Linkage to CFE
121 ********************************************************************* */
122
123/*
124 * Softc for the CFE side of the disk driver.
125 */
126#define MAX_SECTORSIZE 2048
127typedef struct usbdisk_s {
128 uint32_t usbdisk_sectorsize;
129 uint32_t usbdisk_ttlsect;
130 uint32_t usbdisk_devtype;
131 int usbdisk_unit;
132} usbdisk_t;
133
134
135
136/* *********************************************************************
137 * Forward Definitions
138 ********************************************************************* */
139
140static int usbmass_attach(usbdev_t *dev,usb_driver_t *drv);
141static int usbmass_detach(usbdev_t *dev);
142
143/* *********************************************************************
144 * Structures
145 ********************************************************************* */
146
147typedef struct usbmass_softc_s {
148 int umass_inpipe;
149 int umass_outpipe;
150 int umass_devtype;
151 uint32_t umass_curtag;
152 int umass_unit;
153 void *bdev;
154 usbdev_t *dev;
155} usbmass_softc_t;
156
157usb_driver_t usbmass_driver = {
158 "Mass-Storage Device",
159 usbmass_attach,
160 usbmass_detach
161};
162
163usbdev_t *usbmass_dev = NULL; /* XX hack for testing only */
164
165/* *********************************************************************
166 * usbmass_mass_storage_reset(dev,ifc)
167 *
168 * Do a bulk-only mass-storage reset.
169 *
170 * Input parameters:
171 * dev - device to reset
172 * ifc - interface number to reset (bInterfaceNum)
173 *
174 * Return value:
175 * status
176 ********************************************************************* */
177
178#define usbmass_mass_storage_reset(dev,ifc) \
179 usb_simple_request(dev,0x21,0xFF,ifc,0)
180
181#if 0
182/* *********************************************************************
183 * usbmass_get_max_lun(dev,lunp)
184 *
185 * Get maximum LUN from device
186 *
187 * Input parameters:
188 * dev - device to reset
189 * lunp - pointer to int to receive max lun
190 *
191 * Return value:
192 * status
193 ********************************************************************* */
194
195static int usbmass_get_max_lun(usbdev_t *dev,int *lunp)
196{
197 uint8_t buf = 0;
198 int res;
199
200 res = usb_std_request(dev,0xA1,0xFE,0,0,&buf,1);
201
202 if (res < 0) return res;
203
204 if (lunp) *lunp = (int) buf;
205 return 0;
206}
207
208#endif
209
210
211/* *********************************************************************
212 * usbmass_stall_recovery(dev)
213 *
214 * Do whatever it takes to unstick a stalled mass-storage device.
215 *
216 * Input parameters:
217 * dev - usb device
218 *
219 * Return value:
220 * nothing
221 ********************************************************************* */
222
223static void usbmass_stall_recovery(usbdev_t *dev)
224{
225 usbmass_softc_t *softc;
226
227 softc = (usbmass_softc_t *) dev->ud_private;
228
229 usb_clear_stall(dev,softc->umass_inpipe);
230
231 usbmass_request_sense(dev);
232}
233
234
235/* *********************************************************************
236 * usbmass_read_capacity(dev,sectornum,buffer)
237 *
238 * Reads a sector from the device.
239 *
240 * Input parameters:
241 * dev - usb device
242 * sectornum - sector number to read
243 * buffer - place to put sector we read
244 *
245 * Return value:
246 * status
247 ********************************************************************* */
248
249int usbmass_request_sense(usbdev_t *dev)
250{
251 uint8_t *cbwcsw;
252 uint8_t *sector;
253 usbmass_cbw_t *cbw;
254 usbmass_csw_t *csw;
255 usbmass_softc_t *softc;
256 int res;
257
258 softc = (usbmass_softc_t *) dev->ud_private;
259
260 cbwcsw = KMALLOC(64,32);
261 sector = KMALLOC(64,32);
262
263 memset(sector,0,64);
264
265 cbw = (usbmass_cbw_t *) cbwcsw;
266 csw = (usbmass_csw_t *) cbwcsw;
267
268 /*
269 * Fill in the fields of the CBW
270 */
271
272 PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
273 PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
274 PUTCBWFIELD(cbw,dCBWDataTransferLength,18);
275 cbw->bmCBWFlags = 0x80; /* IN */
276 cbw->bCBWLUN = 0;
277 cbw->bCBWCBLength = 12;
278 cbw->CBWCB[0] = 0x3; /* REQUEST SENSE */
279 cbw->CBWCB[1] = 0;
280 cbw->CBWCB[2] = 0;
281 cbw->CBWCB[3] = 0;
282 cbw->CBWCB[4] = 18; /* allocation length */
283 cbw->CBWCB[5] = 0;
284 cbw->CBWCB[6] = 0;
285 cbw->CBWCB[7] = 0;
286 cbw->CBWCB[8] = 0;
287 cbw->CBWCB[9] = 0;
288
289 softc->umass_curtag++;
290
291 /*
292 * Send the CBW
293 */
294
295 res = usb_make_sync_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
296 sizeof(usbmass_cbw_t),UR_FLAG_OUT);
297
298 /*
299 * Get the data
300 */
301
302 memset(sector,0,18);
303 res = usb_make_sync_request(dev,softc->umass_inpipe,sector,
305
306 /*
307 * Get the Status
308 */
309
310 memset(csw,0,sizeof(usbmass_csw_t));
311 res = usb_make_sync_request(dev,softc->umass_inpipe,(uint8_t *) csw,
312 sizeof(usbmass_csw_t),UR_FLAG_IN);
313
314 KFREE(cbwcsw);
315
316 KFREE(sector);
317
318 return 0;
319
320}
321
322/* *********************************************************************
323 * usbmass_read_sector(dev,sectornum,seccnt,buffer)
324 *
325 * Reads a sector from the device.
326 *
327 * Input parameters:
328 * dev - usb device
329 * sectornum - sector number to read
330 * seccnt - count of sectors to read
331 * buffer - place to put sector we read
332 *
333 * Return value:
334 * status
335 ********************************************************************* */
336
337int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
338 hsaddr_t buffer);
339int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
340 hsaddr_t buffer)
341{
342 usbreq_t *ur1;
343 usbreq_t *ur2;
344 usbreq_t *ur3;
345
346 uint8_t *sector;
347 usbmass_cbw_t *cbw;
348 usbmass_csw_t *csw;
349
350 usbmass_softc_t *softc;
351 int res;
352
353 softc = (usbmass_softc_t *) dev->ud_private;
354
355 sector = (uint8_t *) HSADDR2PTR(buffer); /* XXX not 64-bit compatible */
356
357 cbw = (usbmass_cbw_t *) KMALLOC(sizeof(usbmass_cbw_t),32);
358 csw = (usbmass_csw_t *) KMALLOC(sizeof(usbmass_csw_t),32);
359
360 /*
361 * Fill in the fields of the CBW
362 */
363
364 PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
365 PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
366 PUTCBWFIELD(cbw,dCBWDataTransferLength,(512*seccnt));
367 cbw->bmCBWFlags = 0x80; /* IN */
368 cbw->bCBWLUN = 0;
369 cbw->bCBWCBLength = 10;
370 cbw->CBWCB[0] = 0x28; /* READ */
371 cbw->CBWCB[1] = 0;
372 cbw->CBWCB[2] = (sectornum >> 24) & 0xFF; /* LUN 0 & MSB's of sector */
373 cbw->CBWCB[3] = (sectornum >> 16) & 0xFF;
374 cbw->CBWCB[4] = (sectornum >> 8) & 0xFF;
375 cbw->CBWCB[5] = (sectornum >> 0) & 0xFF;
376 cbw->CBWCB[6] = 0;
377 cbw->CBWCB[7] = 0;
378 cbw->CBWCB[8] = seccnt;
379 cbw->CBWCB[9] = 0;
380
381 softc->umass_curtag++;
382
383 /*
384 * Send the CBW
385 */
386
387 ur1 = usb_make_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
388 sizeof(usbmass_cbw_t),UR_FLAG_OUT);
389
391
392 /*
393 * Get the data
394 */
395
396 ur2 = usb_make_request(dev,softc->umass_inpipe,sector,
397 512*seccnt,UR_FLAG_IN | UR_FLAG_SHORTOK);
398
400
401 /*
402 * Get the Status
403 */
404
405 memset(csw,0,sizeof(usbmass_csw_t));
406 ur3 = usb_make_request(dev,softc->umass_inpipe,(uint8_t *) csw,
407 sizeof(usbmass_csw_t),UR_FLAG_IN);
408
410
411 res=usb_wait_request(ur1);
412 usb_free_request(ur1);
413 if (res == 4) {
414 usbmass_stall_recovery(dev);
415 KFREE(cbw);
416 KFREE(csw);
417 return -1;
418 }
419
420 res=usb_wait_request(ur2);
421 usb_free_request(ur2);
422 if (res == 4) {
423 usbmass_stall_recovery(dev);
424 KFREE(cbw);
425 KFREE(csw);
426 return -1;
427 }
428
429 res=usb_wait_request(ur3);
430 usb_free_request(ur3);
431 if (res == 4) {
432 usbmass_stall_recovery(dev);
433 KFREE(cbw);
434 KFREE(csw);
435 return -1;
436 }
437
438#if 0
439 printf("CSW: Signature=%08X Tag=%08X Residue=%08X Status=%02X\n",
440 GETCBWFIELD(csw,dCSWSignature),
441 GETCBWFIELD(csw,dCSWTag),
442 GETCBWFIELD(csw,dCSWDataResidue),
443 csw->bCSWStatus);
444#endif
445
446 res = (csw->bCSWStatus == USBMASS_CSW_PASS) ? 0 : -1;
447
448 KFREE(cbw);
449 KFREE(csw);
450
451 return res;
452
453}
454
455/* *********************************************************************
456 * usbmass_write_sector(dev,sectornum,seccnt,buffer)
457 *
458 * Writes a sector to the device
459 *
460 * Input parameters:
461 * dev - usb device
462 * sectornum - sector number to write
463 * seccnt - count of sectors to write
464 * buffer - place to get sector to write
465 *
466 * Return value:
467 * status
468 ********************************************************************* */
469
470static int usbmass_write_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
471 hsaddr_t buffer)
472{
473 uint8_t *cbwcsw;
474 uint8_t *sector;
475 usbmass_cbw_t *cbw;
476 usbmass_csw_t *csw;
477 usbmass_softc_t *softc;
478 int res;
479
480 softc = (usbmass_softc_t *) dev->ud_private;
481
482 cbwcsw = KMALLOC(64,32);
483 sector = (uint8_t *) HSADDR2PTR(buffer); /* XXX not 64-bit compatible */
484
485 cbw = (usbmass_cbw_t *) cbwcsw;
486 csw = (usbmass_csw_t *) cbwcsw;
487
488 /*
489 * Fill in the fields of the CBW
490 */
491
492 PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
493 PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
494 PUTCBWFIELD(cbw,dCBWDataTransferLength,(512*seccnt));
495 cbw->bmCBWFlags = 0x00; /* OUT */
496 cbw->bCBWLUN = 0;
497 cbw->bCBWCBLength = 10;
498 cbw->CBWCB[0] = 0x2A; /* WRITE */
499 cbw->CBWCB[1] = 0;
500 cbw->CBWCB[2] = (sectornum >> 24) & 0xFF; /* LUN 0 & MSB's of sector */
501 cbw->CBWCB[3] = (sectornum >> 16) & 0xFF;
502 cbw->CBWCB[4] = (sectornum >> 8) & 0xFF;
503 cbw->CBWCB[5] = (sectornum >> 0) & 0xFF;
504 cbw->CBWCB[6] = 0;
505 cbw->CBWCB[7] = 0;
506 cbw->CBWCB[8] = seccnt;
507 cbw->CBWCB[9] = 0;
508
509 softc->umass_curtag++;
510
511 /*
512 * Send the CBW
513 */
514
515 res = usb_make_sync_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
516 sizeof(usbmass_cbw_t),UR_FLAG_OUT);
517
518 /*
519 * Send the data
520 */
521
522 res = usb_make_sync_request(dev,softc->umass_outpipe,sector,
523 512*seccnt,UR_FLAG_OUT);
524
525 /*
526 * Get the Status
527 */
528
529 memset(csw,0,sizeof(usbmass_csw_t));
530 res = usb_make_sync_request(dev,softc->umass_inpipe,(uint8_t *) csw,
531 sizeof(usbmass_csw_t),UR_FLAG_IN);
532
533#if 0
534 printf("CSW: Signature=%08X Tag=%08X Residue=%08X Status=%02X\n",
535 GETCBWFIELD(csw,dCSWSignature),
536 GETCBWFIELD(csw,dCSWTag),
537 GETCBWFIELD(csw,dCSWDataResidue),
538 csw->bCSWStatus);
539#endif
540
541 res = (csw->bCSWStatus == USBMASS_CSW_PASS) ? 0 : -1;
542
543 KFREE(cbwcsw);
544
545 return res;
546}
547
548/* *********************************************************************
549 * usbmass_read_capacity(dev,sectornum,buffer)
550 *
551 * Reads a sector from the device.
552 *
553 * Input parameters:
554 * dev - usb device
555 * sectornum - sector number to read
556 * buffer - place to put sector we read
557 *
558 * Return value:
559 * status
560 ********************************************************************* */
561
562int usbmass_read_capacity(usbdev_t *dev,uint32_t *size);
563int usbmass_read_capacity(usbdev_t *dev,uint32_t *size)
564{
565 uint8_t *cbwcsw;
566 uint8_t *sector;
567 usbmass_cbw_t *cbw;
568 usbmass_csw_t *csw;
569 usbmass_softc_t *softc;
570 int res;
571
572 softc = (usbmass_softc_t *) dev->ud_private;
573
574 cbwcsw = KMALLOC(64,32);
575 sector = KMALLOC(64,32);
576
577 memset(sector,0,64);
578
579 cbw = (usbmass_cbw_t *) cbwcsw;
580 csw = (usbmass_csw_t *) cbwcsw;
581
582 *size = 0;
583
584 /*
585 * Fill in the fields of the CBW
586 */
587
588 PUTCBWFIELD(cbw,dCBWSignature,USBMASS_CBW_SIGNATURE);
589 PUTCBWFIELD(cbw,dCBWTag,softc->umass_curtag);
590 PUTCBWFIELD(cbw,dCBWDataTransferLength,8);
591 cbw->bmCBWFlags = 0x80; /* IN */
592 cbw->bCBWLUN = 0;
593 cbw->bCBWCBLength = 10;
594 cbw->CBWCB[0] = 0x25; /* READ CAPACITY */
595 cbw->CBWCB[1] = 0;
596 cbw->CBWCB[2] = 0;
597 cbw->CBWCB[3] = 0;
598 cbw->CBWCB[4] = 0;
599 cbw->CBWCB[5] = 0;
600 cbw->CBWCB[6] = 0;
601 cbw->CBWCB[7] = 0;
602 cbw->CBWCB[8] = 0;
603 cbw->CBWCB[9] = 0;
604
605 softc->umass_curtag++;
606
607 /*
608 * Send the CBW
609 */
610
611 res = usb_make_sync_request(dev,softc->umass_outpipe,(uint8_t *) cbw,
612 sizeof(usbmass_cbw_t),UR_FLAG_OUT);
613 if (res == 4) {
614 usbmass_stall_recovery(dev);
615 KFREE(cbwcsw);
616 KFREE(sector);
617 return -1;
618 }
619
620 /*
621 * Get the data
622 */
623
624 res = usb_make_sync_request(dev,softc->umass_inpipe,sector,
626 if (res == 4) {
627 usbmass_stall_recovery(dev);
628 KFREE(cbwcsw);
629 KFREE(sector);
630 return -1;
631 }
632
633 /*
634 * Get the Status
635 */
636
637 memset(csw,0,sizeof(usbmass_csw_t));
638 res = usb_make_sync_request(dev,softc->umass_inpipe,(uint8_t *) csw,
639 sizeof(usbmass_csw_t),UR_FLAG_IN);
640
641 KFREE(cbwcsw);
642
643 *size = (((uint32_t) sector[0]) << 24) |
644 (((uint32_t) sector[1]) << 16) |
645 (((uint32_t) sector[2]) << 8) |
646 (((uint32_t) sector[3]) << 0);
647
648 KFREE(sector);
649
650 return 0;
651
652}
653
654/* *********************************************************************
655 * usbmass_attach(dev,drv)
656 *
657 * This routine is called when the bus scan stuff finds a mass-storage
658 * device. We finish up the initialization by configuring the
659 * device and allocating our softc here.
660 *
661 * Input parameters:
662 * dev - usb device, in the "addressed" state.
663 * drv - the driver table entry that matched
664 *
665 * Return value:
666 * 0
667 ********************************************************************* */
668
669static int usbmass_attach(usbdev_t *dev,usb_driver_t *drv)
670{
671 usb_config_descr_t *cfgdscr = dev->ud_cfgdescr;
672 usb_endpoint_descr_t *epdscr;
673 usb_endpoint_descr_t *indscr = NULL;
674 usb_endpoint_descr_t *outdscr = NULL;
675 usb_interface_descr_t *ifdscr;
676 usbmass_softc_t *softc;
677 int idx;
678
679 dev->ud_drv = drv;
680
681 softc = KMALLOC(sizeof(usbmass_softc_t),0);
682 memset(softc,0,sizeof(usbmass_softc_t));
683 dev->ud_private = softc;
684
686 if (ifdscr == NULL) {
687 return -1;
688 }
689
690 if ((ifdscr->bInterfaceSubClass != USBMASS_SUBCLASS_SCSI) ||
691 (ifdscr->bInterfaceProtocol != USBMASS_BULKONLY_PROTOCOL)) {
692 console_log("USBMASS: Do not understand devices with SubClass 0x%02X, Protocol 0x%02X",
693 ifdscr->bInterfaceSubClass,
694 ifdscr->bInterfaceProtocol);
695 return -1;
696 }
697
698 for (idx = 0; idx < 2; idx++) {
700
702 outdscr = epdscr;
703 }
704 else {
705 indscr = epdscr;
706 }
707 }
708
709
710 if (!indscr || !outdscr) {
711 /*
712 * Could not get descriptors, something is very wrong.
713 * Leave device addressed but not configured.
714 */
715 return -1;
716 }
717
718 /*
719 * Choose the standard configuration.
720 */
721
723
724 /*
725 * Open the pipes.
726 */
727
728 softc->umass_inpipe = usb_open_pipe(dev,indscr);
729 softc->umass_outpipe = usb_open_pipe(dev,outdscr);
730 softc->umass_curtag = 0x12345678;
731 softc->dev = dev;
732
733 /*
734 * Save pointer in global unit table so we can
735 * match CFE devices up with USB ones
736 */
737
738 static int num = 0;
739 char name[10];
740 sprintf(name, "ud%c", 'a' + num); num++; num %= 26;
741 //softc->bdev = register_bdev(softc, &usbmass_ops, name);
742
743 usbmass_dev = dev;
744
745 return 0;
746}
747
748/* *********************************************************************
749 * usbmass_detach(dev)
750 *
751 * This routine is called when the bus scanner notices that
752 * this device has been removed from the system. We should
753 * do any cleanup that is required. The pending requests
754 * will be cancelled automagically.
755 *
756 * Input parameters:
757 * dev - usb device
758 *
759 * Return value:
760 * 0
761 ********************************************************************* */
762
763static int usbmass_detach(usbdev_t *dev)
764{
765 usbmass_softc_t *softc;
766 softc = (usbmass_softc_t *) dev->ud_private;
767
768 //unregister_bdev(softc->bdev);
769
770 KFREE(softc);
771 return 0;
772}
773
774
775#if 0
776
777/* *********************************************************************
778 * usbdisk_sectorshift(size)
779 *
780 * Given a sector size, return log2(size). We cheat; this is
781 * only needed for 2048 and 512-byte sectors.
782 * Explicitly using shifts and masks in sector number calculations
783 * helps on 32-bit-only platforms, since we probably won't need
784 * a helper library.
785 *
786 * Input parameters:
787 * size - sector size
788 *
789 * Return value:
790 * # of bits to shift
791 ********************************************************************* */
792
793#define usbdisk_sectorshift(size) (((size)==2048)?11:9)
794
795
796/* *********************************************************************
797 * usbdisk_probe(drv,probe_a,probe_b,probe_ptr)
798 *
799 * Our probe routine. Attach an empty USB disk device to the firmware.
800 *
801 * Input parameters:
802 * drv - driver structure
803 * probe_a - not used
804 * probe_b - not used
805 * probe_ptr - not used
806 *
807 * Return value:
808 * nothing
809 ********************************************************************* */
810
811static void usbdisk_probe(cfe_driver_t *drv,
812 unsigned long probe_a, unsigned long probe_b,
813 void *probe_ptr)
814{
815 usbdisk_t *softc;
816 char descr[128];
817
818 softc = (usbdisk_t *) KMALLOC(sizeof(usbdisk_t),0);
819
820 memset(softc,0,sizeof(usbdisk_t));
821
822 softc->usbdisk_sectorsize = 512;
823 softc->usbdisk_devtype = BLOCK_DEVTYPE_DISK;
824 softc->usbdisk_ttlsect = 0; /* not calculated yet */
825 softc->usbdisk_unit = (int)probe_a;
826
827 xsprintf(descr,"USB Disk unit %d",(int)probe_a);
828
829 cfe_attach(drv,softc,NULL,descr);
830}
831
832
833/* *********************************************************************
834 * usbdisk_open(ctx)
835 *
836 * Process the CFE OPEN call for this device. For IDE disks,
837 * the device is reset and identified, and the geometry is
838 * determined.
839 *
840 * Input parameters:
841 * ctx - device context
842 *
843 * Return value:
844 * 0 if ok, else error code
845 ********************************************************************* */
846
847
848static int usbdisk_open(cfe_devctx_t *ctx)
849{
850 usbdisk_t *softc = ctx->dev_softc;
851 usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
853 int res;
854
855 if (!dev) return CFE_ERR_NOTREADY;
856
857 usbmass_request_sense(dev);
858
859 res = usbmass_read_capacity(dev,&size);
860 if (res < 0) return res;
861
862 softc->usbdisk_ttlsect = size;
863
864 return 0;
865}
866
867/* *********************************************************************
868 * usbdisk_read(ctx,buffer)
869 *
870 * Process a CFE READ command for the IDE device. This is
871 * more complex than it looks, since CFE offsets are byte offsets
872 * and we may need to read partial sectors.
873 *
874 * Input parameters:
875 * ctx - device context
876 * buffer - buffer descriptor
877 *
878 * Return value:
879 * number of bytes read, or <0 if an error occured
880 ********************************************************************* */
881
882static int usbdisk_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
883{
884 usbdisk_t *softc = ctx->dev_softc;
885 usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
886 hsaddr_t bptr;
887 int blen;
888 int numsec;
889 int res = 0;
890 int amtcopy;
892 uint64_t offset;
893 unsigned char sector[MAX_SECTORSIZE];
894 int sectorshift;
895
896 if (!dev) return CFE_ERR_NOTREADY;
897
898 sectorshift = usbdisk_sectorshift(softc->usbdisk_sectorsize);
899
900 bptr = buffer->buf_ptr;
901 blen = buffer->buf_length;
902 offset = buffer->buf_offset;
903 numsec = (blen + softc->usbdisk_sectorsize - 1) >> sectorshift;
904
905 if (offset & (softc->usbdisk_sectorsize-1)) {
906 lba = (offset >> sectorshift);
907 res = usbmass_read_sector(dev,lba,1,PTR2HSADDR(sector));
908 if (res < 0) goto out;
909 amtcopy = softc->usbdisk_sectorsize - (offset & (softc->usbdisk_sectorsize-1));
910 if (amtcopy > blen) amtcopy = blen;
911 hs_memcpy_to_hs(bptr,&sector[offset & (softc->usbdisk_sectorsize-1)],amtcopy);
912 bptr += amtcopy;
913 offset += amtcopy;
914 blen -= amtcopy;
915 }
916
917 if (blen >= softc->usbdisk_sectorsize) {
918 int seccnt;
919
920 lba = (offset >> sectorshift);
921 seccnt = (blen >> sectorshift);
922
923 res = usbmass_read_sector(dev,lba,seccnt,bptr);
924 if (res < 0) goto out;
925
926 amtcopy = seccnt << sectorshift;
927 bptr += amtcopy;
928 offset += amtcopy;
929 blen -= amtcopy;
930 }
931
932 if (blen) {
933 lba = (offset >> sectorshift);
934 res = usbmass_read_sector(dev,lba,1,PTR2HSADDR(sector));
935 if (res < 0) goto out;
936 amtcopy = blen;
937 hs_memcpy_to_hs(bptr,sector,amtcopy);
938 bptr += amtcopy;
939 offset += amtcopy;
940 blen -= amtcopy;
941 }
942
943out:
944 buffer->buf_retlen = bptr - buffer->buf_ptr;
945
946 return res;
947}
948
949/* *********************************************************************
950 * usbdisk_inpstat(ctx,inpstat)
951 *
952 * Test input status for the IDE disk. Disks are always ready
953 * to read.
954 *
955 * Input parameters:
956 * ctx - device context
957 * inpstat - input status structure
958 *
959 * Return value:
960 * 0
961 ********************************************************************* */
962
963static int usbdisk_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
964{
965 /* usbdisk_t *softc = ctx->dev_softc; */
966
967 inpstat->inp_status = 1;
968 return 0;
969}
970
971/* *********************************************************************
972 * usbdisk_write(ctx,buffer)
973 *
974 * Process a CFE WRITE command for the IDE device. If the write
975 * involves partial sectors, the affected sectors are read first
976 * and the changes are merged in.
977 *
978 * Input parameters:
979 * ctx - device context
980 * buffer - buffer descriptor
981 *
982 * Return value:
983 * number of bytes write, or <0 if an error occured
984 ********************************************************************* */
985
986static int usbdisk_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
987{
988 usbdisk_t *softc = ctx->dev_softc;
989 usbdev_t *dev = usbdisk_units[softc->usbdisk_unit];
990 hsaddr_t bptr;
991 int blen;
992 int numsec;
993 int res = 0;
994 int amtcopy;
995 uint64_t offset;
997 unsigned char sector[MAX_SECTORSIZE];
998 int sectorshift;
999
1000 if (!dev) return CFE_ERR_NOTREADY;
1001
1002 sectorshift = usbdisk_sectorshift(softc->usbdisk_sectorsize);
1003
1004 bptr = buffer->buf_ptr;
1005 blen = buffer->buf_length;
1006 offset = buffer->buf_offset;
1007 numsec = (blen + softc->usbdisk_sectorsize - 1) >> sectorshift;
1008
1009 if (offset & (softc->usbdisk_sectorsize-1)) {
1010 lba = (offset >> sectorshift);
1011 res = usbmass_read_sector(dev,lba,1,PTR2HSADDR(sector));
1012 if (res < 0) goto out;
1013 amtcopy = softc->usbdisk_sectorsize - (offset & (softc->usbdisk_sectorsize-1));
1014 if (amtcopy > blen) amtcopy = blen;
1015 hs_memcpy_from_hs(&sector[offset & (softc->usbdisk_sectorsize-1)],bptr,amtcopy);
1016 res = usbmass_write_sector(dev,lba,1,PTR2HSADDR(sector));
1017 if (res < 0) goto out;
1018 bptr += amtcopy;
1019 offset += amtcopy;
1020 blen -= amtcopy;
1021 }
1022
1023 while (blen >= softc->usbdisk_sectorsize) {
1024 amtcopy = softc->usbdisk_sectorsize;
1025 lba = (offset >> sectorshift);
1026 res = usbmass_write_sector(dev,lba,1,bptr);
1027 if (res < 0) goto out;
1028 bptr += amtcopy;
1029 offset += amtcopy;
1030 blen -= amtcopy;
1031 }
1032
1033 if (blen) {
1034 lba = (offset >> sectorshift);
1035 res = usbmass_read_sector(dev,lba,1,PTR2HSADDR(sector));
1036 if (res < 0) goto out;
1037 amtcopy = blen;
1038 hs_memcpy_from_hs(sector,bptr,amtcopy);
1039 res = usbmass_write_sector(dev,lba,1,PTR2HSADDR(sector));
1040 if (res < 0) goto out;
1041 bptr += amtcopy;
1042 offset += amtcopy;
1043 blen -= amtcopy;
1044 }
1045
1046out:
1047 buffer->buf_retlen = bptr - buffer->buf_ptr;
1048
1049 return res;
1050}
1051
1052
1053/* *********************************************************************
1054 * usbdisk_ioctl(ctx,buffer)
1055 *
1056 * Process device I/O control requests for the IDE device.
1057 *
1058 * Input parameters:
1059 * ctx - device context
1060 * buffer - buffer descriptor
1061 *
1062 * Return value:
1063 * 0 if ok
1064 * else error code
1065 ********************************************************************* */
1066
1067static int usbdisk_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
1068{
1069 usbdisk_t *softc = ctx->dev_softc;
1070 unsigned int info;
1071 unsigned long long linfo;
1072 blockdev_info_t devinfo;
1073
1074 switch ((int)buffer->buf_ioctlcmd) {
1075 case IOCTL_BLOCK_GETBLOCKSIZE:
1076 info = softc->usbdisk_sectorsize;
1077 hs_memcpy_to_hs(buffer->buf_ptr,&info,sizeof(info));
1078 break;
1079 case IOCTL_BLOCK_GETTOTALBLOCKS:
1080 linfo = softc->usbdisk_ttlsect;
1081 hs_memcpy_to_hs(buffer->buf_ptr,&linfo,sizeof(linfo));
1082 break;
1083 case IOCTL_BLOCK_GETDEVTYPE:
1084 devinfo.blkdev_totalblocks = softc->usbdisk_ttlsect;
1085 devinfo.blkdev_blocksize = softc->usbdisk_sectorsize;
1086 devinfo.blkdev_devtype = softc->usbdisk_devtype;
1087 hs_memcpy_to_hs(buffer->buf_ptr,&devinfo,sizeof(devinfo));
1088 break;
1089 default:
1090 return -1;
1091 }
1092
1093 return 0;
1094}
1095
1096/* *********************************************************************
1097 * usbdisk_close(ctx)
1098 *
1099 * Close the I/O device.
1100 *
1101 * Input parameters:
1102 * ctx - device context
1103 *
1104 * Return value:
1105 * 0 if ok, else error code
1106 ********************************************************************* */
1107
1108static int usbdisk_close(cfe_devctx_t *ctx)
1109{
1110 /* usbdisk_t *softc = ctx->dev_softc; */
1111
1112 return 0;
1113}
1114
1115
1116#endif
1117
1118#define MAX_SECTOR_PER_REQUEST 8
1119
1120int usbmass_read(struct bdev *dev, void *data, lba_t lba, int num)
1121{
1122 char * p = (char *)data;
1123 usbmass_softc_t *softc = dev->ctx;
1124 lba += dev->offset;
1125
1126 int r = 0;
1127 while (num)
1128 {
1129 int tl = num;
1130 if (tl>MAX_SECTOR_PER_REQUEST) tl=MAX_SECTOR_PER_REQUEST;
1131 if (usbmass_read_sector(softc->dev, lba, tl, PTR2HSADDR(p)))
1132 break;
1133
1134 p += tl*512;
1135 num -= tl;
1136 r += tl;
1137 lba += tl;
1138 }
1139
1140 return r;
1141}
1142
1143int usbmass_write(struct bdev *dev, const void *data, lba_t lba, int num)
1144{
1145 char * p = (char *)data;
1146 usbmass_softc_t *softc = dev->ctx;
1147 lba += dev->offset;
1148
1149 int r = 0;
1150 while (num)
1151 {
1152 int tl = num;
1153 if (tl>MAX_SECTOR_PER_REQUEST) tl=MAX_SECTOR_PER_REQUEST;
1154 if (usbmass_write_sector(softc->dev, lba, tl, PTR2HSADDR(p)))
1155 break;
1156
1157 p += tl*512;
1158 num -= tl;
1159 r += tl;
1160 lba += tl;
1161 }
1162
1163 return r;
1164}
1165
1166#endif
uint32_t lba
Definition: ata.h:2
#define console_log(fmt, x...)
Definition: cfe.h:18
void * hsaddr_t
Definition: cfe.h:11
#define NULL
Definition: def.h:47
u32 size
Definition: iso9660.c:537
#define KMALLOC(size, align)
Definition: lib_malloc.h:92
#define KFREE(ptr)
Definition: lib_malloc.h:93
u32 uint32_t
Definition: libfdt_env.h:11
u64 uint64_t
Definition: libfdt_env.h:12
u8 uint8_t
Definition: libfdt_env.h:9
uint8_t bConfigurationValue
Definition: usbchap9.h:216
uint8_t bEndpointAddress
Definition: usbchap9.h:196
uint8_t bInterfaceSubClass
Definition: usbchap9.h:231
uint8_t bInterfaceProtocol
Definition: usbchap9.h:232
Definition: usbd.h:141
usb_config_descr_t * ud_cfgdescr
Definition: usbd.h:150
void * ud_private
Definition: usbd.h:148
usb_driver_t * ud_drv
Definition: usbd.h:142
Definition: usbd.h:171
#define USB_ENDPOINT_DESCRIPTOR_TYPE
Definition: usbchap9.h:66
#define USB_ENDPOINT_DIR_OUT(addr)
Definition: usbchap9.h:107
#define USB_INTERFACE_DESCRIPTOR_TYPE
Definition: usbchap9.h:65
void * usb_find_cfg_descr(usbdev_t *dev, int dtype, int idx)
Definition: usbd.c:1237
int usb_std_request(usbdev_t *dev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *buffer, int length)
Definition: usbd.c:796
int usb_wait_request(usbreq_t *ur)
Definition: usbd.c:529
usbreq_t * usb_make_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:353
void usb_free_request(usbreq_t *ur)
Definition: usbd.c:457
int usb_clear_stall(usbdev_t *dev, int epaddr)
Definition: usbd.c:731
int usb_queue_request(usbreq_t *ur)
Definition: usbd.c:502
int usb_set_configuration(usbdev_t *dev, int config)
Definition: usbd.c:619
int usb_make_sync_request(usbdev_t *dev, int epaddr, uint8_t *buf, int length, int flags)
Definition: usbd.c:572
int usb_open_pipe(usbdev_t *dev, usb_endpoint_descr_t *epdesc)
Definition: usbd.c:165
#define UR_FLAG_OUT
Definition: usbd.h:165
#define UR_FLAG_IN
Definition: usbd.h:164
#define UR_FLAG_SHORTOK
Definition: usbd.h:168
usbdev_t * usbmass_dev
int usbmass_read_sector(usbdev_t *dev, uint32_t sectornum, uint32_t seccnt, uint8_t *buffer)
union @15 data
unsigned long long lba_t
Definition: xetypes.h:44