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

📄 satadrv.c

📁 vxworks下SATA控制器SIL3124A的驱动代码
💻 C
📖 第 1 页 / 共 4 页
字号:

    return (&pDev->blkDev);
}

/*******************************************************************************
*
* sataBlkRd - read one or more blocks from a SATA/IDE disk
*
* This routine reads one or more blocks from the specified device,
* starting with the specified block number.
*
* If any block offset was specified during sataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the read command didn't succeed.
*/

LOCAL STATUS sataBlkRd
    (
    SATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf
    )
    {
    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkRd: nBlks=%d\n", nBlks, 0, 0, 0, 0, 0);
    return (sataBlkRW (pDev, startBlk, nBlks, pBuf, O_RDONLY));
    }

/*******************************************************************************
*
* sataBlkWrt - write one or more blocks to a SATA/IDE disk
*
* This routine writes one or more blocks to the specified device,
* starting with the specified block number.
*
* If any block offset was specified during sataDevCreate(), it is added
* to <startBlk> before the transfer takes place.
*
* RETURNS: OK, ERROR if the write command didn't succeed.
*/

LOCAL STATUS sataBlkWrt
    (
    SATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf
    )
    {
    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkWrt: nBlks=%d\n", nBlks, 0, 0, 0, 0, 0);
    return (sataBlkRW (pDev, startBlk, nBlks, pBuf, O_WRONLY));
    }

/*******************************************************************************
*
* sataReset - reset a SATA/IDE disk controller
*
* This routine resets a SATA/IDE disk controller.
*
* RETURNS: OK, always.
*/

LOCAL STATUS sataReset
    (
    SATA_DEV  *pDev
    )
{
    SATA_CTRL *pCtrl	= &sataCtrl[pDev->ctrl];
    MOT_SATA_LOG (MOT_SATA_DBG_SATARESET, "Enter into sataReset\n", 0, 0, 0, 0, 0, 0);
    if (!pCtrl->installed)
			return (ERROR);

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    (void) sataInit (pDev->ctrl, 0);

    semGive (&pCtrl->muteSem);

    return (OK);
}

/*******************************************************************************
*
* sataStatus - check status of a SATA/IDE disk controller
*
* This routine check status of a SATA/IDE disk controller.
*
* RETURNS: OK, ERROR if the card is removed.
*/

LOCAL STATUS sataStatus
    (
    SATA_DEV  *pDev
    )
{
    SATA_CTRL *pCtrl	= &sataCtrl[pDev->ctrl];
    BLK_DEV  *pBlkdev	= &pDev->blkDev;
    MOT_SATA_LOG (MOT_SATA_DBG_SSTAT, "Enter into ataStatus\n", 0, 0, 0, 0, 0, 0);
    if (!pCtrl->installed)
			return (ERROR);

    if (pCtrl->changed)
		{
			pBlkdev->bd_readyChanged = TRUE;
			pCtrl->changed		 = FALSE;
		}

    return (OK);
 }

/*******************************************************************************
*
* sataIoctl - do device specific control function
*
* This routine is called when the file system cannot handle an ioctl()
* function.
*
* RETURNS:  OK or ERROR.
*/

LOCAL STATUS sataIoctl
    (
    SATA_DEV  *pDev,
    int      function,
    int      arg
    )
{
    SATA_CTRL *pCtrl	= &sataCtrl[pDev->ctrl];
    register UINT localStatus;	/* local status variable */
		
		MOT_SATA_LOG (MOT_SATA_DBG_SATAIOCTL, "Enter into sataStatus\n", 0, 0, 0, 0, 0, 0);
    if (!pCtrl->installed)
        return (ERROR);

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    switch (function)
		{
		case FIODISKFORMAT:
	    /*(void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
	    localStatus = ERROR;*/
	    pDev->blkDev.bd_readyChanged = TRUE;
	    break;

		default:
	    (void) errnoSet (S_ioLib_UNKNOWN_REQUEST);
	    localStatus = ERROR;
	    break;
		}

    semGive (&pCtrl->muteSem);
		
    return ((localStatus ? ERROR : OK));
}

