/** Reset the Block Device. @param This Indicates a pointer to the calling context. @param ExtendedVerification Driver may perform diagnostics on reset. @retval EFI_SUCCESS The device was reset. @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. **/ EFI_STATUS EFIAPI FdcReset ( IN EFI_BLOCK_IO_PROTOCOL *This, IN BOOLEAN ExtendedVerification ) { FDC_BLK_IO_DEV *FdcDev; // // Reset the Floppy Disk Controller // FdcDev = FDD_BLK_IO_FROM_THIS (This); REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA, FdcDev->DevicePath ); return FddReset (FdcDev); }
/** Start this driver on Controller. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI FdcControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; FDC_BLK_IO_DEV *FdcDev; EFI_ISA_IO_PROTOCOL *IsaIo; UINTN Index; LIST_ENTRY *List; BOOLEAN Found; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; FdcDev = NULL; IsaIo = NULL; // // Open the device path protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report enable progress code // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, ParentDevicePath ); // // Open the ISA I/O Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Done; } // // Allocate the floppy device's Device structure // FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); if (FdcDev == NULL) { goto Done; } // // Initialize the floppy device's device structure // FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; FdcDev->Handle = Controller; FdcDev->IsaIo = IsaIo; FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID; FdcDev->Cache = NULL; FdcDev->Event = NULL; FdcDev->ControllerState = NULL; FdcDev->DevicePath = ParentDevicePath; FdcDev->ControllerNameTable = NULL; AddName (FdcDev); // // Look up the base address of the Floppy Disk Controller which controls this floppy device // for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange; } } // // Maintain the list of floppy disk controllers // Found = FALSE; List = mControllerHead.ForwardLink; while (List != &mControllerHead) { FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { Found = TRUE; break; } List = List->ForwardLink; } if (!Found) { // // A new floppy disk controller controlling this floppy disk drive is found // FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT)); if (FdcDev->ControllerState == NULL) { goto Done; } FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE; FdcDev->ControllerState->FddResetPerformed = FALSE; FdcDev->ControllerState->NeedRecalibrate = FALSE; FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress; FdcDev->ControllerState->NumberOfDrive = 0; InsertTailList (&mControllerHead, &FdcDev->ControllerState->Link); } // // Create a timer event for each floppy disk drive device. // This timer event is used to control the motor on and off // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, FddTimerProc, FdcDev, &FdcDev->Event ); if (EFI_ERROR (Status)) { goto Done; } // // Reset the Floppy Disk Controller // if (!FdcDev->ControllerState->FddResetPerformed) { FdcDev->ControllerState->FddResetPerformed = TRUE; FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev); } if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) { Status = EFI_DEVICE_ERROR; goto Done; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // Discover the Floppy Drive // Status = DiscoverFddDevice (FdcDev); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Done; } // // Install protocol interfaces for the serial device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiBlockIoProtocolGuid, &FdcDev->BlkIo, NULL ); if (!EFI_ERROR (Status)) { FdcDev->ControllerState->NumberOfDrive++; } Done: if (EFI_ERROR (Status)) { REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, ParentDevicePath ); // // If a floppy drive device structure was allocated, then free it // if (FdcDev != NULL) { if (FdcDev->Event != NULL) { // // Close the event for turning the motor off // gBS->CloseEvent (FdcDev->Event); } FreeUnicodeStringTable (FdcDev->ControllerNameTable); FreePool (FdcDev); } // // Close the ISA I/O Protocol // if (IsaIo != NULL) { gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); } // // Close the device path protocol // gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } return Status; }
EFI_STATUS EFIAPI FdcControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: --*/ // GC_TODO: This - add argument and description to function comment // GC_TODO: Controller - add argument and description to function comment // GC_TODO: RemainingDevicePath - add argument and description to function comment { EFI_STATUS Status; FDC_BLK_IO_DEV *FdcDev; EFI_INTERFACE_DEFINITION_FOR_ISA_IO *IsaIo; UINTN Index; EFI_LIST_ENTRY *List; BOOLEAN Found; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; FdcDev = NULL; IsaIo = NULL; // // Open the device path protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report enable progress code // ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Open the ISA I/O Protocol // Status = gBS->OpenProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Done; } // // Allocate the Floppy Disk Controller's Device structure // FdcDev = EfiLibAllocateZeroPool (sizeof (FDC_BLK_IO_DEV)); if (FdcDev == NULL) { goto Done; } // // Initialize the Floppy Disk Controller's Device structure // FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE; FdcDev->Handle = Controller; FdcDev->IsaIo = IsaIo; FdcDev->Disk = IsaIo->ResourceList->Device.UID; FdcDev->Cache = NULL; FdcDev->Event = NULL; FdcDev->ControllerState = NULL; FdcDev->DevicePath = ParentDevicePath; ADD_FLOPPY_NAME (FdcDev); // // Look up the base address of the Floppy Disk Controller // for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) { if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) { FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange; } } // // Maintain the list of controller list // Found = FALSE; List = gControllerHead.ForwardLink; while (List != &gControllerHead) { FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List); if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) { Found = TRUE; break; } List = List->ForwardLink; } if (!Found) { // // The Controller is new // FdcDev->ControllerState = EfiLibAllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT)); if (FdcDev->ControllerState == NULL) { goto Done; } FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE; FdcDev->ControllerState->FddResetPerformed = FALSE; FdcDev->ControllerState->NeedRecalibrate = FALSE; FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress; FdcDev->ControllerState->NumberOfDrive = 0; InsertTailList (&gControllerHead, &FdcDev->ControllerState->Link); } // // Create a timer event for each Floppd Disk Controller. // This timer event is used to control the motor on and off // Status = gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, EFI_TPL_NOTIFY, FddTimerProc, FdcDev, &FdcDev->Event ); if (EFI_ERROR (Status)) { goto Done; } // // Reset the Floppy Disk Controller // if (!FdcDev->ControllerState->FddResetPerformed) { FdcDev->ControllerState->FddResetPerformed = TRUE; FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev); } if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) { Status = EFI_DEVICE_ERROR; goto Done; } ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Discover the Floppy Drive // Status = DiscoverFddDevice (FdcDev); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; goto Done; } // // Install protocol interfaces for the serial device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiBlockIoProtocolGuid, &FdcDev->BlkIo, NULL ); FdcDev->ControllerState->NumberOfDrive++; Done: if (EFI_ERROR (Status)) { ReportStatusCodeWithDevicePath ( EFI_ERROR_CODE | EFI_ERROR_MINOR, EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Close the device path protocol // gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); // // Close the ISA I/O Protocol // if (IsaIo != NULL) { gBS->CloseProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, This->DriverBindingHandle, Controller ); } // // If a Floppy Disk Controller Device structure was allocated, then free it // if (FdcDev != NULL) { if (FdcDev->Event != NULL) { // // Close the event for turning the motor off // gBS->CloseEvent (FdcDev->Event); } EfiLibFreeUnicodeStringTable (FdcDev->ControllerNameTable); gBS->FreePool (FdcDev); } } return Status; }
/** Read or Write a number of blocks to floppy disk @param This Indicates a pointer to the calling context. @param MediaId Id of the media, changes every time the media is replaced. @param Lba The starting Logical Block Address to read from @param BufferSize Size of Buffer, must be a multiple of device block size. @param Operation Specifies the read or write operation. @param Buffer A pointer to the destination buffer for the data. The caller is responsible for either having implicit or explicit ownership of the buffer. @retval EFI_SUCCESS The data was read correctly from the device. @retval EFI_DEVICE_ERROR The device reported an error while performing the read. @retval EFI_NO_MEDIA There is no media in the device. @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, or the buffer is not on proper alignment. @retval EFI_WRITE_PROTECTED The device can not be written to. **/ EFI_STATUS FddReadWriteBlocks ( IN EFI_BLOCK_IO_PROTOCOL *This, IN UINT32 MediaId, IN EFI_LBA Lba, IN UINTN BufferSize, IN BOOLEAN Operation, OUT VOID *Buffer ) { EFI_BLOCK_IO_MEDIA *Media; FDC_BLK_IO_DEV *FdcDev; UINTN BlockSize; UINTN NumberOfBlocks; UINTN BlockCount; EFI_STATUS Status; EFI_LBA Lba0; UINT8 *Pointer; // // Get the intrinsic block size // Media = This->Media; BlockSize = Media->BlockSize; FdcDev = FDD_BLK_IO_FROM_THIS (This); if (Operation == WRITE) { if (Lba == 0) { FdcFreeCache (FdcDev); } } // // Set the drive motor on // Status = MotorOn (FdcDev); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } // // Check to see if media can be detected // Status = DetectMedia (FdcDev); if (EFI_ERROR (Status)) { MotorOff (FdcDev); FdcFreeCache (FdcDev); return EFI_DEVICE_ERROR; } // // Check to see if media is present // if (!(Media->MediaPresent)) { MotorOff (FdcDev); FdcFreeCache (FdcDev); return EFI_NO_MEDIA; } // // Check to see if media has been changed // if (MediaId != Media->MediaId) { MotorOff (FdcDev); FdcFreeCache (FdcDev); return EFI_MEDIA_CHANGED; } if (BufferSize == 0) { MotorOff (FdcDev); return EFI_SUCCESS; } if (Operation == WRITE) { if (Media->ReadOnly) { MotorOff (FdcDev); return EFI_WRITE_PROTECTED; } } // // Check the parameters for this read/write operation // if (Buffer == NULL) { MotorOff (FdcDev); return EFI_INVALID_PARAMETER; } if (BufferSize % BlockSize != 0) { MotorOff (FdcDev); return EFI_BAD_BUFFER_SIZE; } if (Lba > Media->LastBlock) { MotorOff (FdcDev); return EFI_INVALID_PARAMETER; } if (((BufferSize / BlockSize) + Lba - 1) > Media->LastBlock) { MotorOff (FdcDev); return EFI_INVALID_PARAMETER; } if (Operation == READ) { // // See if the data that is being read is already in the cache // if (FdcDev->Cache != NULL) { if (Lba == 0 && BufferSize == BlockSize) { MotorOff (FdcDev); CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize); return EFI_SUCCESS; } } } // // Set up Floppy Disk Controller // Status = Setup (FdcDev); if (EFI_ERROR (Status)) { MotorOff (FdcDev); return EFI_DEVICE_ERROR; } NumberOfBlocks = BufferSize / BlockSize; Lba0 = Lba; Pointer = Buffer; // // read blocks in the same cylinder. // in a cylinder , there are 18 * 2 = 36 blocks // BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); while ((BlockCount != 0) && !EFI_ERROR (Status)) { Status = ReadWriteDataSector (FdcDev, Buffer, Lba, BlockCount, Operation); if (EFI_ERROR (Status)) { MotorOff (FdcDev); FddReset (FdcDev); return EFI_DEVICE_ERROR; } Lba += BlockCount; NumberOfBlocks -= BlockCount; Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize); BlockCount = GetTransferBlockCount (FdcDev, Lba, NumberOfBlocks); } Buffer = Pointer; // // Turn the motor off // MotorOff (FdcDev); if (Operation == READ) { // // Cache the data read // if (Lba0 == 0 && FdcDev->Cache == NULL) { FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer); } } return EFI_SUCCESS; }