⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsi_5380.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
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 + -