/*******************************************************************************
*
* sataBlkRW - read or write sectors to a SATA/IDE disk.
*
* Read or write sectors to a SATA/IDE disk.
*
* RETURNS: OK, ERROR if the command didn't succeed.
*/

LOCAL STATUS sataBlkRW
    (
    SATA_DEV *pDev,
    int     startBlk,
    int     nBlks,
    char    *pBuf,
    int     direction
    )
{
    SATA_CTRL  *pCtrl	= &sataCtrl[pDev->ctrl];
    SATA_DRIVE *pDrive	= &pCtrl->drive[pDev->drive];
    BLK_DEV   *pBlkdev	= &pDev->blkDev;
    SATA_TYPE  *pType	= &sataTypes[pDev->ctrl][pDev->drive];
    int       status	= ERROR;
    int       retryRW0	= 0;
    int       retryRW1	= 0;
    int       retrySeek	= 0;
    int       cylinder;
    int       head;
    int       sector;
    int       nSecs;
    int       ix;

    /* sanity check */
    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "Enter into sataBlkRW\n", 0, 0, 0, 0, 0, 0);
		if (!pCtrl->installed)
        return (ERROR);

    nSecs = pBlkdev->bd_nBlocks;

    if ((startBlk + nBlks) > nSecs)
		{
			MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "startBlk=%d nBlks=%d: 0 - %d\n", startBlk, nBlks, 
                       nSecs, 0, 0, 0);

			return (ERROR);
		}

    startBlk += pDev->blkOffset;

    semTake (&pCtrl->muteSem, WAIT_FOREVER);

    for (ix = 0; ix < nBlks; ix += nSecs)
		{

		if (pDrive->okLba)
	    {
	    	head     = (startBlk & 0x0f000000) >> 24;
	    	cylinder = (startBlk & 0x00ffff00) >> 8;
	    	sector   = (startBlk & 0x000000ff);
	    }
		else
	    {
	    	cylinder = startBlk / (pType->sectors * pType->heads);
	    	sector   = startBlk % (pType->sectors * pType->heads);
	    	head     = sector / pType->sectors;
	    	sector   = sector % pType->sectors + 1;
	    }
		nSecs    = min (nBlks - ix, ATA_MAX_RW_SECTORS);

		retryRW1 = 0;
		retryRW0 = 0;
		while (sataRW(pDev->ctrl, pDev->drive, cylinder, head, sector, pBuf, nSecs, direction) != OK)
    {
	    if (++retryRW0 > ataRetry)
				{
	        (void)sataCmd (pDev->ctrl, pDev->drive, ATA_CMD_RECALIB, 0, 0);

	        if (++retryRW1 > ataRetry)
		    		goto done;

	        retrySeek = 0;
	        while (sataCmd (pDev->ctrl, pDev->drive, ATA_CMD_SEEK, cylinder, head) != OK)
            if (++retrySeek > ataRetry)
		        	goto done;
	        retryRW0 = 0;
				}
	   }
		 startBlk += nSecs;
     pBuf += pBlkdev->bd_bytesPerBlk * nSecs;
	}

  status = OK;

done:

  if (status == ERROR)
      (void)errnoSet (S_ioLib_DEVICE_ERROR);

  semGive (&pCtrl->muteSem);

  return (status);
}

/*******************************************************************************
*
* sataRW - 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.
*/

LOCAL STATUS sataRW
    (
    int ctrl,
    int drive,
    int cylinder,
    int head,
    int sector,
    char *buffer,
    int nSecs,
    int direction
    )
{
    SATA_CTRL *pCtrl	= &sataCtrl[ctrl];
    SATA_DRIVE *pDrive	= &pCtrl->drive[drive];
    SATA_TYPE *pType	= &sataTypes[ctrl][drive];
    int retryCount	= 0;
    int nBytes;
    int semStatus;
    char *pBuf;
    UINT32 tmp;

    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: ctrl=%d drive=%d c=%d h=%d s=%d buf=0x%x ",
                   ctrl, drive, cylinder, head, sector, (int)buffer);
    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "n=%d dir=%d\n", nSecs, direction, 0, 0, 0, 0);

