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

📄 nwatadrv.c

📁 ks8695的ide硬盘程序
💻 C
📖 第 1 页 / 共 5 页
字号:

STATUS ataRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction)
{
    ATA_CTRL *pCtrl	= &ataCtrl[ctrl];
    ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    ATA_TYPE *pType	= &ataTypes[ctrl][drive];
    int retryCount	= 0;
    int block		= 1;
    int nSectors	= nSecs;
    int nWords;
    int semStatus;
    short *pBuf;


	 //
    // If dma enabled then override this function
    //
    if (pDrive->okDma)
      return ataDmaRW(ctrl,drive, cylinder, head, sector,buffer,nSecs,direction);


#ifdef	ATA_DEBUG
    printErr ("ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
              ctrl, drive, cylinder, head, sector, 
	      (int)buffer, nSecs, direction);
#endif	/* ATA_DEBUG */

retryRW:

    ataWait(ctrl, ATA_STAT_READY);
    
    ATA_IO_BYTE_WRITE (pCtrl->sdh,
                           (drive << 4));

    ataWait (ctrl, ATA_STAT_READY);

    pBuf = (UINT16 *)buffer;

    /*start modify by wb 2005-6-20 16:08*/
	if (pDrive->lba48bit ==0)
	{
			ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs);
  
    ATA_IO_BYTE_WRITE (pCtrl->sector, sector);
   
    ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder);
   
    ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8);
      
    if (pDrive->okLba)
    {
        ATA_IO_BYTE_WRITE (pCtrl->sdh,
                           ATA_SDH_LBA | (drive << 4) | (head & 0xf));
    }
    else
    {
        ATA_IO_BYTE_WRITE (pCtrl->sdh,
                           ATA_SDH_IBM | (drive << 4) | (head & 0xf));
		}
	}
	else
	{
			ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs >> 8);
			ATA_IO_BYTE_WRITE(pCtrl->sector, head);
			ATA_IO_BYTE_WRITE(pCtrl->cylLo, 0x00);
			ATA_IO_BYTE_WRITE(pCtrl->cylHi,  0x00);
			ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs & 0xFF);
			ATA_IO_BYTE_WRITE(pCtrl->sector, sector);
			ATA_IO_BYTE_WRITE(pCtrl->cylLo,  (cylinder & 0xff));
			ATA_IO_BYTE_WRITE(pCtrl->cylHi,  (cylinder & 0xff00) >> 8);
			ATA_IO_BYTE_WRITE(pCtrl->sdh,ATA_SDH_LBA | (drive << 4));
	}

/*end modify by wb 2005-6-20 16:08*/

    if (pDrive->rwPio == ATA_PIO_MULTI)
	block = pDrive->multiSecs;

    nWords = (pType->bytes * block) >> 1;

    if (direction == O_WRONLY)     /*1-write 0-read*/
	{
        if (pDrive->rwPio == ATA_PIO_MULTI)
        {
        	if (pDrive->lba48bit == 0)
					{
						ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI);
					}
					else
					{
						ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE_MULTI_EXT);
					}
	    	}
				else
				{
	    		ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_WRITE);
	    	}

    taskDelay(0); 
    ataWait (ctrl, ATA_STAT_DRQ);

	while (nSectors > 0)
	    {
	    if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))
		{
		block = nSectors;
		nWords = (pType->bytes * block) >> 1;
		}


   
	    if (pDrive->rwBits == ATA_BITS_16)
	        ATA_IO_NWORD_WRITE (pCtrl->data, pBuf, nWords);
	    else
	        ATA_IO_NLONG_WRITE (pCtrl->data, (ULONG *)pBuf, nWords >> 1);

        semStatus = semTake (&pCtrl->syncSem, 
				 sysClkRateGet() * pCtrl->semTimeout);
		//pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);		 
    	    if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) {

	           goto errorRW;
            }
        

	        pBuf     += nWords;
	        nSectors -= block;
            if (nSectors > 0) {
             ataWait (ctrl, ATA_STAT_DRQ);

            }
//            ATA_IO_BYTE_READ (pCtrl->status);

            }
	}
    else
	{
        if (pDrive->rwPio == ATA_PIO_MULTI)
        {
	    		if (pDrive->lba48bit == 1)
					{
						ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI);
					}
					else
					{
						ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ_MULTI_EXT);
					}
				}
	else
	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_READ);

	while (nSectors > 0)
	    {


	    if ((pDrive->rwPio == ATA_PIO_MULTI) && (nSectors < block))
			{
				block = nSectors;
				nWords = (pType->bytes * block) >> 1;
			}
                
       semStatus = semTake (&pCtrl->syncSem, 
				sysClkRateGet() * pCtrl->semTimeout);
		//pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);		
        if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR)) {
	        goto errorRW;
        } 
       
        ataWait (ctrl, ATA_STAT_DRQ);

//        ATA_IO_BYTE_READ (pCtrl->status);

				  if (pDrive->rwBits == ATA_BITS_16){
	        ATA_IO_NWORD_READ (pCtrl->data, pBuf, nWords);
        }
	    else
	    {
	        ATA_IO_NLONG_READ (pCtrl->data, (ULONG *)pBuf, nWords >> 1);
	      }
        
        pBuf     += nWords;
	    nSectors -= block;         
	    
	    }
	}

#ifdef	ATA_DEBUG
    printErr ("ataRW: end\n");
#endif	/* ATA_DEBUG */

    return (OK);

errorRW:
#ifdef	ATA_DEBUG
    {
    int error	= ATA_IO_BYTE_READ (pCtrl->error);
    int status	= ATA_IO_BYTE_READ (pCtrl->aStatus);
    printErr ("ataRW err: stat=0x%x 0x%x semStatus=%d error=0x%x\n",
	      pCtrl->intStatus, status, semStatus, error);
    }
#endif	/* ATA_DEBUG */
    if (++retryCount < ataRetry)
	goto retryRW;
    return (ERROR);
    }


/*******************************************************************************
*
* ataDmaRW - 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.
*/
//efine ATA_PERFORMANCE
STATUS ataDmaRW(int ctrl,int drive,int cylinder,int head,int sector,void *buffer,int nSecs,int direction)
{
  ATA_CTRL *pCtrl	= &ataCtrl[ctrl];
  ATA_DRIVE *pDrive	= &pCtrl->drive[drive];
  ATA_TYPE *pType	= &ataTypes[ctrl][drive];
  int retryCount	= 0;
  int semStatus;
  int i;
  unsigned char tmp;
  STATUS status;

#ifdef ATA_PERFORMANCE
  int startTick,endTick;   
#endif

#ifdef	ATA_DEBUG
  printErr ("ataDmaRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x n=%d dir=%d\n",
            ctrl, drive, cylinder, head, sector, (int)buffer, nSecs, direction);
#endif	/* ATA_DEBUG */
  //cacheLock(DATA_CACHE,buffer,sector*512);
	/*cacheDisable(DATA_CACHE);quy del 2006-3-24 8:30*/

retryDmaRW:
	
  status = ataDmaSetupXfer(ctrl,direction,buffer,nSecs*pType->bytes);
    
  if (status != OK)
  {
    /*cacheEnable(DATA_CACHE);quy del 2006-3-24 8:29*/
    return status;
  }
  
	if(pDrive->status == ATA_STANDBY_MODE)
	{
	  ataWait(ctrl, ATA_STAT_BUSY);
    ATA_IO_BYTE_WRITE(pCtrl->sdh, ATA_SDH_LBA | (drive << 4));
    ATA_IO_BYTE_WRITE(pCtrl->command, IDE_CMD_IDLE);
	  pDrive->status = ATA_ACTIVE_MODE;
	  taskDelay(sysClkRateGet()*8);
	}
	  
  ataWait(ctrl, ATA_STAT_READY);
  ATA_IO_BYTE_WRITE (pCtrl->sdh,(drive << 4));
 
  /*start modify by wb 2005-6-20 16:08*/
	if (pDrive->lba48bit == 0)
	{
		ATA_IO_BYTE_WRITE (pCtrl->seccnt, nSecs);
		ATA_IO_BYTE_WRITE (pCtrl->sector, sector);
		ATA_IO_BYTE_WRITE (pCtrl->cylLo, cylinder);
		ATA_IO_BYTE_WRITE (pCtrl->cylHi, cylinder>>8);
		if (pDrive->okLba)
		{
			ATA_IO_BYTE_WRITE (pCtrl->sdh,ATA_SDH_LBA | (drive << 4) | (head & 0xf));
    }
    else
    {
      ATA_IO_BYTE_WRITE (pCtrl->sdh,ATA_SDH_IBM | (drive << 4) | (head & 0xf));
		}
	}
	else
	{
			//ATA_IO_BYTE_WRITE(pCtrl->feature, 0);
	  ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs >> 8);
		ATA_IO_BYTE_WRITE(pCtrl->sector, head);
		ATA_IO_BYTE_WRITE(pCtrl->cylLo, 0x00);
		ATA_IO_BYTE_WRITE(pCtrl->cylHi,  0x00);
		ATA_IO_BYTE_WRITE(pCtrl->seccnt, nSecs & 0xFF);
		ATA_IO_BYTE_WRITE(pCtrl->sector, sector);
		ATA_IO_BYTE_WRITE(pCtrl->cylLo,  (cylinder & 0xff));
		ATA_IO_BYTE_WRITE(pCtrl->cylHi,  (cylinder & 0xff00) >> 8);
		ATA_IO_BYTE_WRITE(pCtrl->sdh,ATA_SDH_LBA | (drive << 4));
	}

/*end modify by wb 2005-6-20 16:08*/

  ataWait (ctrl, ATA_STAT_READY);
