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

📄 satadrv.c

📁 vxworks下SATA控制器SIL3124A的驱动代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	{
  	MOT_SATA_LOG(MOT_SATA_DBG_DINIT,"device is not initialized!\n",1,2,3,4,5,6);
		return (ERROR);
  }
  MOT_SATA_LOG(MOT_SATA_DBG_DINIT,"device is initialized!\n",1,2,3,4,5,6);
  return (OK);      	
}

STATUS Sata_Device_Ready(int ctrl, int drive)
{
	
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_CTRL_STAT), PORT_CS_INIT);
	
	if(Sata_Portwait_Status(ctrl, drive, PORT_CTRL_STAT, PORT_CS_RDY, FALSE) != OK)
	{
  	MOT_SATA_LOG(MOT_SATA_DBG_READY,"device is not ready!\n",1,2,3,4,5,6);
		return (ERROR);
  }
  MOT_SATA_LOG(MOT_SATA_DBG_READY,"device is ready!\n",1,2,3,4,5,6);
  return (OK);      	
}
STATUS Sata_Device_Reset(int ctrl, int drive)
{
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_CTRL_STAT), PORT_CS_DEV_RST);
	
	if(Sata_Portwait_Status(ctrl, drive, PORT_CTRL_STAT, PORT_CS_DEV_RST, TRUE) != OK)
	{
  	MOT_SATA_LOG(MOT_SATA_DBG_DRESET,"device reset is not Reset!\n",1,2,3,4,5,6);
		return (ERROR);
  }
  MOT_SATA_LOG(MOT_SATA_DBG_DRESET,"device reset is over!\n",1,2,3,4,5,6);
  return (OK);      	
}
STATUS Sata_Port_SoftReset(int ctrl, int drive)
{
	UINT32 mask;
	int irq_stat;
	int tmp;
	int slot_stat;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	if (Sata_Device_Present(ctrl, drive) != OK)
		return (ERROR);
	if (Sata_Port_Initialize(ctrl, drive) != OK)
		return (ERROR);
	if (Sata_Device_Ready(ctrl, drive) != OK)
		return (ERROR);
			
	/* disable interrupts */
	tmp = sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_IRQ_ENABLE_SET));
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_IRQ_ENABLE_CLR), tmp);
	
	/* fill in the PRB slot 0 */
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE ), 0x00000080);
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 8 ), 0x00000000);
	
	/* write excutin FIFO */
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_EXEC_FIFO), 0x0);
	
	mask = PORT_IRQ_COMPLETE << PORT_IRQ_RAW_SHIFT;
	
	if(Sata_Portwait_Status(ctrl, drive, PORT_IRQ_STAT, mask, FALSE) != OK)
	{
  	MOT_SATA_LOG(MOT_SATA_DBG_SRESET,"device softreset timeout!\n",1,2,3,4,5,6);
		return (ERROR);
  }
  irq_stat = sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE +PORT_IRQ_STAT));
  irq_stat >>= PORT_IRQ_RAW_SHIFT;
  if (!(irq_stat & PORT_IRQ_COMPLETE))
  {
  	if (irq_stat & PORT_IRQ_ERROR)
  	{
  		MOT_SATA_LOG(MOT_SATA_DBG_SRESET,"Command excuted error !\n",1,2,3,4,5,6);
  		return (ERROR);
  	}
    else
    {
   		MOT_SATA_LOG(MOT_SATA_DBG_SRESET,"Command excuted timeout !\n",1,2,3,4,5,6);
  		return (ERROR);
  	}
  }
  /* clear interrupts pending */
  slot_stat = sysPciInLong((UINT32 *)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_SLOT_STAT));
  sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_IRQ_STAT), 0x0fff0fff);
  sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_IRQ_ENABLE_SET), tmp);
  MOT_SATA_LOG(MOT_SATA_DBG_SRESET,"softreset success !\n",1,2,3,4,5,6);
  return (OK);      	
}

LOCAL void sataWdog(int ctrl)
{
		SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
		MOT_SATA_LOG(MOT_SATA_DBG_WDOG,"softreset success !\n",1,2,3,4,5,6);
    pCtrl->wdgOkay = FALSE;
}

STATUS Sata_Portwait_Status( int ctrl, int drive, UINT32 reg, UINT32 status, BOOL	neg)
{
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	MOT_SATA_LOG(MOT_SATA_DBG_SATASTAT,"softreset success !\n",1,2,3,4,5,6);
	
	wdStart (pCtrl->wdgId, (sysClkRateGet() * pCtrl->wdgTimeout), (FUNCPTR)sataWdog, ctrl);
	if(!neg)
	{
		while (((sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + reg)) & status) != status) && pCtrl->wdgOkay)
        ;   
  }
  else
  {
		while (((sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + reg)) & status) == status) && pCtrl->wdgOkay)
        ;   
  }
  wdCancel (pCtrl->wdgId);
  
  if (!pCtrl->wdgOkay)
  {
  	pCtrl->wdgOkay = TRUE;
   	return (ERROR);
  }
  return (OK);  
}

void sataIntr(int ctrl)
{
	UINT32 status;
	int portNum = 0;
	UINT32 immrVal;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	pCtrl->intStatus = 0;

	/* disable interrupts */
	immrVal = vxImmrGet();
	*M8260_SIPNR_H(immrVal) |= 0x00000800;
	
	status = sysPciInLong((UINT32*)(pCtrl->globalAddr + HOST_IRQ_STAT));
	
	MOT_SATA_LOG(MOT_SATA_DBG_SATAINTR,"enter into inthandler!\n",1,2,3,4,5,6);
	
	if (status == 0xffffffff)
	{
		MOT_SATA_LOG(MOT_SATA_DBG_SATAINTR,"PCI fault or device removal?\n",1,2,3,4,5,6);
		return;
	}
	if (!(status & IRQ_STAT_4PORTS))
		return;
	
	pCtrl->intCount++;
	for(portNum = 0; portNum < SATA_MAX_DRIVES; portNum++)
	{
		if (status & (1 << portNum))
			sata_port_intr(ctrl, portNum);
	}
	semGive (&pCtrl->syncSem);
	return;
}
void sata_port_intr(int ctrl, int portNum)
{
	UINT32 slot_status;
	
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	slot_status = sysPciInLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE +PORT_SLOT_STAT));
	
	if(slot_status & HOST_SSTAT_ATTN)
	{
		sata_error_intr(ctrl, portNum);
		return;
	}
	sata_update_tf(ctrl, portNum);	
	MOT_SATA_LOG(MOT_SATA_DBG_SATAINTR,"enter into sata_port_intr port = %d!\n",portNum,2,3,4,5,6);
	return;
		
}
void sata_error_intr(int ctrl, int portNum)
{
	UINT32 irq_status;
	UINT32 cmd_err, sstatus, serror;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	/* on error, we need to clear IRQ explicitly */
	irq_status = sysPciInLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE +PORT_IRQ_STAT));
	sysPciOutLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE + PORT_IRQ_STAT), irq_status);
	
	if (!(irq_status & PORT_IRQ_ERROR))
	{
		MOT_SATA_LOG(MOT_SATA_DBG_SATAINTR,"non-error exception irq !\n",1,2,3,4,5,6);
		return;
	}
	pCtrl->intStatus = irq_status;	
	cmd_err = sysPciInLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE +PORT_CMD_ERR));
	sstatus = sysPciInLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE +PORT_SSTATUS));
	serror = sysPciInLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE +PORT_SERROR));
	
	if(serror)
		sysPciOutLong ((UINT32*)(pCtrl->portAddr + portNum * PORT_REGS_SIZE + PORT_SERROR), serror);
	
	if(cmd_err > PORT_CERR_SDB)
		MOT_SATA_LOG(MOT_SATA_DBG_SATAINTR,"error interrupt on port%d, irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",portNum,irq_status,cmd_err,sstatus,serror,6);
	
	if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB)
		{
			sata_update_tf(ctrl, portNum);
			if (Sata_Device_Ready(ctrl, portNum) != OK)
				return;
		}
	else
		{
			if (Sata_Device_Reset(ctrl, portNum) != OK)
				return;
			if (Sata_Device_Ready(ctrl, portNum) != OK)
				return;
		}
	
	return;
}
void sata_update_tf(int ctrl, int drive)
{
	int i;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	
	sata_cmd_block->prb.ctrl = sysPciInWord ((USHORT*)(pCtrl->portAddr + drive * PORT_REGS_SIZE));
	sata_cmd_block->prb.prot = sysPciInWord ((USHORT*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 2));
	sata_cmd_block->prb.rx_cnt = sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 4));
	for(i = 0; i < 24; i++)
		sata_cmd_block->prb.fis[i] = sysPciInByte ((UINT8*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 8 + i));
}

STATUS sataPread(int ctrl, int drive, void *buffer)
{
	int 				 semStatus;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	char 				 *ident_param = NULL;
	BOOL     		 retry	= TRUE;
	int      		 retryCount	= 0;
	UINT16       *bufPtr;
	UINT16			 val;
	int 				 i;
			
	ident_param = memalign (8, 4096);
  if ( ident_param == NULL )
  	{
  		MOT_SATA_LOG(MOT_SATA_DBG_PREAD,"could not obtain memory!\n",1,2,3,4,5,6);	
  		return (ERROR);
  	}
  while (retry)
  {
  	memset(ident_param, 0, 4096);
  	MOT_SATA_LOG(MOT_SATA_DBG_PREAD,"ident_param = 0x%x!\n",(UINT32)ident_param,2,3,4,5,6);	
  
 	 /* fill in the PRB slot 0 */
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 4), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 8), 0x00EC8027);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 12), 0xa0000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 16), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 20), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 24), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 28), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 32), (UINT32)ident_param);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 36), 0x00000000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 40), 0x00001000);
  	sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 44), 0x80000000);
  
  	/* write excutin FIFO */
		sysPciOutLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_EXEC_FIFO), 0x0);
			
		semStatus = semTake (&pCtrl->syncSem, sysClkRateGet() * pCtrl->semTimeout);
		if((semStatus == ERROR) || (pCtrl->intStatus))
		{
			MOT_SATA_LOG(MOT_SATA_DBG_PREAD,"identify command failed!\n",1,2,3,4,5,6);	
			if (++retryCount > ataRetry)
				{
					free(ident_param);
	        return (ERROR);
	      }
		}
		else
	    retry = FALSE;
	}
	
	bufPtr = buffer;
	for(i = 0; i < 256; i++)
	{
		val = *(volatile UINT16 *)(ident_param + i*2);
		*(volatile UINT16 *)(bufPtr++) = (val << 8) | (val>>8);
	}
	free(ident_param);
	return (OK);
}
/*******************************************************************************
*
* sataInit 
*/

