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

📄 atadrv.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:

/*******************************************************************************
*
* ataRW - read/write a number of sectors on the current track
*
* Read/write a number of sectors on the current track
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS ataRW
    (
    int ctrl,
    int drive,
    int cylinder,
    int head,
    int sector,
    void *buffer,
    int nSecs,
    int direction
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[ctrl];
    ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    ATA_TYPE *pType	= &ataTypes[ctrl][drive];
    int retryCount	= 0;
    int block		= 1;
    int nSectors;
    int nWords;
    int semStatus;
    short *pBuf;

    ATA_DEBUG_MSG (2, "ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x ",
                   ctrl, drive, cylinder, head, sector, (int)buffer);
    ATA_DEBUG_MSG (2, "n=%d dir=%d\n", nSecs, direction, 0, 0, 0, 0);

retryRW:

    ataWait (ctrl, ATA_STAT_READY);

    pBuf = (short *)buffer;
    nSectors = nSecs;

    ATA_IO_BYTE_WRITE (pCtrl->feature, pType->precomp);
    ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs);
    ATA_IO_BYTE_WRITE (pCtrl->sector, sector);
    ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder);
    ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8);

    if (pDrive->okLba)
        ATA_IO_BYTE_WRITE (pCtrl->sdh,
                           ATA_SDH_LBA | (drive << 4) | (head & 0xf));
    else
        ATA_IO_BYTE_WRITE (pCtrl->sdh,
                           ATA_SDH_IBM | (drive << 4) | (head & 0xf));

    if (pDrive->rwPio == ATA_PIO_MULTI)
	block = pDrive->multiSecs;

    nWords = (pType->bytes * block) >> 1;

    if (direction == O_WRONLY)
	{

        if (pDrive->rwPio == ATA_PIO_MULTI)
	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI);
	else
	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE);

	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
*/

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: ataPiNonOv

⌨️ 快捷键说明

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