/*写数据*/
  if (direction == O_WRONLY)
	{

#ifdef ATA_PERFORMANCE
    startTick = hmpv_read_fcnt();
#endif
		if (pDrive->lba48bit == 0)
		{
	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_WRITE);
	  }
	  else
	  {
	    ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_WRITE_EXT);
	  }
    /*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
    ataWait (ctrl, ATA_STAT_DRQ);
    enableChan(ctrl);
    semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout);
    i=0;
    while(i<5000)
    {
      if(ATA_IO_BYTE_READ( busMasterRegs[ctrl] + BM_STATUS_REG) & 0x4)
        break;
    }
    disableChan(ctrl);
    clearChan(ctrl);
    pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
    
  	if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))
      goto errorDmaRW;
#ifdef ATA_PERFORMANCE
    endTick = hmpv_read_fcnt();
#endif
	}
  else
	{

#ifdef ATA_PERFORMANCE
    startTick = hmpv_read_fcnt();
#endif
		if (pDrive->lba48bit == 0)
		{
		  ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_READ);
		}
		else
		{
		  ATA_IO_BYTE_WRITE (pCtrl->command, ATA_CMD_DMA_READ_EXT);
		}
    ataWait(ctrl,ATA_STAT_DRQ);
    /*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
    enableChan(ctrl);   
	 
    semStatus = semTake (&pCtrl->syncSem,sysClkRateGet() * pCtrl->semTimeout);
    i=0;
    while(i<100000)
    {
      if(ATA_IO_BYTE_READ( busMasterRegs[ctrl] + BM_STATUS_REG) & 0x4)
        break;
    }
    disableChan(ctrl);
    clearChan(ctrl);
    pCtrl->intStatus = ATA_IO_BYTE_READ (pCtrl->status);
    
 	  if ((pCtrl->intStatus & ATA_STAT_ERR) || (semStatus == ERROR))
 	    goto errorDmaRW;
    /*cacheFlush(DATA_CACHE,(void *)buffer, nSecs*512);quy del 2006-3-24 8:28*/
    
#ifdef ATA_PERFORMANCE
    endTick = hmpv_read_fcnt();
#endif
	}
#ifdef	ATA_DEBUG
  printf("ataDmaRW: end\n");
#endif	/* ATA_DEBUG */

#ifdef ATA_PERFORMANCE
  {
    float count,MBps;
    if (endTick > startTick)
      count = endTick - startTick;
    else
      count = 0xFFFFFFF - startTick + endTick;

    MBps = nSecs*pType->bytes/(count/CPU_MHZ);

    if (direction == O_WRONLY )
      printf("Wrote %d bytes. MBps %f\n",nSecs*pType->bytes,MBps);
    else
      printf("Read %d bytes. MBps %f\n",nSecs*pType->bytes,MBps);
  } 
#endif
  /*cacheEnable(DATA_CACHE);*/
	//cacheUnlock(DATA_CACHE,buffer,sector*512);
  return (OK);

errorDmaRW:
#ifdef ATA_DEBUG
  {
    int error	= ATA_IO_BYTE_READ (pCtrl->error);
    int status	= ATA_IO_BYTE_READ (pCtrl->aStatus);
    printErr ("ataDmaRW err: stat=0x%x 0x%x semStatus=%d error=0x%x errorno 0x%x\n",
	      pCtrl->intStatus, status, semStatus, error,errno);
    printErr("sysClkRateGet=%d timeout=%d\n",sysClkRateGet(),sysClkRateGet() * pCtrl->semTimeout);
  }
#endif	/* ATA_DEBUG */
  if (++retryCount < ataRetry)
    goto retryDmaRW;
  /*cacheEnable(DATA_CACHE);*/
	//cacheUnlock(DATA_CACHE,buffer,sector*512);
  return (ERROR);
}


//***********************************************************
//
// ataDmaSetupXfer() -- set up 1, 2 or 3 PRD
//
//*********************************************************** 
STATUS ataDmaSetupXfer(int ctrl, int dir, char *addr, int count)

{
   PPRD_ENTRY prdEntry;
   int numBytes;
   unsigned int tempData1,tempData2;
   /*added by youyan*/
   char *pAddr;
   unsigned int dwBufLen;
   
   // disable/stop the dma channel, clear interrupt and error bits

   disableChan(ctrl);
   clearChan(ctrl);

	//logMsg("the dma data size = 0x%x \n",count,2,3,4,5,6);
   if (count/MAX_TRANSFER /*+ 2*/ > MAX_PRD_ENTRIES) {
    printf("ERROR: too many dma bytes 0x%x, expand table!!!!!\n",count);
    return ERROR;
   }

   prdEntry = &prdTable[ctrl][0];

   //
   // build prd table
   // each entry cannot cross a 64Kbyte bountry so...
   //

#if 1
  pAddr = addr;
  dwBufLen = count;
  while (dwBufLen) 
  {
    prdEntry->address = (char *)((unsigned int)(pAddr) + PCI2DRAM_BASE_ADRS);
    if (dwBufLen > MAX_TRANSFER)
    {
      prdEntry->bits.count = 0;//MAX_TRANSFER;
      prdEntry->bits.EOT = 0;
      dwBufLen -= MAX_TRANSFER;         
      pAddr  += MAX_TRANSFER;  
    }
    else
    {
      prdEntry->bits.count = dwBufLen;
      prdEntry->bits.EOT = 1;
      dwBufLen = 0;
    }
    prdEntry++;
 }

#endif
#if 0
   while (TRUE) {

⌨️ 快捷键说明

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