retryRW:

    pBuf = (char *)buffer;
    nBytes = pType->bytes * nSecs;
    if (direction == O_WRONLY)
		{
			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), 0x00CA8027);
  		if (pDrive->okLba)
        tmp = sector | (cylinder << 8) |((ATA_SDH_LBA | (head & 0xf)) << 24);
    	else
    		tmp = sector | (cylinder << 8) |((ATA_SDH_IBM | (head & 0xf)) << 24);
	 		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 12), tmp);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 16), 0x00000000);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 20), nSecs);
  		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)pBuf);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 36), 0x00000000);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 40), nBytes);
  		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 ((pCtrl->intStatus) || (semStatus == ERROR))
	        goto errorRW;
 		}
    else
		{
			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), 0x00C88027);
  		if (pDrive->okLba)
        tmp = sector | (cylinder << 8) |((ATA_SDH_LBA | (head & 0xf)) << 24);
    	else
    		tmp = sector | (cylinder << 8) |((ATA_SDH_IBM | (head & 0xf)) << 24);
	 		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 12), tmp);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 16), 0x00000000);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 20), nSecs);
  		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)pBuf);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 36), 0x00000000);
  		sysPciOutLong((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + 40), nBytes);
  		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 ((pCtrl->intStatus) || (semStatus == ERROR))
	        goto errorRW;
       
		}

		MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: end!\n", 0, 0, 0, 0, 0, 0);
    return (OK);

errorRW:

    MOT_SATA_LOG (MOT_SATA_DBG_SATABRW, "ataRW: failed!\n", 0, 0, 0, 0, 0, 0);

    if (++retryCount < ataRetry)
			goto retryRW;
    return (ERROR);
}



STATUS sataDevIdentify (int ctrl, int drive)
{
	SATA_CTRL    *pCtrl	= &sataCtrl[ctrl]; 
	SATA_DRIVE   *pDrive	= &pCtrl->drive [drive];
	
	pDrive->type = SATA_TYPE_NONE;
	MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"enter sataDevIdentify!\n",1,2,3,4,5,6);
	
	if (Sata_Device_Reset(ctrl, drive) != OK)
	{
		pDrive->state = SATA_DEV_NONE;
  	return (ERROR);
  }
  	
  if (Sata_Port_SoftReset(ctrl, drive) != OK)
  {
  	pDrive->state = SATA_DEV_NONE;
  	return (ERROR);
  }
  	
  sata_update_tf(ctrl, drive);
  CACHE_DMA_INVALIDATE (sata_cmd_block, 64);
  if((sata_cmd_block->prb.fis[12] != 0x01) || (sata_cmd_block->prb.fis[4] != 0x01) || (sata_cmd_block->prb.fis[5] != 0x00) || (sata_cmd_block->prb.fis[6] != 0x00))
  {
  	MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"device attachment is not a disk drive!\n",1,2,3,4,5,6);
  	pDrive->state = SATA_DEV_NONE;
  	return (ERROR);
  }
  MOT_SATA_LOG(MOT_SATA_DBG_IDENT,"device attachment is a disk drive!\n",1,2,3,4,5,6);
  pDrive->type = SATA_TYPE_ATA;
	return (OK);
 
}
STATUS Sata_Device_Present(int ctrl, int drive)
{
	UINT32 tmp=0;
	SATA_CTRL    *pCtrl		= &sataCtrl[ctrl];
	if(Sata_Portwait_Status(ctrl, drive, PORT_SSTATUS, 0x00000003, FALSE) != OK)
		{
			MOT_SATA_LOG(MOT_SATA_DBG_PRESENT,"device is not present!\n",1,2,3,4,5,6);
		 	return (ERROR);
		}
	
  tmp = sysPciInLong ((UINT32*)(pCtrl->portAddr + drive * PORT_REGS_SIZE + PORT_SSTATUS));
  MOT_SATA_LOG(MOT_SATA_DBG_PRESENT,"device is present! status = 0x%x!\n",tmp,2,3,4,5,6);
  return (OK);      	
}

STATUS Sata_Port_Initialize(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_INIT, TRUE) != OK)

⌨️ 快捷键说明

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