⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbmassstoragehelper.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
--*/         
{ 
  //
  // status returned by Read Capacity Packet Command
  //
  EFI_STATUS                Status;       
  ATAPI_PACKET_COMMAND      Packet;
  EFI_USB_ATAPI_PROTOCOL    *UsbAtapiInterface;
  
  //
  // used for capacity data returned from Usb Floppy
  //
  READ_FORMAT_CAPACITY_DATA   FormatData ;

  EfiZeroMem(&FormatData,sizeof(FormatData));

  UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
    
  EfiZeroMem(&Packet,sizeof(ATAPI_PACKET_COMMAND));
  Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY ;
  Packet.ReadFormatCapacity.allocation_length_lo = 12 ;
  Status = USBFloppyPacketCommand (UsbFloppyDevice, 
                                    &Packet,
                                    sizeof(ATAPI_PACKET_COMMAND),
                                    (VOID *)&FormatData, 
                                    sizeof(READ_FORMAT_CAPACITY_DATA), 
                                    EfiUsbDataIn,
                                    USBFLPTIMEOUT
                                    ) ;
  
  if(EFI_ERROR(Status)) {
    return EFI_DEVICE_ERROR;
  }
  if(FormatData.DesCode == 3) {
  //
  // Media is not present
  //      
    UsbFloppyDevice->BlkIo.Media->MediaId = 0 ;
    UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
    UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
  } else {
        
    UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
                      (FormatData.LastLba2 << 16) | 
                        (FormatData.LastLba1 << 8)  |
                        FormatData.LastLba0;

    UsbFloppyDevice->BlkIo.Media->LastBlock--;      
                  
    UsbFloppyDevice->BlkIo.Media->BlockSize =  (FormatData.BlockSize2 << 16) |
                                               (FormatData.BlockSize1 << 8)  |
                                                FormatData.BlockSize0;
 
    UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;

    UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200 ;

  }

  return EFI_SUCCESS ;  

}

EFI_STATUS  
UsbFloppyRequestSense ( 
  IN  USB_FLOPPY_DEV  *UsbFloppyDevice,
  OUT UINTN           *SenseCounts
  )
/*++

  Routine Description:
    Retrieves Sense Data from device via 
    sending Request Sense Packet Command.
  
  Arguments:
    UsbFloppyDevice:    The USB_FLOPPY_DEV instance.
    SenseCounts:        A pointer to the number of Sense Data returned.
      
  Returns:  

--*/         
{
  EFI_STATUS                Status;
  REQUEST_SENSE_DATA        *Sense;
  UINT8                     *Ptr ;
  BOOLEAN                   SenseReq;
  ATAPI_PACKET_COMMAND      Packet;
  EFI_USB_ATAPI_PROTOCOL    *UsbAtapiInterface;

  
  UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
  
  *SenseCounts = 0 ;
  
  EfiZeroMem(UsbFloppyDevice->SenseData, 
             sizeof(REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber));
  //
  // fill command packet for Request Sense Packet Command
  //
  EfiZeroMem(&Packet, sizeof(ATAPI_PACKET_COMMAND));
  Packet.RequestSense.opcode = REQUEST_SENSE; 
  Packet.RequestSense.allocation_length = sizeof(REQUEST_SENSE_DATA);

  Ptr = (UINT8*)(UsbFloppyDevice->SenseData) ; // initialize pointer

  //
  //  request sense data from device continuously 
  //  until no sense data exists in the device.
  //
  for (SenseReq = TRUE; SenseReq == TRUE; ) {
    
    Sense = (REQUEST_SENSE_DATA *) Ptr ;

    //
    // send out Request Sense Packet Command and get one Sense
    // data from device.
    //
    Status = USBFloppyPacketCommand (UsbFloppyDevice, 
                                      &Packet,
                                      sizeof(ATAPI_PACKET_COMMAND),
                                      (VOID*)Ptr,
                                      sizeof(REQUEST_SENSE_DATA),
                                      EfiUsbDataIn,
                                      USBFLPTIMEOUT
                                      );
    //
    // failed to get Sense data
    //
    if (EFI_ERROR(Status)) {
      //
      // Recovery the device back to normal state.
      //
      UsbFloppyDevice->AtapiProtocol->UsbAtapiReset 
        (UsbFloppyDevice->AtapiProtocol,FALSE);
      
      if (*SenseCounts == 0) {
      //
      // never retrieved any sense data from device,
      // just return error.
      //
        return EFI_DEVICE_ERROR;
      } else {
      //
      // has retrieved some sense data from device,
      // so return success.
      // 
        return EFI_SUCCESS ;
      }
    }
    
    if (Sense->sense_key != SK_NO_SENSE) {       
      
      Ptr += sizeof(REQUEST_SENSE_DATA)  ; // Ptr is byte based pointer
      (*SenseCounts) ++;
  
      
    } else {
      //
      // when no sense key, skip out the loop
      //
      SenseReq = FALSE;   
    }
  
    //
    // If the sense key numbers exceed Sense Data Buffer size,
    // just skip the loop and do not fetch the sense key in this function.
    //
    if (*SenseCounts == UsbFloppyDevice->SenseDataNumber ) {
       SenseReq = FALSE;
    }       
  }
  
  return EFI_SUCCESS; 
} 


EFI_STATUS                                                         
UsbFloppyTestUnitReady (
  IN  USB_FLOPPY_DEV    *UsbFloppyDevice
  ) 
/*++

  Routine Description:
    Sends Test Unit ReadyPacket Command to the device.
  
  Arguments:
    UsbFloppyDevice:    The USB_FLOPPY_DEV instance.
      
  Returns:  

--*/  
{ 
  ATAPI_PACKET_COMMAND      Packet; 
  EFI_STATUS                Status;
  EFI_USB_ATAPI_PROTOCOL    *UsbAtapiInterface;
  
  UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;

  //
  // fill command packet
  //
  EfiZeroMem(&Packet, sizeof(ATAPI_PACKET_COMMAND));
  Packet.TestUnitReady.opcode = TEST_UNIT_READY;

  //
  // send command packet
  //
  Status = USBFloppyPacketCommand (UsbFloppyDevice, 
                                  &Packet,
                                  sizeof(ATAPI_PACKET_COMMAND), 
                                  NULL, 
                                  0,
                                  EfiUsbNoData,
                                  USBFLPTIMEOUT
                                  );
  if(EFI_ERROR(Status)) {    
    return EFI_DEVICE_ERROR;
  }

  return EFI_SUCCESS;
} 



EFI_STATUS
USBFloppyWrite10(
  IN    USB_FLOPPY_DEV    *UsbFloppyDevice,
  IN    VOID              *Buffer, 
  IN    EFI_LBA           Lba, 
  IN    UINTN             NumberOfBlocks
  )
/*++

  Routine Description:
    Sends Write10 Packet Command to device to perform data transfer
    from host to device.
  
  Arguments:
    UsbFloppyDevice:    The USB_FLOPPY_DEV instance.
    Buffer:             A pointer to the source buffer for the data. 
                        The caller is responsible for either having implicit
                        or explicit ownership of the buffer.
    Lba:                The starting logical block address to written to 
                        the device.
    NumberOfBlocks:     Indicates the number of blocks that the write 
                        operation requests.
      
  Returns:  

--*/      
{
  ATAPI_PACKET_COMMAND    Packet;
  READ10_CMD              *Write10Packet;
  UINT16                  MaxBlock ;
  UINT16                  BlocksRemaining;
  UINT16                  SectorCount;
  UINT32                  Lba32;
  UINT32                  BlockSize, ByteCount;
  VOID                    *ptrBuffer;
  EFI_STATUS              Status;
  UINT16                  TimeOut;
  EFI_USB_ATAPI_PROTOCOL  *UsbAtapiInterface;
  UINTN                   SenseCounts;
  
  UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;

  //
  // prepare command packet for the Write10 Packet Command.
  //
  EfiZeroMem(&Packet, sizeof(ATAPI_PACKET_COMMAND));
  Write10Packet = &Packet.Read10;
  Lba32 = (UINT32)Lba;
  ptrBuffer = Buffer;
  BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
  
  MaxBlock = (UINT16)(65536 / BlockSize);  
  BlocksRemaining = (UINT16)NumberOfBlocks;
  
  Status = EFI_SUCCESS;
  while (BlocksRemaining > 0) {
    
    if (BlocksRemaining <= MaxBlock) {
      
      SectorCount = BlocksRemaining ;
    } else {
      
      SectorCount = MaxBlock ;
    }

    //
    // fill the Packet data structure
    //

    Write10Packet->opcode = WRITE_10;

    //
    // Lba0 ~ Lba3 specify the start logical block address 
    // of the data transfer.
    // Lba0 is MSB, Lba3 is LSB   
    //
    Write10Packet->Lba3 = (UINT8)(Lba32 & 0xff);          
    Write10Packet->Lba2 = (UINT8)(Lba32 >> 8);          
    Write10Packet->Lba1 = (UINT8)(Lba32 >> 16);          
    Write10Packet->Lba0 = (UINT8)(Lba32 >> 24); 
      
    //
    // TranLen0 ~ TranLen1 specify the transfer length in block unit.
    // TranLen0 is MSB, TranLen is LSB 
    //
    Write10Packet->TranLen1 = (UINT8)(SectorCount & 0xff);   
    Write10Packet->TranLen0 = (UINT8)(SectorCount >> 8);    

    ByteCount = SectorCount * BlockSize;
    
    TimeOut = (UINT16)(SectorCount * USBFLPTIMEOUT);
 
    Status = USBFloppyPacketCommand(
                              UsbFloppyDevice, 
                              &Packet,
                              sizeof(ATAPI_PACKET_COMMAND), 
                              (void *)ptrBuffer,
                              ByteCount,
                              EfiUsbDataOut,
                              TimeOut
                              );
    if (EFI_ERROR(Status)) {
      Status = UsbFloppyRequestSense (UsbFloppyDevice,&SenseCounts);
      if (!EFI_ERROR(Status)) {
        if (IsLogicalUnitCommunicationOverRun (
                                      UsbFloppyDevice->SenseData,
                                      SenseCounts)) {
          Lba32 = (UINT32)Lba;
          ptrBuffer = Buffer;
          BlocksRemaining = (UINT16)NumberOfBlocks;
          MaxBlock = (UINT16)(MaxBlock / 4);
          if (MaxBlock < 1) {
            MaxBlock = 1;
          }
          continue;
        }
      }
      //
      // retry write10 command
      //
      Status = USBFloppyPacketCommand(
                              UsbFloppyDevice, 
                              &Packet,
                              sizeof(ATAPI_PACKET_COMMAND), 
                              (void *)ptrBuffer,
                              ByteCount,
                              EfiUsbDataOut,
                              TimeOut
                              );
      if (EFI_ERROR(Status)) {
        return EFI_DEVICE_ERROR;
      }
    } 
    
    Lba32 += SectorCount;
    ptrBuffer = (UINT8 *)ptrBuffer + SectorCount * BlockSize;
    BlocksRemaining = (UINT16)(BlocksRemaining - SectorCount);
  }
  
  return Status;
}     

EFI_STATUS 
UsbFloppyDetectMedia (
  IN  USB_FLOPPY_DEV  *UsbFloppyDevice,
  OUT BOOLEAN         *MediaChange
  )
/*++

  Routine Description:
    Retrieves media information.
  
  Arguments:
    UsbFloppyDevice:    The USB_FLOPPY_DEV instance.
    MediaChange:        Indicates whether media was changed.
      
  Returns:  

--*/        
{
  EFI_STATUS          Status;
  EFI_STATUS          FloppyStatus;
  //
  // the following variables are used to record previous media information
  //
  EFI_BLOCK_IO_MEDIA  OldMediaInfo;
  UINTN               SenseCounts;
  UINTN               RetryIndex;
  UINTN               RetryTimes;
  UINTN               MaximumRetryTimes;
  BOOLEAN             NeedRetry;

  //
  // a flag used to determine whether need to perform Read Capacity command.
  //
  BOOLEAN             NeedReadCapacity;

  REQUEST_SENSE_DATA  *SensePtr;

  //
  // init 
  //
  Status            = EFI_SUCCESS;
  FloppyStatus      = EFI_SUCCESS;
  OldMediaInfo      = *UsbFloppyDevice->BlkIo.Media;
  *MediaChange      = FALSE ;
  NeedReadCapacity  = TRUE;
  
  //
  // if there is no media present,or media not changed,
  // the request sense command will detect faster than read capacity command.
  // read capacity command can be bypassed, thus improve performance.
  //
  SenseCounts = 0;
  Status = UsbFloppyRequestSense(UsbFloppyDevice, &SenseCounts);
  
  if (!EFI_ERROR(Status)) {
  
    SensePtr = UsbFloppyDevice->SenseData;

    //
    // No Media
    //
    if(IsNoMedia (UsbFloppyDevice->SenseData,SenseCounts)) {
        
      NeedReadCapacity = FALSE ;
      UsbFloppyDevice->BlkIo.Media->MediaId = 0 ;
      UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
      UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
    } else {        
      //
      // Media Changed
      //
      if (IsMediaChange (UsbFloppyDevice->SenseData,SenseCounts)) {
        UsbFloppyDevice->BlkIo.Media->MediaId++;
      }
        
      //
      // Media Write-protected
      //
      if(IsMediaWriteProtected(UsbFloppyDevice->SenseData,SenseCounts)) {
        UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;        
      }
        
      //
      // Media Error
      //
      if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
        //
        // if media error encountered, make it look like no media present.
        // 
        UsbFloppyDevice->BlkIo.Media->MediaId = 0 ;
        UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
        UsbFloppyDevice->BlkIo.Media->LastBlock = 0;        
      }

    }
    
  }
  
  if (NeedReadCapacity) {
    //
    // at most retry 5 times
    //
    MaximumRetryTimes = 5;
    RetryTimes = 2 ;      // initial retry twice

    for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex ++) {
      
      //
      // Using different command to retrieve media capacity.
      //
      switch (UsbFloppyDevice->DeviceType)  {
        case USBCDROM:
          Status = USBFloppyReadCapacity(UsbFloppyDevice);
          break;
        
        case USBFLOPPY:
          UsbFloppyModeSense1C (UsbFloppyDevice);
          Status = USBFloppyReadFormatCapacity(UsbFloppyDevice);
          if (EFI_ERROR(Status)) {            
            //
            // retry the ReadCapacity command
            //
            UsbFloppyDevice->DeviceType = USBFLOPPY2;
          }
          break;
        
        case USBFLOPPY2:        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -