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

📄 atadrv.c

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

    if ((pDev = (ATA_DEV *)malloc(sizeof (ATA_DEV))) == NULL)
	return (NULL);

    pBlkdev = &pDev->blkDev;

    if ((pDrive->state == ATA_DEV_OK) || (pDrive->state == ATA_DEV_MED_CH))
        {
        pDrive->state = ATA_DEV_MED_CH;

        if (pDrive->type == ATA_TYPE_ATA)
            {

	    /* 
	     * if LBA is supported and ataLbaTotalSecs is not zero
	     * and ataLbaTotalSecs is greater than the product of
	     * CHS, then we should use the LBA value.
	     */

            if ((pDrive->okLba == TRUE)                     && 
		(ataLbaTotalSecs[ctrl][drive] != 0)         &&
		(ataForceCHSonLBA != TRUE)		    &&
		(ataLbaTotalSecs[ctrl][drive] > 
		 (pType->cylinders * pType->heads * pType->sectors)))   
	        {
		maxBlks = (ataLbaTotalSecs[ctrl][drive]) - blkOffset;
		}
	    else /* just use CHS */
	        {
		maxBlks = ((pType->cylinders * pType->heads * pType->sectors) 
			   - blkOffset);
		}

	    if (nBlocks == 0)
	        nBlocks = maxBlks;
    
	    if (nBlocks > maxBlks)
	        nBlocks = maxBlks;

	    pBlkdev->bd_nBlocks		= nBlocks;
	    pBlkdev->bd_bytesPerBlk	= pType->bytes;
	    pBlkdev->bd_blksPerTrack	= pType->sectors;
	    pBlkdev->bd_nHeads		= pType->heads;
	    pBlkdev->bd_removable	= TRUE;
	    pBlkdev->bd_retry		= 1;
	    pBlkdev->bd_mode		= O_RDWR;
	    pBlkdev->bd_readyChanged	= TRUE;
	    pBlkdev->bd_blkRd		= ataBlkRd;
	    pBlkdev->bd_blkWrt		= ataBlkWrt;
	    pBlkdev->bd_ioctl		= ataIoctl;
	    pBlkdev->bd_reset		= ataReset;
	    pBlkdev->bd_statusChk	= ataStatus;
	    pBlkdev->bd_reset		= NULL;
	    pBlkdev->bd_statusChk	= NULL;
	    pDev->ctrl			= ctrl;
	    pDev->drive			= drive;
	    pDev->blkOffset		= blkOffset;
	    }
        else if (pDrive->type == ATA_TYPE_ATAPI)
            {
            pBlkdev->bd_nBlocks         = 100;
            pBlkdev->bd_bytesPerBlk     = 2048;
            pBlkdev->bd_blksPerTrack    = pBlkdev->bd_nBlocks;
            pBlkdev->bd_nHeads          = 1;

            if (pParam->config & CONFIG_REMOVABLE)
                pBlkdev->bd_removable   = TRUE;
            else
                pBlkdev->bd_removable   = FALSE;

            pBlkdev->bd_retry           = 1;
            pBlkdev->bd_mode            = O_RDONLY;
            pBlkdev->bd_readyChanged    = TRUE;
            pBlkdev->bd_blkRd           = ataPiBlkRd;
            pBlkdev->bd_blkWrt          = ataStub;
            pBlkdev->bd_ioctl           = ataPiIoctl;
            pBlkdev->bd_reset           = ataPiReset;
            pBlkdev->bd_statusChk       = ataPiStatusChk;

	    pDev->ctrl		        = ctrl;
	    pDev->drive		        = drive;
	    pDev->blkOffset	        = blkOffset;
            pDev->nBlocks               = nBlocks;

	    }

        ataDriveInit (ctrl, drive);

        pDrive->state = ATA_DEV_OK;
	}

    return (&pDev->blkDev);
    }

/*******************************************************************************
*
* ataRawio - do raw I/O access
*
* This routine is called to perform raw I/O access.
*
* <drive> is a drive number for the hard drive: it must be 0 or 1.
*
* The <pAtaRaw> is a pointer to the structure ATA_RAW which is defined in 
* ataDrv.h.
*
* RETURNS:
* OK, or ERROR if the parameters are not valid.
*
*/

STATUS ataRawio
    (
    int      ctrl,
    int      drive,
    ATA_RAW  *pAtaRaw
    )
    {
    ATA_CTRL  *pCtrl	= &ataCtrl[ctrl];
    ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    ATA_TYPE  *pType	= &ataTypes[ctrl][drive];
    ATA_DEV   ataDev;
    BLK_DEV   *pBlkdev	= &ataDev.blkDev;
    UINT      startBlk;

    if ((ctrl >= ATA_MAX_CTRLS) || (drive >= ATA_MAX_DRIVES) ||
        !ataDrvInstalled || !pCtrl->installed)
	return (ERROR);

    if ((pAtaRaw->cylinder	>= pType->cylinders)	||
        (pAtaRaw->head		>= pType->heads)	||
        (pAtaRaw->sector	>  pType->sectors)	||
        (pAtaRaw->sector	== 0))
	return (ERROR);

    /*
     * if LBA is supported and ataLbaTotalSecs is not zero
     * and ataLbaTotalSecs is greater than the product of
     * CHS, then we should use the LBA value.
     */

    if ((pDrive->okLba == TRUE)                     && 
   	(ataLbaTotalSecs[ctrl][drive] != 0)         &&
	(ataForceCHSonLBA != TRUE)		    &&
	(ataLbaTotalSecs[ctrl][drive] > 
	(pType->cylinders * pType->heads * pType->sectors)))   
	{
	pBlkdev->bd_nBlocks = ataLbaTotalSecs[ctrl][drive];
	}
    else /* just use CHS value */
	{
        pBlkdev->bd_nBlocks	= pType->cylinders * pType->heads * 
				  pType->sectors;
	}

    pBlkdev->bd_bytesPerBlk	= pType->bytes;
    pBlkdev->bd_blksPerTrack	= pType->sectors;
    pBlkdev->bd_nHeads		= pType->heads;
    pBlkdev->bd_removable	= FALSE;
    pBlkdev->bd_retry		= 1;
    pBlkdev->bd_mode		= O_RDWR;
    pBlkdev->bd_readyChanged	= TRUE;
    pBlkdev->bd_blkRd		= ataBlkRd;
    pBlkdev->bd_blkWrt		= ataBlkWrt;
    pBlkdev->bd_ioctl		= ataIoctl;
    pBlkdev->bd_reset		= ataReset;
    pBlkdev->bd_statusChk	= ataStatus;

    ataDev.ctrl			= ctrl;
    ataDev.drive		= drive;
    ataDev.blkOffset		= 0;

    startBlk = pAtaRaw->cylinder * (pType->sectors * pType->heads) +
	       pAtaRaw->head * pType->sectors + pAtaRaw->sector - 1;

    return (ataBlkRW (&ataDev, startBlk, pAtaRaw->nSecs, pAtaRaw->pBuf,
		     pAtaRaw->direction));
    }

/*******************************************************************************
*
* ataBlkRd - read one or more blocks from a ATA/IDE disk
*
* This routine reads one or more blocks from the specified device,
* starting with the specified block number.
*
* If any block offset was specified during ataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the read command didn't succeed.
*/

LOCAL STATUS ataBlkRd
    (
    ATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf
    )
    {
    return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_RDONLY));
    }

/*******************************************************************************
*
* ataBlkWrt - write one or more blocks to a ATA/IDE disk
*
* This routine writes one or more blocks to the specified device,
* starting with the specified block number.
*
* If any block offset was specified during ataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the write command didn't succeed.
*/

LOCAL STATUS ataBlkWrt
    (
    ATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf
    )
    {
    return (ataBlkRW (pDev, startBlk, nBlks, pBuf, O_WRONLY));
    }

/*******************************************************************************
*
* ataReset - reset a ATA/IDE disk controller
*
* This routine resets a ATA/IDE disk controller.
*
* RETURNS: OK, always.
*/

LOCAL STATUS ataReset
    (
    ATA_DEV  *pDev
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[pDev->ctrl];
    
    if (!pCtrl->installed)
	return (ERROR);

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    (void) ataInit (pDev->ctrl, 0);

    semGive (&pCtrl->muteSem);

    return (OK);
    }

/*******************************************************************************
*
* ataStatus - check status of a ATA/IDE disk controller
*
* This routine check status of a ATA/IDE disk controller.
*
* RETURNS: OK, ERROR if the card is removed.
*/

