--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation. All rights reserved. <BR> \r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ IsaFloppyBlock.c\r
+\r
+Abstract:\r
+\r
+ ISA Floppy Driver\r
+ 1. Support two types diskette drive \r
+ 1.44M drive and 2.88M drive (and now only support 1.44M)\r
+ 2. Support two diskette drives\r
+ 3. Use DMA channel 2 to transfer data\r
+ 4. Do not use interrupt\r
+ 5. Support diskette change line signal and write protect\r
+ \r
+ Implement the Block IO interface\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+#include "IsaFloppy.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FdcReset (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+/*++\r
+ \r
+ Routine Description: Reset the Floppy Logic Drive, call the FddReset function \r
+ Parameters:\r
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface\r
+ ExtendedVerification BOOLEAN: Indicate that the driver may perform a more \r
+ exhaustive verification operation of the device during \r
+ reset, now this par is ignored in this driver \r
+ Returns:\r
+ EFI_SUCCESS: The Floppy Logic Drive is reset\r
+ EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly \r
+ and can not be reset\r
+\r
+--*/\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: This - add argument and description to function comment\r
+// GC_TODO: ExtendedVerification - add argument and description to function comment\r
+{\r
+ FDC_BLK_IO_DEV *FdcDev;\r
+\r
+ //\r
+ // Reset the Floppy Disk Controller\r
+ //\r
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
+\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA,\r
+ FdcDev->DevicePath\r
+ );\r
+\r
+ return FddReset (FdcDev);\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FddFlushBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This\r
+ )\r
+/*++\r
+ \r
+ Routine Description: \r
+ Parameters:\r
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface\r
+ Returns:\r
+ EFI_SUCCESS: \r
+\r
+--*/\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: This - add argument and description to function comment\r
+{\r
+ //\r
+ // Not supported yet\r
+ //\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+VOID\r
+FddReportStatus (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN BOOLEAN Read\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
+ Read - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ FDC_BLK_IO_DEV *FdcDev;\r
+\r
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
+\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_ERROR_CODE,\r
+ ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA,\r
+ FdcDev->DevicePath\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FddReadBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+ Routine Description: Read the requested number of blocks from the device \r
+ Parameters:\r
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface\r
+ MediaId UINT32: The media id that the read request is for \r
+ LBA EFI_LBA: The starting logic block address to read from on the device\r
+ BufferSize UINTN: The size of the Buffer in bytes\r
+ Buffer VOID *: A pointer to the destination buffer for the data\r
+ Returns:\r
+ EFI_SUCCESS: The data was read correctly from the device\r
+ EFI_DEVICE_ERROR:The device reported an error while attempting to perform\r
+ the read operation\r
+ EFI_NO_MEDIA: There is no media in the device\r
+ EFI_MEDIA_CHANGED: The MediaId is not for the current media\r
+ EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the \r
+ intrinsic block size of the device\r
+ EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment \r
+\r
+--*/\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: This - add argument and description to function comment\r
+// GC_TODO: MediaId - add argument and description to function comment\r
+// GC_TODO: LBA - add argument and description to function comment\r
+// GC_TODO: BufferSize - add argument and description to function comment\r
+// GC_TODO: Buffer - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, READ, Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FddReportStatus (This, TRUE);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+FddWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer\r
+ )\r
+/*++\r
+\r
+ Routine Description: Write a specified number of blocks to the device \r
+ Parameters:\r
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface\r
+ MediaId UINT32: The media id that the write request is for \r
+ LBA EFI_LBA: The starting logic block address to be written\r
+ BufferSize UINTN: The size in bytes in Buffer\r
+ Buffer VOID *: A pointer to the source buffer for the data\r
+ Returns :\r
+ EFI_SUCCESS: The data were written correctly to the device\r
+ EFI_WRITE_PROTECTED: The device can not be written to \r
+ EFI_NO_MEDIA: There is no media in the device\r
+ EFI_MEDIA_CHANGED: The MediaId is not for the current media\r
+ EFI_DEVICE_ERROR: The device reported an error while attempting to perform \r
+ the write operation \r
+ EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the \r
+ intrinsic block size of the device\r
+ EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid, \r
+ or the buffer is not on proper alignment \r
+\r
+--*/\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: This - add argument and description to function comment\r
+// GC_TODO: MediaId - add argument and description to function comment\r
+// GC_TODO: LBA - add argument and description to function comment\r
+// GC_TODO: BufferSize - add argument and description to function comment\r
+// GC_TODO: Buffer - add argument and description to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, WRITE, Buffer);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FddReportStatus (This, FALSE);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+FddReadWriteBlocks (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA LBA,\r
+ IN UINTN BufferSize,\r
+ IN BOOLEAN Operation,\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
+ MediaId - GC_TODO: add argument description\r
+ LBA - GC_TODO: add argument description\r
+ BufferSize - GC_TODO: add argument description\r
+ Operation - 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_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_NO_MEDIA - GC_TODO: Add description for return value\r
+ EFI_MEDIA_CHANGED - GC_TODO: Add description for return value\r
+ EFI_WRITE_PROTECTED - GC_TODO: Add description for return value\r
+ EFI_BAD_BUFFER_SIZE - 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_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
+\r
+--*/\r
+{\r
+ EFI_BLOCK_IO_MEDIA *Media;\r
+ FDC_BLK_IO_DEV *FdcDev;\r
+ UINTN BlockSize;\r
+ UINTN NumberOfBlocks;\r
+ UINTN BlockCount;\r
+ EFI_STATUS Status;\r
+ //\r
+ // EFI_STATUS CacheStatus;\r
+ //\r
+ EFI_LBA LBA0;\r
+ UINT8 *Pointer;\r
+\r
+ //\r
+ // Get the intrinsic block size\r
+ //\r
+ Media = This->Media;\r
+ BlockSize = Media->BlockSize;\r
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);\r
+\r
+ if (Operation == WRITE) {\r
+ if (LBA == 0) {\r
+ FdcFreeCache (FdcDev);\r
+ }\r
+ }\r
+ //\r
+ // Check the Parameter is valid\r
+ //\r
+ if (Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (BufferSize == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Set the drive motor on\r
+ //\r
+ Status = MotorOn (FdcDev);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Check to see if media can be detected\r
+ //\r
+ Status = DetectMedia (FdcDev);\r
+ if (EFI_ERROR (Status)) {\r
+ MotorOff (FdcDev);\r
+ FdcFreeCache (FdcDev);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Check to see if media is present\r
+ //\r
+ if (!(Media->MediaPresent)) {\r
+ MotorOff (FdcDev);\r
+ FdcFreeCache (FdcDev);\r
+\r
+ /*\r
+ if (FdcDev->Cache) {\r
+ gBS->FreePool (FdcDev->Cache);\r
+ FdcDev->Cache = NULL;\r
+ }\r
+*/\r
+ return EFI_NO_MEDIA;\r
+ }\r
+ //\r
+ // Check to see if media has been changed\r
+ //\r
+ if (MediaId != Media->MediaId) {\r
+ MotorOff (FdcDev);\r
+ FdcFreeCache (FdcDev);\r
+ return EFI_MEDIA_CHANGED;\r
+ }\r
+\r
+ if (Operation == WRITE) {\r
+ if (Media->ReadOnly) {\r
+ MotorOff (FdcDev);\r
+ return EFI_WRITE_PROTECTED;\r
+ }\r
+ }\r
+ //\r
+ // Check the parameters for this read/write operation\r
+ //\r
+ if (BufferSize % BlockSize != 0) {\r
+ MotorOff (FdcDev);\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ if (LBA > Media->LastBlock) {\r
+ MotorOff (FdcDev);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((BufferSize / BlockSize) + LBA - 1) > Media->LastBlock) {\r
+ MotorOff (FdcDev);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Operation == READ) {\r
+ //\r
+ // See if the data that is being read is already in the cache\r
+ //\r
+ if (FdcDev->Cache) {\r
+ if (LBA == 0 && BufferSize == BlockSize) {\r
+ MotorOff (FdcDev);\r
+ CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize);\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Set up Floppy Disk Controller\r
+ //\r
+ Status = Setup (FdcDev);\r
+ if (EFI_ERROR (Status)) {\r
+ MotorOff (FdcDev);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ NumberOfBlocks = BufferSize / BlockSize;\r
+ LBA0 = LBA;\r
+ Pointer = Buffer;\r
+\r
+ //\r
+ // read blocks in the same cylinder.\r
+ // in a cylinder , there are 18 * 2 = 36 blocks\r
+ //\r
+ BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);\r
+ while ((BlockCount != 0) && !EFI_ERROR (Status)) {\r
+ Status = ReadWriteDataSector (FdcDev, Buffer, LBA, BlockCount, Operation);\r
+ if (EFI_ERROR (Status)) {\r
+ MotorOff (FdcDev);\r
+ FddReset (FdcDev);\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ LBA += BlockCount;\r
+ NumberOfBlocks -= BlockCount;\r
+ Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize);\r
+ BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);\r
+ }\r
+\r
+ Buffer = Pointer;\r
+\r
+ //\r
+ // Turn the motor off\r
+ //\r
+ MotorOff (FdcDev);\r
+\r
+ if (Operation == READ) {\r
+ //\r
+ // Cache the data read\r
+ //\r
+ if (LBA0 == 0 && !FdcDev->Cache) {\r
+ FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+}\r
+\r
+VOID\r
+FdcFreeCache (\r
+ IN FDC_BLK_IO_DEV *FdcDev\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FdcDev - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ if (FdcDev->Cache) {\r
+ gBS->FreePool (FdcDev->Cache);\r
+ FdcDev->Cache = NULL;\r
+ }\r
+}\r