LOCAL STATUS sataInit
    (
    int ctrl,
    int dev
    )
    {
    SATA_CTRL *pCtrl	= &sataCtrl[ctrl];
    
    MOT_SATA_LOG(MOT_SATA_DBG_SATAINIT,"enter into sataInit!\n",1,2,3,4,5,6);	

		if (Sata_Port_SoftReset(ctrl, dev) != OK)
		{
			pCtrl->wdgOkay = TRUE;
			return (ERROR);
		}
    pCtrl->wdgOkay = TRUE;
    
    /*
     * The following allows recovery after an interrupt
     * caused by drive software reset
     */

    semBInit(&pCtrl->syncSem, SEM_Q_FIFO, SEM_EMPTY);
    semBInit(&pCtrl->rdsyncSem, SEM_Q_FIFO, SEM_EMPTY);

    MOT_SATA_LOG(MOT_SATA_DBG_SATAINIT,"sataInit end!\n",1,2,3,4,5,6);	

    return (OK);
    }

/*******************************************************************************
*
* sataRawio - do raw I/O access
*
* This routine is called to perform raw I/O access.
*
* <drive> is a drive number for the hard drive: it must be 0 or 1.
*
* The <pAtaRaw> is a pointer to the structure SATA_RAW which is defined in 
* sataDrv.h.
*
* RETURNS:
* OK, or ERROR if the parameters are not valid.
*
*/

STATUS sataRawio
    (
    int      ctrl,
    int      drive,
    SATA_RAW  *pAtaRaw
    )
    {
    SATA_CTRL  *pCtrl	= &sataCtrl[ctrl];
    SATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    SATA_TYPE  *pType	= &sataTypes[ctrl][drive];
    SATA_DEV   sataDev;
    BLK_DEV   *pBlkdev	= &sataDev.blkDev;
    UINT      startBlk;
    
    MOT_SATA_LOG(MOT_SATA_DBG_SATARAW,"Enter into ataRawio!\n",1,2,3,4,5,6);	
		
    if ((ctrl >= SATA_MAX_CTRLS) || (drive >= SATA_MAX_DRIVES) ||
        !sataDrvInstalled || !pCtrl->installed)
	return (ERROR);

    if ((pAtaRaw->cylinder	>= pType->cylinders)	||
        (pAtaRaw->head		>= pType->heads)	||
        (pAtaRaw->sector	>  pType->sectors)	||
        (pAtaRaw->sector	== 0))
	return (ERROR);

    /*
     * 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[ctrl][drive] != 0)         &&
	(ataForceCHSonLBA != TRUE)		    &&
	(ataLbaTotalSecs[ctrl][drive] > 
	(pType->cylinders * pType->heads * pType->sectors)))   
	{
	pBlkdev->bd_nBlocks = ataLbaTotalSecs[ctrl][drive];
	}
    else /* just use CHS value */
	{
        pBlkdev->bd_nBlocks	= pType->cylinders * pType->heads * 
				  pType->sectors;
	}

    pBlkdev->bd_bytesPerBlk	= pType->bytes;
    pBlkdev->bd_blksPerTrack	= pType->sectors;
    pBlkdev->bd_nHeads		= pType->heads;
    pBlkdev->bd_removable	= FALSE;
    pBlkdev->bd_retry		= 0;
    pBlkdev->bd_mode		= O_RDWR;
    pBlkdev->bd_readyChanged	= TRUE;
    pBlkdev->bd_blkRd		= sataBlkRd;
    pBlkdev->bd_blkWrt		= sataBlkWrt;
    pBlkdev->bd_ioctl		= sataIoctl;
    pBlkdev->bd_reset		= NULL;
    pBlkdev->bd_statusChk	= NULL;

    sataDev.ctrl			= ctrl;
    sataDev.drive		= drive;
    sataDev.blkOffset		= 0;

    startBlk = pAtaRaw->cylinder * (pType->sectors * pType->heads) +
	       pAtaRaw->head * pType->sectors + pAtaRaw->sector - 1;
		
    return (sataBlkRW (&sataDev, startBlk, pAtaRaw->nSecs, pAtaRaw->pBuf,
		     pAtaRaw->direction));
    }

⌨️ 快捷键说明

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