+++ /dev/null
-/*++\r
-\r
- Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
- All rights reserved. This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-\r
-Module Name:\r
-\r
- FloppyPeim.c\r
- \r
-Abstract: \r
- \r
-\r
-Revision History\r
---*/\r
-\r
-\r
-#include "FloppyPeim.h"\r
-#include "IndustryStandard/Pcat.h"\r
-//\r
-// #include "sio.h"\r
-//\r
-\r
-#define PageSize 4096\r
-#define ISA_MAX_MEMORY_ADDRESS 0x1000000 // 16 MB Memory Range\r
-UINT16 FdcBaseAddress = 0x3f0;\r
-\r
-static DISKET_PARA_TABLE DiskPara[9] = {\r
- {\r
- 0x09,\r
- 0x50,\r
- 0xff,\r
- 0x2,\r
- 0x27,\r
- 0x4,\r
- 0x25,\r
- 0x14,\r
- 0x80\r
- },\r
- {\r
- 0x09,\r
- 0x2a,\r
- 0xff,\r
- 0x2,\r
- 0x27,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x40\r
- },\r
- {\r
- 0x0f,\r
- 0x54,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x0\r
- },\r
- {\r
- 0x09,\r
- 0x50,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x80\r
- },\r
- {\r
- 0x09,\r
- 0x2a,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x80\r
- },\r
- {\r
- 0x12,\r
- 0x1b,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x0\r
- },\r
- {\r
- 0x09,\r
- 0x2a,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x80\r
- },\r
- {\r
- 0x12,\r
- 0x1b,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0x0\r
- },\r
- {\r
- 0x24,\r
- 0x1b,\r
- 0xff,\r
- 0x2,\r
- 0x4f,\r
- 0x4,\r
- 0x25,\r
- 0x0f,\r
- 0xc0\r
- }\r
-};\r
-\r
-static UINTN BytePerSector[6] = { 0, 256, 512, 1024, 2048, 4096 };\r
-\r
-//\r
-// PEIM Entry Ppint\r
-//\r
-\r
-EFI_STATUS\r
-FdcPeimEntry (\r
- IN EFI_FFS_FILE_HEADER *FfsHeader,\r
- IN EFI_PEI_SERVICES **PeiServices\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Initializes the Fdc Block Io PPI\r
-\r
-Arguments:\r
-\r
- PeiServices - General purpose services available to every PEIM.\r
- FfsHeader - Ffs header pointer\r
- \r
-Returns:\r
-\r
- EFI_UNSUPPORTED - Can't find neccessary Ppi.\r
- EFI_OUT_OF_RESOURCES - Have no enough memory to create instance or descriptors.\r
- EFI_SUCCESS - Success. \r
-\r
---*/\r
-{\r
- UINTN MemPages;\r
- EFI_STATUS Status;\r
- FDC_BLK_IO_DEV *FdcBlkIoDev;\r
- EFI_PHYSICAL_ADDRESS TempPtr;\r
-\r
- //\r
- // Initializing PEI floppy driver.\r
- //\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_INIT);\r
-\r
- //\r
- // Data\r
- //\r
- // Allocate PEI instance data.\r
- //\r
- MemPages = sizeof (FDC_BLK_IO_DEV) / PageSize + 1;\r
- Status = PeiServicesAllocatePages (\r
- EfiConventionalMemory,\r
- MemPages,\r
- &TempPtr\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- //\r
- // Initialize PEI instance data.\r
- //\r
- FdcBlkIoDev = (FDC_BLK_IO_DEV *) ((UINTN) TempPtr);\r
- FdcBlkIoDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;\r
- \r
- //\r
- // InitSio ();\r
- //\r
- FdcEnumeration (FdcBlkIoDev);\r
-\r
- FdcBlkIoDev->FdcBlkIo.GetNumberOfBlockDevices = FdcGetNumberOfBlockDevices;\r
- FdcBlkIoDev->FdcBlkIo.GetBlockDeviceMediaInfo = FdcGetBlockDeviceMediaInfo;\r
- FdcBlkIoDev->FdcBlkIo.ReadBlocks = FdcReadBlocks;\r
-\r
- FdcBlkIoDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
- FdcBlkIoDev->PpiDescriptor.Guid = &gEfiPei144FloppyBlockIoPpiGuid;\r
- FdcBlkIoDev->PpiDescriptor.Ppi = &FdcBlkIoDev->FdcBlkIo;\r
-\r
- if (FdcBlkIoDev->DeviceCount != 0) {\r
- Status = PeiServicesInstallPpi (&FdcBlkIoDev->PpiDescriptor);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // PeiServicesFreePages (TempPtr, MemPages);\r
- //\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- //\r
- // PeiServicesFreePages (TempPtr, MemPages);\r
- //\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FdcGetNumberOfBlockDevices (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
- OUT UINTN *NumberBlockDevices\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
- \r
-Returns:\r
-\r
---*/\r
-// GC_TODO: This - add argument and description to function comment\r
-// GC_TODO: NumberBlockDevices - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\r
-{\r
- FDC_BLK_IO_DEV *FdcBlkIoDev;\r
-\r
- FdcBlkIoDev = NULL;\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
-\r
- *NumberBlockDevices = FdcBlkIoDev->DeviceCount;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FdcGetBlockDeviceMediaInfo (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
- IN UINTN DeviceIndex,\r
- OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - GC_TODO: add argument description\r
- DeviceIndex - GC_TODO: add argument description\r
- MediaInfo - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
- EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINTN DeviceCount;\r
- FDC_BLK_IO_DEV *FdcBlkIoDev;\r
- BOOLEAN bStatus;\r
-\r
- FdcBlkIoDev = NULL;\r
-\r
- if (This == NULL || MediaInfo == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
-\r
- DeviceCount = FdcBlkIoDev->DeviceCount;\r
-\r
- //\r
- // DeviceIndex is zero-based value.\r
- //\r
- if (DeviceIndex > DeviceCount - 1) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // probe media and retrieve latest media information\r
- //\r
- bStatus = DiscoverFdcDevice (\r
- FdcBlkIoDev,\r
- &FdcBlkIoDev->DeviceInfo[DeviceIndex],\r
- MediaInfo\r
- );\r
-\r
- if (!bStatus) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- CopyMem (\r
- &(FdcBlkIoDev->DeviceInfo[DeviceIndex].MediaInfo),\r
- MediaInfo,\r
- sizeof (EFI_PEI_BLOCK_IO_MEDIA)\r
- );\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-FdcReadBlocks (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
- IN UINTN DeviceIndex,\r
- IN EFI_PEI_LBA StartLba,\r
- IN UINTN BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- This - GC_TODO: add argument description\r
- DeviceIndex - GC_TODO: add argument description\r
- StartLba - GC_TODO: add argument description\r
- BufferSize - GC_TODO: add argument description\r
- Buffer - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
- EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
- EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
- EFI_NO_MEDIA - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
-\r
- EFI_PEI_BLOCK_IO_MEDIA MediaInfo;\r
- EFI_STATUS Status;\r
- UINTN i;\r
- UINTN NumberOfBlocks;\r
- UINTN BlockSize;\r
- FDC_BLK_IO_DEV *FdcBlkIoDev;\r
- EFI_PHYSICAL_ADDRESS MemPage;\r
-\r
- FdcBlkIoDev = NULL;\r
-\r
- if (This == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);\r
-\r
- if (Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Status = FdcGetBlockDeviceMediaInfo (PeiServices, This, DeviceIndex, &MediaInfo);\r
- if (Status != EFI_SUCCESS) {\r
- return Status;\r
- }\r
-\r
- BlockSize = MediaInfo.BlockSize;\r
-\r
- if (BufferSize % BlockSize != 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (!MediaInfo.MediaPresent) {\r
- return EFI_NO_MEDIA;\r
- }\r
-\r
- NumberOfBlocks = BufferSize / BlockSize;\r
-\r
- //\r
- // allocate 40 blocks: 5*4k=20k=20*1024=40blocks\r
- //\r
- MemPage = ISA_MAX_MEMORY_ADDRESS - 1;\r
- Status = PeiServicesAllocatePages (\r
- EfiConventionalMemory,\r
- ((BufferSize % EFI_PAGE_SIZE) ? (BufferSize / EFI_PAGE_SIZE + 1) : (BufferSize / EFI_PAGE_SIZE)),\r
- &MemPage\r
- );\r
- if (EFI_ERROR (Status) || (MemPage >= ISA_MAX_MEMORY_ADDRESS)) {\r
- //\r
- // If failed, designate the address space for DMA\r
- //\r
- MemPage = 0x0f00000;\r
- //\r
- // return EFI_OUT_OF_RESOURCES;\r
- //\r
- }\r
- //\r
- // MemPage = (EFI_PHYSICAL_ADDRESS)(UINTN)Temp;\r
- //\r
- Status = MotorOn (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
- if (Status != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Status = Setup (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);\r
- if (Status != EFI_SUCCESS) {\r
- MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // read blocks in the same cylinder.\r
- // in a cylinder , there are 18 * 2 = 36 blocks\r
- //\r
- while ((i = GetTransferBlockCount (\r
- &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),\r
- StartLba,\r
- NumberOfBlocks\r
- )) != 0 && Status == EFI_SUCCESS) {\r
- Status = ReadWriteDataSector (\r
- FdcBlkIoDev,\r
- &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),\r
- (UINT8 *) (UINTN) MemPage,\r
- StartLba,\r
- i,\r
- READ\r
- );\r
- CopyMem ((UINT8 *) Buffer, (UINT8 *) (UINTN) MemPage, BlockSize * i);\r
- StartLba += i;\r
- NumberOfBlocks -= i;\r
- Buffer = (VOID *) ((UINTN) Buffer + i * BlockSize);\r
- }\r
- //\r
- // PeiServicesFreePages (MemPage, 5);\r
- //\r
- MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));\r
-\r
- switch (Status) {\r
- case EFI_SUCCESS:\r
- return EFI_SUCCESS;\r
-\r
- default:\r
- FdcReset (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // return Status;\r
- //\r
-}\r
-//\r
-// Internal function Implementation\r
-//\r
-UINT8\r
-FdcEnumeration (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Enumerate floppy device\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - Instance of floppy device controller\r
-\r
-Returns:\r
-\r
- DevNo - Device No.\r
-\r
---*/\r
-{\r
- UINT8 DevPos;\r
- UINT8 DevNo;\r
- EFI_PEI_BLOCK_IO_MEDIA MediaInfo;\r
- EFI_STATUS Status;\r
-\r
- DevNo = 0;\r
-\r
- //\r
- // DevPos=0 means A: 1 means B:\r
- //\r
- for (DevPos = 0; DevPos < 2; DevPos++) {\r
- //\r
- // Detecting device presence\r
- //\r
- REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_PRESENCE_DETECT);\r
-\r
- //\r
- // Data\r
- //\r
- // Reset FDC\r
- //\r
- Status = FdcReset (FdcBlkIoDev, DevPos);\r
-\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- FdcBlkIoDev->DeviceInfo[DevPos].DevPos = DevPos;\r
- FdcBlkIoDev->DeviceInfo[DevPos].Pcn = 0;\r
- FdcBlkIoDev->DeviceInfo[DevPos].MotorOn = FALSE;\r
- FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate = TRUE;\r
- FdcBlkIoDev->DeviceInfo[DevPos].Type = _1440K_1440K;\r
-\r
- //\r
- // Discover FDC device\r
- //\r
- if (DiscoverFdcDevice (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DevPos]), &MediaInfo)) {\r
- FdcBlkIoDev->DeviceInfo[DevNo].DevPos = DevPos;\r
-\r
- FdcBlkIoDev->DeviceInfo[DevNo].Pcn = FdcBlkIoDev->DeviceInfo[DevPos].Pcn;\r
- FdcBlkIoDev->DeviceInfo[DevNo].MotorOn = FdcBlkIoDev->DeviceInfo[DevPos].MotorOn;\r
- FdcBlkIoDev->DeviceInfo[DevNo].NeedRecalibrate = FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate;\r
- FdcBlkIoDev->DeviceInfo[DevNo].Type = FdcBlkIoDev->DeviceInfo[DevPos].Type;\r
-\r
- CopyMem (\r
- &(FdcBlkIoDev->DeviceInfo[DevNo].MediaInfo),\r
- &MediaInfo,\r
- sizeof (EFI_PEI_BLOCK_IO_MEDIA)\r
- );\r
-\r
- DevNo++;\r
- } else {\r
- //\r
- // Assume controller error\r
- //\r
- REPORT_STATUS_CODE (\r
- EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
- EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_EC_CONTROLLER_ERROR\r
- );\r
-\r
- //\r
- // Data\r
- //\r
- }\r
- }\r
-\r
- FdcBlkIoDev->DeviceCount = DevNo;\r
- return DevNo;\r
-}\r
-\r
-BOOLEAN\r
-DiscoverFdcDevice (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
- OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
- MediaInfo - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- DISKET_PARA_TABLE *Para;\r
-\r
- Status = MotorOn (FdcBlkIoDev, Info);\r
- if (Status != EFI_SUCCESS) {\r
- return FALSE;\r
- }\r
-\r
- Status = Recalibrate (FdcBlkIoDev, Info);\r
-\r
- if (Status != EFI_SUCCESS) {\r
- MotorOff (FdcBlkIoDev, Info);\r
- return FALSE;\r
- }\r
- //\r
- // Set Media Parameter\r
- //\r
- MediaInfo->DeviceType = LegacyFloppy;\r
- MediaInfo->MediaPresent = TRUE;\r
-\r
- //\r
- // Check Media\r
- //\r
- Status = DisketChanged (FdcBlkIoDev, Info);\r
- switch (Status) {\r
- case EFI_NO_MEDIA:\r
- MediaInfo->MediaPresent = FALSE;\r
- break;\r
-\r
- case EFI_MEDIA_CHANGED:\r
- case EFI_SUCCESS:\r
- break;\r
-\r
- default:\r
- //\r
- // EFI_DEVICE_ERROR\r
- //\r
- MotorOff (FdcBlkIoDev, Info);\r
- return FALSE;\r
- }\r
-\r
- MotorOff (FdcBlkIoDev, Info);\r
-\r
- Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
- MediaInfo->BlockSize = BytePerSector[Para->Number];\r
- MediaInfo->LastBlock = Para->EOT * 2 * (Para->MaxTrackNum + 1) - 1;\r
-\r
- return TRUE;\r
-}\r
-\r
-EFI_STATUS\r
-FdcReset (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN UINT8 DevPos\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- DevPos - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 data;\r
- UINT8 sts0;\r
- UINT8 pcn;\r
- UINTN i;\r
-\r
- //\r
- // Reset specified Floppy Logic Drive according to Fdd -> Disk\r
- // Set Digital Output Register(DOR) to do reset work\r
- // bit0 & bit1 of DOR : Drive Select\r
- // bit2 : Reset bit\r
- // bit3 : DMA and Int bit\r
- // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until\r
- // a "1" is written to this bit.\r
- // Reset step 1:\r
- // use bit0 & bit1 to select the logic drive\r
- // write "0" to bit2\r
- //\r
- data = 0x0;\r
- data = (UINT8) (data | (SELECT_DRV & DevPos));\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
-\r
- //\r
- // wait some time,at least 120us\r
- //\r
- MicroSecondDelay (500);\r
- //\r
- // Reset step 2:\r
- // write "1" to bit2\r
- // write "1" to bit3 : enable DMA\r
- //\r
- data |= 0x0C;\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
-\r
- MicroSecondDelay (2000);\r
- \r
- //\r
- // wait specified floppy logic drive is not busy\r
- //\r
- if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Set the Transfer Data Rate\r
- //\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);\r
-\r
- MicroSecondDelay (100);\r
-\r
- //\r
- // Issue Sense interrupt command for each drive (total 4 drives)\r
- //\r
- for (i = 0; i < 4; i++) {\r
- if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
- //\r
- // issue Specify command\r
- //\r
- if (Specify (FdcBlkIoDev) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-FdcWaitForBSYClear (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN UINT8 DevPos,\r
- IN UINTN TimeoutInSeconds\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- DevPos - GC_TODO: add argument description\r
- TimeoutInSeconds - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_TIMEOUT - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINTN Delay;\r
- UINT8 StatusRegister;\r
- UINT8 Mask;\r
-\r
- //\r
- // How to determine drive and command are busy or not: by the bits of Main Status Register\r
- // bit0: Drive 0 busy (drive A)\r
- // bit1: Drive 1 busy (drive B)\r
- // bit4: Command busy\r
- //\r
- // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4\r
- //\r
- Mask = (UINT8) ((DevPos == 0 ? MSR_DAB : MSR_DBB) | MSR_CB);\r
-\r
- Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
-\r
- do {\r
- StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));\r
-\r
- if ((StatusRegister & Mask) == 0x00) {\r
- break;\r
- //\r
- // not busy\r
- //\r
- }\r
-\r
- MicroSecondDelay (50);\r
- } while (--Delay);\r
-\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SenseIntStatus (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT UINT8 *sts0,\r
- IN OUT UINT8 *pcn\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- sts0 - GC_TODO: add argument description\r
- pcn - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 command;\r
-\r
- command = SENSE_INT_STATUS_CMD;\r
- if (DataOutByte (FdcBlkIoDev, &command) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (DataInByte (FdcBlkIoDev, sts0) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (DataInByte (FdcBlkIoDev, pcn) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-Specify (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- FDC_SPECIFY_CMD Command;\r
- UINTN i;\r
- UINT8 *pt;\r
-\r
- ZeroMem (&Command, sizeof (FDC_SPECIFY_CMD));\r
- Command.CommandCode = SPECIFY_CMD;\r
- //\r
- // set SRT, HUT\r
- //\r
- Command.SrtHut = 0xdf;\r
- //\r
- // 0xdf;\r
- // set HLT and DMA\r
- //\r
- Command.HltNd = 0x02;\r
-\r
- pt = (UINT8 *) (&Command);\r
- for (i = 0; i < sizeof (FDC_SPECIFY_CMD); i++) {\r
- if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DataInByte (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT UINT8 *pt\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- pt - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 data;\r
-\r
- //\r
- // wait for 1ms and detect the FDC is ready to be read\r
- //\r
- if (FdcDRQReady (FdcBlkIoDev, DATA_IN, 1) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- //\r
- // is not ready\r
- //\r
- }\r
-\r
- data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR));\r
- MicroSecondDelay (50);\r
- *pt = data;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DataOutByte (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN UINT8 *pt\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- pt - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 data;\r
-\r
- //\r
- // wait for 1ms and detect the FDC is ready to be written\r
- //\r
- if (FdcDRQReady (FdcBlkIoDev, DATA_OUT, 1) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- //\r
- // is not ready\r
- //\r
- }\r
-\r
- data = *pt;\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR), data);\r
- MicroSecondDelay (50);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-FdcDRQReady (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN BOOLEAN Dio,\r
- IN UINTN TimeoutInSeconds\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Dio - GC_TODO: add argument description\r
- TimeoutInSeconds - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_NOT_READY - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINTN Delay;\r
- UINT8 StatusRegister;\r
- UINT8 DataInOut;\r
-\r
- //\r
- // Before writing to FDC or reading from FDC, the Host must examine\r
- // the bit7(RQM) and bit6(DIO) of the Main Status Register.\r
- // That is to say:\r
- // command bytes can not be written to Data Register unless RQM is 1 and DIO is 0\r
- // result bytes can not be read from Data Register unless RQM is 1 and DIO is 1\r
- //\r
- DataInOut = (UINT8) (Dio << 6);\r
- //\r
- // in order to compare bit6\r
- //\r
- Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;\r
- do {\r
- StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));\r
- if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {\r
- break;\r
- //\r
- // FDC is ready\r
- //\r
- }\r
-\r
- MicroSecondDelay (50);\r
- } while (--Delay);\r
-\r
- if (Delay == 0) {\r
- return EFI_NOT_READY;\r
- //\r
- // FDC is not ready within the specified time period\r
- //\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-MotorOn (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- //\r
- // EFI_STATUS Status;\r
- //\r
- UINT8 data;\r
- UINT8 DevPos;\r
-\r
- //\r
- // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it\r
- // on first. But you can not leave the motor on all the time, since that would wear out the\r
- // disk. On the other hand, if you turn the motor off after each operation, the system performance\r
- // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after\r
- // each operation. If a new operation is started in that interval(2s), the motor need not be\r
- // turned on again. If no new operation is started, a timer goes off and the motor is turned off\r
- //\r
- DevPos = Info->DevPos;\r
-\r
- if (Info->MotorOn) {\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // The drive's motor is off, so need turn it on\r
- // first look at command and drive are busy or not\r
- //\r
- if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // for drive A: 1CH, drive B: 2DH\r
- //\r
- data = 0x0C;\r
- data = (UINT8) (data | (SELECT_DRV & DevPos));\r
- if (DevPos == 0) {\r
- data |= DRVA_MOTOR_ON;\r
- //\r
- // FdcTimer[1].MotorOn = FALSE;\r
- // Info->MotorOn = FALSE;\r
- //\r
- } else {\r
- data |= DRVB_MOTOR_ON;\r
- //\r
- // FdcTimer[0].MotorOn = FALSE;\r
- // Info->MotorOn = FALSE;\r
- //\r
- }\r
-\r
- Info->MotorOn = FALSE;\r
-\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
-\r
- MicroSecondDelay (4000);\r
- //\r
- // FdcTimer[DevPos].MotorOn = TRUE;\r
- //\r
- Info->MotorOn = TRUE;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-MotorOff (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 data;\r
- UINT8 DevPos;\r
-\r
- DevPos = Info->DevPos;\r
-\r
- if (!Info->MotorOn) {\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // the motor is on, so need motor off\r
- //\r
- data = 0x0C;\r
- data = (UINT8) (data | (SELECT_DRV & DevPos));\r
-\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);\r
- MicroSecondDelay (50);\r
- //\r
- // FdcTimer[DevPos].MotorOn = FALSE;\r
- //\r
- Info->MotorOn = FALSE;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-DisketChanged (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_NO_MEDIA - GC_TODO: Add description for return value\r
- EFI_MEDIA_CHANGED - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- UINT8 data;\r
-\r
- //\r
- // Check change line\r
- //\r
- data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));\r
-\r
- MicroSecondDelay (50);\r
-\r
- if ((data & DIR_DCL) == 0x80) {\r
- if (Info->Pcn != 0) {\r
- Status = Recalibrate (FdcBlkIoDev, Info);\r
- } else {\r
- Status = Seek (FdcBlkIoDev, Info, 0x30);\r
- }\r
-\r
- if (Status != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- //\r
- // Fail to do the seek or recalibrate operation\r
- //\r
- }\r
-\r
- data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));\r
-\r
- MicroSecondDelay (50);\r
-\r
- if ((data & DIR_DCL) == 0x80) {\r
- return EFI_NO_MEDIA;\r
- }\r
-\r
- return EFI_MEDIA_CHANGED;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-Recalibrate (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- FDC_COMMAND_PACKET2 Command;\r
- UINTN i;\r
- UINT8 sts0;\r
- UINT8 pcn;\r
- UINT8 *pt;\r
- UINT8 Count;\r
- UINT8 DevPos;\r
-\r
- Count = 2;\r
- DevPos = Info->DevPos;\r
-\r
- while (Count > 0) {\r
- ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET2));\r
- Command.CommandCode = RECALIBRATE_CMD;\r
- //\r
- // drive select\r
- //\r
- if (DevPos == 0) {\r
- Command.DiskHeadSel = 0;\r
- //\r
- // 0\r
- //\r
- } else {\r
- Command.DiskHeadSel = 1;\r
- //\r
- // 1\r
- //\r
- }\r
-\r
- pt = (UINT8 *) (&Command);\r
- for (i = 0; i < sizeof (FDC_COMMAND_PACKET2); i++) {\r
- if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- MicroSecondDelay (250000);\r
-\r
- if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((sts0 & 0xf0) == 0x20 && pcn == 0) {\r
- //\r
- // FdcTimer[DevPos].Pcn = 0;\r
- //\r
- Info->Pcn = 0;\r
- //\r
- // FdcTimer[DevPos].NeedRecalibrate = FALSE;\r
- //\r
- Info->NeedRecalibrate = FALSE;\r
- return EFI_SUCCESS;\r
- } else {\r
- Count--;\r
- if (Count == 0) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
- }\r
- //\r
- // end while\r
- //\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-Seek (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
- IN EFI_PEI_LBA Lba\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
- Lba - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- FDC_SEEK_CMD Command;\r
- DISKET_PARA_TABLE *Para;\r
- UINT8 EndOfTrack;\r
- UINT8 Head;\r
- UINT8 Cylinder;\r
- UINT8 sts0;\r
- UINT8 *pt;\r
- UINT8 pcn;\r
- UINTN i;\r
- UINT8 x;\r
- UINT8 DevPos;\r
-\r
- DevPos = Info->DevPos;\r
- if (Info->NeedRecalibrate) {\r
- if (Recalibrate (FdcBlkIoDev, Info) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Recalibrate Success\r
- //\r
- Info->NeedRecalibrate = FALSE;\r
- }\r
-\r
- Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
- EndOfTrack = Para->EOT;\r
- //\r
- // Calculate cylinder based on Lba and EOT\r
- //\r
- Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
-\r
- //\r
- // if the dest cylinder is the present cylinder, unnecessary to do the seek operation\r
- //\r
- if (Info->Pcn == Cylinder) {\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // Calculate the head : 0 or 1\r
- //\r
- Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
-\r
- ZeroMem (&Command, sizeof (FDC_SEEK_CMD));\r
- Command.CommandCode = SEEK_CMD;\r
- if (DevPos == 0) {\r
- Command.DiskHeadSel = 0;\r
- //\r
- // 0\r
- //\r
- } else {\r
- Command.DiskHeadSel = 1;\r
- //\r
- // 1\r
- //\r
- }\r
-\r
- Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));\r
- Command.NewCylinder = Cylinder;\r
-\r
- pt = (UINT8 *) (&Command);\r
- for (i = 0; i < sizeof (FDC_SEEK_CMD); i++) {\r
- if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- MicroSecondDelay (50);\r
-\r
- //\r
- // Calculate waiting time\r
- //\r
- if (Info->Pcn > Cylinder) {\r
- x = (UINT8) (Info->Pcn - Cylinder);\r
- } else {\r
- x = (UINT8) (Cylinder - Info->Pcn);\r
- }\r
-\r
- MicroSecondDelay ((x + 1) * 4000);\r
-\r
- if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((sts0 & 0xf0) == 0x20) {\r
- Info->Pcn = Command.NewCylinder;\r
- Info->NeedRecalibrate = FALSE;\r
- return EFI_SUCCESS;\r
- } else {\r
- Info->NeedRecalibrate = TRUE;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-}\r
-\r
-UINTN\r
-GetTransferBlockCount (\r
- IN PEI_FLOPPY_DEVICE_INFO *Info,\r
- IN EFI_PEI_LBA LBA,\r
- IN UINTN NumberOfBlocks\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Info - GC_TODO: add argument description\r
- LBA - GC_TODO: add argument description\r
- NumberOfBlocks - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- DISKET_PARA_TABLE *Para;\r
- UINT8 EndOfTrack;\r
- UINT8 Head;\r
- UINT8 SectorsInTrack;\r
-\r
- Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
- EndOfTrack = Para->EOT;\r
- Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);\r
-\r
- SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));\r
- if (SectorsInTrack < NumberOfBlocks) {\r
- return SectorsInTrack;\r
- } else {\r
- return NumberOfBlocks;\r
- }\r
-}\r
-\r
-EFI_STATUS\r
-ReadWriteDataSector (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info,\r
- IN VOID *Buffer,\r
- IN EFI_PEI_LBA Lba,\r
- IN UINTN NumberOfBlocks,\r
- IN BOOLEAN Read\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
- Buffer - GC_TODO: add argument description\r
- Lba - GC_TODO: add argument description\r
- NumberOfBlocks - GC_TODO: add argument description\r
- Read - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_TIMEOUT - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- FDC_COMMAND_PACKET1 Command;\r
- FDC_RESULT_PACKET Result;\r
- UINTN i;\r
- UINTN Times;\r
- UINT8 *pt;\r
- //\r
- // UINT8 Temp;\r
- //\r
- Status = Seek (FdcBlkIoDev, Info, Lba);\r
- if (Status != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Set up DMA\r
- //\r
- SetDMA (FdcBlkIoDev, Buffer, NumberOfBlocks, Read);\r
-\r
- //\r
- // Allocate Read or Write command packet\r
- //\r
- ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET1));\r
- if (Read == READ) {\r
- Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;\r
- }\r
- //\r
- // else\r
- // Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;\r
- //\r
- FillPara (Info, Lba, &Command);\r
-\r
- //\r
- // Write command bytes to FDC\r
- //\r
- pt = (UINT8 *) (&Command);\r
- for (i = 0; i < sizeof (FDC_COMMAND_PACKET1); i++) {\r
- if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- //\r
- // wait for some time\r
- //\r
- Times = (STALL_1_SECOND / 50) + 1;\r
- do {\r
- if ((IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR)) & 0xc0) == 0xc0) {\r
- break;\r
- }\r
-\r
- MicroSecondDelay (50);\r
- } while (--Times);\r
-\r
- if (Times == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
- //\r
- // Read result bytes from FDC\r
- //\r
- pt = (UINT8 *) (&Result);\r
- for (i = 0; i < sizeof (FDC_RESULT_PACKET); i++) {\r
- if (DataInByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- return CheckResult (&Result, Info);\r
-}\r
-\r
-EFI_STATUS\r
-CheckResult (\r
- IN FDC_RESULT_PACKET *Result,\r
- IN OUT PEI_FLOPPY_DEVICE_INFO *Info\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Result - GC_TODO: add argument description\r
- Info - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- if ((Result->Status0 & STS0_IC) != IC_NT) {\r
- if ((Result->Status0 & STS0_SE) == 0x20) {\r
- //\r
- // seek error\r
- //\r
- Info->NeedRecalibrate = TRUE;\r
- }\r
-\r
- Info->NeedRecalibrate = TRUE;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Check Status Register1\r
- //\r
- if (Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {\r
- Info->NeedRecalibrate = TRUE;\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Check Status Register2\r
- //\r
- if (Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {\r
- Info->NeedRecalibrate = TRUE;\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-VOID\r
-FillPara (\r
- IN PEI_FLOPPY_DEVICE_INFO *Info,\r
- IN EFI_PEI_LBA Lba,\r
- IN FDC_COMMAND_PACKET1 *Command\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- Info - GC_TODO: add argument description\r
- Lba - GC_TODO: add argument description\r
- Command - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- GC_TODO: add return values\r
-\r
---*/\r
-{\r
- DISKET_PARA_TABLE *Para;\r
- UINT8 EndOfTrack;\r
- UINT8 DevPos;\r
-\r
- DevPos = Info->DevPos;\r
- Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);\r
- EndOfTrack = Para->EOT;\r
-\r
- if (DevPos == 0) {\r
- Command->DiskHeadSel = 0;\r
- } else {\r
- Command->DiskHeadSel = 1;\r
- }\r
-\r
- Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);\r
- Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);\r
- Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);\r
- Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2));\r
- Command->Number = Para->Number;\r
- Command->EndOfTrack = Para->EOT;\r
- Command->GapLength = Para->GPL;\r
- Command->DataLength = Para->DTL;\r
-}\r
-\r
-EFI_STATUS\r
-Setup (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN UINT8 DevPos\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- DevPos - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);\r
-\r
- MicroSecondDelay (100);\r
-\r
- Specify (FdcBlkIoDev);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SetDMA (\r
- IN FDC_BLK_IO_DEV *FdcBlkIoDev,\r
- IN VOID *Buffer,\r
- IN UINTN NumberOfBlocks,\r
- IN BOOLEAN Read\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- GC_TODO: Add function description\r
-\r
-Arguments:\r
-\r
- FdcBlkIoDev - GC_TODO: add argument description\r
- Buffer - GC_TODO: add argument description\r
- NumberOfBlocks - GC_TODO: add argument description\r
- Read - GC_TODO: add argument description\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - GC_TODO: Add description for return value\r
-\r
---*/\r
-{\r
- UINT8 data;\r
- UINTN count;\r
-\r
- //\r
- // mask DMA channel 2;\r
- //\r
- IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);\r
-\r
- //\r
- // clear first/last flip flop\r
- //\r
- IoWrite8 (R_8237_DMA_CBPR_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);\r
-\r
- //\r
- // set mode\r
- //\r
- if (Read == READ) {\r
- IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_IO2MEM | 2);\r
- } else {\r
- IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_MEM2IO | 2);\r
- }\r
- //\r
- // set base address and page register\r
- //\r
- data = (UINT8) (UINTN) Buffer;\r
- IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);\r
- data = (UINT8) ((UINTN) Buffer >> 8);\r
- IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);\r
-\r
- data = (UINT8) ((UINTN) Buffer >> 16);\r
- IoWrite8 (R_8237_DMA_MEM_LP_CH2, data);\r
-\r
- //\r
- // set count register\r
- //\r
- count = 512 * NumberOfBlocks - 1;\r
- data = (UINT8) (count & 0xff);\r
- IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);\r
- data = (UINT8) (count >> 8);\r
- IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);\r
-\r
- //\r
- // clear channel 2 mask\r
- //\r
- IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, 0x02);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r