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

📄 atadrv.c

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

    if (ataDevIdentify (ctrl, drive) != OK)
        goto driveInitExit;

    /* Set Reset function according to device type */

    if (pDrive->type == ATA_TYPE_ATA)
        pDrive->Reset = ataInit;
    else if (pDrive->type == ATA_TYPE_ATAPI)
        pDrive->Reset = ataPiInit;

    if (pDrive->type == ATA_TYPE_ATA)
        {

        if (ataPread (ctrl, drive, (char *)pParam) == OK)
            {

	    if ((pCtrl->ctrlType == ATA_PCMCIA) ||
		((pCtrl->ctrlType != ATA_PCMCIA) && (drive == 0)))
		{

                if (ataCmd (ctrl, drive, ATA_CMD_DIAGNOSE, 0, 0) != OK)
		    {
	            semGive (&pCtrl->muteSem);

	            return (ERROR);
		    }
		}

            /* find out geometry */

            if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE)
                {
                (void) ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0);
                (void) ataPread (ctrl, drive, (char *)pParam);
                }
            else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL)
                {
                pType->cylinders = pParam->cylinders - 1;
                pType->heads     = pParam->heads;
                pType->sectors   = pParam->sectors;
                }
            else if ((configType & ATA_GEO_MASK) == ATA_GEO_CURRENT)
                {

                if ((pParam->currentCylinders != 0) &&
                    (pParam->currentHeads != 0) &&
                    (pParam->currentSectors != 0))
                    {
                    pType->cylinders = pParam->currentCylinders - 1;
                    pType->heads     = pParam->currentHeads;
                    pType->sectors   = pParam->currentSectors;
                    }
                else
                    {
                    pType->cylinders = pParam->cylinders - 1;
                    pType->heads     = pParam->heads;
                    pType->sectors   = pParam->sectors;
                    }
                }

            /* 
             * Not all modern hard drives report a true capacity value 
             * in their IDENTIFY DEVICE CHS fields.
             * For example, a Western Digital 20 Gb drive reports 
             * its CHS as 16383 cylinders, 16 heads, and 63 spt.
             * This is about 8.4GB, but the LBA sectors is reported
             * as 0x02607780, which is closer to 20Gb, the true capacity
             * of the drive.  The reason for this is PC BIOS can have a 
             * 8.4GB limitation, and drive manufacturers have broken the 
             * ATA specification to be compatable.  Negative competition. 
             * Note that the ATA specifications original limit is 
             * about 136.9 Gb, however when combinined with a PC BIOS 
             * interface, a 8.4 Gb limit is produced.    
             * VxWorks does not have such limitations being a true 32bit OS,
             * but since the drive manufactures are not honoring the CHS
             * values, we have to allow for devices that demand "pure" LBA
             * and present incorrect CHS.
             * If the drive supports Logical Block Addresses (LBA)
             * then we need to check the field located at 16bit words 60 & 61,
             * "Total number of user addressable sectors (LBA mode only)". 
             * If this value is greater than the CHS fields report, 
             * then 60-61 holds the true size of the disk and that 
             * will be reported to the block device interface.
             * Note that the CHS values are still left as the disk reported.
             * This is tracked at WRS as SPR#22830
             */

            if (pParam->capabilities & 0x0200)  /* if (drive supports LBA) */
                {
                ataLbaTotalSecs[ctrl][drive] =  (UINT32) 
			((((UINT32) ((pParam->sectors0) & 0x0000ffff)) <<  0) | 
			 (((UINT32) ((pParam->sectors1) & 0x0000ffff)) << 16));

                ATA_DEBUG_MSG (1, "ID_DRIVE reports LBA (60-61) as 0x%08lx\n",
                               ataLbaTotalSecs[ctrl][drive], 0, 0, 0, 0, 0);
                }

            /*
             * reinitialize the controller with parameters read from the
             * controller.
             */

            (void) ataCmd (ctrl, drive, ATA_CMD_INITP, 0, 0);

            /* recalibrate (this command !!! is absent in ATA-4) */

            (void) ataCmd (ctrl, drive, ATA_CMD_RECALIB, 0, 0);
            }
        else
            {
            pDrive->state = ATA_DEV_PREAD_F;
            goto driveInitExit;
            }
        }
    else if (pDrive->type == ATA_TYPE_ATAPI)
        {
        /* Although ATAPI device parameters have been read by ataDevIdentify(), 
         * execute ATAPI Identify Device command to allow ATA commands 
         * acceptance by an ATAPI device after Diagnostic or Reset commands. 
         */

        if (ataPiPread (ctrl, drive, pParam) != OK)
            {
            pDrive->state = ATA_DEV_PREAD_F;

            goto driveInitExit;
            }
        }

    /* find out supported capabilities of the drive */

    pDrive->multiSecs = pParam->multiSecs & 0x00ff;
    pDrive->okMulti   = (pDrive->multiSecs != 0) ? TRUE : FALSE;
    pDrive->okIordy   = (pParam->capabilities & 0x0800) ? TRUE : FALSE;
    pDrive->okLba     = (pParam->capabilities & 0x0200) ? TRUE : FALSE;
    pDrive->okDma     = (pParam->capabilities & 0x0100) ? TRUE : FALSE;

    /* find out supported max PIO mode */

    pDrive->pioMode = (pParam->pioMode >> 8) & 0x03;	/* PIO 0,1,2 */

    if (pDrive->pioMode > 2)
        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);

    /* Disable reverting to power on defaults */

    (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_DISABLE_REVE, 0);

    /* Set multiple mode (multisector read/write) */

    if ((pDrive->rwPio == ATA_PIO_MULTI) && (pDrive->type == ATA_TYPE_ATA))
        {

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

    pDrive->state = ATA_DEV_OK;

driveInitExit:

    semGive (&pCtrl->muteSem);

    if (pDrive->state != ATA_DEV_OK)
        {
        ATA_DEBUG_MSG (1, "ataDriveInit%d/%d: ERROR: state=%d dev=0x%x "
                       "status=0x%x error=0x%x\n", ctrl, drive, pDrive->state, 
                       ATA_IO_BYTE_READ (pCtrl->sdh), 
                       ATA_IO_BYTE_READ (pCtrl->status), 
                       ATA_IO_BYTE_READ (pCtrl->error));
        return (ERROR);
        }

    return (OK);
    } /* ataDriveInit */

