ata.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,343 行 · 第 1/5 页
C
2,343 行
/*++
Copyright (c) 2004 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ata.c
Abstract:
Revision History
2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
update - ATAIdentity() func
update - AtaBlockIoReadBlocks() func
update - AtaBlockIoWriteBlocks() func
add - AtaAtapi6Identify() func
add - AtaReadSectorsExt() func
add - AtaWriteSectorsExt() func
add - AtaPioDataInExt() func
add - AtaPioDataOutExt() func
--*/
#include "idebus.h"
STATIC
EFI_STATUS
AtaAtapi6Identify (
IN IDE_BLK_IO_DEV *IdeDev
);
STATIC
VOID
AtaSMARTSupport (
IN IDE_BLK_IO_DEV *IdeDev
);
EFI_STATUS
AtaReadSectorsExt (
IN IDE_BLK_IO_DEV *IdeDev,
IN OUT VOID *DataBuffer,
IN EFI_LBA StartLba,
IN UINTN NumberOfBlocks
);
EFI_STATUS
AtaWriteSectorsExt (
IN IDE_BLK_IO_DEV *IdeDev,
IN VOID *DataBuffer,
IN EFI_LBA StartLba,
IN UINTN NumberOfBlocks
);
EFI_STATUS
AtaPioDataInExt (
IN IDE_BLK_IO_DEV *IdeDev,
IN OUT VOID *Buffer,
IN UINT32 ByteCount,
IN UINT8 AtaCommand,
IN EFI_LBA StartLba,
IN UINT16 SectorCount
);
EFI_STATUS
AtaPioDataOutExt (
IN IDE_BLK_IO_DEV *IdeDev,
IN VOID *Buffer,
IN UINT32 ByteCount,
IN UINT8 AtaCommand,
IN EFI_LBA StartLba,
IN UINT16 SectorCount
);
EFI_STATUS
ATAIdentify (
IN IDE_BLK_IO_DEV *IdeDev
)
/*++
Name:
ATAIdentify
Purpose:
This function is called by DiscoverIdeDevice() during its device
identification. It sends out the ATA Identify Command to the
specified device. Only ATA device responses to this command. If
the command succeeds, it returns the Identify data structure which
contains information about the device. This function extracts the
information it needs to fill the IDE_BLK_IO_DEV data structure,
including device type, media block size, media capacity, and etc.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure,used
to record all the information of the IDE device.
Returns:
EFI_SUCCESS
Identify ATA device successfully.
EFI_DEVICE_ERROR
ATA Identify Device Command failed or device is not
ATA device.
Notes:
parameter IdeDev will be updated in this function.
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
{
EFI_STATUS Status;
EFI_IDENTIFY_DATA *AtaIdentifyPointer;
UINT32 Capacity;
UINT8 DeviceSelect;
//
// AtaIdentifyPointer is used for accommodating returned IDENTIFY data of
// the ATA Identify command
//
AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) EfiLibAllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));
//
// use ATA PIO Data In protocol to send ATA Identify command
// and receive data from device
//
DeviceSelect = 0;
DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
Status = AtaPioDataIn (
IdeDev,
(VOID *) AtaIdentifyPointer,
sizeof (EFI_IDENTIFY_DATA),
IDENTIFY_DRIVE_CMD,
DeviceSelect,
0,
0,
0,
0
);
//
// If ATA Identify command succeeds, then according to the received
// IDENTIFY data,
// identify the device type ( ATA or not ).
// If ATA device, fill the information in IdeDev.
// If not ATA device, return IDE_DEVICE_ERROR
//
if (!EFI_ERROR (Status)) {
IdeDev->pIdData = AtaIdentifyPointer;
//
// Print ATA Module Name
//
PrintAtaModuleName (IdeDev);
//
// bit 15 of pAtaIdentify->config is used to identify whether device is
// ATA device or ATAPI device.
// if 0, means ATA device; if 1, means ATAPI device.
//
if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {
//
// Detect if support S.M.A.R.T. If yes, enable it as default
//
AtaSMARTSupport (IdeDev);
//
// Check whether this device needs 48-bit addressing (ATAPI-6 ata device)
//
Status = AtaAtapi6Identify (IdeDev);
if (!EFI_ERROR (Status)) {
//
// It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()
//
return EFI_SUCCESS;
}
//
// This is a hard disk <= 120GB capacity, treat it as normal hard disk
//
IdeDev->Type = IdeHardDisk;
//
// Block Media Information:
// Media->LogicalPartition , Media->WriteCaching will be filled
// in the DiscoverIdeDevcie() function.
//
IdeDev->BlkIo.Media->IoAlign = 4;
IdeDev->BlkIo.Media->MediaId = 1;
IdeDev->BlkIo.Media->RemovableMedia = FALSE;
IdeDev->BlkIo.Media->MediaPresent = TRUE;
IdeDev->BlkIo.Media->ReadOnly = FALSE;
IdeDev->BlkIo.Media->BlockSize = 0x200;
//
// Calculate device capacity
//
Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |
AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;
IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
return EFI_SUCCESS;
}
}
gBS->FreePool (AtaIdentifyPointer);
//
// Make sure the pIdData will not be freed again.
//
IdeDev->pIdData = NULL;
return EFI_DEVICE_ERROR;
}
STATIC
EFI_STATUS
AtaAtapi6Identify (
IN IDE_BLK_IO_DEV *IdeDev
)
/*++
Name:
AtaAtapi6Identify
Purpose:
This function is called by ATAIdentify() to identity whether this disk
supports ATA/ATAPI6 48bit addressing, ie support >120G capacity
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
Returns:
EFI_SUCCESS - The disk specified by IdeDev is a Atapi6 supported one
and 48-bit addressing must be used
EFI_UNSUPPORTED - The disk dosn't not support Atapi6 or it supports but
the capacity is below 120G, 48bit addressing is not
needed
Notes:
This function must be called after DEVICE_IDENTITY command has been
successfully returned
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
{
UINT8 Index;
EFI_LBA TmpLba;
EFI_LBA Capacity;
EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;
if (IdeDev->pIdData == NULL) {
return EFI_UNSUPPORTED;
}
Atapi6IdentifyStruct = IdeDev->pIdData;
if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & bit10) == 0) {
//
// The device dosn't support 48 bit addressing
//
return EFI_UNSUPPORTED;
}
//
// 48 bit address feature set is supported, get maximum capacity
//
Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0];
for (Index = 1; Index < 4; Index++) {
//
// Lower byte goes first: word[100] is the lowest word, word[103] is highest
//
TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index];
Capacity |= LShiftU64 (TmpLba, 16 * Index);
}
if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
//
// Capacity exceeds 120GB. 48-bit addressing is really needed
//
IdeDev->Type = Ide48bitAddressingHardDisk;
//
// Fill block media information:Media->LogicalPartition ,
// Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.
//
IdeDev->BlkIo.Media->IoAlign = 4;
IdeDev->BlkIo.Media->MediaId = 1;
IdeDev->BlkIo.Media->RemovableMedia = FALSE;
IdeDev->BlkIo.Media->MediaPresent = TRUE;
IdeDev->BlkIo.Media->ReadOnly = FALSE;
IdeDev->BlkIo.Media->BlockSize = 0x200;
IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
return EFI_SUCCESS;
}
return EFI_UNSUPPORTED;
}
VOID
PrintAtaModuleName (
IN IDE_BLK_IO_DEV *IdeDev
)
/*++
Name:
PrintAtaModuleName
Purpose:
This function is called by ATAIdentify() or ATAPIIdentify()
to print device's module name.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
Returns:
no returns.
Notes:
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
{
if (IdeDev->pIdData == NULL) {
return ;
}
SwapStringChars (IdeDev->ModelName, IdeDev->pIdData->AtaData.ModelName, 40);
IdeDev->ModelName[40] = 0x00;
}
EFI_STATUS
AtaPioDataIn (
IN IDE_BLK_IO_DEV *IdeDev,
IN VOID *Buffer,
IN UINT32 ByteCount,
IN UINT8 AtaCommand,
IN UINT8 Head,
IN UINT8 SectorCount,
IN UINT8 SectorNumber,
IN UINT8 CylinderLsb,
IN UINT8 CylinderMsb
)
/*++
Name:
AtaPioDataIn
Purpose:
This function is used to send out ATA commands conforms to the
PIO Data In Protocol.
Parameters:
IDE_BLK_IO_DEV IN *IdeDev
pointer pointing to IDE_BLK_IO_DEV data structure, used
to record all the information of the IDE device.
VOID IN *Buffer
buffer contained data transferred from device to host.
UINT32 IN ByteCount
data size in byte unit of the buffer.
UINT8 IN AtaCommand
value of the Command Register
UINT8 IN Head
value of the Head/Device Register
UINT8 IN SectorCount
value of the Sector Count Register
UINT8 IN SectorNumber
value of the Sector Number Register
UINT8 IN CylinderLsb
value of the low byte of the Cylinder Register
UINT8 IN CylinderMsb
value of the high byte of the Cylinder Register
Returns:
EFI_SUCCESS
send out the ATA command and device send required
data successfully.
EFI_DEVICE_ERROR
command sent failed.
Notes:
--*/
// TODO: function comment is missing 'Routine Description:'
// TODO: function comment is missing 'Arguments:'
// TODO: IdeDev - add argument and description to function comment
// TODO: Buffer - add argument and description to function comment
// TODO: ByteCount - add argument and description to function comment
// TODO: AtaCommand - add argument and description to function comment
// TODO: Head - add argument and description to function comment
// TODO: SectorCount - add argument and description to function comment
// TODO: SectorNumber - add argument and description to function comment
// TODO: CylinderLsb - add argument and description to function comment
// TODO: CylinderMsb - add argument and description to function comment
{
UINTN WordCount;
UINTN Increment;
UINT16 *Buffer16;
EFI_STATUS Status;
Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
//
// e0:1110,0000-- bit7 and bit5 are reserved bits.
// bit6 set means LBA mode
//
IDEWritePortB (
IdeDev->PciIo,
IdeDev->IoPort->Head,
(UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)
);
//
// All ATAPI device's ATA commands can be issued regardless of the
// state of the DRDY
//
if (IdeDev->Type == IdeHardDisk) {
Status = DRDYReady (IdeDev, ATATIMEOUT);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
}
//
// set all the command parameters
// Before write to all the following registers, BSY and DRQ must be 0.
//
Status = DRQClear2 (IdeDev, ATATIMEOUT);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
if (AtaCommand == SET_FEATURES_CMD) {
IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?