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