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

📄 atadrv.c

📁 promise20265的驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *
 * pci bus master control macros
 *
 ***********************************************************/

#define enableChan(ctrl)  sysOutByte(busMasterRegs[ctrl] + BM_COMMAND_REG, \
                                rwControl[ctrl] | BM_CR_MASK_START )
#define disableChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_COMMAND_REG, \
                                BM_CR_MASK_STOP )
#define clearChan(ctrl) sysOutByte( busMasterRegs[ctrl] + BM_STATUS_REG, \
                              statReg[ctrl] | BM_SR_MASK_INT | BM_SR_MASK_ERR )

       

typedef struct {
   char *  address;
   struct {
     unsigned long count:16;
     unsigned long reserved:15;
     unsigned long EOT:1;
   }bits;             
} PRD_ENTRY,*PPRD_ENTRY;

static STATUS ataDmaSetupXfer(int ctrl, int dir, char *buffer, int count);
static int  ataDmaConfig(int ctrl, UINT32 regAddr );



/* function prototypes */

LOCAL STATUS ataBlkRd	(ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataBlkWrt	(ATA_DEV *pDev, int startBlk, int nBlks, char *p);
LOCAL STATUS ataReset	(ATA_DEV *pDev);
LOCAL STATUS ataStatus	(ATA_DEV *pDev);
LOCAL STATUS ataIoctl	(ATA_DEV *pDev, int function, int arg);
LOCAL STATUS ataBlkRW	(ATA_DEV *pDev, int startBlk, int nBlks, char *p,
			 int direction);
LOCAL void   ataWdog	(int ctrl);
LOCAL void   ataIntr	(int ctrl);
LOCAL STATUS ataInit	(int ctrl, int drive);
LOCAL STATUS ataWait	(int ctrl, int drive, int request, BOOL reset);
LOCAL STATUS ataCmd	(int ctrl, int drive, int cmd, int arg0, int arg1);
LOCAL STATUS ataPread	(int ctrl, int drive, void *p);
LOCAL STATUS ataRW	(int ctrl, int drive, int cylinder, int head, int sec, 
	 		 void *p, int nSecs, int direction);

LOCAL STATUS ataPiBlkRd (ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf);
LOCAL STATUS ataPiBlkWr (ATA_DEV *pDev, int startBlk, int nBlks, char *pBuf);
LOCAL STATUS ataPiIoctl (ATA_DEV *pDev, int function, int arg);
LOCAL STATUS ataPiReset (ATA_DEV *pAtapiDev);
LOCAL STATUS ataPiStatusChk (ATA_DEV *pDev);
LOCAL STATUS ataPiReadCapacity (ATA_DEV *pAtapiDev);
LOCAL STATUS ataPiInit (int ctrl, int dev);

LOCAL STATUS ataPiPread (int ctrl, int drive, void * buffer);
LOCAL STATUS ataDiagnose (int ctrl, int dev);
LOCAL STATUS ataDevIdentify (int ctrl, int dev);
LOCAL STATUS ataDmaRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction);
LOCAL STATUS ataSetbd_readyChanged(ATA_DEV *pAtapiDev);
STATUS ataPiToggleTray(ATA_DEV   *pAtapiDev);
LOCAL STATUS ataPiReadDVDStructure(ATA_DEV *pAtapiDev,void *buffer,int size,int format);
LOCAL STATUS ataPiGetConfiguration(ATA_DEV *pAtapiDev);
/*******************************************************************************
*
* ataStub - block device stub
*
* This routine services as stub for a block device structure's routine pointers.
*
* RETURNS: ERROR always.
*/

LOCAL STATUS ataStub (void)
    {
    return (ERROR);
    } /* ataStub */



ataWaitStatus(int timeNSEC) 
{
    const int i = CPU_MHZ/10;                              
    float cycleTimeNSEC = (1/(float)CPU_MHZ)*i*1000;
    float time = 0;
  
    //printf("ataWaitStatus %f\n",cycleTimeNSEC);
    while (time<timeNSEC) {
        hmpv_mnop(CPU_MHZ/10);
        time+=cycleTimeNSEC;
    }
}
/*******************************************************************************
*
* ataBlkDevFill - fill BLK_DEV strucutre
*
* This routine fills a block device structure with real parameters 
* corresponding to the given device, or with stubs if a device is not detected 
* by prtevious ataDriveInit () call.  The routine considers offset and size 
* requested for the device in ataDevCreate () call.
*
* RETURNS: N/A
*
* SEE ALSO: ataDevCreate (), ataDriveInit ()
*/

LOCAL void ataBlkDevFill
    (
    ATA_DEV *	pDev
    )
    {
    ATA_CTRL *	pCtrl	= &ataCtrl[pDev->ctrl];
    ATA_DRIVE *	pDrive	= &pCtrl->drive[pDev->drive];
    ATA_PARAM *	pParam	= &pDrive->param;
    ATA_TYPE *	pType	= &ataTypes[pDev->ctrl][pDev->drive];
    BLK_DEV *	pBlkDev	= &pDev->blkDev;
    uint32_t	nBlocks	= pDev->nBlocks;
    uint32_t	maxBlks;

    if ( (pDrive->state == ATA_DEV_OK) || (pDrive->state == ATA_DEV_MED_CH) )
        {
	  /* mlg pDrive->state = ATA_DEV_MED_CH; */

        if (pDrive->type == ATA_TYPE_ATA)
            {


	    /* 
	     * 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[pDev->ctrl][pDev->drive] != 0) &&
		 (ataForceCHSonLBA != TRUE)		                &&
		 (ataLbaTotalSecs[pDev->ctrl][pDev->drive] > 
		 (pType->cylinders * pType->heads * pType->sectors)))   
	     {
		  maxBlks = (ataLbaTotalSecs[pDev->ctrl][pDev->drive]) - pDev->blkOffset;
#ifdef ATA_DEBUG
		printErr ("Using LBA value: maxBlks =0x%08lx\n", maxBlks);
#endif /* ATA_DEBUG */
	     }
	     else /* just use CHS */
	     {
	          maxBlks = ((pType->cylinders * pType->heads * pType->sectors) 
				 - pDev->blkOffset);
#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; // 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;
            }
        else if (pDrive->type == ATA_TYPE_ATAPI)
            {
            pBlkDev->bd_nBlocks       = 100;
            pBlkDev->bd_bytesPerBlk   = 2048;
            pBlkDev->bd_blksPerTrack  = pBlkDev->bd_nBlocks;
            pBlkDev->bd_nHeads        = 1;
            if (pParam->config & CONFIG_REMOVABLE)
                pBlkDev->bd_removable = TRUE;
            else
                pBlkDev->bd_removable = FALSE;
            pBlkDev->bd_retry         = 1;
            pBlkDev->bd_mode          = O_RDWR;
            pBlkDev->bd_readyChanged  = TRUE;
            pBlkDev->bd_blkRd         = ataPiBlkRd;
            pBlkDev->bd_blkWrt        = ataPiBlkWr;
            pBlkDev->bd_ioctl         = ataPiIoctl;
            pBlkDev->bd_reset         = ataPiReset;
            pBlkDev->bd_statusChk     = ataPiStatusChk;
	    pDev->ReadCdByte9         = 0x10;
            }
        return;
        }

    /* Set default values */

    pBlkDev->bd_nBlocks 	= 0;
    pBlkDev->bd_bytesPerBlk	= 512;
    pBlkDev->bd_blksPerTrack	= 0;
    pBlkDev->bd_nHeads		= 0;
    pBlkDev->bd_removable	= TRUE;
    pBlkDev->bd_retry		= 1;
    pBlkDev->bd_mode		= O_RDWR;
    pBlkDev->bd_readyChanged	= TRUE;
    pBlkDev->bd_blkRd		= ataStub;
    pBlkDev->bd_blkWrt		= ataStub;
    pBlkDev->bd_ioctl		= ataStub;
    pBlkDev->bd_reset		= ataReset;
    pBlkDev->bd_statusChk	= ataStub;
    } /* ataBlkDevFill */

/*******************************************************************************
*
* ataDriveInit - initialize ATA drive
*
* This routine checks the drive presents, identifies its type, initializes the 
* drive controller and driver control structers.
*
* RETURNS: OK if drive was initialized successfuly, or ERROR.
*/

STATUS ataDriveInit
    (
    int	ctrl,
    int	drive
    )
    {
    ATA_CTRL *	pCtrl		= &ataCtrl[ctrl];
    ATA_DRIVE *	pDrive		= &pCtrl->drive[drive];
    ATA_PARAM *	pParam		= &pDrive->param;
    ATA_TYPE *	pType		= &ataTypes[ctrl][drive];
    int		configType	= pCtrl->configType;	/* configuration type */

    ATA_DEBUG_MSG (1, "ataDriveInit%d/%d: entry:  state %d type %d\n  "
                       ,ctrl,drive,pDrive->state,pDrive->type,0,0);
    if (!pCtrl->installed)
        return (ERROR);
   
    if (pType->cylinders == 0)
        return (ERROR);		/* user specified the device as not present */

    semTake (&ataCtrl[0].muteSem, WAIT_FOREVER);

    /* Identify device presence and its type */


#if FALSE /* Can be changed to FALSE, if Diagnostic command will be avoided */
    if ( (pDrive->state == ATA_DEV_INIT) && (pDrive->type != ATA_TYPE_INIT) )
        { /* device type have been identified by ataDiagnose() call for coupled              device */
        if (pDrive->type == ATA_TYPE_NONE)
            {
            pDrive->state = ATA_DEV_NONE;
            goto driveInitExit;
            }
        }
    else
#endif  
   
#if 0
      if (pDrive->state != ATA_DEV_OK)
      if (ataDevIdentify (ctrl, drive) != OK) 
   		  goto driveInitExit;
#endif     
    /* 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;

//    pDrive->Reset(ctrl,drive);

#if FALSE /* This code may be avoided, since it is not vital necessary. */
    if ( (pDrive->state == ATA_DEV_INIT) && (pDrive->diagCode != 0) )
        { /* diagnostic already have been executed for coupled device */
        if (pDrive->diagCode != ATA_DIAG_PASSED)
            {
            pDrive->state = ATA_DEV_DIAG_F;
            goto driveInitExit;
            }
        }
    else
        if (ataDiagnose (ctrl, drive) != OK)
            goto driveInitExit;
#endif

    if (pDrive->type == ATA_TYPE_ATA)
        {

	  ATA_DEBUG_MSG(3,"calling ataPread\n",0,0,0,0,0,0);

        if (ataPread (ctrl, drive, (char *)pParam) == OK)
            {
   
	  ATA_DEBUG_MSG(3,"after ataPread\n",0,0,0,0,0,0);

            /* find out geometry */

            if ((configType & ATA_GEO_MASK) == ATA_GEO_FORCE)
                {
                (void) ataCmd (ctrl, drive, ATA_CMD_INITP, NULL, NULL);
                (void) ataPread (ctrl, drive, (char *)pParam);
                }
            else if ((configType & ATA_GEO_MASK) == ATA_GEO_PHYSICAL)
                {
// HARRIET the other dirver subtracts 1...
                pType->cylinders = pParam->cylinders;
		//                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;
                    pType->heads     = pParam->currentHeads;
                    pType->sectors   = pParam->currentSectors;
                    }
                else
                    {
                    pType->cylinders = pParam->cylinders;
                    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
			  logMsg ("ID_DRIVE reports LBA (60-61) as 0x%08lx\n",
					  ataLbaTotalSecs[ctrl][drive],0,0,0,0,0);
#endif /* ATA_DEBUG */
			}

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

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

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

            (void) ataCmd (ctrl, drive, ATA_CMD_RECALIB, NULL, NULL);
            }
        else
            {

            pDrive->state = ATA_DEV_PREAD_F;
            goto driveInitExit;
            }
        }
    else if (pDrive->type == ATA_TYPE_ATAPI)
#if TRUE /* Can be changed to FALSE, if Diagnostic command will be avoided */
        {
        /* 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;
            }
        }
#else
        ;	/* ATAPI device parameters have been read by ataDevIdentify() */
#endif

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

⌨️ 快捷键说明

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