summaryrefslogtreecommitdiff
path: root/Core/EM/usb/rt/usbmass.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/usb/rt/usbmass.c')
-rw-r--r--Core/EM/usb/rt/usbmass.c5506
1 files changed, 5506 insertions, 0 deletions
diff --git a/Core/EM/usb/rt/usbmass.c b/Core/EM/usb/rt/usbmass.c
new file mode 100644
index 0000000..0bdb683
--- /dev/null
+++ b/Core/EM/usb/rt/usbmass.c
@@ -0,0 +1,5506 @@
+//****************************************************************************
+//****************************************************************************
+//** **
+//** (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.
+//
+//****************************************************************************
+
+//<AMI_FHDR_START>
+//-----------------------------------------------------------------------------
+//
+// Name: UsbMass.c
+//
+// Description: AMI USB Mass Storage support implementation
+//
+//-----------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "amidef.h"
+#include "usbdef.h"
+#include "amiusb.h"
+#include "UsbMass.h"
+#if USB_RUNTIME_DRIVER_IN_SMM
+#include <AmiBufferValidationLib.h>
+#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;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// FUNCTION: USBMassInitialize
+//
+// DESCRIPTION: This function initializes mass storage device related data
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassDisconnectStorageDevice
+//
+// DESCRIPTION: This function disconnects the storage device
+//
+// PARAMETERS: pDevInfo Device info structure pointer
+//
+// RETURN: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassClearMassXactStruc
+//
+// Description: This function clears the mass transaction structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+USBMassClearMassXactStruc(
+ MASS_XACT_STRUC *MassXactStruc
+)
+{
+ UINT8 i;
+ UINT8* Cleaner = (UINT8*)MassXactStruc;
+
+ for (i = 0; i < sizeof (MASS_XACT_STRUC); i++ ) {
+ *Cleaner++ = 0;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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));
+ }
+ //}
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+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);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID
+iPodShufflePatch(
+ MASS_GET_DEV_INFO *MassGetDevInfo
+)
+{
+ //TO BE IMPLEMENTED
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+ }
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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)
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+ //}
+ //(<EIP59738-)
+ //(EIP80382)>
+ 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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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-)>
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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-)
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+ //(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)
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+ }
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassRequestSense
+//
+// DESCRIPTION: This function sends request sense command and returns
+// the sense key information
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Sense data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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+)
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassTestUnitReady
+//
+// DESCRIPTION: This function sends test unit ready command
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+// RETURN: Sense data
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassCheckDeviceReady
+//
+// Description: This function makes sure the device is ready for next
+// command
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: Sense code
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBMassUpdateDeviceGeometry
+//
+// Description: This function updates the device geometry information
+//
+// Input: Pointer to device info structure
+//
+// Output: USB_SUCCESS or USB_ERROR
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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));
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: USBBOTGetStatus
+//
+// Description: This function gets the BOT status sequence using
+// bulk IN transfer
+//
+// Input: fpDevInfo Pointer to DeviceInfo structure
+//
+// Output: Nothing
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// PROCEDURE: USBMassBOTResetRecovery
+//
+// DESCRIPTION: This function performs the BOT reset recovery
+//
+// PARAMETERS: fpDevInfo Pointer to DeviceInfo structure
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+}
+
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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;
+
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// 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.
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+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 **
+//** **
+//****************************************************************************
+//****************************************************************************