📄 scsi_5380.c
字号:
sz_scsistart(sc, targid, 0); DELAY(sz_wait_after_inquiry); /* * If the bus is wedged (BSY or SEL stuck) * reset the bus. This is painfull but should allow * remaining targets to be seen and prevent system * hang cause by a wedged SCSI bus. */ wedged = 0; if ((szaddr->scs_curstat & SCS_BSY) && (szaddr->scs_curstat & SCS_BSY) && (szaddr->scs_curstat & SCS_BSY)) wedged++; if ((szaddr->scs_curstat & SCS_SEL) && (szaddr->scs_curstat & SCS_SEL) && (szaddr->scs_curstat & SCS_SEL)) wedged++; if (wedged) { printf("szprobe: (bus=%d ID=%d) %s\n",cntlr, targid, "BSY or SEL stuck after start unit"); sz_dumpregs(cntlr, 0); /* printf */ szaddr->scs_inicmd = SCS_INI_RST; DELAY(sz_reset_width); /* hold bus reset 50 Usec */ szaddr->scs_inicmd = 0; i = szaddr->scs_reset; DELAY(sz_wait_for_devices * 1000000); szaddr->scs_mode = SCS_PARCK; } } if (sdp->flags & SCSI_TESTUNITREADY) { sc->sc_curcmd[targid] = SZ_TUR; sz_bldpkt(sc, targid, SZ_TUR, 0, 1); sz_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_READCAPACITY) { sc->sc_curcmd[targid] = SZ_RDCAP; sz_bldpkt(sc, targid, SZ_RDCAP, 0, 1); sz_scsistart(sc, targid, 0); } if (sdp->probedelay > 0) DELAY(sdp->probedelay); if (sdp->flags & SCSI_NODIAG) sz_unit_rcvdiag[targid] = 1; break; } /* end of switch */ /* * Just to be sure the bus is free after inquiry. * RRD40 may hold bus for a while. */ DELAY(sz_wait_after_inquiry); } /* end of for loop */ /* * Clean out any left over interrupts. * NCR 5380 queues interrupts, so reset it * twice just to be safe. * Then re-enable interrupts. */ if (alive) { i = szaddr->scs_reset; i = szaddr->scs_reset; sziaddr->nb_int_reqclr = (SCS_IC_BIT >> cntlr); sziaddr->nb_int_msk |= (SCS_IC_BIT >> cntlr); } /* * NOTE: fixed allocation of the 128KB buffer is used for * this first release of the SCSI driver. A resource * map to manage the 128KB buffer is needed. * * If last (really 2nd) call to szprobe, * or only one controller configured, * assign 128K data buffer slots. * * 128K data buffer allocation strategy (512 byte chunks): * 19 - ST506 controller * 32 - each tape unit * 16 - each cdrom unit * 18 - each scsi floppy unit * ?? - each hard disk unit * 1 - guard page * The guard page protects against accessing off the end of the * buffer due to the 5380 prefetching 1 extra byte on DMA writes. * ?? is what's left after tapes and cdroms divided by # of hard disks. * Any left over pages (fragment) allocated to the first disk. * ?? must be >= 8KB, should be >= 16KB, if not reduce * number of cdroms to 2, then number of tapes to 2. * If the 128KB buffer slot size for disks is still less * than 8KB, warn the user and try to continue. The * system may not function and will surely be slow. * In any "real" VS3100 configuration, we should * never hit these limits. */ if ((nNSCSI == 1) || (szp_firstcall == 0)) { if ((vs_cfgtst & VS_SC_TYPE) == VS_SCSI_SCSI) dboff = 0x0; else dboff = (19 * 512); /* determine rz slot size, must be > 16kb */ while (1) { rz_slotsize = 256 - 1; /* guard page */ rz_slotsize -= (dboff / 512); rz_slotsize -= (szp_ntz * 32); rz_slotsize -= (szp_ncz * 16); rz_slotsize -= (szp_nrx * 18); if ((rz_slotsize > 0) && (szp_nrz - szp_nrx)) { rz_fragsize = rz_slotsize % (szp_nrz - szp_nrx); rz_slotsize = rz_slotsize / (szp_nrz - szp_nrx); } if (rz_slotsize < 32) { if (szp_ncz > 2) { printf("Only 2 CDROM (too many other devices)\n"); szp_ncz = 2; continue; } } if (rz_slotsize < 32) { if (szp_ntz > 2) { printf("Only 2 tz (too many other devices)\n"); szp_ntz = 2; continue; } } if (rz_slotsize < 32) { if (rz_slotsize >= 16) printf("Poor disk performance (too many devices)\n"); else printf("System may not function (too many devices)\n"); } break; } if (rz_slotsize > 128) { rz_slotsize = 128; rz_fragsize = 0; } if ((rz_slotsize + rz_fragsize) > 128) rz_fragsize = 0; rz_slotsize *= 512; tz_slotsize = (32 * 512); cz_slotsize = (16 * 512); rx_slotsize = (18 * 512); ncz = ntz = 0; rz_fragused = 0; /* NOTE: must use ctlr NOT cntlr! */ for (ctlr=0; ctlr<nNSCSI; ctlr++) { sc = &sz_softc[ctlr]; for (targid=0; targid<NDPS; targid++) { if ((1 << targid) == sc->sc_sysid) continue; if (sc->sc_alive[targid] == 0) continue; if (sc->sc_devtyp[targid] & SZ_CDROM) { if (++ncz > szp_ncz) { sc->sc_alive[targid] = 0; continue; } sc->sc_dboff[targid] = dboff; sc->sc_segcnt[targid] = cz_slotsize; dboff += cz_slotsize; } else if (sc->sc_devtyp[targid] & SZ_TAPE) { if (++ntz > szp_ntz) { sc->sc_alive[targid] = 0; continue; } sc->sc_dboff[targid] = dboff; sc->sc_segcnt[targid] = tz_slotsize; dboff += tz_slotsize; } else if (sc->sc_devtyp[targid] & SZ_DISK) { if ((sc->sc_devtyp[targid] == RX23) || (sc->sc_devtyp[targid] == RX33)) { sc->sc_dboff[targid] = dboff; sc->sc_segcnt[targid] = rx_slotsize; dboff += rx_slotsize; } else if (rz_fragused || (rz_fragsize == 0)) { sc->sc_dboff[targid] = dboff; sc->sc_segcnt[targid] = rz_slotsize; dboff += rz_slotsize; } else { sc->sc_dboff[targid] = dboff; sc->sc_segcnt[targid] = rz_slotsize; sc->sc_segcnt[targid] += (rz_fragsize * 512); dboff += (rz_slotsize + (rz_fragsize * 512)); rz_fragused++; } } else continue; } } } /* * Start timer on 2nd (last) call to szprobe. */ if (szp_firstcall) { szp_firstcall = 0; } else { /* * Zero the diagnostice timer register. * It is used by some optional driver stats code. */ sziaddr->nb_diagtime = 0; /* * Start background timer (0.2 sec) to detect * hung bus when driver is not active. */ timeout(sz_timer1, 0, 20); } if (alive) { sc = (struct sz_softc *)&sz_softc[cntlr]; sc->sc_cntlr_alive = 1; } return(alive);}int sz_do_timer1 = 1; /* if 0, don't run driver idle bus hung timer */int sz_t1_dorst = 1; /* if 0, don't reset bus in timer1 *//* * * Name: sz_timer2 -timeout disconnected disks * * Abstract: A 10/30 second timeout starts when a hard/floppy * disk disconnects from the bus. This routine is * called if the disconnected disk has not done a * reselect after 10/30 seconds. This routine sets an * error condition on the disk and calls sz_start. * NOTE: floppy timeout is 30 seconds because retires * can take a long time. * NOTE: we cannot access the 5380's registers * the bus is active, so we backoff .1 sec. * NOTE: just return if bus reset in progress. * * Inputs: * * unit The ULTRIX logical unit number of the disk. This * will be 0 -7 for bus A or 8 - 15 for bus B. * * Outputs: None. * * Return Values: None. * * Side Effects: * IPL raised to 15. * Another timeout queued if the bus is busy. * Disk's context in sz_softc is modified. * sz_start() called. * */sz_timer2(unit)int unit;{ register struct sz_softc *sc; register int cntlr, targid; register int s; int flags; s = spl5(); cntlr = (unit >> 3) & 1; sc = &sz_softc[cntlr]; targid = unit & 7; if (sc->sc_rip) { /* Bus reset in progress, ignore timers */ splx(s); return; } if (sc->sc_active) { /* TODO: may want variable backoff delay */ timeout(sz_timer2, (caddr_t)unit, 10); /* .1 sec */ splx(s); return; } /* This does not happen unless something really went wrong */ flags = SZ_HARDERR | SZ_LOGCMD | SZ_LOGSELST; scsi_logerr(sc, 0, targid, SZ_ET_DISTIMO, 0, 0, flags); sc->sc_szflags[targid] &= ~SZ_TIMERON; /* Do not think this can happen */ if (sc->sc_selstat[targid] != SZ_DISCONN) {#ifdef notdef mprintf("sz_timer2: (bus=%d ID=%d) target not disconnected\n", cntlr, targid);#endif notdef splx(s); return; } sc->sc_selstat[targid] = SZ_IDLE; sc->sc_szflags[targid] &= ~SZ_DID_DMA; sc->sc_active = 0; sc->sc_fstate = 0; sc->sc_szflags[targid] |= SZ_NEED_SENSE; /* force retry even if RQSNS data says NOSENSE */ sc->sc_szflags[targid] |= SZ_RSTIMEOUT; if (sc->sc_dkn[targid] >= 0) dk_busy &= ~(1 << sc->sc_dkn[targid]); sz_start(sc, targid); splx(s);}/* * * Name: sz_timer4 -timeout busy target * * Abstract: If a target cannot accept a command it returns * a BUSY status. In this case a timer is started. * This routine is called when the timer expires. * This routine calls sz_start() to send the command * again. Timeout length is 0.5 seconds. * NOTE: we cannot access the 5380's registers * the bus is active, so we backoff .1 sec. * NOTE: just return if bus reset in progress. * * Inputs: * * unit The ULTRIX logical unit number of the disk. This * will be 0 -7 for bus A or 8 - 15 for bus B. * * Outputs: None. * * Return Values: None. * * Side Effects: * IPL raised to 15. * Another timeout queued if the bus is busy. * sz_start() called. * */sz_timer4(unit)int unit;{ register struct sz_softc *sc; register int cntlr, targid; register int s; s = spl5(); cntlr = (unit >> 3) & 1; sc = &sz_softc[cntlr]; targid = unit & 7; if (sc->sc_rip) { /* Bus reset in progress, ignore timers */ splx(s); return; } if (sc->sc_active) { /* TODO: may want variable backoff delay */ timeout(sz_timer4, (caddr_t)unit, 10); /* .1 sec */ splx(s); return; } /* Do not think this can happen */ if ((sc->sc_szflags[targid] & SZ_BUSYTARG) == 0) {#ifdef notdef mprintf("sz_timer4: (bus=%d ID=%d) target not busy\n", cntlr, targid);#endif notdef splx(s); return; } sc->sc_szflags[targid] &= ~SZ_BUSYTARG; sz_start(sc, targid); splx(s);}/* * * Name: sz_timer3 -selection timeout timer * * Abstract: This routine is part of the 250 MS selection * timeout procedure. The first 20 MS is a spin * loop in sz_scsistart(). If the target does not * respond to the selection after 20 MS, then a * 30 MS timer is started. After 30 MS sz_timer3 * is called, which starts a 50 MS timer 4 times. * On each call sz_timer3 checks for BSY asserted. * If BSY false and time less than 250 MS, then * queue another 50 MS timeout. If BSY true or * time greater than 250 MS, then call sz_start. * NOTE: code assumes a bus reset cannot happen * while we are timing out a select. * * Inputs: * * unit The ULTRIX logical unit number the target. * Will be 0 - 7 for bus A or 8 - 15 for bus B. * * Outputs: None. * * Return Values: None. * * Side Effects: * IPL raised to 15. * sz_start() called. * Another timer may be queued. * */sz_timer3(unit)int unit;{ register struct sz_regs *szaddr; register struct sz_softc *sc; register int cntlr, targid; register int s; s = spl5(); cntlr = (unit >> 3) & 1; sc = &sz_softc[cntlr]; targid = unit & 7; szaddr = (struct sz_regs *)szmem + cntlr; /* Do not think this can ever happen */ if (sc->sc_active == 0) { splx(s); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -