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

📄 atadrv.c

📁 用于EQUATOR处理器上的FAT32文件系统(vxWorks5.5)
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;
#ifdef ATA_DEBUG
		printErr ("Using LBA value: maxBlks =0x%08lx\n", maxBlks);
#endif /* ATA_DEBUG */
	}
    else /* just use CHS */
	{
	maxBlks = pParam->sectors1 & 0xfffff;
	maxBlks = maxBlks << 16;
	maxBlks += pParam->sectors0;
#ifdef ATA_DEBUG
		printErr ("Using CHS value: maxBlks =0x%08lx\n", maxBlks);
#endif /* ATA_DEBUG */
	}

    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	= FALSE;  //mlg changed from 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;
    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 / (pBlkdev->bd_blksPerTrack * pBlkdev->bd_nHeads);
	    sector   = startBlk % (pBlkdev->bd_blksPerTrack * pBlkdev->bd_nHeads);
	    head     = sector / pBlkdev->bd_blksPerTrack;
	    sector   = sector % pBlkdev->bd_blksPerTrack + 1;

	    }
	nSecs    = min (nBlks - ix, ATA_MAX_RW_SECTORS);

	retryRW1 = 3;
	retryRW0 = 3;
	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, NULL,
			      NULL);
	        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
*/

void ataIntr
    (
    int ctrl
    )
    {
    ATA_CTRL *pCtrl	= &ataCtrl[ctrl];
//    UINT8     status;

// this check kills performance so I am commenting it out
//	status = sysInByte( busMasterRegs + BM_STATUS_REG);
//	if (status & 0x4)
//		sysOutByte(busMasterRegs+BM_STATUS_REG,status);
    
    pCtrl->intStatus = sysInByte (pCtrl->status);
#ifdef ATA_DEBUG
	logMsg("ataIntr: status = 0x%x\n",pCtrl->intStatus,0,0,0,0,0);
#endif
    pCtrl->intCount++;
    semGive (&pCtrl->syncSem);
 
    }

/*******************************************************************************
*
* ataWdog - ATA/IDE controller watchdog handler.
*
* RETURNS: N/A
*/

LOCAL void ataWdog
    (
    int ctrl
    )
    {
    volatile ATA_CTRL *pCtrl	= (volatile ATA_CTRL *)&ataCtrl[ctrl];

    pCtrl->wdgOkay = FALSE;
    }

/*******************************************************************************
*
* ataWait - wait the drive ready
*
* Wait the drive ready
*
* RETURNS: OK, ERROR if the drive didn't become ready in certain period of time.
*/
extern BOOL kernelState;
LOCAL void ataWait
    (
    int ctrl,
    int request
    )
    {
    volatile ATA_CTRL *pCtrl	= (volatile ATA_CTRL *)&ataCtrl[ctrl];

#ifdef	ATA_DEBUG
    printErr ("ataWait: ctrl=%d  request=0x%x\n", ctrl, request);
#endif	/* ATA_DEBUG */

    switch (request)
	{
	case ATA_STAT_READY:
	    wdStart (pCtrl->wdgId, (sysClkRateGet() * pCtrl->wdgTimeout), 

⌨️ 快捷键说明

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