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