📄 scsi_5380.c
字号:
extern int szp_nrz; /* number of RZ disks found */extern int szp_ntz; /* number of TZ tapes found */extern int szp_ncz; /* number of CDROM optical disks found */extern int szp_nrx; /* number of RZ23 SCSI floppy disks found */extern struct scsi_devtab szp_rz_udt;extern struct scsi_devtab szp_tz_udt;extern struct scsi_devtab szp_cz_udt;/* * Length of SCSI bus reset in Microseconds. * Set in data/scsi_data.c so customers can * change it. * Factory default is 50 Usec. */extern int sz_reset_width;/* * Each array element represents a SCSI bus. * Set bit 0 to ignore target ID 0, etc. * Ment for debugging only, but..... * Allow for up to 8 SCSI busses (current max is 2). * Not in scsi_data.c so novice uses won't play with it! */#define SZ_MAX_SCSI 8int sz_ignore_target[SZ_MAX_SCSI] = {0, 0, 0, 0, 0, 0, 0, 0};/* * * Name: szprobe -Probe routine * * Abstract: Probe entry point from auto-configure code. * Determine if controller exists. Reset SCSI bus. * Size number and type of targets on SCSI bus. * Set up sz_softc and 128KB hardware buffer. * * Inputs: * * reg SCSI bus controller CSR address (not used). * cntlr SCSI bus controller number (0 = bus A, 1 = bus B). * * Outputs: * * sz_softc * * sc_sysid SCSI bus ID of initiator (CPU). * sc_cntlr_alive Controller alive or not. * *port_start() SCSI command start routine - sz_scsistart(). * *port_reset() SCSI bus reset - sz_reset() [set but not used]. * *device_comp() SCSI device completion routine * *sc_rambuff Virtual address of 128KB hardware RAM buffer. * sc_segcnt[] Per target - 128 KB buffer slot size (max byte cnt). * sc_dstp[] Per target - disk default partition table pointer. * sc_devtyp[] Per target - device type (see scsireg.h). * sc_alive[] Per target - device present at this SCSI bus ID. * sc_device[][] Per target - product ID, vendor ID, rev in ascii. * sc_SZ_bufmap[] Per target - virtual address for buffer mapping. * sc_szbufmap[] Per target - PTEs from get_sys_ptes(). * sc_dboff[] Per target - offset into 128 KB buffer. * sc_devnam[][] Per target - vendor & product ID in ascii. * sc_revlvl[][] Per target - revision level in ascii. * * Return values: * * 0 Controller does not exist or did not respond. * * 1 Controller exists and is alive. * * Side Effects: * * The NCR 5380 chip, the DMA controller, and the * SCSI bus are reset. Much of sz_softc is set up. * Port start and reset routine pointers set up. * Address of 128 KB RAM buffer set up. * Clears diagnostic timer register (nb_diagtime). * Starts hung bus detection timer (sz_timer1). * */szprobe(reg, cntlr) caddr_t reg; /* NOT USED */ int cntlr;{ register struct sz_regs *szaddr = (struct sz_regs *)szmem + cntlr; register struct nb_regs *sziaddr = (struct nb_regs *)nexus; register struct sz_softc *sc; int targid, ctlr; int dboff; int rz_slotsize, tz_slotsize, cz_slotsize, rx_slotsize; int rz_fragsize, rz_fragused; int ncz, ntz; int i, s; struct sz_inq_dt *idp; struct sz_rdcap_dt *rdp; struct scsi_devtab *sdp; struct scsi_devtab *usdp; int sdp_match; char *p; int alive; int stat, wedged; int retries;#ifdef SZDEBUG printd6("szprobe: probing SCSI bus %d\n", cntlr);#endif SZDEBUG /* * Only on VS3100, * return 0 if any other system. */ if (cpu != C_VAXSTAR) return(0); /* * This driver needs the ST506/SCSI or * SCSI/SCSI controller to run. */ if (((vs_cfgtst & VS_SC_TYPE) != VS_SCSI_SCSI) && ((vs_cfgtst & VS_SC_TYPE) != VS_ST506_SCSI)) return(0); /* * Probe must fail if controller not configured. */ alive = 1; if (cntlr >= nNSCSI) alive = 0; /* * Only SCSI/SCSI controller can have 2nd SCSI bus. */ if ((cntlr != 0) && ((vs_cfgtst & VS_SC_TYPE) != VS_SCSI_SCSI)) alive = 0; /* * Assert SCSI bus reset for 50 Usec to * clear the world and generate an interrupt. */ if (alive ) { sziaddr->nb_int_reqclr = (SCS_IC_BIT >> cntlr); sziaddr->nb_int_msk |= (SCS_IC_BIT >> cntlr); szaddr->scs_inicmd = SCS_INI_RST; DELAY(sz_reset_width); /* hold bus reset for 50 Usec (min = 25) */ szaddr->scs_inicmd = 0; i = szaddr->scs_reset; sziaddr->nb_int_reqclr = (SCS_IC_BIT >> cntlr); sziaddr->nb_int_msk &= ~(SCS_IC_BIT >> cntlr); /* disable intr */ /* * SCSI devices take some time after power on or bus reset * before they are ready to speak SCSI and respond to inquiry. * The RRD40 takes longest of the DEC devices (about 6 sec). * * This delay can be changed via sz_wait_for_devices. */ DELAY(sz_wait_for_devices * 1000000); } if (alive) { sc = &sz_softc[cntlr]; sc->sc_active = 0; sc->port_start = sz_scsistart;/* initialize the port_start switch */ sc->port_reset = sz_reset; /* initialize the port_reset switch */ sc->sc_rambuff = (char *)cvseddbmem; /* initialize the RAM buffer pointer*/ /* * Read system's SCSI bus ID from NVR * and save it in sz_softc structure. * Bits 2-4 are cntlr 0 ID, bits 5-7 are cntlr 1 ID. */ i = sziaddr->nb_cpu_scsi_id >> 2; if (cntlr == 0) i &= 0x7; else i = (i >> 3) & 0x7; sc->sc_sysid = (1 << i); szaddr->scs_mode = SCS_PARCK; /* for bus reset detection */ } /* * Use the inquiry command to determine number * and type of targets on this controller. * If this controller does not exist alive will * be zero and the for loop won't do anything. */ for (targid=0; targid<NDPS; targid++) { /* CAUTION: if cntlr not alive, sz_softc pointer not set! */ if (alive == 0) break; /* * Must set sc_unit here because it is used before it * gets set in szslave(). This assumes a fixed mapping * of logical to physical unit number. */ sc->sc_unit[targid] = (8 * cntlr) + targid; sc->sc_rzspecial[targid] = 0; sc->sc_rmv_media &= ~(1 << targid); if ((1 << targid) == sc->sc_sysid) continue; /* skip initiator */ /* * Allows target(s) to be ignored without * being physically disconnected from the bus. */ if (cntlr < SZ_MAX_SCSI) { if (sz_ignore_target[cntlr] & (1 << targid)) continue; } sc->sc_curcmd[targid] = SZ_INQ; sz_bldpkt(sc, targid, SZ_INQ, 0, 0); /* * Each failed select costs about .3 seconds. * All selects fail if no target present at ID. */ retries = 3; i = sz_wait_for_devices; /* # seconds already waited */ while (retries) { /* Zero inquiry data so we don't get stale information. */ bzero ((struct sz_inq_dt *)&sc->sz_dat[targid], sizeof(struct sz_inq_dt)); stat = sz_scsistart(sc, targid, 0); if (sc->sc_szflags[targid] & SZ_BUSYTARG) { sc->sc_szflags[targid] &= ~SZ_BUSYTARG; DELAY(1000000); /* delay 1 second */ if (++i >= sz_max_wait_for_devices) break; continue; } if (stat == SZ_SUCCESS) break; retries--; } /* * 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 inquiry"); sz_dumpregs(cntlr, 0); /* printf */ szaddr->scs_inicmd = SCS_INI_RST; DELAY(sz_reset_width); /* hold bus reset 50 Usec (min = 25) */ szaddr->scs_inicmd = 0; i = szaddr->scs_reset; DELAY(sz_wait_for_devices * 1000000); szaddr->scs_mode = SCS_PARCK; } sc->sc_szflags[targid] = SZ_NORMAL; /* house keeping */ if (stat != SZ_SUCCESS) continue; /* * Initialize data structures for this target and * save all pertinent inquiry data (device type, etc.). * NOTE: 1st 10KB of 128KB data buffer allocated * to ST506 disk controller (only if present). * NOTE: remaining buffer divided between other devices. * TODO: need a resource map for the 128KB data buffer. */ idp = (struct sz_inq_dt *)&sc->sz_dat[targid]; /* Save removable media bit for each target */ if (idp->rmb) sc->sc_rmv_media |= (1 << targid); /* * Zero device name and revsion level * ASCII strings, so we know whether or * not they were loaded by the INQUIRY. */ for (i=0; i<SZ_DNSIZE; i++) sc->sc_devnam[targid][i] = (char)0; for (i=0; i<SZ_REV_LEN; i++) sc->sc_revlvl[targid][i] = (char)0; /* * Save the device name and revision level. * DEC combines vendor & product ID strings. */ p = &sc->sc_devnam[targid][0]; for (i=0; i<SZ_VID_LEN; i++) *p++ = idp->vndrid[i]; for (i=0; i<SZ_PID_LEN; i++) *p++ = idp->prodid[i]; p = &sc->sc_revlvl[targid][0]; for (i=0; i<SZ_REV_LEN; i++) *p++ = idp->revlvl[i]; switch(idp->perfdt) { default: /* Unknown device type */ printf("szprobe: scsi %d targetID %d: %s (%d).\n", cntlr, targid, "unknown peripheral device type", idp->perfdt); /* NO 128 KB data buffer slot will be assigned! */ sc->sc_alive[targid] = 0; sc->sc_devtyp[targid] = SZ_UNKNOWN; sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; bcopy(DEV_UNKNOWN, sc->sc_device[targid], strlen(DEV_UNKNOWN)); break; case 0: /* Direct-access device (disk) */ case 1: /* Sequential-access device (tape) */ case 5: /* Read-only direct-access device (CDROM) */ /* * Allocate PTEs for data buffer double mapping. * We are in BIG trouble if this fails! We print * an error message, but the system will most * likely stall, spin, crash, burn! * Get enough PTEs to map 64kb + two guard pages. */ i = get_sys_ptes(btoc(64*1024)+2, &sc->sc_szbufmap[targid]); if (i == 0) { printf("szprobe: scsi %d targetID %d: %s\n", cntlr, targid, "cannot get PTEs for bufmap"); break; } else sc->sc_SZ_bufmap[targid] = (char *)i; sc->sc_alive[targid] = 1; sc->sc_szflags[targid] = SZ_NORMAL; /* house keeping */ sc->sc_xstate[targid] = SZ_NEXT; sc->sc_xevent[targid] = SZ_BEGIN; /* * Find this device in the scsi_devtab in scsi_data.c. * The answer could come back as unknown or missing. */ usdp = (struct scsi_devtab *)0; sdp_match = 0; for (sdp=scsi_devtab; sdp->namelen; sdp++) { if ((idp->perfdt == 0) && ((sdp->devtype&SZ_DISK) == 0)) continue; if ((idp->perfdt == 1) && ((sdp->devtype&SZ_TAPE) == 0)) continue; if ((idp->perfdt == 5) && ((sdp->devtype&SZ_CDROM) == 0)) continue; /* Save address of unknown device entry, if it exists. */ if ((sdp->name) && (strcmp("UNKNOWN", sdp->name) == 0)) usdp = (struct scsi_devtab *)sdp; /* HACK: DEC tapes don't use vendor/product ID fields. */ if ((sdp->devtype & SZ_TAPE) && (idp->perfdt == 1) && (sc->sc_devnam[targid][0] == 0) && (idp->devtq == sdp->tapetype)) { sdp_match++; break; } if (sdp->name) { if (strncmp(sc->sc_devnam[targid], sdp->name, sdp->namelen) == 0) { sdp_match++; break; } } } /* * If the device name did not match call it RZxx or TZxx. * Use the UNKNOWN entry from scsi_devtab (if it exists), * otherwise use our internal UNKNOWN entry. */ if (!sdp_match) { if (usdp) sdp = usdp; else if (idp->perfdt == 0) sdp = &szp_rz_udt; else if (idp->perfdt == 1) sdp = &szp_tz_udt; else sdp = &szp_cz_udt; } /* * Update counters and set the pointer to the completion * handler. */ if (sdp->devtype & SZ_DISK){ szp_nrz++; sc->device_comp[targid] = rzcomplete; } if (sdp->devtype & SZ_TAPE){ szp_ntz++; sc->device_comp[targid] = tzcomplete; } if (sdp->devtype & SZ_CDROM){ szp_ncz++; sc->device_comp[targid] = rzcomplete; } if ((sdp->devtype == RX23) || (sdp->devtype == RX33) || (sdp->devtype == RX26)) { szp_nrx++; sc->sc_mc_cnt[targid] = 1; sc->device_comp[targid] = rzcomplete; } /* TODO: assumes length < 8 bytes */ bcopy(sdp->sysname, sc->sc_device[targid], strlen(sdp->sysname)); sc->sc_devtab[targid] = sdp; sc->sc_devtyp[targid] = sdp->devtype; sc->sc_dstp[targid] = sdp->disksize; /* * Act on the flags in device's scsi_devtab entry. * NOTE: SCSI_STARTUNIT and SCSI_NODIAG are the only flags * that should be set for the NCR 5380. However, * setting any other flags should be harmless. */ /* SCSI_TRYSYNC not supported (NCR 5380 is async only) */ if (sdp->flags & SCSI_REQSNS) { sc->sc_curcmd[targid] = SZ_RQSNS; sz_bldpkt(sc, targid, SZ_RQSNS, 0, 1); sz_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_STARTUNIT) { /* * Send two start unit commands because a pending unit * attention may cause the first one to fail. We don't * for the drive to spin up here (happens in rzopen). */ sc->sc_curcmd[targid] = SZ_P_SSUNIT; sz_bldpkt(sc, targid, SZ_P_SSUNIT, 0, 1); sz_scsistart(sc, targid, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -