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

📄 atadrv.c

📁 用于EQUATOR处理器上的FAT32文件系统(vxWorks5.5)
💻 C
📖 第 1 页 / 共 3 页
字号:
	        pDrive->pioMode = 0;

	    if ((pDrive->okIordy) && (pParam->valid & 0x02))	/* PIO 3,4 */
		{
		if (pParam->advancedPio & 0x01)
		    pDrive->pioMode = 3;
		if (pParam->advancedPio & 0x02)
		    pDrive->pioMode = 4;
		}

	    /* find out supported max DMA mode */

	    if ((pDrive->okDma) && (pParam->valid & 0x02))
		{
	        pDrive->singleDmaMode = (pParam->dmaMode >> 8) & 0x03;
		if (pDrive->singleDmaMode >= 2)
	            pDrive->singleDmaMode = 0;
		pDrive->multiDmaMode  = 0;

		if (pParam->singleDma & 0x04)
		    pDrive->singleDmaMode = 2;
		else if (pParam->singleDma & 0x02)
		    pDrive->singleDmaMode = 1;
		else if (pParam->singleDma & 0x01)
		    pDrive->singleDmaMode = 0;

		if (pParam->multiDma & 0x04)
		    pDrive->multiDmaMode = 2;
		else if (pParam->multiDma & 0x02)
		    pDrive->multiDmaMode = 1;
		else if (pParam->multiDma & 0x01)
		    pDrive->multiDmaMode = 0;
		}

	    /* find out transfer mode to use */

	    pDrive->rwBits = configType & ATA_BITS_MASK;
	    pDrive->rwPio  = configType & ATA_PIO_MASK;
	    pDrive->rwDma  = configType & ATA_DMA_MASK;
	    pDrive->rwMode = ATA_PIO_DEF_W;

	    switch (configType & ATA_MODE_MASK)
		{
		case ATA_PIO_0:
		case ATA_PIO_1:
		case ATA_PIO_2:
		case ATA_PIO_3:
		case ATA_PIO_4:
		case ATA_PIO_DEF_0:
		case ATA_PIO_DEF_1:
	            pDrive->rwMode = configType & ATA_MODE_MASK;
		    break;
		case ATA_PIO_AUTO:
	            pDrive->rwMode = ATA_PIO_W_0 + pDrive->pioMode;
		    break;
		case ATA_DMA_0:
		case ATA_DMA_1:
		case ATA_DMA_2:
	            if (pDrive->okDma)
		        {
		        if (pDrive->rwDma == ATA_DMA_SINGLE)
	                    pDrive->rwMode |= ATA_DMA_SINGLE_0;
		        if (pDrive->rwDma == ATA_DMA_MULTI)
	                    pDrive->rwMode |= ATA_DMA_MULTI_0;
		        }
		    break;
		case ATA_DMA_AUTO:
	            if (pDrive->okDma)
		        {
		        if (pDrive->rwDma == ATA_DMA_SINGLE)
	                    pDrive->rwMode = ATA_DMA_SINGLE_0 + 
					     pDrive->singleDmaMode;
		        if (pDrive->rwDma == ATA_DMA_MULTI)
	                    pDrive->rwMode = ATA_DMA_MULTI_0 + 
					     pDrive->multiDmaMode;
		        }
		    break;
		default:
		    break;
		}
	    
	    /* set the transfer mode */

	    (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE,
			   pDrive->rwMode);

	    if (pDrive->rwPio == ATA_PIO_MULTI)
		{
	        if (pDrive->okMulti)
	            (void) ataCmd (ctrl, drive, ATA_CMD_SET_MULTI,
			           pDrive->multiSecs, NULL);
		else
		    pDrive->rwPio = ATA_PIO_SINGLE;
		}
	    }

	pCtrl->installed = TRUE;

#ifdef  ATA_DEBUG
        printErr ("ataDrv Calling sysAtaInit (if present):\n");
#endif  /* ATA_DEBUG */
 
	/* Call system INIT routine to allow proper PIO mode setup */
        SYS_ATA_INIT_RTN (ctrl);
 
#ifdef  ATA_DEBUG
        printErr ("ataDrv sysAtaInit returned:\n");
#endif  /* ATA_DEBUG */

	semGive (&pCtrl->muteSem);
	}

    return (OK);
    }

/*******************************************************************************
*
* ataDevCreate - create a device for a ATA/IDE disk
*
* This routine creates a device for a specified ATA/IDE disk.
*
* <drive> is a drive number for the hard drive; it must be 0 or 1.
*
* The <nBlocks> parameter specifies the size of the device in blocks.
* If <nBlocks> is zero, the whole disk is used.
*
* The <blkOffset> parameter specifies an offset, in blocks, from the start
* of the device to be used when writing or reading the hard disk.  This
* offset is added to the block numbers passed by the file system during
* disk accesses.  (VxWorks file systems always use block numbers beginning
* at zero for the start of a device.)
*
*
* RETURNS:
* A pointer to a block device structure (BLK_DEV) or NULL if memory cannot
* be allocated for the device structure.
*
* SEE ALSO: dosFsMkfs(), dosFsDevInit(), rt11FsDevInit(), rt11FsMkfs(),
* rawFsDevInit()
*/

BLK_DEV *ataDevCreate
    (
    int ctrl,
    int drive,
    int nBlocks,
    int blkOffset
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[ctrl];
    ATA_TYPE *pType	= &ataTypes[ctrl][drive];
    ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    ATA_DEV *pDev;
    BLK_DEV *pBlkdev;
    int	    maxBlks;



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

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

    pBlkdev = &pDev->blkDev;


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

    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);

    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)
	{
#ifdef	ATA_DEBUG
	printErr ("startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, nSecs);
#endif	/* ATA_DEBUG */
	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);

⌨️ 快捷键说明

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