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

📄 tmscsim.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************** *	FILE NAME : TMSCSIM.C					       * *	     BY   : C.L. Huang,  ching@tekram.com.tw		       * *	Description: Device Driver for Tekram DC-390(T) PCI SCSI       * *		     Bus Master Host Adapter			       * * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.		       * ***********************************************************************//*	Minor enhancements and bugfixes by				* *	Kurt Garloff <K.Garloff@ping.de>				* ***********************************************************************//*	HISTORY:							* *									* *	REV#	DATE	NAME	DESCRIPTION				* *	1.00  04/24/96	CLH	First release				* *	1.01  06/12/96	CLH	Fixed bug of Media Change for Removable * *				Device, scan all LUN. Support Pre2.0.10 * *	1.02  06/18/96	CLH	Fixed bug of Command timeout ...	* *	1.03  09/25/96	KG	Added tmscsim_proc_info()		* *	1.04  10/11/96	CLH	Updating for support KV 2.0.x		* *	1.05  10/18/96	KG	Fixed bug in DC390_abort(null ptr deref)* *	1.06  10/25/96	KG	Fixed module support			* *	1.07  11/09/96	KG	Fixed tmscsim_proc_info()		* *	1.08  11/18/96	KG	Fixed null ptr in DC390_Disconnect()	* *	1.09  11/30/96	KG	Added register the allocated IO space	* *	1.10  12/05/96	CLH	Modified tmscsim_proc_info(), and reset * *				pending interrupt in DC390_detect()	* * 	1.11  02/05/97	KG/CLH	Fixeds problem with partitions greater	* * 				than 1GB				* ***********************************************************************/#define DC390_DEBUG#define SCSI_MALLOC#ifdef MODULE#include <linux/module.h>#endif#include <asm/dma.h>#include <asm/io.h>#include <asm/system.h>#include <linux/delay.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/bios32.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/config.h>#include <linux/version.h>#if LINUX_VERSION_CODE < 66354 /* 1.3.50 */#include "../block/blk.h"#else#include <linux/blk.h>#endif#include "scsi.h"#include "hosts.h"#include "tmscsim.h"#include "constants.h"#include "sd.h"#include <linux/stat.h>#include "dc390.h"#define PCI_DEVICE_ID_AMD53C974 	PCI_DEVICE_ID_AMD_SCSI#ifndef  VERSION_ELF_1_2_13struct proc_dir_entry	proc_scsi_tmscsim ={       PROC_SCSI_DC390T, 7 ,"tmscsim",       S_IFDIR | S_IRUGO | S_IXUGO, 2       };#endifstatic USHORT DC390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );static void DC390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void DC390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void SetXferRate( PACB pACB, PDCB pDCB );static void DC390_Disconnect( PACB pACB );static void DC390_Reselect( PACB pACB );static void SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );static void DoingSRB_Done( PACB pACB );static void DC390_ScsiRstDetect( PACB pACB );static void DC390_ResetSCSIBus( PACB pACB );static void RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );static void EnableMsgOut2( PACB pACB, PSRB pSRB );static void EnableMsgOut( PACB pACB, PSRB pSRB );static void DC390_InvalidCmd( PACB pACB );int    DC390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, USHORT index );void   DC390_initDCB( PACB pACB, PDCB pDCB, PSCSICMD cmd );#ifdef MODULEstatic int DC390_release(struct Scsi_Host *host);static int DC390_shutdown (struct Scsi_Host *host);#endifstatic PSHT	pSHT_start = NULL;static PSH	pSH_start = NULL;static PSH	pSH_current = NULL;static PACB	pACB_start= NULL;static PACB	pACB_current = NULL;static PDCB	pPrevDCB = NULL;static USHORT	adapterCnt = 0;static USHORT	InitialTime = 0;static USHORT	CurrSyncOffset = 0;static ULONG	mech1addr;static UCHAR	mech2bus, mech2Agent, mech2CfgSPenR;static PVOID DC390_phase0[]={       DC390_DataOut_0,       DC390_DataIn_0,       DC390_Command_0,       DC390_Status_0,       DC390_Nop_0,       DC390_Nop_0,       DC390_MsgOut_0,       DC390_MsgIn_0,       DC390_Nop_1       };static PVOID DC390_phase1[]={       DC390_DataOutPhase,       DC390_DataInPhase,       DC390_CommandPhase,       DC390_StatusPhase,       DC390_Nop_0,       DC390_Nop_0,       DC390_MsgOutPhase,       DC390_MsgInPhase,       DC390_Nop_1,       };UCHAR  eepromBuf[MAX_ADAPTER_NUM][128];UCHAR  clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};UCHAR  baddevname1[2][28] ={       "SEAGATE ST3390N         9546",       "HP      C3323-300       4269"};#define BADDEVCNT	2/*********************************************************************** * * * **********************************************************************/static voidQLinkcmd( PSCSICMD cmd, PDCB pDCB ){    ULONG  flags;    PSCSICMD  pcmd;    save_flags(flags);    cli();    if( !pDCB->QIORBCnt )    {	pDCB->pQIORBhead = cmd;	pDCB->pQIORBtail = cmd;	pDCB->QIORBCnt++;	cmd->next = NULL;    }    else    {	pcmd = pDCB->pQIORBtail;	pcmd->next = cmd;	pDCB->pQIORBtail = cmd;	pDCB->QIORBCnt++;	cmd->next = NULL;    }    restore_flags(flags);}static PSCSICMDGetcmd( PDCB pDCB ){    ULONG  flags;    PSCSICMD  pcmd;    save_flags(flags);    cli();    pcmd = pDCB->pQIORBhead;    pDCB->pQIORBhead = pcmd->next;    pcmd->next = NULL;    pDCB->QIORBCnt--;    restore_flags(flags);    return( pcmd );}static PSRBGetSRB( PACB pACB ){    ULONG  flags;    PSRB   pSRB;    save_flags(flags);    cli();    pSRB = pACB->pFreeSRB;    if( pSRB )    {	pACB->pFreeSRB = pSRB->pNextSRB;	pSRB->pNextSRB = NULL;    }    restore_flags(flags);    return( pSRB );}static voidRewaitSRB0( PDCB pDCB, PSRB pSRB ){    PSRB   psrb1;    ULONG  flags;    save_flags(flags);    cli();    if( (psrb1 = pDCB->pWaitingSRB) )    {	pSRB->pNextSRB = psrb1;	pDCB->pWaitingSRB = pSRB;    }    else    {	pSRB->pNextSRB = NULL;	pDCB->pWaitingSRB = pSRB;	pDCB->pWaitLast = pSRB;    }    restore_flags(flags);}static voidRewaitSRB( PDCB pDCB, PSRB pSRB ){    PSRB   psrb1;    ULONG  flags;    UCHAR  bval;    save_flags(flags);    cli();    pDCB->GoingSRBCnt--;    psrb1 = pDCB->pGoingSRB;    if( pSRB == psrb1 )    {	pDCB->pGoingSRB = psrb1->pNextSRB;    }    else    {	while( pSRB != psrb1->pNextSRB )	    psrb1 = psrb1->pNextSRB;	psrb1->pNextSRB = pSRB->pNextSRB;	if( pSRB == pDCB->pGoingLast )	    pDCB->pGoingLast = psrb1;    }    if( (psrb1 = pDCB->pWaitingSRB) )    {	pSRB->pNextSRB = psrb1;	pDCB->pWaitingSRB = pSRB;    }    else    {	pSRB->pNextSRB = NULL;	pDCB->pWaitingSRB = pSRB;	pDCB->pWaitLast = pSRB;    }    bval = pSRB->TagNumber;    pDCB->TagMask &= (~(1 << bval));	  /* Free TAG number */    restore_flags(flags);}static voidDoWaitingSRB( PACB pACB ){    ULONG  flags;    PDCB   ptr, ptr1;    PSRB   pSRB;    save_flags(flags);    cli();    if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )    {	ptr = pACB->pDCBRunRobin;	if( !ptr )	{	    ptr = pACB->pLinkDCB;	    pACB->pDCBRunRobin = ptr;	}	ptr1 = ptr;	for( ;ptr1; )	{	    pACB->pDCBRunRobin = ptr1->pNextDCB;	    if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||		!( pSRB = ptr1->pWaitingSRB ) )	    {		if(pACB->pDCBRunRobin == ptr)		    break;		ptr1 = ptr1->pNextDCB;	    }	    else	    {		if( !DC390_StartSCSI(pACB, ptr1, pSRB) )		{		    ptr1->GoingSRBCnt++;		    if( ptr1->pWaitLast == pSRB )		    {			ptr1->pWaitingSRB = NULL;			ptr1->pWaitLast = NULL;		    }		    else		    {			ptr1->pWaitingSRB = pSRB->pNextSRB;		    }		    pSRB->pNextSRB = NULL;		    if( ptr1->pGoingSRB )			ptr1->pGoingLast->pNextSRB = pSRB;		    else			ptr1->pGoingSRB = pSRB;		    ptr1->pGoingLast = pSRB;		}		break;	    }	}    }    restore_flags(flags);    return;}static voidSRBwaiting( PDCB pDCB, PSRB pSRB){    if( pDCB->pWaitingSRB )    {	pDCB->pWaitLast->pNextSRB = pSRB;	pDCB->pWaitLast = pSRB;	pSRB->pNextSRB = NULL;    }    else    {	pDCB->pWaitingSRB = pSRB;	pDCB->pWaitLast = pSRB;    }}static voidSendSRB( PSCSICMD pcmd, PACB pACB, PSRB pSRB ){    ULONG  flags;    PDCB   pDCB;    save_flags(flags);    cli();    pDCB = pSRB->pSRBDCB;    if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||	(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )    {	SRBwaiting(pDCB, pSRB);	goto SND_EXIT;    }    if( pDCB->pWaitingSRB )    {	SRBwaiting(pDCB, pSRB);/*	pSRB = GetWaitingSRB(pDCB); */	pSRB = pDCB->pWaitingSRB;	pDCB->pWaitingSRB = pSRB->pNextSRB;	pSRB->pNextSRB = NULL;    }    if( !DC390_StartSCSI(pACB, pDCB, pSRB) )    {	pDCB->GoingSRBCnt++;	if( pDCB->pGoingSRB )	{	    pDCB->pGoingLast->pNextSRB = pSRB;	    pDCB->pGoingLast = pSRB;	}	else	{	    pDCB->pGoingSRB = pSRB;	    pDCB->pGoingLast = pSRB;	}    }    else	RewaitSRB0( pDCB, pSRB );SND_EXIT:    restore_flags(flags);    return;}/*********************************************************************** * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, *					       void (*done)(Scsi_Cmnd *)) * * Purpose : enqueues a SCSI command * * Inputs : cmd - SCSI command, done - function called on completion, with *	    a pointer to the command descriptor. * * Returns : 0 * ***********************************************************************/intDC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)){    USHORT ioport, i;    Scsi_Cmnd *pcmd;    struct Scsi_Host *psh;    PACB   pACB;    PDCB   pDCB;    PSRB   pSRB;    ULONG  flags;    PUCHAR ptr,ptr1;    psh = cmd->host;    pACB = (PACB ) psh->hostdata;    ioport = pACB->IOPortBase;#ifdef DC390_DEBUG0/*  if(pACB->scan_devices) */	printk("Cmd=%2x,ID=%d,LUN=%d,",cmd->cmnd[0],cmd->target,cmd->lun);#endif    if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) )    {	pACB->scan_devices = 0;	pPrevDCB->pNextDCB = pACB->pLinkDCB;    }    else if( (pACB->scan_devices) && (cmd->cmnd[0] == 8) )    {	pACB->scan_devices = 0;	pPrevDCB->pNextDCB = pACB->pLinkDCB;    }    if ( ( cmd->target > pACB->max_id ) || (cmd->lun > pACB->max_lun) )    {/*	printk("DC390: Ignore target %d lun %d\n",		cmd->target, cmd->lun); */	cmd->result = (DID_BAD_TARGET << 16);	done(cmd);	return( 0 );    }    if( (pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )    {	if( pACB->DeviceCnt < MAX_DEVICES )	{	    pACB->DCBmap[cmd->target] |= (1 << cmd->lun);	    pDCB = pACB->pDCB_free;#ifdef DC390_DEBUG0	    printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);#endif	    DC390_initDCB( pACB, pDCB, cmd );	}	else	/* ???? */	{/*	    printk("DC390: Ignore target %d lun %d\n",		    cmd->target, cmd->lun); */	    cmd->result = (DID_BAD_TARGET << 16);	    done(cmd);	    return(0);	}    }    else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )    {/*	printk("DC390: Ignore target %d lun %d\n",		cmd->target, cmd->lun); */	cmd->result = (DID_BAD_TARGET << 16);	done(cmd);	return(0);    }    else    {	pDCB = pACB->pLinkDCB;	while( (pDCB->UnitSCSIID != cmd->target) ||	       (pDCB->UnitSCSILUN != cmd->lun) )	{	    pDCB = pDCB->pNextDCB;	}#ifdef DC390_DEBUG0	    printk("pDCB=%8x,ID=%2x,", (UINT) pDCB, cmd->target);#endif    }    cmd->scsi_done = done;    cmd->result = 0;    save_flags(flags);    cli();    if( pDCB->QIORBCnt )    {	QLinkcmd( cmd, pDCB );	pcmd = Getcmd( pDCB );    }    else	pcmd = cmd;    pSRB = GetSRB( pACB );    if( !pSRB )    {	QLinkcmd( pcmd, pDCB );	restore_flags(flags);	return(0);    }/*  BuildSRB(pSRB); */    pSRB->pSRBDCB = pDCB;    pSRB->pcmd = pcmd;    ptr = (PUCHAR) pSRB->CmdBlock;    ptr1 = (PUCHAR) pcmd->cmnd;    pSRB->ScsiCmdLen = pcmd->cmd_len;    for(i=0; i< pcmd->cmd_len; i++)    {	*ptr = *ptr1;	ptr++;	ptr1++;    }    if( pcmd->use_sg )    {	pSRB->SGcount = (UCHAR) pcmd->use_sg;	pSRB->pSegmentList = (PSGL) pcmd->request_buffer;    }    else if( pcmd->request_buffer )    {	pSRB->SGcount = 1;	pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;	pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;	pSRB->Segmentx.length = pcmd->request_bufflen;    }    else	pSRB->SGcount = 0;    pSRB->SGIndex = 0;    pSRB->AdaptStatus = 0;    pSRB->TargetStatus = 0;    pSRB->MsgCnt = 0;    if( pDCB->DevType != TYPE_TAPE )	pSRB->RetryCnt = 1;    else	pSRB->RetryCnt = 0;    pSRB->SRBStatus = 0;    pSRB->SRBFlag = 0;    pSRB->SRBState = 0;    pSRB->TotalXferredLen = 0;    pSRB->SGPhysAddr = 0;    pSRB->SGToBeXferLen = 0;    pSRB->ScsiPhase = 0;    pSRB->EndMessage = 0;    SendSRB( pcmd, pACB, pSRB );    restore_flags(flags);    return(0);}static voidDoNextCmd( PACB pACB, PDCB pDCB ){    Scsi_Cmnd *pcmd;    PSRB   pSRB;    ULONG  flags;    PUCHAR ptr,ptr1;    USHORT i;    if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )	return;    save_flags(flags);    cli();    pcmd = Getcmd( pDCB );    pSRB = GetSRB( pACB );    if( !pSRB )    {	QLinkcmd( pcmd, pDCB );	restore_flags(flags);	return;    }    pSRB->pSRBDCB = pDCB;    pSRB->pcmd = pcmd;    ptr = (PUCHAR) pSRB->CmdBlock;    ptr1 = (PUCHAR) pcmd->cmnd;    pSRB->ScsiCmdLen = pcmd->cmd_len;    for(i=0; i< pcmd->cmd_len; i++)    {	*ptr = *ptr1;	ptr++;	ptr1++;    }    if( pcmd->use_sg )    {	pSRB->SGcount = (UCHAR) pcmd->use_sg;	pSRB->pSegmentList = (PSGL) pcmd->request_buffer;    }    else if( pcmd->request_buffer )    {	pSRB->SGcount = 1;	pSRB->pSegmentList = (PSGL) &pSRB->Segmentx;	pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer;

⌨️ 快捷键说明

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