LOCAL STATUS ataStatus
    (
    ATA_DEV  *pDev
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[pDev->ctrl];
    BLK_DEV  *pBlkdev	= &pDev->blkDev;
    
    if (!pCtrl->installed)
	return (ERROR);

    if (pCtrl->changed)
	{
	pBlkdev->bd_readyChanged = TRUE;
	pCtrl->changed		 = FALSE;
	}

    return (OK);
    }

/*******************************************************************************
*
* ataIoctl - do device specific control function
*
* This routine is called when the file system cannot handle an ioctl()
* function.
*
* RETURNS:  OK or ERROR.
*/

LOCAL STATUS ataIoctl
    (
    ATA_DEV  *pDev,
    int      function,
    int      arg
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[pDev->ctrl];
    FAST int status	= ERROR;

    if (!pCtrl->installed)
        return (ERROR);

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    switch (function)
	{
	case FIODISKFORMAT:
	    (void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
	    break;

	default:
	    (void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
	}

    semGive (&pCtrl->muteSem);

    return (status);
    }

/*******************************************************************************
*
* ataBlkRW - read or write sectors to a ATA/IDE disk.
*
* Read or write sectors to a ATA/IDE disk.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS ataBlkRW
    (
    ATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf,
    int     direction
    )
    {
    ATA_CTRL  *pCtrl	= &ataCtrl[pDev->ctrl];
    ATA_DRIVE *pDrive	= &pCtrl->drive[pDev->drive];
    BLK_DEV   *pBlkdev	= &pDev->blkDev;
    ATA_TYPE  *pType	= &ataTypes[pDev->ctrl][pDev->drive];
    int       status	= ERROR;
    int       retryRW0	= 0;
    int       retryRW1	= 0;
    int       retrySeek	= 0;
    int       cylinder;
    int       head;
    int       sector;
    int       nSecs;
    int       ix;

    /* sanity check */

    if (!pCtrl->installed)
        return (ERROR);

    nSecs = pBlkdev->bd_nBlocks;

    if ((startBlk + nBlks) > nSecs)
	{
	ATA_DEBUG_MSG (1, "startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, 
                       nSecs, 0, 0, 0);

	return (ERROR);
	}

    startBlk += pDev->blkOffset;

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    for (ix = 0; ix < nBlks; ix += nSecs)
	{

	if (pDrive->okLba)
	    {
	    head     = (startBlk & 0x0f000000) >> 24;
	    cylinder = (startBlk & 0x00ffff00) >> 8;
	    sector   = (startBlk & 0x000000ff);
	    }
	else
	    {
	    cylinder = startBlk / (pType->sectors * pType->heads);
	    sector   = startBlk % (pType->sectors * pType->heads);
	    head     = sector / pType->sectors;
	    sector   = sector % pType->sectors + 1;
	    }
	nSecs    = min (nBlks - ix, ATA_MAX_RW_SECTORS);

	retryRW1 = 0;
	retryRW0 = 0;

	while (ataRW(pDev->ctrl, pDev->drive, cylinder, head, sector, 
	       pBuf, nSecs, direction) != OK)
	    {

	    if (++retryRW0 > ataRetry)
		{
	        (void)ataCmd (pDev->ctrl, pDev->drive, ATA_CMD_RECALIB, 0, 0);

	        if (++retryRW1 > ataRetry)
		    goto done;

	        retrySeek = 0;

	        while (ataCmd (pDev->ctrl, pDev->drive, ATA_CMD_SEEK, cylinder,
			       head) != OK)

	            if (++retrySeek > ataRetry)
		        goto done;

	        retryRW0 = 0;
		}
	    }

        startBlk += nSecs;
        pBuf += pBlkdev->bd_bytesPerBlk * nSecs;
	}

    status = OK;

done:

    if (status == ERROR)
        (void)errnoSet (S_ioLib_DEVICE_ERROR);

    semGive (&pCtrl->muteSem);

    return (status);
    }

/*******************************************************************************
*
* ataIntr - ATA/IDE controller interrupt handler.
*
* RETURNS: N/A
*/

LOCAL void ataIntr
    (
    int ctrl
    )

⌨️ 快捷键说明

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