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

📄 atadrv.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	while (nSectors > 0)	    {	    if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))		{		block = nSectors;		nWords = (pType->bytes * block) >> 1;		}            ataWait (ctrl, ATA_STAT_BUSY);            ataWait (ctrl, ATA_STAT_DRQ);	    if (pDrive->rwBits == ATA_BITS_16)	        ATA_IO_NWORD_WRITE (pCtrl->data, pBuf, nWords);	    else	        ATA_IO_NLONG_WRITE (pCtrl->data, (long *)pBuf, nWords >> 1);            semStatus = semTake (&pCtrl->syncSem, 				 sysClkRateGet() * pCtrl->semTimeout);    	    if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))	        goto errorRW;	    pBuf     += nWords;	    nSectors -= block;            }	}    else	{        if (pDrive->rwPio == ATA_PIO_MULTI)	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI);	else	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ);	while (nSectors > 0)	    {	    if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))		{		block = nSectors;		nWords = (pType->bytes * block) >> 1;		}            semStatus = semTake (&pCtrl->syncSem, 				 sysClkRateGet() * pCtrl->semTimeout);    	    if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))	        goto errorRW;            ataWait (ctrl, ATA_STAT_BUSY); /* wait for slow disk */            ataWait (ctrl, ATA_STAT_DRQ);	    if (pDrive->rwBits == ATA_BITS_16)	        ATA_IO_NWORD_READ (pCtrl->data, pBuf, nWords);	    else	        ATA_IO_NLONG_READ (pCtrl->data, (long *)pBuf, nWords >> 1);	    pBuf     += nWords;	    nSectors -= block;	    }	}    ATA_DEBUG_MSG (2, "ataRW: end\n", 0, 0, 0, 0, 0, 0);    return (OK);errorRW:    ATA_DEBUG_MSG (1, "ataRW err: stat=0x%x 0x%x semStatus=%d error=0x%x\n",	           pCtrl->intStatus, ATA_IO_BYTE_READ (pCtrl->aStatus),                    semStatus, ATA_IO_BYTE_READ (pCtrl->error), 0, 0);    if (++retryCount < ataRetry)	goto retryRW;    return (ERROR);    }/******************************* ATAPI Devices *********************************//********************************************************************************* ataDevIdentify - identify device** This routine checks whether the device is connected to the controller, and if* so determines its type.  The routine set `type' field in the corresponding * ATA_DRIVE structure.* If device identification failed, the routine set `state' field in the * corresponding ATA_DRIVE structure to ATA_DEV_NONE.** RETURNS: TRUE if a device is present, FALSE otherwise*/LOCAL STATUS ataDevIdentify    (    int	ctrl,    int	dev    )    {    ATA_CTRL    *pCtrl	= &ataCtrl[ctrl];    ATA_DRIVE   *pDrive	= &pCtrl->drive [dev];    ATA_PARAM   *pParam	= &pDrive->param;    pDrive->type = ATA_TYPE_NONE;    /* Select device */     ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (dev << 4));     /* Wait for device selection */     ATA_WAIT_STATUS;     /* Clear semaphore: Selection of nonexistent device may rise an interrupt */    semTake (&pCtrl->syncSem, NO_WAIT);    ATA_IO_BYTE_WRITE (pCtrl->seccnt, 0xaa);    ATA_IO_BYTE_WRITE (pCtrl->sector, 0x55);     if (ATA_IO_BYTE_READ (pCtrl->seccnt) == 0xaa)        {        if (ataPiPread (ctrl, dev, pParam) == OK)            {            pDrive->type = ATA_TYPE_ATAPI;            }        else             if ( ((ATA_IO_BYTE_READ (ATAPI_STATUS) & (ATA_STAT_BUSY | 		   ATA_STAT_WRTFLT | ATA_STAT_DRQ | ATA_STAT_ERR)) ==                    ATA_STAT_ERR) &&                  (ATA_IO_BYTE_READ (ATAPI_ERROR) == ERR_ABRT) )                {                if (ataPiWait (ctrl, ATA_STAT_READY, FALSE) == OK)                    pDrive->type = ATA_TYPE_ATA;                }        }     if (pDrive->type != ATA_TYPE_NONE)        return (OK);    ATA_DEBUG_MSG (1, "ataDevIdentify%d/%d: ERROR: status=0x%x dev=0x%x "                   "error=0x%x\n", ctrl, dev, ATA_IO_BYTE_READ (pCtrl->status),                   ATA_IO_BYTE_READ (pCtrl->sdh),                    ATA_IO_BYTE_READ (pCtrl->error), 0);    /* Select present device */    ATA_IO_BYTE_WRITE (pCtrl->sdh, ATA_SDH_IBM | (((~dev) & 0x1) << 4)); /* define macro for 0x1 */    pDrive->state = ATA_DEV_NONE;    return (ERROR);    } /* ataDevIdentify *//********************************************************************************* ataPiInit - init a ATAPI CD-ROM disk controller** This routine resets a ATAPI CD-ROM disk controller.** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataPiInit     (    int ctrl,    int drive    )    {    ATA_CTRL    *pCtrl = &ataCtrl[ctrl];    int		retryCount = 0;    int		i;    ATA_DEBUG_MSG (2, "ataPiInit%d/%d: \n", ctrl, drive, 0, 0, 0, 0);    while (TRUE) /* Forever */        {        ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4));        ATA_WAIT_STATUS;        ATA_IO_BYTE_WRITE (ATAPI_COMMAND, ATA_PI_CMD_SRST);        for (i = 0; i < 5000; i++)	/* 2 ms */            {            ATA_WAIT_STATUS;            }        ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4));        ATA_WAIT_STATUS;        pCtrl->wdgOkay = TRUE;        wdStart (pCtrl->wdgId, (sysClkRateGet() * pCtrl->wdgTimeout),                  (FUNCPTR)ataWdog, ctrl);        while ( (ATA_IO_BYTE_READ (ATAPI_STATUS) & (ATA_STAT_BUSY |                  ATA_STAT_READY | ATA_STAT_WRTFLT | ATA_STAT_DRQ |                  ATA_STAT_ECCCOR | ATA_STAT_ERR)) && (pCtrl->wdgOkay) )	    ;        wdCancel (pCtrl->wdgId);        if (pCtrl->wdgOkay)            break;        pCtrl->wdgOkay = TRUE;        ATA_DEBUG_MSG (1, "ataPiInit%d/%d: ERROR: status=0x%x error=0x%x\n",                        ctrl, drive, ATA_IO_BYTE_READ(ATAPI_STATUS),                        ATA_IO_BYTE_READ(ATAPI_ERROR), 0, 0);	if (++retryCount == ataRetry)	    return (ERROR);        }    /* The following allow to recover after accidental interrupt */    if (semTake (&pCtrl->syncSem, NO_WAIT) == OK)        {        ATA_DEBUG_MSG (2, "ataPiInit%d/%d: WARNING: interrupt cleared: "                       "status=0x%x dev=0x%x error=0x%x\n", ctrl, drive,                        ATA_IO_BYTE_READ(ATAPI_STATUS),                        ATA_IO_BYTE_READ(ATAPI_D_SELECT),                        ATA_IO_BYTE_READ(ATAPI_ERROR), 0);        }    else        {        ATA_DEBUG_MSG (2, "ataPiInit%d/%d: Ok: status=0x%x dev=0x%x error=0x%x"                       "\n", ctrl, drive, ATA_IO_BYTE_READ(ATAPI_STATUS),                        ATA_IO_BYTE_READ(ATAPI_D_SELECT),                        ATA_IO_BYTE_READ(ATAPI_ERROR), 0);        }    return (OK);    } /* ataPiInit *//********************************************************************************* ataPiPread - Read ATAPI drive parameters** This routine reads drive parameters.** RETURNS: OK, ERROR if the command didn't succeed.*/LOCAL STATUS ataPiPread    (    int		ctrl,    int		drive,    void        *buffer    )    {    ATA_CTRL    *pCtrl		= &ataCtrl[ctrl];    int		status;    int		error;    int		semStatus;    ATA_DEBUG_MSG (2, "ataPiPread%d/%d: \n", ctrl, drive, 0, 0, 0, 0);    ataPiWait (ctrl, ATA_STAT_ACCESS, TRUE);    /* Select device */    ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4));    ATA_WAIT_STATUS;    if (ataPiWait (ctrl, ATA_STAT_ACCESS, TRUE) != OK)        {        ATA_IO_BYTE_WRITE (ATAPI_D_SELECT, DSEL_FILLER | (drive << 4));;        ATA_WAIT_STATUS;        }    /* ATAPI Identify Device Command */    ATA_IO_BYTE_WRITE (ATAPI_COMMAND, ATA_PI_CMD_IDENTD);    ATA_WAIT_STATUS;    /*     * Poll Status Register instead of wait for interrupt to avoid needless      * delay.     */    ataPiWait (ctrl, ATA_STAT_BUSY, FALSE);    semStatus = semTake (&pCtrl->syncSem, 1);    status = ATA_IO_BYTE_READ (ATAPI_STATUS);    if ( (status & ATA_STAT_ERR) || !(status & ATA_STAT_DRQ) ||          (semStatus != OK) )        {        error = ATA_IO_BYTE_READ (ATAPI_ERROR);        ATA_DEBUG_MSG (1, "ataPiPread%d/%d: ERROR: status=0x%x intStatus=0x%x "                      "error=0x%x semStatus=%d\n", ctrl, drive, status,                        pCtrl->intStatus, error, semStatus);        return (ERROR);        }    /* Receive parameter information from the drive */    ATA_IO_NWORD_READ_SWAP (ATAPI_DATA, (short *)buffer,                             sizeof(ATA_PARAM)/sizeof(short));    /* To prevent from reading status before it is valid */    ATA_IO_BYTE_READ (pCtrl->aStatus);    /* Wait for device to be ready !!! */    ataPiWait (ctrl, ATA_STAT_READY, TRUE);    ATA_DEBUG_MSG (2, "ataPiPread%d/%d:Ok: status=0x%x devReg=0x%x\n",                   ctrl, drive, ATA_IO_BYTE_READ (pCtrl->status),                   ATA_IO_BYTE_READ (pCtrl->sdh), 0, 0);    return (OK);    } /* ataPiPread *//********************************************************************************* atapiDMAInit - initialize the DMA engine** This routine initializes the DMA engine.** RETURN: OK, or ERROR*/LOCAL STATUS atapiDMAInit (void)    {    printErr("ATAPI (DMA Init.) ERROR: DMA transfer is not emplemented.\n");    return ERROR;    }/********************************************************************************* atapiDMATransfer - transfer a single data packet via DMA** This routine transfers a single data packet via DMA.** RETURN: OK, or ERROR** SEE ALSO: ataPiPIOTransfer()*/LOCAL STATUS atapiDMATransfer     (    ATA_DEV *pAtapiDev    )    {    pAtapiDev->errNum = 27;    return ERROR;    }/********************************************************************************* ataPiOverlapTransferLoop - loop for DRQ Interrupts with Overlapping** This routine loops for Data Request Interrupts until all data packets are * transferred.  It is invoked when ataPiPktCmd() executes an Overlapped command.  * When Device executes an Overlapped command, it releases the ATA bus until the* device is ready to transfer a data or to present the completion status.** RETURN: OK, or ERROR** SEE ALSO: ataPiNonOverTransferLoop()*/LOCAL STATUS ataPiOverlapTransferLoop    (    ATA_DEV *pAtapiDev,    FUNCPTR pTransferProc    )    {    pAtapiDev->errNum = 26;    return ERROR;    }/********************************************************************************* ataPiPIOTransfer - transfer a single data packet via PIO** This routine transfers a single data packet via PIO.** RETURN: OK, or ERROR** SEE ALSO: atapiDMATransfer()*/LOCAL STATUS ataPiPIOTransfer    (    ATA_DEV     *pAtapiDev    )    {    ATA_CTRL    *pCtrl	= &ataCtrl[pAtapiDev->ctrl];    uint32_t	desiredSize;    uint32_t	remainderSize;    short	bucket;    /* Read Byte Count */    pAtapiDev->transSize = ((uint16_t)ATA_IO_BYTE_READ (ATAPI_BCOUNT_HI)) << 8;    pAtapiDev->transSize += ATA_IO_BYTE_READ (ATAPI_BCOUNT_LO);    /*     * From ATA Packet Interface for CD-ROMs SFF-8020i:     * If the Device requests more data be transfered than required by the      * command protocol, the Host shall pad when sending data to the Device,      * and dump extra data into a bit bucket when reading data from the Device.     *     * Why device will request more data than required? It is not clear.     * (May be some devices can't transfer part of the internal buffer?) !!!     */    if ( (pAtapiDev->pBufEnd == NULL) && (pAtapiDev->transSize != 0) )        {        pAtapiDev->errNum = 8;        return ERROR;        }    desiredSize = pAtapiDev->pBufEnd - pAtapiDev->pBuf;    if (desiredSize <= pAtapiDev->transSize)        {        remainderSize = pAtapiDev->transSize - desiredSize;        pAtapiDev->pBufEnd = NULL;        }    else        {        desiredSize = pAtapiDev->transSize;        remainderSize = 0;        }    /* Transfer Data Bytes */    switch (pAtapiDev->direction)        {        case OUT_DATA:            if((pAtapiDev->intReason & INTR_IO) != 0)	/* IO cleared */                    goto errorPIOTransfer;            ATA_IO_NWORD_WRITE (ATAPI_DATA, (short *)pAtapiDev->pBuf,                                 desiredSize / 2);            while (remainderSize)                {                bucket = 0;                ATA_IO_NWORD_WRITE (ATAPI_DATA, &bucket, 1);          

⌨️ 快捷键说明

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