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

📄 scsi_sii.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
 *  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 sii_sent_cmd = 0;			/* SCSI Command Sent flag    */short sii_wait_count = SII_WAIT_COUNT;	/* Delay count for SII chip */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 *//* * The configuration code on the vax side needs to be modified * to pass a pointer to uba_ctlr instead on the cntlr number. */sii_probe(reg, um)caddr_t reg;register struct uba_ctlr *um;{	int cntlr = um->um_ctlr;	SII_REG *siiaddr = (struct sii_regs *) reg;	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) {	    sii_stray_intr[cntlr] = 1;	    sc = &sz_softc[cntlr];	    sc->sc_siinum = cntlr;	    sc->scsi_polled_mode = 1;	    sc->scsi_bus_idle = 0;	    sc->sc_sysid =		    get_scsiid(cntlr);      /* init the host adapter ID */	    sc->sc_active = 0;		    /* init the active flag */	    sc->port_start = sii_scsistart; /* init the port_start switch */	    sc->port_reset = sii_reset;	    /* init the port_reset switch */	    /*	     * Determine the rambuffer copy and zero routines.  The PMAX             * utilizes a 16bit rambuffer where there are 16bit holes.	     * The Firefox and Mipsmate utilize 32bit rambuffers where	     * there are no such holes.	     */	    /* 	     * Need to init these here, to support 2nd sii controller	     */	    sc->sc_rambuff = SII_BUF_ADDR;  /* init the RAM buffer pointer*/ 	    sc->sc_scsiaddr = (caddr_t)reg; /* init the sii addres */	    if (cpu == DS_3100) {		    sc->rmbcopy = rmbcopy;	            sc->wmbcopy = wmbcopy;                    sc->wmbzero = wmbzero;	    }	    else if (cpu == DS_5100) {		    sc->rmbcopy = kn230_rbcopy;		    sc->wmbcopy = kn230_wbcopy;	 	    sc->wmbzero = kn230_bzero;		    /* 		     * If 2nd kn230 controller, set-up accordingly:		     *		     *   - 16bit pmax bcopy		     *   - different start address		     *   - different ram buffer address		     */#define KN230_OPT_REG (volatile struct sii_regs *)PHYS_TO_K1(0x15000000) #define KN230_OPT_BUF (volatile char *)PHYS_TO_K1(0x15200000)		    if( cntlr == 1 ){ 			    sc->rmbcopy = rmbcopy;			    sc->wmbcopy = wmbcopy;			    sc->wmbzero = wmbzero;			    			    siiaddr = KN230_OPT_REG;			    sc->sc_scsiaddr = (caddr_t)KN230_OPT_REG;			    sc->sc_rambuff = KN230_OPT_BUF; 		    }	    }	    else {	            sc->rmbcopy = bcopy;		    sc->wmbcopy = bcopy;	 	    sc->wmbzero = bzero;	    }	    sii_reset(sc); 		    /* reset the SII chip */	    sc->sii_was_reset = 0;	}	/*	 * 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_attached[targid] = 0;	    sc->sc_rzspecial[targid] = 0;	    sc->sc_rmv_media &= ~(1 << targid);	    if(targid == sc->sc_sysid)		continue;	/* skip initiator */	    retries = 5;	    status = 1;	    i = sz_wait_for_devices;	    while (retries)	    {		/* Clear where the inquiry data will be going.  This is like		   putting the cart before the horse, the offsets have not 		   been setup yet.  However, scsistart() calls recvdata() and		   recvdata() uses the values in siidboff[] in transfering the		   data.  This causes all transfers to occur in the first 		   ram buffer "page".  And valid inquiry data from the previous		   targit is still there.  This can cause some interesting		   device types. */		sc->sc_szflags[targid] = SZ_NORMAL; 		sc->sc_curcmd[targid] = SZ_INQ;		(sc->wmbzero)((char *)(sc->sc_rambuff + sc->sc_siidboff[targid]),			256);	/* magic # !! check with siidboff alloc */		sc->sc_siisentsync[targid] = 1;		sz_bldpkt(sc, targid, SZ_INQ, 0, 0);		stat = sii_scsistart(sc, targid, 0);		PRINTD(targid, 0x2,		       ("sii_probe: targid %d stat from scsistart=%x\n",			targid, stat));		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) {			status = 0;			break;		}		else if(stat == SZ_RET_ABORT) {			status = 1;			break;		}		DELAY(1000);		retries--;		continue;	    }	    if (status != 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 removable 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",		       um->um_ctlr, 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",			um->um_ctlr, 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.	 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -