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

📄 atadrv.c

📁 用于EQUATOR处理器上的FAT32文件系统(vxWorks5.5)
💻 C
📖 第 1 页 / 共 5 页
字号:
}



void    sysOutLongString
    (
    ULONG port,
    ULONG *pData, 
    int count
    )
    {
    int i;
    for(i=0;i<count;i++)
       sysOutLong(port,*(pData+i));
    }


/*******************************************************************************
*
* ataDrv - initialize the ATA driver
*
* This routine initializes the ATA/IDE 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 */
    BOOL 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_CTRL *pCtrl;
    ATA_RESOURCE *pAta;
    PCCARD_RESOURCE *pResource;
    ATA_DRIVE *pDrive;
    ATA_PARAM *pParam;
    ATA_TYPE *pType;
    int drive;
    int ix;
	int status;
	int numberOfDrives = 0;

    pCtrl		= &ataCtrl[ctrl];
    pAta		= &ataResources[ctrl];
    pResource	= &pAta->resource;

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


#ifdef  INCLUDE_VT82C686B

        (void) SuperIOintConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ataResources[ctrl].intVector),
		           (VOIDFUNCPTR)ataIntr, ctrl);
    
#else
    status = pciIntConnect((VOIDFUNCPTR *)INUM_TO_IVEC (ataResources[ctrl].intVector),
		           (VOIDFUNCPTR)ataIntr, ctrl);

   if (status != OK) {
#ifdef  ATA_DEBUG
        printErr ("ERROR: pciIntConnect\n");
#endif  /* ATA_DEBUG */
    return status;
   } 
#endif

	pCtrl->intLevel = level;
	pCtrl->wdgOkay  = TRUE;

	semTake (&pCtrl->muteSem, WAIT_FOREVER);

        if (ataInit (ctrl) != OK)
	    {
	    semGive (&pCtrl->muteSem);
	    return (ERROR);
	    }

        for (drive = 0; drive < drives; drive++)
	    {
	    pType  = &ataTypes[ctrl][drive];
	    pDrive = &pCtrl->drive[drive];
	    pParam = &pDrive->param;
	    if (pType->cylinders == 0)
	        return ERROR;

	    if ((pCtrl->ctrlType == ATA_PCMCIA) ||
		((pCtrl->ctrlType != ATA_PCMCIA) && (drive == 0)))
		{
                if (ataCmd (ctrl, drive, ATA_CMD_DIAGNOSE, NULL, NULL) != OK)
		    {
	            semGive (&pCtrl->muteSem);
	            return (ERROR);
		    }
 
		}

	    /* find out geometry */

	    if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE)
	        {
	           if(ataCmd (ctrl, drive, ATA_CMD_INITP, NULL, NULL) != OK) {
				   break;
               }
                if(ataPread (ctrl, drive, (char *)pParam) != OK)
				  break;
	        }
	    else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL)
	        {
                if(ataPread (ctrl, drive, (char *)pParam) != OK)
					break;
	        pType->cylinders = pParam->cylinders - 1;
	        pType->heads	 = pParam->heads;
	        pType->sectors   = pParam->sectors;
  //          pType->bytes     = pParam->bytesSec;

	        }
	    else if ((configType & ATA_GEO_MASK) == ATA_GEO_CURRENT)
	        {
                if(ataPread (ctrl, drive, (char *)pParam) != OK)
					break;

		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));
#ifdef ATA_DEBUG
		printErr ("ID_DRIVE reports LBA (60-61) as 0x%08lx\n",
			ataLbaTotalSecs[ctrl][drive]);
#endif /* ATA_DEBUG */
		}

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

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

            /* recalibrate */

	    (void) ataCmd (ctrl, drive, ATA_CMD_RECALIB, NULL, NULL);

		numberOfDrives++;

	    /* find out supported capabilities of the drive */

	    pDrive->multiSecs = pParam->multiSecs & 0x00ff;
	    pDrive->okMulti = (pDrive->multiSecs) ? 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 (pParam->multiDma & 0x04)
		    pDrive->multiDmaMode = 2;
		else if (pParam->multiDma & 0x02)
		    pDrive->multiDmaMode = 1;
		else if (pParam->multiDma & 0x01)
		    pDrive->multiDmaMode = 0;
        else pDrive->multiDmaMode = -1;
       
  
        /* Is Ultra DMA supported */
        

        if (pParam->valid & 0x04) {
		   if (pParam->ultraDma & 0x20)
		      pDrive->ultraDmaMode = 5;
		   else if (pParam->ultraDma & 0x10)
		      pDrive->ultraDmaMode = 4;
		   else if (pParam->ultraDma & 0x08)
		      pDrive->ultraDmaMode = 3;
		   else if (pParam->ultraDma & 0x04)
		      pDrive->ultraDmaMode = 2;
		   else if (pParam->ultraDma & 0x02)
		      pDrive->ultraDmaMode = 1;
		   else if (pParam->ultraDma & 0x01)
		       pDrive->ultraDmaMode = 0;
        } else
           pDrive->ultraDmaMode = -1;

      
        if (pDrive->ultraDmaMode == -1 &&
            pDrive->multiDmaMode == -1)
            pDrive->okDma = FALSE;
        else
            pDrive->okDma = TRUE;
		

	    /* find out transfer mode to use */

	    pDrive->rwBits = configType & ATA_BITS_MASK;
	    pDrive->rwPio  = configType & ATA_PIO_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;
        }

        if(pDrive->okDma)
       	switch (configType & ATA_DMA_MODE_MASK)
		{
		case ATA_DMA_MULTI_0:
           pDrive->rwDma = ATA_DMA_MULTI_W_0;
           break;
		case ATA_DMA_MULTI_1:
           pDrive->rwDma = ATA_DMA_MULTI_W_1;
           break;
		case ATA_DMA_MULTI_2:
           pDrive->rwDma = ATA_DMA_MULTI_W_2;
           break;
		case ATA_DMA_ULTRA_0:
           pDrive->rwDma = ATA_DMA_ULTRA_W_0;
           break;
		case ATA_DMA_ULTRA_1:
           pDrive->rwDma = ATA_DMA_ULTRA_W_1;
           break;
		case ATA_DMA_ULTRA_2:
           pDrive->rwDma = ATA_DMA_ULTRA_W_2;
           break;
		case ATA_DMA_ULTRA_3:
           pDrive->rwDma = ATA_DMA_ULTRA_W_3;
           break;
		case ATA_DMA_ULTRA_4:
           pDrive->rwDma = ATA_DMA_ULTRA_W_4;
           break;
		case ATA_DMA_ULTRA_5:
           pDrive->rwDma = ATA_DMA_ULTRA_W_5;
           break;
		case ATA_DMA_AUTO:
#if 1
		        if (pDrive->ultraDmaMode != -1)
	                    pDrive->rwDma = ATA_DMA_ULTRA_W_0 + pDrive->ultraDmaMode;
#endif
		        else if (pDrive->multiDmaMode != -1)
	                    pDrive->rwDma = ATA_DMA_MULTI_W_0 + pDrive->multiDmaMode;
    
		    break;
		default:
            //
            // Turn off dma
            //
            
            pDrive->okDma = FALSE;   
		    break;
		} //end switch

  
	    /* set the transfer modes */

	    (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE,
			   pDrive->rwMode);
//        if (pDrive->okDma)     
//	    (void) ataCmd (ctrl, drive, ATA_CMD_SET_FEATURE, ATA_SUB_SET_RWMODE,
//			   pDrive->rwDma);

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

//        ataTuneDrive(ctrl,drive);

    } // end for

    pCtrl->drives = numberOfDrives;

	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;
    ATA_DEV *pDev;
    BLK_DEV *pBlkdev;
    ATA_PARAM *pParam;
    UINT32	    maxBlks;

    pDrive = &pCtrl->drive[drive];
    pParam = &pDrive->param;

⌨️ 快捷键说明

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