//**************************************************************************** //**************************************************************************** //** ** //** (C)Copyright 1985-2016, American Megatrends, Inc. ** //** ** //** All Rights Reserved. ** //** ** //** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** //** ** //** Phone (770)-246-8600 ** //** ** //**************************************************************************** //**************************************************************************** //**************************************************************************** // $Header: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbmass.c 174 10/20/16 11:19p Wilsonlee $ // // $Revision: 174 $ // // $Date: 10/20/16 11:19p $ //**************************************************************************** //**************************************************************************** // Revision History // ---------------- // // $Log: /Alaska/SOURCE/Modules/USB/ALASKA/RT/usbmass.c $ // // 174 10/20/16 11:19p Wilsonlee // [TAG] EIP297268 // [Category] Improvement // [Description] Update Media information only in EfiUsbMass driver when // Media is changed. // [Files] usbmass.c, efiusbmass.c // // 173 10/16/16 10:12p Wilsonlee // [TAG] EIP288158 // [Category] Improvement // [Description] Check if gUsbData is integrity. // [Files] amiusb.cif, usbsb.c, AmiUsbLib.cif, AmiUsbLib.sdl, // AmiUsbSmmGlobalDataValidationLib.c, // AmiUsbSmmGlobalDataValidationLib.cif, // AmiUsbSmmGlobalDataValidationLib.mak, Crc32.c, amiusb.c, amiusb.h, // ehci.c, elib.c, ohci.c, syskbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, // usbhid.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c, usbrt.mak, xhci.c, // amiusbhc.c, efiusbccid.c, efiusbmass.c, uhcd.c, usbmisc.c, // AmiUsbController.h, AmiUsbLibInclude.cif, // AmiUsbSmmGlobalDataValidationLib.h // // 172 7/22/16 3:51a Wilsonlee // [TAG] EIP277810 // [Category] Improvement // [Description] Validate the memory buffer is entirely outside of SMM. // [Files] usbsb.c, amiusb.c, ehci.c, ohci.c, uhci.c, usbCCID.c, // usbdef.h, usbmass.c, xhci.c, amiusbhc.c, efiusbccid.c, efiusbmass.c, // uhcd.c, uhcd.h, usbmisc.c // // 171 7/07/16 1:09a Wilsonlee // [TAG] EIP277810 // [Category] Improvement // [Description] Validate the memory buffer is entirely outside of SMM. // [Files] usbsb.c, amiusb.c, ehci.c, ohci.c, uhci.c, usbCCID.c, // usbdef.h, usbmass.c, xhci.c, amiusbhc.c, efiusbccid.c, efiusbmass.c, // uhcd.c, uhcd.h, usbmisc.c // // 170 4/08/16 3:54a Wilsonlee // [TAG] EIP260113 // [Category] Bug Fix // [Severity] Normal // [Symptom] We return success for writing data to to the // write-protected device. // [RootCause] Command Block Status is Command Failed when we send the // write command to the write-protected device. // [Solution] When CSW isn't Valid, we should issue a REQUEST SENSE // command to receive the sense data describing what caused the error // condition. // [Files] usbmass.c // // 169 3/02/16 9:41p Wilsonlee // [TAG] EIP254309 // [Category] Bug Fix // [Severity] Normal // [Symptom] GK-FORCE K83 USB KB function abnormal. // [RootCause] This device has an interrupt out endpoint and doesn't // support "Set Report" request. // [Solution] Use the interrupt out endpoint instead of sending "Set // Report" request. // [Files] AmiUsbController.h, xhci.c, usbmass.c, usbkbd.h, usbkbd.c, // usbhub.c, usbhid.c, usbdef.h, usbCCID.c, usb.c, uhci.c, ohci.c, ehci.c, // amiusb.h, efiusbms,c, amiusbhc.c // // 168 2/14/16 9:46p Wilsonlee // [TAG] EIP254924 // [Category] Improvement // [Description] Issue a Set TR Dequeue Pointer Command after issuing // for a ClearFeature(ENDPOINT_HALT) request to device. // [Files] usbmass.c, xhci.c // // 167 7/24/15 4:41a Wilsonlee // [TAG] EIP226493 // [Category] Improvement // [Description] Block to process periodic list to prevent that we might // send the wrong command sequences to the same device. // [Files] usbmass.c, ehci.c, xhci.h, xhci.c, usbdef.h, uhcd.c // // 166 5/27/15 2:13a Wilsonlee // [TAG] EIP220162 // [Category] Improvement // [Description] The read / write request contain the latest LBA that // are valid. // [Files] usbmass.c, efiusbmass.c // // 165 4/29/15 11:26p Wilsonlee // [TAG] EIP215031 // [Category] Bug Fix // [Severity] Normal // [Symptom] Transcend USB 3.0 HDD is disappeared in the setup menu by // cold boot. // [RootCause] We only can get SerialNumber string descriptor before // setting configuration for this device, otherwise it is failed at // getting this descriptor and inquiry command is also failed. // [Solution] Retry inquiry command. // [Files] usb.c, usbmass.c, efiusbmass.c, usbbus.c, usbdef.h // // 164 1/15/15 9:54p Wilsonlee // [TAG] EIP198806 // [Category] Improvement // [Description] Send "RequestSense" command only if "TestUnitReady" // command is failed. // [Files] usbmass.c // // 163 12/24/14 1:08a Wilsonlee // [TAG] EIP192517 // [Category] Improvement // [Description] SB Driver handles 0x100 NumHeads as a valid value. // [Files] usbmass.c, usbdef.h, UsbInt13.c, UsbInt13.h, UI13.bin, // Bfiusb.equ, Bfiusb.asm // // 162 11/30/14 10:30p Wilsonlee // [TAG] EIP193829 // [Category] Bug Fix // [Severity] Normal // [Symptom] Ghost on multiple USB dvd rom span (Legacy Dos )fails if // boot disk is smaller than second disk. // [RootCause] RWVCommand gets one byte data after we change Media, but // data isn't correct. // [Solution] Check if data length processed is correct. // [Files] usbmass.c // // 161 11/24/14 12:56a Wilsonlee // [TAG] EIP192326 // [Category] Improvement // [Description] Check that division by zero exception doesn't occur. // [Files] usbmass.c // // 160 11/23/14 10:53p Wilsonlee // [TAG] EIP186754 // [Category] Improvement // [Description] The minimum of sector should be 1. // [Files] usbmass.c // // 159 11/23/14 10:36p Wilsonlee // [TAG] EIP188492 // [Category] Improvement // [Description] Create a token to keep usb mass storage devices are // RemovableMedia. // [Files] usbmass.c, usb.sdl // // 158 9/02/14 4:09a Wilsonlee // [TAG] EIP183522 // [Category] Bug Fix // [Severity] Minor // [Symptom] Heads, Sectors and Cylinders aren't correct if usb mass // storages report media change. // [RootCause] We update CHS from read capacity parameters if media // change. // [Solution] We already update CHS from boot record and legacy boot // doesn't support dynamic media insertion, we should not update it from // read capacity parameters. // [Files] usbmass.c // // 157 8/07/14 5:35a Wilsonlee // [TAG] EIP180686 // [Category] Improvement // [Description] Right shifts 64bit values that should be using Shr64(). // [Files] usbmass.c // // 156 7/04/14 5:23a Wilsonlee // [TAG] EIP175485 // [Category] Bug Fix // [Severity] Minor // [Symptom] USB key can't be save during secure boot key. // [RootCause] The usb key, MSI 8G Team, has two luns. One is CD-ROM, it // always reports there is no media until we send "Get_Configuration" // command to it, then it causes the other lun will report media change // when we read/write data later. // [Solution] Send "Get_Configuration" command for CD/DVD devices. // [Files] usbmass.c // // 155 6/26/14 1:16a Wilsonlee // [TAG] EIP173387 // [Category] Improvement // [Description] Remove TODO comments. // [Files] usbsetup.c, xhci.c, usbmass.c, usbCCID.c, usb.c, uhci.c, // syskbc.c, usbport.c, usbbus.c, uhcd.c, UsbBotPeim.c, PeiXhci.c, // PeiEhci.c // // 154 4/30/14 5:25a Wilsonlee // [TAG] EIP164842 // [Category] Improvement // [Description] Check if the devices have put into to our queue before // we put them. // [Files] UsbInt13.c, amiusb.c, ehci.c, ohci.c, usb.c, usbdef.h, // usbmass.c, xhci.c, amiusbhc.c, efiusbmass.c, uhcd.c, usbbus.c, usbsb.c // // 153 4/30/14 1:59a Wilsonlee // [TAG] EIP162993 // [Category] Improvement // [Description] We need to return success on INT 13 func 2 even if // there is no media. // [Files] usbmass.c, UI13.bin, Bfiusb.asm // // 152 4/29/14 8:55p Wilsonlee // [TAG] EIP165610 // [Category] Improvement // [Description] We still need to try readformatcapacity command even if // the subclass isn't UFI. // [Files] usbmass.c // // 151 4/29/14 8:47p Wilsonlee // [TAG] EIP152539 // [Category] Improvement // [Description] If the pervious device status is that media not present // and current device status comes as media present, modified the code to // report as media changed along with current status in the usbmass.c. // [Files] usbmass.c // // 150 4/07/14 2:07a Wilsonlee // [TAG] EIP156126 // [Category] Bug Fix // [Severity] Important // [Symptom] The power Format of UEFI can not be identified when we // install OS from USB CD-ROM. // [RootCause] The media information is incorrect when we install // BlockIoProtocol for usb CD / DVD devices. // [Solution] Get the media status before we install BlockIoProtocol. // [Files] usbmass.c, usbdef.h, efiusbmass.c // // 149 4/03/14 3:32a Wilsonlee // [TAG] EIP161240 // [Category] Improvement // [Description] Use Div64 if variables is UINT64. // [Files] usbmass.c // // 148 2/25/14 10:15p Wilsonlee // [TAG] EIP155805 // [Category] Bug Fix // [Severity] Minor // [Symptom] WinCE loader can't boot. // [RootCause] It can't boot if the mass storage doesn't have validate // partition table. // [Solution] We should set the type to FORCED_FDD if it's not a Floppy // and doesn't have validate partition table. // [Files] usbmass.c // // 147 12/23/13 1:56a Ryanchou // [TAG] EIP147532 // [Category] Bug Fix // [Severity] Normal // [Symptom] Dynamic DVD Insertion failed to Read the files // [RootCause] The Last Block is not updated properly when the new CD is // inserted. // [Solution] Update geometry if media is changed. // [Files] usbmass.c // // 146 12/15/13 10:16p Wilsonlee // [TAG] EIP136594 // [Category] New Feature // [Description] Support 64 bits LBA of usb mass storages. // [Files] Bfiusb.asm, Bfiusb.equ, UsbInt13.c, UsbInt13.h, amiusb.c, // usbdef.h, usbmass.c, UsbMass.h, efiusbmass.c, UI13.bin // // 145 10/20/13 11:32p Wilsonlee // [TAG] EIP139719 // [Category] Improvement // [Description] Ignore the bulk data if the status transport causes // time out. // [Files] usbmass.c // // 144 9/04/13 5:35a Wilsonlee // [TAG] EIP135036 // [Category] Bug Fix // [Severity] Normal // [Symptom] MultilUN deviices don't install successfully after hotplug // in shell. // [RootCause] We skip to get maximum LUN if this mass storage is // already registered. // [Solution] Get maximum LUN even if this mass storage is already // registered. // [Files] usbmass.c // // 143 9/04/13 4:49a Wilsonlee // [TAG] EIP133270 // [Category] Bug Fix // [Severity] Minor // [Symptom] Sony MS card reader sometimes cause system hang at 0xD5. // [RootCause] This device may return the wrong data when we send "read // format capacities" command. // [Solution] Return error if capacity list header is wrong. // [Files] usbmass.c // // 142 8/23/13 5:41a Ryanchou // [TAG] EIP131624 // [Category] Bug Fix // [Severity] Normal // [Symptom] USB mass storage configured fails // [RootCause] USB Mass Storage driver canot find the correct DeviccInfo // structure if it is a multiple interface device and the first interface // is not mass storage class // [Solution] Compare the DeviceInfo pointer to find the correct one, // not device address // [Files] usbmass.c // // 141 8/02/13 6:17a Ryanchou // // 140 7/29/13 5:21a Roberthsu // [TAG] EIP126741 // [Category] Bug Fix // [Severity] Normal // [Symptom] Cannot boot to uefi usb device with Sophos software. // [RootCause] When boot into tool. Ownership to os event occur.Usb // will disconnect device.And record this disconnect event. Then ownership // to bios,bios will connect all device.Run legacy to efi function. Bios // run disconnect event first.Then reconnect device.Because usb key behind // hub. So usb key disconnect also. // [Solution] Check device when device reconnect.If device and port // number the same.Use the same device info. // [Files] usb.c,usbmass.c,efiusbmass.c,uhcd.c // // 139 7/23/13 11:50a Pats // [TAG] EIP128964 // [Category] Bug Fix // [Severity] Minor // [Symptom] Int 13 Function 08 doesn't work right for USB mass storage // devices. // [RootCause] The default Head and Sector values for USB mass storage // devices are fixed, resulting in a Cylinder value that is too large for // the CHS format, when the device is over 2095104 sectors in size. // [Solution] Modify function USBMassSetDefaultGeometry() to use Head and // Sector values based ot total size. // [Files] usbmass.c // // 138 7/23/13 2:14a Wilsonlee // [TAG] EIP127941 // [Category] Improvement // [Description] Replace UI13HDDFunc08 with UI13FDDFunc08 if the media // descriptor is a fixed disk. // [Files] UsbInt13.h, UsbInt13.c, usbmass.c, usbdef.h, Bfiusb.asm, // Bfiusb.equ // // 137 7/03/13 4:48a Ryanchou // [TAG] EIP127800 // [Category] Improvement // [Description] Add non-bootable device type handing // [Files] usbmass.c, efiusbmass.c // // 136 3/19/13 3:59a Ryanchou // [TAG] EIP118177 // [Category] Improvement // [Description] Dynamically allocate HCStrucTable at runtime. // [Files] usb.sdl, usbport.c, usbsb.c, amiusb.c, ehci.c, ohci.c, // syskbc.c, sysnokbc.c, uhci.c, usb.c, usbCCID.c, usbdef.h, usbhid.c, // usbhub.c, usbmass.c, usbrt.mak, usb.sd, amiusbhc.c, efiusbccid.c, // efiusbhid.c, efiusbmass.c, efiusbms.c, uhcd.c, uhcd.h, uhcd.mak, // usbmisc.c, usbsrc.sdl // // 135 3/08/13 4:04a Roberthsu // [TAG] EIP113379 // [Category] Bug Fix // [Severity] Normal // [Symptom] USB MBR data read with 125MB USB key will get wrong // value // [RootCause] When device emu force floppy.Read command will clear // some information when read mbr. // [Solution] If device emu force floppy.Only change mbr data when // legacy. // [Files] usbmass.c // // 134 1/22/13 5:10a Wilsonlee // [TAG] EIP110635 // [Category] Bug Fix // [Severity] Minor // [Symptom] ReadOnly attribute is not properly updated for USB FDD. // [RootCause] The Media change status never gets refelected in // AmiUsbBlkIoReadWrite function. // [Solution] We should pass this information if the media has changed. // [Files] usbmass.c // // 133 1/22/13 3:09a Wilsonlee // [TAG] EIP112938 // [Category] Improvement // [Description] Create a header file for usb mass storage driver. // [Files] UsbMass.h, usbmass.c, usbdef.h, amiusb.c, efiusbmass.c // // 132 1/22/13 2:38a Wilsonlee // [TAG] EIP110305 // [Category] Improvement // [Description] Set the device address after we send the first // get-device-descriptor command. // [Files] usbmass.c, usb.c, usbdef.h, usbbus.c, efiusbmass.c, uhcd.c, // usbport.c // // 131 1/11/13 4:15a Ryanchou // [TAG] EIP102491 // [Category] Improvement // [Description] Synchronized with Aptio V USB module // [Files] usbport.c, usbsb.c, ehci.c, ehci.h, ohci.c, ohci.h, uhci.h, // usb.c, usbdef.h, usbhid.c, usbhub.c, usbkbd.c, usbkbd.h, usbmass.c. // usbms.c, usbpoint.c, xhci.h, usb.sd, amiusbhc.c, componentname.c, // efiusbkc.c, efiusbmass.c, uhcd.c, uhcd.h, usbbus.c, usbbus.h, usbmisc.c // // 130 12/24/12 1:43a Roberthsu // [TAG] EIP107198 // [Category] Bug Fix // [Severity] Normal // [Symptom] Run gdisk.exe fail // [RootCause] Device no media, gdisk call int13 get worng geometry. // [Solution] If device no present.Do not return geometry. // [Files] usbmass.c // // 129 11/10/12 6:39a Ryanchou // [TAG] EIP99431 // [Category] Bug Fix // [Severity] Minor // [Symptom] Cannot use the UsbIo's UsbAsyncInterruptTransfer for // keyboard input // [RootCause] Stopping EFI USB keyboard driver does not stop the // endpoint polling, then application calls UsbAsyncInterruptTransfer, // error will be returned. // [Solution] Stops endpoint polling and release resource when // disconnecting the device driver. And improve the // UsbSyncInterruptTransfer. // [Files] amiusb.c, amiusb.h, ehci.c, ohci.c, uhci.c, usb.c, // usbCCID.c, usbdef.h, usbhub.c, usbkbd.c, usbmass.c, usbms.c, // usbpoint.c, amiusbhc.c, efiusbhid.c, usbbus.c, usbbus.h // // 128 10/03/12 5:40a Wilsonlee // [TAG] EIP101623 // [Category] Bug Fix // [Severity] Minor // [Symptom] Fingerprint reader causes system waiting a long period at // PC B4. // [RootCause] The fingerprint reader returns sense key 0x02 instead of // 0x00 if it doesn't have error sense key for request sense command. // Which causes our code to repeatly wait for correct sense key. // [Solution] We should send the request sense command only if the CSW // is failed. However, current architecture has side-effect with this // method. So we skip the sense key 0x02 as a workaround here. // [Files] usbmass.c // // 127 9/28/12 2:38a Wilsonlee // [TAG] EIP93154 // [Category] Improvement // [Description] Change the unit of the FixedDelay from 15 us to 1 us. // [Files] amiusb.h, xhci.c, ehci.c, ohci.c, uhci.c, usb.c, usbCCID.c, // usbmass.c, usbhub.c, elib.c // // 126 9/04/12 8:03a Wilsonlee // [TAG] EIP99882 // [Category] New Feature // [Description] Add the usb setup item and usbpolicyprotocol to enable // or disable the usb mass storage driver. // [Files] UsbPolicy.h, usb.uni, usb.sd, usbmass.c, usbdef.h, // efiusbmass.c, usbport.c, uhcd.c // // 125 8/13/12 2:10a Roberthsu // [TAG] EIP94060 // [Category] Bug Fix // [Severity] Normal // [Symptom] USB key can not boot to DOS after Ctrl+Alt+Del // [RootCause] Because some device does not support mode sense // command. // [Solution] Send mode sense command when device type is UFI . // [Files] usbmass.c // // 124 7/12/12 2:39a Roberthsu // [TAG] EIP93460 // [Category] Improvement // [Description] Add token decide mass available under efi application // when legacy support disabled. // [Files] usb.sd,usb.uni,usbmass.c,usbsrc.sdl // // 123 6/28/12 10:21p Wilsonlee // [TAG] EIP90503 // [Category] Bug Fix // [Severity] Minor // [Symptom] Plug USB card reader cause time too long to boot // [RootCause] t sometimes happens "STALL" when data transport, then the // next command will causes device timeout (20 seconds). // [Solution] We perform reset recovery if there is the second "STALL" // when we attempt to read CSW from Bulk-in endpoint. // [Files] usbmass.c // // 122 6/14/12 2:59a Ryanchou // [TAG] EIP91363 // [Category] Improvement // [Description] Correct the initial value of variable "bRetValue" in // USBMassReadSector. // [Files] usbmass.c // // 121 5/03/12 4:36a Ryanchou // [TAG] EIP88240 // [Category] Bug Fix // [Severity] Minor // [Symptom] Disconnect and Connect USB Mass Driver will cause system // hang up. // [RootCause] The data toggle is not sync with device. // [Solution] Remove the code that reset data toggle in // USBMassConfigureStorageDevice. // [Files] usbmass.c // // 120 5/02/12 8:12a Wilsonlee // [TAG] EIP86793 // [Category] New Feature // [Description] Add the SDL token "USB_MASS_EMULATION_FOR_NO_MEDIA" for // determine the USB mass storage device emulation type without media. // [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl // // 119 4/10/12 9:51p Wilsonlee // [TAG] EIP84684 // [Category] Bug Fix // [Severity] Minor // [Symptom] Access SD Card In Auto Mode Test Fail - 1APUY012 BQA (F1) // [RootCause] Usb module token MAX_SIZE_FOR_FLOPPY_EMULATION // redefinition. // [Solution] Change the token name to // MAX_SIZE_FOR_USB_FLOPPY_EMULATION. // [Files] usbmass.c, usbsrc.sdl // // 118 4/06/12 5:01a Ryanchou // [TAG] EIP83321 // [Category] Bug Fix // [Severity] Normal // [Symptom] System hangs at checkpoint 0xBd with specific USB key. // [RootCause] The device report itself as floppy after reset, the // subclass is UFI device and protocol is CBI with command completion // interrupt, but there is the interrupt endpoint in the configuration // descriptor. // [Solution] Check if the interrupt is invalid, if it is invalid, skip // the status transport. // [Files] usbmass.c // // 116 4/05/12 7:28a Wilsonlee // [TAG] EIP86125 // [Category] Improvement // [Description] Clear the flag ¡§USB_MASS_MEDIA_CHANGED¡¨when the // sensekey is 0. // [Files] usbmass.c // // 115 3/20/12 10:34p Wilsonlee // [TAG] EIP83295 // [Category] Bug Fix // [Severity] Normal // [Symptom] System will hang at B2 when do S3/S4 long run test or DOS // reboot test. // [RootCause] It causes the stack problem when we call // IsUSBKeyboardBufferEmpty function. // [Solution] Change to use pointer as parameter to // IsUSBKeyboardBufferEmpty function. // [Files] efiusbkb.c, efisubkb.h, usbmass.c, ehci.c // // 114 1/14/12 6:39a Wilsonlee // [TAG] EIP80382 // [Category] New Feature // [Description] Add the SDL token "USB_MASS_EMULATION_BY_SIZE" for // determine the USB mass storage device emulation type by size only. // [Files] usbmass.c, usbport.c, uhcd.c, usbdef.h, usbsrc.sdl // // 113 1/13/12 4:25a Ryanchou // [TAG] EIP47348 // [Category] New Feature // [Description] Support for USB Port Reset function. // [Files] amiusb.c, amiusb.h, amiusbhc.c, uhci.c, usb.c, usbbus.c, // usbbus.h, usbmass.c // // 112 1/06/12 12:58a Rajeshms // [TAG] EIP62737 // [Category] Improvement // [Description] Added USB Device number into USB mass device name // string based on SDL Token. // [Files] Usb.sdl, usbport.c, usbmass.c, UsbInt13.h, UsbInt13.c, // usbbus.c, Bfiusb.equ // // 111 11/08/11 7:39a Ryanchou // [TAG] EIP71262 // [Category] Bug Fix // [Severity] Minor // [Symptom] Sanyo ICR-PS401RM cause system hang at PC B4 // [RootCause] The data length of Read Format Capacity command returned // exceed allocation length. // [Solution] Increase the allocation length to avoid this issue. // [Files] usbmass.c // // 110 11/08/11 2:23a Ryanchou // [TAG] EIP63706 // [Category] Improvement // [Description] Filter out the character if it is invisible. // [Files] usbmass.c // // 109 11/05/11 7:36a Wilsonlee // [TAG] EIP64781 // [Category] New Feature // [Description] Added SDL token // SKIP_CARD_READER_CONNECT_BEEP_IF_NO_MEDIA that skip the connect beep if // no media present in USB card reader. // [Files] usbport.c, usbmass.c, usb.c, usbdef.h, uhcd.c, usbsrc.sdl // // 108 10/24/11 4:55a Ryanchou // [TAG] EIP70814 // [Category] Improvement // [Description] Read a block size each time to avoid out of memory // problem. // [Files] usbmass.c // // 107 8/08/11 5:18a Ryanchou // [TAG] EIP60561 // [Category] New Feature // [Description] Add USB timing policy protocol for timing override. // [Files] ehci.c, guids.c, ohci.c, uhcd.c, uhci.c usb.c, usbdef.h, // usbhub.c, usbmass.c, UsbPolicy.h, usbport.c usbsrc.sdl // // 106 7/12/11 11:34p Ryanchou // [TAG] EIP61388 // [Category] Bug Fix // [Severity] Normal // [Symptom] FreeDOS will hang at USB storage device while selecting Force // FDD. // [RootCause] Hidden sector is not 0. // [Solution] Force #of hidden sectors to 0 // [Files] usbmass.c // // 105 7/12/11 6:32a Ryanchou // [TAG] EIP63308 // [Category] Bug Fix // [Severity] Normal // [Symptom] POST hang with USB WiMAX Dongle plugged on USB3.0 port // [RootCause] The device always return invalid Command Status Wrapper. // [Solution] Do nothing if CSW is invalid. // [Files] usbmass.c // // 104 6/27/11 12:33a Ryanchou // Correct EIP51158 changes. // // 103 6/22/11 1:45a Ryanchou // [TAG] EIP59738 // [Category] Improvement // [Description] Support Block size other than 512 bytes USB HDD in UEFI // mode. // [Files] efiusbmass.c, uhci.c, usb.c, usbdef.h, usbmass.c // // 102 6/22/11 12:43a Ryanchou // [TAG] EIP51158 // [Category] Bug Fix // [Severity] Normal // [Symptom] Samsung i7500 mobile phone can't be recognized // [RootCause] The data packet length of UFI command is not same as SCSI // command, the device stalls the UFI command. // [Solution] Use SCSI command if the subclass code indicate the device // support SCSI command set. // [Files] usbmass.c // // 101 6/21/11 11:02a Ryanchou // [TAG] EIP59579 // [Category] Improvement // [Description] USB device information structure should be reserved for // the UsbIO to use even install driver fail. // [Files] usbmass.c, usbkbd.c, usbms.c // // 100 6/21/11 10:54a Ryanchou // [TAG] EIP60588 // [Category] Bug Fix // [Severity] Normal // [Symptom] MS-DOS 7.1 boot by USB 2.0 Flash Drive will crash system at // black screen. // [RootCause] The LBA that will be read is greater than the max LBA. // [Solution] Set the the starting LBA address to (the last LBA - number // of blocks to process) if dStartLBA is greater than (dMaxLba - // wNumBlks). // [Files] usbmass.c // // 99 5/03/11 10:11a Ryanchou // [TAG] EIP54283 // [Category] Improvement // [Description] Follow XHCI spec ver 1.0 section 4.6.8 to recovery // endpoint halt. // [Files] ehci.c, ohci.c, uhci.c, usbdef.h, usbmass.c, xhci.c // // 98 5/03/11 8:29a Ryanchou // [TAG] EIP43711 // [Category] Bug Fix // [Severity] Normal // [Symptom] USB-FDD will be recognized as USB-HDD in BIOS Setup. // [RootCause] The media reports valid partition which is same as HDD. // [Solution] Check the device class to fix this issue. // [Files] usbmass.c // // 97 5/03/11 7:51a Ryanchou // [TAG] EIP53416 // [Category] Bug Fix // [Severity] Normal // [Symptom] Iomega Zip250 hang at StatusCode 0xB4 // [RootCause] Fail to calculate CHS values from max LBA if device is // not ready. // [Solution] Should not get device geometry if device is not ready. // [Files] usbmass.c // // 96 4/06/11 4:29a Ryanchou // [TAG] EIP57573 // [Category] Bug Fix // [Severity] Important // [Symptom] Can't boot to USB 3.0 device // [RootCause] Some device haven't indicate Test Unit Ready command // failure in the CSW status. // [Solution] Undo the EIP55440 changes and send Test Unit Ready command // again if the Sense key is MEDIUM ERROR. // [Files] usbmass.c // // 95 3/30/11 8:15a Ryanchou // [TAG] EIP54126 // [Category] Bug Fix // [Severity] Normal // [Symptom] Sometimes system hangs at checkpoint 0xB4. // [RootCause] The bLength field of configuration descriptor is zero. // [Solution] Check wether bLength field is zero before paring next // descriptor. // [Files] usb.c, usbbus.c, usbhub.c, usbkbd.c, usbmass.c, usbms.c // // 94 3/26/11 4:13a Ryanchou // [TAG] EIP55440 // [Category] Improvement // [Description] Request Sense command should be sent only if the CSW of // the storage command isn't Success. // [Files] usbmass.c // // 93 3/16/11 11:45p Ryanchou // [TAG] EIP52719 // [Category] Bug Fix // [Severity] Normal // [Symptom] USB 3.0 HDD is detected as USB FDD // [RootCause] Fail to read MBR while configure the device. // [Solution] Retry 10 times. // [Files] usbmass.c // // 92 1/25/11 5:30p Olegi // [TAG] EIP52205 // [Category] Improvement // [Description] System can not boot from a certain FD image. Changed // MBR validation routine to check the valid partition(s) size. // [Files] usbmass.c // // 91 12/28/10 4:45a Ryanchou // [TAG] EIP50968 // [Category] Bug Fix // [Severity] Normal // [Symptom] BIOS can't boot to WD My Book 3.0. // [RootCause] The USB 3.0 device returns sense data 0x800000 when // device is ready. // [Solution] Ignore the ASC and ASCQ, check the Sense key only. // [Files] usbmass.c, xhci.h // // 90 12/27/10 12:44a Ryanchou // [TAG] EIP50458 // [Category] Improvement // [Description] If pre skip and post skip is not zero, allocate a // buffer for data transfer. // [Files] usbmass.c // // 89 12/12/10 11:14p Ryanchou // [TAG] EIP48166 // [Category] Bug Fix // [Severity] Minor // [Symptom] POST takes a long time if USB ODD is connected. // [RootCause] USB driver determines media not present when Sense Data // is 0x003A02. the USB ODD returns 0x013A02 for no media condition. // [Solution] Check Sense key and ASC only for no media condition. // // 88 11/11/10 8:50a Ryanchou // [TAG] EIP47638 // [Category] Bug Fix // [Severity] Minor // [Symptom] The command block of read command is invalid // [RootCause] The command block is destoyed in USBMassSendBOTCommand. // [Solution] Reinitialize the command block. // [Files] usbmass.c // // 87 10/28/10 12:25a Ryanchou // EIP45643: Fixed system hangs when hot plug USB mass storage quickly on // USB 3.0 port. // // 86 10/21/10 10:13a Ryanchou // EIP45121: Added xHCI Supported Protocol Capability and fix the problem // that USB 3.0 device can't be detected. // // 85 10/20/10 9:16a Ryanchou // EIP44239: Delay for the device to get ready if sense key is 0x06. // // 84 10/20/10 12:56a Ryanchou // EIP45828: If the flag DEV_INFO_MASS_DEV_REGD is set, check if the // controller type is difference between old DevInfo and new one. // // 83 10/12/10 2:13a Rameshr // [TAG]- EIP 44585 // [Category]-IMPROVEMENT // [Description]- Number of maximum supported USB Mass Storage device // increased from 8 to 16. // [Files]- Uin13.bin, UsbPort.c, UsbInt13.h, Usb.c, Usbdef.h, Uasbmass.c, // Usb.sd, usb.uni, UsbSetup.c, UsbSrc.sdl, UsbPolicy.h // // 82 9/07/10 4:34a Tonylo // Remove user tags for coding standard. // // 81 9/01/10 8:32a Ryanchou // EIP42297: Fixed boot to hot plug USB HDD fail. // // 80 8/18/10 4:23p Olegi // Klockwork related fixes; EIP37978 // // 79 7/15/10 4:40a Tonylo // EIP21649 - USB mass storage device still appear in BBS menu when USB // legacy support is disabled. // // 78 6/22/10 9:31a Ryanchou // EIP39374: Fixed USB key hot plug issue. // // 77 6/10/10 11:27p Ryanchou // The USB0089 patch is for card reader, floppy doesn't need. // // 76 5/05/10 12:02p Olegi // Send Start Unit command to the device when sense data is 0x020402. // EIP36909 // // 75 4/12/10 4:17p Olegi // Slow MSD may return invalid block size and max lba when device is not // ready. Check the value of block Size and max lba returned by Read // Capacity Command. EIP37167. // // 74 3/02/10 9:52a Olegi // Bugfix in USBMassUpdateCHSFromBootRecord, EIP34794. // // 73 2/08/10 10:03a Olegi // EIP33381: Implement multiple bulk endpoint in UsbIoProtocol. // // 72 12/18/09 12:12p Olegi // Added SDL token USB_START_UNIT_BEFORE_MSD_ENUMERATION that controls the // execution of bugfix for EIP25229. Disable by default. // // 71 11/30/09 11:33a Olegi // Change in USBMassGetFreeMassDeviceInfoStruc, zero device info structure // can not be returned. EIP27635. // // 70 10/02/09 10:49a Olegi // Code cleanup. // // 69 9/09/09 11:28a Olegi // Increased R/W command timeout delay from 10 to 20 swconds. EIP#24326 // // 68 8/26/09 11:52a Olegi // xUbuntu on USB fix: Start unit command before access it. EIP#25229 // (Core8 EIP#23581) // // 67 6/05/09 2:34p Olegi // Do not enumerate device if it is not a CD-ROM and has the block size // different from 512 Bytes. EIP#15595, iPod nano makes POST hang. // // 66 6/04/09 3:46p Olegi // EIP21970: support for hotplug drives, re-inserting them to a different // controller/port. // // 65 6/01/09 10:02a Olegi // Fix for EIP#21681: The problem is in the Read Format Capacities command // (0x23), the DataTransferLength is 0x40 in the CBW, but the Allocation // Length is 0x80 in the CDB. Thus, the driver return Status = Phase // Error. // // 64 5/21/09 5:12p Olegi // Added HDD hotplug support. // // 63 5/15/09 5:50p Olegi // EIP#21179 - failure of Transcend Card reader configuration fix. // // 62 4/24/09 9:32a Olegi // Bugfix for EIP#20863. // // 61 2/17/09 9:18a Olegi // // 60 1/29/09 2:40p Olegi // Added a check for Mass Storage device limit before creating a new LUN // device. // // 59 1/23/09 10:17a Olegi // Modified the resolution of EIP#18553 // // 58 1/16/09 4:04p Olegi // - Removed the limitation of MAX_BULK_DATA_SIZE in // USBMassIssueBulkTransfer. // - Modified USBMassCheckDeviceReady, EIP18553. // // 57 11/20/08 1:12p Olegi // EIP#17634 fix: added StartStopUnit command if TestUnitReady returns the // value of 0x020402. // Note: current fix is done only for the device VID 0x0DC4 DID 0x0207; in // future we may want to extend this fix for other devices. This will // require additional testing. // // 56 11/06/08 11:40a Olegi // Fixed device configuration for multi-LUN devices. // // 55 9/05/08 5:39p Olegi // // 54 9/05/08 4:22p Olegi // fpCallbackNotify4 is replaced with the call within SMI. // // 53 8/25/08 12:09p Olegi // // 52 8/25/08 12:00p Olegi // Added USBMassReadCapacityBlockSizePatch function. // // 51 8/21/08 12:28p Olegi // Modification in CreateLogicalUnits function: // - At the point of the new unit creation, the Lun0 device might be // locked by the bus driver (USBBUS.usbhc_on_timer); clear the lock // indicator for the new LUN. // // 50 8/13/08 5:32p Olegi // // 49 8/13/08 5:27p Olegi // Bugfix in USBMassGetFormatType. // // 48 7/04/08 1:08p Olegi // Added REQUEST_SENSE command in the sequence of failed MODE_SENSE. // // 47 6/27/08 5:54p Olegi // Mass Device name field is populated in DEV_INFO structure. // // 46 6/13/08 3:54p Olegi // Additions related to 720KB floppy support. // // 45 5/16/08 12:01p Olegi // Compliance with AMI coding standard. // // 44 1/30/08 12:43p Olegi // - change in USBMassGetDeviceGeometry that returns default geometry for // those devices with BlockSize reported as 0. // - change in USBMassGetDeviceInfo that reports PCI bus/dev/function. // // 43 10/15/07 5:15p Olegi // - Modification in USBMassCreateLogicalUnits that allows different // emulation type for different LUNs // - Bugfix in USBMassGetFormatType that clears bHiddenSectors field in // multiple-LUN device // // 42 9/17/07 3:33p Olegi // // 41 7/10/07 10:25a Olegi // // 40 7/09/07 2:11p Olegi // Changed the maximum data size of the BulkTransfer from 1kB to 64kB. // // 39 6/14/07 12:28p Olegi // // 38 5/29/07 6:11p Olegi // // 37 5/24/07 4:09p Olegi // // 36 5/18/07 10:53a Olegi // Bugfix in USBMassGetDeviceGeometry that used the device ID instead of // DEV_INFO index for USBMassGetDeviceStatus call. // // 35 5/05/07 1:54p Olegi // Persistent DOS drives. // // 34 4/18/07 2:51p Fredericko // Bugfix in USBMassUpdateDeviceGeometry, removed redundant code that // corrupted memory. // // 32 4/17/07 11:05a Olegi // // 30 3/29/07 6:40p Olegi // Modified USBMassUpdateDeviceGeometry to take care of USB floppy drive // with no floppy in it. // // 29 3/20/07 12:19p Olegi // // 28 2/27/07 10:45a Olegi // // 27 12/22/06 4:05p Olegi // Timeout implementation. // // 26 12/20/06 3:38p Olegi // // 25 12/20/06 2:30p Olegi // // 24 12/12/06 12:32p Olegi // // 22 11/09/06 4:57p Olegi // // 18 4/14/06 6:39p Olegi // Conversion to be able to use x64 compiler. // // 17 3/21/06 12:01p Olegi // // 16 3/20/06 3:37p Olegi // Version 8.5 - x64 compatible. // // 15 3/16/06 2:33p Olegi // // 14 3/06/06 6:25p Olegi // Lun devices support modifications: supported using the index in // DEV_INFO table, not through dedicated massLun table. // // 13 1/11/06 11:52a Olegi // Setup related modifications. // // 12 12/19/05 10:17a Olegi // DeviceDelayCount is Setup driven. // // 11 12/01/05 5:49p Olegi // // 10 11/10/05 11:11a Olegi // // 9 11/04/05 6:22p Olegi // Multiple LUN support. // // 8 10/17/05 5:12p Olegi // // 7 9/22/05 6:28p Olegi // // 6 9/15/05 6:10p Andriyn // Fix: Mass Storage name gets corrupted in setup // // 5 8/23/05 5:53p Olegi // Latest USB mass storage updates from AMIBIOS USB module are applied. // // 4 6/03/05 9:31a Olegi // MediaId update moved to EFI mass strorage driver. // // 3 5/17/05 7:51p Andriyn // USB BUS pre-release // // 2 4/26/05 5:09p Olegi // Modifications in USBMassRWVCommand, USBMassCheckDeviceReady to properly // handle USB FDDs with no media in them. // // 1 3/28/05 6:20p Olegi // // 1 3/15/05 9:23a Olegi // Initial VSS check-in. // //**************************************************************************** // //----------------------------------------------------------------------------- // // Name: UsbMass.c // // Description: AMI USB Mass Storage support implementation // //----------------------------------------------------------------------------- // #include "amidef.h" #include "usbdef.h" #include "amiusb.h" #include "UsbMass.h" #if USB_RUNTIME_DRIVER_IN_SMM #include #endif extern USB_GLOBAL_DATA *gUsbData; extern BOOLEAN gCheckUsbApiParameter; VOID USBMassInitialize(VOID); UINT8 USBMassCheckForStorageDevice(DEV_INFO*, UINT8, UINT8, UINT8); DEV_INFO* USBMassConfigureStorageDevice(HC_STRUC*, DEV_INFO*, UINT8*, UINT16, UINT16); UINT8 USBMassDisconnectStorageDevice(DEV_INFO*); UINT16 USBMassSendCBICommand(DEV_INFO*, MASS_XACT_STRUC*); UINT32 USBMassProcessBulkData(DEV_INFO*, MASS_XACT_STRUC*); UINT8 USBMassConsumeBulkData(DEV_INFO*,UINT8,UINT16); UINT32 USBMassIssueBOTTransaction(DEV_INFO*, MASS_XACT_STRUC*); VOID USBMassClearBulkEndpointStall(DEV_INFO*, UINT8); VOID USBMassBOTResetRecovery(DEV_INFO*); UINT16 USBMassSendBOTCommand(DEV_INFO*, MASS_XACT_STRUC*); UINT8 USBMassGetBOTStatus(DEV_INFO*, MASS_XACT_STRUC*); UINT16 USBMassCBIGetStatus(DEV_INFO*); UINT32 USBMassIssueCBITransaction(DEV_INFO*, MASS_XACT_STRUC*); UINT8 USBMassReadCapacity10Command(DEV_INFO*); UINT32 USBMassCheckDeviceReady(DEV_INFO*); UINT32 USBMassRequestSense(DEV_INFO* fpDevInfo); VOID USBMassSenseKeyParsing(DEV_INFO* , UINT32); MASS_INQUIRY *USBMassInquiryCommand(DEV_INFO*); UINT8 USBMassUpdateDeviceGeometry( DEV_INFO* fpDevInfo ); UINT16 USBMassBOTGetMaxLUN(DEV_INFO*); VOID USBMassIdentifyDeviceType(DEV_INFO*, UINT8*); UINT32 USBMassIssueBulkTransfer(DEV_INFO*, UINT8, UINT8*, UINT32); VOID iPodShufflePatch(MASS_GET_DEV_INFO*); VOID USBMassUpdateCylinderInfo(DEV_INFO*, UINT64); UINT8 USBMassSetDefaultGeometry(DEV_INFO*, UINT64); UINT8 USBMassValidatePartitionTable(MASTER_BOOT_RECORD*, UINT64, MBR_PARTITION*); UINT16 USBMassSetDefaultType(DEV_INFO*, UINT64); VOID USBMassGetPhysicalDeviceType(DEV_INFO*, UINT8*); UINT8 USB_SetAddress(HC_STRUC*, DEV_INFO*, UINT8); UINT32 dabc_to_abcd(UINT32); DEV_INFO* USBGetProperDeviceInfoStructure(DEV_INFO*, UINT8); UINT32 USBMassTestUnitReady(DEV_INFO*); VOID StoreUsbMassDeviceName(DEV_INFO*, UINT8*); extern VOID AddPortNumbertoDeviceString(DEV_INFO*); UINT8 USBMassGetConfiguration(DEV_INFO*); VOID MemFill (UINT8*, UINT32, UINT8); VOID MemCopy (UINT8*, UINT8*, UINT32); VOID* USB_MemAlloc (UINT16); DEV_INFO* USB_GetDeviceInfoStruc(UINT8, DEV_INFO*, UINT8, HC_STRUC*); MASS_INQUIRY* USBMassGetDeviceParameters(DEV_INFO*); UINT8 USB_MemFree (VOID*, UINT16); VOID FixedDelay(UINTN); VOID SpeakerBeep (UINT8, UINT16, HC_STRUC*); //(EIP64781+) static char* IOMegaZIPString = "IOMEGA ZIP"; #define IOMegaZIPStringLength 11 static char* MSysDiskOnKeyString = "M-Sys DiskOnKey"; #define MSysDiskOnKeyStringLength 17 BOOLEAN CheckDeviceLimit(UINT8); VOID USBMassFillDriverEntries (DEV_DRIVER *fpDevDriver) { fpDevDriver->bDevType = BIOS_DEV_TYPE_STORAGE; fpDevDriver->bProtocol = 0; fpDevDriver->pfnDeviceInit = USBMassInitialize; fpDevDriver->pfnCheckDeviceType = USBMassCheckForStorageDevice; fpDevDriver->pfnConfigureDevice = USBMassConfigureStorageDevice; fpDevDriver->pfnDisconnectDevice = USBMassDisconnectStorageDevice; } // //--------------------------------------------------------------------------- // // FUNCTION: USBMassInitialize // // DESCRIPTION: This function initializes mass storage device related data // //--------------------------------------------------------------------------- // VOID USBMassInitialize () { // // Set default value for the delay. Selections are: 20,40,60,80 for 10,20,30,40 sec. // gUsbData->bUSBStorageDeviceDelayCount = (gUsbData->UsbMassResetDelay + 1)*10; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassCheckForStorageDevice // // DESCRIPTION: This routine checks for hub type device from the // interface data provided // // PARAMETERS: bBaseClass USB base class code // bSubClass USB sub-class code // bProtocol USB protocol code // // RETURN: BIOS_DEV_TYPE_STORAGE type on success or 0FFH on error // //---------------------------------------------------------------------------- // UINT8 USBMassCheckForStorageDevice ( DEV_INFO* DevInfo, UINT8 BaseClass, UINT8 SubClass, UINT8 Protocol ) { if (BaseClass != BASE_CLASS_MASS_STORAGE) { return USB_ERROR; } //(EIP99882+)> if (!gUsbData->UsbSetupData.UsbMassDriverSupport) { return USB_ERROR; } //<(EIP99882+) //Skip USB mass storage devices enumeration when legacy is disabled if (gUsbData->dUSBStateFlag & USB_FLAG_DISABLE_LEGACY_SUPPORT) { if (LEGACY_USB_DISABLE_FOR_USB_MASS) { //(EIP93469) return USB_ERROR; } } // // Base class is okay. Check the protocol field for supported protocols. // Currently we support CBI, CB and BOT protocols. // if ((Protocol != PROTOCOL_CBI) && (Protocol != PROTOCOL_CBI_NO_INT) && (Protocol != PROTOCOL_BOT)) { return USB_ERROR; } return BIOS_DEV_TYPE_STORAGE; } // //---------------------------------------------------------------------------- // Procedure: USBMassGetFreeMassDeviceInfoStruc // // Description: This function finds a free mass device info structure and // returns the pointer to it // // Input: None // // Output: Pointer to the Mass Device Info (0 on failure) // The number mass storage DeviceInfo structure (0-based) // //---------------------------------------------------------------------------- // DEV_INFO* USBMassGetFreeMassDeviceInfoStruc( DEV_INFO *DevInfo, UINT8 *Indx ) { DEV_INFO* Dev = &gUsbData->aDevInfoTable[1]; UINT8 Count; UINT8 MassDevIndx = 0; for (Count = 0; Count < (MAX_DEVICES-1); Count++, Dev++) { if (!(Dev->Flag & DEV_INFO_VALID_STRUC)) { continue; } if (Dev->bDeviceType == BIOS_DEV_TYPE_STORAGE) { MassDevIndx++; } if (Dev == DevInfo) { break; } } if (Count == (MAX_DEVICES-1)) { return NULL; } *Indx = MassDevIndx; return Dev; } // //---------------------------------------------------------------------------- // Procedure: USBMassFindFreeMassDeviceInfo // // Description: This function finds a free mass device info structure and // copies the current mass device info structure into it // // Input: Current mass device info structure // // Output: New mass device info // //---------------------------------------------------------------------------- // DEV_INFO* USBMassFindFreeMassDeviceInfo( DEV_INFO* Dev, UINT8 *EmulIndex ) { UINT8 Indx = 0; DEV_INFO *NewDev; // Get the free mass device info structure pointer NewDev = USBMassGetFreeMassDeviceInfoStruc(Dev, &Indx); if (NewDev == NULL) { return NULL; // No free entry found. } // Get the emulation type setup question associated with this device ASSERT(Indx>0 && Indx<17); if ((Indx == 0) || (Indx > 16)) { return NULL; } Dev->wEmulationOption = gUsbData->USBMassEmulationOptionTable[Indx-1]; USB_DEBUG(DEBUG_LEVEL_3, "USBMassFindFreeMassDeviceInfo-------- indx %d, emu %d\n", Indx, Dev->wEmulationOption); // Set default device type and emulation type to 0 Dev->bStorageType = 0; Dev->fpLUN0DevInfoPtr = 0; Dev->Flag |= DEV_INFO_DEV_PRESENT; *EmulIndex = Indx-1; return Dev; } // //---------------------------------------------------------------------------- // Procedure: USBMassCreateLogicalUnits // // Description: This function verifies the presence of logical units (LUN) // in the USB mass device and creates appropriate device info // structures for them // // Input: fpDevInfo - Device information structure pointer // bMaxLun - Maximum number of logical units present (non-ZERO) // // Output: USB_ERROR On error // USB_SUCCESS On successfull completion // //---------------------------------------------------------------------------- // UINT8 USBMassCreateLogicalUnits( DEV_INFO* DevInfo, UINT8 MaxLun, UINT8 EmulIndex ) { UINT8 Lun; DEV_INFO* NewDevInfo; MASS_INQUIRY *Inq; for (Lun = 1; Lun <= MaxLun; Lun++) { if (CheckDeviceLimit(BASE_CLASS_MASS_STORAGE) == TRUE) { break; } // // Get the proper device info structure // NewDevInfo = USBGetProperDeviceInfoStructure(DevInfo, Lun); if (!NewDevInfo) { return USB_ERROR; } // // Check whether this device is reconnected by checking the // valid structure flag // if ((NewDevInfo->Flag & DEV_INFO_MASS_DEV_REGD)) { // // Indicate device as connected // NewDevInfo->Flag |= DEV_INFO_DEV_PRESENT; // Change the parent HC number and port number in the existing DEV_INFO NewDevInfo->bHCNumber = DevInfo->bHCNumber; NewDevInfo->bHubDeviceNumber = DevInfo->bHubDeviceNumber; NewDevInfo->bHubPortNumber = DevInfo->bHubPortNumber; NewDevInfo->bEndpointSpeed = DevInfo->bEndpointSpeed; NewDevInfo->wEndp0MaxPacket = DevInfo->wEndp0MaxPacket; NewDevInfo->DevMiscInfo = DevInfo->DevMiscInfo; NewDevInfo->bDeviceAddress = DevInfo->bDeviceAddress; NewDevInfo->bBulkInEndpoint = DevInfo->bBulkInEndpoint; NewDevInfo->wBulkInMaxPkt = DevInfo->wBulkInMaxPkt; NewDevInfo->bBulkOutEndpoint = DevInfo->bBulkOutEndpoint; NewDevInfo->wBulkOutMaxPkt = DevInfo->wBulkOutMaxPkt; NewDevInfo->IntInEndpoint = DevInfo->IntInEndpoint; NewDevInfo->IntInMaxPkt = DevInfo->IntInMaxPkt; NewDevInfo->bPollInterval = DevInfo->bPollInterval; NewDevInfo->fpLUN0DevInfoPtr = DevInfo; } else { // This is different device, it was not reconnected // // Copy the old device info structure into the new one // MemCopy((UINT8*)DevInfo, (UINT8*)NewDevInfo, sizeof (DEV_INFO)); NewDevInfo->bLUN = Lun; // Change LUN number NewDevInfo->wEmulationOption = gUsbData->USBMassEmulationOptionTable[EmulIndex + Lun]; MemFill(NewDevInfo->DevNameString, 64, 0); // // Save the Lun0 device info pointer in the current LUN // NewDevInfo->fpLUN0DevInfoPtr = DevInfo; // // The Lun0 device might have been already locked by the // bus (USBBUS.usbhc_on_timer), clear it for current LUN. // NewDevInfo->Flag &= ~DEV_INFO_DEV_BUS; Inq = USBMassGetDeviceParameters(NewDevInfo); ASSERT(Inq); StoreUsbMassDeviceName(NewDevInfo, (UINT8*)Inq + 8); if (NewDevInfo->bStorageType == USB_MASS_DEV_CDROM) { USBMassGetConfiguration(NewDevInfo); } } if (gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) { if (!(NewDevInfo->Flag & DEV_INFO_IN_QUEUE)) { USB_SmiQueuePut(NewDevInfo); NewDevInfo->Flag |= DEV_INFO_IN_QUEUE; } } } return USB_SUCCESS; } VOID StoreUsbMassDeviceName( DEV_INFO *Device, UINT8 *Str ) { UINT8 i; UINT8 j; for (i = 0; i < 64; i++) { if (Device->DevNameString[i] != 0) { return; } } for (i = 0, j = 0; i < 32; i++) { if (*Str == 0) { Str++; j++; // supress leading zeroes } } for (i = 0; i < (32-j); i++, Str++) { // supress spaces if more than one if ((i>0) && (Device->DevNameString[i-1]==' ') && (*Str==' ')) { i--; continue; } //(EIP63706+)> // Filter out the character if it is invisible. if (((*Str != 0) && (*Str < 0x20)) || (*Str > 0x7E)) { i--; continue; } //<(EIP63706+) Device->DevNameString[i] = *Str; } // // Add Device number to the USB device string // #if USB_DIFFERENTIATE_IDENTICAL_DEVICE_NAME AddPortNumbertoDeviceString(Device); #endif } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassConfigureStorageDevice // // DESCRIPTION: This function checks an interface descriptor of a device // to see if it describes a USB mass device. If the device // is a mass storage device, then it is configured // and initialized. // // PARAMETERS: pHCStruc HCStruc pointer // pDevInfo Device information structure pointer // pDesc Pointer to the descriptor structure // wEnd End offset of the device descriptor // // RETURN: New device info structure, NULL on error // //---------------------------------------------------------------------------- // DEV_INFO* USBMassConfigureStorageDevice ( HC_STRUC* fpHCStruc, DEV_INFO* fpDevInfo, UINT8* fpDesc, UINT16 wStart, UINT16 wEnd) { UINT8 bTemp; UINT16 wRetValue; ENDP_DESC *fpEndpDesc; INTRF_DESC *fpIntrfDesc; UINT8 bMaxLUN; DEV_INFO* newDev; MASS_INQUIRY *inq; BOOLEAN checkFDDhotplug, checkCDROMhotplug, checkHDDhotplug; UINT8 EmulIndex; UINT8 i; //(EIP64781+) wRetValue = 0; bMaxLUN = 0; // // Set fpDevInfo->bDeviceType. This serves as a flag // that indicates a usable interface has been found in the current // configuration. This is needed so we can check for other usable interfaces // in the current configuration (composite device) without trying to search // in other configurations. // fpDevInfo->bDeviceType = BIOS_DEV_TYPE_STORAGE; fpDevInfo->fpPollTDPtr = 0; USB_DEBUG (DEBUG_LEVEL_3, "USBMassConfigureDevice ....\n"); bTemp = 0x03; // bit 1 = Bulk In, bit 0 = Bulk Out fpDevInfo->bBulkOutEndpoint = 0; fpDevInfo->bBulkInEndpoint = 0; fpDevInfo->IntInEndpoint = 0; fpIntrfDesc = (INTRF_DESC*)(fpDesc + wStart); fpDesc+=((CNFG_DESC*)fpDesc)->wTotalLength; // Calculate the end of descriptor block fpEndpDesc = (ENDP_DESC*)((char*)fpIntrfDesc + fpIntrfDesc->bDescLength); for( ;(fpEndpDesc->bDescType != DESC_TYPE_INTERFACE) && ((UINT8*)fpEndpDesc < fpDesc); fpEndpDesc = (ENDP_DESC*)((char*)fpEndpDesc + fpEndpDesc->bDescLength)){ if(!(fpEndpDesc->bDescLength)) { break; // Br if 0 length desc (should never happen, but...) } if( fpEndpDesc->bDescType != DESC_TYPE_ENDPOINT ) { continue; } if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) == EP_DESC_FLAG_TYPE_BULK) { // Bit 1-0: 10 = Endpoint does bulk transfers if(!(fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT)) { // // Bit 7: Dir. of the endpoint: 1/0 = In/Out // If Bulk-Out endpoint already found then skip subsequent ones // on the interface. // if (bTemp & 1) { fpDevInfo->bBulkOutEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_EP_NUM); fpDevInfo->wBulkOutMaxPkt = fpEndpDesc->wMaxPacketSize; bTemp &= 0xFE; USB_DEBUG(3, "bulk out endpoint addr: %x, max packet size: %x\n", fpDevInfo->bBulkOutEndpoint, fpDevInfo->wBulkOutMaxPkt); } } else { // // If Bulk-In endpoint already found then skip subsequent ones // on the interface // if (bTemp & 2) { fpDevInfo->bBulkInEndpoint = (UINT8)(fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_EP_NUM); fpDevInfo->wBulkInMaxPkt = fpEndpDesc->wMaxPacketSize; bTemp &= 0xFD; USB_DEBUG(3, "bulk in endpoint addr: %x, max packet size: %x\n", fpDevInfo->bBulkInEndpoint, fpDevInfo->wBulkInMaxPkt); } } } // // Check for and configure Interrupt endpoint if present // if ((fpEndpDesc->bEndpointFlags & EP_DESC_FLAG_TYPE_BITS) != EP_DESC_FLAG_TYPE_INT) { // Bit 1-0: 10 = Endpoint does interrupt transfers continue; } if (fpEndpDesc->bEndpointAddr & EP_DESC_ADDR_DIR_BIT ) { fpDevInfo->IntInEndpoint = fpEndpDesc->bEndpointAddr; fpDevInfo->IntInMaxPkt = fpEndpDesc->wMaxPacketSize; fpDevInfo->bPollInterval = fpEndpDesc->bPollInterval; USB_DEBUG(3, "interrupt in endpoint addr: %x, max packet size: %x\n", fpDevInfo->IntInEndpoint, fpDevInfo->IntInMaxPkt); } } // // Check the compatibility flag for LUN support // if (!(fpDevInfo->wIncompatFlags & USB_INCMPT_SINGLE_LUN_DEVICE)) { // // If it is a BOT device, get maximum LUN supported // if (fpDevInfo->bProtocol == PROTOCOL_BOT) { bMaxLUN = (UINT8)USBMassBOTGetMaxLUN(fpDevInfo); } } // // Check whether the device is already registered. If so, proceed with current // mass info structure // if (fpDevInfo->Flag & DEV_INFO_MASS_DEV_REGD) { newDev = fpDevInfo; goto UMCM_MassDeviceOkay; } // Find a new mass device info structure and copy the old one into the new one // Note: this is called before GetDeviceParameters because it sets up dev->wEmulationOption newDev = USBMassFindFreeMassDeviceInfo(fpDevInfo, &EmulIndex); if (newDev == NULL) goto UMCM_Error; fpDevInfo = newDev; inq = USBMassGetDeviceParameters(fpDevInfo); if (inq == NULL) goto UMCM_Error; // // Do not enumerate device if it is not a CD-ROM and has the block size different from 512 Bytes // EIP#15595, iPod nano makes POST hang. // //(EIP59738-)> //if ( fpDevInfo->bPhyDevType!=USB_MASS_DEV_CDROM ) { // if( fpDevInfo->wBlockSize!=0x200 && fpDevInfo->wBlockSize!=0xFFFF && fpDevInfo->wBlockSize!=0 ) // goto UMCM_Error; //} //<(EIP59738-) StoreUsbMassDeviceName(fpDevInfo, (UINT8*)inq+8); // Check for the hotplug devices current status, install the new one if needed if ( !(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) ) { // Find out if FDD/HDD/CDROM hotplugging is a valid option checkFDDhotplug = ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) || ((gUsbData->fdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) && (gUsbData->NumberOfFDDs == 0))) && !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_FDD_ENABLED); checkHDDhotplug = ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) || ((gUsbData->hdd_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) && (gUsbData->NumberOfHDDs == 0))) && !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_HDD_ENABLED); checkCDROMhotplug = ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_ENABLED) || ((gUsbData->cdrom_hotplug_support == SETUP_DATA_HOTPLUG_AUTO) && (gUsbData->NumberOfCDROMs == 0))) && !(BOOLEAN)(gUsbData->dUSBStateFlag & USB_HOTPLUG_CDROM_ENABLED); if ( checkFDDhotplug || checkCDROMhotplug || checkHDDhotplug ) { USB_DEBUG(DEBUG_LEVEL_3, "connecting hotplug..."); // inq = USBMassGetDeviceParameters(fpDevInfo); // if (inq == NULL) goto UMCM_Error; USB_DEBUG(DEBUG_LEVEL_3, "devtype phy %d, emu %d...", fpDevInfo->bPhyDevType, fpDevInfo->bEmuType); if ( checkFDDhotplug && (fpDevInfo->bStorageType == USB_MASS_DEV_ARMD) ) { newDev = &gUsbData->FddHotplugDev; gUsbData->dUSBStateFlag |= USB_HOTPLUG_FDD_ENABLED; } if ( checkHDDhotplug && (fpDevInfo->bEmuType == USB_EMU_HDD_ONLY) ) { newDev = &gUsbData->HddHotplugDev; gUsbData->dUSBStateFlag |= USB_HOTPLUG_HDD_ENABLED; } if ( checkCDROMhotplug && (fpDevInfo->bPhyDevType == USB_MASS_DEV_CDROM) ) { newDev = &gUsbData->CdromHotplugDev; gUsbData->dUSBStateFlag |= USB_HOTPLUG_CDROM_ENABLED; } fpDevInfo->Flag |= DEV_INFO_HOTPLUG; *newDev = *fpDevInfo; // Copy device into DevInfo dedicated to hotplug fpDevInfo->Flag &= ~DEV_INFO_VALIDPRESENT; // Release fpDevInfo fpDevInfo = newDev; } } UMCM_MassDeviceOkay: if ( (newDev->bEmuType == USB_EMU_FLOPPY_ONLY) || (newDev->bEmuType == USB_EMU_FORCED_FDD) ) { gUsbData->NumberOfFDDs++; } if ( newDev->bEmuType == USB_EMU_HDD_ONLY ) { gUsbData->NumberOfHDDs++; } // if ( newDev->bPhyDevType == USB_EMU_HDD_OR_FDD ) { if ( newDev->bPhyDevType == USB_MASS_DEV_CDROM ) { gUsbData->NumberOfCDROMs++; USBMassGetConfiguration(newDev); } if (bMaxLUN) { USBMassCreateLogicalUnits(newDev, bMaxLUN, EmulIndex); } //(EIP64781+)> if (gUsbData->dUSBStateFlag & USB_FLAG_SKIP_CARD_READER_CONNECT_BEEP) { if ((newDev->bLastStatus & USB_MASS_MEDIA_PRESENT) || newDev->bPhyDevType == USB_MASS_DEV_CDROM || newDev->bPhyDevType == USB_MASS_DEV_FDD) { SpeakerBeep(4, 0x1000, fpHCStruc); } else if (bMaxLUN) { for(i = 1; i < MAX_DEVICES; i++) { if (gUsbData->aDevInfoTable[i].fpLUN0DevInfoPtr == newDev) { if (gUsbData->aDevInfoTable[i].bLastStatus & USB_MASS_MEDIA_PRESENT) { SpeakerBeep(4, 0x1000, fpHCStruc); break; } } } } } //<(EIP64781+) return newDev; UMCM_Error: //USB_AbortConnectDev(fpDevInfo); //(EIP59579-) return NULL; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassDisconnectStorageDevice // // DESCRIPTION: This function disconnects the storage device // // PARAMETERS: pDevInfo Device info structure pointer // // RETURN: Nothing // //---------------------------------------------------------------------------- // UINT8 USBMassDisconnectStorageDevice ( DEV_INFO* DevInfo ) { // USB_DEBUG (DEBUG_LEVEL_5, "USBMassDisconnectDevice .... \n"); DevInfo->bBulkOutEndpoint = 0; DevInfo->bBulkInEndpoint = 0; DevInfo->IntInEndpoint = 0; if ((DevInfo->bEmuType == USB_EMU_FLOPPY_ONLY) || (DevInfo->bEmuType == USB_EMU_FORCED_FDD)) { gUsbData->NumberOfFDDs--; } if (DevInfo->bEmuType == USB_EMU_HDD_ONLY) { gUsbData->NumberOfHDDs--; } // if ( newDev->bPhyDevType == USB_EMU_HDD_OR_FDD ) { if ( DevInfo->bPhyDevType == USB_MASS_DEV_CDROM ) { gUsbData->NumberOfCDROMs--; } if (DevInfo->Flag & DEV_INFO_HOTPLUG) { DevInfo->Flag &= ~DEV_INFO_HOTPLUG; if (DevInfo == &gUsbData->FddHotplugDev) { gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_FDD_ENABLED; } else if (DevInfo == &gUsbData->HddHotplugDev) { gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_HDD_ENABLED; } else if (DevInfo == &gUsbData->CdromHotplugDev) { gUsbData->dUSBStateFlag &= ~USB_HOTPLUG_CDROM_ENABLED; } } return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassClearMassXactStruc // // Description: This function clears the mass transaction structure // //---------------------------------------------------------------------------- // VOID USBMassClearMassXactStruc( MASS_XACT_STRUC *MassXactStruc ) { UINT8 i; UINT8* Cleaner = (UINT8*)MassXactStruc; for (i = 0; i < sizeof (MASS_XACT_STRUC); i++ ) { *Cleaner++ = 0; } } // //---------------------------------------------------------------------------- // Procedure: USBMassClearBulkEndpointStall // // Description: This function clears the bulk endpoint stall by sending // CLEAR_FEATURE command to bulk endpoints // // Input: fpDevInfo Pointer to DeviceInfo structure // bDirec Endpoint direction // // Output: Nothing // //---------------------------------------------------------------------------- // VOID USBMassClearBulkEndpointStall( DEV_INFO* DevInfo, UINT8 Direc ) { UINT8 Shift; UINT16 EndPoint; HC_STRUC *HcStruc; HCD_HEADER *HcdDriver; HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1]; HcdDriver = &gUsbData->aHCDriverTable[GET_HCD_INDEX(HcStruc->bHCType)]; EndPoint = (UINT16)((DevInfo->bBulkInEndpoint) | BIT7); if (!(Direc & BIT7)) { EndPoint = DevInfo->bBulkOutEndpoint; } // // Issue clear port feature command // HcdDriver->pfnHCDControlTransfer(HcStruc, DevInfo, (UINT16)ENDPOINT_CLEAR_PORT_FEATURE, EndPoint,(UINT16)ENDPOINT_HALT, 0, 0); //if (HcdDriver->pfnHCDClearEndpointState) { // HcdDriver->pfnHCDClearEndpointState(HcStruc, DevInfo, (UINT8)EndPoint); //} else { // // Reset the toggle bit // Shift = (EndPoint & 0xF) - 1; if (Direc & BIT7) { DevInfo->wDataInSync &= ~((UINT16)(1 << Shift)); } else { DevInfo->wDataOutSync &= ~((UINT16)(1 << Shift)); } if (DevInfo->fpLUN0DevInfoPtr == NULL) { return; } if (Direc & BIT7) { DevInfo->fpLUN0DevInfoPtr->wDataInSync &= ~((UINT16)(1 << Shift)); } else { DevInfo->fpLUN0DevInfoPtr->wDataOutSync &= ~((UINT16)(1 << Shift)); } //} } // //---------------------------------------------------------------------------- // Procedure: USBMassIssueMassTransaction // // Description: This function performs a mass storage transaction by // invoking proper transaction protocol. // // Input: Pointer to DeviceInfo structure // stMassXactStruc // pCmdBuffer Pointer to command buffer // bCmdSize Size of command block // bXferDir Transfer direction // fpBuffer Data buffer far pointer // dwLength Amount of data to be transferred // wPreSkip Number of bytes to skip before data // wPostSkip Number of bytes to skip after data // // Output: Amount of data actually transferred // //---------------------------------------------------------------------------- // UINT32 USBMassIssueMassTransaction( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT32 DataLength; HC_STRUC *HcStruc; if ((DevInfo->bProtocol == PROTOCOL_CBI) || (DevInfo->bProtocol == PROTOCOL_CBI_NO_INT)) { return USBMassIssueCBITransaction(DevInfo, MassXactStruc); } if (DevInfo->bProtocol == PROTOCOL_BOT) { // Block to process periodic list to prevent that we might send the wrong // command sequences to the same device. gUsbData->ProcessingPeriodicList = FALSE; DataLength = USBMassIssueBOTTransaction(DevInfo, MassXactStruc); // To process any pending periodic list. gUsbData->ProcessingPeriodicList = TRUE; HcStruc = gUsbData->HcTable[DevInfo->bHCNumber - 1]; (*gUsbData->aHCDriverTable [GET_HCD_INDEX(HcStruc->bHCType)].pfnHCDProcessInterrupt)(HcStruc); return DataLength; } return 0; } // //---------------------------------------------------------------------------- // Procedure: USBMassGetDeviceParameters // // Description: This function gets the USB mass device parameters such as // max cylinder, head, sector, block size and // // Input: Pointer to DeviceInfo structure // // Output: Pointer to the temp buffer, NULL on error // //---------------------------------------------------------------------------- // MASS_INQUIRY* USBMassGetDeviceParameters( DEV_INFO* DevInfo ) { MASS_INQUIRY *Inq; UINT8 i; for (i = 0; i < 2; i++) { Inq = USBMassInquiryCommand(DevInfo); if (Inq) { break; } if (!(gUsbData->bLastCommandStatus & USB_BULK_STALLED)) { break; } } //USB_DEBUG(DEBUG_LEVEL_3, "fpMassInquiry = %x\n", Inq); if (!Inq) { return NULL; } DevInfo->wBlockSize = 0xFFFF; // Clear the cached block size // // Find the device type and update the device type structure accordingly // USBMassIdentifyDeviceType(DevInfo, (UINT8*)Inq); return Inq; } // //---------------------------------------------------------------------------- // Procedure: ValidateDeviceName // // Description: This procedure check whether device return valid device name // if no valid device name returned, assign default name for it // // Input: Inquiry Data // //---------------------------------------------------------------------------- // VOID ValidateDeviceName ( MASS_INQUIRY *InqData ) { static UINT8 DefaultName[] = "USB Storage Device"; UINT8 *Name = ((UINT8*)InqData) + 8; UINT8 *DefName = DefaultName; UINT8 Count; // check for a blank name if (*Name) return; // for (Count = 0; Count < 28; Count++) { // if (*(Name + Count)) return; // Not blank // } // copy default name for (Count = 0; Count < sizeof(DefaultName); Count++) { *(Name + Count) = *(DefName + Count); } } // //---------------------------------------------------------------------------- // Procedure: USBMassGetDeviceInfo // // Description: This function fills and returns the mass get device info // structure // // Input: fpMassGetDevInfo Pointer to the mass get info struc // bDevAddr USB device address of the device // // Output: USB_SUCCESS or USB_ERROR // fpMassGetDevInfo Pointer to the mass get info struc // dSenseData Sense data of the last command // bDevType Device type byte (HDD, CD, Removable) // bEmuType Emulation type used // fpDevId Far pointer to the device ID // // Notes: Initially the bDevAddr should be set to 0 as input. This // function returns the information regarding the first mass // storage device (if no device found it returns bDevAddr as // 0FFh) and also updates bDevAddr to the device address of // the current mass storage device. If no other mass storage // device is found then the routine sets the bit7 to 1 // indicating current information is valid but no more mass // device found in the system. The caller can get the next // device info if bDevAddr is not 0FFh and bit7 is not set // //---------------------------------------------------------------------------- // UINT8 USBMassGetDeviceInfo ( MASS_GET_DEV_INFO *MassGetDevInfo ) { DEV_INFO *DevInfo; MASS_INQUIRY *MassInq; UINT8 Dev = MassGetDevInfo->bDevAddr; // // Get the total number of Mass Storage Devices // MassGetDevInfo->bTotalMassDev = (UINT8)(UINTN)USB_GetDeviceInfoStruc(USB_SRCH_DEV_NUM, 0, BIOS_DEV_TYPE_STORAGE, 0); if (Dev == 0) { iPodShufflePatch(MassGetDevInfo); } if (Dev & BIT7) { return USB_ERROR; // Check for device address validity } // // If bDev = 0 then get information about first mass storage device // if (!Dev) { DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, 0, BIOS_DEV_TYPE_STORAGE, 0); //USB_DEBUG(DEBUG_LEVEL_3, "Get Mass0 info: %x\n", DevInfo); if (!DevInfo) { // Set as no more device found MassGetDevInfo->bDevAddr = 0xFF; return USB_SUCCESS; } } else { // Not the first mass device // // Get the device info structure for the matching device index // DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, Dev, 0); ASSERT(DevInfo); if ( (!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT)) ) { // Error return USB_ERROR; } // // Get device info structure for next device // DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, DevInfo, BIOS_DEV_TYPE_STORAGE, 0); ASSERT(DevInfo); if (!DevInfo) { // Error. Exit ! return USB_ERROR; } } MassInq = USBMassGetDeviceParameters(DevInfo); if (!MassInq) { return USB_ERROR; } MassGetDevInfo->bDevType = DevInfo->bPhyDevType; // MassGetDevInfo->bPhyDevType = fpDevInfo->bPhyDevType; MassGetDevInfo->bEmuType = DevInfo->bEmuType; MassGetDevInfo->wPciInfo = gUsbData->HcTable[DevInfo->bHCNumber - 1]->wBusDevFuncNum; MassGetDevInfo->fpDevId = (UINT32)(UINTN)((UINT8*)MassInq + 8); // MassGetDevInfo->fpDevId = USBMassAdjustIdString((UINT32)MassInq + 8); Dev = (UINT8)(UINTN)USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, DevInfo, 0, 0); ASSERT(Dev); Dev |= BIT7; // Assume that no more mass device present // // Check whether more mass device is present // if (USB_GetDeviceInfoStruc(USB_SRCH_DEV_TYPE, DevInfo, BIOS_DEV_TYPE_STORAGE, 0)) { Dev &= ~BIT7; } DevInfo->Flag |= DEV_INFO_MASS_DEV_REGD; MassGetDevInfo->bDevAddr = Dev; *(UINTN*)MassGetDevInfo->Handle = *(UINTN*)DevInfo->Handle; return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: iPodShufflePatch // // Description: This check whether iPod shuffle attached to system and move // iPod shuffle to first initial device. // // Input: Pointer to the mass get info struc // // Output: None // // Notes: Attaching iPod shuffle and iPod mini to system causes BIOS POST // stop. iPod shuffle must be initialized as early as possible. // iPod mini cosumes about 2 seconds to complete initialization, // init iPod shuffle first to fix problem. // //---------------------------------------------------------------------------- // VOID iPodShufflePatch( MASS_GET_DEV_INFO *MassGetDevInfo ) { //TO BE IMPLEMENTED } // //---------------------------------------------------------------------------- // Procedure: USBMassGetDeviceStatus // // Description: Get USB MassStorage device status. Include Media Informarion. // Refer to USB_MASS_MEDIA_XXX in USBDEF.H // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR or USB_SUCCESS // //---------------------------------------------------------------------------- // UINT8 USBMassGetDeviceStatus ( MASS_GET_DEV_STATUS *MassGetDevSts ) { DEV_INFO* DevInfo; UINT8 DevAddr = MassGetDevSts->bDevAddr; UINT8 LastStatus; DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); ASSERT(DevInfo != NULL); if (DevInfo == NULL) { return USB_ERROR; } LastStatus= DevInfo->bLastStatus; USBMassCheckDeviceReady(DevInfo); // When the Media is not present in the drive and insert the Media // it's just sends the status as Media Present. So check the last status // and if the media not present and current stauts is media present // report it as Media changed if ((LastStatus ^ DevInfo->bLastStatus) & USB_MASS_MEDIA_PRESENT) { // Report the Last Status along with Media Changed status DevInfo->bLastStatus |= USB_MASS_MEDIA_CHANGED; } MassGetDevSts->bDeviceStatus = DevInfo->bLastStatus; if (DevInfo->bLastStatus & USB_MASS_MEDIA_CHANGED) { // // Clear Media Change Status. // DevInfo->bLastStatus &= (UINT8)(~USB_MASS_MEDIA_CHANGED); } return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassCmdPassThru // // Description: This function issues the command/data sequence provided // as input. This function can be used to send raw data // to the USB mass storage device // // Input: fpDevInfo Pointer to Device Info structure // fpMassCmdPassThru Pointer to the mass command pass // through structure // bDevAddr USB device address of the device // dSenseData Sense data of the last command // fpCmdBuffer Far pointer to the command buffer // wCmdLength Command length // fpDataBuffer Far pointer for data buffer // wDataLength Data length // bXferDir Data transfer direction // // Output: USB_SUCCESS or USB_ERROR // dSenseData Sense data of the last command // fpDataBuffer Updated with returned data if the transfer // is an IN transaction // //---------------------------------------------------------------------------- // UINT8 USBMassCmdPassThru ( MASS_CMD_PASS_THRU *MassCmdPassThru ) { UINT8 *CmdBuffer; UINT8 *Src; UINT8 *Dst; DEV_INFO *DevInfo; // UINT8 CommandRetried = FALSE; UINT8 CmdBlkSize; UINT8 Count; UINT16 Data16; UINT32 Data32; UINT8 DevAddr = MassCmdPassThru->bDevAddr; MASS_XACT_STRUC MassXactStruc; DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); if ( (!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT)) ) { // Error return USB_ERROR; } CmdBlkSize = (UINT8)((MassCmdPassThru->wCmdLength + USB_MEM_BLK_SIZE - 1) >> USB_MEM_BLK_SIZE_SHIFT); // // Check whether the drive is ready for read TOC command // USBMassCheckDeviceReady(DevInfo); // // Allocate memory for the command buffer // CmdBuffer = USB_MemAlloc((UINT8)GET_MEM_BLK_COUNT(CmdBlkSize)); if (!CmdBuffer) { return USB_ERROR; } // // Copy the command into (just allocated) mass command buffer // Src = (UINT8*)(UINTN)MassCmdPassThru->fpCmdBuffer; Dst = CmdBuffer; for (Count = 0; Count < MassCmdPassThru->wCmdLength; Count++) { *Dst++ = *Src++; } // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = CmdBuffer; MassXactStruc.bCmdSize = (UINT8)MassCmdPassThru->wCmdLength; MassXactStruc.bXferDir = MassCmdPassThru->bXferDir; MassXactStruc.fpBuffer = (UINT8*)(UINTN)MassCmdPassThru->fpDataBuffer; MassXactStruc.dLength = (UINT32)MassCmdPassThru->wDataLength; Data16 = (UINT16)USBMassIssueMassTransaction(DevInfo, &MassXactStruc); // // Update the actual data length processed/returned // MassCmdPassThru->wDataLength = Data16; Data32 = USBMassRequestSense (DevInfo); MassCmdPassThru->dSenseData = Data32; // // Check and free command buffer // if (!CmdBuffer) { return USB_ERROR; } USB_MemFree(CmdBuffer, (UINT16)GET_MEM_BLK_COUNT(CmdBlkSize)); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassReadCapacity16Command // // Description: This function issues read capacity of the mass storage // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR or USB_SUCCESS // // Notes: This routine will update the MassDeviceInfo structure // with the block size & last LBA values obtained from the // device // //---------------------------------------------------------------------------- // UINT8 USBMassReadCapacity16Command ( DEV_INFO* DevInfo ) { UINT32 Data; COMN_READ_CAPACITY_16_CMD *CmdBuffer; MASS_XACT_STRUC MassXactStruc; if (!VALID_DEVINFO(DevInfo)) { return USB_ERROR; } // // Allocate memory for the command buffer // CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD)); if (!CmdBuffer) { return USB_ERROR; } CmdBuffer->OpCode = COMMON_READ_CAPACITY_16_OPCODE; CmdBuffer->ServiceAction = 0x10; CmdBuffer->AllocLength = 0x0C000000; // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); // // Change the bulk transfer delay to 10 seconds (For CDROM drives) // gUsbData->wBulkDataXferDelay = 10000; // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; MassXactStruc.bCmdSize = sizeof(COMN_RWV_16_CMD); MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer; MassXactStruc.dLength = 0xC; USB_DEBUG (DEBUG_LEVEL_3, "rcc.."); Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); // // Reset the delay back // gUsbData->wBulkDataXferDelay = 0; if (!Data) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD)); USB_DEBUG (DEBUG_LEVEL_3, "err "); return USB_ERROR; } Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 8)); // // Change little endian format to big endian(INTEL) format // Data = dabc_to_abcd(Data); //(EIP37167+)> if (!Data) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_16_CMD)); USB_DEBUG (DEBUG_LEVEL_3, "err "); return USB_ERROR; } DevInfo->wBlockSize = (UINT16)Data; USB_DEBUG(3,"BlockSize %x\n", DevInfo->wBlockSize); // // Store the last LBA number in the mass info structure // Data = *((UINT32*)(gUsbData->fpUSBTempBuffer)); Data = dabc_to_abcd(Data); DevInfo->MaxLba = Shl64(Data, 32); Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 4)); Data = dabc_to_abcd(Data); DevInfo->MaxLba |= Data; USB_DEBUG(3,"MaxLba %lx\n", DevInfo->MaxLba); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassReadCapacity10Command // // Description: This function issues read capacity of the mass storage // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR or USB_SUCCESS // // Notes: This routine will update the MassDeviceInfo structure // with the block size & last LBA values obtained from the // device // //---------------------------------------------------------------------------- // UINT8 USBMassReadCapacity10Command ( DEV_INFO* DevInfo ) { UINT32 Data; COMN_READ_CAPACITY_10_CMD *CmdBuffer; MASS_XACT_STRUC MassXactStruc; if (!VALID_DEVINFO(DevInfo)) { return USB_ERROR; } if (Shr64(DevInfo->MaxLba, 32)) { USBMassReadCapacity16Command(DevInfo); return USB_SUCCESS; } // // Allocate memory for the command buffer // CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); if (!CmdBuffer) { return USB_ERROR; } CmdBuffer->bOpCode = COMMON_READ_CAPACITY_10_OPCODE; // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); // // Change the bulk transfer delay to 10 seconds (For CDROM drives) // gUsbData->wBulkDataXferDelay = 10000; // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; //(EIP51158+)> if (DevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x0A; //SBC-3_66 } else { MassXactStruc.bCmdSize = sizeof (COMN_READ_CAPACITY_10_CMD); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer; MassXactStruc.dLength = 8; USB_DEBUG (DEBUG_LEVEL_3, "rcc.."); Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); // // Reset the delay back // gUsbData->wBulkDataXferDelay = 0; if (!Data) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); USB_DEBUG (DEBUG_LEVEL_3, "err "); return USB_ERROR; } USB_DEBUG(3,"Read Capacity 10 LBA %x\n", *(UINT32*)gUsbData->fpUSBTempBuffer); if (*(UINT32*)gUsbData->fpUSBTempBuffer == 0xFFFFFFFF) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); USBMassReadCapacity16Command(DevInfo); return USB_SUCCESS; } Data = *((UINT32*)(gUsbData->fpUSBTempBuffer + 4)); // // Change little endian format to big endian(INTEL) format // Data = dabc_to_abcd(Data); //(EIP37167+)> if (!Data) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); USB_DEBUG(DEBUG_LEVEL_3, "err "); return USB_ERROR; } //<(EIP37167+) DevInfo->wBlockSize = (UINT16)Data; //USB_DEBUG(DEBUG_LEVEL_3, "succ: %x, %x\n", dData, fpDevInfo); // // Store the last LBA number in the mass info structure // Data = *((UINT32*)(gUsbData->fpUSBTempBuffer)); Data = dabc_to_abcd(Data); if (!Data) { USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); USB_DEBUG (DEBUG_LEVEL_3, "err "); return USB_ERROR; } DevInfo->MaxLba = Data + 1; // 1-based value USB_DEBUG(DEBUG_LEVEL_3, "%x ", DevInfo->MaxLba); USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_CAPACITY_10_CMD)); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassReadFormatCapacity // // Description: This function sends read format capacity command to the USB // mass storage device // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR or USB_SUCCESS // // Notes: This routine will update the MassDeviceInfo structure // with the block size & last LBA values obtained from the // device //---------------------------------------------------------------------------- // UINT8 USBMassReadFormatCapacity (DEV_INFO* fpDevInfo) { COMN_READ_FMT_CAPACITY *fpCmdBuffer; UINT32 dData; UINT16 wData; UINT8* DataBuffer; UINT16 DataBufferSize = 0xFC; MASS_XACT_STRUC MassXactStruc; // // Allocate memory for the command buffer // fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); if(!fpCmdBuffer) { return USB_ERROR; } DataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(DataBufferSize)); if (DataBuffer == NULL) { return USB_ERROR; } fpCmdBuffer->bOpCode = COMMON_READ_FORMAT_CAPACITY_OPCODE; fpCmdBuffer->wAllocLength = (UINT16)((DataBufferSize << 8) + (DataBufferSize >> 8)); USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer; //(EIP51158+)> if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x0A; } else { MassXactStruc.bCmdSize = sizeof (COMN_READ_FMT_CAPACITY); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = DataBuffer; // MassXactStruc.dLength = MAX_TEMP_BUFFER_SIZE; // // Temp buffer 40h-64h was used as device name string buffer. // Limit Transaction size to 40h to prevent name string display problem. // MassXactStruc.dLength = DataBufferSize; USB_DEBUG (DEBUG_LEVEL_5, "Issue ReadFormatCapacityCommand .... \n"); dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc); // // The amount of data obtained should be atleast of read format capacity structure size // if (dData < sizeof (COMN_READ_FMT_CAPACITY)) { USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); return USB_ERROR; } if ((DataBuffer[0] != 0) || (DataBuffer[1] != 0) || (DataBuffer[2] != 0) || (DataBuffer[3] < 0x08)) { USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); return USB_ERROR; } wData = *((UINT16*)(DataBuffer + 10)); // Offset 10 if (wData == 0) { USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); return USB_ERROR; } fpDevInfo->wBlockSize = (UINT16)((wData << 8) + (wData >> 8)); dData = *((UINT32*)(DataBuffer + 4)); // Offset 4 if (dData == 0) { USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); return USB_ERROR; } dData = dabc_to_abcd(dData); fpDevInfo->MaxLba = dData; if (dData == USB_144MB_FDD_MAX_LBA) { // // Return parameters for 1.44MB floppy // fpDevInfo->Heads = USB_144MB_FDD_MAX_HEADS; fpDevInfo->NonLBAHeads = USB_144MB_FDD_MAX_HEADS; fpDevInfo->bSectors = USB_144MB_FDD_MAX_SECTORS; fpDevInfo->bNonLBASectors = USB_144MB_FDD_MAX_SECTORS; fpDevInfo->wCylinders = USB_144MB_FDD_MAX_CYLINDERS; fpDevInfo->wNonLBACylinders = USB_144MB_FDD_MAX_CYLINDERS; fpDevInfo->bMediaType = USB_144MB_FDD_MEDIA_TYPE; } USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_READ_FMT_CAPACITY)); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassGetConfiguration // // Description: This function sends get configuration command to the USB // mass storage device // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR or USB_SUCCESS // //---------------------------------------------------------------------------- // UINT8 USBMassGetConfiguration( DEV_INFO* DevInfo ) { COMMON_GET_CONFIGURATION *CmdBuffer; UINT32 Data; UINT8 *DataBuffer; UINT16 DataBufferSize = 0x8; MASS_XACT_STRUC MassXactStruc; // // Allocate memory for the command buffer // CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_GET_CONFIGURATION)); if (!CmdBuffer) { return USB_ERROR; } DataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(DataBufferSize)); if (DataBuffer == NULL) { return USB_ERROR; } CmdBuffer->OpCode = COMMON_GET_CONFIGURATION_OPCODE; CmdBuffer->AllocLength = (UINT16)((DataBufferSize << 8) + (DataBufferSize >> 8)); USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; MassXactStruc.bCmdSize = sizeof (COMMON_GET_CONFIGURATION); MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = DataBuffer; MassXactStruc.dLength = DataBufferSize; USB_DEBUG(DEBUG_LEVEL_5, "Issue GetConfigurationCommand .... \n"); Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); USB_MemFree(DataBuffer, GET_MEM_BLK_COUNT(DataBufferSize)); USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_GET_CONFIGURATION)); if (Data) { return USB_SUCCESS; } else { return USB_ERROR; } } // //---------------------------------------------------------------------------- // Procedure: USBMassReadSector // // Description: This function a sector at the LBA specified // // Input: Pointer to DeviceInfo structure // LBA to read // DS:DI Data buffer pointer // // Output: USB_SUCCESS or USB_ERROR // //---------------------------------------------------------------------------- // UINT8 USBMassReadSector( DEV_INFO* DevInfo, UINT32 Lba, UINT8* Buffer ) { COMN_RWV_10_CMD *CmdBuffer; UINT32 Data; UINT8 Counter; UINT8 RetValue = USB_ERROR; MASS_XACT_STRUC MassXactStruc; // // Allocate memory for the command buffer // CmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_RWV_10_CMD)); if (!CmdBuffer) { return USB_ERROR; } USBMassClearMassXactStruc(&MassXactStruc); Counter = 10; do { // // Set opcode to read command // CmdBuffer->bOpCode = COMMON_READ_10_OPCODE; CmdBuffer->wTransferLength = 0x100; // Big endian to little endian: 0x0001 -> 0x0100 Data = Lba; // // Change LBA from big endian to little endian // Data = dabc_to_abcd(Data); CmdBuffer->dLba = Data; // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; //(EIP51158+)> if (DevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x0A; //SBC-3_60 } else { MassXactStruc.bCmdSize = sizeof (COMN_RWV_10_CMD); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = Buffer; MassXactStruc.dLength = DevInfo->wBlockSize; //(EIP59738) MassXactStruc.wPreSkip = 0; MassXactStruc.wPostSkip= 0; USB_DEBUG (DEBUG_LEVEL_5, "Read Sector .... \n"); Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); if(Data) { RetValue = USB_SUCCESS; break; // Success } // // May be drive error. Try to correct from it ! // Check whether the drive is ready for read/write/verify command // Data = USBMassCheckDeviceReady(DevInfo); if (Data) { // Device is not ready. RetValue = USB_ERROR; break; } MemFill((UINT8*)CmdBuffer, sizeof(COMN_RWV_10_CMD), 0); } while (Counter--); USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_RWV_10_CMD)); return RetValue; } // //---------------------------------------------------------------------------- // Procedure: USBMassUpdateCHSFromBootRecord // // Description: This function parses the boot record and extract the CHS // information of the formatted media from the boot record. // This routine checks for DOS & NTFS formats only // // Input: Pointer to DeviceInfo structure // Maximum LBA in the device // Boot record of the device // // Output: USB_ERROR If the boot record is un-recognizable and CHS info // is not extracted // USB_SUCCESS If the boot record is recognizable and CHS info // is extracted. CHS information is updated in the // mass device info structure //---------------------------------------------------------------------------- // UINT8 USBMassUpdateCHSFromBootRecord( DEV_INFO *DevInfo, UINT64 MaxLba, BOOT_SECTOR *BootSetor ) { UINT32 OemName = 0; UINT32 Fat16SysType = 0; UINT32 Fat32SysType = 0; if (BootSetor->Signature != 0xAA55) { return USB_ERROR; } // // Check for valid MSDOS/MSWIN/NTFS boot record // MemCopy((UINT8*)BootSetor->OEMName, (UINT8*)&OemName, sizeof(OemName)); if ((OemName != 0x4F44534D) && // "ODSM", MSDO... (OemName != 0x4957534D) && // "IWSM", MSWI... (OemName != 0x5346544E)) { // "SFTN", NTFS // // Check for valid FAT,FAT16 or FAT32 boot records // BootSetor->Fat.Fat16.FilSysType[3] = 0x20; MemCopy((UINT8*)BootSetor->Fat.Fat16.FilSysType, (UINT8*)&Fat16SysType, sizeof(Fat16SysType)); MemCopy((UINT8*)BootSetor->Fat.Fat32.FilSysType, (UINT8*)&Fat32SysType, sizeof(Fat32SysType)); if ((Fat16SysType != 0x20544146) && // " TAF", FAT (Fat32SysType != 0x33544146)) { // "3TAF", FAT3 // // None of the conditions met - boot record is invalid. Return with error // return USB_ERROR; } } // zero check added to prevent invalid sector/head information in BPB if (BootSetor->SecPerTrk == 0) { return USB_ERROR; } DevInfo->bSectors = (UINT8)BootSetor->SecPerTrk; DevInfo->bNonLBASectors = (UINT8)BootSetor->SecPerTrk; // Wrong BPB in MSI MegaStick 128; this is preformat usility issue, wrong BPB // information built in device. if (BootSetor->NumHeads == 0) { return USB_ERROR; } DevInfo->Heads = BootSetor->NumHeads; DevInfo->NonLBAHeads = BootSetor->NumHeads; DevInfo->BpbMediaDesc = BootSetor->Media; USBMassUpdateCylinderInfo(DevInfo, MaxLba); USB_DEBUG (DEBUG_LEVEL_4, "CHS: %x %x %x\n", DevInfo->bSectors, DevInfo->Heads, DevInfo->wCylinders); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassUpdateCylinderInfo // // Description: This procedure update cylinder parameter for device geometry. // head and sector paramaters are required before invoke this // function. // // Input: Pointer to DeviceInfo structure // Maximum LBA in the device // dev->bHeads // dev->bSectors // // Output: None // //---------------------------------------------------------------------------- // VOID USBMassUpdateCylinderInfo( DEV_INFO* Dev, UINT64 Lba ) { UINT64 Data; if ((Dev->bSectors != 0) && (Dev->Heads != 0)) { Data = Div64(Lba, (Dev->bSectors * Dev->Heads), NULL); } else { Data = 0; } if (Data <= 1) { Data++; } if (Data > 0xFFFF) { Data = 0xFFFF; // DOS workaround } Dev->wCylinders = (UINT16)Data; Dev->wNonLBACylinders = (UINT16)Data; } // //---------------------------------------------------------------------------- // Procedure: USBMassGetFormatType // // Description: This function reads the first sector from the mass storage // device and identifies the formatted type. // // Input: Pointer to DeviceInfo structure // Maximum LBA of the device // // Output: USB_ERROR If could not identify the formatted type // USB_SUCCESS If formatted type is identified // MSB of emu - Emulation type // LSB of emu - Device type (Floppy, Harddisk or CDROM) // //---------------------------------------------------------------------------- // UINT8 USBMassGetFormatType( DEV_INFO* DevInfo, UINT64 MaxLba, UINT16 *Emu ) { MBR_PARTITION Partition = {0}; // // Read the first sector of the device // if (USBMassReadSector(DevInfo, 0, gUsbData->fpUSBMassConsumeBuffer) == USB_ERROR) { return USB_ERROR; } DevInfo->bHiddenSectors = 0; // // Check for validity of the partition table/boot record // if (*((UINT16*)(gUsbData->fpUSBMassConsumeBuffer + 0x1FE)) != 0xAA55) { USBMassSetDefaultGeometry(DevInfo, MaxLba); return USB_ERROR; } if (USBMassValidatePartitionTable((MASTER_BOOT_RECORD*)gUsbData->fpUSBMassConsumeBuffer, MaxLba, &Partition) == USB_SUCCESS) { // // Only one partition present, check the device size, if the device size // is less than 530 MB assume FDD or else assume the emulation as HDD // //if (((MaxLba >> 11) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) && //(EIP80382) // !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) { // emu_ = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; //}else { // emu_ = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD; //} // // Read boot sector, set the LBA number to boot record LBA number // DevInfo->bHiddenSectors = Partition.StartingLba; if (USBMassReadSector(DevInfo, Partition.StartingLba, gUsbData->fpUSBMassConsumeBuffer) == USB_ERROR) { return USB_ERROR; } if (USBMassUpdateCHSFromBootRecord(DevInfo, MaxLba, (BOOT_SECTOR*)gUsbData->fpUSBMassConsumeBuffer) == USB_SUCCESS) { if (((Shr64(MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) && !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) { if (DevInfo->bSubClass != SUB_CLASS_UFI) { *Emu = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; } } return USB_SUCCESS; } else { // Reset hidden sector value and return HDD emulation USBMassSetDefaultGeometry(DevInfo, MaxLba); DevInfo->bHiddenSectors = 0; //(EIP43711)> //don't emulate as HDD for UFI class even media has valid partition like HDD if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_SIZE_EMULATION) { if (DevInfo->bSubClass != SUB_CLASS_UFI) { if ((Shr64(MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) { *Emu = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; } } } //<(EIP43711) return USB_SUCCESS; } } *Emu = USBMassSetDefaultType(DevInfo, MaxLba); if (USBMassUpdateCHSFromBootRecord(DevInfo, MaxLba, (BOOT_SECTOR*)gUsbData->fpUSBMassConsumeBuffer) == USB_SUCCESS) { //*emu = USBMassSetDefaultType(fpDevInfo, MaxLba); if (gUsbData->dUSBStateFlag & USB_FLAG_MASS_SIZE_EMULATION) { if (DevInfo->bSubClass != SUB_CLASS_UFI) { if ((Shr64(MaxLba, 11)) >= MAX_SIZE_FOR_USB_FLOPPY_EMULATION) { *Emu = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD; } } } return USB_SUCCESS; } USBMassSetDefaultGeometry(DevInfo, MaxLba); //*emu = USBMassSetDefaultType(fpDevInfo, MaxLba); if (((Shr64(MaxLba, 11)) >= MAX_SIZE_FOR_USB_FLOPPY_EMULATION) && !(gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) { if (DevInfo->bSubClass != SUB_CLASS_UFI) { *Emu = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD; } DevInfo->bHiddenSectors = 0; } //*emu = emu_; return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassSetDefaultType // // Description: This procedure set device type depend on device class. // // Input: Pointer to DeviceInfo structure // Maximum LBA in the device (DWORD) // // Output: Device Type (WORD) // //---------------------------------------------------------------------------- // UINT16 USBMassSetDefaultType( DEV_INFO* Dev, UINT64 Lba ) { UINT16 DevType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD; if (Dev->bSubClass != SUB_CLASS_UFI) { // Check whether UFI class device // Assume force FDD emulation for non-UFI class device DevType = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; } return DevType; } // //---------------------------------------------------------------------------- // Procedure: USBMassValidatePartitionTable // // Description: This procedure check whether partition table valid. // // Input: Partition table content // Maximum LBA in the device // // Output: USB_SUCCESS - partion table is valid: // Possible valid entry count(1-based) // Table entry counts(0-based, 4 means all entries scaned) // Activate entry offset(Absolute offset) // USB_ERROR - Invalid partition table // //---------------------------------------------------------------------------- // UINT8 USBMassValidatePartitionTable( IN MASTER_BOOT_RECORD *Mbr, IN UINT64 Lba, OUT MBR_PARTITION *Partition) { UINT8 Index = 0; UINT8 ActivateIndex = 0; // The partition table area could be all 0's, and it would pass the below tests, // So test for that here (test sector count for all partitions). if ((Mbr->PartRec[0].SizeInLba == 0) && (Mbr->PartRec[1].SizeInLba == 0) && (Mbr->PartRec[2].SizeInLba == 0) && (Mbr->PartRec[3].SizeInLba == 0)) { return USB_ERROR; } for (Index = 0; Index < 4; Index++) { // Boot flag check added to ensure that boot sector will not be treated as // a valid partation table. if (Mbr->PartRec[Index].BootIndicator & 0x7F) { return USB_ERROR; // BootFlag should be 0x0 or 0x80 } // Check whether beginning LBA is reasonable if (Mbr->PartRec[Index].StartingLba > Lba) { return USB_ERROR; } // Check whether the size is reasonable #if HDD_PART_SIZE_CHECK if (Mbr->PartRec[Index].SizeInLba > Lba) { return USB_ERROR; } #endif // Update activate entry offset if (!(Mbr->PartRec[Index].BootIndicator & 0x80)) { continue; } ActivateIndex = Index; } // If no activate partition table entry found use first entry MemCopy((UINT8*)&Mbr->PartRec[ActivateIndex], (UINT8*)Partition, sizeof(MBR_PARTITION)); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassSetDefaultGeometry // // Description: This procedure set default geometry for mass storage devices. // // Input: Pointer to DeviceInfo structure // Maximum LBA in the device // // Output: USB_ERROR If could not identify the formatted type // USB_SUCCESS If formatted type is identified // Emulation type - bits 8..15 // Device type (Floppy, Harddisk or CDROM) - bits 0..7 // //---------------------------------------------------------------------------- // UINT8 USBMassSetDefaultGeometry(DEV_INFO* dev, UINT64 lba) { if (dev->bSubClass == SUB_CLASS_UFI) { dev->Heads = 0x02; dev->NonLBAHeads = 0x02; dev->bSectors = 0x12; dev->bNonLBASectors = 0x12; } else { dev->bSectors = 0x3F; dev->bNonLBASectors = 0x3F; // Use default heads that results in 1023 (3FF) cylinders or less for CHS if (lba <= 0x1F7820) { dev->Heads = 0x20; dev->NonLBAHeads = 0x20; } else if ( (lba > 0x1F7820) && (lba <= 0x3EF040) ) { dev->Heads = 0x40; dev->NonLBAHeads = 0x40; } else if ( (lba > 0x3EF040) && (lba <= 0x7DE080) ) { dev->Heads = 0x80; dev->NonLBAHeads = 0x80; } else if (lba > 0x7DE080) { dev->Heads = 0xFF; dev->NonLBAHeads = 0xFF; } } USBMassUpdateCylinderInfo(dev, lba); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassIdentifyDeviceType // // Description: This function identifies the type of the USB mass storage // device attached from the INQUIRY data obtained from the drive // // Input: Pointer to DeviceInfo structure // Pointer to the inquiry data (read from device) // // Output: Nothing // //---------------------------------------------------------------------------- // VOID USBMassIdentifyDeviceType( DEV_INFO* DevInfo, UINT8* InqData ) { UINT16 EmulationType; UINT16 ForceEmulationType = 0; UINT32 Data = 0; UINT8 Count; static UINT16 UsbMassEmulationTypeTable[5] = { 0, // Auto (USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD, // Floppy (USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD, // Forced floppy (USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD, // HDD (USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM }; // CDROM USBMassGetPhysicalDeviceType(DevInfo, InqData); // Note: at this point we assume that dev->wEmulationOption is filled in // according to the setup question selection. if (!(DevInfo->Flag & DEV_INFO_HOTPLUG) || DevInfo->wEmulationOption) { // not auto EmulationType = UsbMassEmulationTypeTable[DevInfo->wEmulationOption]; ForceEmulationType = UsbMassEmulationTypeTable[DevInfo->wEmulationOption]; } //USB_DEBUG(DEBUG_LEVEL_3, ">>-- IdentifyDeviceType:: Device #%d, Emul#: %d, Emul: %x\n", // DevInfo->bDeviceAddress, DevInfo->wEmulationOption, EmulationType); #if USB_STORAGE_DEVICE_RMB_CHECK if (*(InqData + 1) & 0x80) { // Check RMB status DevInfo->bLastStatus |= USB_MASS_MEDIA_REMOVEABLE; } #else DevInfo->bLastStatus |= USB_MASS_MEDIA_REMOVEABLE; #endif DevInfo->bLastStatus |= USB_MASS_MEDIA_PRESENT; // Assume Media Present if (*InqData == 5) { // CDROM // Set the type as CDROM and emulation as HDD or FDD DevInfo->wBlockSize = 0x800; EmulationType = (UINT16)(USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM; goto UMIDT_DeviceTypeOver; } // ;(EIP25229+)> #if USB_START_UNIT_BEFORE_MSD_ENUMERATION // Start unit command before access it USBMassStartUnitCommand(DevInfo); #endif // ;<(EIP25229+) //(EIP80382)> if (DevInfo->bSubClass == SUB_CLASS_UFI) { EmulationType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD; } else { EmulationType = (UINT16)(USB_EMU_HDD_ONLY << 8) + USB_MASS_DEV_HDD; } //<(EIP80382) FixedDelay(gUsbData->UsbTimingPolicy.MassDeviceComeUp * 1000); // Device is coming up give 500ms delay // // Some USB mass storage devces are not fast enough to accept mass storage // commands for parsing geometry, issue read capacity command to make sure device // is ready for further access. (USB0089+)> // if (DevInfo->bSubClass != SUB_CLASS_UFI) { for (Count = 0; Count < 30 && VALID_DEVINFO(DevInfo); Count++) { if (USBMassReadCapacity10Command(DevInfo) == USB_SUCCESS) { break; } if ((UINT16)USBMassRequestSense(DevInfo) == 0x3A02 ) { //(EIP86793) break; // No media } } } // // Get the block size & last LBA number // Data = USBMassCheckDeviceReady(DevInfo); //(EIP86793)> if ((UINT16)Data == 0x3A02) { // Check for media presence status // // Media not present. Try to get disk geometry from Format // capacity command // if (!(DevInfo->wIncompatFlags & USB_INCMPT_FORMAT_CAPACITY_NOT_SUPPORTED)) { USBMassReadFormatCapacity(DevInfo); if ((DevInfo->MaxLba != 0) && (DevInfo->MaxLba <= USB_144MB_FDD_MAX_LBA)) { EmulationType = (UINT16)(USB_EMU_FLOPPY_ONLY << 8) + USB_MASS_DEV_ARMD; } else { if (!(gUsbData->dUSBStateFlag & USB_FLAG_MASS_EMULATION_FOR_NO_MEDIA)) { EmulationType = (UINT16)(USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; } } goto UMIDT_DeviceTypeOver; } } // // Proceed with normal checking // if (!Data) { //(EIP59738-)> // // Get the max LBA & block size; if block size is other than // 512 bytes assume emulation as CDROM // //if ( dev->wBlockSize > 0x200 ) { // wEmulationType = (UINT16)(USB_EMU_HDD_OR_FDD << 8) + USB_MASS_DEV_CDROM; // goto UMIDT_DeviceTypeOver; //} //( if (USBMassGetFormatType(DevInfo, DevInfo->MaxLba, &EmulationType) == USB_ERROR) { // // Find the device type by size // if (((Shr64(DevInfo->MaxLba, 11)) < MAX_SIZE_FOR_USB_FLOPPY_EMULATION) || (gUsbData->dUSBStateFlag & USB_FLAG_MASS_NATIVE_EMULATION)) { if (DevInfo->bSubClass != SUB_CLASS_UFI) { EmulationType = (USB_EMU_FORCED_FDD << 8) + USB_MASS_DEV_ARMD; } } } } //<(EIP80382) //<(EIP86793) UMIDT_DeviceTypeOver: if (ForceEmulationType) { EmulationType = ForceEmulationType; } DevInfo->bStorageType = (UINT8)EmulationType; DevInfo->bEmuType = (UINT8)(EmulationType >> 8); USB_DEBUG(DEBUG_LEVEL_3, "<<-- IdentifyDeviceType:: Emul: %x\n", EmulationType); return; } // //---------------------------------------------------------------------------- // Procedure: USBMassGetPhysicalDeviceType // // Description: This procedure classify USB mass storage devices according to // inquiry command return data. // // Input: Pointer to DeviceInfo structure // Pointer to the inquiry data (read from device) // // Output: Nothing // //---------------------------------------------------------------------------- // VOID USBMassGetPhysicalDeviceType( DEV_INFO* Dev, UINT8 *Buf ) { switch (*Buf) { case 0x0: if (Dev->bSubClass == SUB_CLASS_UFI) { Dev->bPhyDevType = USB_MASS_DEV_FDD; break; } Dev->bPhyDevType = (*(Buf+1) & 0x80) ? USB_MASS_DEV_ARMD : USB_MASS_DEV_HDD; break; case 0x5: Dev->bPhyDevType = USB_MASS_DEV_CDROM; break; case 0x7: Dev->bPhyDevType = USB_MASS_DEV_MO; break; case 0xE: Dev->bPhyDevType = USB_MASS_DEV_ARMD; break; default: Dev->bPhyDevType = USB_MASS_DEV_UNKNOWN; break; } } /* //(EIP59738-)> // //---------------------------------------------------------------------------- // PROCEDURE: USBMassConsumeBulkData // // DESCRIPTION: This function reads unwanted amount of data specified in // the size // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // bXferDir Transfer direction // wLength Size of data to consume // // RETURN: USB_ERROR or USB_SUCCESS // //---------------------------------------------------------------------------- // UINT8 USBMassConsumeBulkData( DEV_INFO* fpDevInfo, UINT8 bXferDir, UINT16 wLength) { UINT16 wBytesToTransfer, wBytesRemaining; UINT32 dData; // // Need to process only maximum amount of data that pUSBMassConsumeBuffer can // handle, i.e. MAX_CONTROL_DATA_SIZE // wBytesRemaining = wLength; do { wBytesToTransfer = (UINT16)((wBytesRemaining < MAX_CONTROL_DATA_SIZE)? wBytesRemaining : MAX_CONTROL_DATA_SIZE); dData = USBMassIssueBulkTransfer(fpDevInfo, bXferDir, gUsbData->fpUSBMassConsumeBuffer, (UINT32)wBytesToTransfer); if ((UINT16)dData != wBytesToTransfer) { // Comparing word should be sufficient return USB_ERROR; } wBytesRemaining = (UINT16)(wBytesRemaining - dData); } while (wBytesRemaining); return USB_SUCCESS; } */ //<(EIP59738-) // //---------------------------------------------------------------------------- // PROCEDURE: USBMassProcessBulkData // // DESCRIPTION: This function reads/writes the data to the mass storage // device using bulk transfer. It also takes care of pre and // post skip bytes. // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // stMassXactStruc (given for reference) // bXferDir Transfer direction // fpBuffer Data buffer far pointer // dLength Amount of data to be transferred // wPreSkip Number of bytes to skip before data // wPostSkip Number of bytes to skip after data // // RETURN: Amount of data actually transferred // //---------------------------------------------------------------------------- // //(EIP70814)> UINT32 USBMassProcessBulkData( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT32 dData; UINT16 wTemp; UINT8 *Buffer; UINT8 *SrcBuffer; UINT8 *DestBuffer; UINT16 PreSkip; UINT32 XferSize; UINT32 XferedSize; UINT32 RemainingSize; //USB_DEBUG (DEBUG_LEVEL_3, "Pre,%x;Post,%x\n", MassXactStruc->wPreSkip, // MassXactStruc->wPostSkip); // // Check whether something we have to transfer // if (!MassXactStruc->dLength) { return 0; } wTemp = gUsbData->wTimeOutValue; // Save original value if (gUsbData->wBulkDataXferDelay) { // Check the bulk data delay specified gUsbData->wTimeOutValue = gUsbData->wBulkDataXferDelay; } if ((MassXactStruc->wPreSkip == 0) && (MassXactStruc->wPostSkip == 0)) { dData = USBMassIssueBulkTransfer( DevInfo, MassXactStruc->bXferDir, MassXactStruc->fpBuffer, MassXactStruc->dLength); } else { // Allocate a data buffer Buffer = USB_MemAlloc((UINT16)GET_MEM_BLK_COUNT(DevInfo->wBlockSize)); PreSkip = MassXactStruc->wPreSkip; RemainingSize = MassXactStruc->dLength - (PreSkip + MassXactStruc->wPostSkip); DestBuffer = MassXactStruc->fpBuffer; for (XferedSize = 0; XferedSize < MassXactStruc->dLength;) { XferSize = MassXactStruc->dLength >= DevInfo->wBlockSize ? DevInfo->wBlockSize : MassXactStruc->dLength; dData = USBMassIssueBulkTransfer( DevInfo, MassXactStruc->bXferDir, Buffer, XferSize); if (dData == 0) { //(EIP83295)> //return 0; XferedSize = 0; break; //<(EIP83295) } XferedSize += XferSize; if (RemainingSize == 0) { continue; } SrcBuffer = Buffer; if (PreSkip != 0) { if (PreSkip >= XferSize) { PreSkip -= XferSize; continue; } SrcBuffer += PreSkip; XferSize -= (UINT32)PreSkip; PreSkip = 0; } XferSize = RemainingSize < XferSize ? RemainingSize : XferSize; MemCopy(SrcBuffer, DestBuffer, XferSize); // Update the destination buffer pointer DestBuffer += XferSize; RemainingSize -= XferSize; } USB_MemFree(Buffer, (UINT16)GET_MEM_BLK_COUNT(DevInfo->wBlockSize)); dData = XferedSize; } gUsbData->wTimeOutValue = wTemp; // Restore original timeout value gUsbData->wBulkDataXferDelay = 0; return dData; } //<(EIP70814) // //---------------------------------------------------------------------------- // PROCEDURE: USBMassInquiryCommand // // DESCRIPTION: This function sends inquiry command to the USB mass storage // device // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // // RETURN: Pointer to the inquiry data // //---------------------------------------------------------------------------- // MASS_INQUIRY* USBMassInquiryCommand (DEV_INFO* fpDevInfo) { COMMON_INQ_CMD *fpCmdBuffer; UINT32 dData; MASS_XACT_STRUC MassXactStruc; // // Allocate memory for the command buffer // fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_INQ_CMD)); if(!fpCmdBuffer) { return NULL; } fpCmdBuffer->bOpCode = COMMON_INQUIRY_OPCODE; fpCmdBuffer->bAllocLength = 0x24; // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer; //(EIP51158+)> if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x06; //SPC-4_246 } else { MassXactStruc.bCmdSize = sizeof (COMMON_INQ_CMD); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer + 0x40; MassXactStruc.dLength = 0x24; USB_DEBUG (DEBUG_LEVEL_5, "Issue Inquiry Command .... \n"); dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_INQ_CMD)); if (dData) { return (MASS_INQUIRY*)(gUsbData->fpUSBTempBuffer + 0x40); } else { return NULL; } } // //---------------------------------------------------------------------------- // Procedure: USBMassRWVCommand // // Description: This function reads/writes/verifies blocks of data from the // USB mass device specified by its device address // // Input: fpDevInfo Pointer to DeviceInfo structure // bOpCode Read/Write/Verify // fpReadData Pointer to the read command structure // bDevAddr USB device address of the device // dStartLBA Starting LBA address // wNumBlks Number of blocks to process // wPreSkipSize Number of bytes to skip before // wPostSkipSize Number of bytes to skip after // fpBufferPtr Far buffer pointer // // Output: Return code (0 - Failure, <>0 - Size read) // fpReadData Pointer to the mass read command structure // dSenseData Sense data of the last command // fpBufferPtr Far buffer pointer // //---------------------------------------------------------------------------- // UINT16 USBMassRWVCommand( DEV_INFO *DevInfo, UINT8 OpCode, VOID *DataStruc ) { MASS_READ *MassDataStruc = (MASS_READ*)DataStruc; COMN_RWV_16_CMD *CmdBuffer; UINT64 StartLba; UINT32 BytesToRw; UINT32 Data; UINT32 SenseData; UINT8 Dir; // BIT7 0/1 - R/W UINT8 RetryNum; UINT16 RetCode = 0; UINT8 CmdSize; MASS_XACT_STRUC MassXactStruc; EFI_STATUS EfiStatus = EFI_SUCCESS; #if USB_RUNTIME_DRIVER_IN_SMM if (gCheckUsbApiParameter) { EfiStatus = AmiValidateMemoryBuffer((VOID*)MassDataStruc->BufferPtr, (UINT32)MassDataStruc->NumBlks * (UINT32)DevInfo->wBlockSize); if (EFI_ERROR(EfiStatus)) { USB_DEBUG(3, "UsbMassRWVCommand Invalid Pointer, Buffer is in SMRAM.\n"); return 0; } gCheckUsbApiParameter = TRUE; } #endif // // Set the sense code as 0 // MassDataStruc->SenseData = 0; // // Allocate memory for the command buffer // CmdBuffer = (COMN_RWV_16_CMD*)USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_RWV_16_CMD)); if (!CmdBuffer) { return 0; } for (RetryNum = 0; RetryNum < 2; RetryNum++) { // // Load command into (just allocated) mass command buffer // CmdBuffer->OpCode = OpCode; StartLba = MassDataStruc->StartLba; //(EIP60588+)> if (StartLba > (DevInfo->MaxLba - MassDataStruc->NumBlks)) { StartLba = DevInfo->MaxLba - MassDataStruc->NumBlks; } //<(EIP60588+) // // If the "Forced FDD" option is selected that means the device has // to be emulated as a floppy drive even though it has a HDD emulated // image. This is accomplished by hiding the first cylinder totally. // The partition table is in the first cylinder. LBA value for all // the requests to the device will be offset with the number of sectors // in the cylinder. // // // Check for forced floppy emulated device and change LBA accordingly // if (DevInfo->bEmuType == USB_EMU_FORCED_FDD) { if (!(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI)) //(EIP113379+) // // Skip first track in case of floppy emulation // StartLba += DevInfo->bHiddenSectors; } // // Check the validity of the block size // if (DevInfo->wBlockSize != 0xFFFF) { // // Change big endian format (INTEL) to little endian format // if ((OpCode == COMMON_READ_10_OPCODE) || (OpCode == COMMON_WRITE_10_OPCODE) || (OpCode == COMMON_VERIFY_10_OPCODE)) { ((COMN_RWV_10_CMD*)CmdBuffer)->dLba = dabc_to_abcd((UINT32)StartLba); ((COMN_RWV_10_CMD*)CmdBuffer)->wTransferLength = (UINT16)((MassDataStruc->NumBlks << 8) + (MassDataStruc->NumBlks >> 8)); if (DevInfo->bSubClass == SUB_CLASS_SCSI) { CmdSize = 0x0A; //SBC-3_60 } else { CmdSize = sizeof (COMN_RWV_10_CMD); } } else { CmdBuffer->Lba = Shl64(dabc_to_abcd((UINT32)StartLba), 32); CmdBuffer->Lba |= dabc_to_abcd((UINT32)Shr64(StartLba, 32)); CmdBuffer->TransferLength = dabc_to_abcd(MassDataStruc->NumBlks); CmdSize = sizeof(COMN_RWV_16_CMD); } // // Verify command does not need delay // gUsbData->wBulkDataXferDelay = 0; // // Calculate number of bytes to transfer (for verify command nothing // to read/write. // BytesToRw = 0; if ((OpCode != COMMON_VERIFY_10_OPCODE) && (OpCode != COMMON_VERIFY_16_OPCODE)){ // // Read/write command may need long time delay // gUsbData->wBulkDataXferDelay = 20000; BytesToRw = (UINT32)MassDataStruc->NumBlks * (UINT32)DevInfo->wBlockSize; } // // Set the direction properly // if ((OpCode == COMMON_WRITE_10_OPCODE) || (OpCode == COMMON_WRITE_16_OPCODE)) { Dir = 0; } else { Dir = BIT7; } // // Fill the common bulk transaction structure // Fill Command buffer address & size // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; MassXactStruc.bCmdSize = CmdSize; MassXactStruc.bXferDir = Dir; MassXactStruc.fpBuffer = (UINT8*)(UINTN)MassDataStruc->BufferPtr; MassXactStruc.wPreSkip = MassDataStruc->PreSkipSize; MassXactStruc.wPostSkip = MassDataStruc->PostSkipSize; MassXactStruc.dLength = BytesToRw; Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); if ((Data) && ((RetryNum != 0) || (Data == BytesToRw))) { // Some data processed. Set return value // // Bug fix for installing Linux from USB CD-ROM. // Linux64Bit Boot // If data read is 64K or higher return 0FFFFh // if (Data >= 0x010000) { Data = 0xFFFF; } RetCode = (UINT16)Data; // // Check for forced floppy emulated device // if ((DevInfo->bEmuType == USB_EMU_FORCED_FDD) && (OpCode == COMMON_READ_10_OPCODE) && (MassDataStruc->StartLba == 0) && !(gUsbData->dUSBStateFlag & USB_FLAG_RUNNING_UNDER_EFI) ) { //(EIP113379+) // // This is a floppy emulated ZIP drive, with read to // first sector. Update the boot record so that floppy // emulation is okay. // // Force #of hidden sectors to 0 // *(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0xB + 0x11) = 0; // // FreeDOS workaround // if ((*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 3)==0x65657246) && // 'eerF' (*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 7)==0x20534F44) && // ' SOD' (*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0x3A)!=0x20202032)) { //(EIP61388) *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x42) = *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x42)-(UINT16)DevInfo->bHiddenSectors; *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x46) = *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x46)-(UINT16)DevInfo->bHiddenSectors; *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x4A) = *(UINT16*)((UINTN)MassDataStruc->BufferPtr + 0x4A)-(UINT16)DevInfo->bHiddenSectors; } // // Force physical drive# to 0 // For FAT32, physical drive number is present in offset 40h // if ((*(UINT32*)((UINTN)MassDataStruc->BufferPtr + 0x52)) == 0x33544146) { // "3TAF", FAT3 *(UINT8*)((UINTN)MassDataStruc->BufferPtr + 0x40) = 0; } else { *(UINT8*)((UINTN)MassDataStruc->BufferPtr + 0x24) = 0; } } break; // dData ready } else { // Error condition: dData = 0, RetCode = 0 // // Check for error // SenseData = USBMassRequestSense(DevInfo); MassDataStruc->SenseData = SenseData; Data = SenseData; // // Check for write protect error code // if ((UINT8)SenseData == 7) { break; } if (((OpCode == COMMON_VERIFY_10_OPCODE) || (OpCode == COMMON_VERIFY_16_OPCODE)) && (!SenseData)) { // // This is verify command so no data to send or read and // also sense data is 0. So set return value to success. // RetCode = 0xFFFF; break; } } } // fpDevInfo->wBlockSize != 0xFFFF // // UPRCC_ProceedIfRW // May be drive error, try to correct it // Check whether the drive is ready for read/write/verify command // Data = USBMassCheckDeviceReady(DevInfo); MassDataStruc->SenseData = Data; if (Data) { break; // Return error } MemFill((UINT8*)CmdBuffer, sizeof(COMN_RWV_16_CMD), 0); } // Fof loop USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_RWV_16_CMD)); return RetCode; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassStartUnitCommand // // DESCRIPTION: This function sends the start unit command to the mass device // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // // RETURN: Sense data: 0 - Success, <>0 - Error // //---------------------------------------------------------------------------- // UINT16 USBMassStartUnitCommand (DEV_INFO* fpDevInfo) { COMMON_START_STOP_UNIT_CMD *fpCmdBuffer; MASS_XACT_STRUC MassXactStruc; // MASS_START_STOP_UNIT *fpStartData; USB_DEBUG (DEBUG_LEVEL_5, "USBMProStartUnitCommand .... \n"); // // Check the compatibility flag for start unit command not supported // if (fpDevInfo->wIncompatFlags & USB_INCMPT_START_UNIT_NOT_SUPPORTED) { return USB_SUCCESS; } // // Allocate memory for the command buffer // fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_START_STOP_UNIT_CMD)); if (!fpCmdBuffer) { return USB_ERROR; } // // Load command into (just allocated) mass command buffer // fpCmdBuffer->bOpCode = COMMON_START_STOP_UNIT_OPCODE; fpCmdBuffer->bStart = 1; // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); gUsbData->wBulkDataXferDelay = 10000; // Start unit command may need long time delay // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer; //(EIP51158+)> if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x06; //SBC-3_77 } else { MassXactStruc.bCmdSize = sizeof (COMMON_START_STOP_UNIT_CMD); } //<(EIP51158+) USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc); // // No data to read/write. So do not process return code. // Check and free command buffer // USB_MemFree(fpCmdBuffer,GET_MEM_BLK_COUNT_STRUC(COMMON_START_STOP_UNIT_CMD)); return USBMassRequestSense(fpDevInfo); } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassModeSense // // DESCRIPTION: This function requests the mode sense data page number 5 from // the USB mass storage device // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // // RETURN: USB_SUCCESS/USB_ERROR on Success/Failure // fpModeSenseData Pointer to the mode sense data // dSenseData Sense data // bNumHeads Number of heads // wNumCylinders Number of cylinders // bNumSectors Number of sectors // wBytesPerSector Number of bytes per sector // bMediaType Media type // //---------------------------------------------------------------------------- // UINT8 USBMassModeSense( DEV_INFO *fpDevInfo, MASS_MODE_SENSE *fpModeSenseData) { UINT32 dData; UINT8 bRetCode; COMN_MODE_SENSE_10CMD *fpCmdBuffer; MODE_SENSE_10_HEADER *fpModeSense10_Header; PAGE_CODE_5 *fpPageCode5; MASS_XACT_STRUC MassXactStruc; dData = 0; bRetCode = USB_ERROR; fpCmdBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD)); if (!fpCmdBuffer) { return USB_ERROR; } // // Load command into (just allocated) mass command buffer // fpCmdBuffer->bOpCode = COMMON_MODE_SENSE_10_OPCODE; fpCmdBuffer->wAllocLength = 0x2800; // Allocation Length = 40 bytes (0x28) fpCmdBuffer->bPageCode = 5; // Page code // // Clear the common bulk transaction structure // USBMassClearMassXactStruc(&MassXactStruc); // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer; //(EIP51158+)> if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x0A; //SPC-4_280 } else { MassXactStruc.bCmdSize = sizeof (COMN_MODE_SENSE_10CMD); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = gUsbData->fpUSBTempBuffer; MassXactStruc.dLength = 0x28; // // Bulk in, with temp buffer & 40 bytes of data to read // dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc); if (!dData) { USBMassRequestSense( fpDevInfo ); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD)); return USB_ERROR; } // // Fill in the output data // fpModeSense10_Header = (MODE_SENSE_10_HEADER*)gUsbData->fpUSBTempBuffer; // // Process media type // fpModeSenseData->bMediaType = fpModeSense10_Header->bMediaType; // // Position to the correct page code starting location // fpPageCode5 = (PAGE_CODE_5*)((UINT8*)fpModeSense10_Header + fpModeSense10_Header->wBlkDescSize + sizeof (MODE_SENSE_10_HEADER)); // USB_DEBUG (DEBUG_LEVEL_3, "USBMassModeSense .... fpPageCode5->bPageCode %x\n",fpPageCode5->bPageCode); bRetCode = USB_ERROR; if(fpPageCode5->bPageCode == 5) { // // Process number of bytes per sector (the block size) // fpModeSenseData->wBytesPerSector = (UINT16)((fpPageCode5->wBlockSize << 8) + (fpPageCode5->wBlockSize >>8)); // // Process number of heads and number of sectors/track // fpModeSenseData->bNumHeads = fpPageCode5->bHeads; fpModeSenseData->bNumSectors = fpPageCode5->bSectors; // // Process number of cylinders // fpModeSenseData->wNumCylinders = (UINT16)((fpPageCode5->wCylinders << 8) + (fpPageCode5->wCylinders >> 8)); bRetCode = USB_SUCCESS; } fpModeSenseData->dSenseData = USBMassRequestSense( fpDevInfo ); USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_MODE_SENSE_10CMD)); // USB_DEBUG (DEBUG_LEVEL_5, "USBMProModeSense .... wRetCode %x\n",wRetCode); return bRetCode; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassRequestSense // // DESCRIPTION: This function sends request sense command and returns // the sense key information // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // // RETURN: Sense data // //---------------------------------------------------------------------------- // UINT32 USBMassRequestSense(DEV_INFO* fpDevInfo) { UINT32 dData; UINT8 *fpDataBuffer; COMMON_REQ_SENSE_CMD *fpCmdBuffer; MASS_XACT_STRUC MassXactStruc; // // Allocate memory for the command buffer // fpCmdBuffer = (COMMON_REQ_SENSE_CMD*)USB_MemAlloc(GET_MEM_BLK_COUNT_STRUC(COMMON_REQ_SENSE_CMD)); if(!fpCmdBuffer) { return USB_ERROR; // Error - return no sense data <>0 } fpDataBuffer = USB_MemAlloc(GET_MEM_BLK_COUNT(1)); if(!fpDataBuffer) { return USB_ERROR; // Error - return no sense data <>0 } // // Load command into (just allocated) mass command buffer // fpCmdBuffer->bOpCode = COMMON_REQUEST_SENSE_OPCODE; fpCmdBuffer->bAllocLength = 0x12; // Length of transfer USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)fpCmdBuffer; //(EIP51158+)> if (fpDevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x06; //SPC-4_350 } else { MassXactStruc.bCmdSize = sizeof (COMMON_REQ_SENSE_CMD); } //<(EIP51158+) MassXactStruc.bXferDir = BIT7; // IN MassXactStruc.fpBuffer = fpDataBuffer; MassXactStruc.dLength = 0x12; // // Bulk in, with locally allocated temp buffer & 12h bytes of data to read // dData = USBMassIssueMassTransaction(fpDevInfo, &MassXactStruc); if(dData) { // // Form the return value: // Bit 0..7 - Sense key (offset 002d) // Bit 8..15 - ASC code (offset 012d) // Bit 16..23 - ASCQ code (offset 013d) // dData = (UINT32)(fpDataBuffer[2] + (fpDataBuffer[12] << 8) + (fpDataBuffer[13] << 16)); USBMassSenseKeyParsing(fpDevInfo, dData); } //(EIP20863+)> else dData = USB_ERROR; //<(EIP20863+) USB_MemFree(fpCmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMMON_REQ_SENSE_CMD)); USB_MemFree(fpDataBuffer, GET_MEM_BLK_COUNT(1)); return dData; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassSenseKeyParsing // // DESCRIPTION: Translate USB sense key to USB MassStorage status. // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // dCode[23..16] ASCQ // dCode[15..08] ASC // dCode[07..00] Sense Code // // RETURN: Sense data // //---------------------------------------------------------------------------- // VOID USBMassSenseKeyParsing(DEV_INFO* fpDevInfo, UINT32 dCode) { if ((UINT16)dCode == 0x3A02) { //(EIP86793) fpDevInfo->bLastStatus &= ~USB_MASS_MEDIA_PRESENT; } if((UINT16)dCode == 0x2806) { fpDevInfo->bLastStatus |= (USB_MASS_MEDIA_PRESENT | USB_MASS_MEDIA_CHANGED); } //(EIP86125+)> if(dCode == 0) { fpDevInfo->bLastStatus |= USB_MASS_MEDIA_PRESENT; } //<(EIP86125+) } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassTestUnitReady // // DESCRIPTION: This function sends test unit ready command // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // // RETURN: Sense data // //---------------------------------------------------------------------------- // UINT32 USBMassTestUnitReady( DEV_INFO* DevInfo ) { COMN_TEST_UNIT_READY_CMD *CmdBuffer; UINT32 Data; MASS_XACT_STRUC MassXactStruc; CmdBuffer = (COMN_TEST_UNIT_READY_CMD*)USB_MemAlloc( GET_MEM_BLK_COUNT_STRUC(COMN_TEST_UNIT_READY_CMD)); if (!CmdBuffer) { return USB_ERROR; // Error - return no sense data } CmdBuffer->bOpCode = COMMON_TEST_UNIT_READY_OPCODE; USB_DEBUG (DEBUG_LEVEL_5, "USBMassTestUnitReady .... \n"); USBMassClearMassXactStruc(&MassXactStruc); // Clear the common bulk transaction structure // // Fill the common bulk transaction structure // MassXactStruc.fpCmdBuffer = (UINT8*)CmdBuffer; //(EIP51158+)> if (DevInfo->bSubClass == SUB_CLASS_SCSI) { MassXactStruc.bCmdSize = 0x06; //SPC-4_368 } else { MassXactStruc.bCmdSize = sizeof (COMN_TEST_UNIT_READY_CMD); } //<(EIP51158+) Data = USBMassIssueMassTransaction(DevInfo, &MassXactStruc); USB_MemFree(CmdBuffer, GET_MEM_BLK_COUNT_STRUC(COMN_TEST_UNIT_READY_CMD)); if ((Data == USB_ERROR) || (DevInfo->bProtocol == PROTOCOL_CBI) || (DevInfo->bProtocol == PROTOCOL_CBI_NO_INT)) { Data = USBMassRequestSense(DevInfo); } return Data; } // //---------------------------------------------------------------------------- // Procedure: USBMassCheckDeviceReady // // Description: This function makes sure the device is ready for next // command // // Input: fpDevInfo Pointer to DeviceInfo structure // // Output: Sense code // //---------------------------------------------------------------------------- // UINT32 USBMassCheckDeviceReady (DEV_INFO* fpDevInfo) { UINT8 count, nomedia_count; UINT8 NotReadyCount; //(EIP101623+) UINT32 dData = 0; count = gUsbData->bUSBStorageDeviceDelayCount; nomedia_count = 3; NotReadyCount = 3; //(EIP101623+) while (count) { if (fpDevInfo->wIncompatFlags & USB_INCMPT_TEST_UNIT_READY_FAILED) { break; // consider device is ready } // // Issue test unit ready command and check the return value // dData = USBMassTestUnitReady( fpDevInfo ); //USB_DEBUG(DEBUG_LEVEL_3, "(%d)tur..%x ", fpDevInfo->bDeviceAddress, dData); if ((UINT8)dData == 0) { // Device ready break; } // // Device is not ready. // Check for getting ready/reset command occurence in dData: // Bit 0..7 - Sense Code // Bit 8..15 - Additional Sense Code (ASC) // Bit 16..23 - Additional Sense Code Qualifier (ASCQ) // if ((UINT16)dData == 0x2806) { // // Send Start/Stop Unit command to UFI class device only // if (fpDevInfo->bSubClass == SUB_CLASS_UFI) { USBMassStartUnitCommand (fpDevInfo); } FixedDelay(100 * 1000); // 100 msec delay count--; continue; } if ((UINT16)dData == 0x3A02) { // Media is not present nomedia_count--; if (nomedia_count == 0) return dData; // No media FixedDelay(20 * 1000); // 20 msec delay count--; continue; } if (dData == 0x020402) { USBMassStartUnitCommand (fpDevInfo); FixedDelay(100 * 1000); count--; continue; } if ((UINT16)dData == 0x1103) { FixedDelay(100 * 1000); count--; continue; } // // Check whether we can recover from this error condition // Currently only recoverable error condition are // 1. Device is getting ready (010402) // 2. Device reset occurred (002906) // if (dData != 0x010402) { // // Check for write protected command // if ( (UINT8)dData == 7 ) { break; } if (((UINT8)dData != 0x06) && ((UINT8)dData != 0x02)) { return dData; } } //(EIP101623+)> if (dData == 0x02) { NotReadyCount--; if (NotReadyCount == 0) return dData; FixedDelay(20 * 1000); // 20 msec delay count--; continue; } //<(EIP101623+) // // Prepare for the next itaration // Delay for the device to get ready // FixedDelay(1000 * 1000); // 1 sec delay count--; } // while //(EIP53416+)> if (count == 0) { return dData; } //<(EIP53416+) return USBMassUpdateDeviceGeometry(fpDevInfo); } // //---------------------------------------------------------------------------- // Procedure: USBMassUpdateParamUsingModeSense // // Description: This function obtains the device geometry from the device // using mode sense command and updates the global variables // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR On error // USB_SUCCESS On success // //---------------------------------------------------------------------------- // UINT8 USBMassUpdateParamUsingModeSense(DEV_INFO* fpDevInfo) { MASS_MODE_SENSE ModeSenseData; gUsbData->wModeSenseCylinders = gUsbData->bModeSenseHeads = gUsbData->bModeSenseSectors = 0; // // Check the compatibility flag for mode sense support // if (fpDevInfo->wIncompatFlags & USB_INCMPT_MODE_SENSE_NOT_SUPPORTED) { return USB_SUCCESS; } // // CDROM devices never support mode sense page code 5 (Flexible disk page) // so skip it // if (fpDevInfo->bStorageType == USB_MASS_DEV_CDROM) { return USB_ERROR; } // // Issue mode sense command // if (USBMassModeSense(fpDevInfo, &ModeSenseData)) { USB_DEBUG(DEBUG_LEVEL_3, "ms..err "); return USB_ERROR; } // // Mode sense is supported. Update the local structure. // gUsbData->wModeSenseCylinders = ModeSenseData.wNumCylinders; // Number of cylinders gUsbData->bModeSenseHeads = ModeSenseData.bNumHeads; // Number of heads gUsbData->bModeSenseSectors = ModeSenseData.bNumSectors; // Number of sectors gUsbData->wModeSenseBlockSize = ModeSenseData.wBytesPerSector;// Number of bytes per sector gUsbData->bDiskMediaType = ModeSenseData.bMediaType; // Media type USB_DEBUG(DEBUG_LEVEL_4, "ms..%x %x %x %x %x ", gUsbData->wModeSenseCylinders, gUsbData->bModeSenseHeads, gUsbData->bModeSenseSectors, gUsbData->wModeSenseBlockSize, gUsbData->bDiskMediaType ); if (fpDevInfo->bStorageType == USB_MASS_DEV_HDD) { gUsbData->bDiskMediaType = USB_UNKNOWN_MEDIA_TYPE; } // // Calculate and update Max LBA // gUsbData->dModeSenseMaxLBA = (UINT32)(ModeSenseData.wNumCylinders * ModeSenseData.bNumHeads * ModeSenseData.bNumSectors); // // Set the flag indicating mode sense is executed // gUsbData->bGeometryCommandStatus |= MODE_SENSE_COMMAND_EXECUTED; return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassUpdateParamUsingReadCapacity // // Description: This function obtains the device geometry from the device // using read capacity command and updates the global variables // // Input: Pointer to DeviceInfo structure // // Output: USB_ERROR On error // USB_SUCCESS On success // //---------------------------------------------------------------------------- // UINT8 USBMassUpdateParamUsingReadCapacity( DEV_INFO* DevInfo ) { UINT8 Sectors; UINT8 Heads; // // Either mode sense not supported or failed. Try read capacity // Issue read capacity command // if (USBMassReadCapacity10Command(DevInfo)) { return USB_ERROR; } // // Set the flag indicating read capacity is executed // gUsbData->bGeometryCommandStatus |= READ_CAPACITY_COMMAND_EXECUTED; // // Max LBA & block size are updated in MassDeviceInfo structure // if (DevInfo->MaxLba < 0x4000) { // last LBA < 16MB switch (DevInfo->MaxLba) { case USB_144MB_FDD_MAX_LBA: gUsbData->bReadCapHeads = USB_144MB_FDD_MAX_HEADS; gUsbData->bReadCapSectors = USB_144MB_FDD_MAX_SECTORS; gUsbData->wReadCapCylinders= USB_144MB_FDD_MAX_CYLINDERS; gUsbData->bDiskMediaType = USB_144MB_FDD_MEDIA_TYPE; return USB_SUCCESS; case USB_720KB_FDD_MAX_LBA: gUsbData->bReadCapHeads = USB_720KB_FDD_MAX_HEADS; gUsbData->bReadCapSectors = USB_720KB_FDD_MAX_SECTORS; gUsbData->wReadCapCylinders= USB_720KB_FDD_MAX_CYLINDERS; gUsbData->bDiskMediaType = USB_720KB_FDD_MEDIA_TYPE; return USB_SUCCESS; } } // // Convert to CHS // gUsbData->wReadCapBlockSize = DevInfo->wBlockSize; // // Do CHS conversion // Use fixed sectors/track & heads for CHS conversion // if (DevInfo->MaxLba < 0x400) { // < 512 KB Sectors = 1; Heads = 1; } else { if (DevInfo->MaxLba < 0x200000) { // < 1GB Sectors = USB_FIXED_LBA_SPT_BELOW_1GB; Heads = USB_FIXED_LBA_HPT_BELOW_1GB; } else { // > 1GB Sectors = USB_FIXED_LBA_SPT_ABOVE_1GB; Heads = USB_FIXED_LBA_HPT_ABOVE_1GB; } } gUsbData->bReadCapSectors = Sectors; gUsbData->bReadCapHeads = Heads; // // Calculate number of cylinders Cyl = LBA/(Head*Sec) // if ((Sectors != 0) && (Heads != 0)) { gUsbData->wReadCapCylinders = (UINT16)Div64(DevInfo->MaxLba, (Sectors * Heads), NULL); } else { gUsbData->wReadCapCylinders = 0; } return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassUpdateDeviceGeometry // // Description: This function updates the device geometry information // // Input: Pointer to device info structure // // Output: USB_SUCCESS or USB_ERROR // //---------------------------------------------------------------------------- // UINT8 USBMassUpdateDeviceGeometry ( DEV_INFO* DevInfo ) { UINT64 MaxLba; UINT8 Heads; UINT8 Sectors; UINT16 Cylinders; UINT8 Status; // // Try to update geometry if it is not valid // "Valid" block size is 1...FFFE // Additional check added to ensure the head, sector, and cylinder values are non-zero. // //(EIP13457+)> if ((DevInfo->Heads != 0) && (DevInfo->bSectors != 0) && (DevInfo->wCylinders != 0) && !(DevInfo->bLastStatus & USB_MASS_MEDIA_CHANGED) && (!((DevInfo->bLastStatus & USB_MASS_GET_MEDIA_FORMAT) && (DevInfo->bSubClass == SUB_CLASS_UFI)))) { DevInfo->bLastStatus &= ~USB_MASS_GET_MEDIA_FORMAT; if (DevInfo->wBlockSize && (DevInfo->wBlockSize != 0xFFFF)) { return USB_SUCCESS; } } DevInfo->bLastStatus &= ~USB_MASS_GET_MEDIA_FORMAT; // // Set default values for the global variables // gUsbData->bDiskMediaType = USB_UNKNOWN_MEDIA_TYPE; gUsbData->bGeometryCommandStatus &= ~(MODE_SENSE_COMMAND_EXECUTED | READ_CAPACITY_COMMAND_EXECUTED); // // Get disk geometry using Mode Sense // if (DevInfo->bSubClass == SUB_CLASS_UFI) { //(EIP94060) USBMassUpdateParamUsingModeSense(DevInfo); } // // Get disk geometry using Read Capacity // Status = USBMassUpdateParamUsingReadCapacity(DevInfo); // // Parameters are obtained and stored in respective global variables; // check whether any of the commands executed. // if (!(gUsbData->bGeometryCommandStatus & (READ_CAPACITY_COMMAND_EXECUTED | MODE_SENSE_COMMAND_EXECUTED))) { USB_DEBUG(DEBUG_LEVEL_3, "-error\n"); return USB_ERROR; } // // Check whether read capacity is executed. If so, then max LBA & block size // are already updated in the MassDeviceInfo structure. If not update it using // mode sense parameters // if (!(gUsbData->bGeometryCommandStatus & READ_CAPACITY_COMMAND_EXECUTED)) { // // At this point we made sure atleast one of the command (Mode sense or Read // Capacity) was executed. So if one command is not executed then other // command is surely executed. // // // Update the max LBA & block size using mode sense parameters // DevInfo->wBlockSize = gUsbData->wModeSenseBlockSize; DevInfo->MaxLba = gUsbData->dModeSenseMaxLBA; USB_DEBUG(DEBUG_LEVEL_4, "size %x lba %lx\n", DevInfo->wBlockSize, DevInfo->MaxLba); } //Some usb mass storages report media change even if they don't, we already //update CHS from boot record and legacy boot doesn't support dynamic //media insertion, we should not update it from read capacity parameters. if ((DevInfo->Heads != 0) && (DevInfo->bSectors != 0) && (DevInfo->wCylinders !=0)) { return USB_SUCCESS; } // // Update the media type byte // DevInfo->bMediaType = gUsbData->bDiskMediaType; // // Check whether mode sense is executed. If so, then update CHS from mode // sense value or else update from read capacity values. // // // Update the CHS values using mode sense parameters // Heads = gUsbData->bModeSenseHeads; Sectors = gUsbData->bModeSenseSectors; Cylinders = gUsbData->wModeSenseCylinders; // if ((gUsbData->bGeometryCommandStatus & MODE_SENSE_COMMAND_EXECUTED) && if ((Heads * Sectors * Cylinders) == 0) { // // Update the CHS values using read capacity parameters // Heads = gUsbData->bReadCapHeads; Sectors = gUsbData->bReadCapSectors; Cylinders = gUsbData->wReadCapCylinders; } USB_DEBUG (DEBUG_LEVEL_4, "Cyl-%x, Hds-%x, Sec-%x", Cylinders, Heads, Sectors); DevInfo->Heads = Heads; DevInfo->bSectors = Sectors; DevInfo->wCylinders = Cylinders; // // Calculate non-LBA CHS values from max LBA // MaxLba = DevInfo->MaxLba; // // Do not translate sectors for non HDD devices // if ((!DevInfo->bStorageType) || (DevInfo->bStorageType == USB_MASS_DEV_HDD)) { // // If Total number of sectors < 1032192(0FC000h) CHS translation is not // needed // if (MaxLba >= 0xFC000) { Sectors = 63; Heads = 32; // // If Total number of sectors < 2064384(01F8000h) then use // 63 Sec/track and 32 head for translation // if (MaxLba >= 0x01F8000) { Heads = 64; // // If Total number of sectors < 4128768(03F0000h) then use // 63 Sec/track and 64 head for translation // if (MaxLba >= 0x03F0000) { Heads = 128; // // If Total number of sectors < 8257536(07E0000h) then use // 63 Sec/track and 128 head for translation else use 255 heads // if (MaxLba >= 0x7E0000) { Heads = 255; MaxLba = DevInfo->MaxLba; } } } } // // In any case, check the parameters for maximum values allowed by BIOS and // ATA specs (that is, 1024 cylinders, 16 heads and 63 sectors per track) // for (;;) { // // Calculate translated number of cylinders // if ((Sectors != 0) && (Heads != 0)) { Cylinders = (UINT16)Div64(MaxLba, (Heads * Sectors), NULL); } else { Cylinders = 0; } // // Check whether number of cylinders is less than or equal to 1024 // if (Cylinders <= 1024) break; // // Cylinders are getting larger than usually supported try increasing // head count keeping cylinders within safe limit // Cylinders = 1024; if (Heads == 0xFF) { break; // Heads limit reached } // // Double number of heads // Heads <<= 1; if (!Heads) { Heads = 0xFF; } } } // // Save the parameters // DevInfo->NonLBAHeads = Heads; DevInfo->bNonLBASectors = Sectors; DevInfo->wNonLBACylinders = Cylinders; USB_DEBUG(DEBUG_LEVEL_5, "BPS %d H %d S %d C %d MT %d\n", DevInfo->wBlockSize, DevInfo->Heads, DevInfo->bSectors, DevInfo->wCylinders, DevInfo->bMediaType); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassIssueBOTTransaction // // Description: This function performs a mass storage transaction using bulk // only transport (BOT) protocol. // // Input: Pointer to DeviceInfo structure // stMassXactStruc // pCmdBuffer Pointer to command buffer // bCmdSize Size of command block // bXferDir Transfer direction // fpBuffer Data buffer far pointer // dwLength Amount of data to be transferred // wPreSkip Number of bytes to skip before data // wPostSkip Number of bytes to skip after data // // Output: Amount of data actually transferred // //---------------------------------------------------------------------------- // UINT32 USBMassIssueBOTTransaction( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT32 Data; UINT8 Status; Data = USBMassSendBOTCommand(DevInfo, MassXactStruc); // Send the command control transfer if (!Data) { // // Check for stall/timedout condition // if (gUsbData->bLastCommandStatus & (USB_BULK_STALLED + USB_BULK_TIMEDOUT)) { // // Perform USB BOT reset recovery // USBMassBOTResetRecovery(DevInfo); return 0; } else { return 0; // Unknown error exit } } if (!MassXactStruc->dLength) { // No data if (gUsbData->wBulkDataXferDelay) { // // Issue some delay // FixedDelay(100 * 1000); gUsbData->wBulkDataXferDelay = 0; } // // Get the status for the last transfer // Data = USBMassGetBOTStatus(DevInfo, MassXactStruc); return Data; } // // Tranfer the bulk data // Data = USBMassProcessBulkData(DevInfo, MassXactStruc); // Actual data size // // Check for stall/timeout condition // if (!(gUsbData->bLastCommandStatus & (USB_BULK_STALLED + USB_BULK_TIMEDOUT))) { // // Get the status for the last transfer // Status = USBMassGetBOTStatus(DevInfo, MassXactStruc); if ((Status == USB_ERROR) || (gUsbData->bLastCommandStatus & USB_BULK_TIMEDOUT)) { return 0; } else { return Data; } } // // Check for time out condition // if (gUsbData->bLastCommandStatus & USB_BULK_TIMEDOUT) { // // Perform USB BOT reset recovery // USBMassBOTResetRecovery(DevInfo); return 0; } // // Clear endpoint stall // USBMassClearBulkEndpointStall(DevInfo, MassXactStruc->bXferDir); // // Get the status for the last transfer // USBMassGetBOTStatus(DevInfo, MassXactStruc); return Data; } // //---------------------------------------------------------------------------- // PROCEDURE: USBBOTSendCommand // // DESCRIPTION: This function performs a mass storage transaction using bulk // only transport (BOT) protocol. // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // bXferDir Transfer direction // dwDataSize Amount of data to be transferred // fpCmdBuffer Pointer to the command buffer // bCmdSize Size of command block // RETURN: Amount of data actually transferred // //---------------------------------------------------------------------------- // UINT16 USBMassSendBOTCommand( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT8 Count; UINT8 *Src; UINT8 *Dest; BOT_CMD_BLK *BotCmdBlk; UINT8 CmdSize; BotCmdBlk = (BOT_CMD_BLK*)MassXactStruc->fpCmdBuffer; CmdSize = MassXactStruc->bCmdSize; // if( !VALID_DEVINFO2( fpDevInfo) ) // return 0; // // Make enough space for BOT command block wrapper // Move backwards // Src = MassXactStruc->fpCmdBuffer + CmdSize - 1; // // BOT_COMMAND_BLOCK + end of command // Dest = Src + ((UINT8*)BotCmdBlk->aCBWCB - (UINT8*)BotCmdBlk); for (Count = 0; Count < CmdSize; Count++) { *Dest = *Src; --Dest; --Src; } //fpDest = gUsbData->stMassXactStruc.fpCmdBuffer; // // Clear the BOT command block // //for (bCount = 0; bCount < bCmdSize; bCount++) { // *fpDest = 0x00; // ++fpDest; //} BotCmdBlk->dCbwSignature = BOT_CBW_SIGNATURE; BotCmdBlk->dCbwTag = ++(gUsbData->dBOTCommandTag); BotCmdBlk->dCbwDataLength = MassXactStruc->dLength; BotCmdBlk->bmCbwFlags = MassXactStruc->bXferDir; BotCmdBlk->bCbwLun = DevInfo->bLUN; BotCmdBlk->bCbwLength = CmdSize; return (UINT16)USBMassIssueBulkTransfer( DevInfo, 0, (UINT8*)BotCmdBlk, sizeof (BOT_CMD_BLK)); } // //---------------------------------------------------------------------------- // Procedure: USBBOTGetStatus // // Description: This function gets the BOT status sequence using // bulk IN transfer // // Input: fpDevInfo Pointer to DeviceInfo structure // // Output: Nothing // //---------------------------------------------------------------------------- // UINT8 USBMassGetBOTStatus( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { //(EIP90503)> UINT8* CmdBuffer; UINT16 Data; CmdBuffer = MassXactStruc->fpCmdBuffer; Data = (UINT16)USBMassIssueBulkTransfer(DevInfo, BIT7, CmdBuffer, sizeof (BOT_STATUS_BLOCK)); if ((Data != sizeof (BOT_STATUS_BLOCK))) { if (gUsbData->bLastCommandStatus & USB_BULK_STALLED) { USBMassClearBulkEndpointStall(DevInfo, BIT7); } Data = (UINT16)USBMassIssueBulkTransfer(DevInfo, BIT7, CmdBuffer, sizeof (BOT_STATUS_BLOCK)); if (gUsbData->bLastCommandStatus & USB_BULK_STALLED) { USBMassBOTResetRecovery(DevInfo); return USB_ERROR; } } // // Check for valid CSW // if ((Data != sizeof (BOT_STATUS_BLOCK)) || (((BOT_STATUS_BLOCK*)CmdBuffer)->dCswSignature != BOT_CSW_SIGNATURE) || (((BOT_STATUS_BLOCK*)CmdBuffer)->dCswTag != gUsbData->dBOTCommandTag)) { //USBMassClearBulkEndpointStall(fpDevInfo, BIT7); //(EIP63308-) //USBMassClearBulkEndpointStall(fpDevInfo, BIT0); //(EIP63308-) return USB_ERROR; } //<(EIP90503) // // Check for meaningful CSW // if (((BOT_STATUS_BLOCK*)CmdBuffer)->bmCswStatus) { if (((BOT_STATUS_BLOCK*)CmdBuffer)->bmCswStatus > 1) { // // Perform reset recovery if BOT status is phase error // USBMassBOTResetRecovery(DevInfo); } return USB_ERROR; } return USB_SUCCESS; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassBOTResetRecovery // // DESCRIPTION: This function performs the BOT reset recovery // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // //---------------------------------------------------------------------------- // VOID USBMassBOTResetRecovery(DEV_INFO* fpDevInfo) { (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer) (gUsbData->HcTable[fpDevInfo->bHCNumber - 1], //(EIP20863)> //fpDevInfo, ADSC_OUT_REQUEST_TYPE, //(UINT16)fpDevInfo->bInterfaceNum,BOT_RESET_REQUEST_CODE, 0, 0); fpDevInfo, ADSC_OUT_REQUEST_TYPE + (BOT_RESET_REQUEST_CODE << 8), (UINT16)fpDevInfo->bInterfaceNum, 0, 0, 0); //<(EIP20863) USBMassClearBulkEndpointStall(fpDevInfo, BIT7); USBMassClearBulkEndpointStall(fpDevInfo, BIT0); } // //---------------------------------------------------------------------------- // Procedure: USBMassBOTGetMaxLUN // // Description: This function gets the maximum logical unit number(LUN) // supported by the device. It is zero based value. // // Input: Pointer to DeviceInfo structure // // Output: Max LUN supported // //---------------------------------------------------------------------------- // UINT16 USBMassBOTGetMaxLUN( DEV_INFO* DevInfo ) { UINT8 *Buffer = NULL; UINT8 MaxLun = 0; UINT16 Status; if (DevInfo->wIncompatFlags & USB_INCMPT_GETMAXLUN_NOT_SUPPORTED) { return 0; } Buffer = USB_MemAlloc(1); ASSERT(Buffer); if (Buffer == NULL) { return 0; } Status = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable [DevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer) (gUsbData->HcTable[DevInfo->bHCNumber - 1], DevInfo, ADSC_IN_REQUEST_TYPE + (BOT_GET_MAX_LUN_REQUEST_CODE << 8), DevInfo->bInterfaceNum, 0, Buffer, 1); if (Status) { MaxLun = *Buffer; } USB_MemFree(Buffer, 1); return MaxLun; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassIssueCBITransaction // // DESCRIPTION: This function performs a mass storage transaction using CBI // or CB protocol. // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // fpCmdBuffer Pointer to command buffer // bCmdSize Size of command block // bXferDir Transfer direction // fpBuffer Data buffer far pointer // dwLength Amount of data to be transferred // wPreSkip Number of bytes to skip before data // wPostSkip Number of bytes to skip after data // // RETURN: Amount of data actually transferred // //---------------------------------------------------------------------------- // UINT32 USBMassIssueCBITransaction( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT32 Data = 0; if (!(USBMassSendCBICommand(DevInfo, MassXactStruc))) { // Returns 0 on error return 0; } if (MassXactStruc->dLength) { Data = USBMassProcessBulkData(DevInfo, MassXactStruc); if (!Data) { if(gUsbData->bLastCommandStatus & USB_BULK_STALLED) { USBMassClearBulkEndpointStall(DevInfo, MassXactStruc->bXferDir); return Data; } } } if(DevInfo->bProtocol != PROTOCOL_CBI_NO_INT && DevInfo->IntInEndpoint != 0) { // // Bypass interrupt transaction if it is CB protocol // USBMassCBIGetStatus(DevInfo); } return Data; } // //---------------------------------------------------------------------------- // PROCEDURE: USBMassSendCBICommand // // DESCRIPTION: This function performs a mass storage transaction using CBI // or CB protocol. // // PARAMETERS: fpDevInfo Pointer to DeviceInfo structure // fpCmdBuffer Pointer to the command buffer // bCmdSize Size of command block // // RETURN: 0xFFFF SUCCESS // 0x00 ERROR // //---------------------------------------------------------------------------- // UINT16 USBMassSendCBICommand( DEV_INFO* DevInfo, MASS_XACT_STRUC* MassXactStruc ) { UINT16 RetValue; RetValue = (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable [DevInfo->bHCNumber - 1]->bHCType)].pfnHCDControlTransfer) (gUsbData->HcTable[DevInfo->bHCNumber - 1], DevInfo, ADSC_OUT_REQUEST_TYPE, (UINT16)DevInfo->bInterfaceNum, 0, MassXactStruc->fpCmdBuffer, (UINT16)MassXactStruc->bCmdSize); return RetValue; } // //---------------------------------------------------------------------------- // Procedure: USBMassCBIGetStatus // // Description: This function gets the status of the mass transaction // through an interrupt transfer // // Input: pDevInfo Pointer to DeviceInfo structure // // Output: Return value from the interrupt transfer // //---------------------------------------------------------------------------- // UINT16 USBMassCBIGetStatus(DEV_INFO* fpDevInfo) { (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDInterruptTransfer) (gUsbData->HcTable[fpDevInfo->bHCNumber - 1], fpDevInfo, fpDevInfo->IntInEndpoint, fpDevInfo->IntInMaxPkt, (UINT8*)&gUsbData->wInterruptStatus, 2); return ((UINT16)gUsbData->wInterruptStatus); } // //---------------------------------------------------------------------------- // Procedure: USBMiscIssueBulkTransfer // // Description: This function executes a bulk transaction on the USB. The // transfer may be either DATA_IN or DATA_OUT packets containing // data sent from the host to the device or vice-versa. This // function wil not return until the request either completes // successfully or completes with error (due to time out, etc.) // Size of data can be upto 64K // // Input: - DeviceInfo structure (if available else 0) // - Transfer direction // Bit 7 : Data direction // 0 Host sending data to device // 1 Device sending data to host // Bit 6-0 : Reserved // - Buffer containing data to be sent to the device or // buffer to be used to receive data. Value in // - Length request parameter, number of bytes of data // to be transferred in or out of the host controller // // Output: Amount of data transferred // //---------------------------------------------------------------------------- // UINT32 USBMassIssueBulkTransfer(DEV_INFO* fpDevInfo, UINT8 bXferDir, UINT8* fpCmdBuffer, UINT32 dSize) { return (*gUsbData->aHCDriverTable[GET_HCD_INDEX(gUsbData->HcTable [fpDevInfo->bHCNumber - 1]->bHCType)].pfnHCDBulkTransfer) (gUsbData->HcTable[fpDevInfo->bHCNumber -1], fpDevInfo, bXferDir, fpCmdBuffer, dSize); } // //---------------------------------------------------------------------------- // Procedure: USBMassGetDeviceGeometry // // Description: This function fills and returns the mass get device geometry // structure // // Input: fpMassGetDevGeo Pointer to mass get geometry struc // // Output: Return value // fpMassGetDevGeo Pointer to mass get geometry struc // dSenseData Sense data of the last command // bNumHeads Number of heads // wNumCylinders Number of cylinders // bNumSectors Number of sectors // wBytesPerSector Number of bytes per sector // bMediaType Media type // //---------------------------------------------------------------------------- // UINT8 USBMassGetDeviceGeometry( MASS_GET_DEV_GEO *GetDevGeometry ) { DEV_INFO *DevInfo; UINT8 DevAddr = GetDevGeometry->bDevAddr; BOOLEAN ValidGeo; MASS_GET_DEV_STATUS MassGetDevSts; DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); if ((!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { // Error return USB_ERROR; } MassGetDevSts.bDevAddr = DevAddr; //(EIP13457+)> if (GetDevGeometry->bInt13FuncNum == 0x20){ DevInfo->bLastStatus |= USB_MASS_GET_MEDIA_FORMAT; } if ((!DevInfo->wBlockSize) || (DevInfo->wBlockSize == 0xFFFF) || (!(DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT) || (GetDevGeometry->bInt13FuncNum == 0x20)) ) { // USBMassCheckDeviceReady(fpDevInfo); USBMassGetDeviceStatus(&MassGetDevSts); } //<(EIP13457+) ValidGeo = (BOOLEAN)((DevInfo->wBlockSize != 0xFFFF) && (DevInfo->wBlockSize != 0)); ValidGeo &= (DevInfo->bLastStatus & USB_MASS_MEDIA_PRESENT); //(EIP107198+)> GetDevGeometry->wBytesPerSector = ValidGeo? DevInfo->wBlockSize : 0; GetDevGeometry->LBANumHeads = ValidGeo? DevInfo->Heads : 0; GetDevGeometry->bLBANumSectors = ValidGeo? DevInfo->bSectors : 1; GetDevGeometry->wLBANumCyls = ValidGeo? DevInfo->wCylinders : 0; GetDevGeometry->NumHeads = ValidGeo? DevInfo->NonLBAHeads : 0; GetDevGeometry->bNumSectors = ValidGeo? DevInfo->bNonLBASectors : 1; GetDevGeometry->wNumCylinders = ValidGeo? DevInfo->wNonLBACylinders : 0; GetDevGeometry->bMediaType = DevInfo->bMediaType; GetDevGeometry->LastLBA = ValidGeo? DevInfo->MaxLba : 0; GetDevGeometry->BpbMediaDesc = ValidGeo? DevInfo->BpbMediaDesc : 0; //<(EIP107198+) USB_DEBUG(DEBUG_LEVEL_4, "BPS %d H %d S %d C %d MT %d\n", DevInfo->wBlockSize, DevInfo->Heads, DevInfo->bSectors, DevInfo->wCylinders, DevInfo->bMediaType); return USB_SUCCESS; } // //---------------------------------------------------------------------------- // Procedure: USBMassReadCapacity // // Description: This function issues read capacity command to the mass // device and returns the value obtained // // Input: fpReadCapacity Pointer to the read capacity structure // bDevAddr USB device address of the device // //---------------------------------------------------------------------------- // UINT8 USBMassReadCapacity( MASS_READ_CAPACITY *ReadCapacity ) { DEV_INFO *DevInfo; UINT8 DevAddr = ReadCapacity->bDevAddr; DevInfo = USB_GetDeviceInfoStruc(USB_SRCH_DEV_INDX, 0, DevAddr, 0); if ((!DevInfo) || (!(DevInfo->Flag & DEV_INFO_DEV_PRESENT))) { // Error return USB_ERROR; } return USBMassReadCapacity10Command(DevInfo); } // //---------------------------------------------------------------------------- // Procedure: dabc_to_abcd // // Description: This function swaps the bytes in dword: 0-3,1-2,2-1,3-0. Can be // used for example in little endian->big endian conversions. // // Input: DWORD to swap // // Output: Input value with the swapped bytes in it. // //---------------------------------------------------------------------------- // UINT32 dabc_to_abcd(UINT32 dData) { return (((dData & 0x000000FF) << 24) | ((dData & 0x0000FF00) << 8) | ((dData & 0x00FF0000) >> 8) | ((dData & 0xFF000000) >> 24)); } //**************************************************************************** //**************************************************************************** //** ** //** (C)Copyright 1985-2016, American Megatrends, Inc. ** //** ** //** All Rights Reserved. ** //** ** //** 5555 Oakbrook Pkwy, Norcross, GA 30093 ** //** ** //** Phone (770)-246-8600 ** //** ** //**************************************************************************** //****************************************************************************