]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Isa/IsaFloppyDxe/Dxe/IsaFloppyCtrl.c
Rename IsaFloppy to IsaFloppyDxe
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / IsaFloppyDxe / Dxe / IsaFloppyCtrl.c
CommitLineData
11f43dfd 1/*++\r
2\r
6db49ee6 3 Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11f43dfd 11\r
12Module Name:\r
13\r
14 IsaFloppyCtrl.c\r
15\r
16Abstract:\r
17\r
18 ISA Floppy Driver\r
19 1. Support two types diskette drive \r
20 1.44M drive and 2.88M drive (and now only support 1.44M)\r
21 2. Support two diskette drives\r
22 3. Use DMA channel 2 to transfer data\r
23 4. Do not use interrupt\r
24 5. Support diskette change line signal and write protect\r
25 \r
26 The internal function for the floppy driver\r
27\r
28Revision History:\r
29\r
30--*/\r
31\r
32#include "IsaFloppy.h"\r
33\r
34EFI_STATUS\r
35DiscoverFddDevice (\r
36 IN FDC_BLK_IO_DEV *FdcDev\r
37 )\r
38/*++\r
39\r
40 Routine Description: Detect the floppy drive is presented or not \r
41 Parameters:\r
42 FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV \r
43 Returns:\r
44 EFI_SUCCESS Drive is presented \r
45 EFI_NOT_FOUND Drive is not presented\r
46\r
47--*/\r
48// GC_TODO: function comment is missing 'Arguments:'\r
49// GC_TODO: FdcDev - add argument and description to function comment\r
50{\r
51 EFI_STATUS Status;\r
52\r
53 FdcDev->BlkIo.Media = &FdcDev->BlkMedia;\r
54\r
55 //\r
56 // Call FddIndentify subroutine\r
57 //\r
58 Status = FddIdentify (FdcDev);\r
59 if (EFI_ERROR (Status)) {\r
60 return EFI_NOT_FOUND;\r
61 }\r
62\r
63 FdcDev->BlkIo.Reset = FdcReset;\r
64 FdcDev->BlkIo.FlushBlocks = FddFlushBlocks;\r
65 FdcDev->BlkIo.ReadBlocks = FddReadBlocks;\r
66 FdcDev->BlkIo.WriteBlocks = FddWriteBlocks;\r
67 FdcDev->BlkMedia.LogicalPartition = FALSE;\r
68 FdcDev->BlkMedia.WriteCaching = FALSE;\r
69\r
70 return EFI_SUCCESS;\r
71}\r
72\r
73EFI_STATUS\r
74FddIdentify (\r
75 IN FDC_BLK_IO_DEV *FdcDev\r
76 )\r
77/*++\r
78\r
79 Routine Description: Do recalibrate and see the drive is presented or not\r
80 Set the media parameters\r
81 Parameters:\r
82 FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV \r
83 Returns:\r
84 EFI_SUCCESS: \r
85 EFI_DEVICE_ERROR: \r
86\r
87--*/\r
88// GC_TODO: function comment is missing 'Arguments:'\r
89// GC_TODO: FdcDev - add argument and description to function comment\r
90{\r
91 EFI_STATUS Status;\r
92\r
93 //\r
94 // Set Floppy Disk Controller's motor on\r
95 //\r
96 Status = MotorOn (FdcDev);\r
97 if (EFI_ERROR (Status)) {\r
98 return EFI_DEVICE_ERROR;\r
99 }\r
100\r
101 Status = Recalibrate (FdcDev);\r
102\r
103 if (EFI_ERROR (Status)) {\r
104 MotorOff (FdcDev);\r
105 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
106 return EFI_DEVICE_ERROR;\r
107 }\r
108 //\r
109 // Set Media Parameter\r
110 //\r
111 FdcDev->BlkIo.Media->RemovableMedia = TRUE;\r
112 FdcDev->BlkIo.Media->MediaPresent = TRUE;\r
113 //\r
114 // investigate\r
115 //\r
116 FdcDev->BlkIo.Media->MediaId = 0;\r
117\r
118 //\r
119 // Check Media\r
120 //\r
121 Status = DisketChanged (FdcDev);\r
122 switch (Status) {\r
123 case EFI_NO_MEDIA:\r
124 FdcDev->BlkIo.Media->MediaPresent = FALSE;\r
125 break;\r
126\r
127 case EFI_MEDIA_CHANGED:\r
128 case EFI_SUCCESS:\r
129 break;\r
130\r
131 default:\r
132 MotorOff (FdcDev);\r
133 return Status;\r
134 }\r
135 //\r
136 // Check Disk Write Protected\r
137 //\r
138 Status = SenseDrvStatus (FdcDev, 0);\r
139 switch (Status) {\r
140 case EFI_WRITE_PROTECTED:\r
141 FdcDev->BlkIo.Media->ReadOnly = TRUE;\r
142 break;\r
143\r
144 case EFI_SUCCESS:\r
145 FdcDev->BlkIo.Media->ReadOnly = FALSE;\r
146 break;\r
147\r
148 default:\r
149 return EFI_DEVICE_ERROR;\r
150 break;\r
151 }\r
152\r
153 MotorOff (FdcDev);\r
154\r
155 //\r
156 // Set Media Default Type\r
157 //\r
158 FdcDev->BlkIo.Media->BlockSize = DISK_1440K_BYTEPERSECTOR;\r
159 FdcDev->BlkIo.Media->LastBlock = DISK_1440K_EOT * 2 * (DISK_1440K_MAXTRACKNUM + 1) - 1;\r
160\r
161 return EFI_SUCCESS;\r
162}\r
163\r
164EFI_STATUS\r
165FddReset (\r
166 IN FDC_BLK_IO_DEV *FdcDev\r
167 )\r
168/*++\r
169\r
170 Routine Description: Reset the Floppy Logic Drive \r
171 Parameters:\r
172 FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV \r
173 Returns:\r
174 EFI_SUCCESS: The Floppy Logic Drive is reset\r
175 EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and \r
176 can not be reset\r
177\r
178--*/\r
179// GC_TODO: function comment is missing 'Arguments:'\r
180// GC_TODO: FdcDev - add argument and description to function comment\r
181{\r
182 UINT8 data;\r
183 UINT8 StatusRegister0;\r
184 UINT8 PresentCylinderNumber;\r
185 UINTN Index;\r
186\r
187 //\r
188 // Report reset progress code\r
189 //\r
190 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
191 EFI_PROGRESS_CODE,\r
192 EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET,\r
193 FdcDev->DevicePath\r
194 );\r
195\r
196 //\r
197 // Reset specified Floppy Logic Drive according to FdcDev -> Disk\r
198 // Set Digital Output Register(DOR) to do reset work\r
199 // bit0 & bit1 of DOR : Drive Select\r
200 // bit2 : Reset bit\r
201 // bit3 : DMA and Int bit\r
202 // Reset : a "0" written to bit2 resets the FDC, this reset will remain\r
203 // active until\r
204 // a "1" is written to this bit.\r
205 // Reset step 1:\r
206 // use bit0 & bit1 to select the logic drive\r
207 // write "0" to bit2\r
208 //\r
209 data = 0x0;\r
210 data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));\r
211 FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);\r
212\r
213 //\r
214 // wait some time,at least 120us\r
215 //\r
216 MicroSecondDelay (500);\r
217\r
218 //\r
219 // Reset step 2:\r
220 // write "1" to bit2\r
221 // write "1" to bit3 : enable DMA\r
222 //\r
223 data |= 0x0C;\r
224 FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);\r
225\r
226 //\r
227 // Experience value\r
228 //\r
229 MicroSecondDelay (2000);\r
230\r
231 //\r
232 // wait specified floppy logic drive is not busy\r
233 //\r
234 if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {\r
235 return EFI_DEVICE_ERROR;\r
236 }\r
237 //\r
238 // Set the Transfer Data Rate\r
239 //\r
240 FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);\r
241\r
242 //\r
243 // Experience value\r
244 //\r
245 MicroSecondDelay (100);\r
246\r
247 //\r
248 // Issue Sense interrupt command for each drive (total 4 drives)\r
249 //\r
250 for (Index = 0; Index < 4; Index++) {\r
251 if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {\r
252 return EFI_DEVICE_ERROR;\r
253 }\r
254 }\r
255 //\r
256 // issue Specify command\r
257 //\r
258 if (EFI_ERROR (Specify (FdcDev))) {\r
259 return EFI_DEVICE_ERROR;\r
260 }\r
261\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265EFI_STATUS\r
266MotorOn (\r
267 IN FDC_BLK_IO_DEV *FdcDev\r
268 )\r
269/*++\r
270\r
271 Routine Description: Turn the drive's motor on\r
272 The drive's motor must be on before any command can be executed \r
273 Parameters:\r
274 FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV \r
275 Returns:\r
276 EFI_SUCCESS: Turn the drive's motor on successfully\r
277 EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on \r
278 EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer) \r
279\r
280--*/\r
281// GC_TODO: function comment is missing 'Arguments:'\r
282// GC_TODO: FdcDev - add argument and description to function comment\r
283{\r
284 EFI_STATUS Status;\r
285 UINT8 data;\r
286\r
287 //\r
288 // Control of the floppy drive motors is a big pain. If motor is off, you have\r
289 // to turn it on first. But you can not leave the motor on all the time, since\r
290 // that would wear out the disk. On the other hand, if you turn the motor off\r
291 // after each operation, the system performance will be awful. The compromise\r
292 // used in this driver is to leave the motor on for 2 seconds after\r
293 // each operation. If a new operation is started in that interval(2s),\r
294 // the motor need not be turned on again. If no new operation is started,\r
295 // a timer goes off and the motor is turned off\r
296 //\r
297 //\r
298 // Cancel the timer\r
299 //\r
300 Status = gBS->SetTimer (FdcDev->Event, TimerCancel, 0);\r
301\r
302 if (EFI_ERROR (Status)) {\r
303 return EFI_INVALID_PARAMETER;\r
304 }\r
305 //\r
306 // Get the motor status\r
307 //\r
308 data = FdcReadPort (FdcDev, FDC_REGISTER_DOR);\r
309\r
310 if (((FdcDev->Disk == FDC_DISK0) && ((data & 0x10) == 0x10)) ||\r
311 ((FdcDev->Disk == FDC_DISK1) && ((data & 0x21) == 0x21))\r
312 ) {\r
313 return EFI_SUCCESS;\r
314 }\r
315 //\r
316 // The drive's motor is off, so need turn it on\r
317 // first look at command and drive are busy or not\r
318 //\r
319 if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {\r
320 return EFI_DEVICE_ERROR;\r
321 }\r
322 //\r
323 // for drive A: 1CH, drive B: 2DH\r
324 //\r
325 data = 0x0C;\r
326 data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));\r
327 if (FdcDev->Disk == FDC_DISK0) {\r
328 //\r
329 // drive A\r
330 //\r
331 data |= DRVA_MOTOR_ON;\r
332 } else {\r
333 //\r
334 // drive B\r
335 //\r
336 data |= DRVB_MOTOR_ON;\r
337 }\r
338\r
339 FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);\r
340\r
341 //\r
342 // Experience value\r
343 //\r
344 MicroSecondDelay (4000);\r
345\r
346 return EFI_SUCCESS;\r
347}\r
348\r
349EFI_STATUS\r
350MotorOff (\r
351 IN FDC_BLK_IO_DEV *FdcDev\r
352 )\r
353/*++\r
354\r
355 Routine Description: Set a Timer and when Timer goes off, turn the motor off\r
356 Parameters:\r
357 FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV \r
358 Returns:\r
359 EFI_SUCCESS: Set the Timer successfully\r
360 EFI_INVALID_PARAMETER: Fail to Set the timer \r
361\r
362--*/\r
363// GC_TODO: function comment is missing 'Arguments:'\r
364// GC_TODO: FdcDev - add argument and description to function comment\r
365{\r
366 //\r
367 // Set the timer : 2s\r
368 //\r
369 return gBS->SetTimer (FdcDev->Event, TimerRelative, 20000000);\r
370}\r
371\r
372EFI_STATUS\r
373DisketChanged (\r
374 IN FDC_BLK_IO_DEV *FdcDev\r
375 )\r
376/*++\r
377\r
378 Routine Description: Detect the disk in the drive is changed or not\r
379 Parameters:\r
380 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV \r
381 Returns:\r
382 EFI_SUCCESS: No disk media change\r
383 EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation\r
384 EFI_NO_MEDIA: No disk in the drive\r
385 EFI_MEDIA_CHANGED: There is a new disk in the drive\r
386\r
387--*/\r
388// GC_TODO: function comment is missing 'Arguments:'\r
389// GC_TODO: FdcDev - add argument and description to function comment\r
390{\r
391 EFI_STATUS Status;\r
392 UINT8 data;\r
393\r
394 //\r
395 // Check change line\r
396 //\r
397 data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);\r
398\r
399 //\r
400 // Io delay\r
401 //\r
402 MicroSecondDelay (50);\r
403\r
404 if ((data & DIR_DCL) == 0x80) {\r
405 //\r
406 // disk change line is active\r
407 //\r
408 if (FdcDev->PresentCylinderNumber != 0) {\r
409 Status = Recalibrate (FdcDev);\r
410 } else {\r
411 Status = Seek (FdcDev, 0x30);\r
412 }\r
413\r
414 if (EFI_ERROR (Status)) {\r
415 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
416 return EFI_DEVICE_ERROR;\r
417 //\r
418 // Fail to do the seek or recalibrate operation\r
419 //\r
420 }\r
421\r
422 data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);\r
423\r
424 //\r
425 // Io delay\r
426 //\r
427 MicroSecondDelay (50);\r
428\r
429 if ((data & DIR_DCL) == 0x80) {\r
430 return EFI_NO_MEDIA;\r
431 }\r
432\r
433 return EFI_MEDIA_CHANGED;\r
434 }\r
435\r
436 return EFI_SUCCESS;\r
437}\r
438\r
439EFI_STATUS\r
440Specify (\r
441 IN FDC_BLK_IO_DEV *FdcDev\r
442 )\r
443/*++\r
444\r
445 Routine Description: Do the Specify command, this command sets DMA operation\r
446 and the initial values for each of the three internal \r
447 times: HUT, SRT and HLT\r
448 Parameters:\r
449 None\r
450 Returns:\r
451 EFI_SUCCESS: Execute the Specify command successfully\r
452 EFI_DEVICE_ERROR: Fail to execute the command\r
453\r
454--*/\r
455// GC_TODO: function comment is missing 'Arguments:'\r
456// GC_TODO: FdcDev - add argument and description to function comment\r
457{\r
458 FDD_SPECIFY_CMD Command;\r
459 UINTN Index;\r
460 UINT8 *CommandPointer;\r
461\r
462 ZeroMem (&Command, sizeof (FDD_SPECIFY_CMD));\r
463 Command.CommandCode = SPECIFY_CMD;\r
464 //\r
465 // set SRT, HUT\r
466 //\r
467 Command.SrtHut = 0xdf;\r
468 //\r
469 // 0xdf;\r
470 //\r
471 // set HLT and DMA\r
472 //\r
473 Command.HltNd = 0x02;\r
474\r
475 CommandPointer = (UINT8 *) (&Command);\r
476 for (Index = 0; Index < sizeof (FDD_SPECIFY_CMD); Index++) {\r
477 if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {\r
478 return EFI_DEVICE_ERROR;\r
479 }\r
480 }\r
481\r
482 return EFI_SUCCESS;\r
483}\r
484\r
485EFI_STATUS\r
486Recalibrate (\r
487 IN FDC_BLK_IO_DEV *FdcDev\r
488 )\r
489/*++\r
490\r
491 Routine Description: Set the head of floppy drive to track 0\r
492 Parameters:\r
493 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV\r
494 Returns:\r
495 EFI_SUCCESS: Execute the Recalibrate operation successfully\r
496 EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation\r
497\r
498--*/\r
499// GC_TODO: function comment is missing 'Arguments:'\r
500// GC_TODO: FdcDev - add argument and description to function comment\r
501{\r
502 FDD_COMMAND_PACKET2 Command;\r
503 UINTN Index;\r
504 UINT8 StatusRegister0;\r
505 UINT8 PresentCylinderNumber;\r
506 UINT8 *CommandPointer;\r
507 UINT8 Count;\r
508\r
509 Count = 2;\r
510\r
511 while (Count > 0) {\r
512 ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));\r
513 Command.CommandCode = RECALIBRATE_CMD;\r
514 //\r
515 // drive select\r
516 //\r
517 if (FdcDev->Disk == FDC_DISK0) {\r
518 Command.DiskHeadSel = 0;\r
519 //\r
520 // 0\r
521 //\r
522 } else {\r
523 Command.DiskHeadSel = 1;\r
524 //\r
525 // 1\r
526 //\r
527 }\r
528\r
529 CommandPointer = (UINT8 *) (&Command);\r
530 for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {\r
531 if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {\r
532 return EFI_DEVICE_ERROR;\r
533 }\r
534 }\r
535 //\r
536 // Experience value\r
537 //\r
538 MicroSecondDelay (250000);\r
539 //\r
540 // need modify according to 1.44M or 2.88M\r
541 //\r
542 if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {\r
543 return EFI_DEVICE_ERROR;\r
544 }\r
545\r
546 if ((StatusRegister0 & 0xf0) == 0x20 && PresentCylinderNumber == 0) {\r
547 FdcDev->PresentCylinderNumber = 0;\r
548 FdcDev->ControllerState->NeedRecalibrate = FALSE;\r
549 return EFI_SUCCESS;\r
550 } else {\r
551 Count--;\r
552 if (Count == 0) {\r
553 return EFI_DEVICE_ERROR;\r
554 }\r
555 }\r
556 }\r
557 //\r
558 // end while\r
559 //\r
560 return EFI_SUCCESS;\r
561}\r
562\r
563EFI_STATUS\r
564Seek (\r
565 IN FDC_BLK_IO_DEV *FdcDev,\r
566 IN EFI_LBA Lba\r
567 )\r
568/*++\r
569\r
570 Routine Description: Set the head of floppy drive to the new cylinder\r
571 Parameters:\r
572 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV\r
573 Lba EFI_LBA : The logic block address want to seek\r
574 Returns:\r
575 EFI_SUCCESS: Execute the Seek operation successfully\r
576 EFI_DEVICE_ERROR: Fail to execute the Seek operation\r
577\r
578--*/\r
579// GC_TODO: function comment is missing 'Arguments:'\r
580// GC_TODO: FdcDev - add argument and description to function comment\r
581// GC_TODO: Lba - add argument and description to function comment\r
582{\r
583 FDD_SEEK_CMD Command;\r
584 UINT8 EndOfTrack;\r
585 UINT8 Head;\r
586 UINT8 Cylinder;\r
587 UINT8 StatusRegister0;\r
588 UINT8 *CommandPointer;\r
589 UINT8 PresentCylinderNumber;\r
590 UINTN Index;\r
591 UINT8 DelayTime;\r
592\r
593 if (FdcDev->ControllerState->NeedRecalibrate) {\r
594 if (EFI_ERROR (Recalibrate (FdcDev))) {\r
595 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
596 return EFI_DEVICE_ERROR;\r
597 }\r
598 }\r
599\r
600 EndOfTrack = DISK_1440K_EOT;\r
601 //\r
602 // Calculate cylinder based on Lba and EOT\r
603 //\r
604 Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
605\r
606 //\r
607 // if the destination cylinder is the present cylinder, unnecessary to do the\r
608 // seek operation\r
609 //\r
610 if (FdcDev->PresentCylinderNumber == Cylinder) {\r
611 return EFI_SUCCESS;\r
612 }\r
613 //\r
614 // Calculate the head : 0 or 1\r
615 //\r
616 Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
617\r
618 ZeroMem (&Command, sizeof (FDD_SEEK_CMD));\r
619 Command.CommandCode = SEEK_CMD;\r
620 if (FdcDev->Disk == FDC_DISK0) {\r
621 Command.DiskHeadSel = 0;\r
622 //\r
623 // 0\r
624 //\r
625 } else {\r
626 Command.DiskHeadSel = 1;\r
627 //\r
628 // 1\r
629 //\r
630 }\r
631\r
632 Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));\r
633 Command.NewCylinder = Cylinder;\r
634\r
635 CommandPointer = (UINT8 *) (&Command);\r
636 for (Index = 0; Index < sizeof (FDD_SEEK_CMD); Index++) {\r
637 if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {\r
638 return EFI_DEVICE_ERROR;\r
639 }\r
640 }\r
641 //\r
642 // Io delay\r
643 //\r
644 MicroSecondDelay (100);\r
645\r
646 //\r
647 // Calculate waiting time\r
648 //\r
649 if (FdcDev->PresentCylinderNumber > Cylinder) {\r
650 DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder);\r
651 } else {\r
652 DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber);\r
653 }\r
654\r
655 MicroSecondDelay ((DelayTime + 1) * 4000);\r
656\r
657 if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {\r
658 return EFI_DEVICE_ERROR;\r
659 }\r
660\r
661 if ((StatusRegister0 & 0xf0) == 0x20) {\r
662 FdcDev->PresentCylinderNumber = Command.NewCylinder;\r
663 return EFI_SUCCESS;\r
664 } else {\r
665 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
666 return EFI_DEVICE_ERROR;\r
667 }\r
668}\r
669\r
670EFI_STATUS\r
671SenseIntStatus (\r
672 IN FDC_BLK_IO_DEV *FdcDev,\r
673 IN OUT UINT8 *StatusRegister0,\r
674 IN OUT UINT8 *PresentCylinderNumber\r
675 )\r
676/*++\r
677\r
678 Routine Description: Do the Sense Interrupt Status command, this command \r
679 resets the interrupt signal\r
680 Parameters:\r
681 StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC \r
682 PresentCylinderNumber UINT8 *: Be used to save present cylinder number \r
683 read from FDC\r
684 Returns:\r
685 EFI_SUCCESS: Execute the Sense Interrupt Status command successfully\r
686 EFI_DEVICE_ERROR: Fail to execute the command\r
687\r
688--*/\r
689// GC_TODO: function comment is missing 'Arguments:'\r
690// GC_TODO: FdcDev - add argument and description to function comment\r
691// GC_TODO: StatusRegister0 - add argument and description to function comment\r
692// GC_TODO: PresentCylinderNumber - add argument and description to function comment\r
693{\r
694 UINT8 command;\r
695\r
696 command = SENSE_INT_STATUS_CMD;\r
697 if (EFI_ERROR (DataOutByte (FdcDev, &command))) {\r
698 return EFI_DEVICE_ERROR;\r
699 }\r
700\r
701 if (EFI_ERROR (DataInByte (FdcDev, StatusRegister0))) {\r
702 return EFI_DEVICE_ERROR;\r
703 }\r
704\r
705 if (EFI_ERROR (DataInByte (FdcDev, PresentCylinderNumber))) {\r
706 return EFI_DEVICE_ERROR;\r
707 }\r
708\r
709 return EFI_SUCCESS;\r
710}\r
711\r
712EFI_STATUS\r
713SenseDrvStatus (\r
714 IN FDC_BLK_IO_DEV *FdcDev,\r
715 IN EFI_LBA Lba\r
716 )\r
717/*++\r
718\r
719 Routine Description: Do the Sense Drive Status command\r
720 Parameters:\r
721 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV \r
722 Lba EFI_LBA : Logic block address\r
723 Returns:\r
724 EFI_SUCCESS: Execute the Sense Drive Status command successfully\r
725 EFI_DEVICE_ERROR: Fail to execute the command\r
726 EFI_WRITE_PROTECTED:The disk is write protected \r
727\r
728--*/\r
729// GC_TODO: function comment is missing 'Arguments:'\r
730// GC_TODO: FdcDev - add argument and description to function comment\r
731// GC_TODO: Lba - add argument and description to function comment\r
732{\r
733 FDD_COMMAND_PACKET2 Command;\r
734 UINT8 Head;\r
735 UINT8 EndOfTrack;\r
736 UINTN Index;\r
737 UINT8 StatusRegister3;\r
738 UINT8 *CommandPointer;\r
739\r
740 //\r
741 // Sense Drive Status command obtains drive status information,\r
742 // it has not execution phase and goes directly to the result phase from the\r
743 // command phase, Status Register 3 contains the drive status information\r
744 //\r
745 ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));\r
746 Command.CommandCode = SENSE_DRV_STATUS_CMD;\r
747\r
748 if (FdcDev->Disk == FDC_DISK0) {\r
749 Command.DiskHeadSel = 0;\r
750 } else {\r
751 Command.DiskHeadSel = 1;\r
752 }\r
753\r
754 EndOfTrack = DISK_1440K_EOT;\r
755 Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
756 Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));\r
757\r
758 CommandPointer = (UINT8 *) (&Command);\r
759 for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {\r
760 if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {\r
761 return EFI_DEVICE_ERROR;\r
762 }\r
763 }\r
764\r
765 if (EFI_ERROR (DataInByte (FdcDev, &StatusRegister3))) {\r
766 return EFI_DEVICE_ERROR;\r
767 }\r
768 //\r
769 // Io delay\r
770 //\r
771 MicroSecondDelay (50);\r
772\r
773 //\r
774 // Check Status Register 3 to get drive status information\r
775 //\r
776 return CheckStatus3 (StatusRegister3);\r
777}\r
778\r
779EFI_STATUS\r
780DetectMedia (\r
781 IN FDC_BLK_IO_DEV *FdcDev\r
782 )\r
783/*++\r
784\r
785 Routine Description: Update the disk media properties and if necessary \r
786 reinstall Block I/O interface\r
787 Parameters:\r
788 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV \r
789 Returns:\r
790 EFI_SUCCESS: Do the operation successfully\r
791 EFI_DEVICE_ERROR: Fail to the operation\r
792\r
793--*/\r
794// GC_TODO: function comment is missing 'Arguments:'\r
795// GC_TODO: FdcDev - add argument and description to function comment\r
796{\r
797 EFI_STATUS Status;\r
798 BOOLEAN bReset;\r
799 BOOLEAN bReadOnlyLastTime;\r
800 BOOLEAN bMediaPresentLastTime;\r
801\r
802 bReset = FALSE;\r
803 bReadOnlyLastTime = FdcDev->BlkIo.Media->ReadOnly;\r
804 bMediaPresentLastTime = FdcDev->BlkIo.Media->MediaPresent;\r
805\r
806 //\r
807 // Check disk change\r
808 //\r
809 Status = DisketChanged (FdcDev);\r
810 switch (Status) {\r
811 case EFI_MEDIA_CHANGED:\r
812 FdcDev->BlkIo.Media->MediaId++;\r
813 FdcDev->BlkIo.Media->MediaPresent = TRUE;\r
814 bReset = TRUE;\r
815 break;\r
816\r
817 case EFI_NO_MEDIA:\r
818 FdcDev->BlkIo.Media->MediaPresent = FALSE;\r
819 break;\r
820\r
821 case EFI_SUCCESS:\r
822 break;\r
823\r
824 default:\r
825 MotorOff (FdcDev);\r
826 return Status;\r
827 //\r
828 // EFI_DEVICE_ERROR\r
829 //\r
830 }\r
831\r
832 if (FdcDev->BlkIo.Media->MediaPresent) {\r
833 //\r
834 // Check disk write protected\r
835 //\r
836 Status = SenseDrvStatus (FdcDev, 0);\r
837 if (Status == EFI_WRITE_PROTECTED) {\r
838 FdcDev->BlkIo.Media->ReadOnly = TRUE;\r
839 } else {\r
840 FdcDev->BlkIo.Media->ReadOnly = FALSE;\r
841 }\r
842 }\r
843\r
844 if (FdcDev->BlkIo.Media->MediaPresent && (bReadOnlyLastTime != FdcDev->BlkIo.Media->ReadOnly)) {\r
845 bReset = TRUE;\r
846 }\r
847\r
848 if (bMediaPresentLastTime != FdcDev->BlkIo.Media->MediaPresent) {\r
849 bReset = TRUE;\r
850 }\r
851\r
852 if (bReset) {\r
853 Status = gBS->ReinstallProtocolInterface (\r
854 FdcDev->Handle,\r
855 &gEfiBlockIoProtocolGuid,\r
856 &FdcDev->BlkIo,\r
857 &FdcDev->BlkIo\r
858 );\r
859\r
860 if (EFI_ERROR (Status)) {\r
861 return Status;\r
862 }\r
863 }\r
864\r
865 return EFI_SUCCESS;\r
866}\r
867\r
868EFI_STATUS\r
869Setup (\r
870 IN FDC_BLK_IO_DEV *FdcDev\r
871 )\r
872/*++\r
873\r
874 Routine Description: Set the data rate and so on\r
875 Parameters:\r
876 None \r
877 Returns:\r
878 EFI_SUCCESS: \r
879\r
880--*/\r
881// GC_TODO: function comment is missing 'Arguments:'\r
882// GC_TODO: FdcDev - add argument and description to function comment\r
883// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
884{\r
885 EFI_STATUS Status;\r
886\r
887 //\r
888 // Set data rate 500kbs\r
889 //\r
890 FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);\r
891\r
892 //\r
893 // Io delay\r
894 //\r
895 MicroSecondDelay (50);\r
896\r
897 Status = Specify (FdcDev);\r
898\r
899 if (EFI_ERROR (Status)) {\r
900 return EFI_DEVICE_ERROR;\r
901 }\r
902\r
903 return EFI_SUCCESS;\r
904}\r
905\r
906EFI_STATUS\r
907ReadWriteDataSector (\r
908 IN FDC_BLK_IO_DEV *FdcDev,\r
909 IN VOID *HostAddress,\r
910 IN EFI_LBA Lba,\r
911 IN UINTN NumberOfBlocks,\r
912 IN BOOLEAN Read\r
913 )\r
914/*++\r
915\r
916 Routine Description: Read or Write a number of blocks in the same cylinder\r
917 Parameters:\r
918 FdcDev FDC_BLK_IO_DEV * : A pointer to Data Structure FDC_BLK_IO_DEV\r
919 Buffer VOID *:\r
920 Lba EFI_LBA:\r
921 NumberOfBlocks UINTN:\r
922 Read BOOLEAN: \r
923 Returns:\r
924 EFI_SUCCESS: \r
925\r
926--*/\r
927// GC_TODO: function comment is missing 'Arguments:'\r
928// GC_TODO: FdcDev - add argument and description to function comment\r
929// GC_TODO: HostAddress - add argument and description to function comment\r
930// GC_TODO: Lba - add argument and description to function comment\r
931// GC_TODO: NumberOfBlocks - add argument and description to function comment\r
932// GC_TODO: Read - add argument and description to function comment\r
933// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
934// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
935// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
936// GC_TODO: EFI_TIMEOUT - add return value to function comment\r
937// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
938{\r
939 EFI_STATUS Status;\r
940 FDD_COMMAND_PACKET1 Command;\r
941 FDD_RESULT_PACKET Result;\r
942 UINTN Index;\r
943 UINTN Times;\r
944 UINT8 *CommandPointer;\r
945\r
946 EFI_PHYSICAL_ADDRESS DeviceAddress;\r
947 EFI_ISA_IO_PROTOCOL *IsaIo;\r
948 UINTN NumberofBytes;\r
949 VOID *Mapping;\r
950 EFI_ISA_IO_PROTOCOL_OPERATION Operation;\r
951 EFI_STATUS Status1;\r
952 UINT8 Channel;\r
953 EFI_ISA_ACPI_RESOURCE *ResourceItem;\r
954 UINT32 Attribute;\r
955\r
956 Status = Seek (FdcDev, Lba);\r
957 if (EFI_ERROR (Status)) {\r
958 return EFI_DEVICE_ERROR;\r
959 }\r
960 //\r
961 // Map Dma\r
962 //\r
963 IsaIo = FdcDev->IsaIo;\r
964 NumberofBytes = NumberOfBlocks * 512;\r
965 if (Read == READ) {\r
966 Operation = EfiIsaIoOperationSlaveWrite;\r
967 } else {\r
968 Operation = EfiIsaIoOperationSlaveRead;\r
969 }\r
970\r
971 ResourceItem = IsaIo->ResourceList->ResourceItem;\r
972 Index = 0;\r
973 while (ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList) {\r
974 if (ResourceItem[Index].Type == EfiIsaAcpiResourceDma) {\r
975 break;\r
976 }\r
977\r
978 Index++;\r
979 }\r
980\r
981 if (ResourceItem[Index].Type == EfiIsaAcpiResourceEndOfList) {\r
982 return EFI_DEVICE_ERROR;\r
983 }\r
984\r
985 Channel = (UINT8) IsaIo->ResourceList->ResourceItem[Index].StartRange;\r
986 Attribute = IsaIo->ResourceList->ResourceItem[Index].Attribute;\r
987\r
988 Status1 = IsaIo->Map (\r
989 IsaIo,\r
990 Operation,\r
991 Channel,\r
992 Attribute,\r
993 HostAddress,\r
994 &NumberofBytes,\r
995 &DeviceAddress,\r
996 &Mapping\r
997 );\r
998 if (EFI_ERROR (Status1)) {\r
999 return Status1;\r
1000 }\r
1001\r
1002 //\r
1003 // Allocate Read or Write command packet\r
1004 //\r
1005 ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET1));\r
1006 if (Read == READ) {\r
1007 Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;\r
1008 } else {\r
1009 Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;\r
1010 }\r
1011\r
1012 FillPara (FdcDev, Lba, &Command);\r
1013\r
1014 //\r
1015 // Write command bytes to FDC\r
1016 //\r
1017 CommandPointer = (UINT8 *) (&Command);\r
1018 for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET1); Index++) {\r
1019 if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {\r
1020 return EFI_DEVICE_ERROR;\r
1021 }\r
1022 }\r
1023 //\r
1024 // wait for some time\r
1025 //\r
1026 Times = (STALL_1_SECOND / 50) + 1;\r
1027 do {\r
1028 if ((FdcReadPort (FdcDev, FDC_REGISTER_MSR) & 0xc0) == 0xc0) {\r
1029 break;\r
1030 }\r
1031\r
1032 MicroSecondDelay (50);\r
1033 Times = Times - 1;\r
1034 } while (Times);\r
1035\r
1036 if (Times == 0) {\r
1037 return EFI_TIMEOUT;\r
1038 }\r
1039 //\r
1040 // Read result bytes from FDC\r
1041 //\r
1042 CommandPointer = (UINT8 *) (&Result);\r
1043 for (Index = 0; Index < sizeof (FDD_RESULT_PACKET); Index++) {\r
1044 if (EFI_ERROR (DataInByte (FdcDev, CommandPointer++))) {\r
1045 return EFI_DEVICE_ERROR;\r
1046 }\r
1047 }\r
1048 //\r
1049 // Flush before Unmap\r
1050 //\r
1051 if (Read == READ) {\r
1052 Status1 = IsaIo->Flush (IsaIo);\r
1053 if (EFI_ERROR (Status1)) {\r
1054 return Status1;\r
1055 }\r
1056 }\r
1057 //\r
1058 // Unmap Dma\r
1059 //\r
1060 Status1 = IsaIo->Unmap (IsaIo, Mapping);\r
1061 if (EFI_ERROR (Status1)) {\r
1062 return Status1;\r
1063 }\r
1064\r
1065 return CheckResult (&Result, FdcDev);\r
1066}\r
1067\r
1068VOID\r
1069FillPara (\r
1070 IN FDC_BLK_IO_DEV *FdcDev,\r
1071 IN EFI_LBA Lba,\r
1072 IN FDD_COMMAND_PACKET1 *Command\r
1073 )\r
1074/*++\r
1075\r
1076 Routine Description: Fill in Parameter\r
1077 Parameters:\r
1078 Returns:\r
1079 \r
1080--*/\r
1081// GC_TODO: function comment is missing 'Arguments:'\r
1082// GC_TODO: FdcDev - add argument and description to function comment\r
1083// GC_TODO: Lba - add argument and description to function comment\r
1084// GC_TODO: Command - add argument and description to function comment\r
1085{\r
1086 UINT8 EndOfTrack;\r
1087\r
1088 //\r
1089 // Get EndOfTrack from the Para table\r
1090 //\r
1091 EndOfTrack = DISK_1440K_EOT;\r
1092\r
1093 //\r
1094 // Fill the command parameter\r
1095 //\r
1096 if (FdcDev->Disk == FDC_DISK0) {\r
1097 Command->DiskHeadSel = 0;\r
1098 } else {\r
1099 Command->DiskHeadSel = 1;\r
1100 }\r
1101\r
1102 Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
1103 Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
1104 Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);\r
1105 Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2));\r
1106 Command->Number = DISK_1440K_NUMBER;\r
1107 Command->EndOfTrack = DISK_1440K_EOT;\r
1108 Command->GapLength = DISK_1440K_GPL;\r
1109 Command->DataLength = DISK_1440K_DTL;\r
1110}\r
1111\r
1112EFI_STATUS\r
1113DataInByte (\r
1114 IN FDC_BLK_IO_DEV *FdcDev,\r
1115 IN OUT UINT8 *Pointer\r
1116 )\r
1117/*++\r
1118\r
1119 Routine Description: Read result byte from Data Register of FDC\r
1120 Parameters:\r
1121 Pointer UINT8 *: Be used to save result byte read from FDC \r
1122 Returns:\r
1123 EFI_SUCCESS: Read result byte from FDC successfully\r
1124 EFI_DEVICE_ERROR: The FDC is not ready to be read\r
1125\r
1126--*/\r
1127// GC_TODO: function comment is missing 'Arguments:'\r
1128// GC_TODO: FdcDev - add argument and description to function comment\r
1129// GC_TODO: Pointer - add argument and description to function comment\r
1130{\r
1131 UINT8 data;\r
1132\r
1133 //\r
1134 // wait for 1ms and detect the FDC is ready to be read\r
1135 //\r
1136 if (EFI_ERROR (FddDRQReady (FdcDev, DATA_IN, 1))) {\r
1137 return EFI_DEVICE_ERROR;\r
1138 //\r
1139 // is not ready\r
1140 //\r
1141 }\r
1142\r
1143 data = FdcReadPort (FdcDev, FDC_REGISTER_DTR);\r
1144\r
1145 //\r
1146 // Io delay\r
1147 //\r
1148 MicroSecondDelay (50);\r
1149\r
1150 *Pointer = data;\r
1151 return EFI_SUCCESS;\r
1152}\r
1153\r
1154EFI_STATUS\r
1155DataOutByte (\r
1156 IN FDC_BLK_IO_DEV *FdcDev,\r
1157 IN UINT8 *Pointer\r
1158 )\r
1159/*++\r
1160\r
1161 Routine Description: Write command byte to Data Register of FDC\r
1162 Parameters:\r
1163 Pointer UINT8 *: Be used to save command byte written to FDC \r
1164 Returns:\r
1165 EFI_SUCCESS: Write command byte to FDC successfully\r
1166 EFI_DEVICE_ERROR: The FDC is not ready to be written\r
1167\r
1168--*/\r
1169// GC_TODO: function comment is missing 'Arguments:'\r
1170// GC_TODO: FdcDev - add argument and description to function comment\r
1171// GC_TODO: Pointer - add argument and description to function comment\r
1172{\r
1173 UINT8 data;\r
1174\r
1175 //\r
1176 // wait for 1ms and detect the FDC is ready to be written\r
1177 //\r
1178 if (EFI_ERROR (FddDRQReady (FdcDev, DATA_OUT, 1))) {\r
1179 return EFI_DEVICE_ERROR;\r
1180 //\r
1181 // is not ready\r
1182 //\r
1183 }\r
1184\r
1185 data = *Pointer;\r
1186\r
1187 FdcWritePort (FdcDev, FDC_REGISTER_DTR, data);\r
1188\r
1189 //\r
1190 // Io delay\r
1191 //\r
1192 MicroSecondDelay (50);\r
1193\r
1194 return EFI_SUCCESS;\r
1195}\r
1196\r
1197EFI_STATUS\r
1198FddWaitForBSYClear (\r
1199 IN FDC_BLK_IO_DEV *FdcDev,\r
1200 IN UINTN TimeoutInSeconds\r
1201 )\r
1202/*++\r
1203\r
1204 Routine Description: Detect the specified floppy logic drive is busy or \r
1205 not within a period of time\r
1206 Parameters:\r
1207 Disk EFI_FDC_DISK: Indicate it is drive A or drive B\r
1208 TimeoutInSeconds UINTN: the time period for waiting \r
1209 Returns:\r
1210 EFI_SUCCESS: The drive and command are not busy\r
1211 EFI_TIMEOUT: The drive or command is still busy after a period time that \r
1212 set by TimeoutInSeconds\r
1213\r
1214--*/\r
1215// GC_TODO: function comment is missing 'Arguments:'\r
1216// GC_TODO: FdcDev - add argument and description to function comment\r
1217// GC_TODO: TimeoutInSeconds - add argument and description to function comment\r
1218{\r
1219 UINTN Delay;\r
1220 UINT8 StatusRegister;\r
1221 UINT8 Mask;\r
1222\r
1223 //\r
1224 // How to determine drive and command are busy or not: by the bits of\r
1225 // Main Status Register\r
1226 // bit0: Drive 0 busy (drive A)\r
1227 // bit1: Drive 1 busy (drive B)\r
1228 // bit4: Command busy\r
1229 //\r
1230 //\r
1231 // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4\r
1232 //\r
1233 Mask = (UINT8) ((FdcDev->Disk == FDC_DISK0 ? MSR_DAB : MSR_DBB) | MSR_CB);\r
1234\r
1235 Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
1236 do {\r
1237 StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);\r
1238 if ((StatusRegister & Mask) == 0x00) {\r
1239 break;\r
1240 //\r
1241 // not busy\r
1242 //\r
1243 }\r
1244\r
1245 MicroSecondDelay (50);\r
1246 Delay = Delay - 1;\r
1247 } while (Delay);\r
1248\r
1249 if (Delay == 0) {\r
1250 return EFI_TIMEOUT;\r
1251 }\r
1252\r
1253 return EFI_SUCCESS;\r
1254}\r
1255\r
1256EFI_STATUS\r
1257FddDRQReady (\r
1258 IN FDC_BLK_IO_DEV *FdcDev,\r
1259 IN BOOLEAN Dio,\r
1260 IN UINTN TimeoutInSeconds\r
1261 )\r
1262/*++\r
1263\r
1264 Routine Description: Determine whether FDC is ready to write or read\r
1265 Parameters:\r
1266 Dio BOOLEAN: Indicate the FDC is waiting to write or read\r
1267 TimeoutInSeconds UINTN: The time period for waiting \r
1268 Returns:\r
1269 EFI_SUCCESS: FDC is ready to write or read\r
1270 EFI_NOT_READY: FDC is not ready within the specified time period\r
1271\r
1272--*/\r
1273// GC_TODO: function comment is missing 'Arguments:'\r
1274// GC_TODO: FdcDev - add argument and description to function comment\r
1275// GC_TODO: Dio - add argument and description to function comment\r
1276// GC_TODO: TimeoutInSeconds - add argument and description to function comment\r
1277{\r
1278 UINTN Delay;\r
1279 UINT8 StatusRegister;\r
1280 UINT8 DataInOut;\r
1281\r
1282 //\r
1283 // Before writing to FDC or reading from FDC, the Host must examine\r
1284 // the bit7(RQM) and bit6(DIO) of the Main Status Register.\r
1285 // That is to say:\r
1286 // command bytes can not be written to Data Register\r
1287 // unless RQM is 1 and DIO is 0\r
1288 // result bytes can not be read from Data Register\r
1289 // unless RQM is 1 and DIO is 1\r
1290 //\r
1291 DataInOut = (UINT8) (Dio << 6);\r
1292 //\r
1293 // in order to compare bit6\r
1294 //\r
1295 Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
1296 do {\r
1297 StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);\r
1298 if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {\r
1299 break;\r
1300 //\r
1301 // FDC is ready\r
1302 //\r
1303 }\r
1304\r
1305 MicroSecondDelay (50);\r
1306 //\r
1307 // Stall for 50 us\r
1308 //\r
1309 Delay = Delay - 1;\r
1310 } while (Delay);\r
1311\r
1312 if (Delay == 0) {\r
1313 return EFI_NOT_READY;\r
1314 //\r
1315 // FDC is not ready within the specified time period\r
1316 //\r
1317 }\r
1318\r
1319 return EFI_SUCCESS;\r
1320}\r
1321\r
1322EFI_STATUS\r
1323CheckResult (\r
1324 IN FDD_RESULT_PACKET *Result,\r
1325 IN OUT FDC_BLK_IO_DEV *FdcDev\r
1326 )\r
1327/*++\r
1328\r
1329Routine Description:\r
1330\r
1331 GC_TODO: Add function description\r
1332\r
1333Arguments:\r
1334\r
1335 Result - GC_TODO: add argument description\r
1336 FdcDev - GC_TODO: add argument description\r
1337\r
1338Returns:\r
1339\r
1340 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1341 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1342 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
1343 EFI_SUCCESS - GC_TODO: Add description for return value\r
1344\r
1345--*/\r
1346{\r
1347 //\r
1348 // Check Status Register0\r
1349 //\r
1350 if ((Result->Status0 & STS0_IC) != IC_NT) {\r
1351 if ((Result->Status0 & STS0_SE) == 0x20) {\r
1352 //\r
1353 // seek error\r
1354 //\r
1355 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
1356 }\r
1357\r
1358 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
1359 return EFI_DEVICE_ERROR;\r
1360 }\r
1361 //\r
1362 // Check Status Register1\r
1363 //\r
1364 if (Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {\r
1365 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
1366 return EFI_DEVICE_ERROR;\r
1367 }\r
1368 //\r
1369 // Check Status Register2\r
1370 //\r
1371 if (Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {\r
1372 FdcDev->ControllerState->NeedRecalibrate = TRUE;\r
1373 return EFI_DEVICE_ERROR;\r
1374 }\r
1375\r
1376 return EFI_SUCCESS;\r
1377}\r
1378\r
1379EFI_STATUS\r
1380CheckStatus3 (\r
1381 IN UINT8 StatusRegister3\r
1382 )\r
1383/*++\r
1384\r
1385 Routine Description: Check the drive status information\r
1386 Parameters:\r
1387 StatusRegister3 UINT8: the value of Status Register 3 \r
1388 Returns:\r
1389 EFI_SUCCESS: \r
1390 EFI_WRITE_PROTECTED: The disk is write protected\r
1391\r
1392--*/\r
1393// GC_TODO: function comment is missing 'Arguments:'\r
1394// GC_TODO: StatusRegister3 - add argument and description to function comment\r
1395{\r
1396 if (StatusRegister3 & STS3_WP) {\r
1397 return EFI_WRITE_PROTECTED;\r
1398 }\r
1399\r
1400 return EFI_SUCCESS;\r
1401}\r
1402\r
1403UINTN\r
1404GetTransferBlockCount (\r
1405 IN FDC_BLK_IO_DEV *FdcDev,\r
1406 IN EFI_LBA LBA,\r
1407 IN UINTN NumberOfBlocks\r
1408 )\r
1409/*++\r
1410\r
1411 Routine Description: Calculate the number of block in the same cylinder \r
1412 according to LBA\r
1413 Parameters:\r
1414 FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV\r
1415 LBA EFI_LBA: The starting logic block address \r
1416 NumberOfBlocks UINTN: The number of blocks\r
1417 Returns:\r
1418 UINTN : The number of blocks in the same cylinder which the starting \r
1419 logic block address is LBA\r
1420\r
1421--*/\r
1422// GC_TODO: function comment is missing 'Arguments:'\r
1423// GC_TODO: FdcDev - add argument and description to function comment\r
1424// GC_TODO: LBA - add argument and description to function comment\r
1425// GC_TODO: NumberOfBlocks - add argument and description to function comment\r
1426{\r
1427 UINT8 EndOfTrack;\r
1428 UINT8 Head;\r
1429 UINT8 SectorsInTrack;\r
1430\r
1431 //\r
1432 // Calculate the number of block in the same cylinder\r
1433 //\r
1434 EndOfTrack = DISK_1440K_EOT;\r
1435 Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);\r
1436\r
1437 SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));\r
1438 if (SectorsInTrack < NumberOfBlocks) {\r
1439 return SectorsInTrack;\r
1440 } else {\r
1441 return NumberOfBlocks;\r
1442 }\r
1443}\r
1444\r
1445VOID\r
1446EFIAPI\r
1447FddTimerProc (\r
1448 IN EFI_EVENT Event,\r
1449 IN VOID *Context\r
1450 )\r
1451/*++\r
1452\r
1453 Routine Description: When the Timer(2s) off, turn the drive's motor off\r
1454 Parameters:\r
1455 Event EFI_EVENT: Event(the timer) whose notification function is being \r
1456 invoked\r
1457 Context VOID *: Pointer to the notification function's context \r
1458 Returns:\r
1459 VOID\r
1460\r
1461--*/\r
1462// GC_TODO: function comment is missing 'Arguments:'\r
1463// GC_TODO: Event - add argument and description to function comment\r
1464// GC_TODO: Context - add argument and description to function comment\r
1465{\r
1466 FDC_BLK_IO_DEV *FdcDev;\r
1467 UINT8 data;\r
1468\r
1469 FdcDev = (FDC_BLK_IO_DEV *) Context;\r
1470\r
1471 //\r
1472 // Get the motor status\r
1473 //\r
1474 data = FdcReadPort (FdcDev, FDC_REGISTER_DOR);\r
1475\r
1476 if (((FdcDev->Disk == FDC_DISK0) && ((data & 0x10) != 0x10)) ||\r
1477 ((FdcDev->Disk == FDC_DISK1) && ((data & 0x21) != 0x21))\r
1478 ) {\r
1479 return ;\r
1480 }\r
1481 //\r
1482 // the motor is on, so need motor off\r
1483 //\r
1484 data = 0x0C;\r
1485 data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));\r
1486 FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);\r
1487 MicroSecondDelay (500);\r
1488}\r
1489\r
1490UINT8\r
1491FdcReadPort (\r
1492 IN FDC_BLK_IO_DEV *FdcDev,\r
1493 IN UINT32 Offset\r
1494 )\r
1495/*++\r
1496\r
1497 Routine Description: Read I/O port for FDC \r
1498 Parameters:\r
1499 Returns:\r
1500 \r
1501--*/\r
1502// GC_TODO: function comment is missing 'Arguments:'\r
1503// GC_TODO: FdcDev - add argument and description to function comment\r
1504// GC_TODO: Offset - add argument and description to function comment\r
1505{\r
1506 UINT8 Data;\r
1507\r
1508 //\r
1509 // Call IsaIo\r
1510 //\r
1511 FdcDev->IsaIo->Io.Read (\r
1512 FdcDev->IsaIo,\r
1513 EfiIsaIoWidthUint8,\r
1514 FdcDev->BaseAddress + Offset,\r
1515 1,\r
1516 &Data\r
1517 );\r
1518\r
1519 return Data;\r
1520}\r
1521\r
1522VOID\r
1523FdcWritePort (\r
1524 IN FDC_BLK_IO_DEV *FdcDev,\r
1525 IN UINT32 Offset,\r
1526 IN UINT8 Data\r
1527 )\r
1528/*++\r
1529\r
1530 Routine Description: Write I/O port for FDC \r
1531 Parameters:\r
1532 Returns:\r
1533 \r
1534--*/\r
1535// GC_TODO: function comment is missing 'Arguments:'\r
1536// GC_TODO: FdcDev - add argument and description to function comment\r
1537// GC_TODO: Offset - add argument and description to function comment\r
1538// GC_TODO: Data - add argument and description to function comment\r
1539{\r
1540\r
1541 //\r
1542 // Call IsaIo\r
1543 //\r
1544 FdcDev->IsaIo->Io.Write (\r
1545 FdcDev->IsaIo,\r
1546 EfiIsaIoWidthUint8,\r
1547 FdcDev->BaseAddress + Offset,\r
1548 1,\r
1549 &Data\r
1550 );\r
1551}\r