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

📄 biosial.c

📁 此为marvell 6081在bios芯片中运行的代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    return MV_TRUE;
}


/*******************************************************************************
* waitForKeystroke - Wait for a key pressed by user
*
*
* DESCRIPTION:
*   Utilizes BIOS 8 interrupt 16h, this function waits for a key pressed
*   by the user
*
* INPUT:
*   None
*
* RETURN:
*   None
*
*******************************************************************************/

void waitForKeystroke (void)
{
    _asm
    {
        pusha
        mov ah, 0x0
        waitForKeystrok_:
        int 0x16
        cmp al, 0
        je  waitForKeystrok_
        popa
        nop
        nop

    }
}

/*******************************************************************************
* readSegmentOffset8bit - Read 8bit from pointer indicated by segment:offset
*
*
* DESCRIPTION:
*   Read 16bit from pointer indicated by segment:offset
*
* INPUT:
*   segment_    -   Segment of requested data
*   offset_     -   Offset within the segment of the request data
*
* RETURN:
*   8bit of data that is requested
*
*******************************************************************************/
unsigned char readSegmentOffset8bit (unsigned short segment_, unsigned short offset_)
{
    unsigned char value = 0;
    _asm
    {
        pusha
        push fs
        mov di, segment_
        mov fs,di
        mov di, offset_
        mov cl, fs:[di]
        mov value, cl
        pop fs
        popa

    }
    return value;
}

/*******************************************************************************
* writeSegmentOffset8bit - Writes 8bit to a 8bit memory indicated by segment:offset
*
*
* DESCRIPTION:
*   Read 16bit from pointer indicated by segment:offset
*
* INPUT:
*   segment_    -   Segment of the memory to write to
*   offset_     -   Offset within the segment of the request data
*   value_      -   Value of the data to be written
*
* RETURN:
*   None
*
*******************************************************************************/
void writeSegmentOffset8bit (unsigned short segment_, unsigned short offset_, unsigned char value_)
{
    _asm
    {
        pusha
        push fs
        mov di, segment_
        mov fs,di
        mov di, offset_
        mov cl, value_
        mov fs:[di], cl
        pop fs
        popa

    }
    return;
}

/*******************************************************************************
* readSegmentOffset16bit - Read 16bit from pointer indicated by segment:offset
*
*
* DESCRIPTION:
*   Read 16bit from pointer indicated by segment:offset
*
* INPUT:
*   segment_    -   Segment of requested data
*   offset_     -   Offset within the segment of the request data
*
* RETURN:
*   16bit of data that is requested
*
*******************************************************************************/
unsigned short readSegmentOffset16bit (unsigned short segment_, unsigned short offset_)
{
    unsigned short value = 0;
    _asm
    {
        pusha
        push fs
        mov di, segment_
        mov fs,di
        mov di, offset_
        mov cx, fs:[di]
        mov value, cx
        pop fs
        popa

    }
    return value;
}

/*******************************************************************************
* writeSegmentOffset16bit - Writes 16bit to a 16bit memory indicated by segment:offset
*
*
* DESCRIPTION:
*   Read 16bit from pointer indicated by segment:offset
*
* INPUT:
*   segment_    -   Segment of the memory to write to
*   offset_     -   Offset within the segment of the request data
*   value_      -   Value of the data to be written
*
* RETURN:
*   None
*
*******************************************************************************/
void writeSegmentOffset16bit (unsigned short segment_, unsigned short offset_, unsigned short value_)
{
    _asm
    {
        pusha
        push fs
        mov di, segment_
        mov fs,di
        mov di, offset_
        mov cx, value_
        mov fs:[di], cx
        pop fs
        popa

    }
    return;
}

/*******************************************************************************
* memcpySegmentOffset32bitForward - Memory copy within segment
*
*
* DESCRIPTION:
*   Copies memory from source to destination within same segment, each read
*   write of 32 bit. The copy process is done from the end of the buffer
*   to the start, due to overlapping issues.
*
* INPUT:
*   segment_    -   Segment of requested data
*   offset_     -   Offset within the segment of the request data
*
* RETURN:
*   16bit of data that is requested
*
*******************************************************************************/
void memcpySegmentOffset32bitForward (unsigned short segment_,
                                      unsigned short destinationOffset_,
                                      unsigned short sourceOffset_,
                                      unsigned short byteCount_)
{
    _asm
    {
        pusha
        push fs
        push ecx
        mov di, segment_
        mov fs,di
        mov di, destinationOffset_
        mov si, sourceOffset_
        mov ax, byteCount_
        add di, ax
        add si, ax

        copyLoop:
        sub di, 4
        sub si, 4
        mov ecx, fs:[si]
        mov fs:[di], ecx
        sub ax, 4
        jnz copyLoop
        pop ecx
        pop fs
        popa

    }
}


#define WRITE_ATA_COMMAND_REG(addr, data, reg, isLast)              \
do{                                                                 \
    *(addr) = MV_CPU_TO_LE16((((MV_U8)(data)) & 0xff) | ((reg) << 8) | (isLast));   \
} while(0)

/* Calculate the base address of the registers for a SATA channel */
MV_U32 edmaRegOffst[MV_SATA_CHANNELS_NUM] = {0x22000, 0x24000, 0x26000, 0x28000,
    0x32000, 0x34000, 0x36000, 0x38000};

#define getEdmaRegOffset(x) edmaRegOffst[(x)]

MV_U32 generate32Addr (MV_U16 segment, MV_U16 offset)
{
    MV_U32 addr = 0;
    addr = (((MV_U32)segment) << 4) & 0x000ffff0;
    addr = addr + (MV_U32) offset;
    return addr;
}

MV_U8 requestIO (MV_U8 channelIndex, MV_U8 PMPort,
                 MV_U32 lowLBAAddress, MV_U16 highLBAAddress, MV_U16 sectorCount,
                 MV_UDMA_TYPE readWrite, MV_U16 bufferSegment, MV_U16 bufferOffset)
{
    volatile MV_U16  *pCommand;
    MV_SATA_EDMA_PRD_ENTRY  *prdTable;
    MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry;
    MV_U32 edmaRegsOffset;
    MV_U32 reqQEdmaAddr;
    MV_U16 stackSegment = 0;
    MV_U16 savedDataSegment = 0;
    MV_U16 timerBase, timerChanges;
    MV_U8 ATAStatus;
    MV_BOOLEAN isEXT;
    MV_U32 edmaErrorCause;
    MV_U8   bufferAllignment;
    MV_U8   savedBufferAllignment[8]; /* Used for 8byte buffer allignment */
    MV_U8   temp;
    MV_U32  bufferIOAddr = generate32Addr(bufferSegment, bufferOffset);

    /*
     * The following allocation is for PRD table and an EDMA request 
     * queue entry. The request queue entry is also used for the
     * response queue completion entry.
     * The PRD table and the request queue must be 32 byte alligned,
     * so we need to allocate 32*3 for the allignment.
     */
    unsigned char buffer[32*3];
    edmaRegsOffset = getEdmaRegOffset(channelIndex);
    /* Allign PRD table to 32 bytes */
    prdTable = (MV_SATA_EDMA_PRD_ENTRY *)(((MV_U16)buffer & 0xfff0) + 0x10);
    /* Request queue entry is 32bytes off the PRD table */
    pReqEntry = (MV_DMA_REQUEST_QUEUE_ENTRY *)(((MV_U16)buffer & 0xfff0) + 0x30);
    bufferAllignment = (MV_U8) bufferIOAddr & (requestedAllignment - 1);
    /* If not 32 byte alligned then add another 16byte */
    _asm {
        mov stackSegment, ss
        mov savedDataSegment, ds
        mov ds, stackSegment
    }
    if((generate32Addr (stackSegment, (MV_U16)prdTable) & MV_BIT4))
    {
        prdTable = (MV_SATA_EDMA_PRD_ENTRY *)((MV_U16) prdTable + 0x10);
        pReqEntry = (MV_DMA_REQUEST_QUEUE_ENTRY *)((MV_U16) pReqEntry + 0x10);
    }

    /* Populate the PRD table */
    prdTable[0].highBaseAddr = 0;
    prdTable[0].lowBaseAddr = bufferIOAddr - (MV_U32)bufferAllignment;
    prdTable[0].byteCount = (MV_U16) (sectorCount * 512);
    prdTable[0].flags = MV_EDMA_PRD_EOT_FLAG;
    prdTable[0].reserved = 0;

    /* Save the data for allignment */

    for(temp = 0 ; temp < bufferAllignment ; temp ++)
    {
        savedBufferAllignment[temp] =
        readSegmentOffset8bit(bufferSegment,
                              (bufferOffset - bufferAllignment) + temp);
    }

    /* Populate the request queue entry */
    pReqEntry->prdHighAddr = 0;
    pReqEntry->prdLowAddr = generate32Addr (stackSegment, (MV_U16)prdTable);
    reqQEdmaAddr = generate32Addr (stackSegment, (MV_U16)pReqEntry);
    pCommand = &pReqEntry->command[0];

    if((lowLBAAddress + (MV_U32)sectorCount) & 0xf0000000)
    { /* Use LBA48 */
        isEXT = MV_TRUE;
    } else
    {
        isEXT = MV_FALSE;
    }

    /* Set the direction of the transaction (read/write) */
    pReqEntry->controlFlags = (readWrite == MV_UDMA_TYPE_READ) ? 0x1 : 0x0;
    pReqEntry->controlFlags |= ((((MV_U16)PMPort) & 0x000f) << 12);

    if(isEXT == MV_TRUE)
    {   /* READ/WRITE DMA EXT */
        WRITE_ATA_COMMAND_REG(pCommand++,
                              (sectorCount & 0xFF00) >> 8,
                              MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (sectorCount) & 0xFF,
                              MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress & 0xFF000000) 
                              >> 24,
                              MV_EDMA_ATA_LBA_LOW_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++, 
                              (lowLBAAddress) &0xFF,
                              MV_EDMA_ATA_LBA_LOW_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (highLBAAddress & 0xFF),
                              MV_EDMA_ATA_LBA_MID_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress & 0xFF00) >> 8,
                              MV_EDMA_ATA_LBA_MID_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (highLBAAddress & 0xFF00) >> 8,
                              MV_EDMA_ATA_LBA_HIGH_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress & 0xFF0000)
                              >> 16,
                              MV_EDMA_ATA_LBA_HIGH_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR,
                              0);

        if(readWrite == MV_UDMA_TYPE_READ)
        {
            WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_READ_DMA_EXT,
                                  MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
        } else
        {
            WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_WRITE_DMA_EXT,
                                  MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
        }
    } else
    { /* READ/WRITE DMA */
        WRITE_ATA_COMMAND_REG(pCommand++,
                              (sectorCount) & 0xFF,
                              MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress) & 0xFF,
                              MV_EDMA_ATA_LBA_LOW_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress & 0xFF00) >> 8,
                              MV_EDMA_ATA_LBA_MID_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              (lowLBAAddress & 0xFF0000)
                              >> 16,
                              MV_EDMA_ATA_LBA_HIGH_ADDR, 0);

        WRITE_ATA_COMMAND_REG(pCommand++,
                              MV_BIT6 | (MV_U8)((lowLBAAddress & 
                                                 0xF000000) >> 24),
                              MV_EDMA_ATA_DEVICE_ADDR, 0);

        if(readWrite == MV_UDMA_TYPE_READ)

⌨️ 快捷键说明

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