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

📄 scsiiom.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************** *	FILE NAME : SCSIIOM.C					       * *	     BY   : C.L. Huang,    ching@tekram.com.tw		       * *	Description: Device Driver for Tekram DC-390 (T) PCI SCSI      * *		     Bus Master Host Adapter			       * ***********************************************************************/static USHORTDC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ){    USHORT ioport, rc;    UCHAR  bval, bval1, i, cnt;    PUCHAR ptr;    ULONG  wlval;    pSRB->TagNumber = 31;    ioport = pACB->IOPortBase;    bval = pDCB->UnitSCSIID;    outb(bval,ioport+Scsi_Dest_ID);    bval = pDCB->SyncPeriod;    outb(bval,ioport+Sync_Period);    bval = pDCB->SyncOffset;    outb(bval,ioport+Sync_Offset);    bval = pDCB->CtrlR1;    outb(bval,ioport+CtrlReg1);    bval = pDCB->CtrlR3;    outb(bval,ioport+CtrlReg3);    bval = pDCB->CtrlR4;    outb(bval,ioport+CtrlReg4);    bval = CLEAR_FIFO_CMD;	   /* Flush FIFO */    outb(bval,ioport+ScsiCmd);    pSRB->ScsiPhase = SCSI_NOP0;    bval = pDCB->IdentifyMsg;    if( !(pDCB->SyncMode & EN_ATN_STOP) )    {	if( (pSRB->CmdBlock[0] == INQUIRY) ||	    (pSRB->CmdBlock[0] == REQUEST_SENSE) ||	    (pSRB->SRBFlag & AUTO_REQSENSE) )	{	    bval &= 0xBF;	/* NO disconnection */	    outb(bval,ioport+ScsiFifo);	    bval1 = SELECT_W_ATN;	    pSRB->SRBState = SRB_START_;	    if( pDCB->SyncMode & SYNC_ENABLE )	    {		if( !(pDCB->IdentifyMsg & 7) ||		    (pSRB->CmdBlock[0] != INQUIRY) )		{		    bval1 = SEL_W_ATN_STOP;		    pSRB->SRBState = SRB_MSGOUT;		}	    }	}	else	{	    if(pDCB->SyncMode & EN_TAG_QUEUING)	    {		outb(bval,ioport+ScsiFifo);		bval = MSG_SIMPLE_QTAG;		outb(bval,ioport+ScsiFifo);		wlval = 1;		bval = 0;		while( wlval & pDCB->TagMask )		{		    wlval = wlval << 1;		    bval++;		}		outb(bval,ioport+ScsiFifo);		pDCB->TagMask |= wlval;		pSRB->TagNumber = bval;		bval1 = SEL_W_ATN2;		pSRB->SRBState = SRB_START_;	    }	    else	    {		outb(bval,ioport+ScsiFifo);		bval1 = SELECT_W_ATN;		pSRB->SRBState = SRB_START_;	    }	}	if( pSRB->SRBFlag & AUTO_REQSENSE )	{	    bval = REQUEST_SENSE;	    outb(bval,ioport+ScsiFifo);	    bval = pDCB->IdentifyMsg << 5;	    outb(bval,ioport+ScsiFifo);	    bval = 0;	    outb(bval,ioport+ScsiFifo);	    outb(bval,ioport+ScsiFifo);	    bval = sizeof(pSRB->pcmd->sense_buffer);	    outb(bval,ioport+ScsiFifo);	    bval = 0;	    outb(bval,ioport+ScsiFifo);	}	else	{	    cnt = pSRB->ScsiCmdLen;	    ptr = (PUCHAR) pSRB->CmdBlock;	    for(i=0; i<cnt; i++)	    {		bval = *ptr++;		outb(bval,ioport+ScsiFifo);	    }	}    }    else	/* ATN_STOP */    {	if( (pSRB->CmdBlock[0] == INQUIRY) ||	    (pSRB->CmdBlock[0] == REQUEST_SENSE) ||	    (pSRB->SRBFlag & AUTO_REQSENSE) )	{	    bval &= 0xBF;	    outb(bval,ioport+ScsiFifo);	    bval1 = SELECT_W_ATN;	    pSRB->SRBState = SRB_START_;	    if( pDCB->SyncMode & SYNC_ENABLE )	    {		if( !(pDCB->IdentifyMsg & 7) ||		    (pSRB->CmdBlock[0] != INQUIRY) )		{		    bval1 = SEL_W_ATN_STOP;		    pSRB->SRBState = SRB_MSGOUT;		}	    }	}	else	{	    if(pDCB->SyncMode & EN_TAG_QUEUING)	    {		outb(bval,ioport+ScsiFifo);		pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;		wlval = 1;		bval = 0;		while( wlval & pDCB->TagMask )		{		    wlval = wlval << 1;		    bval++;		}		pDCB->TagMask |= wlval;		pSRB->TagNumber = bval;		pSRB->MsgOutBuf[1] = bval;		pSRB->MsgCnt = 2;		bval1 = SEL_W_ATN_STOP;		pSRB->SRBState = SRB_START_;	    }	    else	    {		outb(bval,ioport+ScsiFifo);		pSRB->MsgOutBuf[0] = MSG_NOP;		pSRB->MsgCnt = 1;		pSRB->SRBState = SRB_START_;		bval1 = SEL_W_ATN_STOP;	    }	}    }    bval = inb( ioport+Scsi_Status );    if( bval & INTERRUPT )    {	pSRB->SRBState = SRB_READY;	pDCB->TagMask &= ~( 1 << pSRB->TagNumber );	rc = 1;    }    else    {	pSRB->ScsiPhase = SCSI_NOP1;	pACB->pActiveDCB = pDCB;	pDCB->pActiveSRB = pSRB;	rc = 0;	outb(bval1,ioport+ScsiCmd);    }    return( rc );}#ifndef  VERSION_ELF_1_2_13static voidDC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)#elsestatic voidDC390_Interrupt( int irq, struct pt_regs *regs)#endif{    PACB   pACB;    PDCB   pDCB;    PSRB   pSRB;    USHORT ioport = 0;    USHORT phase, i;    void   (*stateV)( PACB, PSRB, PUCHAR );    UCHAR  istate = 0;    UCHAR  sstatus=0, istatus;    pACB = pACB_start;    if( pACB == NULL )	return;    for( i=0; i < adapterCnt; i++ )    {	if( pACB->IRQLevel == (UCHAR) irq )	{	     ioport = pACB->IOPortBase;	     sstatus = inb( ioport+Scsi_Status );	     if( sstatus & INTERRUPT )		 break;	     else		pACB = pACB->pNextACB;	}	else	{	    pACB = pACB->pNextACB;	}    }#ifdef DC390_DEBUG1	printk("sstatus=%2x,",sstatus);#endif    if( pACB == (PACB )-1 )    {	printk("DC390: Spurious interrupt detected!\n");	return;    }    istate = inb( ioport+Intern_State );    istatus = inb( ioport+INT_Status );#ifdef DC390_DEBUG1	printk("Istatus=%2x,",istatus);#endif    if(istatus &  DISCONNECTED)    {	DC390_Disconnect( pACB );	return;    }    if(istatus &  RESELECTED)    {	DC390_Reselect( pACB );	return;    }    if(istatus &  INVALID_CMD)    {	DC390_InvalidCmd( pACB );	return;    }    if(istatus &  SCSI_RESET)    {	DC390_ScsiRstDetect( pACB );	return;    }    if( istatus & (SUCCESSFUL_OP+SERVICE_REQUEST) )    {	pDCB = pACB->pActiveDCB;	pSRB = pDCB->pActiveSRB;	if( pDCB )	{	    if( pDCB->DCBFlag & ABORT_DEV_ )		EnableMsgOut( pACB, pSRB );	}	phase = (USHORT) pSRB->ScsiPhase;	stateV = (void *) DC390_phase0[phase];	stateV( pACB, pSRB, &sstatus );	pSRB->ScsiPhase = sstatus & 7;	phase = (USHORT) sstatus & 7;	stateV = (void *) DC390_phase1[phase];	stateV( pACB, pSRB, &sstatus );    }}static voidDC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    UCHAR   sstatus, bval;    USHORT  ioport;    PSGL    psgl;    ULONG   ResidCnt, xferCnt;    ioport = pACB->IOPortBase;    sstatus = *psstatus;    if( !(pSRB->SRBState & SRB_XFERPAD) )    {	if( sstatus & PARITY_ERR )	    pSRB->SRBStatus |= PARITY_ERROR;	if( sstatus & COUNT_2_ZERO )	{	    bval = inb(ioport+DMA_Status);	    while( !(bval & DMA_XFER_DONE) )		bval = inb(ioport+DMA_Status);	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;	    pSRB->SGIndex++;	    if( pSRB->SGIndex < pSRB->SGcount )	    {		pSRB->pSegmentList++;		psgl = pSRB->pSegmentList;#ifndef VERSION_ELF_1_2_13		pSRB->SGPhysAddr = virt_to_phys( psgl->address );#else		pSRB->SGPhysAddr = (ULONG) psgl->address;#endif		pSRB->SGToBeXferLen = (ULONG) psgl->length;	    }	    else		pSRB->SGToBeXferLen = 0;	}	else	{	    bval = inb( ioport+Current_Fifo );	    bval &= 0x1f;	    ResidCnt = (ULONG) inb(ioport+CtcReg_High);	    ResidCnt = ResidCnt << 8;	    ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);	    ResidCnt = ResidCnt << 8;	    ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);	    ResidCnt += (ULONG) bval;	    xferCnt = pSRB->SGToBeXferLen - ResidCnt;	    pSRB->SGPhysAddr += xferCnt;	    pSRB->TotalXferredLen += xferCnt;	    pSRB->SGToBeXferLen = ResidCnt;	}    }    bval = WRITE_DIRECTION+DMA_IDLE_CMD;    outb( bval, ioport+DMA_Cmd);}static voidDC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    UCHAR   sstatus, bval;    USHORT  i, ioport, residual;    PSGL    psgl;    ULONG   ResidCnt, xferCnt;    PUCHAR  ptr;    ioport = pACB->IOPortBase;    sstatus = *psstatus;    if( !(pSRB->SRBState & SRB_XFERPAD) )    {	if( sstatus & PARITY_ERR )	    pSRB->SRBStatus |= PARITY_ERROR;	if( sstatus & COUNT_2_ZERO )	{	    bval = inb(ioport+DMA_Status);	    while( !(bval & DMA_XFER_DONE) )		bval = inb(ioport+DMA_Status);	    bval = READ_DIRECTION+DMA_IDLE_CMD;	    outb( bval, ioport+DMA_Cmd);	    pSRB->TotalXferredLen += pSRB->SGToBeXferLen;	    pSRB->SGIndex++;	    if( pSRB->SGIndex < pSRB->SGcount )	    {		pSRB->pSegmentList++;		psgl = pSRB->pSegmentList;#ifndef VERSION_ELF_1_2_13		pSRB->SGPhysAddr = virt_to_phys( psgl->address );#else		pSRB->SGPhysAddr = (ULONG) psgl->address;#endif		pSRB->SGToBeXferLen = (ULONG) psgl->length;	    }	    else		pSRB->SGToBeXferLen = 0;	}	else	/* phase changed */	{	    residual = 0;	    bval = inb(ioport+Current_Fifo);	    while( bval & 0x1f )	    {		if( (bval & 0x1f) == 1 )		{		    for(i=0; i< 0x100; i++)		    {			bval = inb(ioport+Current_Fifo);			if( !(bval & 0x1f) )			    goto din_1;			else if( i == 0x0ff )			{			    residual = 1;   /* ;1 residual byte */			    goto din_1;			}		    }		}		else		    bval = inb(ioport+Current_Fifo);	    }din_1:	    bval = READ_DIRECTION+DMA_BLAST_CMD;	    outb(bval, ioport+DMA_Cmd);	    for(i=0; i<0x8000; i++)	    {		bval = inb(ioport+DMA_Status);		if(bval & BLAST_COMPLETE)		    break;	    }	    bval = READ_DIRECTION+DMA_IDLE_CMD;	    outb(bval, ioport+DMA_Cmd);	    ResidCnt = (ULONG) inb(ioport+CtcReg_High);	    ResidCnt = ResidCnt << 8;	    ResidCnt |= (ULONG) inb(ioport+CtcReg_Mid);	    ResidCnt = ResidCnt << 8;	    ResidCnt |= (ULONG) inb(ioport+CtcReg_Low);	    xferCnt = pSRB->SGToBeXferLen - ResidCnt;	    pSRB->SGPhysAddr += xferCnt;	    pSRB->TotalXferredLen += xferCnt;	    pSRB->SGToBeXferLen = ResidCnt;	    if( residual )	    {		bval = inb(ioport+ScsiFifo);	    /* get residual byte */#ifndef VERSION_ELF_1_2_13		ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr );#else		ptr = (PUCHAR) pSRB->SGPhysAddr;#endif		*ptr = bval;		pSRB->SGPhysAddr++;		pSRB->TotalXferredLen++;		pSRB->SGToBeXferLen--;	    }	}    }}static voidDC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){}static voidDC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    UCHAR  bval;    USHORT ioport;    ioport = pACB->IOPortBase;    bval = inb(ioport+ScsiFifo);    pSRB->TargetStatus = bval;    bval++;    bval = inb(ioport+ScsiFifo);	/* get message */    pSRB->EndMessage = bval;    *psstatus = SCSI_NOP0;    pSRB->SRBState = SRB_COMPLETED;    bval = MSG_ACCEPTED_CMD;    outb(bval, ioport+ScsiCmd);}static voidDC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )	*psstatus = SCSI_NOP0;}static voidDC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    UCHAR  bval;    USHORT ioport, wval, wval1;    PDCB   pDCB;    PSRB   psrb;    ioport = pACB->IOPortBase;    pDCB = pACB->pActiveDCB;    bval = inb( ioport+ScsiFifo );    if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )    {	if(bval == MSG_DISCONNECT)	{	    pSRB->SRBState = SRB_DISCONNECT;	}	else if( bval == MSG_SAVE_PTR )	    goto  min6;	else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&					    (bval <= MSG_ORDER_QTAG)) )	{	    pSRB->SRBState |= SRB_MSGIN_MULTI;	    pSRB->MsgInBuf[0] = bval;	    pSRB->MsgCnt = 1;	    pSRB->pMsgPtr = &pSRB->MsgInBuf[1];	}	else if(bval == MSG_REJECT_)	{	    bval = RESET_ATN_CMD;	    outb(bval, ioport+ScsiCmd);	    if( pSRB->SRBState & DO_SYNC_NEGO)		goto  set_async;	}	else if( bval == MSG_RESTORE_PTR)	    goto  min6;	else	    goto  min6;    }

⌨️ 快捷键说明

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