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