📄 scsi_kzq.c
字号:
/*#ifndef lintstatic char *sccsid = "@(#)scsi_kzq.c 4.2 (ULTRIX) 4/30/91";#endif lint/*/************************************************************************ * * * Copyright (c) 1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * scsi_kzq.c 09/07/90 * * PVAX/FIREFOX/PMAX SCSI KZQSA device driver (SII/Qbus routines) * * Modification history: * * 4/24/91 Brian Nadeau / Richard Napolitano * Add get_validbuf_kzq() and change all references to * get_validbuf() to use the new routine. * Also - merge 10 byte cdb support and rrd42 work-around. * * 09/07/90 Charles M. Richmond (IIS Corp) * Modified existing scsi_sii.c file for the KZQSA board. These * changes encompass the lack of padding in the kzqsa/sii regs * and the differences in qbus/ibus implementations. EG the * different calls for probe. For previous history see the * scsi_sii.c file. * ***********************************************************************/#include "../data/scsi_data.c"/* * Define ELDEBUG to create error for uerf debuging. * NOTE: must not be defined at submit time (performance hit). *//*#define ELDEBUG */#include "scsi_debug.h"int kzqdebug = 0;int kzqtarget = 0;int sii_rse_flag;#ifdef vaxextern char cvqmsi[] [512*NBPG];extern char cvqmsirb[];#endif vaxextern char szbufmap[];extern short sz_timetable[];extern int cpu;int kzq_wait_after_inquiry = 1000;/* For quick hacks at debugging. */#undef DEBUGint kzq_busy_target(); /* for forware reference */int bzero(), bcopy();/****************************************************************** * * Probe routine for KZQ. * ******************************************************************/short kzq_reject_message = 0;short kzq_assert_attn = 0; /* Assert Attention Flag *//* * Number of seconds to wait for SCSI devices * to come ready enough to respond to inquiry * after bus reset. Needs to be a variable so * users can change it (I am such a nice guy). * Factory default is 7 seconds (in scsi_data.c). * Note on note... I think that the above is Fred... cmr */extern int sz_wait_for_devices;extern int sz_max_wait_for_devices;extern int kzq_scsistart();extern int kzq_reset();extern struct scsi_devtab szp_rz_udt;extern struct scsi_devtab szp_tz_udt;extern struct scsi_devtab szp_cz_udt;extern int szp_nrz;extern int szp_ntz;extern int szp_ncz;extern int szp_nrx;extern int rz_max_xfer;extern int cz_max_xfer;extern int tz_max_xfer;extern int rzcomplete();extern int tzcomplete();extern int sz_cdb_length();/********************************************************************** * * Name: kzq_probe * * Abstract: The KZQ probe entry point routine from auto-configure * code. Determine if the KZQ controller exists. Reset the * SCSI bus. Size the number and type of targets on the * SCSI bus. Set up the "sz_softc" structure and the 128K * hardware buffer. * * Inputs: * reg SCSI bus controller CSR address. * cntlr SCSI bus controller number. * * Outputs: * sz_softc * * sc_sysid SCSI bus ID of initiator (CPU). * *port_start() SCSI command start routine - kzq_scsistart(). * *port_reset() SCSI bus reset - kzq_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 kzq_sent_cmd = 0; /* SCSI Command Sent flag */short kzq_wait_count = KZQ_WAIT_COUNT; /* Delay count for SII chip */short kzq_use_programmed_io = 0; /* Programmed IO Mode flag */short kzq_firstcall = 1; /* First call to probe flag */short kzq_debug_probe = 0; /* Used for debugging probe */short kzq_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. */kzq_probe(reg, cntlr)caddr_t reg;int cntlr;{ KZQ_REG *kzqaddr = (struct kzq_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, found; struct sz_inq_dt *idp; struct sz_rdcap_dt *rdp; struct scsi_devtab *sdp; struct scsi_devtab *usdp; struct uba_ctlr *kzq_um; int sdp_match; char *p; int alive; int cnt; int retries, status; int save_kzqdebug; int save_kzqtarget; int kzq_intr(); extern int stray();#ifdef SZDEBUG /* Check if debug probe flag is set */ if(kzq_debug_probe) { save_kzqdebug = kzqdebug; save_kzqtarget = kzqtarget; kzqdebug = 0x1f; kzqtarget = -1; } PRINTD(-1, 0x8, ("kzq_probe: start probing the SCSI bus\n"));#endif SZDEBUG /* * Probe must fail if controller not configured. */ alive = 1; if(cntlr >= nNKZQ) alive = 0; /* * Initialize certain fields in the softc structure * and reset the SII chip. */ if(alive) { kzq_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 = kzq_scsistart; /* init the port_start switch */ sc->port_reset = kzq_reset; /* init the port_reset switch */ sc->rmbcopy = bcopy; sc->wmbcopy = bcopy; sc->wmbzero = bzero; /* The following reads the jumpers for the rambuffer 128k addr */ /* shifts the bits into place and converts to Qbus virtual by */ /* adding in 'qmem' */ sc->sc_rambuff =(char *)(((kzqaddr->kzq_vector & 0xf800)<<6) +(int)qmem); sc->sc_scsiaddr = (caddr_t)reg; /* init the sii addres */ kzq_reset(sc); /* reset the SII chip */ sc->sii_was_reset = 0; /* The following indexes through the ubminit array of */ /* structs until it reaches the kzq controller or until it */ /* runs out of valid struct addresses */ found=0; kzq_um = ubminit; while((found == 0) && ((kzq_um++)->um_driver)) { if (strcmp(kzq_um->um_ctlrname,"kzq")==0) { found=1; /* The following for loop finds the first vacant vector and */ /* loads it with the kzqsa interupt address */ for(cnt=QVEC_BCNT;cnt>=0;cnt--) { if(uba_hd[kzq_um->um_ubanum].uh_vec[cnt]== stray) /*first free*/ { uba_hd[kzq_um->um_ubanum].uh_vec[cnt] = kzq_intr; /*address*/ kzqaddr->kzq_vector = cnt<<2; cvec= cnt<<2; break; } } } } } /* * 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 = kzq_scsistart(sc, targid, 0); PRINTD(targid, 0x2, ("kzq_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, ("", kzq_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("kzq_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("kzq_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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -