📄 scsi_sii.c
字号:
* Outputs: * sz_softc * * sc_sysid SCSI bus ID of initiator (CPU). * *port_start() SCSI command start routine - sii_scsistart(). * *port_reset() SCSI bus reset - sii_reset(). * *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. * sc_siisentsync[] Per target - sent synchronous message flag. * sc_siireqack[] Per target - the req/ack offset for synchronous. * sc_siidboff[] SCSI bus special RAM buffer slots. * * Return values: * 0 Controller does not exist or did not respond. * 1 Controller exists and is alive. * * Side Effects: * The SII 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. * **********************************************************************/short scsi_bus_idle = 0; /* SCSI bus is idle flag */short scsi_completed[NDPS]; /* Command Complete flag */short scsi_polled_mode = 0; /* SCSI Polled Mode flag */short sii_sent_cmd = 0; /* SCSI Command Sent flag */short sii_wait_count = SII_WAIT_COUNT; /* Delay count for SII chip */short sii_no_disconnects = 0; /* Allow No Disconnects flag */short sii_use_programmed_io = 0; /* Programmed IO Mode flag */short sii_firstcall = 1; /* First call to probe flag */short sii_debug_probe = 0; /* Used for debugging probe */short sii_test = 0; /* Used for testing purposes */sii_probe(reg, cntlr)caddr_t reg;int cntlr;{ register struct sii_regs *siiaddr = (struct sii_regs *)cvqmsi + cntlr; register struct sz_softc *sc; int targid, unit; int dboff; int rz_slotsize, tz_slotsize, cz_slotsize; int ncz, ntz; int i, s, stat; 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 retries, status; int save_siidebug; int save_siitarget;#ifdef SZDEBUG /* Check if debug probe flag is set */ if(sii_debug_probe) { save_siidebug = siidebug; save_siitarget = siitarget; siidebug = 0x1f; siitarget = -1; } PRINTD(-1, 0x8, ("sii_probe: start probing the SCSI bus\n"));#endif SZDEBUG /* * Probe must fail if controller not configured. */ alive = 1; if(cntlr >= nNSII) alive = 0; /* * Initialize certain fields in the softc structure * and reset the SII chip. */ if(alive) { scsi_polled_mode = 1; sc = &sz_softc[cntlr]; sc->sc_sysid = 7; /* init the host adapter ID */ sc->sc_active = 0; /* init the active flag */ sc->sc_rip = 0; /* init reset in progress flag */ sc->port_start = sii_scsistart; /* init the port_start switch */ sc->port_reset = sii_reset; /* init the port_reset switch */ sc->sc_rambuff = cvqmsirb; /* init the RAM buffer pointer*/ sii_reset(sc); /* reset the SII chip */ } /* * 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++) { if(alive == 0) break; sc->sc_siisentsync[targid] = 0; sc->sc_siireqack[targid] = 0; sc->sc_rzspecial[targid] = 0; sc->sc_rmv_media &= ~(1 << targid); if(targid == sc->sc_sysid) continue; /* skip initiator */ retries = 3; while(retries--) { sc->sc_szflags[targid] = SZ_NORMAL; sc->sc_curcmd[targid] = SZ_INQ; bzero((sc->sc_rambuff + sc->sc_siidboff[targid]), sizeof(sc->sz_dat[targid])); sz_bldpkt(sc, targid, SZ_INQ, 0, 0); stat = sii_scsistart(sc, targid, 0); if(stat == SZ_SUCCESS) break; } if(stat != SZ_SUCCESS) continue; /* * Initialize data structures for this target and * save all pertinent inquiry data (device type, etc.). */ idp = (struct sz_inq_dt *)&sc->sz_dat[targid]; /* Save removalbe media bit for each target */ if (idp->rmb) sc->sc_rmv_media |= (1 << targid);#ifdef SZDEBUG PRINTD(targid, 0x8, ("", sii_print_inq_info(idp)));#endif SZDEBUG /* * 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("sii_probe: 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("sii_probe: 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. */ if (sdp->flags & SCSI_TRYSYNC) sc->sc_siisentsync[targid] = 0; else sc->sc_siisentsync[targid] = 1; if (sdp->flags & SCSI_REQSNS) { sc->sc_curcmd[targid] = SZ_RQSNS; sz_bldpkt(sc, targid, SZ_RQSNS, 0, 1); sii_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); sii_scsistart(sc, targid, 0); sii_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_TESTUNITREADY) { sc->sc_curcmd[targid] = SZ_TUR; sz_bldpkt(sc, targid, SZ_TUR, 0, 1); sii_scsistart(sc, targid, 0); } if (sdp->flags & SCSI_READCAPACITY) { sc->sc_curcmd[targid] = SZ_RDCAP; sz_bldpkt(sc, targid, SZ_RDCAP, 0, 1); sii_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(sii_wait_after_inquiry); } /* end of for loop */ /* * Clean out any left over interrupts. */ if (alive) { siiaddr->sii_cstat = siiaddr->sii_cstat; siiaddr->sii_dstat = siiaddr->sii_dstat; siiaddr->sii_csr = (SII_HPM | SII_RSE | SII_SLE | SII_PCE | SII_IE); } /* * TODO: should use map to allocate 128KB buffer * * If last (really 2nd) call to sii_probe, * or only one controller configured, * assign 128K data buffer slots. * * 128K data buffer allocation strategy: * 1KB - SII controller for non READ/WRITE DMA transfers * 16KB - for each tape unit * 8KB - for each cdrom unit * ??KB - for each disk unit * ?? is what's left after tapes and cdroms divided by # of disks. * ?? must be >= 8KB, should be >= 16KB, if not reduce * number of cdroms to 2, then number of tapes to 2. * If that don't fix it panic! * In any "real" configuration, we should * never hit these limits. */ if ((nNSII == 1) || (sii_firstcall == 0)) { dboff = 0x0; /* * Setup 128 byte ram buffer slots for each target to * be used for non READ/WRITE DMA Transfers on the SII. */ for(i=0; i<NDPS; i++) { sc->sc_siidboff[i] = dboff; dboff += 128; } dboff = (1 * 1024); /* determine rz slot size, must be > 16kb */ while (1) { rz_slotsize = 128 - (dboff/1024); rz_slotsize -= (szp_ntz * 16); rz_slotsize -= (szp_ncz * 8); if ((rz_slotsize > 0) && szp_nrz) rz_slotsize = rz_slotsize / szp_nrz; if (rz_slotsize < 16) { if (szp_ncz > 2) { printf("Only 2 CDROM's (too many other devices)\n"); szp_ncz = 2; continue; } } if (rz_slotsize < 16) { if (szp_ntz > 2) { printf("Only 2 TAPE's (too many other devices)\n"); szp_ntz = 2; continue; } } if (rz_slotsize < 16) { if (rz_slotsize >= 8) printf("Poor disk performance (too many devices)\n"); else panic ("Impossible number of devices"); } break; } if (rz_slotsize > 64) rz_slotsize = 64; rz_slotsize *= 1024; tz_slotsize = (16 * 1024); cz_slotsize = (8 * 1024); ncz = ntz = 0; for (cntlr=0; cntlr<nNSII; cntlr++) { sc = &sz_softc[cntlr]; for (targid=0; targid<NDPS; targid++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -