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

📄 scsiiom.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    else		pSRB->SGToBeXferLen = 0;	}	else	/* phase changed */	{	    residual = 0;	    bval = DC390_read8 (Current_Fifo);	    while( bval & 0x1f )	    {		DEBUG1(printk (KERN_DEBUG "Check for residuals,");)		if( (bval & 0x1f) == 1 )		{		    for(i=0; i < 0x100; i++)		    {			bval = DC390_read8 (Current_Fifo);			if( !(bval & 0x1f) )			    goto din_1;			else if( i == 0x0ff )			{			    residual = 1;   /* ;1 residual byte */			    goto din_1;			}		    }		}		else		    bval = DC390_read8 (Current_Fifo);	    }din_1:	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);	    for (i = 0xa000; i; i--)	    {		bval = DC390_read8 (DMA_Status);		if (bval & BLAST_COMPLETE)		    break;	    }	    /* It seems a DMA Blast abort isn't that bad ... */	    if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");	    //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */	    dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;	    DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval);)	    ResidCnt = (UINT) DC390_read8 (CtcReg_High);	    ResidCnt <<= 8;	    ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid);	    ResidCnt <<= 8;	    ResidCnt |= (UINT) DC390_read8 (CtcReg_Low);	    xferCnt = pSRB->SGToBeXferLen - ResidCnt;	    pSRB->SGBusAddr += xferCnt;	    pSRB->TotalXferredLen += xferCnt;	    pSRB->SGToBeXferLen = ResidCnt;	    if( residual )	    {		bval = DC390_read8 (ScsiFifo);	    /* get one residual byte */		ptr = (PUCHAR) bus_to_virt( pSRB->SGBusAddr );		*ptr = bval;		pSRB->SGBusAddr++; xferCnt++;		pSRB->TotalXferredLen++;		pSRB->SGToBeXferLen--;	    }	    DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\			   pSRB->TotalXferredLen, pSRB->SGToBeXferLen);)	}    }    if ((*psstatus & 7) != SCSI_DATA_IN)    {	    DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);	    DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */    }	    }static voiddc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){}static voiddc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    pSRB->TargetStatus = DC390_read8 (ScsiFifo);    //udelay (1);    pSRB->EndMessage = DC390_read8 (ScsiFifo);	/* get message */    *psstatus = SCSI_NOP0;    pSRB->SRBState = SRB_COMPLETED;    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);}static voiddc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )	*psstatus = SCSI_NOP0;    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);}static void __inline__dc390_reprog (PACB pACB, PDCB pDCB){  DC390_write8 (Sync_Period, pDCB->SyncPeriod);  DC390_write8 (Sync_Offset, pDCB->SyncOffset);  DC390_write8 (CtrlReg3, pDCB->CtrlR3);  DC390_write8 (CtrlReg4, pDCB->CtrlR4);  dc390_SetXferRate (pACB, pDCB);};#ifdef DC390_DEBUG0static voiddc390_printMsg (UCHAR *MsgBuf, UCHAR len){  int i;  printk (" %02x", MsgBuf[0]);  for (i = 1; i < len; i++)    printk (" %02x", MsgBuf[i]);  printk ("\n");};#endif#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)/* reject_msg */static void __inline__dc390_MsgIn_reject (PACB pACB, PSRB pSRB){  pSRB->MsgOutBuf[0] = MESSAGE_REJECT;  pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;  DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)}/* abort command */static void __inline__dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ){    pSRB->MsgOutBuf[0] = ABORT;     pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;    pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;}static PSRBdc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag){  PSRB lastSRB = pDCB->pGoingLast;  PSRB pSRB = pDCB->pGoingSRB;  if (pSRB)    {      for( ;pSRB ; )	{	  if (pSRB->TagNumber == tag) break;	  if (pSRB == lastSRB) goto mingx0;	  pSRB = pSRB->pNextSRB;	}      if( pDCB->DCBFlag & ABORT_DEV_ )	{	  pSRB->SRBState = SRB_ABORT_SENT;	  dc390_EnableMsgOut_Abort( pACB, pSRB );	}      if( !(pSRB->SRBState & SRB_DISCONNECT) )	goto  mingx0;      pDCB->pActiveSRB = pSRB;      pSRB->SRBState = SRB_DATA_XFER;    }  else    {    mingx0:      pSRB = pACB->pTmpSRB;      pSRB->SRBState = SRB_UNEXPECT_RESEL;      pDCB->pActiveSRB = pSRB;      pSRB->MsgOutBuf[0] = ABORT_TAG;      pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;    }  return pSRB;}/* set async transfer mode */static void dc390_MsgIn_set_async (PACB pACB, PSRB pSRB){  PDCB pDCB = pSRB->pSRBDCB;  if (!(pSRB->SRBState & DO_SYNC_NEGO))     printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);  pSRB->SRBState &= ~DO_SYNC_NEGO;  pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);  pDCB->SyncPeriod = 0;  pDCB->SyncOffset = 0;  //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */  pDCB->CtrlR3 = FAST_CLK;	/* fast clock / normal scsi */  pDCB->CtrlR4 &= 0x3f;  pDCB->CtrlR4 |= pACB->glitch_cfg;	/* glitch eater */  dc390_reprog (pACB, pDCB);}/* set sync transfer mode */static voiddc390_MsgIn_set_sync (PACB pACB, PSRB pSRB){  UCHAR bval;  USHORT wval, wval1;  PDCB pDCB = pSRB->pSRBDCB;  UCHAR oldsyncperiod = pDCB->SyncPeriod;  UCHAR oldsyncoffset = pDCB->SyncOffset;    if (!(pSRB->SRBState & DO_SYNC_NEGO))    {      printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", 	      pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);      /* reject */      //dc390_MsgIn_reject (pACB, pSRB);      //return dc390_MsgIn_set_async (pACB, pSRB);      /* Reply with corrected SDTR Message */      if (pSRB->MsgInBuf[4] > 15)	{ 	  printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");	  pSRB->MsgInBuf[4] = 15;	}      if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)	{	  printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);	  pSRB->MsgInBuf[3] = pDCB->NegoPeriod;	};      memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);      pSRB->MsgCnt = 5;      DC390_ENABLE_MSGOUT;    };  pSRB->SRBState &= ~DO_SYNC_NEGO;  pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;  pDCB->SyncOffset &= 0x0f0;  pDCB->SyncOffset |= pSRB->MsgInBuf[4];  pDCB->NegoPeriod = pSRB->MsgInBuf[3];  wval = (USHORT) pSRB->MsgInBuf[3];  wval = wval << 2; wval -= 3; wval1 = wval / 25;	/* compute speed */  if( (wval1 * 25) != wval) wval1++;  bval = FAST_CLK+FAST_SCSI;	/* fast clock / fast scsi */  pDCB->CtrlR4 &= 0x3f;		/* Glitch eater: 12ns less than normal */  if (pACB->glitch_cfg != NS_TO_GLITCH(0))    pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));  else    pDCB->CtrlR4 |= NS_TO_GLITCH(0);  if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */  if (wval1 >= 8)    {      wval1--;	/* Timing computation differs by 1 from FAST_SCSI */      bval = FAST_CLK;		/* fast clock / normal scsi */      pDCB->CtrlR4 |= pACB->glitch_cfg; 	/* glitch eater */    }  pDCB->CtrlR3 = bval;  pDCB->SyncPeriod = (UCHAR)wval1;    if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)    {      if (! (bval & FAST_SCSI)) wval1++;      printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, 	      40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);    }    dc390_reprog (pACB, pDCB);};/* handle RESTORE_PTR */static void dc390_restore_ptr (PACB pACB, PSRB pSRB){  PSGL psgl;  pSRB->TotalXferredLen = 0;  pSRB->SGIndex = 0;  if( pSRB->pcmd->use_sg )    {      pSRB->SGcount = (UCHAR) pSRB->pcmd->use_sg;      pSRB->pSegmentList = (PSGL) pSRB->pcmd->request_buffer;      psgl = pSRB->pSegmentList;      while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr)	{	  pSRB->TotalXferredLen += (ULONG) psgl->length;	  pSRB->SGIndex++;	  if( pSRB->SGIndex < pSRB->SGcount )	    {	      pSRB->pSegmentList++;	      psgl = pSRB->pSegmentList;	      	      pSRB->SGBusAddr = virt_to_bus( psgl->address );	      pSRB->SGToBeXferLen = (ULONG) psgl->length;	    }	  else	    pSRB->SGToBeXferLen = 0;	}      pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);      pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);      printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);    }    else if( pSRB->pcmd->request_buffer )    {	pSRB->SGcount = 1;	pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;	pSRB->Segmentx.address = (PUCHAR) pSRB->pcmd->request_buffer + pSRB->Saved_Ptr;	pSRB->Segmentx.length = pSRB->pcmd->request_bufflen - pSRB->Saved_Ptr;	printk (KERN_INFO "DC390: Pointer restored. Total %li, Bus %p\n",		pSRB->Saved_Ptr, pSRB->Segmentx.address);    }     else       {	 pSRB->SGcount = 0;	 printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n");       };  pSRB->TotalXferredLen = pSRB->Saved_Ptr;};/* According to the docs, the AM53C974 reads the message and  * generates a Succesful Operation IRQ before asserting ACK for * the last byte (how does it know whether it's the last ?) *//* The old code handled it in another way, indicating, that on * every message byte an IRQ is generated and every byte has to * be manually ACKed. Hmmm ?  (KG, 98/11/28) *//* The old implementation was correct. Sigh! *//* Check if the message is complete */static UCHAR __inline__dc390_MsgIn_complete (UCHAR *msgbuf, UINT len){   if (*msgbuf == EXTENDED_MESSAGE)  {	if (len < 2) return 0;	if (len < msgbuf[1] + 2) return 0;  }  else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages	if (len < 2) return 0;  return 1;}/* read and eval received messages */voiddc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus){    PDCB   pDCB = pACB->pActiveDCB;    /* Read the msg */    pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);    //pSRB->SRBState = 0;    /* Msg complete ? */    if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))      {	DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);)	/* Now eval the msg */	switch (pSRB->MsgInBuf[0]) 	  {	  case DISCONNECT: 	    pSRB->SRBState = SRB_DISCONNECT; break;	    	  case SIMPLE_QUEUE_TAG:	  case HEAD_OF_QUEUE_TAG:	  case ORDERED_QUEUE_TAG:	    pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);	    break;	    	  case MESSAGE_REJECT: 	    DC390_write8 (ScsiCmd, RESET_ATN_CMD);	    pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */	    if( pSRB->SRBState & DO_SYNC_NEGO)	      dc390_MsgIn_set_async (pACB, pSRB);	    break;	    	  case EXTENDED_MESSAGE:	    /* reject every extended msg but SDTR */	    if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)	      dc390_MsgIn_reject (pACB, pSRB);	    else	      {		if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)		  dc390_MsgIn_set_async (pACB, pSRB);		else		  dc390_MsgIn_set_sync (pACB, pSRB);	      };	    	    // nothing has to be done	  case COMMAND_COMPLETE: break;	    	    // SAVE POINTER may be ignored as we have the PSRB associated with the	    // scsi command. Thanks, Gerard, for pointing it out.	  case SAVE_POINTERS: 	    pSRB->Saved_Ptr = pSRB->TotalXferredLen;	    break;	    // The device might want to restart transfer with a RESTORE	  case RESTORE_POINTERS:	    DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n");)	    dc390_restore_ptr (pACB, pSRB);	    break;	    // reject unknown messages	  default: dc390_MsgIn_reject (pACB, pSRB);	  }		/* Clear counter and MsgIn state */	pSRB->SRBState &= ~SRB_MSGIN;	pACB->MsgLen = 0;      };    *psstatus = SCSI_NOP0;    DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);    //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);}voiddc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir){    PSGL   psgl;    ULONG  lval;    PDCB   pDCB = pACB->pActiveDCB;    if (pSRB == pACB->pTmpSRB)    {	if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",			  pDCB->TargetID, pDCB->TargetLUN);	else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");	dc390_EnableMsgOut_Abort (pACB, pSRB);	if (pDCB) pDCB->DCBFlag |= ABORT_DEV;	return;    }    if( pSRB->SGIndex < pSRB->SGcount )    {	DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);	if( !pSRB->SGToBeXferLen )	{	    psgl = pSRB->pSegmentList;	    pSRB->SGBusAddr = virt_to_bus( psgl->address );

⌨️ 快捷键说明

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