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

📄 idedrv.c

📁 这个软件主要是介绍Vxwork驱动编写
💻 C
📖 第 1 页 / 共 2 页
字号:

	default:
	    (void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
	}

doneIoctl:
    semGive (&ideMuteSem);
    return (status);
    }

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

LOCAL STATUS ideBlkRW
    (
    IDE_DEV *pIdeDev,
    int startBlk,
    int nBlks,
    char *pBuf,
    int direction
    )
    {
    BLK_DEV *pBlkDev = &pIdeDev->blkDev;
    int cylinder;
    int head;
    int sector;
    int ix;
    int nSecs;
    int retryRW0 = 0;
    int retryRW1 = 0;
    int retrySeek = 0;
    int status = ERROR;
    IDE_TYPE *pType = &ideTypes[pIdeDev->drive];

    /* sanity check */

    nSecs =  pBlkDev->bd_nBlocks;
    if ((startBlk + nBlks) > nSecs)
	{
        if (ideDebugErr)
	    printErr ("startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, nSecs);
	return (ERROR);
	}

    startBlk += pIdeDev->blkOffset;

    semTake (&ideMuteSem, WAIT_FOREVER);

    for (ix = 0; ix < nBlks; ix += nSecs)
	{
	cylinder = startBlk / (pType->sectorsTrack * pType->heads);
	sector   = startBlk % (pType->sectorsTrack * pType->heads);
	head     = sector / pType->sectorsTrack;
	sector   = sector % pType->sectorsTrack + 1;
	nSecs    = min (nBlks - ix, pType->sectorsTrack - sector + 1);

	retrySeek = 0;
	while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
	    if (++retrySeek > ideRetry)
		goto done;
	
	retryRW1 = 0;
	retryRW0 = 0;
	while (ideRW (pIdeDev->drive, cylinder, head, sector, 
	  pBuf, nSecs, direction) != OK)
	    {
	    if (++retryRW0 > ideRetry)
		{
	        (void) ideRecalib (pIdeDev->drive);
	        if (++retryRW1 > ideRetry)
		    goto done;
	        retrySeek = 0;
	        while (ideSeek(pIdeDev->drive, cylinder, head) != OK)
	            if (++retrySeek > ideRetry)
		        goto done;
	        retryRW0 = 0;
		}
	    }

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

    status = OK;

done:
    if (status == ERROR)
        (void)errnoSet (S_ioLib_DEVICE_ERROR);
    semGive (&ideMuteSem);
    return (status);
    }

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

LOCAL void ideIntr
    (
    int ctrl
    )
    {
    ideIntCount++;	/* XXX */
    ideStatus = sysInByte (IDE_STATUS);
    semGive (&ideSyncSem);
    }

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

LOCAL void ideWdog
    (
    int ctrl
    )
    {
    ideWaitForever = FALSE;
    }

/*******************************************************************************
*
* ideWait - wait the drive ready
*
* Wait the drive ready
*
* RETURNS: OK, ERROR if the drive didn't become ready in certain period of time.
*/

LOCAL void ideWait
    (
    int request
    )
    {

    switch (request)
	{
	case STAT_READY:
	    wdStart (ideWid, (sysClkRateGet() * ideWdSec), (FUNCPTR)ideInit, 0);
            while (sysInByte (IDE_STATUS) & STAT_BUSY)
	        ;
            while ((sysInByte (IDE_STATUS) & STAT_READY) == 0)
	        ;
	    wdCancel (ideWid);
	    break;

	case STAT_DRQ:
            while ((sysInByte (IDE_STATUS) & STAT_DRQ) == 0)
	        ;
	    break;

	case STAT_SEEKCMPLT:
            while ((sysInByte (IDE_STATUS) & STAT_SEEKCMPLT) == 0)
	        ;
	    break;
	}

    if (ideDebug)
	printErr ("ideWait end: \n");
    }

/*******************************************************************************
*
* ideInit - init a IDE disk controller
*
* This routine initializes a IDE disk controller.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL void ideInit (void)
    {
    int ix;

    sysOutByte (IDE_D_CONTROL, CTL_RST | CTL_IDS);
    for (ix = 0; ix < 100; ix++)
        sysDelay ();

    sysOutByte (IDE_D_CONTROL, CTL_IDS);
    for (ix = 0; ix < 100; ix++)
        sysDelay ();
    while ((sysInByte (IDE_STATUS) & STAT_BUSY) && (ideWaitForever))
	;

    sysOutByte (IDE_D_CONTROL, CTL_4BIT);
    for (ix = 0; ix < 100; ix++)
        sysDelay ();
    while (((sysInByte (IDE_STATUS) & STAT_READY) == 0) && (ideWaitForever))
	;

    semBInit (&ideSyncSem, SEM_Q_FIFO, SEM_EMPTY);

    if (ideDebug)
	printErr ("ideInit end: \n");
    }

/*******************************************************************************
*
* ideDiagnose - diagnose the drive
*
* Diagnose the drive
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS ideDiagnose (void)
    {
    int error;
    int semStatus;

    sysOutByte (IDE_SDH, SDH_IBM);
    ideWait (STAT_READY);

    sysOutByte (IDE_COMMAND, CMD_DIAGNOSE);
    semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);

    if (((error = sysInByte(IDE_ERROR)) != DIAG_OK) || (semStatus == ERROR))
	{
	if (ideDebugErr)
	    printErr ("ideDiagnose: status=0x%x error=0x%x\n", 
		      ideStatus, error);
	return (ERROR);
	}

    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("ideDiagnose end: \n");

    return (OK);
    }

/*******************************************************************************
*
* idePinit - Initialize drive parameters
*
* Initialize drive parameters.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS idePinit
    (
    int drive
    )
    {
    int status;
    int error;
    int semStatus;
    int retryCount = 0;
    IDE_TYPE *pType = &ideTypes[drive];

retryPinit:
    sysOutByte (IDE_CYL_LO, pType->cylinders);
    sysOutByte (IDE_CYL_HI, pType->cylinders >> 8);
    sysOutByte (IDE_SECCNT, pType->sectorsTrack);
    sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | ((pType->heads & 0xf) - 1));
    ideWait (STAT_READY);

    sysOutByte (IDE_COMMAND, CMD_INITP);
    semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);

    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	{
	error = sysInByte (IDE_ERROR);
	status = sysInByte (IDE_STATUS);
	ideInit ();
	if (ideDebugErr)
            printErr ("idePinit%d err: stat=0x%x 0x%x error=0x%x\n",
	              drive, ideStatus, status, error);
	if (++retryCount < ideRetry)
	    goto retryPinit;
	return (ERROR);
	}

    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("idePinit%d end: \n", drive);

    return (OK);
    }

/*******************************************************************************
*
* idePread - Read drive parameters
*
* Read drive parameters.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS idePread
    (
    int drive,
    void *buffer
    )
    {
    int status;
    int error;
    int semStatus;
    int retryCount = 0;

retryPread:
    sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
    ideWait (STAT_READY);

    sysOutByte (IDE_COMMAND, CMD_READP);
    semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);

    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	{
	error = sysInByte (IDE_ERROR);
	status = sysInByte (IDE_STATUS);
	ideInit ();
	if (ideDebugErr)
            printErr ("idePread%d err: stat=0x%x 0x%x error=0x%x\n",
	              drive, ideStatus, status, error);
	if (++retryCount < ideRetry)
	    goto retryPread;
	return (ERROR);
	}

    ideWait (STAT_DRQ);

    sysInWordString (IDE_DATA, (short *)buffer, 256);

    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("idePread%d end: \n", drive);

    return (OK);
    }
/*******************************************************************************
*
* ideRecalib - recalibrate the drive
*
* Recalibrate the drive
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS ideRecalib
    (
    int drive
    )
    {
    int status;
    int error;
    int semStatus;
    int retryCount = 0;

retryRecalib:
    sysOutByte (IDE_SDH, SDH_IBM | (drive << 4));
    ideWait (STAT_READY);

    sysOutByte (IDE_COMMAND, CMD_RECALIB);
    semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);

    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	{
	error = sysInByte (IDE_ERROR);
	status = sysInByte (IDE_STATUS);
	ideInit ();
	if (ideDebugErr)
	    printErr ("ideRecalib%d err: status=0x%x 0x%x error=0x%x\n",
	              drive, ideStatus, status, error);
	if (++retryCount < ideRetry)
	    goto retryRecalib;
	return (ERROR);
	}
    
    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("ideRecalib%d end: \n", drive);

    return (OK);
    }

/*******************************************************************************
*
* ideSeek - seek the drive heads to the specified cylinder
*
* Seek the drive heads to the specified cylinder
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS ideSeek
    (
    int drive,
    int cylinder,
    int head
    )
    {
    int status;
    int error;
    int semStatus;
    int retryCount = 0;

retrySeek:
    sysOutByte (IDE_CYL_LO, cylinder);
    sysOutByte (IDE_CYL_HI, cylinder>>8);
    sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
    ideWait (STAT_READY);

    sysOutByte (IDE_COMMAND, CMD_SEEK);
    semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);

    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	{
	error = sysInByte (IDE_ERROR);
	status = sysInByte (IDE_STATUS);
	ideInit ();
	if (ideDebugErr)
	    printErr ("ideSeek%d err: c=%d h=%d status=0x%x 0x%x error=0x%x\n",
		      drive, cylinder, head, ideStatus, status, error);
	if (++retryCount < ideRetry)
	    goto retrySeek;
	return (ERROR);
	}

    ideWait (STAT_SEEKCMPLT);

    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("ideSeek%d end: c=%d h=%d\n", drive, cylinder, head);

    return (OK);
    }

/*******************************************************************************
*
* ideRW - 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 ideRW
    (
    int drive,
    int cylinder,
    int head,
    int sector,
    void *buffer,
    int nSecs,
    int direction
    )
    {
    int ix;
    int status;
    int error;
    int semStatus;
    int retryCount = 0;
    short *pBuf = (short *)buffer;
    IDE_TYPE *pType = &ideTypes[drive];
    int nWords = pType->bytesSector >> 1;

retryRW:
    sysOutByte (IDE_PRECOMP, pType->precomp);
    sysOutByte (IDE_SECCNT, nSecs);
    sysOutByte (IDE_SECTOR, sector);
    sysOutByte (IDE_CYL_LO, cylinder);
    sysOutByte (IDE_CYL_HI, cylinder>>8);
    sysOutByte (IDE_SDH, SDH_IBM | (drive << 4) | (head & 0xf));
    ideWait (STAT_READY);

    if (direction == O_WRONLY)
	{
	sysOutByte (IDE_COMMAND, CMD_WRITE);
	for (ix = 0; ix < nSecs; ix++)
	    {
            ideWait (STAT_DRQ);
	    sysOutWordString (IDE_DATA, pBuf, nWords);
            semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
    	    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	        goto errorRW;
	    pBuf += nWords;
            }
	}
    else
	{
	sysOutByte (IDE_COMMAND, CMD_READ);
	for (ix = 0; ix < nSecs; ix++)
	    {
            semStatus = semTake (&ideSyncSem, sysClkRateGet() * ideSemSec);
    	    if ((ideStatus & STAT_ERR) || (semStatus == ERROR))
	        goto errorRW;
            ideWait (STAT_DRQ);
	    sysInWordString (IDE_DATA, pBuf, nWords);
	    pBuf += nWords;
	    }
	}

    ideWait (STAT_READY);

    if (ideDebug)
	printErr ("ideRW%d end: c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
                  drive, cylinder, head, sector, (int)buffer, nSecs, direction);

    return (OK);

errorRW:
    error = sysInByte (IDE_ERROR);
    status = sysInByte (IDE_STATUS);
    ideInit ();
    if (ideDebugErr)
	{
        printErr ("ideRW%d err: c=%d h=%d s=%d buf=0x%x n=%d dir=%d ",
                  drive, cylinder, head, sector, (int)buffer, nSecs, direction);
        printErr ("stat=0x%x 0x%x error=0x%x\n", ideStatus, status, error);
	}
    if (++retryCount < ideRetry)
	goto retryRW;
    return (ERROR);
    }

/*******************************************************************************
*
* ideFormat - format the current track
*
* format the current track; not supported.
*
* RETURNS: ERROR always.
*/

LOCAL STATUS ideFormat
    (
    int drive,
    int cylinder,
    int head,
    int interleave
    )
    {
    return (ERROR);
    }

⌨️ 快捷键说明

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