⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atapiromi.cpp

📁 三星ARM9系列CPU S3C2440A的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 + -