📄 ide.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name: ide.c
Abstract: Boot loader IDE/ATA access functions.
Functions:
ide_reset - Reset IDE drive.
id_drive - Locate/identify drive.
lba_to_pchs - Convert LBA address to Physical CHS.
read_sector - Read the contents of a disk sector.
init_ide - Initialize IDE drive.
load_image_ide - Load OS image from drive.
OEMHDDPlatformInit - Blcommon interface functions.
OEMHDDPreDownload - "
OEMHDDReadData - "
OEMHDDLaunch - "
Notes:
Assumptions:
- only primary master drive is supported
- FAT16
- file op routines only work on a single file at a time
- kernel image is in the root directory with the bootloader image
--*/
#include <windows.h>
#include <memorymap.h>
#include <blcommon.h>
#include <halether.h>
#include <debugtimer.h>
#include <atapi2.h>
#include "eboot.h"
#include "hwdefs.h"
#include "ide.h"
#include "fat.h"
extern void EdbgDumpHexBuf(PUCHAR pBuf, DWORD Count);
int m_BootDeviceType =0;
static BOOL m_f16Bit=TRUE;
static BOOL m_fLBAMode=TRUE;
static IDENTIFY_DATA m_Id;
static int m_bSectorsPerBlock=1;
static int m_dwDevice =0;
#define ZONE_INFO 1
#define SERPRINT EdbgOutputDebugString
// This data supplements the BPB information - used to save time.
extern t_FAT_PARMS g_FATParms;
// Global variables.
//
//UCHAR g_bsect[SECTOR_SIZE];
ULONG g_sectorsread=0;
UCHAR g_bstartcounting=0;
//STATUSBAR g_statbar;
// Function prototypes.
//
//int create_statusbar(PSTATUSBAR pbar, ULONG sval, ULONG eval);
//int update_statusbar(PSTATUSBAR pbar, ULONG cval);
//BOOL InitNIC(void);
// Externs.
//
extern FILEINFO g_fileinfo;
extern BOOLEAN ReadSectors(UCHAR Drive, ULONG LBA, USHORT nSectors, PUCHAR pBuffer);
ULONG ATAReadRegister(ULONG ulRegister)
{
switch(m_BootDeviceType)
{
case BOOT_FROM_PCMCIA:
return *(volatile UCHAR *)(PCMCIACARD_IO + (ulRegister>>2));
break;
case BOOT_FROM_IDE_ATADISK:
case BOOT_FROM_IDE_CDROM:
{
ULONG uiValue;
register ULONG ulControl;
*IDE_CTRL = ulControl = IDE_CTRL_DIOR | IDE_CTRL_DIOW | ulRegister;
*IDE_CTRL = ulControl &= ~IDE_CTRL_DIOR;
*IDE_CTRL = ulControl |= IDE_CTRL_DIOR;
uiValue = *IDE_DATAIN;
if(ulRegister == CSDA_DATA_REG)
{
return(uiValue & 0xFFFF);
}
else
{
return(uiValue & 0xFF);
}
}
break;
}
return 0;
}
void ATAWriteRegister(ULONG ulRegister, UINT uiData)
{
switch(m_BootDeviceType)
{
case BOOT_FROM_PCMCIA:
*(volatile UCHAR *)(PCMCIACARD_IO + (ulRegister>>2)) = (BYTE)uiData;
break;
case BOOT_FROM_IDE_CDROM:
case BOOT_FROM_IDE_ATADISK:
{
register ULONG ulControl;
*IDE_CTRL = ulControl = IDE_CTRL_DIOR | IDE_CTRL_DIOW | ulRegister;
*IDE_DATAOUT = uiData;
*IDE_CTRL = ulControl &= ~IDE_CTRL_DIOW;
*IDE_CTRL = ulControl |= IDE_CTRL_DIOW;
}
break;
}
}
BYTE GetBaseStatus()
{
if(m_BootDeviceType == BOOT_FROM_PCMCIA)
return *(volatile UCHAR *)(PCMCIACARD_IO + IDE_STAT_REG);
else
return (BYTE) (ATAReadRegister(CSDA_STAT_REG) & 0xFF);
}
BYTE GetAltStatus()
{
if(m_BootDeviceType == BOOT_FROM_PCMCIA)
return *(volatile UCHAR *)(PCMCIACARD_IO + IDE_ALT_CTRL_REG);
else
return (BYTE) (ATAReadRegister(CSDA_ALT_STAT_REG) & 0xFF);
}
void WriteAltDriveController(BYTE bData)
{
if(m_BootDeviceType == BOOT_FROM_PCMCIA)
*(volatile UCHAR *)(PCMCIACARD_IO + IDE_ALT_CTRL_REG) = (BYTE)bData;
else
ATAWriteRegister(CSDA_ALT_CTRL_REG, (ULONG) bData);
}
void SetDriveHead(BYTE bDriveHead)
{
ATAWriteRegister(CSDA_DRVHD_REG, (ULONG) bDriveHead);
}
BYTE GetReason()
{
return (BYTE) (ATAReadRegister(CSDA_REASON_REG) & 0xFF);
}
BYTE GetError()
{
return (BYTE) (ATAReadRegister(CSDA_ERROR_REG) & 0xFF);
}
void SelectDevice()
{
ATAWriteRegister(CSDA_DRVHD_REG, (m_dwDevice == 0 ) ? ATA_HEAD_DRIVE_1 : ATA_HEAD_DRIVE_2);
}
void WriteCommand(BYTE bCommand)
{
ATAWriteRegister(CSDA_CMD_REG, (ULONG) bCommand);
}
void WriteFeature(BYTE bFeature)
{
ATAWriteRegister(CSDA_FEATURE_REG, (ULONG) bFeature);
}
void WriteSectorCount(BYTE bValue)
{
ATAWriteRegister(CSDA_SECTCNT_REG, (ULONG) bValue);
}
void WriteDriveHeadReg(BYTE bValue)
{
ATAWriteRegister(CSDA_DRVHD_REG, (ULONG) bValue);
}
void WriteSectorNumber(BYTE bValue)
{
ATAWriteRegister(CSDA_SECTNUM_REG, (ULONG) bValue);
}
///void WriteDriveController(BYTE bData)
///{
/// ATAWriteRegister(CSDA_ALT_CTRL_REG, (ULONG) bData);
///}
void WriteLowCount(BYTE bValue)
{
ATAWriteRegister(CSDA_CYLL_REG, (ULONG) bValue);
}
void WriteHighCount(BYTE bValue)
{
ATAWriteRegister(CSDA_CYLH_REG, (ULONG) bValue);
}
void ReadWordBuffer( PWORD pBuffer, DWORD dwCount)
{
PWORD pEnd;
pEnd = pBuffer + dwCount;
if(m_BootDeviceType == BOOT_FROM_PCMCIA)
{
while(pBuffer < pEnd)
{
*pBuffer++ = *(volatile USHORT *)(PCMCIACARD_IO + IDE_DATA_REG);
}
}
else
{
while(pBuffer < pEnd)
{
*pBuffer++ = (WORD)(ATAReadRegister(CSDA_DATA_REG) & 0xFFFF);
}
}
}
void ReadByteBuffer( PBYTE pBuffer, DWORD dwCount)
{
DWORD dwIndex;
for(dwIndex = 0 ; dwIndex < dwCount ; dwIndex++)
{
pBuffer[dwIndex] = (BYTE)(ATAReadRegister(CSDA_DATA_REG) & 0xFF);
}
}
WORD ReadWord()
{
if(m_BootDeviceType == BOOT_FROM_PCMCIA)
return *(volatile USHORT *)(PCMCIACARD_IO + IDE_DATA_REG);
else
return ((WORD)(ATAReadRegister(CSDA_DATA_REG) & 0xFFFF));
}
WORD ReadByte()
{
return ((BYTE)(ATAReadRegister(CSDA_DATA_REG) & 0xFF));
}
BOOL WaitForDisc_P(BYTE bStatusType, DWORD dwTimeOut,DWORD dwPeriod)
{
BYTE bStatusRead;
bStatusRead = 0;
if (dwPeriod == 0)
dwPeriod = dwTimeOut;
while( TRUE)
{
bStatusRead = GetAltStatus();
switch (bStatusType) {
case WAIT_TYPE_BUSY:
if (bStatusRead & ATA_STATUS_BUSY)
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_BUSY\r\n")));
goto ExitDone;
}
break;
case WAIT_TYPE_NOT_BUSY:
if (!(bStatusRead & ATA_STATUS_BUSY))
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_NOT_BUSY\r\n")));
goto ExitDone;
}
break;
case WAIT_TYPE_READY:
if (bStatusRead & ATA_STATUS_READY)
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_READY\r\n")));
// DelayInuSec(100);
goto ExitDone;
}
break;
case WAIT_TYPE_DRQ:
if (bStatusRead & ATA_STATUS_DATA_REQ)
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_DRQ\r\n")));
goto ExitDone;
}
break;
case WAIT_TYPE_NOT_DRQ:
if (!(bStatusRead & ATA_STATUS_DATA_REQ))
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_NOT_DRQ\r\n")));
goto ExitDone;
}
break;
case WAIT_TYPE_ERROR:
if (bStatusRead & ATA_STATUS_ERROR)
{
// DEBUGMSG(ZONE_IO, (TEXT("ATAPI:WaitForDisc - WAIT_TYPE_ERROR\r\n")));
goto ExitDone;
}
break;
}
if ((int)dwTimeOut > 0)
{
DelayInuSec(dwPeriod);
dwTimeOut -= dwPeriod;
}
else
{
// DEBUGMSG(ZONE_ERROR, (TEXT("ATAPI:WaitForDisc - TimeOut !!! WaitType = %ld Status=%02X\r\n"), bStatusType, bStatusRead));
return ERROR_GEN_FAILURE;
}
}
ExitDone:
return ERROR_SUCCESS;
}
BOOL WaitForDisc(BYTE bStatusType, DWORD dwTimeOut)
{
DWORD dwPeriod =0;
return WaitForDisc_P(bStatusType, dwTimeOut, dwPeriod);
}
void ide_enable()
{
SERPRINT("Enable IDE controller\r\n");
*IDE_CFG = 0;
//
// Initialize the IDE interface to PIO mode 4.
//
*IDE_CFG = IDE_CFG_IDEEN | IDE_CFG_PIOEN | IDE_CFG_PIO4 | (1 <<IDE_CFG_WST_SHIFT);
*IDE_CTRL = IDE_CTRL_DIOR | IDE_CTRL_DIOW | CSDA_DATA_REG;
//
// Make sure that MDMA and UDMA are disabled.
//
*IDE_MDMAOP = 0;
*IDE_UDMAOP = 0;
// SelectDevice();
// WriteDriveController( ATA_CTRL_ENABLE_INTR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -