]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/IsaFloppy.c
9b04af057cc0c7699e98f4274264cf892ba72fee
[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 = EfiLibInstallAllDriverProtocols (
63 ImageHandle,
64 SystemTable,
65 &gFdcControllerDriver,
66 ImageHandle,
67 &gIsaFloppyComponentName,
68 NULL,
69 NULL
70 );
71 ASSERT_EFI_ERROR (Status);
72
73
74 return Status;
75 }
76
77
78 EFI_STATUS
79 EFIAPI
80 FdcControllerDriverSupported (
81 IN EFI_DRIVER_BINDING_PROTOCOL *This,
82 IN EFI_HANDLE Controller,
83 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
84 )
85 /*++
86
87 Routine Description:
88
89 ControllerDriver Protocol Method
90
91 Arguments:
92
93 Returns:
94
95 --*/
96 // GC_TODO: This - add argument and description to function comment
97 // GC_TODO: Controller - add argument and description to function comment
98 // GC_TODO: RemainingDevicePath - add argument and description to function comment
99 {
100 EFI_STATUS Status;
101 EFI_ISA_IO_PROTOCOL *IsaIo;
102
103 //
104 // Open the ISA I/O Protocol
105 //
106 Status = gBS->OpenProtocol (
107 Controller,
108 &gEfiIsaIoProtocolGuid,
109 (VOID **) &IsaIo,
110 This->DriverBindingHandle,
111 Controller,
112 EFI_OPEN_PROTOCOL_BY_DRIVER
113 );
114 if (EFI_ERROR (Status)) {
115 return Status;
116 }
117 //
118 // Use the ISA I/O Protocol to see if Controller is a Floppy Disk Controller
119 //
120 Status = EFI_SUCCESS;
121 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
122 Status = EFI_UNSUPPORTED;
123 }
124 //
125 // Close the ISA I/O Protocol
126 //
127 gBS->CloseProtocol (
128 Controller,
129 &gEfiIsaIoProtocolGuid,
130 This->DriverBindingHandle,
131 Controller
132 );
133
134 return Status;
135 }
136
137 EFI_STATUS
138 EFIAPI
139 FdcControllerDriverStart (
140 IN EFI_DRIVER_BINDING_PROTOCOL *This,
141 IN EFI_HANDLE Controller,
142 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
143 )
144 /*++
145
146 Routine Description:
147
148 Arguments:
149
150 Returns:
151
152 --*/
153 // GC_TODO: This - add argument and description to function comment
154 // GC_TODO: Controller - add argument and description to function comment
155 // GC_TODO: RemainingDevicePath - add argument and description to function comment
156 {
157 EFI_STATUS Status;
158 FDC_BLK_IO_DEV *FdcDev;
159 EFI_ISA_IO_PROTOCOL *IsaIo;
160 UINTN Index;
161 LIST_ENTRY *List;
162 BOOLEAN Found;
163 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
164
165 FdcDev = NULL;
166 IsaIo = NULL;
167
168 //
169 // Open the device path protocol
170 //
171 Status = gBS->OpenProtocol (
172 Controller,
173 &gEfiDevicePathProtocolGuid,
174 (VOID **) &ParentDevicePath,
175 This->DriverBindingHandle,
176 Controller,
177 EFI_OPEN_PROTOCOL_BY_DRIVER
178 );
179 if (EFI_ERROR (Status)) {
180 return Status;
181 }
182 //
183 // Report enable progress code
184 //
185 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
186 EFI_PROGRESS_CODE,
187 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE,
188 ParentDevicePath
189 );
190
191 //
192 // Open the ISA I/O Protocol
193 //
194 Status = gBS->OpenProtocol (
195 Controller,
196 &gEfiIsaIoProtocolGuid,
197 (VOID **) &IsaIo,
198 This->DriverBindingHandle,
199 Controller,
200 EFI_OPEN_PROTOCOL_BY_DRIVER
201 );
202 if (EFI_ERROR (Status)) {
203 goto Done;
204 }
205 //
206 // Allocate the Floppy Disk Controller's Device structure
207 //
208 FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV));
209 if (FdcDev == NULL) {
210 goto Done;
211 }
212 //
213 // Initialize the Floppy Disk Controller's Device structure
214 //
215 FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;
216 FdcDev->Handle = Controller;
217 FdcDev->IsaIo = IsaIo;
218 FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID;
219 FdcDev->Cache = NULL;
220 FdcDev->Event = NULL;
221 FdcDev->ControllerState = NULL;
222 FdcDev->DevicePath = ParentDevicePath;
223
224 ADD_FLOPPY_NAME (FdcDev);
225
226 //
227 // Look up the base address of the Floppy Disk Controller
228 //
229 for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {
230 if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {
231 FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange;
232 }
233 }
234 //
235 // Maintain the list of controller list
236 //
237 Found = FALSE;
238 List = gControllerHead.ForwardLink;
239 while (List != &gControllerHead) {
240 FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List);
241 if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) {
242 Found = TRUE;
243 break;
244 }
245
246 List = List->ForwardLink;
247 }
248
249 if (!Found) {
250 //
251 // The Controller is new
252 //
253 FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT));
254 if (FdcDev->ControllerState == NULL) {
255 goto Done;
256 }
257
258 FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE;
259 FdcDev->ControllerState->FddResetPerformed = FALSE;
260 FdcDev->ControllerState->NeedRecalibrate = FALSE;
261 FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress;
262 FdcDev->ControllerState->NumberOfDrive = 0;
263
264 InsertTailList (&gControllerHead, &FdcDev->ControllerState->Link);
265 }
266 //
267 // Create a timer event for each Floppd Disk Controller.
268 // This timer event is used to control the motor on and off
269 //
270 Status = gBS->CreateEvent (
271 EVT_TIMER | EVT_NOTIFY_SIGNAL,
272 TPL_NOTIFY,
273 FddTimerProc,
274 FdcDev,
275 &FdcDev->Event
276 );
277 if (EFI_ERROR (Status)) {
278 goto Done;
279 }
280 //
281 // Reset the Floppy Disk Controller
282 //
283 if (!FdcDev->ControllerState->FddResetPerformed) {
284 FdcDev->ControllerState->FddResetPerformed = TRUE;
285 FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev);
286 }
287
288 if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) {
289 Status = EFI_DEVICE_ERROR;
290 goto Done;
291 }
292
293 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
294 EFI_PROGRESS_CODE,
295 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT,
296 ParentDevicePath
297 );
298
299 //
300 // Discover the Floppy Drive
301 //
302 Status = DiscoverFddDevice (FdcDev);
303 if (EFI_ERROR (Status)) {
304 Status = EFI_DEVICE_ERROR;
305 goto Done;
306 }
307 //
308 // Install protocol interfaces for the serial device.
309 //
310 Status = gBS->InstallMultipleProtocolInterfaces (
311 &Controller,
312 &gEfiBlockIoProtocolGuid,
313 &FdcDev->BlkIo,
314 NULL
315 );
316
317 FdcDev->ControllerState->NumberOfDrive++;
318
319 Done:
320 if (EFI_ERROR (Status)) {
321
322 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
323 EFI_ERROR_CODE | EFI_ERROR_MINOR,
324 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR,
325 ParentDevicePath
326 );
327
328 //
329 // Close the device path protocol
330 //
331 gBS->CloseProtocol (
332 Controller,
333 &gEfiDevicePathProtocolGuid,
334 This->DriverBindingHandle,
335 Controller
336 );
337
338 //
339 // Close the ISA I/O Protocol
340 //
341 if (IsaIo != NULL) {
342 gBS->CloseProtocol (
343 Controller,
344 &gEfiIsaIoProtocolGuid,
345 This->DriverBindingHandle,
346 Controller
347 );
348 }
349 //
350 // If a Floppy Disk Controller 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 gBS->FreePool (FdcDev);
362 }
363 }
364
365 return Status;
366 }
367
368 EFI_STATUS
369 EFIAPI
370 FdcControllerDriverStop (
371 IN EFI_DRIVER_BINDING_PROTOCOL *This,
372 IN EFI_HANDLE Controller,
373 IN UINTN NumberOfChildren,
374 IN EFI_HANDLE *ChildHandleBuffer
375 )
376 /*++
377
378 Routine Description:
379
380 Arguments:
381
382 Returns:
383
384 --*/
385 // GC_TODO: This - add argument and description to function comment
386 // GC_TODO: Controller - add argument and description to function comment
387 // GC_TODO: NumberOfChildren - add argument and description to function comment
388 // GC_TODO: ChildHandleBuffer - add argument and description to function comment
389 // GC_TODO: EFI_SUCCESS - add return value to function comment
390 {
391 EFI_STATUS Status;
392 EFI_BLOCK_IO_PROTOCOL *BlkIo;
393 FDC_BLK_IO_DEV *FdcDev;
394
395 //
396 // Get the Block I/O Protocol on Controller
397 //
398 Status = gBS->OpenProtocol (
399 Controller,
400 &gEfiBlockIoProtocolGuid,
401 (VOID **) &BlkIo,
402 This->DriverBindingHandle,
403 Controller,
404 EFI_OPEN_PROTOCOL_GET_PROTOCOL
405 );
406 if (EFI_ERROR (Status)) {
407 return Status;
408 }
409 //
410 // Get the Floppy Disk Controller's Device structure
411 //
412 FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo);
413
414 //
415 // Report disable progress code
416 //
417 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
418 EFI_PROGRESS_CODE,
419 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE,
420 FdcDev->DevicePath
421 );
422
423 //
424 // Turn the motor off on the Floppy Disk Controller
425 //
426 FddTimerProc (FdcDev->Event, FdcDev);
427
428 //
429 // Uninstall the Block I/O Protocol
430 //
431 Status = gBS->UninstallProtocolInterface (
432 Controller,
433 &gEfiBlockIoProtocolGuid,
434 &FdcDev->BlkIo
435 );
436 if (EFI_ERROR (Status)) {
437 return Status;
438 }
439 //
440 // Close the device path protocol
441 //
442 gBS->CloseProtocol (
443 Controller,
444 &gEfiDevicePathProtocolGuid,
445 This->DriverBindingHandle,
446 Controller
447 );
448
449 //
450 // Close the ISA I/O Protocol
451 //
452 gBS->CloseProtocol (
453 Controller,
454 &gEfiIsaIoProtocolGuid,
455 This->DriverBindingHandle,
456 Controller
457 );
458
459 //
460 // Free the controller list if needed
461 //
462 FdcDev->ControllerState->NumberOfDrive--;
463
464 //
465 // Close the event for turning the motor off
466 //
467 gBS->CloseEvent (FdcDev->Event);
468
469 //
470 // Free the cache if one was allocated
471 //
472 FdcFreeCache (FdcDev);
473
474 //
475 // Free the Floppy Disk Controller's Device structure
476 //
477 FreeUnicodeStringTable (FdcDev->ControllerNameTable);
478 gBS->FreePool (FdcDev);
479
480 return EFI_SUCCESS;
481 }