/*******************************************************************************
*
* ataDrv - initialize the ATA driver
*
* This routine initializes the ATA/IDE/ATAPI CDROM driver, sets up interrupt
* vectors, and performs hardware initialization of the ATA/IDE chip.
*
* This routine must be called exactly once, before any reads, writes,
* or calls to ataDevCreate().  Normally, it is called by usrRoot()
* in usrConfig.c.
*
* RETURNS: OK, or ERROR if initialization fails.
*
* SEE ALSO: ataDevCreate()
*/

STATUS ataDrv
    (
    int  ctrl,			/* controller no. */
    int  drives,		/* number of drives */
    int  vector,		/* interrupt vector */
    int  level,			/* interrupt level */
    int  configType,		/* configuration type */
    int  semTimeout,		/* timeout seconds for sync semaphore */
    int  wdgTimeout		/* timeout seconds for watch dog */
    )
    {
    ATA_CTRL        *pCtrl	= &ataCtrl[ctrl];
    ATA_RESOURCE    *pAta	= &ataResources[ctrl];
    PCCARD_RESOURCE *pResource	= &pAta->resource;
    ATA_DRIVE       *pDrive;
    ATA_PARAM       *pParam;
    ATA_TYPE        *pType;
    int             drive;
    int             ix;

    if ((ctrl >= ATA_MAX_CTRLS) || (drives > ATA_MAX_DRIVES))
	return (ERROR);

    if (!ataDrvInstalled)
	{

	for (ix = 0; ix < ATA_MAX_CTRLS; ix++)
            ataCtrl[ix].wdgId = wdCreate ();

    	ataDrvInstalled = TRUE;
	}

    if (!pCtrl->installed)
	{

	if (semTimeout == 0)
	    pCtrl->semTimeout = ATA_SEM_TIMEOUT_DEF;
	else
	    pCtrl->semTimeout = semTimeout;

	if (wdgTimeout == 0)
	    pCtrl->wdgTimeout = ATA_WDG_TIMEOUT_DEF;
	else
	    pCtrl->wdgTimeout = wdgTimeout;

        semBInit (&pCtrl->syncSem, SEM_Q_FIFO, SEM_EMPTY);
        semMInit (&pCtrl->muteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE |
	          SEM_INVERSION_SAFE);

	pCtrl->data	= ATA_DATA	(pResource->ioStart[0]);
	pCtrl->error	= ATA_ERROR	(pResource->ioStart[0]);
	pCtrl->feature	= ATA_FEATURE	(pResource->ioStart[0]);
	pCtrl->seccnt	= ATA_SECCNT	(pResource->ioStart[0]);
	pCtrl->sector	= ATA_SECTOR	(pResource->ioStart[0]);
	pCtrl->cylLo	= ATA_CYL_LO	(pResource->ioStart[0]);
	pCtrl->cylHi	= ATA_CYL_HI	(pResource->ioStart[0]);
	pCtrl->sdh	= ATA_SDH	(pResource->ioStart[0]);
	pCtrl->command	= ATA_COMMAND	(pResource->ioStart[0]);
	pCtrl->status	= ATA_STATUS	(pResource->ioStart[0]);
	pCtrl->aStatus	= ATA_A_STATUS	(pResource->ioStart[1]);
	pCtrl->dControl	= ATA_D_CONTROL (pResource->ioStart[1]);
	pCtrl->dAddress	= ATA_D_ADDRESS (pResource->ioStart[1]);

        (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (vector),
		           (VOIDFUNCPTR)ataIntr, ctrl);
        sysIntEnablePIC (level);	/* unmask the interrupt level */
	pCtrl->intLevel = level;
	pCtrl->wdgOkay  = TRUE;
	pCtrl->configType = configType;

	semTake (&pCtrl->muteSem, WAIT_FOREVER);

	pCtrl->installed = TRUE;

        for (drive = 0; drive < drives; drive++)
	    {
	    pType  = &ataTypes[ctrl][drive];
	    pDrive = &pCtrl->drive[drive];
	    pParam = &pDrive->param;
            pDrive->state	= ATA_DEV_INIT;
            pDrive->type	= ATA_TYPE_INIT;
            pDrive->diagCode	= 0;
            pDrive->Reset	= ataInit;

            ataDriveInit (ctrl, drive);
            }

        ATA_DEBUG_MSG (1, "ataDrv Calling sysAtaInit (if present):\n",
                      0, 0, 0, 0, 0, 0);
 
	/* Call system INIT routine to allow proper PIO mode setup */

        SYS_ATA_INIT_RTN (ctrl);
 
        ATA_DEBUG_MSG (1, "ataDrv sysAtaInit returned:\n",
                      0, 0, 0, 0, 0, 0);

	semGive (&pCtrl->muteSem);
	}

    return (OK);
    }

/*******************************************************************************
*
* ataDevCreate - create a device for a ATA/IDE disk
*
* This routine creates a device for a specified ATA/IDE or ATAPI CDROM disk.
*
* <ctrl> is a controller number for the ATA controller; the primary controller
* is 0.  The maximum is specified via ATA_MAX_CTRLS.
*
* <drive> is the drive number for the ATA hard drive; the master drive
* is 0.  The maximum is specified via ATA_MAX_DRIVES.
*
* 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,     /* ATA controller number, 0 is the primary controller */
    int drive,    /* ATA drive number, 0 is the master drive */
    int nBlocks,  /* number of blocks on device, 0 = use entire disc */
    int blkOffset /* offset BLK_DEV nBlocks from the start of the drive */
    )
    {
    ATA_CTRL  *pCtrl	= &ataCtrl[ctrl];
    ATA_TYPE  *pType	= &ataTypes[ctrl][drive];
    ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    ATA_PARAM *pParam	= &pDrive->param; /* move * */
    ATA_DEV   *pDev;
    BLK_DEV   *pBlkdev;
    int	      maxBlks;

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

⌨️ 快捷键说明

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