3 Copyright (c) 2006, 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
24 #include "FloppyPeim.h"
25 #include "IndustryStandard/Pcat.h"
31 #define ISA_MAX_MEMORY_ADDRESS 0x1000000 // 16 MB Memory Range
32 UINT16 FdcBaseAddress
= 0x3f0;
34 static DISKET_PARA_TABLE DiskPara
[9] = {
136 static UINTN BytePerSector
[6] = { 0, 256, 512, 1024, 2048, 4096 };
144 IN EFI_FFS_FILE_HEADER
*FfsHeader
,
145 IN EFI_PEI_SERVICES
**PeiServices
151 Initializes the Fdc Block Io PPI
155 PeiServices - General purpose services available to every PEIM.
156 FfsHeader - Ffs header pointer
160 EFI_UNSUPPORTED - Can't find neccessary Ppi.
161 EFI_OUT_OF_RESOURCES - Have no enough memory to create instance or descriptors.
162 EFI_SUCCESS - Success.
168 FDC_BLK_IO_DEV
*FdcBlkIoDev
;
169 EFI_PHYSICAL_ADDRESS TempPtr
;
172 // Initializing PEI floppy driver.
174 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, EFI_PERIPHERAL_REMOVABLE_MEDIA
+ EFI_P_PC_INIT
);
179 // Allocate PEI instance data.
181 MemPages
= sizeof (FDC_BLK_IO_DEV
) / PageSize
+ 1;
182 Status
= PeiServicesAllocatePages (
183 EfiConventionalMemory
,
187 if (EFI_ERROR (Status
)) {
188 return EFI_OUT_OF_RESOURCES
;
192 // Initialize PEI instance data.
194 FdcBlkIoDev
= (FDC_BLK_IO_DEV
*) ((UINTN
) TempPtr
);
195 FdcBlkIoDev
->Signature
= FDC_BLK_IO_DEV_SIGNATURE
;
200 FdcEnumeration (FdcBlkIoDev
);
202 FdcBlkIoDev
->FdcBlkIo
.GetNumberOfBlockDevices
= FdcGetNumberOfBlockDevices
;
203 FdcBlkIoDev
->FdcBlkIo
.GetBlockDeviceMediaInfo
= FdcGetBlockDeviceMediaInfo
;
204 FdcBlkIoDev
->FdcBlkIo
.ReadBlocks
= FdcReadBlocks
;
206 FdcBlkIoDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
207 FdcBlkIoDev
->PpiDescriptor
.Guid
= &gEfiPei144FloppyBlockIoPpiGuid
;
208 FdcBlkIoDev
->PpiDescriptor
.Ppi
= &FdcBlkIoDev
->FdcBlkIo
;
210 if (FdcBlkIoDev
->DeviceCount
!= 0) {
211 Status
= PeiServicesInstallPpi (&FdcBlkIoDev
->PpiDescriptor
);
212 if (EFI_ERROR (Status
)) {
214 // PeiServicesFreePages (TempPtr, MemPages);
216 return EFI_OUT_OF_RESOURCES
;
220 // PeiServicesFreePages (TempPtr, MemPages);
229 FdcGetNumberOfBlockDevices (
230 IN EFI_PEI_SERVICES
**PeiServices
,
231 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
232 OUT UINTN
*NumberBlockDevices
243 // GC_TODO: This - add argument and description to function comment
244 // GC_TODO: NumberBlockDevices - add argument and description to function comment
245 // GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
246 // GC_TODO: EFI_SUCCESS - add return value to function comment
248 FDC_BLK_IO_DEV
*FdcBlkIoDev
;
252 return EFI_INVALID_PARAMETER
;
255 FdcBlkIoDev
= PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This
);
257 *NumberBlockDevices
= FdcBlkIoDev
->DeviceCount
;
264 FdcGetBlockDeviceMediaInfo (
265 IN EFI_PEI_SERVICES
**PeiServices
,
266 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
267 IN UINTN DeviceIndex
,
268 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
274 GC_TODO: Add function description
278 This - GC_TODO: add argument description
279 DeviceIndex - GC_TODO: add argument description
280 MediaInfo - GC_TODO: add argument description
284 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
285 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
286 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
287 EFI_SUCCESS - GC_TODO: Add description for return value
292 FDC_BLK_IO_DEV
*FdcBlkIoDev
;
297 if (This
== NULL
|| MediaInfo
== NULL
) {
298 return EFI_INVALID_PARAMETER
;
301 FdcBlkIoDev
= PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This
);
303 DeviceCount
= FdcBlkIoDev
->DeviceCount
;
306 // DeviceIndex is zero-based value.
308 if (DeviceIndex
> DeviceCount
- 1) {
309 return EFI_INVALID_PARAMETER
;
312 // probe media and retrieve latest media information
314 bStatus
= DiscoverFdcDevice (
316 &FdcBlkIoDev
->DeviceInfo
[DeviceIndex
],
321 return EFI_DEVICE_ERROR
;
325 &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
].MediaInfo
),
327 sizeof (EFI_PEI_BLOCK_IO_MEDIA
)
335 IN EFI_PEI_SERVICES
**PeiServices
,
336 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
337 IN UINTN DeviceIndex
,
338 IN EFI_PEI_LBA StartLba
,
346 GC_TODO: Add function description
350 This - GC_TODO: add argument description
351 DeviceIndex - GC_TODO: add argument description
352 StartLba - GC_TODO: add argument description
353 BufferSize - GC_TODO: add argument description
354 Buffer - GC_TODO: add argument description
358 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
359 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
360 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
361 EFI_NO_MEDIA - GC_TODO: Add description for return value
362 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
363 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
364 EFI_SUCCESS - GC_TODO: Add description for return value
365 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
370 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
373 UINTN NumberOfBlocks
;
375 FDC_BLK_IO_DEV
*FdcBlkIoDev
;
376 EFI_PHYSICAL_ADDRESS MemPage
;
381 return EFI_INVALID_PARAMETER
;
384 FdcBlkIoDev
= PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This
);
386 if (Buffer
== NULL
) {
387 return EFI_INVALID_PARAMETER
;
390 Status
= FdcGetBlockDeviceMediaInfo (PeiServices
, This
, DeviceIndex
, &MediaInfo
);
391 if (Status
!= EFI_SUCCESS
) {
395 BlockSize
= MediaInfo
.BlockSize
;
397 if (BufferSize
% BlockSize
!= 0) {
398 return EFI_INVALID_PARAMETER
;
401 if (!MediaInfo
.MediaPresent
) {
405 NumberOfBlocks
= BufferSize
/ BlockSize
;
408 // allocate 40 blocks: 5*4k=20k=20*1024=40blocks
410 MemPage
= ISA_MAX_MEMORY_ADDRESS
- 1;
411 Status
= PeiServicesAllocatePages (
412 EfiConventionalMemory
,
413 ((BufferSize
% EFI_PAGE_SIZE
) ? (BufferSize
/ EFI_PAGE_SIZE
+ 1) : (BufferSize
/ EFI_PAGE_SIZE
)),
416 if (EFI_ERROR (Status
) || (MemPage
>= ISA_MAX_MEMORY_ADDRESS
)) {
418 // If failed, designate the address space for DMA
422 // return EFI_OUT_OF_RESOURCES;
426 // MemPage = (EFI_PHYSICAL_ADDRESS)(UINTN)Temp;
428 Status
= MotorOn (FdcBlkIoDev
, &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
]));
429 if (Status
!= EFI_SUCCESS
) {
430 return EFI_DEVICE_ERROR
;
433 Status
= Setup (FdcBlkIoDev
, FdcBlkIoDev
->DeviceInfo
[DeviceIndex
].DevPos
);
434 if (Status
!= EFI_SUCCESS
) {
435 MotorOff (FdcBlkIoDev
, &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
]));
436 return EFI_DEVICE_ERROR
;
439 // read blocks in the same cylinder.
440 // in a cylinder , there are 18 * 2 = 36 blocks
442 while ((i
= GetTransferBlockCount (
443 &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
]),
446 )) != 0 && Status
== EFI_SUCCESS
) {
447 Status
= ReadWriteDataSector (
449 &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
]),
450 (UINT8
*) (UINTN
) MemPage
,
455 CopyMem ((UINT8
*) Buffer
, (UINT8
*) (UINTN
) MemPage
, BlockSize
* i
);
458 Buffer
= (VOID
*) ((UINTN
) Buffer
+ i
* BlockSize
);
461 // PeiServicesFreePages (MemPage, 5);
463 MotorOff (FdcBlkIoDev
, &(FdcBlkIoDev
->DeviceInfo
[DeviceIndex
]));
470 FdcReset (FdcBlkIoDev
, FdcBlkIoDev
->DeviceInfo
[DeviceIndex
].DevPos
);
471 return EFI_DEVICE_ERROR
;
478 // Internal function Implementation
482 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
488 Enumerate floppy device
492 FdcBlkIoDev - Instance of floppy device controller
502 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
508 // DevPos=0 means A: 1 means B:
510 for (DevPos
= 0; DevPos
< 2; DevPos
++) {
512 // Detecting device presence
514 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, EFI_PERIPHERAL_REMOVABLE_MEDIA
+ EFI_P_PC_PRESENCE_DETECT
);
521 Status
= FdcReset (FdcBlkIoDev
, DevPos
);
523 if (EFI_ERROR (Status
)) {
527 FdcBlkIoDev
->DeviceInfo
[DevPos
].DevPos
= DevPos
;
528 FdcBlkIoDev
->DeviceInfo
[DevPos
].Pcn
= 0;
529 FdcBlkIoDev
->DeviceInfo
[DevPos
].MotorOn
= FALSE
;
530 FdcBlkIoDev
->DeviceInfo
[DevPos
].NeedRecalibrate
= TRUE
;
531 FdcBlkIoDev
->DeviceInfo
[DevPos
].Type
= _1440K_1440K
;
534 // Discover FDC device
536 if (DiscoverFdcDevice (FdcBlkIoDev
, &(FdcBlkIoDev
->DeviceInfo
[DevPos
]), &MediaInfo
)) {
537 FdcBlkIoDev
->DeviceInfo
[DevNo
].DevPos
= DevPos
;
539 FdcBlkIoDev
->DeviceInfo
[DevNo
].Pcn
= FdcBlkIoDev
->DeviceInfo
[DevPos
].Pcn
;
540 FdcBlkIoDev
->DeviceInfo
[DevNo
].MotorOn
= FdcBlkIoDev
->DeviceInfo
[DevPos
].MotorOn
;
541 FdcBlkIoDev
->DeviceInfo
[DevNo
].NeedRecalibrate
= FdcBlkIoDev
->DeviceInfo
[DevPos
].NeedRecalibrate
;
542 FdcBlkIoDev
->DeviceInfo
[DevNo
].Type
= FdcBlkIoDev
->DeviceInfo
[DevPos
].Type
;
545 &(FdcBlkIoDev
->DeviceInfo
[DevNo
].MediaInfo
),
547 sizeof (EFI_PEI_BLOCK_IO_MEDIA
)
553 // Assume controller error
556 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
557 EFI_PERIPHERAL_REMOVABLE_MEDIA
+ EFI_P_EC_CONTROLLER_ERROR
566 FdcBlkIoDev
->DeviceCount
= DevNo
;
572 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
573 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
,
574 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
580 GC_TODO: Add function description
584 FdcBlkIoDev - GC_TODO: add argument description
585 Info - GC_TODO: add argument description
586 MediaInfo - GC_TODO: add argument description
590 GC_TODO: add return values
595 DISKET_PARA_TABLE
*Para
;
597 Status
= MotorOn (FdcBlkIoDev
, Info
);
598 if (Status
!= EFI_SUCCESS
) {
602 Status
= Recalibrate (FdcBlkIoDev
, Info
);
604 if (Status
!= EFI_SUCCESS
) {
605 MotorOff (FdcBlkIoDev
, Info
);
609 // Set Media Parameter
611 MediaInfo
->DeviceType
= LegacyFloppy
;
612 MediaInfo
->MediaPresent
= TRUE
;
617 Status
= DisketChanged (FdcBlkIoDev
, Info
);
620 MediaInfo
->MediaPresent
= FALSE
;
623 case EFI_MEDIA_CHANGED
:
631 MotorOff (FdcBlkIoDev
, Info
);
635 MotorOff (FdcBlkIoDev
, Info
);
637 Para
= (DISKET_PARA_TABLE
*) ((UINT8
*) DiskPara
+ sizeof (DISKET_PARA_TABLE
) * Info
->Type
);
638 MediaInfo
->BlockSize
= BytePerSector
[Para
->Number
];
639 MediaInfo
->LastBlock
= Para
->EOT
* 2 * (Para
->MaxTrackNum
+ 1) - 1;
646 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
653 GC_TODO: Add function description
657 FdcBlkIoDev - GC_TODO: add argument description
658 DevPos - GC_TODO: add argument description
662 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
663 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
664 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
665 EFI_SUCCESS - GC_TODO: Add description for return value
675 // Reset specified Floppy Logic Drive according to Fdd -> Disk
676 // Set Digital Output Register(DOR) to do reset work
677 // bit0 & bit1 of DOR : Drive Select
679 // bit3 : DMA and Int bit
680 // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until
681 // a "1" is written to this bit.
683 // use bit0 & bit1 to select the logic drive
687 data
= (UINT8
) (data
| (SELECT_DRV
& DevPos
));
688 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DOR
), data
);
691 // wait some time,at least 120us
693 MicroSecondDelay (500);
697 // write "1" to bit3 : enable DMA
700 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DOR
), data
);
702 MicroSecondDelay (2000);
705 // wait specified floppy logic drive is not busy
707 if (FdcWaitForBSYClear (FdcBlkIoDev
, DevPos
, 1) != EFI_SUCCESS
) {
708 return EFI_DEVICE_ERROR
;
711 // Set the Transfer Data Rate
713 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_CCR
), 0x0);
715 MicroSecondDelay (100);
718 // Issue Sense interrupt command for each drive (total 4 drives)
720 for (i
= 0; i
< 4; i
++) {
721 if (SenseIntStatus (FdcBlkIoDev
, &sts0
, &pcn
) != EFI_SUCCESS
) {
722 return EFI_DEVICE_ERROR
;
726 // issue Specify command
728 if (Specify (FdcBlkIoDev
) != EFI_SUCCESS
) {
729 return EFI_DEVICE_ERROR
;
737 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
739 IN UINTN TimeoutInSeconds
745 GC_TODO: Add function description
749 FdcBlkIoDev - GC_TODO: add argument description
750 DevPos - GC_TODO: add argument description
751 TimeoutInSeconds - GC_TODO: add argument description
755 EFI_TIMEOUT - GC_TODO: Add description for return value
756 EFI_SUCCESS - GC_TODO: Add description for return value
761 UINT8 StatusRegister
;
765 // How to determine drive and command are busy or not: by the bits of Main Status Register
766 // bit0: Drive 0 busy (drive A)
767 // bit1: Drive 1 busy (drive B)
768 // bit4: Command busy
770 // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4
772 Mask
= (UINT8
) ((DevPos
== 0 ? MSR_DAB
: MSR_DBB
) | MSR_CB
);
774 Delay
= ((TimeoutInSeconds
* STALL_1_MSECOND
) / 50) + 1;
777 StatusRegister
= IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_MSR
));
779 if ((StatusRegister
& Mask
) == 0x00) {
786 MicroSecondDelay (50);
798 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
806 GC_TODO: Add function description
810 FdcBlkIoDev - GC_TODO: add argument description
811 sts0 - GC_TODO: add argument description
812 pcn - GC_TODO: add argument description
816 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
817 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
818 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
819 EFI_SUCCESS - GC_TODO: Add description for return value
825 command
= SENSE_INT_STATUS_CMD
;
826 if (DataOutByte (FdcBlkIoDev
, &command
) != EFI_SUCCESS
) {
827 return EFI_DEVICE_ERROR
;
830 if (DataInByte (FdcBlkIoDev
, sts0
) != EFI_SUCCESS
) {
831 return EFI_DEVICE_ERROR
;
834 if (DataInByte (FdcBlkIoDev
, pcn
) != EFI_SUCCESS
) {
835 return EFI_DEVICE_ERROR
;
843 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
849 GC_TODO: Add function description
853 FdcBlkIoDev - GC_TODO: add argument description
857 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
858 EFI_SUCCESS - GC_TODO: Add description for return value
862 FDC_SPECIFY_CMD Command
;
866 ZeroMem (&Command
, sizeof (FDC_SPECIFY_CMD
));
867 Command
.CommandCode
= SPECIFY_CMD
;
871 Command
.SrtHut
= 0xdf;
876 Command
.HltNd
= 0x02;
878 pt
= (UINT8
*) (&Command
);
879 for (i
= 0; i
< sizeof (FDC_SPECIFY_CMD
); i
++) {
880 if (DataOutByte (FdcBlkIoDev
, pt
++) != EFI_SUCCESS
) {
881 return EFI_DEVICE_ERROR
;
890 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
897 GC_TODO: Add function description
901 FdcBlkIoDev - GC_TODO: add argument description
902 pt - GC_TODO: add argument description
906 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
907 EFI_SUCCESS - GC_TODO: Add description for return value
914 // wait for 1ms and detect the FDC is ready to be read
916 if (FdcDRQReady (FdcBlkIoDev
, DATA_IN
, 1) != EFI_SUCCESS
) {
917 return EFI_DEVICE_ERROR
;
923 data
= IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DTR
));
924 MicroSecondDelay (50);
931 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
938 GC_TODO: Add function description
942 FdcBlkIoDev - GC_TODO: add argument description
943 pt - GC_TODO: add argument description
947 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
948 EFI_SUCCESS - GC_TODO: Add description for return value
955 // wait for 1ms and detect the FDC is ready to be written
957 if (FdcDRQReady (FdcBlkIoDev
, DATA_OUT
, 1) != EFI_SUCCESS
) {
958 return EFI_DEVICE_ERROR
;
965 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DTR
), data
);
966 MicroSecondDelay (50);
972 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
974 IN UINTN TimeoutInSeconds
980 GC_TODO: Add function description
984 FdcBlkIoDev - GC_TODO: add argument description
985 Dio - GC_TODO: add argument description
986 TimeoutInSeconds - GC_TODO: add argument description
990 EFI_NOT_READY - GC_TODO: Add description for return value
991 EFI_SUCCESS - GC_TODO: Add description for return value
996 UINT8 StatusRegister
;
1000 // Before writing to FDC or reading from FDC, the Host must examine
1001 // the bit7(RQM) and bit6(DIO) of the Main Status Register.
1003 // command bytes can not be written to Data Register unless RQM is 1 and DIO is 0
1004 // result bytes can not be read from Data Register unless RQM is 1 and DIO is 1
1006 DataInOut
= (UINT8
) (Dio
<< 6);
1008 // in order to compare bit6
1010 Delay
= ((TimeoutInSeconds
* STALL_1_MSECOND
) / 50) + 1;
1012 StatusRegister
= IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_MSR
));
1013 if ((StatusRegister
& MSR_RQM
) == MSR_RQM
&& (StatusRegister
& MSR_DIO
) == DataInOut
) {
1020 MicroSecondDelay (50);
1024 return EFI_NOT_READY
;
1026 // FDC is not ready within the specified time period
1035 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1036 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
1040 Routine Description:
1042 GC_TODO: Add function description
1046 FdcBlkIoDev - GC_TODO: add argument description
1047 Info - GC_TODO: add argument description
1051 EFI_SUCCESS - GC_TODO: Add description for return value
1052 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1053 EFI_SUCCESS - GC_TODO: Add description for return value
1058 // EFI_STATUS Status;
1064 // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it
1065 // on first. But you can not leave the motor on all the time, since that would wear out the
1066 // disk. On the other hand, if you turn the motor off after each operation, the system performance
1067 // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after
1068 // each operation. If a new operation is started in that interval(2s), the motor need not be
1069 // turned on again. If no new operation is started, a timer goes off and the motor is turned off
1071 DevPos
= Info
->DevPos
;
1073 if (Info
->MotorOn
) {
1077 // The drive's motor is off, so need turn it on
1078 // first look at command and drive are busy or not
1080 if (FdcWaitForBSYClear (FdcBlkIoDev
, DevPos
, 1) != EFI_SUCCESS
) {
1081 return EFI_DEVICE_ERROR
;
1084 // for drive A: 1CH, drive B: 2DH
1087 data
= (UINT8
) (data
| (SELECT_DRV
& DevPos
));
1089 data
|= DRVA_MOTOR_ON
;
1091 // FdcTimer[1].MotorOn = FALSE;
1092 // Info->MotorOn = FALSE;
1095 data
|= DRVB_MOTOR_ON
;
1097 // FdcTimer[0].MotorOn = FALSE;
1098 // Info->MotorOn = FALSE;
1102 Info
->MotorOn
= FALSE
;
1104 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DOR
), data
);
1106 MicroSecondDelay (4000);
1108 // FdcTimer[DevPos].MotorOn = TRUE;
1110 Info
->MotorOn
= TRUE
;
1116 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1117 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
1121 Routine Description:
1123 GC_TODO: Add function description
1127 FdcBlkIoDev - GC_TODO: add argument description
1128 Info - GC_TODO: add argument description
1132 EFI_SUCCESS - GC_TODO: Add description for return value
1133 EFI_SUCCESS - GC_TODO: Add description for return value
1140 DevPos
= Info
->DevPos
;
1142 if (!Info
->MotorOn
) {
1146 // the motor is on, so need motor off
1149 data
= (UINT8
) (data
| (SELECT_DRV
& DevPos
));
1151 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DOR
), data
);
1152 MicroSecondDelay (50);
1154 // FdcTimer[DevPos].MotorOn = FALSE;
1156 Info
->MotorOn
= FALSE
;
1163 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1164 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
1168 Routine Description:
1170 GC_TODO: Add function description
1174 FdcBlkIoDev - GC_TODO: add argument description
1175 Info - GC_TODO: add argument description
1179 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1180 EFI_NO_MEDIA - GC_TODO: Add description for return value
1181 EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
1182 EFI_SUCCESS - GC_TODO: Add description for return value
1190 // Check change line
1192 data
= IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DIR
));
1194 MicroSecondDelay (50);
1196 if ((data
& DIR_DCL
) == 0x80) {
1197 if (Info
->Pcn
!= 0) {
1198 Status
= Recalibrate (FdcBlkIoDev
, Info
);
1200 Status
= Seek (FdcBlkIoDev
, Info
, 0x30);
1203 if (Status
!= EFI_SUCCESS
) {
1204 return EFI_DEVICE_ERROR
;
1206 // Fail to do the seek or recalibrate operation
1210 data
= IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_DIR
));
1212 MicroSecondDelay (50);
1214 if ((data
& DIR_DCL
) == 0x80) {
1215 return EFI_NO_MEDIA
;
1218 return EFI_MEDIA_CHANGED
;
1226 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1227 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
1231 Routine Description:
1233 GC_TODO: Add function description
1237 FdcBlkIoDev - GC_TODO: add argument description
1238 Info - GC_TODO: add argument description
1242 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1243 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1244 EFI_SUCCESS - GC_TODO: Add description for return value
1245 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1246 EFI_SUCCESS - GC_TODO: Add description for return value
1250 FDC_COMMAND_PACKET2 Command
;
1259 DevPos
= Info
->DevPos
;
1262 ZeroMem (&Command
, sizeof (FDC_COMMAND_PACKET2
));
1263 Command
.CommandCode
= RECALIBRATE_CMD
;
1268 Command
.DiskHeadSel
= 0;
1273 Command
.DiskHeadSel
= 1;
1279 pt
= (UINT8
*) (&Command
);
1280 for (i
= 0; i
< sizeof (FDC_COMMAND_PACKET2
); i
++) {
1281 if (DataOutByte (FdcBlkIoDev
, pt
++) != EFI_SUCCESS
) {
1282 return EFI_DEVICE_ERROR
;
1286 MicroSecondDelay (250000);
1288 if (SenseIntStatus (FdcBlkIoDev
, &sts0
, &pcn
) != EFI_SUCCESS
) {
1289 return EFI_DEVICE_ERROR
;
1292 if ((sts0
& 0xf0) == 0x20 && pcn
== 0) {
1294 // FdcTimer[DevPos].Pcn = 0;
1298 // FdcTimer[DevPos].NeedRecalibrate = FALSE;
1300 Info
->NeedRecalibrate
= FALSE
;
1305 return EFI_DEVICE_ERROR
;
1317 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1318 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
,
1323 Routine Description:
1325 GC_TODO: Add function description
1329 FdcBlkIoDev - GC_TODO: add argument description
1330 Info - GC_TODO: add argument description
1331 Lba - GC_TODO: add argument description
1335 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1336 EFI_SUCCESS - GC_TODO: Add description for return value
1337 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1338 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1339 EFI_SUCCESS - GC_TODO: Add description for return value
1340 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1344 FDC_SEEK_CMD Command
;
1345 DISKET_PARA_TABLE
*Para
;
1356 DevPos
= Info
->DevPos
;
1357 if (Info
->NeedRecalibrate
) {
1358 if (Recalibrate (FdcBlkIoDev
, Info
) != EFI_SUCCESS
) {
1359 return EFI_DEVICE_ERROR
;
1362 // Recalibrate Success
1364 Info
->NeedRecalibrate
= FALSE
;
1367 Para
= (DISKET_PARA_TABLE
*) ((UINT8
*) DiskPara
+ sizeof (DISKET_PARA_TABLE
) * Info
->Type
);
1368 EndOfTrack
= Para
->EOT
;
1370 // Calculate cylinder based on Lba and EOT
1372 Cylinder
= (UINT8
) ((UINTN
) Lba
/ EndOfTrack
/ 2);
1375 // if the dest cylinder is the present cylinder, unnecessary to do the seek operation
1377 if (Info
->Pcn
== Cylinder
) {
1381 // Calculate the head : 0 or 1
1383 Head
= (UINT8
) ((UINTN
) Lba
/ EndOfTrack
% 2);
1385 ZeroMem (&Command
, sizeof (FDC_SEEK_CMD
));
1386 Command
.CommandCode
= SEEK_CMD
;
1388 Command
.DiskHeadSel
= 0;
1393 Command
.DiskHeadSel
= 1;
1399 Command
.DiskHeadSel
= (UINT8
) (Command
.DiskHeadSel
| (Head
<< 2));
1400 Command
.NewCylinder
= Cylinder
;
1402 pt
= (UINT8
*) (&Command
);
1403 for (i
= 0; i
< sizeof (FDC_SEEK_CMD
); i
++) {
1404 if (DataOutByte (FdcBlkIoDev
, pt
++) != EFI_SUCCESS
) {
1405 return EFI_DEVICE_ERROR
;
1409 MicroSecondDelay (50);
1412 // Calculate waiting time
1414 if (Info
->Pcn
> Cylinder
) {
1415 x
= (UINT8
) (Info
->Pcn
- Cylinder
);
1417 x
= (UINT8
) (Cylinder
- Info
->Pcn
);
1420 MicroSecondDelay ((x
+ 1) * 4000);
1422 if (SenseIntStatus (FdcBlkIoDev
, &sts0
, &pcn
) != EFI_SUCCESS
) {
1423 return EFI_DEVICE_ERROR
;
1426 if ((sts0
& 0xf0) == 0x20) {
1427 Info
->Pcn
= Command
.NewCylinder
;
1428 Info
->NeedRecalibrate
= FALSE
;
1431 Info
->NeedRecalibrate
= TRUE
;
1432 return EFI_DEVICE_ERROR
;
1437 GetTransferBlockCount (
1438 IN PEI_FLOPPY_DEVICE_INFO
*Info
,
1440 IN UINTN NumberOfBlocks
1444 Routine Description:
1446 GC_TODO: Add function description
1450 Info - GC_TODO: add argument description
1451 LBA - GC_TODO: add argument description
1452 NumberOfBlocks - GC_TODO: add argument description
1456 GC_TODO: add return values
1460 DISKET_PARA_TABLE
*Para
;
1463 UINT8 SectorsInTrack
;
1465 Para
= (DISKET_PARA_TABLE
*) ((UINT8
*) DiskPara
+ sizeof (DISKET_PARA_TABLE
) * Info
->Type
);
1466 EndOfTrack
= Para
->EOT
;
1467 Head
= (UINT8
) ((UINTN
) LBA
/ EndOfTrack
% 2);
1469 SectorsInTrack
= (UINT8
) (EndOfTrack
* (2 - Head
) - (UINT8
) ((UINTN
) LBA
% EndOfTrack
));
1470 if (SectorsInTrack
< NumberOfBlocks
) {
1471 return SectorsInTrack
;
1473 return NumberOfBlocks
;
1478 ReadWriteDataSector (
1479 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1480 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
,
1483 IN UINTN NumberOfBlocks
,
1488 Routine Description:
1490 GC_TODO: Add function description
1494 FdcBlkIoDev - GC_TODO: add argument description
1495 Info - GC_TODO: add argument description
1496 Buffer - GC_TODO: add argument description
1497 Lba - GC_TODO: add argument description
1498 NumberOfBlocks - GC_TODO: add argument description
1499 Read - GC_TODO: add argument description
1503 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1504 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1505 EFI_TIMEOUT - GC_TODO: Add description for return value
1506 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1511 FDC_COMMAND_PACKET1 Command
;
1512 FDC_RESULT_PACKET Result
;
1519 Status
= Seek (FdcBlkIoDev
, Info
, Lba
);
1520 if (Status
!= EFI_SUCCESS
) {
1521 return EFI_DEVICE_ERROR
;
1526 SetDMA (FdcBlkIoDev
, Buffer
, NumberOfBlocks
, Read
);
1529 // Allocate Read or Write command packet
1531 ZeroMem (&Command
, sizeof (FDC_COMMAND_PACKET1
));
1533 Command
.CommandCode
= READ_DATA_CMD
| CMD_MT
| CMD_MFM
| CMD_SK
;
1537 // Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;
1539 FillPara (Info
, Lba
, &Command
);
1542 // Write command bytes to FDC
1544 pt
= (UINT8
*) (&Command
);
1545 for (i
= 0; i
< sizeof (FDC_COMMAND_PACKET1
); i
++) {
1546 if (DataOutByte (FdcBlkIoDev
, pt
++) != EFI_SUCCESS
) {
1547 return EFI_DEVICE_ERROR
;
1552 // wait for some time
1554 Times
= (STALL_1_SECOND
/ 50) + 1;
1556 if ((IoRead8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_MSR
)) & 0xc0) == 0xc0) {
1560 MicroSecondDelay (50);
1567 // Read result bytes from FDC
1569 pt
= (UINT8
*) (&Result
);
1570 for (i
= 0; i
< sizeof (FDC_RESULT_PACKET
); i
++) {
1571 if (DataInByte (FdcBlkIoDev
, pt
++) != EFI_SUCCESS
) {
1572 return EFI_DEVICE_ERROR
;
1576 return CheckResult (&Result
, Info
);
1581 IN FDC_RESULT_PACKET
*Result
,
1582 IN OUT PEI_FLOPPY_DEVICE_INFO
*Info
1586 Routine Description:
1588 GC_TODO: Add function description
1592 Result - GC_TODO: add argument description
1593 Info - GC_TODO: add argument description
1597 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1598 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1599 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1600 EFI_SUCCESS - GC_TODO: Add description for return value
1604 if ((Result
->Status0
& STS0_IC
) != IC_NT
) {
1605 if ((Result
->Status0
& STS0_SE
) == 0x20) {
1609 Info
->NeedRecalibrate
= TRUE
;
1612 Info
->NeedRecalibrate
= TRUE
;
1613 return EFI_DEVICE_ERROR
;
1616 // Check Status Register1
1618 if (Result
->Status1
& (STS1_EN
| STS1_DE
| STS1_OR
| STS1_ND
| STS1_NW
| STS1_MA
)) {
1619 Info
->NeedRecalibrate
= TRUE
;
1620 return EFI_DEVICE_ERROR
;
1623 // Check Status Register2
1625 if (Result
->Status2
& (STS2_CM
| STS2_DD
| STS2_WC
| STS2_BC
| STS2_MD
)) {
1626 Info
->NeedRecalibrate
= TRUE
;
1627 return EFI_DEVICE_ERROR
;
1635 IN PEI_FLOPPY_DEVICE_INFO
*Info
,
1637 IN FDC_COMMAND_PACKET1
*Command
1641 Routine Description:
1643 GC_TODO: Add function description
1647 Info - GC_TODO: add argument description
1648 Lba - GC_TODO: add argument description
1649 Command - GC_TODO: add argument description
1653 GC_TODO: add return values
1657 DISKET_PARA_TABLE
*Para
;
1661 DevPos
= Info
->DevPos
;
1662 Para
= (DISKET_PARA_TABLE
*) ((UINT8
*) DiskPara
+ sizeof (DISKET_PARA_TABLE
) * Info
->Type
);
1663 EndOfTrack
= Para
->EOT
;
1666 Command
->DiskHeadSel
= 0;
1668 Command
->DiskHeadSel
= 1;
1671 Command
->Cylinder
= (UINT8
) ((UINTN
) Lba
/ EndOfTrack
/ 2);
1672 Command
->Head
= (UINT8
) ((UINTN
) Lba
/ EndOfTrack
% 2);
1673 Command
->Sector
= (UINT8
) ((UINT8
) ((UINTN
) Lba
% EndOfTrack
) + 1);
1674 Command
->DiskHeadSel
= (UINT8
) (Command
->DiskHeadSel
| (Command
->Head
<< 2));
1675 Command
->Number
= Para
->Number
;
1676 Command
->EndOfTrack
= Para
->EOT
;
1677 Command
->GapLength
= Para
->GPL
;
1678 Command
->DataLength
= Para
->DTL
;
1683 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1688 Routine Description:
1690 GC_TODO: Add function description
1694 FdcBlkIoDev - GC_TODO: add argument description
1695 DevPos - GC_TODO: add argument description
1699 EFI_SUCCESS - GC_TODO: Add description for return value
1703 IoWrite8 ((UINT16
) (FdcBaseAddress
+ FDC_REGISTER_CCR
), 0x0);
1705 MicroSecondDelay (100);
1707 Specify (FdcBlkIoDev
);
1713 IN FDC_BLK_IO_DEV
*FdcBlkIoDev
,
1715 IN UINTN NumberOfBlocks
,
1720 Routine Description:
1722 GC_TODO: Add function description
1726 FdcBlkIoDev - GC_TODO: add argument description
1727 Buffer - GC_TODO: add argument description
1728 NumberOfBlocks - GC_TODO: add argument description
1729 Read - GC_TODO: add argument description
1733 EFI_SUCCESS - GC_TODO: Add description for return value
1741 // mask DMA channel 2;
1743 IoWrite8 (R_8237_DMA_WRSMSK_CH0_3
, B_8237_DMA_WRSMSK_CMS
| 2);
1746 // clear first/last flip flop
1748 IoWrite8 (R_8237_DMA_CBPR_CH0_3
, B_8237_DMA_WRSMSK_CMS
| 2);
1754 IoWrite8 (R_8237_DMA_CHMODE_CH0_3
, V_8237_DMA_CHMODE_SINGLE
| V_8237_DMA_CHMODE_IO2MEM
| 2);
1756 IoWrite8 (R_8237_DMA_CHMODE_CH0_3
, V_8237_DMA_CHMODE_SINGLE
| V_8237_DMA_CHMODE_MEM2IO
| 2);
1759 // set base address and page register
1761 data
= (UINT8
) (UINTN
) Buffer
;
1762 IoWrite8 (R_8237_DMA_BASE_CA_CH2
, data
);
1763 data
= (UINT8
) ((UINTN
) Buffer
>> 8);
1764 IoWrite8 (R_8237_DMA_BASE_CA_CH2
, data
);
1766 data
= (UINT8
) ((UINTN
) Buffer
>> 16);
1767 IoWrite8 (R_8237_DMA_MEM_LP_CH2
, data
);
1770 // set count register
1772 count
= 512 * NumberOfBlocks
- 1;
1773 data
= (UINT8
) (count
& 0xff);
1774 IoWrite8 (R_8237_DMA_BASE_CC_CH2
, data
);
1775 data
= (UINT8
) (count
>> 8);
1776 IoWrite8 (R_8237_DMA_BASE_CC_CH2
, data
);
1779 // clear channel 2 mask
1781 IoWrite8 (R_8237_DMA_WRSMSK_CH0_3
, 0x02);