📄 tmscsim.c
字号:
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 + -