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