📄 atapiromi.cpp
字号:
//
// 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.
//
/*++
Module Name:
atapiRomi.cpp
based on atapipci.cpp
Abstract:
ATA/ATAPI for 2440 Ref Board.
Revision History:
--*/
#include "atapiRomi.h"
#include "atapiRomipm.h"
#include "Bsp_cfg.h"
#define Tacs 1
#define Tcos 3 // 2clk = 15.038ns
#define Tacc 5 // 6clk = 45.114ns
#define Tcoh 1 //
#define Tcah 1
#define Tacp 0
#define PMC 0
LONG CRomiDisk::m_lDeviceCount = 0;
static TCHAR *g_szPCICDRomDisk = TEXT("CD-ROM");
static TCHAR *g_szPCIHardDisk = TEXT("Hard Disk");
// ----------------------------------------------------------------------------
// Function: CreatePCIHD
// Spawn function called by IDE/ATA controller enumerator
//
// Parameters:
// hDevKey -
// ----------------------------------------------------------------------------
EXTERN_C
CDisk *
CreateRomi(
HKEY hDevKey
)
{
return new CRomiDisk(hDevKey);
}
// ----------------------------------------------------------------------------
// Function: CRomiDisk
// Constructor
//
// Parameters:
// hKey -
// ----------------------------------------------------------------------------
CRomiDisk::CRomiDisk(
HKEY hKey
) : CDisk(hKey)
{
m_pStartMemory = NULL;
m_pPort = NULL;
m_pPhysList = NULL;
m_pSGCopy = NULL;
m_pPFNs = NULL;
m_pPRDPhys = 0;
m_pPRD = NULL;
m_dwPhysCount = 0;
m_dwSGCount = 0;
m_dwPRDSize = 0;
m_pBMCommand = NULL;
InterlockedIncrement(&m_lDeviceCount);
DEBUGMSG(ZONE_INIT|ZONE_PCI, (_T(
"Atapi!CRomiDisk::CRomiDisk> device count(%d)\r\n"
), m_lDeviceCount));
}
// ----------------------------------------------------------------------------
// Function: ~CRomiDisk
// Destructor
//
// Parameters:
// None
// ----------------------------------------------------------------------------
CRomiDisk::~CRomiDisk(
)
{
FreeDMABuffers();
if ( m_vpIOPRegs )
{
VirtualFree((PVOID)m_vpIOPRegs, 0, MEM_RELEASE);
m_vpIOPRegs = NULL;
}
if ( m_vpMEMRegs)
{
VirtualFree((PVOID)m_vpMEMRegs, 0, MEM_RELEASE);
m_vpMEMRegs= NULL;
}
InterlockedDecrement(&m_lDeviceCount);
DEBUGMSG(ZONE_INIT|ZONE_PCI, (_T(
"Atapi!CRomiDisk::~CRomiDisk> device count(%d)\r\n"
), m_lDeviceCount));
}
// ----------------------------------------------------------------------------
// Function: FreeDMABuffers
// Deallocate DMA buffers
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CRomiDisk::FreeDMABuffers(
)
{
if (m_pPRD) {
FreePhysMem(m_pPRD);
m_pPRDPhys = NULL;
m_pPRD = NULL;
}
if (m_pPhysList) {
// free the fixed pages; the variable pages should already be free
for (DWORD i = 0; i < MIN_PHYS_PAGES; i++) {
FreePhysMem(m_pPhysList[i].pVirtualAddress);
}
VirtualFree(m_pPhysList, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
m_pPhysList = NULL;
}
if (m_pSGCopy) {
VirtualFree(m_pSGCopy, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
m_pSGCopy = NULL;
}
if (m_pPFNs) {
VirtualFree(m_pPFNs, UserKInfo[KINX_PAGESIZE], MEM_DECOMMIT);
m_pSGCopy = NULL;
}
VirtualFree(m_pStartMemory, 0, MEM_RELEASE);
m_pStartMemory = NULL;
m_dwPhysCount = 0;
m_dwSGCount = 0;
}
// ----------------------------------------------------------------------------
// Function: CopyDiskInfoFromPort
// This function is not used
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CRomiDisk::CopyDiskInfoFromPort(
)
{
ASSERT(m_pPort->m_dwRegBase != 0);
m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;
ASSERT(m_pPort->m_dwBMR != 0);
m_pBMCommand = (LPBYTE)m_pPort->m_dwBMR;
}
// ----------------------------------------------------------------------------
// Function: WaitForInterrupt
// Wait for interrupt
//
// Parameters:
// dwTimeOut -
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::WaitForInterrupt(
DWORD dwTimeOut
)
{
BYTE bStatus;
BOOL fRet = TRUE;
DWORD dwRet;
// wait for interrupt
dwRet = WaitForSingleObject(m_pPort->m_hIRQEvent, dwTimeOut);
if (dwRet == WAIT_TIMEOUT) {
fRet = FALSE;
}
else {
if (dwRet != WAIT_OBJECT_0) {
if (!WaitForDisc(WAIT_TYPE_DRQ, dwTimeOut, 10)) {
fRet = FALSE;
}
}
}
// read status; acknowledge interrupt
bStatus = GetBaseStatus();
if (bStatus & ATA_STATUS_ERROR) {
bStatus = GetError();
fRet = FALSE;
}
// signal interrupt done
InterruptDone(m_pPort->m_dwSysIntr);
return fRet;
}
// ----------------------------------------------------------------------------
// Function: EnableInterrupt
// Enable channel interrupt
//
// Parameters:
// None
// ----------------------------------------------------------------------------
void
CRomiDisk::EnableInterrupt(
)
{
GetBaseStatus(); // acknowledge interrupt, if pending
// signal interrupt done
InterruptDone(m_pPort->m_dwSysIntr);
}
// ----------------------------------------------------------------------------
// Function: ConfigureRegisterBlock
// This function is called by DSK_Init before any other CDisk function to
// set up the register block.
//
// Parameters:
// dwStride -
// ----------------------------------------------------------------------------
VOID
CRomiDisk::ConfigureRegisterBlock(
DWORD dwStride
)
{
m_dwStride = dwStride;
m_dwDataDrvCtrlOffset = ATA_REG_DATA * dwStride;
m_dwFeatureErrorOffset = ATA_REG_FEATURE * dwStride;
m_dwSectCntReasonOffset = ATA_REG_SECT_CNT * dwStride;
m_dwSectNumOffset = ATA_REG_SECT_NUM * dwStride;
m_dwByteCountLowOffset = ATA_REG_BYTECOUNTLOW * dwStride;
m_dwByteCountHighOffset = ATA_REG_BYTECOUNTHIGH * dwStride;
m_dwDrvHeadOffset = ATA_REG_DRV_HEAD * dwStride;
m_dwCommandStatusOffset = ATA_REG_COMMAND * dwStride;
// PCI ATA implementations don't assign I/O resources for the first four
// bytes, as they are unused
m_dwAltStatusOffset = 0x1C; //ATA_REG_ALT_STATUS * dwStride;
m_dwAltDrvCtrl = 0x1C; // ATA_REG_DRV_CTRL * dwStride;
}
// ----------------------------------------------------------------------------
// Function: Init
// Initialize channel
//
// Parameters:
// hActiveKey -
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::Init(
HKEY hActiveKey
)
{
BOOL bRet = FALSE;
m_f16Bit = TRUE; // PCI is 16-bit
// configure port
if (!ConfigPort()) {
DEBUGMSG(ZONE_INIT, (_T(
"Atapi!CRomiDisk::Init> Failed to configure port; device(%u)\r\n"
), m_dwDeviceId));
goto exit;
}
// assign the appropriate folder name
m_szDiskName = (IsCDRomDevice() ? g_szPCICDRomDisk : g_szPCIHardDisk);
// reserve memory for DMA buffers
m_pStartMemory = (LPBYTE)VirtualAlloc(NULL, 0x10000, MEM_RESERVE, PAGE_READWRITE);
if (!m_pStartMemory) {
bRet = FALSE;
}
// finish intialization; i.e., initialize device
bRet = CDisk::Init(hActiveKey);
if (!bRet) {
goto exit;
}
exit:;
return bRet;
}
// ----------------------------------------------------------------------------
// Function: MainIoctl
// This is redundant
//
// Parameters:
// pIOReq -
// ----------------------------------------------------------------------------
DWORD
CRomiDisk::MainIoctl(
PIOREQ pIOReq
)
{
DEBUGMSG(ZONE_IOCTL, (_T(
"Atapi!CRomiDisk::MainIoctl> IOCTL(%d), device(%d) \r\n"
), pIOReq->dwCode, m_dwDeviceId));
return CDisk::MainIoctl(pIOReq);
}
// ----------------------------------------------------------------------------
// Function: ConfigPort
// Initialize IST/ISR
//
// Parameters:
// None
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::ConfigPort(
)
{
// int i;
int RetValue=TRUE;
DWORD dwCleanUp = 0; // track progress for undo on clean up
m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;
m_pBMCommand = (PBYTE)m_pPort->m_dwBMR;
m_vpIOPRegs = (S3C2440A_IOPORT_REG*)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);
if (m_vpIOPRegs == NULL)
{
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpIOPRegs is not allocated\n\r")));
RetValue = FALSE;
}
if (!VirtualCopy((PVOID)m_vpIOPRegs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpIOPRegs is not mapped\n\r")));
RetValue = FALSE;
}
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpIOPRegs is mapped to %x\n\r"), m_vpIOPRegs));
m_vpMEMRegs = (S3C2440A_MEMCTRL_REG*)VirtualAlloc(0,sizeof(S3C2440A_MEMCTRL_REG), MEM_RESERVE,PAGE_NOACCESS);
if(m_vpMEMRegs == NULL)
{
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpMEMRegs is not allocated\n\r")));
RetValue = FALSE;
}
if(!VirtualCopy((PVOID)m_vpMEMRegs,(PVOID)(S3C2440A_BASE_REG_PA_MEMCTRL >> 8),sizeof(S3C2440A_MEMCTRL_REG), PAGE_PHYSICAL|PAGE_READWRITE|PAGE_NOCACHE)) {
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpMEMRegs is not mapped\n\r")));
RetValue = FALSE;
}
DEBUGMSG (1,(TEXT("+++ Atapi!CRomiDisk::ConfigPort : m_vpMEMRegs is mapped to %x\n\r"), m_vpMEMRegs));
//jungpil GPGCON setting should come before power-on
// no reason found...
m_vpIOPRegs->GPGCON = (m_vpIOPRegs->GPGCON&~(0x3<<24))|(2<<24); // EINT20
m_vpIOPRegs->GPGUP = m_vpIOPRegs->GPGUP & ~(0x1000) | 0x1000; //GPG12 Pull Up Disable(1)
m_vpIOPRegs->EXTINT2 = (m_vpIOPRegs->EXTINT2 & ~(7<<16)) | 0x4<<16; //EINT20 raising 10x falling 01x high 1 low 0 both 11x
//power on
m_vpIOPRegs->GPGCON = (m_vpIOPRegs->GPGCON&~(0x3<<6))|(1<<6); // GPG3 output
m_vpIOPRegs->GPGDAT &=~(1<<3); // off
// Sleep(1000);
Sleep(20);
m_vpIOPRegs->GPGDAT |=(1<<3); //on
Sleep(100);
// hw reset.. not requird now.
/* m_vpIOPRegs->GPGCON = (m_vpIOPRegs->GPGCON & ~(0x3<<22)) | (0x2<<22);
m_vpIOPRegs->GPGDAT &= ~(1<<11);
Sleep(1000);
m_vpIOPRegs->GPGDAT |= (1<<11);
Sleep(1000);
m_vpIOPRegs->GPGDAT &= ~(1<<11);
Sleep(1000);*/
// nGCS5=nWAIT,16-bit
m_vpMEMRegs->BWSCON = (m_vpMEMRegs->BWSCON & ~(0xf<<20)) |(0<<23)|(1<<22)|(1<<20);
// BANK5 access timing
m_vpMEMRegs->BANKCON5 = (Tacs<<13) | (Tcos<<11) | (Tacc<<8) | (Tcoh<<6) | (Tcah<<4) | (Tacp<<2) | PMC;
// this function is called for the master and slave on this channel; if
// this has already been called, then exit
if (m_pPort->m_hIRQEvent) {
m_dwDeviceFlags |= DFLAGS_DEVICE_INITIALIZED;
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T("atapiRomi already initialized\n")));
return TRUE;
}
// create interrupt event
if (NULL == (m_pPort->m_hIRQEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CRomiDisk::ConfigPort> Failed to create interrupt event for device(%d)\r\n"
), m_dwDeviceId));
return FALSE;
}
// associate interrupt event with IRQ
if (!InterruptInitialize(
m_pPort->m_dwSysIntr,
m_pPort->m_hIRQEvent,
NULL,
0)
) {
DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
"Atapi!CRomiDisk::ConfigPort> Failed to initialize interrupt(SysIntr(%d)) for device(%d)\r\n"
), m_pPort->m_dwSysIntr, m_dwDeviceId));
return FALSE;
}
WriteAltDriveController(0);// interrupt enabled
/*if(RetValue == TRUE && GetAltStatus() == 0x50)
RETAILMSG(1,(TEXT("atapiRomi : CF HDD initialized Successfully\r\n")));
else
RETAILMSG(1,(TEXT("atapiRomi : CF HDD initialization failed\r\n")));*/
return RetValue;
}
// ----------------------------------------------------------------------------
// Function: TranslateAddress
// Translate a system address to a bus address for the DMA controller
//
// Parameters:
// pdwAddr -
// ----------------------------------------------------------------------------
BOOL
CRomiDisk::TranslateAddress(
PDWORD pdwAddr
)
{
// translate a system address to a bus address for the DMA bus controller
PHYSICAL_ADDRESS SystemLogicalAddress, TransLogicalAddress;
DWORD dwBus;
// fetch bus number/type
// if (m_pPort->m_pCNTRL != NULL) {
// dwBus = m_pPort->m_pCNTRL->m_dwBus;
// }
// else {
// dwBus = 0;
// }
dwBus = m_pPort->m_pController->m_dwi.dwBusNumber;
// translate address
SystemLogicalAddress.HighPart = 0;
SystemLogicalAddress.LowPart = *pdwAddr;
if (!HalTranslateSystemAddress(PCIBus, dwBus, SystemLogicalAddress, &TransLogicalAddress)) {
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -