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

📄 biosial.c

📁 此为marvell 6081在bios芯片中运行的代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        {
            WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_READ_DMA,
                                  MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
        } else
        {
            WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_WRITE_DMA,
                                  MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
        }
    }
    _asm
    {
        mov ds, savedDataSegment
    }
    /* Zero out the registers of EDMA */
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_REQUEST_Q_BAH_REG_OFFSET,
                       0);
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET,
                       0);
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
                       0);

    /* Set request / response queue to point to the single EDMA entry */
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
                       reqQEdmaAddr);
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET,
                       reqQEdmaAddr & MV_EDMA_REQUEST_Q_OUTP_MASK);
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
                       reqQEdmaAddr);
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_RESPONSE_Q_INP_REG_OFFSET,
                       reqQEdmaAddr & MV_EDMA_RESPONSE_Q_INP_MASK);

    /* This will clear any pending interrupts on drive */
    ATAStatus = MV_REG_READ_BYTE(mvSataBarOffset,
                                 edmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);

    /* Enable EDMA */
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET,
                       MV_EDMA_COMMAND_ENABLE_MASK);
    MV_REG_READ_DWORD(mvSataBarOffset,
                      edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET);

    /*
     * Advance request queue in pointer to next entry, thus triggering EDMA
     * to start the IO.
     * Beware that when advancing to wrap aroud the IN pointer by EDMA 
     * request queue size.
     */

    /* Need a wrap around ? */
    if((reqQEdmaAddr & 0x000003ffUL) == 0x3e0UL)
    {
        MV_REG_WRITE_DWORD(mvSataBarOffset,
                           edmaRegsOffset + MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
                           reqQEdmaAddr & 0xfffffc00);
    } else
    {
        MV_REG_WRITE_DWORD(mvSataBarOffset,
                           edmaRegsOffset + MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
                           reqQEdmaAddr + 0x20UL);

    }
    /* Poll on response queue in pointer for completion of command */
    timerChanges = 0;
    timerBase = readSystemClockTimer();
    while(1)
    {
        MV_U16 timerCurrent;
        if((MV_REG_READ_DWORD(mvSataBarOffset, 
                              edmaRegsOffset +
                              MV_EDMA_RESPONSE_Q_INP_REG_OFFSET)
            & MV_EDMA_RESPONSE_Q_INP_MASK) !=
           (reqQEdmaAddr & MV_EDMA_RESPONSE_Q_INP_MASK))
        {
            break;
        }

        timerCurrent = readSystemClockTimer();
        /* 
         * For measuring the time, the driver is waiting for changes on the 
         * system timer and count these changes.
         */
        if(timerCurrent != timerBase)
        {
            timerChanges ++;
            timerBase = timerCurrent;
        }

        /* 
         * Check if reached 10 seconds timeout. The 18*10 is because the system
         * timer is ~18Hz, and the required timeout is 10seconds
         */

        if(timerChanges == (18*10))
        {
#ifdef DEBUG_IAL
            printHexSingle ("Timeout !!!",0);
#endif
            break;
        }
    }
    /* Disable EDMA */
    MV_REG_WRITE_DWORD(mvSataBarOffset,
                       edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET,
                       MV_EDMA_COMMAND_DISABLE_MASK);

    MV_REG_READ_DWORD(mvSataBarOffset,
                      edmaRegsOffset + MV_EDMA_COMMAND_REG_OFFSET);

    /* Do allignment if necessary */
    if(bufferAllignment)
    {
        memcpySegmentOffset32bitForward (bufferSegment,
                                         bufferOffset,
                                         bufferOffset - bufferAllignment,
                                         (MV_U16) (sectorCount * 512));
        for(temp = 0 ; temp < bufferAllignment ; temp ++)
        {
            writeSegmentOffset8bit(bufferSegment,
                                   (bufferOffset - bufferAllignment) + temp,
                                   savedBufferAllignment[temp]);
        }


    }
    edmaErrorCause = MV_REG_READ_DWORD (mvSataBarOffset, edmaRegsOffset +
                                        MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
    ATAStatus = MV_REG_READ_BYTE(mvSataBarOffset,
                                 edmaRegsOffset + MV_ATA_DEVICE_STATUS_REG_OFFSET);

    /* Clear EDMA error cause register */
    MV_REG_WRITE_DWORD (mvSataBarOffset, edmaRegsOffset +
                        MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
    /* Clear unit cause register */
    if(channelIndex >= 4)
    {
        MV_REG_WRITE_DWORD (mvSataBarOffset,
                            MV_SATAHC_1_REGS_BASE_OFFSET +
                            MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, 0);
    } else
    {
        MV_REG_WRITE_DWORD (mvSataBarOffset,
                            MV_SATAHC_0_REGS_BASE_OFFSET +
                            MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, 0);
    }
    /* Check if disk is busy */
    if(ATAStatus & MV_BIT7)
    {
#ifdef DEBUG_IAL
        printHexSingle ("Disk Busy",0);
#endif

        /* Return timeout ; disk busy */
        return 0x80;

    }
    /* Check if ATA error occured */
    if(ATAStatus & MV_BIT0)
    {
        MV_U8 ATAError;
        ATAError = MV_REG_READ_BYTE(mvSataBarOffset,
                                    edmaRegsOffset + MV_ATA_DEVICE_ERROR_REG_OFFSET);
#ifdef DEBUG_IAL
        printHexSingle ("Error reg",ATAError);
#endif
        if(ATAError & MV_BIT6)
        {
            if(readWrite == MV_UDMA_TYPE_READ)
            {
                /* Return bad sector when UDMA read command (Medium error) */
                return 0x2;
            } else
            {
                /* Return write fault when UDMA write command (Write Protect) */
                return 0xcc;
            }
        }
        if(ATAError & MV_BIT7)
        {
            /* Return CRC error */
            return 0x10;
        }
        if(ATAError & MV_BIT4)
        {
            /* Return Sector not found */
            return 0x4;
        }
        if(ATAError & MV_BIT2)
        {
            /*
             * This should be returned as command aborted, but no such error
             * in BIOS codes, so returning Undefined error.
             */
            return 0xbb;
        }
        /* Undefined error */
        return 0xbb;
    }
    /* Check if EDMA error occured */
    if(edmaErrorCause & 0x1fff)
    {
#ifdef DEBUG_IAL
        printHexSingle ("EDMA Err",edmaErrorCause);
#endif

        /* Error in the IO */
        return 0x20;
    }

    return 0; /* All sectors transfered */

}

/*******************************************************************************
* int13ExecuteRequest - Main interrupt 13h handler
*
*
* DESCRIPTION:
*   Main interrupt 13h handler ; gets requests through AH and executes and
*   updates results accordingly
*
* INPUT:
*   All CPU registers through stack
*
* RETURN:
*   None
*
*******************************************************************************/
void interrupt
int13ExecuteRequest(volatile unsigned short gs,
                    volatile unsigned short fs,
                    volatile unsigned short es,
                    volatile unsigned short ds,
                    volatile reg16 di,
                    volatile reg16 si,
                    volatile reg16 bp,
                    volatile reg16 sp,
                    volatile reg16 bx,
                    volatile reg16 dx,
                    volatile reg16 cx,
                    volatile reg16 ax,
                    volatile unsigned short ip,
                    volatile unsigned short cs,
                    volatile unsigned short flags, 
                    ...)
{
    MV_U8 channelIndex = 0, PMPort = 0;
    int counter;
    MV_BOOLEAN incrementSP = MV_FALSE;
#ifdef DEBUG_IAL
    MV_BOOLEAN printAll = MV_FALSE;
    /* Comment and uncomment the following for full debug messages or debug messages on error only */
#if defined (MV_LOG_DEBUG)
    printAll = MV_TRUE; 
#endif
#endif

    /* Set data segment to point to code segment (the driver's data segment) */
    _asm
    {
        nop
        nop
        nop
        nop
        push cs
        pop ds
    }
#ifdef DEBUG_IAL
    initializeSerial ();
    if(printAll == MV_TRUE)
    {
        printHexSingle ("++++",0);
        printHexSingle ("+ AX",ax);
        printHexSingle ("+ BX",bx);
        printHexSingle ("+ CX",cx);
        printHexSingle ("+ DX",dx);
        printHexSingle ("+ ES",es);
        printHexSingle ("+ DI",di);
        printHexSingle ("+ DS",ds);
        printHexSingle ("++++",0);
    }
#endif
    /* If adapter's offset bit 20 is '1', then A20 line should be enabled */
    if((mvSataBarOffset & 0x00100000) && (useIoBar == MV_FALSE))
    {
        unsigned long requestQueueHiBase = 0;
        /* Check if it is already enabled ? */
        if(!(mvSataReadConfigWord(0x44) & 0x1000))
        {
            activateA20Gate();
            mvSataWriteConfigWord(0x44, mvSataReadConfigWord(0x44)
                                  + (1<<9));
        }
        requestQueueHiBase = mvSataReadReg(&sataAdapter.mvSataAdapter, 0x22010);
        if((requestQueueHiBase & 0xfffffffe0) != 
           (mvSataBarOffset & 0xffffffe0))
        {
#ifdef DEBUG_IAL
            printHexSingle ("Enabling A20",0);
#endif
            activateA20Gate();
        }
        requestQueueHiBase = mvSataReadReg(&sataAdapter.mvSataAdapter, 0x22010);
        if((requestQueueHiBase & 0xfffffffe0) != 
           (mvSataBarOffset & 0xffffffe0))
        {
#ifdef DEBUG_IAL
            printHexSingle ("Signature err",0);
#endif
            flags |= 0x1;
            ax.parts.hval = 0x20;
            return;
        }

    }

    flags &= ~0x01;     /* preset the carry flag to indicate no errors */

    for(counter = 0 ; counter < MV_SATA_BIOS_MAX_DRIVES ; counter ++)    //修改--将MV_SATA_CHANNELS_NUM替换为MV_SATA_BIOS_MAX_DRIVES
    {
        if(drivesNumbers[counter] == dx.parts.lval)
        {
            channelIndex = sataChannelNumber[counter];
            PMPort = portMultiplierPort[counter];
            /* Check if PMPort is specified for the channel */
            if(PMPort == 0xff)
            {
                /*
                 * If not specified then set it for PMPort 0. This is necessary
                 * in order to set the PMPort in EDMA request queue entry 
                 * to 0
                 */
                PMPort = 0;
            }
            break;
        }
    }
    if(counter == MV_SATA_BIOS_MAX_DRIVES)   //修改--将MV_SATA_CHANNELS_NUM替换为MV_SATA_BIOS_MAX_DRIVES
    {
        flags |= 0x1;
        ax.parts.hval = 0xbb;
#ifdef DEBUG_IAL
        printHexSingle ("ERR-invld CH",counter);
#endif
        return ;
    }
    if(channelIndex >= sataAdapter.mvSataAdapter.numberOfChannels)
    {
        flags |= 0x1;
        ax.parts.hval = 0xbb;
#ifdef DEBUG_IAL
        printHexSingle ("ERR-invld CH",channelIndex);
#endif
        return ;
    }

    switch(ax.parts.hval)
    {
    case 0x01:          /* Read disk Status */
        {
            ax.parts.hval = 0x1;
            ax.parts.lval = (MV_U8)(readSegmentOffset16bit (0x0040, 0x0041));
            break;
        }
    case 0x02:          /* Read Sectors */
    case 0x03:          /* Write Sectors */
        {
            MV_U32 lowLBAAddress;
            unsigned long track, head;
            unsigned char sector;
            sector = (unsigned short) (cx.parts.lval & 0x3f);
            track = (((unsigned short)(cx.parts.lval & 0xc0) << 2) | cx.parts.hval);
            head = (unsigned short) dx.parts.hval;
            lowLBAAddress = 
            (unsigned long) track * HEADS * SECTORS +
            (unsigned long) head * SECTORS +
            (unsigned long) (sector - 1) ;

            /* Check if sector count is more than 128 or equals 0 */
            if((ax.parts.lval > 128) || (ax.parts.lval == 0))
            {
#ifdef DEBUG_IAL
                printHexSingle ("Sect Cnt Err",readSegmentOffset16bit(ds,si.val+2));
#endif
                flags |= 0x1;
                ax.parts.lval = 0xa;
                break;
            }

⌨️ 快捷键说明

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