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

📄 atamx31.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//     pIOReq -
// ----------------------------------------------------------------------------

DWORD
CMX31Disk::MainIoctl(
    PIOREQ pIOReq
    )
{
    DEBUGMSG(ZONE_FUNC, (_T(
        "Ata!CMX31Disk::MainIoctl> IOCTL(%d), device(%d) \r\n"
        ), pIOReq->dwCode, m_dwDeviceId));

    return CDisk::MainIoctl(pIOReq);
}

// ----------------------------------------------------------------------------
// Function: ConfigPort
//     Initialize IST/ISR
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CMX31Disk::ConfigPort(
    )
{
    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: ConfigPort+")));

    m_pATAReg = (PBYTE)m_pPort->m_dwRegBase;
    m_pATARegAlt = (PBYTE)m_pPort->m_dwRegAlt;

    if(!InitializePort()) 
    {
        return FALSE;
    }

    // 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;
        return TRUE;
    }

    // create interrupt event
    if (NULL == (m_pPort->m_hIRQEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!CMX31Disk::ConfigPort> Failed to create interrupt event for device(%d)\r\n"
            ), m_dwDeviceId));
        return FALSE;
    }

    // Translate IRQ to SYSINTR
    if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &(m_pPort->m_dwIrq), 
            sizeof(m_pPort->m_dwIrq), &m_pPort->m_dwSysIntr, 
            sizeof(m_pPort->m_dwSysIntr), NULL))
    {
        ERRORMSG(1,(TEXT("%s: Request SYSINTR failed\r\n"), __WFUNCTION__));
        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(
            "Ata!CMX31Disk::ConfigPort> Failed to initialize interrupt(SysIntr(%d)) for device(%d)\r\n"
            ), m_pPort->m_dwSysIntr, m_dwDeviceId));
        return FALSE;
    }

    // c=Create interrupt wait event
    if (NULL == (m_pPort->m_hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL))) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!CMX31Disk::ConfigPort> Failed to create interrupt wait event for device(%d)\r\n"
            ), m_dwDeviceId));
        return FALSE;
    }

    // Create IST for ATA interrupts
    m_pPort->m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) IntrServThread, m_pPort, 0, NULL);      
    if (!m_pPort->m_hThread) 
    {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Ata!CMX31Disk::ConfigPort> Failed to create IST for device(%d)\r\n"
            ), m_dwDeviceId));
        return FALSE;
    }

    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: ConfigPort-")));
    return TRUE;
}

/* SetTimingRegisters() programs host timing. "speed" is the ATA mode programmed,
   mode can be PIO_MODE, UDMA_MODE or MDMA_MODE, ClkSpd is the clock period in
   ns */
void CMX31Disk::SetTimingRegisters(int speed, int mode, int ClkSpd)
{
    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: SetTimingRegisters+(%d,%d,%d)+"), speed,mode,ClkSpd));
    INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG0, 0x0000ffff, 0x00000303);
    switch(mode)
    {
        case PIO_MODE:
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG0, 0xffff0000,
                (((t1_spec[speed] + ClkSpd) / ClkSpd) << 16) |
                (((t2_8spec[speed] + ClkSpd) / ClkSpd) << 24)) ;
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG1, 0xffffffff,
                (((t2_8spec[speed] + ClkSpd) / ClkSpd) ) |
                ((((tA_spec[speed] + ClkSpd) / ClkSpd) + 2) << 8) |
                (1 << 16) |
                (((t4_spec[speed] + ClkSpd) / ClkSpd) << 24)) ;
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG2, 0xff, (((t9_spec[speed] + ClkSpd) / ClkSpd)));
            break ;
        case MDMA_MODE :
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG2, 0xffffff00,
                (((tM_spec[speed] + ClkSpd) / ClkSpd) << 8) |
                (((tJNH_spec[speed] + ClkSpd) / ClkSpd) << 16) |
                    (((tD_spec[speed] + ClkSpd) / ClkSpd) << 24)) ;
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG3, 0xff, (((tKW_spec[speed] + ClkSpd) / ClkSpd))) ;
            break ;
        case UDMA_MODE :
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG3, 0xffffff00,
                (((tACK_spec[speed] + ClkSpd) / ClkSpd) << 8) |
                (((tENV_minspec[speed] + ClkSpd) / ClkSpd) << 16) |
                ((((tRP_spec[speed] + ClkSpd) / ClkSpd) + 2) << 24)) ;
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG4, 0xffffffff,
                (((tZAH_spec[speed] + ClkSpd) / ClkSpd)) |
                (((tMLI_spec[speed] + ClkSpd) / ClkSpd) << 8) |
                (((tDVH_spec[speed] + ClkSpd) / ClkSpd) << 16) |
                (((tDZFS_spec[speed] + ClkSpd) / ClkSpd) << 24)) ;
            INSREG32(&g_pVAtaReg->ATA_TIME_CONFIG5, 0xffffffff,
                (((tCYC_spec[speed] + ClkSpd) / ClkSpd)) << 24 |
                (((tDVS_spec[speed] + ClkSpd) / ClkSpd)) |
                (((tCVH_spec[speed] + ClkSpd) / ClkSpd) << 8) |
                (((tSS_spec[speed] + ClkSpd) / ClkSpd) << 16)) ;
            break ;
        default :
            break;
    }
    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: SetTimingRegisters-")));
}


