📄 u14-34f.c
字号:
dkinfo[1] = 63; dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); }#if defined (DEBUG_GEOMETRY) printk ("%s: biosparam, head=%d, sec=%d, cyl=%d.\n", driver_name, dkinfo[0], dkinfo[1], dkinfo[2]);#endif return FALSE;}static void sort(unsigned long sk[], unsigned int da[], unsigned int n, unsigned int rev) { unsigned int i, j, k, y; unsigned long x; for (i = 0; i < n - 1; i++) { k = i; for (j = k + 1; j < n; j++) if (rev) { if (sk[j] > sk[k]) k = j; } else { if (sk[j] < sk[k]) k = j; } if (k != i) { x = sk[k]; sk[k] = sk[i]; sk[i] = x; y = da[k]; da[k] = da[i]; da[i] = y; } } return; }static inline int reorder(unsigned int j, unsigned long cursec, unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { Scsi_Cmnd *SCpnt; struct mscp *cpp; unsigned int k, n; unsigned int rev = FALSE, s = TRUE, r = TRUE; unsigned int input_only = TRUE, overlap = FALSE; unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; unsigned long maxsec = 0, minsec = ULONG_MAX, seek = 0, iseek = 0; unsigned long ioseek = 0; static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; static unsigned int readysorted = 0, revcount = 0; static unsigned long seeksorted = 0, seeknosort = 0; if (link_statistics && !(++flushcount % link_statistics)) printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ " av %ldK as %ldK.\n", flushcount, batchcount, inputcount, ovlcount, readycount, readysorted, sortcount, revcount, seeknosort / (readycount + 1), seeksorted / (readycount + 1)); if (n_ready <= 1) return FALSE; for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; if (!(cpp->xdir == DTD_IN)) input_only = FALSE; if (SCpnt->request.sector < minsec) minsec = SCpnt->request.sector; if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector; sl[n] = SCpnt->request.sector; ioseek += SCpnt->request.nr_sectors; if (!n) continue; if (sl[n] < sl[n - 1]) s = FALSE; if (sl[n] > sl[n - 1]) r = FALSE; if (link_statistics) { if (sl[n] > sl[n - 1]) seek += sl[n] - sl[n - 1]; else seek += sl[n - 1] - sl[n]; } } if (link_statistics) { if (cursec > sl[0]) seek += cursec - sl[0]; else seek += sl[0] - cursec; } if (cursec > ((maxsec + minsec) / 2)) rev = TRUE; if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE; if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); if (!input_only) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid; if (!n) continue; if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE; } if (overlap) sort(pl, il, n_ready, FALSE); if (link_statistics) { if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; batchcount++; readycount += n_ready, seeknosort += seek / 1024; if (input_only) inputcount++; if (overlap) { ovlcount++; seeksorted += iseek / 1024; } else seeksorted += (iseek + maxsec - minsec) / 1024; if (rev && !r) { revcount++; readysorted += n_ready; } if (!rev && !s) { sortcount++; readysorted += n_ready; } }#if defined(DEBUG_LINKED_COMMANDS) if (link_statistics && (overlap || !(flushcount % link_statistics))) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\ " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, SCpnt->request.sector, SCpnt->request.nr_sectors, cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(overlap), cpp->xdir); }#endif return overlap;}static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, unsigned int ihdlr) { Scsi_Cmnd *SCpnt; struct mscp *cpp; unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES]; for (k = 0; k < sh[j]->can_queue; k++) { if (HD(j)->cp_stat[k] != READY && HD(j)->cp_stat[k] != IN_USE) continue; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; if (SCpnt->device != dev) continue; if (HD(j)->cp_stat[k] == IN_USE) return; il[n_ready++] = k; } if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1; for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\ " busy, will abort.\n", BN(j), (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k); HD(j)->cp_stat[k] = ABORTING; continue; } outl(V2DEV(cpp), sh[j]->io_port + REG_OGM); outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR); HD(j)->cp_stat[k] = IN_USE; }}static inline void ihdlr(int irq, unsigned int j) { Scsi_Cmnd *SCpnt; unsigned int i, k, c, status, tstatus, reg, ret; struct mscp *spp, *cpp; if (sh[j]->irq != irq) panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j), irq, sh[j]->irq); /* Check if this board need to be serviced */ if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)) & IRQ_ASSERTED)) return; HD(j)->iocount++; if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j), irq, HD(j)->iocount); /* Check if this board is still busy */ if (wait_on_busy(sh[j]->io_port, 20 * MAXLOOP)) { outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR); printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", BN(j), irq, reg, HD(j)->iocount); return; } spp = (struct mscp *)DEV2V(ret = inl(sh[j]->io_port + REG_ICM)); cpp = spp; /* Clear interrupt pending flag */ outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);#if defined(DEBUG_GENERATE_ABORTS) if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 500) < 3)) return;#endif /* Find the mailbox to be serviced on this board */ i = cpp - HD(j)->cp; if (cpp < HD(j)->cp || cpp >= HD(j)->cp + sh[j]->can_queue || i >= sh[j]->can_queue) panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j), (void *)ret, HD(j)->cp); if (HD(j)->cp_stat[i] == IGNORE) { HD(j)->cp_stat[i] = FREE; return; } else if (HD(j)->cp_stat[i] == LOCKED) { HD(j)->cp_stat[i] = FREE; printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j), i, HD(j)->iocount); return; } else if (HD(j)->cp_stat[i] == FREE) { printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j), i, HD(j)->iocount); return; } else if (HD(j)->cp_stat[i] == IN_RESET) printk("%s: ihdlr, mbox %d is in reset.\n", BN(j), i); else if (HD(j)->cp_stat[i] != IN_USE) panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", BN(j), i, HD(j)->cp_stat[i]); HD(j)->cp_stat[i] = FREE; SCpnt = cpp->SCpnt; if (SCpnt == NULL) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j), i); if (SCpnt->host_scribble == NULL) panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, SCpnt->pid, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble); if (linked_comm && SCpnt->device->queue_depth > 2 && TLDEV(SCpnt->device->type)) flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE); tstatus = status_byte(spp->target_status);#if defined(DEBUG_GENERATE_ERRORS) if ((HD(j)->iocount > 500) && ((HD(j)->iocount % 200) < 2)) spp->adapter_status = 0x01;#endif switch (spp->adapter_status) { case ASOK: /* status OK */ /* Forces a reset if a disk drive keeps returning BUSY */ if (tstatus == BUSY && SCpnt->device->type != TYPE_TAPE) status = DID_ERROR << 16; /* If there was a bus reset, redo operation on each target */ else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK && HD(j)->target_redo[SCpnt->target][SCpnt->channel]) status = DID_BUS_BUSY << 16; /* Works around a flaw in scsi.c */ else if (tstatus == CHECK_CONDITION && SCpnt->device->type == TYPE_DISK && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR) status = DID_BUS_BUSY << 16; else status = DID_OK << 16; if (tstatus == GOOD) HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; if (spp->target_status && SCpnt->device->type == TYPE_DISK) printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ "target_status 0x%x, sense key 0x%x.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, spp->target_status, SCpnt->sense_buffer[2]); HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0; if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; break; case ASST: /* Selection Time Out */ if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1) status = DID_ERROR << 16; else { status = DID_TIME_OUT << 16; HD(j)->target_to[SCpnt->target][SCpnt->channel]++; } break; /* Perform a limited number of internal retries */ case 0x93: /* Unexpected bus free */ case 0x94: /* Target bus phase sequence failure */ case 0x96: /* Illegal SCSI command */ case 0xa3: /* SCSI bus reset error */ for (c = 0; c <= sh[j]->max_channel; c++) for (k = 0; k < sh[j]->max_id; k++) HD(j)->target_redo[k][c] = TRUE; case 0x92: /* Data over/under-run */ if (SCpnt->device->type != TYPE_TAPE && HD(j)->retries < MAX_INTERNAL_RETRIES) {#if defined(DID_SOFT_ERROR) status = DID_SOFT_ERROR << 16;#else status = DID_BUS_BUSY << 16;#endif HD(j)->retries++; HD(j)->last_retried_pid = SCpnt->pid; } else status = DID_ERROR << 16; break; case 0x01: /* Invalid command */ case 0x02: /* Invalid parameters */ case 0x03: /* Invalid data list */ case 0x84: /* SCSI bus abort error */ case 0x9b: /* Auto request sense error */ case 0x9f: /* Unexpected command complete message error */ case 0xff: /* Invalid parameter in the S/G list */ default: status = DID_ERROR << 16; break; } SCpnt->result = status | spp->target_status;#if defined(DEBUG_INTERRUPT) if (SCpnt->result || do_trace)#else if ((spp->adapter_status != ASOK && HD(j)->iocount > 1000) || (spp->adapter_status != ASOK && spp->adapter_status != ASST && HD(j)->iocount <= 1000) || do_trace || msg_byte(spp->target_status))#endif printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", BN(j), i, spp->adapter_status, spp->target_status, SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, reg, HD(j)->iocount); /* Set the command state to inactive */ SCpnt->host_scribble = NULL; SCpnt->scsi_done(SCpnt); if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j), irq, HD(j)->iocount); return;}static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) { unsigned int j; IRQ_FLAGS SPIN_FLAGS /* Check if the interrupt must be processed by this handler */ if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return; SPIN_LOCK_SAVE IRQ_LOCK_SAVE ihdlr(irq, j); IRQ_UNLOCK_RESTORE SPIN_UNLOCK_RESTORE}int
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -