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

📄 scsi_sii.c

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