]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c
e819a1d13219e0b3939c1450bf697cd8751274ab
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppyDxe / IsaFloppy.c
1 /**@file
2 ISA Floppy Driver
3 1. Support two types diskette drive
4 1.44M drive and 2.88M drive (and now only support 1.44M)
5 2. Support two diskette drives
6 3. Use DMA channel 2 to transfer data
7 4. Do not use interrupt
8 5. Support diskette change line signal and write protect
9
10 conforming to EFI driver model
11
12 Copyright (c) 2006 - 2007, Intel Corporation.<BR>
13 All rights reserved. This program and the accompanying materials
14 are licensed and made available under the terms and conditions of the BSD License
15 which accompanies this distribution. The full text of the license may be found at
16 http://opensource.org/licenses/bsd-license.php
17
18 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
19 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20
21 **/
22
23 #include "IsaFloppy.h"
24
25 LIST_ENTRY gControllerHead = INITIALIZE_LIST_HEAD_VARIABLE(gControllerHead);
26
27 //
28 // ISA Floppy Driver Binding Protocol
29 //
30 EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver = {
31 FdcControllerDriverSupported,
32 FdcControllerDriverStart,
33 FdcControllerDriverStop,
34 0xa,
35 NULL,
36 NULL
37 };
38
39
40 /**
41 The user Entry Point for module IsaFloppy. The user code starts with this function.
42
43 @param[in] ImageHandle The firmware allocated handle for the EFI image.
44 @param[in] SystemTable A pointer to the EFI System Table.
45
46 @retval EFI_SUCCESS The entry point is executed successfully.
47 @retval other Some error occurs when executing this entry point.
48
49 **/
50 EFI_STATUS
51 EFIAPI
52 InitializeIsaFloppy(
53 IN EFI_HANDLE ImageHandle,
54 IN EFI_SYSTEM_TABLE *SystemTable
55 )
56 {
57 EFI_STATUS Status;
58
59 //
60 // Install driver model protocol(s).
61 //
62 Status = EfiLibInstallDriverBindingComponentName2 (
63 ImageHandle,
64 SystemTable,
65 &gFdcControllerDriver,
66 ImageHandle,
67 &gIsaFloppyComponentName,
68 &gIsaFloppyComponentName2
69 );
70 ASSERT_EFI_ERROR (Status);
71
72
73 return Status;
74 }
75
76 /**
77 Test controller is a Floppy Disk Controller
78
79 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
80 @param Controller driver's controller
81 @param RemainingDevicePath children device path
82
83 @retval EFI_UNSUPPORTED controller is not floppy disk
84 @retval EFI_SUCCESS controller is floppy disk
85 **/
86 EFI_STATUS
87 EFIAPI
88 FdcControllerDriverSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL *This,
90 IN EFI_HANDLE Controller,
91 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
92 )
93 {
94 EFI_STATUS Status;
95 EFI_ISA_IO_PROTOCOL *IsaIo;
96
97 //
98 // Open the ISA I/O Protocol
99 //
100 Status = gBS->OpenProtocol (
101 Controller,
102 &gEfiIsaIoProtocolGuid,
103 (VOID **) &IsaIo,
104 This->DriverBindingHandle,
105 Controller,
106 EFI_OPEN_PROTOCOL_BY_DRIVER
107 );
108 if (EFI_ERROR (Status)) {
109 return Status;
110 }
111 //
112 // Use the ISA I/O Protocol to see if Controller is a Floppy Disk Controller
113 //
114 Status = EFI_SUCCESS;
115 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
116 Status = EFI_UNSUPPORTED;
117 }
118 //
119 // Close the ISA I/O Protocol
120 //
121 gBS->CloseProtocol (
122 Controller,
123 &gEfiIsaIoProtocolGuid,
124 This->DriverBindingHandle,
125 Controller
126 );
127
128 return Status;
129 }
130
131 /**
132 Create floppy control instance on controller.
133
134 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
135 @param Controller driver controller handle
136 @param RemainingDevicePath Children's device path
137
138 @retval whether success to create floppy control instance.
139 **/
140 EFI_STATUS
141 EFIAPI
142 FdcControllerDriverStart (
143 IN EFI_DRIVER_BINDING_PROTOCOL *This,
144 IN EFI_HANDLE Controller,
145 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
146 )
147 {
148 EFI_STATUS Status;
149 FDC_BLK_IO_DEV *FdcDev;
150 EFI_ISA_IO_PROTOCOL *IsaIo;
151 UINTN Index;
152 LIST_ENTRY *List;
153 BOOLEAN Found;
154 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
155
156 FdcDev = NULL;
157 IsaIo = NULL;
158
159 //
160 // Open the device path protocol
161 //
162 Status = gBS->OpenProtocol (
163 Controller,
164 &gEfiDevicePathProtocolGuid,
165 (VOID **) &ParentDevicePath,
166 This->DriverBindingHandle,
167 Controller,
168 EFI_OPEN_PROTOCOL_BY_DRIVER
169 );
170 if (EFI_ERROR (Status)) {
171 return Status;
172 }
173 //
174 // Report enable progress code
175 //
176 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
177 EFI_PROGRESS_CODE,
178 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE,
179 ParentDevicePath
180 );
181
182 //
183 // Open the ISA I/O Protocol
184 //
185 Status = gBS->OpenProtocol (
186 Controller,
187 &gEfiIsaIoProtocolGuid,
188 (VOID **) &IsaIo,
189 This->DriverBindingHandle,
190 Controller,
191 EFI_OPEN_PROTOCOL_BY_DRIVER
192 );
193 if (EFI_ERROR (Status)) {
194 goto Done;
195 }
196 //
197 // Allocate the Floppy Disk Controller's Device structure
198 //
199 FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV));
200 if (FdcDev == NULL) {
201 goto Done;
202 }
203 //
204 // Initialize the Floppy Disk Controller's Device structure
205 //
206 FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;
207 FdcDev->Handle = Controller;
208 FdcDev->IsaIo = IsaIo;
209 FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID;
210 FdcDev->Cache = NULL;
211 FdcDev->Event = NULL;
212 FdcDev->ControllerState = NULL;
213 FdcDev->DevicePath = ParentDevicePath;
214
215 ADD_FLOPPY_NAME (FdcDev);
216
217 //
218 // Look up the base address of the Floppy Disk Controller
219 //
220 for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {
221 if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {
222 FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange;
223 }
224 }
225 //
226 // Maintain the list of controller list
227 //
228 Found = FALSE;
229 List = gControllerHead.ForwardLink;
230 while (List != &gControllerHead) {
231 FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List);
232 if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) {
233 Found = TRUE;
234 break;
235 }
236
237 List = List->ForwardLink;
238 }
239
240 if (!Found) {
241 //
242 // The Controller is new
243 //
244 FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT));
245 if (FdcDev->ControllerState == NULL) {
246 goto Done;
247 }
248
249 FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE;
250 FdcDev->ControllerState->FddResetPerformed = FALSE;
251 FdcDev->ControllerState->NeedRecalibrate = FALSE;
252 FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress;
253 FdcDev->ControllerState->NumberOfDrive = 0;
254
255 InsertTailList (&gControllerHead, &FdcDev->ControllerState->Link);
256 }
257 //
258 // Create a timer event for each Floppd Disk Controller.
259 // This timer event is used to control the motor on and off
260 //
261 Status = gBS->CreateEvent (
262 EVT_TIMER | EVT_NOTIFY_SIGNAL,
263 TPL_NOTIFY,
264 FddTimerProc,
265 FdcDev,
266 &FdcDev->Event
267 );
268 if (EFI_ERROR (Status)) {
269 goto Done;
270 }
271 //
272 // Reset the Floppy Disk Controller
273 //
274 if (!FdcDev->ControllerState->FddResetPerformed) {
275 FdcDev->ControllerState->FddResetPerformed = TRUE;
276 FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev);
277 }
278
279 if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) {
280 Status = EFI_DEVICE_ERROR;
281 goto Done;
282 }
283
284 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
285 EFI_PROGRESS_CODE,
286 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT,
287 ParentDevicePath
288 );
289
290 //
291 // Discover the Floppy Drive
292 //
293 Status = DiscoverFddDevice (FdcDev);
294 if (EFI_ERROR (Status)) {
295 Status = EFI_DEVICE_ERROR;
296 goto Done;
297 }
298 //
299 // Install protocol interfaces for the serial device.
300 //
301 Status = gBS->InstallMultipleProtocolInterfaces (
302 &Controller,
303 &gEfiBlockIoProtocolGuid,
304 &FdcDev->BlkIo,
305 NULL
306 );
307
308 FdcDev->ControllerState->NumberOfDrive++;
309
310 Done:
311 if (EFI_ERROR (Status)) {
312
313 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
314 EFI_ERROR_CODE | EFI_ERROR_MINOR,
315 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR,
316 ParentDevicePath
317 );
318
319 //
320 // Close the device path protocol
321 //
322 gBS->CloseProtocol (
323 Controller,
324 &gEfiDevicePathProtocolGuid,
325 This->DriverBindingHandle,
326 Controller
327 );
328
329 //
330 // Close the ISA I/O Protocol
331 //
332 if (IsaIo != NULL) {
333 gBS->CloseProtocol (
334 Controller,
335 &gEfiIsaIoProtocolGuid,
336 This->DriverBindingHandle,
337 Controller
338 );
339 }
340 //
341 // If a Floppy Disk Controller Device structure was allocated, then free it
342 //
343 if (FdcDev != NULL) {
344 if (FdcDev->Event != NULL) {
345 //
346 // Close the event for turning the motor off
347 //
348 gBS->CloseEvent (FdcDev->Event);
349 }
350
351 FreeUnicodeStringTable (FdcDev->ControllerNameTable);
352 gBS->FreePool (FdcDev);
353 }
354 }
355
356 return Status;
357 }
358
359 /**
360 Stop this driver on ControllerHandle. Support stoping any child handles
361 created by this driver.
362
363 @param This Protocol instance pointer.
364 @param Controller Handle of device to stop driver on
365 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
366 children is zero stop the entire bus driver.
367 @param ChildHandleBuffer List of Child Handles to Stop.
368
369 @retval EFI_SUCCESS This driver is removed ControllerHandle
370 @retval other This driver was not removed from this device
371
372 **/
373 EFI_STATUS
374 EFIAPI
375 FdcControllerDriverStop (
376 IN EFI_DRIVER_BINDING_PROTOCOL *This,
377 IN EFI_HANDLE Controller,
378 IN UINTN NumberOfChildren,
379 IN EFI_HANDLE *ChildHandleBuffer
380 )
381 {
382 EFI_STATUS Status;
383 EFI_BLOCK_IO_PROTOCOL *BlkIo;
384 FDC_BLK_IO_DEV *FdcDev;
385
386 //
387 // Get the Block I/O Protocol on Controller
388 //
389 Status = gBS->OpenProtocol (
390 Controller,
391 &gEfiBlockIoProtocolGuid,
392 (VOID **) &BlkIo,
393 This->DriverBindingHandle,
394 Controller,
395 EFI_OPEN_PROTOCOL_GET_PROTOCOL
396 );
397 if (EFI_ERROR (Status)) {
398 return Status;
399 }
400 //
401 // Get the Floppy Disk Controller's Device structure
402 //
403 FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo);
404
405 //
406 // Report disable progress code
407 //
408 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
409 EFI_PROGRESS_CODE,
410 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE,
411 FdcDev->DevicePath
412 );
413
414 //
415 // Turn the motor off on the Floppy Disk Controller
416 //
417 FddTimerProc (FdcDev->Event, FdcDev);
418
419 //
420 // Uninstall the Block I/O Protocol
421 //
422 Status = gBS->UninstallProtocolInterface (
423 Controller,
424 &gEfiBlockIoProtocolGuid,
425 &FdcDev->BlkIo
426 );
427 if (EFI_ERROR (Status)) {
428 return Status;
429 }
430 //
431 // Close the device path protocol
432 //
433 gBS->CloseProtocol (
434 Controller,
435 &gEfiDevicePathProtocolGuid,
436 This->DriverBindingHandle,
437 Controller
438 );
439
440 //
441 // Close the ISA I/O Protocol
442 //
443 gBS->CloseProtocol (
444 Controller,
445 &gEfiIsaIoProtocolGuid,
446 This->DriverBindingHandle,
447 Controller
448 );
449
450 //
451 // Free the controller list if needed
452 //
453 FdcDev->ControllerState->NumberOfDrive--;
454
455 //
456 // Close the event for turning the motor off
457 //
458 gBS->CloseEvent (FdcDev->Event);
459
460 //
461 // Free the cache if one was allocated
462 //
463 FdcFreeCache (FdcDev);
464
465 //
466 // Free the Floppy Disk Controller's Device structure
467 //
468 FreeUnicodeStringTable (FdcDev->ControllerNameTable);
469 gBS->FreePool (FdcDev);
470
471 return EFI_SUCCESS;
472 }
473