]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c
6d7edd6f10446dad32b95b16d9ce09865fbd3f82
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppyDxe / IsaFloppy.c
1 /** @file
2 ISA Floppy Disk UEFI Driver conforming to the UEFI driver model
3
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
10
11 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
12 SPDX-License-Identifier: BSD-2-Clause-Patent
13
14 **/
15
16 #include "IsaFloppy.h"
17
18 LIST_ENTRY mControllerHead = INITIALIZE_LIST_HEAD_VARIABLE (mControllerHead);
19
20 //
21 // ISA Floppy Driver Binding Protocol
22 //
23 EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver = {
24 FdcControllerDriverSupported,
25 FdcControllerDriverStart,
26 FdcControllerDriverStop,
27 0xa,
28 NULL,
29 NULL
30 };
31
32
33 /**
34 The main Entry Point for this driver.
35
36 @param[in] ImageHandle The firmware allocated handle for the EFI image.
37 @param[in] SystemTable A pointer to the EFI System Table.
38
39 @retval EFI_SUCCESS The entry point is executed successfully.
40 @retval other Some error occurs when executing this entry point.
41 **/
42 EFI_STATUS
43 EFIAPI
44 InitializeIsaFloppy(
45 IN EFI_HANDLE ImageHandle,
46 IN EFI_SYSTEM_TABLE *SystemTable
47 )
48 {
49 EFI_STATUS Status;
50
51 //
52 // Install driver model protocol(s).
53 //
54 Status = EfiLibInstallDriverBindingComponentName2 (
55 ImageHandle,
56 SystemTable,
57 &gFdcControllerDriver,
58 ImageHandle,
59 &gIsaFloppyComponentName,
60 &gIsaFloppyComponentName2
61 );
62 ASSERT_EFI_ERROR (Status);
63
64 return Status;
65 }
66
67 /**
68 Test if the controller is a floppy disk drive device
69
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.
73
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.
79 **/
80 EFI_STATUS
81 EFIAPI
82 FdcControllerDriverSupported (
83 IN EFI_DRIVER_BINDING_PROTOCOL *This,
84 IN EFI_HANDLE Controller,
85 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
86 )
87 {
88 EFI_STATUS Status;
89 EFI_ISA_IO_PROTOCOL *IsaIo;
90 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
91
92 //
93 // Ignore the parameter RemainingDevicePath because this is a device driver.
94 //
95
96 //
97 // Open the device path protocol
98 //
99 Status = gBS->OpenProtocol (
100 Controller,
101 &gEfiDevicePathProtocolGuid,
102 (VOID **) &ParentDevicePath,
103 This->DriverBindingHandle,
104 Controller,
105 EFI_OPEN_PROTOCOL_BY_DRIVER
106 );
107 if (EFI_ERROR (Status)) {
108 return Status;
109 }
110
111 gBS->CloseProtocol (
112 Controller,
113 &gEfiDevicePathProtocolGuid,
114 This->DriverBindingHandle,
115 Controller
116 );
117
118 //
119 // Open the ISA I/O Protocol
120 //
121 Status = gBS->OpenProtocol (
122 Controller,
123 &gEfiIsaIoProtocolGuid,
124 (VOID **) &IsaIo,
125 This->DriverBindingHandle,
126 Controller,
127 EFI_OPEN_PROTOCOL_BY_DRIVER
128 );
129 if (EFI_ERROR (Status)) {
130 return Status;
131 }
132 //
133 // Use the ISA I/O Protocol to see if Controller is a floppy disk drive device
134 //
135 Status = EFI_SUCCESS;
136 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
137 Status = EFI_UNSUPPORTED;
138 }
139 //
140 // Close the ISA I/O Protocol
141 //
142 gBS->CloseProtocol (
143 Controller,
144 &gEfiIsaIoProtocolGuid,
145 This->DriverBindingHandle,
146 Controller
147 );
148
149 return Status;
150 }
151
152 /**
153 Start this driver on Controller.
154
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.
161
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.
167 **/
168 EFI_STATUS
169 EFIAPI
170 FdcControllerDriverStart (
171 IN EFI_DRIVER_BINDING_PROTOCOL *This,
172 IN EFI_HANDLE Controller,
173 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
174 )
175 {
176 EFI_STATUS Status;
177 FDC_BLK_IO_DEV *FdcDev;
178 EFI_ISA_IO_PROTOCOL *IsaIo;
179 UINTN Index;
180 LIST_ENTRY *List;
181 BOOLEAN Found;
182 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
183
184 FdcDev = NULL;
185 IsaIo = NULL;
186
187 //
188 // Open the device path protocol
189 //
190 Status = gBS->OpenProtocol (
191 Controller,
192 &gEfiDevicePathProtocolGuid,
193 (VOID **) &ParentDevicePath,
194 This->DriverBindingHandle,
195 Controller,
196 EFI_OPEN_PROTOCOL_BY_DRIVER
197 );
198 if (EFI_ERROR (Status)) {
199 return Status;
200 }
201 //
202 // Report enable progress code
203 //
204 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
205 EFI_PROGRESS_CODE,
206 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE,
207 ParentDevicePath
208 );
209
210 //
211 // Open the ISA I/O Protocol
212 //
213 Status = gBS->OpenProtocol (
214 Controller,
215 &gEfiIsaIoProtocolGuid,
216 (VOID **) &IsaIo,
217 This->DriverBindingHandle,
218 Controller,
219 EFI_OPEN_PROTOCOL_BY_DRIVER
220 );
221 if (EFI_ERROR (Status)) {
222 goto Done;
223 }
224 //
225 // Allocate the floppy device's Device structure
226 //
227 FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV));
228 if (FdcDev == NULL) {
229 goto Done;
230 }
231 //
232 // Initialize the floppy device's device structure
233 //
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;
242
243 FdcDev->ControllerNameTable = NULL;
244 AddName (FdcDev);
245
246 //
247 // Look up the base address of the Floppy Disk Controller which controls this floppy device
248 //
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;
252 }
253 }
254 //
255 // Maintain the list of floppy disk controllers
256 //
257 Found = FALSE;
258 List = mControllerHead.ForwardLink;
259 while (List != &mControllerHead) {
260 FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List);
261 if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) {
262 Found = TRUE;
263 break;
264 }
265
266 List = List->ForwardLink;
267 }
268
269 if (!Found) {
270 //
271 // A new floppy disk controller controlling this floppy disk drive is found
272 //
273 FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT));
274 if (FdcDev->ControllerState == NULL) {
275 goto Done;
276 }
277
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;
283
284 InsertTailList (&mControllerHead, &FdcDev->ControllerState->Link);
285 }
286 //
287 // Create a timer event for each floppy disk drive device.
288 // This timer event is used to control the motor on and off
289 //
290 Status = gBS->CreateEvent (
291 EVT_TIMER | EVT_NOTIFY_SIGNAL,
292 TPL_NOTIFY,
293 FddTimerProc,
294 FdcDev,
295 &FdcDev->Event
296 );
297 if (EFI_ERROR (Status)) {
298 goto Done;
299 }
300 //
301 // Reset the Floppy Disk Controller
302 //
303 if (!FdcDev->ControllerState->FddResetPerformed) {
304 FdcDev->ControllerState->FddResetPerformed = TRUE;
305 FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev);
306 }
307
308 if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) {
309 Status = EFI_DEVICE_ERROR;
310 goto Done;
311 }
312
313 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
314 EFI_PROGRESS_CODE,
315 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT,
316 ParentDevicePath
317 );
318
319 //
320 // Discover the Floppy Drive
321 //
322 Status = DiscoverFddDevice (FdcDev);
323 if (EFI_ERROR (Status)) {
324 Status = EFI_DEVICE_ERROR;
325 goto Done;
326 }
327 //
328 // Install protocol interfaces for the serial device.
329 //
330 Status = gBS->InstallMultipleProtocolInterfaces (
331 &Controller,
332 &gEfiBlockIoProtocolGuid,
333 &FdcDev->BlkIo,
334 NULL
335 );
336 if (!EFI_ERROR (Status)) {
337 FdcDev->ControllerState->NumberOfDrive++;
338 }
339
340 Done:
341 if (EFI_ERROR (Status)) {
342
343 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
344 EFI_ERROR_CODE | EFI_ERROR_MINOR,
345 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR,
346 ParentDevicePath
347 );
348
349 //
350 // If a floppy drive device structure was allocated, then free it
351 //
352 if (FdcDev != NULL) {
353 if (FdcDev->Event != NULL) {
354 //
355 // Close the event for turning the motor off
356 //
357 gBS->CloseEvent (FdcDev->Event);
358 }
359
360 FreeUnicodeStringTable (FdcDev->ControllerNameTable);
361 FreePool (FdcDev);
362 }
363
364 //
365 // Close the ISA I/O Protocol
366 //
367 if (IsaIo != NULL) {
368 gBS->CloseProtocol (
369 Controller,
370 &gEfiIsaIoProtocolGuid,
371 This->DriverBindingHandle,
372 Controller
373 );
374 }
375
376 //
377 // Close the device path protocol
378 //
379 gBS->CloseProtocol (
380 Controller,
381 &gEfiDevicePathProtocolGuid,
382 This->DriverBindingHandle,
383 Controller
384 );
385 }
386
387 return Status;
388 }
389
390 /**
391 Stop this driver on ControllerHandle.
392
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.
400
401 @retval EFI_SUCCESS The device was stopped.
402 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
403 **/
404 EFI_STATUS
405 EFIAPI
406 FdcControllerDriverStop (
407 IN EFI_DRIVER_BINDING_PROTOCOL *This,
408 IN EFI_HANDLE Controller,
409 IN UINTN NumberOfChildren,
410 IN EFI_HANDLE *ChildHandleBuffer
411 )
412 {
413 EFI_STATUS Status;
414 EFI_BLOCK_IO_PROTOCOL *BlkIo;
415 FDC_BLK_IO_DEV *FdcDev;
416
417 //
418 // Ignore NumberOfChildren since this is a device driver
419 //
420
421 //
422 // Get the Block I/O Protocol on Controller
423 //
424 Status = gBS->OpenProtocol (
425 Controller,
426 &gEfiBlockIoProtocolGuid,
427 (VOID **) &BlkIo,
428 This->DriverBindingHandle,
429 Controller,
430 EFI_OPEN_PROTOCOL_GET_PROTOCOL
431 );
432 if (EFI_ERROR (Status)) {
433 return Status;
434 }
435 //
436 // Get the floppy drive device's Device structure
437 //
438 FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo);
439
440 //
441 // Report disable progress code
442 //
443 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
444 EFI_PROGRESS_CODE,
445 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE,
446 FdcDev->DevicePath
447 );
448
449 //
450 // Uninstall the Block I/O Protocol
451 //
452 Status = gBS->UninstallProtocolInterface (
453 Controller,
454 &gEfiBlockIoProtocolGuid,
455 &FdcDev->BlkIo
456 );
457 if (EFI_ERROR (Status)) {
458 return Status;
459 }
460
461 //
462 // Close the event for turning the motor off
463 //
464 gBS->CloseEvent (FdcDev->Event);
465
466 //
467 // Turn the motor off on the floppy drive device
468 //
469 FddTimerProc (FdcDev->Event, FdcDev);
470
471 //
472 // Close the device path protocol
473 //
474 gBS->CloseProtocol (
475 Controller,
476 &gEfiDevicePathProtocolGuid,
477 This->DriverBindingHandle,
478 Controller
479 );
480
481 //
482 // Close the ISA I/O Protocol
483 //
484 gBS->CloseProtocol (
485 Controller,
486 &gEfiIsaIoProtocolGuid,
487 This->DriverBindingHandle,
488 Controller
489 );
490
491 //
492 // Free the controller list if needed
493 //
494 FdcDev->ControllerState->NumberOfDrive--;
495
496 //
497 // Free the cache if one was allocated
498 //
499 FdcFreeCache (FdcDev);
500
501 //
502 // Free the floppy drive device's device structure
503 //
504 FreeUnicodeStringTable (FdcDev->ControllerNameTable);
505 FreePool (FdcDev);
506
507 return EFI_SUCCESS;
508 }
509