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

📄 scsiio.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************** *	FILE NAME : SCSIIO.C					       * *	     BY   : C.L. Huang					       * *	Description: Device Driver for Tekram DC-390W/U/F (T) PCI SCSI * *		     Bus Master Host Adapter			       * ***********************************************************************/static voidPrepareSG( PACB pACB, PDCB pDCB, PSRB pSRB ){    ULONG  retAddr,wlval;    USHORT wval,i;    PSGL   psgl;    PSGE   psge;    retAddr = pACB->jmp_table8;    if(pDCB->DCBscntl3 & EN_WIDE_SCSI)	retAddr += jmp_table16;    wval = (USHORT)(pSRB->SGcount);    wval <<= 4; 	/* 16 bytes per entry, datain=8, dataout=8 */			/* (4 bytes for count, 4 bytes for addr) */    retAddr -= (ULONG)wval;    pSRB->ReturnAddr = retAddr;    /* return address for SCRIPT */    if(wval)    {	wval >>= 1;	wlval = (ULONG) pSRB->SegmentPad;	wlval -= (ULONG)wval;	wval >>= 3;	psge = (PSGE) wlval;	psgl = pSRB->pSegmentList;	for(i=0; i<wval; i++)	{#ifndef VERSION_ELF_1_2_13	    psge->SGXPtr = virt_to_phys( psgl->address );#else	    psge->SGXPtr = (ULONG) psgl->address;#endif	    psge->SGXLen = psgl->length;	    psge++;	    psgl++;	}    }}static voidDC390W_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ){    USHORT ioport;    UCHAR  bval;    pSRB->TagNumber = 31;    ioport = pACB->IOPortBase;    bval = SIGNAL_PROC;    outb(bval,ioport+ISTAT);    pACB->pActiveDCB = pDCB;    pDCB->pActiveSRB = pSRB;    return;}#ifndef  VERSION_ELF_1_2_13static voidDC390W_Interrupt( int irq, void *dev_id, struct pt_regs *regs)#elsestatic voidDC390W_Interrupt( int irq, struct pt_regs *regs)#endif{    PACB pACB;    PDCB pDCB;    ULONG  wlval;    USHORT ioport = 0;    USHORT wval, i;    void  (*stateV)( PACB );    UCHAR  istat = 0;    UCHAR  bval;    pACB = pACB_start;    if( pACB == NULL )	return;    for( i=0; i < adapterCnt; i++ )    {	if( pACB->IRQLevel == (UCHAR) irq )	{	     ioport = pACB->IOPortBase;	     istat = inb( ioport+ISTAT );	     if( istat & (ABORT_OP+SCSI_INT_PENDING+DMA_INT_PENDING) )		 break;	     else		pACB = pACB->pNextACB;	}	else	{	    pACB = pACB->pNextACB;	}    }    if( pACB == (PACB )-1 )    {	printk("DC390W_intr: Spurious interrupt detected!\n");	return;    }#ifdef DC390W_DEBUG1	printk("Istate=%2x,",istat);#endif    /* if Abort operation occurred, reset abort bit before reading DMA status       to prevent further aborted interrupt.  */    if(istat &	ABORT_OP)    {	istat &= ~ABORT_OP;	outb(istat,ioport+ISTAT);    }    pDCB = pACB->pActiveDCB;    bval = inb(ioport+CTEST2);	 /* Clear Signal Bit */    /*	If Scsi Interrupt, then clear Interrupt Status by reading	Scsi interrupt status register 0. */    wlval = 0;    if(istat & SCSI_INT_PENDING)    {	wlval = (ULONG)inw( ioport+SIST0 );	wlval <<= 8;    }    /*	If DMA Interrupt, then read the DMA status register to see what happen */    if(istat & DMA_INT_PENDING)    {	bval = inb(ioport+DSTAT);	wlval |= (ULONG) bval;    }#ifdef DC390W_DEBUG1	printk("IDstate=%8x,",(UINT) wlval);#endif    if(wlval & ( (SEL_TIMEOUT << 16)+		 ((SCSI_GERROR+UNEXPECT_DISC+SCSI_RESET) << 8)+		 ILLEGAL_INSTRUC+ABORT_) )    {	 ExceptionHandler( wlval, pACB, pDCB );    }    else if( wlval & SCRIPTS_INT )    {	 wval = inw( ioport+DSPS );	 stateV = (void *) IntVector[wval];	 stateV( pACB );    }    else if( wlval & ( PARITY_ERROR << 8) )	ParityError( pACB, pDCB );    else if( wlval & ( PHASE_MISMATCH << 8) )	PhaseMismatch( pACB );    return;}static voidExceptionHandler(ULONG wlval, PACB pACB, PDCB pDCB){    PSRB  pSRB;    UCHAR bval;    USHORT ioport;/* disconnect/scsi reset/illegal instruction */    ioport = pACB->IOPortBase;    if(wlval & ( (SCSI_RESET+SCSI_GERROR) << 8) )	DC390W_ScsiRstDetect( pACB );    else if(wlval & ABORT_)    {#ifdef DC390W_DEBUG0	printk("AboRst,");#endif	if( !InitialTime )	    DC390W_ResetSCSIBus2( pACB );    }    else if(wlval & (SEL_TIMEOUT << 16) )    {	pACB->status = SCSI_STAT_SEL_TIMEOUT;#ifdef DC390W_DEBUG1	printk("Selto,");#endif	DC390W_CmdCompleted( pACB );    }    else if(wlval & (UNEXPECT_DISC << 8) )    {	bval = inb(ioport+STEST3);	bval |= CLR_SCSI_FIFO;	outb(bval,ioport+STEST3);	bval = CLR_DMA_FIFO;	outb(bval,ioport+CTEST3);	pSRB = pDCB->pActiveSRB;	if( pSRB->SRBState & DO_SYNC_NEGO )	{	    pDCB->DevMode &= ~SYNC_NEGO_;	    pACB->status = SCSI_STAT_CHECKCOND;	    DC390W_CmdCompleted( pACB );	}	else if( pSRB->SRBState & DO_WIDE_NEGO )	{	    pDCB->DevMode &= ~WIDE_NEGO_;	    pACB->status = SCSI_STAT_CHECKCOND;	    DC390W_CmdCompleted( pACB );	}	else	{	    pACB->status = SCSI_STAT_UNEXP_BUS_F;	    DC390W_CmdCompleted( pACB );	}#ifdef DC390W_DEBUG0	printk("Uxpbf,");#endif    }    else    {#ifdef DC390W_DEBUG0	printk("Except,");#endif	DC390W_ResetSCSIBus( pACB );    }}static voidParityError( PACB pACB, PDCB pDCB ){    ULONG   ioport;    UCHAR   bval,msg;    ULONG   wlval;    PSRB    pSRB;    ioport = pACB->IOPortBase;    bval = inb(ioport+SCRATCHA);    if(bval & RE_SELECTED_)    {#ifdef DC390W_DEBUG0	printk("ParityErr,");#endif	DC390W_ResetSCSIBus( pACB );	return;    }    else    {	pSRB = pDCB->pActiveSRB;	bval = inb(ioport+STEST3);	bval |= CLR_SCSI_FIFO;	outb(bval,ioport+STEST3);	bval = CLR_DMA_FIFO;	outb(bval,ioport+CTEST3);	bval = inb(ioport+DCMD);	bval &= 0x07;	    /* get phase bits */	if(bval == 0x07)    /* message in phase */	{	    msg = MSG_PARITY_ERROR;	    wlval = pACB->jmp_clear_ack;	}	else	{	    msg = MSG_INITIATOR_ERROR;	    wlval = pACB->jmp_next;	}	pSRB->__msgout0[0] = 1;	pSRB->MsgOutBuf[0] = msg;	outl(wlval,(ioport+DSP));	return;    }}static voidDC390W_Signal( PACB pACB ){    PDCB pDCB;    PSRB pSRB;    USHORT ioport;    ULONG wlval, flags;    UCHAR bval,msgcnt,tagnum;    save_flags(flags);    cli();    ioport = pACB->IOPortBase;    pDCB = pACB->pActiveDCB;    pSRB = pDCB->pActiveSRB;#ifdef DC390W_DEBUG0    printk("Signal,Cmd=%2x", pSRB->CmdBlock[0]);#endif    wlval = pSRB->PhysSRB;    outl(wlval,(ioport+DSA));    wlval = pSRB->ReturnAddr;    outl(wlval,(ioport+TEMP));    msgcnt = 1;    bval = pDCB->IdentifyMsg;    pSRB->MsgOutBuf[0] = bval;    if( (pSRB->CmdBlock[0] != INQUIRY) &&	(pSRB->CmdBlock[0] != REQUEST_SENSE) )    {	if(pDCB->MaxCommand > 1)	{	    wlval = 1;	    tagnum = 0;	    while( wlval & pDCB->TagMask )	    {		wlval = wlval << 1;		tagnum++;	    }	    pDCB->TagMask |= wlval;	    pSRB->TagNumber = tagnum;	    pSRB->MsgOutBuf[1] = MSG_SIMPLE_QTAG;	    pSRB->MsgOutBuf[2] = tagnum;	    msgcnt = 3;	}    }    else    {	pSRB->MsgOutBuf[0] &= 0xBF;	   /* Diable Disconnected */	if(pSRB->CmdBlock[0] == INQUIRY)	{	    if(bval & 0x07)		goto type_6_3;	}	if(pDCB->DevMode & WIDE_NEGO_)	{	    msgcnt = 5;	    *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x01030201;	    pSRB->SRBState |= DO_WIDE_NEGO;	}	else if(pDCB->DevMode & SYNC_NEGO_)	{	    msgcnt = 6;	    *((PULONG) &(pSRB->MsgOutBuf[1])) = 0x00010301;	    pSRB->MsgOutBuf[4] = pDCB->NegoPeriod;	    pSRB->MsgOutBuf[5] = SYNC_NEGO_OFFSET;	    pSRB->SRBState |= DO_SYNC_NEGO;	}    }type_6_3:    pSRB->__msgout0[0] = (ULONG) msgcnt;    wlval = 0;    outl(wlval,(ioport+SCRATCHA));    bval = pDCB->DCBscntl0;    outb(bval,ioport+SCNTL0);    pSRB->__select = *((PULONG) &(pDCB->DCBselect));#ifdef DC390W_DEBUG0    printk("__sel=%8x,", (UINT)(pSRB->__select));#endif    wlval = pACB->jmp_select;    outl(wlval,(ioport+DSP));    restore_flags(flags);    return;}static voidDC390W_MessageWide( PACB pACB ){    PDCB pDCB;    PSRB pSRB;    PUCHAR msgoutPtr;    USHORT ioport;    ULONG wlval;    UCHAR bval,msgcnt;#ifdef DC390W_DEBUG0    printk("MsgWide,");#endif    ioport = pACB->IOPortBase;    pDCB = pACB->pActiveDCB;    pSRB = pDCB->pActiveSRB;    msgcnt = 0;    pDCB->DCBscntl3 &= ~EN_WIDE_SCSI;    msgoutPtr = pSRB->MsgOutBuf;    if( pSRB->SRBState & DO_WIDE_NEGO )    {	pSRB->SRBState &= ~DO_WIDE_NEGO;	if( pACB->msgin123[0] == 3 )	{	    bval = pACB->msgin123[1];	    if(bval == 1)	    {		pDCB->DCBscntl3 |= EN_WIDE_SCSI;		goto x5;	    }	    if(bval < 1)		goto x5;	}    }/*type_11_1:*/    msgcnt = 1;    *msgoutPtr = MSG_REJECT_;    msgoutPtr++;x5:    bval = pDCB->DCBscntl3;    outb(bval,ioport+SCNTL3);    AdjustTemp(pACB,pDCB,pSRB);    SetXferRate(pACB,pDCB);    if( pDCB->DevMode & SYNC_NEGO_ )    {	*((PULONG)msgoutPtr) = 0x00010301;	*(msgoutPtr + 3) = pDCB->NegoPeriod;	*(msgoutPtr + 4) = SYNC_NEGO_OFFSET;	msgcnt += 5;	pSRB->SRBState |= DO_SYNC_NEGO;    }    pSRB->__msgout0[0] = (ULONG) msgcnt;    wlval = pACB->jmp_clear_ack;    if(msgcnt)	wlval = pACB->jmp_set_atn;    outl(wlval,(ioport+DSP));    return;}static voidDC390W_MessageSync( PACB pACB ){    PDCB pDCB;    PSRB pSRB;    USHORT ioport;    ULONG wlval;    USHORT wval,wval1;    UCHAR bval,bval1;#ifdef DC390W_DEBUG0    printk("MsgSync,");#endif    ioport = pACB->IOPortBase;    pDCB = pACB->pActiveDCB;    pSRB = pDCB->pActiveSRB;    if( !(pSRB->SRBState & DO_SYNC_NEGO) )	 goto MessageExtnd;    pSRB->SRBState &= ~DO_SYNC_NEGO;    if(pACB->msgin123[0] != 1)    {MessageExtnd:	pSRB->__msgout0[0] = 1;	pSRB->MsgOutBuf[0] = MSG_REJECT_;	wlval = pACB->jmp_set_atn;	outl(wlval,(ioport+DSP));	return;    }    bval = pACB->msgin123[2];	/* offset */asyncx:    pDCB->DCBsxfer = bval;    if(bval == 0)	 /* if offset or period == 0, async */    {	if( pACB->AdaptType == DC390W )	    bval = SYNC_CLK_F2+ASYNC_CLK_F2;	else	    bval = SYNC_CLK_F4+ASYNC_CLK_F4;	pDCB->DCBscntl3 = bval;    }    else    {	bval = pACB->msgin123[1];	if(bval == 0)	    goto asyncx;	pDCB->SyncPeriod = bval;	wval = (USHORT)bval;	wval <<= 3;	bval = pDCB->DCBscntl3;	bval &= 0x0f;	if(wval < 200)		/* < 100 ns ==> Fast-20 */	{	    bval |= 0x90;	/* Fast-20 and div 1 */	    bval1 = 25; 	/* 12.5 ns */	}	else if(wval < 400)	{	    bval |= 0x30;	/* 1 cycle = 25ns */	    bval1 = 50;	}	else			/* Non Fast */	{	    bval |= 0x50;	/* 1 cycle = 50ns */	    bval1 = 100;	}	if( pACB->AdaptType == DC390W )	    bval -= 0x20;  /* turn down to 40Mhz scsi clock */			   /* assume 390W will not receive fast-20 */	wval1 = wval;	wval /= bval1;	if(wval * bval1 < wval1)	    wval++;			    /* XFERP	 TP2 TP1 TP0  */	wval -= 4;	    /*	 4	  0   0   0   */			    /*	 5	  0   0   1   */	wval <<= 5;	pDCB->DCBsxfer |= (UCHAR)wval;	pDCB->DCBscntl3 = bval;    }/*sync_2:*/    SetXferRate( pACB,pDCB );    wlval = pACB->jmp_clear_ack;/*sync_3:*/    bval = pDCB->DCBscntl3;    outb(bval,ioport+SCNTL3);    bval = pDCB->DCBsxfer;    outb(bval,ioport+SXFER);    outl(wlval,(ioport+DSP));    return;}

⌨️ 快捷键说明

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