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

📄 tmscsim.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	    printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", 		    cmd->target, cmd->lun);	    DC390_UNLOCK_ACB;	    printk ("DC390: No DCB in queuecommand (2)!\n");#ifdef USE_NEW_EH	    return (1);#else	    done (cmd);	    return (0);#endif	 };    }    pACB->Cmds++;    cmd->scsi_done = done;    cmd->result = 0;	    dc390_Query_to_Waiting (pACB);    if( pACB->QueryCnt ) /* Unsent commands ? */    {	DEBUG0(printk ("DC390: QueryCnt != 0\n");)	dc390_Query_append ( cmd, pACB );	dc390_Waiting_process (pACB);    }    else if (pDCB->pWaitingSRB)    { 	pSRB = dc390_Free_get ( pACB );	DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n");)	if (!pSRB) dc390_Query_append (cmd, pACB);	else 	  {	    dc390_BuildSRB (cmd, pDCB, pSRB);	    dc390_Waiting_append (pDCB, pSRB);	  }	dc390_Waiting_process (pACB);    }    else    { 	pSRB = dc390_Free_get ( pACB );	DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n");)	if (!pSRB)	{	    dc390_Query_append (cmd, pACB);	    dc390_Waiting_process (pACB);	}	else 	{	    dc390_BuildSRB (cmd, pDCB, pSRB);	    dc390_SendSRB (pACB, pSRB);	};    };    DC390_UNLOCK_ACB;    DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid);)    return(0);}/* We ignore mapping problems, as we expect everybody to respect  * valid partition tables. Waiting for complaints ;-) */#ifdef CONFIG_SCSI_DC390T_TRADMAP/*  * The next function, partsize(), is copied from scsicam.c. * * This is ugly code duplication, but I didn't find another way to solve it: * We want to respect the partition table and if it fails, we apply the  * DC390 BIOS heuristic. Too bad, just calling scsicam_bios_param() doesn't do * the job, because we don't know, whether the values returned are from * the part. table or determined by setsize(). Unfortunately the setsize()  * values differ from the ones chosen by the DC390 BIOS. * * Looking forward to seeing suggestions for a better solution! KG, 98/10/14 */#include <asm/unaligned.h>/* * Function : static int partsize(struct buffer_head *bh, unsigned long  *     capacity,unsigned int *cyls, unsigned int *hds, unsigned int *secs); * * Purpose : to determine the BIOS mapping used to create the partition *	table, storing the results in *cyls, *hds, and *secs  * * Returns : -1 on failure, 0 on success. * */static int partsize(struct buffer_head *bh, unsigned long capacity,    unsigned int  *cyls, unsigned int *hds, unsigned int *secs) {    struct partition *p, *largest = NULL;    int i, largest_cyl;    int cyl, ext_cyl, end_head, end_cyl, end_sector;    unsigned int logical_end, physical_end, ext_physical_end;        if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {	for (largest_cyl = -1, p = (struct partition *)     	    (0x1BE + bh->b_data), i = 0; i < 4; ++i, ++p) {    	    if (!p->sys_ind)    	    	continue;    	    cyl = p->cyl + ((p->sector & 0xc0) << 2);    	    if (cyl > largest_cyl) {    	    	largest_cyl = cyl;    	    	largest = p;    	    }    	}    }    if (largest) {    	end_cyl = largest->end_cyl + ((largest->end_sector & 0xc0) << 2);    	end_head = largest->end_head;    	end_sector = largest->end_sector & 0x3f;    	physical_end =  end_cyl * (end_head + 1) * end_sector +    	    end_head * end_sector + end_sector;	/* This is the actual _sector_ number at the end */	logical_end = get_unaligned(&largest->start_sect)			+ get_unaligned(&largest->nr_sects);	/* This is for >1023 cylinders */        ext_cyl= (logical_end-(end_head * end_sector + end_sector))                                        /(end_head + 1) / end_sector;	ext_physical_end = ext_cyl * (end_head + 1) * end_sector +            end_head * end_sector + end_sector;    	if ((logical_end == physical_end) ||	    (end_cyl==1023 && ext_physical_end==logical_end)) {    	    *secs = end_sector;    	    *hds = end_head + 1;    	    *cyls = capacity / ((end_head + 1) * end_sector);    	    return 0;    	}    }    return -1;}/*********************************************************************** * Function: *   DC390_bios_param * * Description: *   Return the disk geometry for the given SCSI device. *   Respect the partition table, otherwise try own heuristic * * Note: *   In contrary to other externally callable funcs (DC390_), we don't lock ***********************************************************************/int DC390_bios_param (Disk *disk, kdev_t devno, int geom[]){    int heads, sectors, cylinders;    PACB pACB = (PACB) disk->device->host->hostdata;    struct buffer_head *bh;    int ret_code = -1;    int size = disk->capacity;    if ((bh = bread(MKDEV(MAJOR(devno), MINOR(devno)&~0xf), 0, 1024)))    {	/* try to infer mapping from partition table */	ret_code = partsize (bh, (unsigned long) size, (unsigned int *) geom + 2,			     (unsigned int *) geom + 0, (unsigned int *) geom + 1);	brelse (bh);    }    if (ret_code == -1)    {	heads = 64;	sectors = 32;	cylinders = size / (heads * sectors);	if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) )	{		heads = 255;		sectors = 63;		cylinders = size / (heads * sectors);	}	geom[0] = heads;	geom[1] = sectors;	geom[2] = cylinders;    }    return (0);}#elseint DC390_bios_param (Disk *disk, kdev_t devno, int geom[]){    return scsicam_bios_param (disk, devno, geom);};#endifvoid dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB){    USHORT pstat; PDEVDECL1;    if (!pDCB) pDCB = pACB->pActiveDCB;    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;    if (pSRB)     {	printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",		pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,		pSRB->ScsiPhase);	printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);    };    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);    printk ("DC390: Register dump: SCSI block:\n");    printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");    printk ("DC390:  %06x   %02x   %02x   %02x",	    DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),	    DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));    printk ("   %02x   %02x   %02x   %02x   %02x   %02x\n",	    DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),	    DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));    DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);    if (DC390_read8(Current_Fifo) & 0x1f)      {	printk ("DC390: FIFO:");	while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));	printk ("\n");      };    printk ("DC390: Register dump: DMA engine:\n");    printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");    printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",	    DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),	    DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),	    DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));    DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);    PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat);    printk ("DC390: Register dump: PCI Status: %04x\n", pstat);    printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n");};/*********************************************************************** * Function : int DC390_abort (Scsi_Cmnd *cmd) * * Purpose : Abort an errant SCSI command * * Inputs : cmd - command to abort * * Returns : 0 on success, -1 on failure. * * Status: Buggy ! ***********************************************************************/int DC390_abort (Scsi_Cmnd *cmd){    PDCB  pDCB;    PSRB  pSRB, psrb;    UINT  count, i;    PSCSICMD  pcmd;    int   status;    //ULONG sbac;    DC390_AFLAGS    PACB  pACB = (PACB) cmd->host->hostdata;    DC390_LOCK_ACB;    printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",	    cmd->pid, cmd->target, cmd->lun);    /* First scan Query list */    if( pACB->QueryCnt )    {	pcmd = pACB->pQueryHead;	if( pcmd == cmd )	{	    /* Found: Dequeue */	    pACB->pQueryHead = pcmd->next;	    pcmd->next = NULL;	    if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;	    pACB->QueryCnt--;	    status = SCSI_ABORT_SUCCESS;	    goto  ABO_X;	}	for( count = pACB->QueryCnt, i=0; i<count-1; i++)	{	    if( pcmd->next == cmd )	    {		pcmd->next = cmd->next;		cmd->next = NULL;		if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;		pACB->QueryCnt--;		status = SCSI_ABORT_SUCCESS;		goto  ABO_X;	    }	    else	    {		pcmd = pcmd->next;	    }	}    }	    pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);    if( !pDCB ) goto  NOT_RUN;    /* Added 98/07/02 KG */    /*    pSRB = pDCB->pActiveSRB;    if (pSRB && pSRB->pcmd == cmd )	goto ON_GOING;     */        pSRB = pDCB->pWaitingSRB;    if( !pSRB )	goto  ON_GOING;    /* Now scan Waiting queue */    if( pSRB->pcmd == cmd )    {	pDCB->pWaitingSRB = pSRB->pNextSRB;	goto  IN_WAIT;    }    else    {	psrb = pSRB;	if( !(psrb->pNextSRB) )	    goto ON_GOING;	while( psrb->pNextSRB->pcmd != cmd )	{	    psrb = psrb->pNextSRB;	    if( !(psrb->pNextSRB) || psrb == pSRB)		goto ON_GOING;	}	pSRB = psrb->pNextSRB;	psrb->pNextSRB = pSRB->pNextSRB;	if( pSRB == pDCB->pWaitLast )	    pDCB->pWaitLast = psrb;IN_WAIT:	dc390_Free_insert (pACB, pSRB);	pDCB->WaitSRBCnt--;	cmd->next = NULL;	status = SCSI_ABORT_SUCCESS;	goto  ABO_X;    }    /* SRB has already been sent ! */ON_GOING:    /* abort() is too stupid for already sent commands at the moment.      * If it's called we are in trouble anyway, so let's dump some info      * into the syslog at least. (KG, 98/08/20,99/06/20) */    dc390_dumpinfo (pACB, pDCB, pSRB);    pSRB = pDCB->pGoingSRB;    pDCB->DCBFlag |= ABORT_DEV_;    /* Now for the hard part: The command is currently processed */    for( count = pDCB->GoingSRBCnt, i=0; i<count; i++)    {	if( pSRB->pcmd != cmd )	    pSRB = pSRB->pNextSRB;	else	{	    if( (pACB->pActiveDCB == pDCB) && (pDCB->pActiveSRB == pSRB) )	    {		status = SCSI_ABORT_BUSY;		printk ("DC390: Abort current command (pid %li, SRB %p)\n",			cmd->pid, pSRB);		goto  ABO_X;	    }	    else	    {		status = SCSI_ABORT_SNOOZE;		goto  ABO_X;	    }	}    }NOT_RUN:    status = SCSI_ABORT_NOT_RUNNING;ABO_X:    cmd->result = DID_ABORT << 16;    printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);#if 0    if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */	{		/* Let's do something to help the bus getting clean again */		DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);		DC390_write8 (ScsiCmd, DMA_COMMAND);		//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);		//DC390_write8 (ScsiCmd, RESET_ATN_CMD);		DC390_write8 (ScsiCmd, NOP_CMD);		//udelay (10000);		//DC390_read8 (INT_Status);		//DC390_write8 (ScsiCmd, EN_SEL_RESEL);	};    sbac = DC390_read32 (DMA_ScsiBusCtrl);    if (sbac & SCSI_BUSY)    {	/* clear BSY, SEL and ATN */	printk (KERN_WARNING "DC390: Reset SCSI device: ");	//DC390_write32 (DMA_ScsiBusCtrl, (sbac | SCAM) & ~SCSI_LINES);	//udelay (250);	//sbac = DC390_read32 (DMA_ScsiBusCtrl);	//printk ("%08lx ", sbac);	//DC390_write32 (DMA_ScsiBusCtrl, sbac & ~(SCSI_LINES | SCAM));	//udelay (100);	//sbac = DC390_read32 (DMA_ScsiBusCtrl);	//printk ("%08lx ", sbac);	DC390_write8 (ScsiCmd, RST_DEVICE_CMD);	udelay (250);	DC390_write8 (ScsiCmd, NOP_CMD);	sbac = DC390_read32 (DMA_ScsiBusCtrl);	printk ("%08lx\n", sbac);    };#endif    dc390_lastabortedpid = cmd->pid;    DC390_UNLOCK_ACB;    //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);#ifndef USE_NEW_EH	    if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);#endif	    return( status );}static void dc390_ResetDevParam( PACB pACB ){    PDCB   pDCB, pdcb;    pDCB = pACB->pLinkDCB;    if (! pDCB) return;    pdcb = pDCB;    do    {	pDCB->SyncMode &= ~SYNC_NEGO_DONE;	pDCB->SyncPeriod = 0;	pDCB->SyncOffset = 0;	pDCB->TagMask = 0;	pDCB->CtrlR3 = FAST_CLK;	pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;

⌨️ 快捷键说明

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