// ----------------------------------------------------------------------------
// Function: InitializePort
//     Initialize ATA Port
//
// Parameters:
//     None
// Returns:
//      Returns TRUE if successful, otherwise returns FALSE.
// ----------------------------------------------------------------------------
BOOL CMX31Disk::InitializePort(void)
{
    PHYSICAL_ADDRESS phyAddr;
    BOOL bRet = FALSE;

    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: InitializePort+")));
    if(g_pVAtaReg == NULL)
    {

		// Call the BSP function to map the PBC registers
		if(!BSPATApbcmapping(&phyAddr))
		{
            DEBUGMSG(ZONE_ERROR, (TEXT("CMX31Disk::InitializePort PCSP_PBC_REGS MmMapIoSpace failed!\r\n")));
			goto exit;

		}

        phyAddr.QuadPart = CSP_BASE_REG_PA_ATA_CTRL;
        g_pVAtaReg = (PCSP_ATA_REG) MmMapIoSpace(phyAddr, sizeof(CSP_ATA_REG), FALSE);

        // Check if virtual mapping failed
        if (g_pVAtaReg == NULL)
        {
            DEBUGMSG(ZONE_ERROR, (TEXT("CMX31Disk: MmMapIoSpace failed!\r\n")));
            goto exit;
        }

        m_pATAReg = (PBYTE) (g_pVAtaReg);
        m_pATARegAlt = (PBYTE) (g_pVAtaReg);

        ConfigureRegisterBlock(4);
        
        // Enabling ATA Clock
        if (!BSPATAEnableClock(TRUE))
        {
            DEBUGMSG(ZONE_FUNC, (TEXT("BSPATAEnableClock(): ATA Clock cannot be enabled! \r\n")));
            return FALSE;
        }
        
		// BSPATAIOMUXConfig configure the available IOMUX settings 
        BSPATAIOMUXConfig();
        
        SetTimingRegisters(0, PIO_MODE, CLOCK_PERIOD);
        SetTimingRegisters(0, MDMA_MODE, CLOCK_PERIOD);
        SetTimingRegisters(0, UDMA_MODE, CLOCK_PERIOD);

        OUTREG8(&g_pVAtaReg->ATAControl, 0x00);
        Sleep(20);
        OUTREG8(&g_pVAtaReg->ATAControl, 0x40);
        Sleep(20);
    }
    bRet = TRUE;

exit:;
    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk: InitializePort-")));
    return bRet;
}

// ----------------------------------------------------------------------------
// Function: ShowRegisters
//     Print current ATA registers
//
// Parameters:
//     None
// Returns:
//     None
// ----------------------------------------------------------------------------
void CMX31Disk::ShowRegisters(UCHAR usel)
{
    if(usel & 0x01)
    {
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG0 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG0, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG0)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG1 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG1, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG1)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG2 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG2, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG2)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG3 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG3, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG3)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG4 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG4, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG4)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATA_TIME_CONFIG5 %p,0x%08x\n"), &g_pVAtaReg->ATA_TIME_CONFIG5, INREG32(&g_pVAtaReg->ATA_TIME_CONFIG5)));

        DEBUGMSG(ZONE_INIT, (_T("ATAReg: ATAControl %p,0x%02x\n"), &g_pVAtaReg->ATAControl, INREG8(&g_pVAtaReg->ATAControl)));
        DEBUGMSG(ZONE_INIT, (_T("ATAReg: InterruptPending %p,0x%02x\n"), &g_pVAtaReg->InterruptPending, INREG8(&g_pVAtaReg->InterruptPending)));
    } 

    if(usel & 0x02)
    {
    }
}

#ifdef USE_SDMA

// ----------------------------------------------------------------------------
// Function: SetupDMA
//     Setup DMA transfer
//
// Parameters:
//     pSgBuf -
//     dwSgCount -
//     fRead -
// ----------------------------------------------------------------------------
BOOL CMX31Disk::SetupDMA(PSG_BUF pSgBuf, DWORD dwSgCount, BOOL fRead)
{
    UINT8 chan = fRead ? DmaChanATARx : DmaChanATATx;
    BOOL rc = TRUE;
#ifdef USE_SDMA_SG_LIST
    BOOL fAlign = TRUE;
#else
    BOOL fAlign = FALSE;
#endif
    DWORD dwLockedPages = 0;
    DWORD dwSize;
    DWORD dwBytesRemain = dwSectorsToTransfer * BYTES_PER_SECTOR; 

    DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::SetupDMA(%d, %d)+\n"), fRead, dwSectorsToTransfer * BYTES_PER_SECTOR));
     
    m_pDMASgBuf = pSgBuf;
    m_dwAlignedSgCount = 0;
    m_dwAlignedDescCount = 0;
    m_dwAlignedSgBytes = 0;
    m_DMAChan = chan;
     
    OUTREG8(&g_pVAtaReg->ATAControl, 0x40);  
     
    DWORD currentSg = 0;
    DWORD currentDesc = 0;
    DWORD pdwPages[ATA_MAX_DESC_COUNT];

    // For each ATA watermark aligned scatter/gather buffer 
    while((currentSg < dwSgCount) && fAlign)
    {    
        // Map address and check for security violation
        LPBYTE pBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[currentSg].sb_buf, pSgBuf[currentSg].sb_len);
        if (pSgBuf[currentSg].sb_buf != NULL && pBuffer == NULL) 
        {
            // security violation
            ERRORMSG(ZONE_ERROR, (TEXT(
                "CMX31Disk::SetupDMA> Failed to map pointer to caller\r\n"
                )));
            rc = FALSE;
            goto cleanUp;
        }

        if (!LockPages(pBuffer,pSgBuf[currentSg].sb_len,pdwPages, fRead ? LOCKFLAG_WRITE : LOCKFLAG_READ))
        {
            DEBUGMSG(ZONE_ERROR, (TEXT(
                "CMX31Disk::SetupDMA> LockPages failed\r\n"
                )));
            // Try to fall back to copy using aligned buffer
            fAlign = FALSE;
            break;
        }
        else
        {
            // Keep track of how many pages we have locked so we can
            // unlock them if we encounter a failure
            dwLockedPages++;
        }
            
        DWORD dwMaxPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(pSgBuf[currentSg].sb_buf,pSgBuf[currentSg].sb_len);
        DWORD dwTempLen = pSgBuf[currentSg].sb_len;
        DWORD dwTempPtr = (DWORD)pBuffer;

        for(DWORD i = 0; (i < dwMaxPages) && (dwTempLen > 0) && fAlign; i++)
        {                                   
            // try and rule out broken values
            DEBUGCHK(pdwPages[i] != 0);

            DWORD dwPhys = pdwPages[i] << UserKInfo[KINX_PFN_SHIFT]; // get the start address of pages        
            DWORD dwOffset = dwTempPtr & (UserKInfo[KINX_PAGESIZE] - 1); // offset into page, if any                       
            dwSize = UserKInfo[KINX_PAGESIZE] - dwOffset;
            
            if(dwSize > dwTempLen)
                dwSize = dwTempLen;
            
            dwPhys += dwOffset;                
            
            dwTempLen -= dwSize;
            dwTempPtr += dwSize;

            // If we have any unaligned SG pages, perform remainder of transfer
            // using a copy into an aligned buffer
            if (dwSize & (0x3))
            {
                //DEBUGMSG(ZONE_FUNC, (_T("CMX31Disk::SetupDMA unaligned page (sg = %d, page = %d, size = %d\r\n"), currentSg, i, dwSize));
                
                UnlockPages(pBuffer,pSgBuf[currentSg].sb_len);
                --dwLockedPages;

                fAlign = FALSE;
            }
            else
            {
                // if we're at the end to enable the intr flag
                DWORD dwFlags;
                if(dwTempLen == 0 && (currentSg == (dwSgCount - 1)))
                    dwFlags = DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP;
                else
                    dwFlags = DDK_DMA_FLAGS_CONT;
                
                //DEBUGMSG(ZONE_FUNC, (_T("DDKSdmaSetBufDesc-SG (BD[%d], chan = %d, flags = 0x%x, size = %d\r\n"), currentDesc, chan, dwFlags, dwSize));

                // add new descriptor to chain
                DDKSdmaSetBufDesc(chan, currentDesc, dwFlags, dwPhys,
                    0, DDK_DMA_ACCESS_32BIT, (WORD)dwSize);

                ++currentDesc;
                                                                
            }
                                
        }

        if (fAlign)
        {
            // Keep track of the aligned SG buffers.  If we encounter a
            // a misaligned length while walking through the current 
            // SG buffer pages, we will punt the remainder of the list back to
            // MapDMABuffers implementation
            m_dwAlignedSgBytes += pSgBuf[currentSg].sb_len;
            m_dwAlignedDescCount = currentDesc;
            m_dwAlignedSgCount = ++currentSg;
        }        
                                        
    }

    if (!fAlign)
    {
        if (fRead)
        {
            dwSize = dwSectorsToTransfer * BYTES_PER_SECTOR - m_dwAlignedSgBytes;
        }
        else
        {
            dwSize = MoveDMABuffer(pSgBuf, m_dwAlignedSgCount, dwSgCount, fRead);
            DEBUGCHK(dwSize == (dwSectorsToTransfer * BYTES_PER_SECTOR - m_dwAlignedSgBytes));
        }
            
        DEBUGCHK(!(dwSize & (ATA_DMA_WATERMARK - 1)));

        //DEBUGMSG(ZONE_FUNC, (_T("DDKSdmaSetBufDesc (BD[%d], chan = %d, flags = 0x%x, size = %d\r\n"), dwAlignedDescCount, chan, DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP, dwSize));

        // Set number of bytes to transfer
        DDKSdmaSetBufDesc(chan, m_dwAlignedDescCount, 
            DDK_DMA_FLAGS_INTR | DDK_DMA_FLAGS_WRAP, 
            PhysDMABufferAddr.LowPart, 0, DDK_DMA_ACCESS_32BIT, 
            (WORD)(dwSize)); 
    }


    DDKSdmaStartChan(chan);
    
    // set fifo alarm to 16 halfwords, midway
    OUTREG8(&g_pVAtaReg->FIFOAlarm, ATA_DMA_WATERMARK/2) ;
    OUTREG8(&g_pVAtaReg->InterruptClear, 0xff);
    OUTREG8(&g_pVAtaReg->InterruptEnable, 0x80);

cleanUp:
    if(!rc)
    {
        // Unlock any previous locked page ranges
        for(DWORD i = 0; i < dwLockedPages; i++)
        {
            LPBYTE pUnlockBuffer = (LPBYTE)MapCallerPtr((LPVOID)pSgBuf[i].sb_buf, pSgBuf[i].sb_len);        
            UnlockPages(pUnlockBuffer,pSgBuf[i].sb_len);
        }
        
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -