1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * USB Mass-Storage driver File: usbmass.c
6 * This driver deals with mass-storage devices that support
7 * the SCSI Transparent command set and USB Bulk-Only protocol
9 * Author: Mitch Lichtenberg (mpl@broadcom.com)
11 *********************************************************************
13 * Copyright 2000,2001,2002,2003
14 * Broadcom Corporation. All rights reserved.
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.
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.
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.
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 ********************************************************************* */
56 #include "lib_types.h"
57 #include "lib_string.h"
58 #include "lib_printf.h"
59 #include "cfe_timer.h"
61 #include "cfe_device.h"
62 #include "cfe_ioctl.h"
63 #include "cfe_error.h"
64 #include "cfe_console.h"
67 #include "lib_malloc.h"
68 #include "lib_queue.h"
72 /* *********************************************************************
73 * USB Mass-Storage class Constants
74 ********************************************************************* */
76 #define USBMASS_CBI_PROTOCOL 0
77 #define USBMASS_CBI_NOCOMPLETE_PROTOCOL 1
78 #define USBMASS_BULKONLY_PROTOCOL 0x50
80 #define USBMASS_SUBCLASS_RBC 0x01
81 #define USBMASS_SUBCLASS_SFF8020 0x02
82 #define USBMASS_SUBCLASS_QIC157 0x03
83 #define USBMASS_SUBCLASS_UFI 0x04
84 #define USBMASS_SUBCLASS_SFF8070 0x05
85 #define USBMASS_SUBCLASS_SCSI 0x06
87 #define USBMASS_CSW_PASS 0x00
88 #define USBMASS_CSW_FAILED 0x01
89 #define USBMASS_CSW_PHASEERR 0x02
91 #define USBMASS_CBW_SIGNATURE 0x43425355
92 #define USBMASS_CSW_SIGNATURE 0x53425355
94 /* *********************************************************************
95 * USB Mass-Storage class Structures
96 ********************************************************************* */
98 typedef struct usbmass_cbw_s
{
99 uint8_t dCBWSignature0
,dCBWSignature1
,dCBWSignature2
,dCBWSignature3
;
100 uint8_t dCBWTag0
,dCBWTag1
,dCBWTag2
,dCBWTag3
;
101 uint8_t dCBWDataTransferLength0
,dCBWDataTransferLength1
,
102 dCBWDataTransferLength2
,dCBWDataTransferLength3
;
105 uint8_t bCBWCBLength
;
109 typedef struct usbmass_csw_s
{
110 uint8_t dCSWSignature0
,dCSWSignature1
,dCSWSignature2
,dCSWSignature3
;
111 uint8_t dCSWTag0
,dCSWTag1
,dCSWTag2
,dCSWTag3
;
112 uint8_t dCSWDataResidue0
,dCSWDataResidue1
,dCSWDataResidue2
,dCSWDataResidue3
;
116 #define GETCBWFIELD(s,f) ((uint32_t)((s)->f##0) | ((uint32_t)((s)->f##1) << 8) | \
117 ((uint32_t)((s)->f##2) << 16) | ((uint32_t)((s)->f##3) << 24))
118 #define PUTCBWFIELD(s,f,v) (s)->f##0 = (v & 0xFF); \
119 (s)->f##1 = ((v)>>8 & 0xFF); \
120 (s)->f##2 = ((v)>>16 & 0xFF); \
121 (s)->f##3 = ((v)>>24 & 0xFF);
124 int usbmass_request_sense(usbdev_t
*dev
);
126 /* *********************************************************************
128 ********************************************************************* */
133 * Softc for the CFE side of the disk driver.
135 #define MAX_SECTORSIZE 2048
136 typedef struct usbdisk_s
{
137 uint32_t usbdisk_sectorsize
;
138 uint32_t usbdisk_ttlsect
;
139 uint32_t usbdisk_devtype
;
144 * This table points at the currently configured USB disk
145 * devices. This lets us leave the CFE half of the driver lying
146 * around while the USB devices come and go. We use the unit number
147 * from the original CFE attach to index this table, and devices
148 * that are not present are "not ready."
151 #define USBDISK_MAXUNITS 4
152 static usbdev_t
*usbdisk_units
[USBDISK_MAXUNITS
];
155 * CFE device driver routine forwards
158 static void usbdisk_probe(cfe_driver_t
*drv
,
159 unsigned long probe_a
, unsigned long probe_b
,
162 static int usbdisk_open(cfe_devctx_t
*ctx
);
163 static int usbdisk_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
164 static int usbdisk_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
165 static int usbdisk_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
166 static int usbdisk_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
167 static int usbdisk_close(cfe_devctx_t
*ctx
);
170 * CFE device driver descriptor
173 const static cfe_devdisp_t usbdisk_dispatch
= {
184 const cfe_driver_t usb_disk
= {
197 /* *********************************************************************
198 * Forward Definitions
199 ********************************************************************* */
201 static int usbmass_attach(usbdev_t
*dev
,usb_driver_t
*drv
);
202 static int usbmass_detach(usbdev_t
*dev
);
204 /* *********************************************************************
206 ********************************************************************* */
208 typedef struct usbmass_softc_s
{
212 uint32_t umass_curtag
;
216 usb_driver_t usbmass_driver
= {
217 "Mass-Storage Device",
222 usbdev_t
*usbmass_dev
= NULL
; /* XX hack for testing only */
224 /* *********************************************************************
225 * usbmass_mass_storage_reset(dev,ifc)
227 * Do a bulk-only mass-storage reset.
230 * dev - device to reset
231 * ifc - interface number to reset (bInterfaceNum)
235 ********************************************************************* */
237 #define usbmass_mass_storage_reset(dev,ifc) \
238 usb_simple_request(dev,0x21,0xFF,ifc,0)
242 /* *********************************************************************
243 * usbmass_stall_recovery(dev)
245 * Do whatever it takes to unstick a stalled mass-storage device.
252 ********************************************************************* */
254 static void usbmass_stall_recovery(usbdev_t
*dev
)
256 usbmass_softc_t
*softc
;
258 softc
= (usbmass_softc_t
*) dev
->ud_private
;
260 usb_clear_stall(dev
,softc
->umass_inpipe
);
262 usbmass_request_sense(dev
);
266 /* *********************************************************************
267 * usbmass_read_capacity(dev,sectornum,buffer)
269 * Reads a sector from the device.
273 * sectornum - sector number to read
274 * buffer - place to put sector we read
278 ********************************************************************* */
280 int usbmass_request_sense(usbdev_t
*dev
)
287 usbmass_softc_t
*softc
;
290 softc
= (usbmass_softc_t
*) dev
->ud_private
;
292 cbwcsw
= KMALLOC(64,32);
293 sector
= KMALLOC(64,32);
297 cbw
= (usbmass_cbw_t
*) cbwcsw
;
298 csw
= (usbmass_csw_t
*) cbwcsw
;
301 * Fill in the fields of the CBW
304 PUTCBWFIELD(cbw
,dCBWSignature
,USBMASS_CBW_SIGNATURE
);
305 PUTCBWFIELD(cbw
,dCBWTag
,softc
->umass_curtag
);
306 PUTCBWFIELD(cbw
,dCBWDataTransferLength
,18);
307 cbw
->bmCBWFlags
= 0x80; /* IN */
309 cbw
->bCBWCBLength
= 12;
310 cbw
->CBWCB
[0] = 0x3; /* REQUEST SENSE */
314 cbw
->CBWCB
[4] = 18; /* allocation length */
321 softc
->umass_curtag
++;
327 ur
= usb_make_request(dev
,softc
->umass_outpipe
,(uint8_t *) cbw
,
328 sizeof(usbmass_cbw_t
),UR_FLAG_OUT
);
329 res
= usb_sync_request(ur
);
330 usb_free_request(ur
);
337 ur
= usb_make_request(dev
,softc
->umass_inpipe
,sector
,
338 18,UR_FLAG_IN
| UR_FLAG_SHORTOK
);
339 res
= usb_sync_request(ur
);
340 usb_free_request(ur
);
346 memset(csw
,0,sizeof(usbmass_csw_t
));
347 ur
= usb_make_request(dev
,softc
->umass_inpipe
,(uint8_t *) csw
,
348 sizeof(usbmass_csw_t
),UR_FLAG_IN
);
349 res
= usb_sync_request(ur
);
350 usb_free_request(ur
);
360 /* *********************************************************************
361 * usbmass_read_sector(dev,sectornum,seccnt,buffer)
363 * Reads a sector from the device.
367 * sectornum - sector number to read
368 * seccnt - count of sectors to read
369 * buffer - place to put sector we read
373 ********************************************************************* */
375 int usbmass_read_sector(usbdev_t
*dev
,uint32_t sectornum
,uint32_t seccnt
,
377 int usbmass_read_sector(usbdev_t
*dev
,uint32_t sectornum
,uint32_t seccnt
,
385 usbmass_softc_t
*softc
;
388 softc
= (usbmass_softc_t
*) dev
->ud_private
;
390 cbwcsw
= KMALLOC(64,32);
393 cbw
= (usbmass_cbw_t
*) cbwcsw
;
394 csw
= (usbmass_csw_t
*) cbwcsw
;
397 * Fill in the fields of the CBW
400 PUTCBWFIELD(cbw
,dCBWSignature
,USBMASS_CBW_SIGNATURE
);
401 PUTCBWFIELD(cbw
,dCBWTag
,softc
->umass_curtag
);
402 PUTCBWFIELD(cbw
,dCBWDataTransferLength
,(512*seccnt
));
403 cbw
->bmCBWFlags
= 0x80; /* IN */
405 cbw
->bCBWCBLength
= 10;
406 cbw
->CBWCB
[0] = 0x28; /* READ */
408 cbw
->CBWCB
[2] = (sectornum
>> 24) & 0xFF; /* LUN 0 & MSB's of sector */
409 cbw
->CBWCB
[3] = (sectornum
>> 16) & 0xFF;
410 cbw
->CBWCB
[4] = (sectornum
>> 8) & 0xFF;
411 cbw
->CBWCB
[5] = (sectornum
>> 0) & 0xFF;
414 cbw
->CBWCB
[8] = seccnt
;
417 softc
->umass_curtag
++;
423 ur
= usb_make_request(dev
,softc
->umass_outpipe
,(uint8_t *) cbw
,
424 sizeof(usbmass_cbw_t
),UR_FLAG_OUT
);
425 res
= usb_sync_request(ur
);
426 usb_free_request(ur
);
428 usbmass_stall_recovery(dev
);
438 ur
= usb_make_request(dev
,softc
->umass_inpipe
,sector
,
439 512*seccnt
,UR_FLAG_IN
| UR_FLAG_SHORTOK
);
440 res
= usb_sync_request(ur
);
441 usb_free_request(ur
);
443 usbmass_stall_recovery(dev
);
453 memset(csw
,0,sizeof(usbmass_csw_t
));
454 ur
= usb_make_request(dev
,softc
->umass_inpipe
,(uint8_t *) csw
,
455 sizeof(usbmass_csw_t
),UR_FLAG_IN
);
456 res
= usb_sync_request(ur
);
457 usb_free_request(ur
);
459 usbmass_stall_recovery(dev
);
466 res
= (csw
->bCSWStatus
== USBMASS_CSW_PASS
) ? 0 : -1;
474 /* *********************************************************************
475 * usbmass_write_sector(dev,sectornum,seccnt,buffer)
477 * Writes a sector to the device
481 * sectornum - sector number to write
482 * seccnt - count of sectors to write
483 * buffer - place to get sector to write
487 ********************************************************************* */
489 static int usbmass_write_sector(usbdev_t
*dev
,uint32_t sectornum
,uint32_t seccnt
,
497 usbmass_softc_t
*softc
;
500 softc
= (usbmass_softc_t
*) dev
->ud_private
;
502 cbwcsw
= KMALLOC(64,32);
505 cbw
= (usbmass_cbw_t
*) cbwcsw
;
506 csw
= (usbmass_csw_t
*) cbwcsw
;
509 * Fill in the fields of the CBW
512 PUTCBWFIELD(cbw
,dCBWSignature
,USBMASS_CBW_SIGNATURE
);
513 PUTCBWFIELD(cbw
,dCBWTag
,softc
->umass_curtag
);
514 PUTCBWFIELD(cbw
,dCBWDataTransferLength
,(512*seccnt
));
515 cbw
->bmCBWFlags
= 0x00; /* OUT */
517 cbw
->bCBWCBLength
= 10;
518 cbw
->CBWCB
[0] = 0x2A; /* WRITE */
520 cbw
->CBWCB
[2] = (sectornum
>> 24) & 0xFF; /* LUN 0 & MSB's of sector */
521 cbw
->CBWCB
[3] = (sectornum
>> 16) & 0xFF;
522 cbw
->CBWCB
[4] = (sectornum
>> 8) & 0xFF;
523 cbw
->CBWCB
[5] = (sectornum
>> 0) & 0xFF;
526 cbw
->CBWCB
[8] = seccnt
;
529 softc
->umass_curtag
++;
535 ur
= usb_make_request(dev
,softc
->umass_outpipe
,(uint8_t *) cbw
,
536 sizeof(usbmass_cbw_t
),UR_FLAG_OUT
);
537 res
= usb_sync_request(ur
);
538 usb_free_request(ur
);
544 ur
= usb_make_request(dev
,softc
->umass_outpipe
,sector
,
545 512*seccnt
,UR_FLAG_OUT
);
546 res
= usb_sync_request(ur
);
547 usb_free_request(ur
);
553 memset(csw
,0,sizeof(usbmass_csw_t
));
554 ur
= usb_make_request(dev
,softc
->umass_inpipe
,(uint8_t *) csw
,
555 sizeof(usbmass_csw_t
),UR_FLAG_IN
);
556 res
= usb_sync_request(ur
);
557 usb_free_request(ur
);
560 res
= (csw
->bCSWStatus
== USBMASS_CSW_PASS
) ? 0 : -1;
567 /* *********************************************************************
568 * usbmass_read_capacity(dev,sectornum,buffer)
570 * Reads a sector from the device.
574 * sectornum - sector number to read
575 * buffer - place to put sector we read
579 ********************************************************************* */
581 int usbmass_read_capacity(usbdev_t
*dev
,uint32_t *size
);
582 int usbmass_read_capacity(usbdev_t
*dev
,uint32_t *size
)
589 usbmass_softc_t
*softc
;
592 softc
= (usbmass_softc_t
*) dev
->ud_private
;
594 cbwcsw
= KMALLOC(64,32);
595 sector
= KMALLOC(64,32);
599 cbw
= (usbmass_cbw_t
*) cbwcsw
;
600 csw
= (usbmass_csw_t
*) cbwcsw
;
605 * Fill in the fields of the CBW
608 PUTCBWFIELD(cbw
,dCBWSignature
,USBMASS_CBW_SIGNATURE
);
609 PUTCBWFIELD(cbw
,dCBWTag
,softc
->umass_curtag
);
610 PUTCBWFIELD(cbw
,dCBWDataTransferLength
,8);
611 cbw
->bmCBWFlags
= 0x80; /* IN */
613 cbw
->bCBWCBLength
= 10;
614 cbw
->CBWCB
[0] = 0x25; /* READ CAPACITY */
625 softc
->umass_curtag
++;
631 ur
= usb_make_request(dev
,softc
->umass_outpipe
,(uint8_t *) cbw
,
632 sizeof(usbmass_cbw_t
),UR_FLAG_OUT
);
633 res
= usb_sync_request(ur
);
634 usb_free_request(ur
);
637 usbmass_stall_recovery(dev
);
647 ur
= usb_make_request(dev
,softc
->umass_inpipe
,sector
,
648 8,UR_FLAG_IN
| UR_FLAG_SHORTOK
);
649 res
= usb_sync_request(ur
);
650 usb_free_request(ur
);
653 usbmass_stall_recovery(dev
);
663 memset(csw
,0,sizeof(usbmass_csw_t
));
664 ur
= usb_make_request(dev
,softc
->umass_inpipe
,(uint8_t *) csw
,
665 sizeof(usbmass_csw_t
),UR_FLAG_IN
);
666 res
= usb_sync_request(ur
);
667 usb_free_request(ur
);
671 *size
= (((uint32_t) sector
[0]) << 24) |
672 (((uint32_t) sector
[1]) << 16) |
673 (((uint32_t) sector
[2]) << 8) |
674 (((uint32_t) sector
[3]) << 0);
684 /* *********************************************************************
685 * usbmass_attach(dev,drv)
687 * This routine is called when the bus scan stuff finds a mass-storage
688 * device. We finish up the initialization by configuring the
689 * device and allocating our softc here.
692 * dev - usb device, in the "addressed" state.
693 * drv - the driver table entry that matched
697 ********************************************************************* */
699 static int usbmass_attach(usbdev_t
*dev
,usb_driver_t
*drv
)
701 usb_config_descr_t
*cfgdscr
= dev
->ud_cfgdescr
;
702 usb_endpoint_descr_t
*epdscr
;
703 usb_endpoint_descr_t
*indscr
= NULL
;
704 usb_endpoint_descr_t
*outdscr
= NULL
;
705 usb_interface_descr_t
*ifdscr
;
706 usbmass_softc_t
*softc
;
711 softc
= KMALLOC(sizeof(usbmass_softc_t
),0);
712 memset(softc
,0,sizeof(usbmass_softc_t
));
713 dev
->ud_private
= softc
;
715 ifdscr
= usb_find_cfg_descr(dev
,USB_INTERFACE_DESCRIPTOR_TYPE
,0);
716 if (ifdscr
== NULL
) {
720 if ((ifdscr
->bInterfaceSubClass
!= USBMASS_SUBCLASS_SCSI
) ||
721 (ifdscr
->bInterfaceProtocol
!= USBMASS_BULKONLY_PROTOCOL
)) {
722 console_log("USBMASS: Do not understand devices with SubClass 0x%02X, Protocol 0x%02X",
723 ifdscr
->bInterfaceSubClass
,
724 ifdscr
->bInterfaceProtocol
);
728 for (idx
= 0; idx
< 2; idx
++) {
729 epdscr
= usb_find_cfg_descr(dev
,USB_ENDPOINT_DESCRIPTOR_TYPE
,idx
);
731 if (USB_ENDPOINT_DIR_OUT(epdscr
->bEndpointAddress
)) {
740 if (!indscr
|| !outdscr
) {
742 * Could not get descriptors, something is very wrong.
743 * Leave device addressed but not configured.
749 * Choose the standard configuration.
752 usb_set_configuration(dev
,cfgdscr
->bConfigurationValue
);
758 softc
->umass_inpipe
= usb_open_pipe(dev
,indscr
);
759 softc
->umass_outpipe
= usb_open_pipe(dev
,outdscr
);
760 softc
->umass_curtag
= 0x12345678;
763 * Save pointer in global unit table so we can
764 * match CFE devices up with USB ones
769 softc
->umass_unit
= -1;
770 for (idx
= 0; idx
< USBDISK_MAXUNITS
; idx
++) {
771 if (usbdisk_units
[idx
] == NULL
) {
772 softc
->umass_unit
= idx
;
773 usbdisk_units
[idx
] = dev
;
778 console_log("USBMASS: Unit %d connected",softc
->umass_unit
);
786 /* *********************************************************************
787 * usbmass_detach(dev)
789 * This routine is called when the bus scanner notices that
790 * this device has been removed from the system. We should
791 * do any cleanup that is required. The pending requests
792 * will be cancelled automagically.
799 ********************************************************************* */
801 static int usbmass_detach(usbdev_t
*dev
)
803 usbmass_softc_t
*softc
;
804 softc
= (usbmass_softc_t
*) dev
->ud_private
;
807 console_log("USBMASS: USB unit %d disconnected",softc
->umass_unit
);
808 if (softc
->umass_unit
>= 0) usbdisk_units
[softc
->umass_unit
] = NULL
;
820 /* *********************************************************************
821 * usbdisk_sectorshift(size)
823 * Given a sector size, return log2(size). We cheat; this is
824 * only needed for 2048 and 512-byte sectors.
825 * Explicitly using shifts and masks in sector number calculations
826 * helps on 32-bit-only platforms, since we probably won't need
834 ********************************************************************* */
836 #define usbdisk_sectorshift(size) (((size)==2048)?11:9)
839 /* *********************************************************************
840 * usbdisk_probe(drv,probe_a,probe_b,probe_ptr)
842 * Our probe routine. Attach an empty USB disk device to the firmware.
845 * drv - driver structure
848 * probe_ptr - not used
852 ********************************************************************* */
854 static void usbdisk_probe(cfe_driver_t
*drv
,
855 unsigned long probe_a
, unsigned long probe_b
,
861 softc
= (usbdisk_t
*) KMALLOC(sizeof(usbdisk_t
),0);
863 memset(softc
,0,sizeof(usbdisk_t
));
865 softc
->usbdisk_sectorsize
= 512;
866 softc
->usbdisk_devtype
= BLOCK_DEVTYPE_DISK
;
867 softc
->usbdisk_ttlsect
= 0; /* not calculated yet */
868 softc
->usbdisk_unit
= (int)probe_a
;
870 xsprintf(descr
,"USB Disk unit %d",(int)probe_a
);
872 cfe_attach(drv
,softc
,NULL
,descr
);
876 /* *********************************************************************
879 * Process the CFE OPEN call for this device. For IDE disks,
880 * the device is reset and identified, and the geometry is
884 * ctx - device context
887 * 0 if ok, else error code
888 ********************************************************************* */
891 static int usbdisk_open(cfe_devctx_t
*ctx
)
893 usbdisk_t
*softc
= ctx
->dev_softc
;
894 usbdev_t
*dev
= usbdisk_units
[softc
->usbdisk_unit
];
898 if (!dev
) return CFE_ERR_NOTREADY
;
900 usbmass_request_sense(dev
);
902 res
= usbmass_read_capacity(dev
,&size
);
903 if (res
< 0) return res
;
905 softc
->usbdisk_ttlsect
= size
;
910 /* *********************************************************************
911 * usbdisk_read(ctx,buffer)
913 * Process a CFE READ command for the IDE device. This is
914 * more complex than it looks, since CFE offsets are byte offsets
915 * and we may need to read partial sectors.
918 * ctx - device context
919 * buffer - buffer descriptor
922 * number of bytes read, or <0 if an error occured
923 ********************************************************************* */
925 static int usbdisk_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
927 usbdisk_t
*softc
= ctx
->dev_softc
;
928 usbdev_t
*dev
= usbdisk_units
[softc
->usbdisk_unit
];
936 unsigned char sector
[MAX_SECTORSIZE
];
939 if (!dev
) return CFE_ERR_NOTREADY
;
941 sectorshift
= usbdisk_sectorshift(softc
->usbdisk_sectorsize
);
943 bptr
= buffer
->buf_ptr
;
944 blen
= buffer
->buf_length
;
945 offset
= buffer
->buf_offset
;
946 numsec
= (blen
+ softc
->usbdisk_sectorsize
- 1) >> sectorshift
;
948 if (offset
& (softc
->usbdisk_sectorsize
-1)) {
949 lba
= (offset
>> sectorshift
);
950 res
= usbmass_read_sector(dev
,lba
,1,sector
);
951 if (res
< 0) goto out
;
952 amtcopy
= softc
->usbdisk_sectorsize
- (offset
& (softc
->usbdisk_sectorsize
-1));
953 if (amtcopy
> blen
) amtcopy
= blen
;
954 memcpy(bptr
,§or
[offset
& (softc
->usbdisk_sectorsize
-1)],amtcopy
);
960 if (blen
>= softc
->usbdisk_sectorsize
) {
963 lba
= (offset
>> sectorshift
);
964 seccnt
= (blen
>> sectorshift
);
966 res
= usbmass_read_sector(dev
,lba
,seccnt
,bptr
);
967 if (res
< 0) goto out
;
969 amtcopy
= seccnt
<< sectorshift
;
976 lba
= (offset
>> sectorshift
);
977 res
= usbmass_read_sector(dev
,lba
,1,sector
);
978 if (res
< 0) goto out
;
980 memcpy(bptr
,sector
,amtcopy
);
987 buffer
->buf_retlen
= bptr
- buffer
->buf_ptr
;
992 /* *********************************************************************
993 * usbdisk_inpstat(ctx,inpstat)
995 * Test input status for the IDE disk. Disks are always ready
999 * ctx - device context
1000 * inpstat - input status structure
1004 ********************************************************************* */
1006 static int usbdisk_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
)
1008 /* usbdisk_t *softc = ctx->dev_softc; */
1010 inpstat
->inp_status
= 1;
1014 /* *********************************************************************
1015 * usbdisk_write(ctx,buffer)
1017 * Process a CFE WRITE command for the IDE device. If the write
1018 * involves partial sectors, the affected sectors are read first
1019 * and the changes are merged in.
1022 * ctx - device context
1023 * buffer - buffer descriptor
1026 * number of bytes write, or <0 if an error occured
1027 ********************************************************************* */
1029 static int usbdisk_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
1031 usbdisk_t
*softc
= ctx
->dev_softc
;
1032 usbdev_t
*dev
= usbdisk_units
[softc
->usbdisk_unit
];
1033 unsigned char *bptr
;
1040 unsigned char sector
[MAX_SECTORSIZE
];
1043 if (!dev
) return CFE_ERR_NOTREADY
;
1045 sectorshift
= usbdisk_sectorshift(softc
->usbdisk_sectorsize
);
1047 bptr
= buffer
->buf_ptr
;
1048 blen
= buffer
->buf_length
;
1049 offset
= buffer
->buf_offset
;
1050 numsec
= (blen
+ softc
->usbdisk_sectorsize
- 1) >> sectorshift
;
1052 if (offset
& (softc
->usbdisk_sectorsize
-1)) {
1053 lba
= (offset
>> sectorshift
);
1054 res
= usbmass_read_sector(dev
,lba
,1,sector
);
1055 if (res
< 0) goto out
;
1056 amtcopy
= softc
->usbdisk_sectorsize
- (offset
& (softc
->usbdisk_sectorsize
-1));
1057 if (amtcopy
> blen
) amtcopy
= blen
;
1058 memcpy(§or
[offset
& (softc
->usbdisk_sectorsize
-1)],bptr
,amtcopy
);
1059 res
= usbmass_write_sector(dev
,lba
,1,sector
);
1060 if (res
< 0) goto out
;
1066 while (blen
>= softc
->usbdisk_sectorsize
) {
1067 amtcopy
= softc
->usbdisk_sectorsize
;
1068 lba
= (offset
>> sectorshift
);
1069 res
= usbmass_write_sector(dev
,lba
,1,bptr
);
1070 if (res
< 0) goto out
;
1077 lba
= (offset
>> sectorshift
);
1078 res
= usbmass_read_sector(dev
,lba
,1,sector
);
1079 if (res
< 0) goto out
;
1081 memcpy(sector
,bptr
,amtcopy
);
1082 res
= usbmass_write_sector(dev
,lba
,1,sector
);
1083 if (res
< 0) goto out
;
1090 buffer
->buf_retlen
= bptr
- buffer
->buf_ptr
;
1096 /* *********************************************************************
1097 * usbdisk_ioctl(ctx,buffer)
1099 * Process device I/O control requests for the IDE device.
1102 * ctx - device context
1103 * buffer - buffer descriptor
1108 ********************************************************************* */
1110 static int usbdisk_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
1112 usbdisk_t
*softc
= ctx
->dev_softc
;
1113 unsigned int *info
= (unsigned int *) buffer
->buf_ptr
;
1114 unsigned long long *linfo
= (unsigned long long *) buffer
->buf_ptr
;
1115 blockdev_info_t
*devinfo
;
1117 switch ((int)buffer
->buf_ioctlcmd
) {
1118 case IOCTL_BLOCK_GETBLOCKSIZE
:
1119 *info
= softc
->usbdisk_sectorsize
;
1121 case IOCTL_BLOCK_GETTOTALBLOCKS
:
1122 *linfo
= softc
->usbdisk_ttlsect
;
1124 case IOCTL_BLOCK_GETDEVTYPE
:
1125 devinfo
= (blockdev_info_t
*) buffer
->buf_ptr
;
1126 devinfo
->blkdev_totalblocks
= softc
->usbdisk_ttlsect
;
1127 devinfo
->blkdev_blocksize
= softc
->usbdisk_sectorsize
;
1128 devinfo
->blkdev_devtype
= softc
->usbdisk_devtype
;
1137 /* *********************************************************************
1138 * usbdisk_close(ctx)
1140 * Close the I/O device.
1143 * ctx - device context
1146 * 0 if ok, else error code
1147 ********************************************************************* */
1149 static int usbdisk_close(cfe_devctx_t
*ctx
)
1151 /* usbdisk_t *softc = ctx->dev_softc; */