2 ISA Floppy Disk UEFI Driver conforming to the UEFI driver model
4 1. Support two types diskette drive
5 1.44M drive and 2.88M drive (and now only support 1.44M)
6 2. Support two diskette drives per floppy disk controller
7 3. Use DMA channel 2 to transfer data
8 4. Do not use interrupt
9 5. Support diskette change line signal and write protect
11 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
12 SPDX-License-Identifier: BSD-2-Clause-Patent
16 #include "IsaFloppy.h"
18 LIST_ENTRY mControllerHead
= INITIALIZE_LIST_HEAD_VARIABLE (mControllerHead
);
21 // ISA Floppy Driver Binding Protocol
23 EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
= {
24 FdcControllerDriverSupported
,
25 FdcControllerDriverStart
,
26 FdcControllerDriverStop
,
34 The main Entry Point for this driver.
36 @param[in] ImageHandle The firmware allocated handle for the EFI image.
37 @param[in] SystemTable A pointer to the EFI System Table.
39 @retval EFI_SUCCESS The entry point is executed successfully.
40 @retval other Some error occurs when executing this entry point.
45 IN EFI_HANDLE ImageHandle
,
46 IN EFI_SYSTEM_TABLE
*SystemTable
52 // Install driver model protocol(s).
54 Status
= EfiLibInstallDriverBindingComponentName2 (
57 &gFdcControllerDriver
,
59 &gIsaFloppyComponentName
,
60 &gIsaFloppyComponentName2
62 ASSERT_EFI_ERROR (Status
);
68 Test if the controller is a floppy disk drive device
70 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
71 @param[in] Controller The handle of the controller to test.
72 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
74 @retval EFI_SUCCESS The device is supported by this driver.
75 @retval EFI_ALREADY_STARTED The device is already being managed by this driver.
76 @retval EFI_ACCESS_DENIED The device is already being managed by a different driver
77 or an application that requires exclusive access.
78 @retval EFI_UNSUPPORTED The device is is not supported by this driver.
82 FdcControllerDriverSupported (
83 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
84 IN EFI_HANDLE Controller
,
85 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
89 EFI_ISA_IO_PROTOCOL
*IsaIo
;
90 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
93 // Ignore the parameter RemainingDevicePath because this is a device driver.
97 // Open the device path protocol
99 Status
= gBS
->OpenProtocol (
101 &gEfiDevicePathProtocolGuid
,
102 (VOID
**) &ParentDevicePath
,
103 This
->DriverBindingHandle
,
105 EFI_OPEN_PROTOCOL_BY_DRIVER
107 if (EFI_ERROR (Status
)) {
113 &gEfiDevicePathProtocolGuid
,
114 This
->DriverBindingHandle
,
119 // Open the ISA I/O Protocol
121 Status
= gBS
->OpenProtocol (
123 &gEfiIsaIoProtocolGuid
,
125 This
->DriverBindingHandle
,
127 EFI_OPEN_PROTOCOL_BY_DRIVER
129 if (EFI_ERROR (Status
)) {
133 // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device
135 Status
= EFI_SUCCESS
;
136 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x604)) {
137 Status
= EFI_UNSUPPORTED
;
140 // Close the ISA I/O Protocol
144 &gEfiIsaIoProtocolGuid
,
145 This
->DriverBindingHandle
,
153 Start this driver on Controller.
155 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
156 @param[in] ControllerHandle The handle of the controller to start. This handle
157 must support a protocol interface that supplies
158 an I/O abstraction to the driver.
159 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
160 This parameter is ignored by device drivers, and is optional for bus drivers.
162 @retval EFI_SUCCESS The device was started.
163 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
164 Currently not implemented.
165 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
166 @retval Others The driver failded to start the device.
170 FdcControllerDriverStart (
171 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
172 IN EFI_HANDLE Controller
,
173 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
177 FDC_BLK_IO_DEV
*FdcDev
;
178 EFI_ISA_IO_PROTOCOL
*IsaIo
;
182 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
188 // Open the device path protocol
190 Status
= gBS
->OpenProtocol (
192 &gEfiDevicePathProtocolGuid
,
193 (VOID
**) &ParentDevicePath
,
194 This
->DriverBindingHandle
,
196 EFI_OPEN_PROTOCOL_BY_DRIVER
198 if (EFI_ERROR (Status
)) {
202 // Report enable progress code
204 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
206 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
,
211 // Open the ISA I/O Protocol
213 Status
= gBS
->OpenProtocol (
215 &gEfiIsaIoProtocolGuid
,
217 This
->DriverBindingHandle
,
219 EFI_OPEN_PROTOCOL_BY_DRIVER
221 if (EFI_ERROR (Status
)) {
225 // Allocate the floppy device's Device structure
227 FdcDev
= AllocateZeroPool (sizeof (FDC_BLK_IO_DEV
));
228 if (FdcDev
== NULL
) {
232 // Initialize the floppy device's device structure
234 FdcDev
->Signature
= FDC_BLK_IO_DEV_SIGNATURE
;
235 FdcDev
->Handle
= Controller
;
236 FdcDev
->IsaIo
= IsaIo
;
237 FdcDev
->Disk
= (EFI_FDC_DISK
) IsaIo
->ResourceList
->Device
.UID
;
238 FdcDev
->Cache
= NULL
;
239 FdcDev
->Event
= NULL
;
240 FdcDev
->ControllerState
= NULL
;
241 FdcDev
->DevicePath
= ParentDevicePath
;
243 FdcDev
->ControllerNameTable
= NULL
;
247 // Look up the base address of the Floppy Disk Controller which controls this floppy device
249 for (Index
= 0; FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
250 if (FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
251 FdcDev
->BaseAddress
= (UINT16
) FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
255 // Maintain the list of floppy disk controllers
258 List
= mControllerHead
.ForwardLink
;
259 while (List
!= &mControllerHead
) {
260 FdcDev
->ControllerState
= FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List
);
261 if (FdcDev
->BaseAddress
== FdcDev
->ControllerState
->BaseAddress
) {
266 List
= List
->ForwardLink
;
271 // A new floppy disk controller controlling this floppy disk drive is found
273 FdcDev
->ControllerState
= AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT
));
274 if (FdcDev
->ControllerState
== NULL
) {
278 FdcDev
->ControllerState
->Signature
= FLOPPY_CONTROLLER_CONTEXT_SIGNATURE
;
279 FdcDev
->ControllerState
->FddResetPerformed
= FALSE
;
280 FdcDev
->ControllerState
->NeedRecalibrate
= FALSE
;
281 FdcDev
->ControllerState
->BaseAddress
= FdcDev
->BaseAddress
;
282 FdcDev
->ControllerState
->NumberOfDrive
= 0;
284 InsertTailList (&mControllerHead
, &FdcDev
->ControllerState
->Link
);
287 // Create a timer event for each floppy disk drive device.
288 // This timer event is used to control the motor on and off
290 Status
= gBS
->CreateEvent (
291 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
297 if (EFI_ERROR (Status
)) {
301 // Reset the Floppy Disk Controller
303 if (!FdcDev
->ControllerState
->FddResetPerformed
) {
304 FdcDev
->ControllerState
->FddResetPerformed
= TRUE
;
305 FdcDev
->ControllerState
->FddResetStatus
= FddReset (FdcDev
);
308 if (EFI_ERROR (FdcDev
->ControllerState
->FddResetStatus
)) {
309 Status
= EFI_DEVICE_ERROR
;
313 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
315 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_PRESENCE_DETECT
,
320 // Discover the Floppy Drive
322 Status
= DiscoverFddDevice (FdcDev
);
323 if (EFI_ERROR (Status
)) {
324 Status
= EFI_DEVICE_ERROR
;
328 // Install protocol interfaces for the serial device.
330 Status
= gBS
->InstallMultipleProtocolInterfaces (
332 &gEfiBlockIoProtocolGuid
,
336 if (!EFI_ERROR (Status
)) {
337 FdcDev
->ControllerState
->NumberOfDrive
++;
341 if (EFI_ERROR (Status
)) {
343 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
344 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
345 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_CONTROLLER_ERROR
,
350 // If a floppy drive device structure was allocated, then free it
352 if (FdcDev
!= NULL
) {
353 if (FdcDev
->Event
!= NULL
) {
355 // Close the event for turning the motor off
357 gBS
->CloseEvent (FdcDev
->Event
);
360 FreeUnicodeStringTable (FdcDev
->ControllerNameTable
);
365 // Close the ISA I/O Protocol
370 &gEfiIsaIoProtocolGuid
,
371 This
->DriverBindingHandle
,
377 // Close the device path protocol
381 &gEfiDevicePathProtocolGuid
,
382 This
->DriverBindingHandle
,
391 Stop this driver on ControllerHandle.
393 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
394 @param[in] ControllerHandle A handle to the device being stopped. The handle must
395 support a bus specific I/O protocol for the driver
396 to use to stop the device.
397 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
398 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
399 if NumberOfChildren is 0.
401 @retval EFI_SUCCESS The device was stopped.
402 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
406 FdcControllerDriverStop (
407 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
408 IN EFI_HANDLE Controller
,
409 IN UINTN NumberOfChildren
,
410 IN EFI_HANDLE
*ChildHandleBuffer
414 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
415 FDC_BLK_IO_DEV
*FdcDev
;
418 // Ignore NumberOfChildren since this is a device driver
422 // Get the Block I/O Protocol on Controller
424 Status
= gBS
->OpenProtocol (
426 &gEfiBlockIoProtocolGuid
,
428 This
->DriverBindingHandle
,
430 EFI_OPEN_PROTOCOL_GET_PROTOCOL
432 if (EFI_ERROR (Status
)) {
436 // Get the floppy drive device's Device structure
438 FdcDev
= FDD_BLK_IO_FROM_THIS (BlkIo
);
441 // Report disable progress code
443 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
445 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
,
450 // Uninstall the Block I/O Protocol
452 Status
= gBS
->UninstallProtocolInterface (
454 &gEfiBlockIoProtocolGuid
,
457 if (EFI_ERROR (Status
)) {
462 // Close the event for turning the motor off
464 gBS
->CloseEvent (FdcDev
->Event
);
467 // Turn the motor off on the floppy drive device
469 FddTimerProc (FdcDev
->Event
, FdcDev
);
472 // Close the device path protocol
476 &gEfiDevicePathProtocolGuid
,
477 This
->DriverBindingHandle
,
482 // Close the ISA I/O Protocol
486 &gEfiIsaIoProtocolGuid
,
487 This
->DriverBindingHandle
,
492 // Free the controller list if needed
494 FdcDev
->ControllerState
->NumberOfDrive
--;
497 // Free the cache if one was allocated
499 FdcFreeCache (FdcDev
);
502 // Free the floppy drive device's device structure
504 FreeUnicodeStringTable (FdcDev
->ControllerNameTable
);