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 - 2009, Intel Corporation. All rights reserved.<BR>
12 This program and the accompanying materials
13 are licensed and made available under the terms and conditions of the BSD License
14 which accompanies this distribution. The full text of the license may be found at
15 http://opensource.org/licenses/bsd-license.php
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include "IsaFloppy.h"
24 LIST_ENTRY mControllerHead
= INITIALIZE_LIST_HEAD_VARIABLE (mControllerHead
);
27 // ISA Floppy Driver Binding Protocol
29 EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
= {
30 FdcControllerDriverSupported
,
31 FdcControllerDriverStart
,
32 FdcControllerDriverStop
,
40 The main Entry Point for this driver.
42 @param[in] ImageHandle The firmware allocated handle for the EFI image.
43 @param[in] SystemTable A pointer to the EFI System Table.
45 @retval EFI_SUCCESS The entry point is executed successfully.
46 @retval other Some error occurs when executing this entry point.
51 IN EFI_HANDLE ImageHandle
,
52 IN EFI_SYSTEM_TABLE
*SystemTable
58 // Install driver model protocol(s).
60 Status
= EfiLibInstallDriverBindingComponentName2 (
63 &gFdcControllerDriver
,
65 &gIsaFloppyComponentName
,
66 &gIsaFloppyComponentName2
68 ASSERT_EFI_ERROR (Status
);
74 Test if the controller is a floppy disk drive device
76 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
77 @param[in] Controller The handle of the controller to test.
78 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
80 @retval EFI_SUCCESS The device is supported by this driver.
81 @retval EFI_ALREADY_STARTED The device is already being managed by this driver.
82 @retval EFI_ACCESS_DENIED The device is already being managed by a different driver
83 or an application that requires exclusive access.
84 @retval EFI_UNSUPPORTED The device is is not supported by this driver.
88 FdcControllerDriverSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
90 IN EFI_HANDLE Controller
,
91 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
95 EFI_ISA_IO_PROTOCOL
*IsaIo
;
96 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
99 // Ignore the parameter RemainingDevicePath because this is a device driver.
103 // Open the device path protocol
105 Status
= gBS
->OpenProtocol (
107 &gEfiDevicePathProtocolGuid
,
108 (VOID
**) &ParentDevicePath
,
109 This
->DriverBindingHandle
,
111 EFI_OPEN_PROTOCOL_BY_DRIVER
113 if (EFI_ERROR (Status
)) {
119 &gEfiDevicePathProtocolGuid
,
120 This
->DriverBindingHandle
,
125 // Open the ISA I/O Protocol
127 Status
= gBS
->OpenProtocol (
129 &gEfiIsaIoProtocolGuid
,
131 This
->DriverBindingHandle
,
133 EFI_OPEN_PROTOCOL_BY_DRIVER
135 if (EFI_ERROR (Status
)) {
139 // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device
141 Status
= EFI_SUCCESS
;
142 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x604)) {
143 Status
= EFI_UNSUPPORTED
;
146 // Close the ISA I/O Protocol
150 &gEfiIsaIoProtocolGuid
,
151 This
->DriverBindingHandle
,
159 Start this driver on Controller.
161 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
162 @param[in] ControllerHandle The handle of the controller to start. This handle
163 must support a protocol interface that supplies
164 an I/O abstraction to the driver.
165 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
166 This parameter is ignored by device drivers, and is optional for bus drivers.
168 @retval EFI_SUCCESS The device was started.
169 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
170 Currently not implemented.
171 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
172 @retval Others The driver failded to start the device.
176 FdcControllerDriverStart (
177 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
178 IN EFI_HANDLE Controller
,
179 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
183 FDC_BLK_IO_DEV
*FdcDev
;
184 EFI_ISA_IO_PROTOCOL
*IsaIo
;
188 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
194 // Open the device path protocol
196 Status
= gBS
->OpenProtocol (
198 &gEfiDevicePathProtocolGuid
,
199 (VOID
**) &ParentDevicePath
,
200 This
->DriverBindingHandle
,
202 EFI_OPEN_PROTOCOL_BY_DRIVER
204 if (EFI_ERROR (Status
)) {
208 // Report enable progress code
210 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
212 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_ENABLE
,
217 // Open the ISA I/O Protocol
219 Status
= gBS
->OpenProtocol (
221 &gEfiIsaIoProtocolGuid
,
223 This
->DriverBindingHandle
,
225 EFI_OPEN_PROTOCOL_BY_DRIVER
227 if (EFI_ERROR (Status
)) {
231 // Allocate the floppy device's Device structure
233 FdcDev
= AllocateZeroPool (sizeof (FDC_BLK_IO_DEV
));
234 if (FdcDev
== NULL
) {
238 // Initialize the floppy device's device structure
240 FdcDev
->Signature
= FDC_BLK_IO_DEV_SIGNATURE
;
241 FdcDev
->Handle
= Controller
;
242 FdcDev
->IsaIo
= IsaIo
;
243 FdcDev
->Disk
= (EFI_FDC_DISK
) IsaIo
->ResourceList
->Device
.UID
;
244 FdcDev
->Cache
= NULL
;
245 FdcDev
->Event
= NULL
;
246 FdcDev
->ControllerState
= NULL
;
247 FdcDev
->DevicePath
= ParentDevicePath
;
249 FdcDev
->ControllerNameTable
= NULL
;
253 // Look up the base address of the Floppy Disk Controller which controls this floppy device
255 for (Index
= 0; FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
!= EfiIsaAcpiResourceEndOfList
; Index
++) {
256 if (FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].Type
== EfiIsaAcpiResourceIo
) {
257 FdcDev
->BaseAddress
= (UINT16
) FdcDev
->IsaIo
->ResourceList
->ResourceItem
[Index
].StartRange
;
261 // Maintain the list of floppy disk controllers
264 List
= mControllerHead
.ForwardLink
;
265 while (List
!= &mControllerHead
) {
266 FdcDev
->ControllerState
= FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List
);
267 if (FdcDev
->BaseAddress
== FdcDev
->ControllerState
->BaseAddress
) {
272 List
= List
->ForwardLink
;
277 // A new floppy disk controller controlling this floppy disk drive is found
279 FdcDev
->ControllerState
= AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT
));
280 if (FdcDev
->ControllerState
== NULL
) {
284 FdcDev
->ControllerState
->Signature
= FLOPPY_CONTROLLER_CONTEXT_SIGNATURE
;
285 FdcDev
->ControllerState
->FddResetPerformed
= FALSE
;
286 FdcDev
->ControllerState
->NeedRecalibrate
= FALSE
;
287 FdcDev
->ControllerState
->BaseAddress
= FdcDev
->BaseAddress
;
288 FdcDev
->ControllerState
->NumberOfDrive
= 0;
290 InsertTailList (&mControllerHead
, &FdcDev
->ControllerState
->Link
);
293 // Create a timer event for each floppy disk drive device.
294 // This timer event is used to control the motor on and off
296 Status
= gBS
->CreateEvent (
297 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
303 if (EFI_ERROR (Status
)) {
307 // Reset the Floppy Disk Controller
309 if (!FdcDev
->ControllerState
->FddResetPerformed
) {
310 FdcDev
->ControllerState
->FddResetPerformed
= TRUE
;
311 FdcDev
->ControllerState
->FddResetStatus
= FddReset (FdcDev
);
314 if (EFI_ERROR (FdcDev
->ControllerState
->FddResetStatus
)) {
315 Status
= EFI_DEVICE_ERROR
;
319 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
321 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_PRESENCE_DETECT
,
326 // Discover the Floppy Drive
328 Status
= DiscoverFddDevice (FdcDev
);
329 if (EFI_ERROR (Status
)) {
330 Status
= EFI_DEVICE_ERROR
;
334 // Install protocol interfaces for the serial device.
336 Status
= gBS
->InstallMultipleProtocolInterfaces (
338 &gEfiBlockIoProtocolGuid
,
342 if (!EFI_ERROR (Status
)) {
343 FdcDev
->ControllerState
->NumberOfDrive
++;
347 if (EFI_ERROR (Status
)) {
349 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
350 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
351 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_EC_CONTROLLER_ERROR
,
356 // If a floppy drive device structure was allocated, then free it
358 if (FdcDev
!= NULL
) {
359 if (FdcDev
->Event
!= NULL
) {
361 // Close the event for turning the motor off
363 gBS
->CloseEvent (FdcDev
->Event
);
366 FreeUnicodeStringTable (FdcDev
->ControllerNameTable
);
371 // Close the ISA I/O Protocol
376 &gEfiIsaIoProtocolGuid
,
377 This
->DriverBindingHandle
,
383 // Close the device path protocol
387 &gEfiDevicePathProtocolGuid
,
388 This
->DriverBindingHandle
,
397 Stop this driver on ControllerHandle.
399 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
400 @param[in] ControllerHandle A handle to the device being stopped. The handle must
401 support a bus specific I/O protocol for the driver
402 to use to stop the device.
403 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
404 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
405 if NumberOfChildren is 0.
407 @retval EFI_SUCCESS The device was stopped.
408 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
412 FdcControllerDriverStop (
413 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
414 IN EFI_HANDLE Controller
,
415 IN UINTN NumberOfChildren
,
416 IN EFI_HANDLE
*ChildHandleBuffer
420 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
421 FDC_BLK_IO_DEV
*FdcDev
;
424 // Ignore NumberOfChildren since this is a device driver
428 // Get the Block I/O Protocol on Controller
430 Status
= gBS
->OpenProtocol (
432 &gEfiBlockIoProtocolGuid
,
434 This
->DriverBindingHandle
,
436 EFI_OPEN_PROTOCOL_GET_PROTOCOL
438 if (EFI_ERROR (Status
)) {
442 // Get the floppy drive device's Device structure
444 FdcDev
= FDD_BLK_IO_FROM_THIS (BlkIo
);
447 // Report disable progress code
449 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
451 EFI_PERIPHERAL_REMOVABLE_MEDIA
| EFI_P_PC_DISABLE
,
456 // Uninstall the Block I/O Protocol
458 Status
= gBS
->UninstallProtocolInterface (
460 &gEfiBlockIoProtocolGuid
,
463 if (EFI_ERROR (Status
)) {
468 // Close the event for turning the motor off
470 gBS
->CloseEvent (FdcDev
->Event
);
473 // Turn the motor off on the floppy drive device
475 FddTimerProc (FdcDev
->Event
, FdcDev
);
478 // Close the device path protocol
482 &gEfiDevicePathProtocolGuid
,
483 This
->DriverBindingHandle
,
488 // Close the ISA I/O Protocol
492 &gEfiIsaIoProtocolGuid
,
493 This
->DriverBindingHandle
,
498 // Free the controller list if needed
500 FdcDev
->ControllerState
->NumberOfDrive
--;
503 // Free the cache if one was allocated
505 FdcFreeCache (FdcDev
);
508 // Free the floppy drive device's device structure
510 FreeUnicodeStringTable (FdcDev
->ControllerNameTable
);