diff options
Diffstat (limited to 'sys/scsi/scsiconf.c')
-rw-r--r-- | sys/scsi/scsiconf.c | 1110 |
1 files changed, 514 insertions, 596 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 70765b0..708cc7c 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -14,768 +14,686 @@ * * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * - * $Id: scsiconf.c,v 1.5 1993/08/28 03:08:53 rgrimes Exp $ + * $Id: scsiconf.c,v 2.6 93/10/24 12:43:51 julian Exp Locker: julian $ */ #include <sys/types.h> +#include <sys/param.h> +#include <sys/systm.h> + +#include <sys/malloc.h> #include "st.h" #include "sd.h" #include "ch.h" #include "cd.h" -#include "sg.h" +#include "uk.h" +#include "su.h" +#ifndef NSCBUS +#define NSCBUS 8 +#endif /* NSCBUS */ -#ifdef MACH -#include <i386/machparam.h> -#endif MACH #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> -#if !defined(OSF) && !defined(__386BSD__) +#ifdef TFS #include "bll.h" #include "cals.h" #include "kil.h" -#else +#include "scan.h" +#else /* TFS */ #define NBLL 0 #define NCALS 0 #define NKIL 0 -#endif /* !defined(OSF) && !defined(__386BSD__) */ +#define NSCAN 0 +#endif /* TFS */ #if NSD > 0 -extern sdattach(); -#endif NSD +extern sdattach(); +#endif /* NSD */ #if NST > 0 -extern stattach(); -#endif NST +extern stattach(); +#endif /* NST */ #if NCH > 0 -extern chattach(); -#endif NCH +extern chattach(); +#endif /* NCH */ #if NCD > 0 -extern cdattach(); -#endif NCD +extern cdattach(); +#endif /* NCD */ #if NBLL > 0 -extern bllattach(); -#endif NBLL +extern bllattach(); +#endif /* NBLL */ #if NCALS > 0 -extern calsattach(); -#endif NCALS +extern calsattach(); +#endif /* NCALS */ #if NKIL > 0 -extern kil_attach(); -#endif NKIL - -/***************************************************************\ -* The structure of pre-configured devices that might be turned * -* off and therefore may not show up * -\***************************************************************/ -struct predefined -{ - u_char scsibus; - u_char dev; - u_char lu; - int (*attach_rtn)(); - char *devname; - char flags; -} -pd[] = +extern kil_attach(); +#endif /* NKIL */ +#if NUK > 0 +extern ukattach(); +#endif /* NUK */ + +/* + * One of these is allocated and filled in for each scsi bus. + * it holds pointers to allow the scsi bus to get to the driver + * That is running each LUN on the bus + * it also has a template entry which is the prototype struct + * supplied by the adapter driver, this is used to initialise + * the others, before they have the rest of the fields filled in + */ +struct scsibus_data *scbus_data[NSCBUS]; + +/* + * The structure of pre-configured devices that might be turned + * off and therefore may not show up + */ +struct predefined { + u_char scsibus; + u_char dev; + u_char lu; + errval(*attach_rtn) (); + char *devname; + char flags; +} pd[] = + { #ifdef EXAMPLE_PREDEFINE #if NSD > 0 - {0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */ -#endif NSD -#endif EXAMPLE_PREDEFINE - {0,9,9} /*illegal dummy end entry */ + { + 0, 0, 0, sdattach, "sd", 0 + }, /* define a disk at scsibus=0 dev=0 lu=0 */ +#endif /* NSD */ +#endif /* EXAMPLE_PREDEFINE */ + { + 0, 9, 9 + } /*illegal dummy end entry */ }; +/* + * The structure of known drivers for autoconfiguration + */ +struct scsidevs { + u_int32 type; + boolean removable; + char *manufacturer; + char *model; + char *version; + errval(*attach_rtn) (); + char *devname; + char flags; /* 1 show my comparisons during boot(debug) */ +}; -/***************************************************************\ -* The structure of known drivers for autoconfiguration * -\***************************************************************/ -static struct scsidevs -{ - int type; - int removable; - char *manufacturer; - char *model; - char *version; - int (*attach_rtn)(); - char *devname; - char flags; /* 1 show my comparisons during boot(debug) */ -} #define SC_SHOWME 0x01 #define SC_ONE_LU 0x00 #define SC_MORE_LUS 0x02 -knowndevs[] = { +#if NUK > 0 + +static struct scsidevs unknowndev = { + -1, 0, "standard", "any" + ,"any", ukattach, "uk", SC_MORE_LUS +}; +#endif /*NUK*/ +static struct scsidevs knowndevs[] = +{ #if NSD > 0 - { T_DIRECT,T_FIXED,"standard","any" - ,"any",sdattach,"sd",SC_ONE_LU }, - { T_DIRECT,T_FIXED,"MAXTOR ","XT-4170S " - ,"B5A ",sdattach,"mx1",SC_ONE_LU }, -#endif NSD + { + T_DIRECT, T_FIXED, "standard", "any" + ,"any", sdattach, "sd", SC_ONE_LU + }, + { + T_DIRECT, T_FIXED, "MAXTOR ", "XT-4170S " + ,"B5A ", sdattach, "mx1", SC_ONE_LU + }, +#endif /* NSD */ #if NST > 0 - { T_SEQUENTIAL,T_REMOV,"standard","any" - ,"any",stattach,"st",SC_ONE_LU }, -#endif NST + { + T_SEQUENTIAL, T_REMOV, "standard", "any" + ,"any", stattach, "st", SC_ONE_LU + }, +#endif /* NST */ #if NCALS > 0 - { T_PROCESSOR,T_FIXED,"standard","any" - ,"any",calsattach,"cals",SC_MORE_LUS }, -#endif NCALS + { + T_PROCESSOR, T_FIXED, "standard", "any" + ,"any", calsattach, "cals", SC_MORE_LUS + }, +#endif /* NCALS */ #if NCH > 0 - { T_CHANGER,T_REMOV,"standard","any" - ,"any",chattach,"ch",SC_ONE_LU }, -#endif NCH + { + T_CHANGER, T_REMOV, "standard", "any" + ,"any", chattach, "ch", SC_ONE_LU + }, +#endif /* NCH */ #if NCD > 0 - { T_READONLY,T_REMOV,"SONY ","CD-ROM CDU-8012 " - ,"3.1a",cdattach,"cd",SC_ONE_LU }, - { T_READONLY,T_REMOV,"PIONEER ","CD-ROM DRM-600 " - ,"any",cdattach,"cd",SC_MORE_LUS }, -#endif NCD +#ifndef UKTEST /* make cdroms unrecognised to test the uk driver */ + { + T_READONLY, T_REMOV, "SONY ", "CD-ROM CDU-8012 " + ,"3.1a", cdattach, "cd", SC_ONE_LU + }, + { + T_READONLY, T_REMOV, "PIONEER ", "CD-ROM DRM-600 " + ,"any", cdattach, "cd", SC_MORE_LUS + }, +#endif +#endif /* NCD */ #if NBLL > 0 - { T_PROCESSOR,T_FIXED,"AEG ","READER " - ,"V1.0",bllattach,"bll",SC_MORE_LUS }, -#endif NBLL + { + T_PROCESSOR, T_FIXED, "AEG ", "READER " + ,"V1.0", bllattach, "bll", SC_MORE_LUS + }, +#endif /* NBLL */ #if NKIL > 0 - { T_SCANNER,T_FIXED,"KODAK ","IL Scanner 900 " - ,"any",kil_attach,"kil",SC_ONE_LU }, -#endif NKIL + { + T_SCANNER, T_FIXED, "KODAK ", "IL Scanner 900 " + ,"any", kil_attach, "kil", SC_ONE_LU + }, +#endif /* NKIL */ -{0} + { + 0 + } }; -/***************************************************************\ -* Declarations * -\***************************************************************/ -struct predefined *scsi_get_predef(); -struct scsidevs *scsi_probedev(); -struct scsidevs *selectdev(); - -/* controls debug level within the scsi subsystem */ -/* see scsiconf.h for values */ -int scsi_debug = 0x0; -int scsibus = 0x0; /* This is the Nth scsibus */ - -/***************************************************************\ -* The routine called by the adapter boards to get all their * -* devices configured in. * -\***************************************************************/ -scsi_attachdevs( unit, scsi_addr, scsi_switch) -int unit,scsi_addr; -struct scsi_switch *scsi_switch; + +/* + * Declarations + */ +struct predefined *scsi_get_predef(); +struct scsidevs *scsi_probedev(); +struct scsidevs *selectdev(); +errval scsi_probe_bus __P((int bus, int targ, int lun)); + +struct scsi_device probe_switch = { - int targ,lun; - struct scsidevs *bestmatch = (struct scsidevs *)0; - struct predefined *predef; - int maybe_more; + NULL, + NULL, + NULL, + NULL, + "probe", + 0, + { 0, 0 } +}; -#ifdef SCSI_DELAY -#if SCSI_DELAY > 2 +/* + * controls debug level within the scsi subsystem - + * see scsiconf.h for values + */ +int32 scsibus = 0x0; /* This is the Nth scsibus we've seen */ + +/* + * The routine called by the adapter boards to get all their + * devices configured in. + */ +void +scsi_attachdevs(sc_link_proto) + struct scsi_link *sc_link_proto; +{ + + if(scsibus >= NSCBUS) { + printf("too many scsi busses, reconfigure the kernel\n"); + return; + } + sc_link_proto->scsibus = scsibus; + scbus_data[scsibus] = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT); + if(!scbus_data[scsibus]) { + panic("scsi_attachdevs: malloc\n"); + } + bzero(scbus_data[scsibus], sizeof(struct scsibus_data)); + scbus_data[scsibus]->adapter_link = sc_link_proto; +#if defined(SCSI_DELAY) && SCSI_DELAY > 2 printf("%s%d waiting for scsi devices to settle\n", - scsi_switch->name, unit); -#else SCSI_DELAY > 2 -#define SCSI_DELAY 2 -#endif SCSI_DELAY > 2 -#else + sc_link_proto->adapter->name, sc_link_proto->adapter_unit); +#else /* SCSI_DELAY > 2 */ +#undef SCSI_DELAY #define SCSI_DELAY 2 -#endif SCSI_DELAY - spinwait(1000 * SCSI_DELAY); - targ = 0; - while(targ < 8) - { - maybe_more = 0; /* by default only check 1 lun */ - if (targ == scsi_addr) - { - targ++; +#endif /* SCSI_DELAY */ + DELAY(1000000 * SCSI_DELAY); + scsibus++; + scsi_probe_bus(scsibus - 1,-1,-1); +} + +/* + * Probe the requested scsi bus. It must be already set up. + * -1 requests all set up scsi busses. + * targ and lun optionally narrow the search if not -1 + */ +errval +scsi_probe_busses(int bus, int targ, int lun) +{ + if (bus == -1) { + for(bus = 0; bus < scsibus; bus++) { + scsi_probe_bus(bus, targ, lun); + } + return 0; + } else { + return scsi_probe_bus(bus, targ, lun); + } +} + +/* + * Probe the requested scsi bus. It must be already set up. + * targ and lun optionally narrow the search if not -1 + */ +errval +scsi_probe_bus(int bus, int targ, int lun) +{ + struct scsibus_data *scsi ; + int maxtarg,mintarg,maxlun,minlun; + struct scsi_link *sc_link_proto; + u_int8 scsi_addr ; + struct scsidevs *bestmatch = NULL; + struct predefined *predef = NULL; + struct scsi_link *sc_link = NULL; + boolean maybe_more; + + if ((bus < 0 ) || ( bus >= scsibus)) { + return ENXIO; + } + scsi = scbus_data[bus]; + if(!scsi) return ENXIO; + sc_link_proto = scsi->adapter_link; + scsi_addr = sc_link_proto->adapter_targ; + if(targ == -1){ + maxtarg = 7; + mintarg = 0; + } else { + if((targ < 0 ) || (targ > 7)) return EINVAL; + maxtarg = mintarg = targ; + } + + if(lun == -1){ + maxlun = 7; + minlun = 0; + } else { + if((lun < 0 ) || (lun > 7)) return EINVAL; + maxlun = minlun = lun; + } + + + for ( targ = mintarg;targ <= maxtarg; targ++) { + maybe_more = 0; /* by default only check 1 lun */ + if (targ == scsi_addr) { continue; } - lun = 0; - while(lun < 8) - { - predef = scsi_get_predef(scsibus - ,targ - ,lun - ,scsi_switch - ,&maybe_more); - bestmatch = scsi_probedev(unit - ,targ - ,lun - ,scsi_switch - ,&maybe_more); - if((bestmatch) && (predef)) /* both exist */ - { - if(bestmatch->attach_rtn - != predef->attach_rtn) - { - printf("Clash in found/expected devices\n"); - printf("will link in FOUND\n"); + for ( lun = minlun; lun <= maxlun ;lun++) { + /* + * The spot appears to already have something + * linked in, skip past it. Must be doing a 'reprobe' + */ + if(scsi->sc_link[targ][lun]) + {/* don't do this one, but check other luns */ + maybe_more = 1; + continue; + } + /* + * If we presently don't have a link block + * then allocate one to use while probing + */ + if (!sc_link) { + sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT); + *sc_link = *sc_link_proto; /* struct copy */ + sc_link->opennings = 1; + sc_link->device = &probe_switch; + } + sc_link->target = targ; + sc_link->lun = lun; + predef = scsi_get_predef(sc_link, &maybe_more); + bestmatch = scsi_probedev(sc_link, &maybe_more); + if ((bestmatch) && (predef)) { /* both exist */ + if (bestmatch->attach_rtn + != predef->attach_rtn) { + printf("Clash in found/expected devices\n"); +#if NUK > 0 + if(bestmatch == &unknowndev) { + printf("will link in PREDEFINED\n"); + (*(predef->attach_rtn)) (sc_link); + } else +#endif /*NUK*/ + { + printf("will link in FOUND\n"); + (*(bestmatch->attach_rtn)) (sc_link); + } + } else { + (*(bestmatch->attach_rtn)) (sc_link); } - (*(bestmatch->attach_rtn))(unit, - targ, - lun, - scsi_switch); } - if((bestmatch) && (!predef)) /* just FOUND */ - { - (*(bestmatch->attach_rtn))(unit, - targ, - lun, - scsi_switch); + if ((bestmatch) && (!predef)) { /* just FOUND */ + (*(bestmatch->attach_rtn)) (sc_link); } - if((!bestmatch) && (predef)) /* just predef */ - { - (*(predef->attach_rtn))(unit, - targ, - lun, - scsi_switch); + if ((!bestmatch) && (predef)) { /* just predef */ + (*(predef->attach_rtn)) (sc_link); } - if(!(maybe_more)) /* nothing suggests we'll find more */ - { + if ((bestmatch) || (predef)) { /* one exists */ + scsi->sc_link[targ][lun] = sc_link; + sc_link = NULL; /* it's been used */ + } + if (!(maybe_more)) { /* nothing suggests we'll find more */ break; /* nothing here, skip to next targ */ } - /* otherwise something says we should look further*/ - lun++; + /* otherwise something says we should look further */ } - targ++; } -#if NSG > 0 - /***************************************************************\ - * If available hook up the generic scsi driver, letting it * - * know which target is US. (i.e. illegal or at least special) * - \***************************************************************/ - sg_attach(unit,scsi_addr,scsi_switch); -#endif - scsibus++; /* next time we are on the NEXT scsi bus */ + if (sc_link) { + free(sc_link, M_TEMP); + } + return 0; } -/***********************************************\ -* given a target and lu, check if there is a * -* predefined device for that address * -\***********************************************/ -struct predefined *scsi_get_predef(unit,target,lu,scsi_switch,maybe_more) -int unit,target,lu,*maybe_more; -struct scsi_switch *scsi_switch; +/* + * given a target and lu, check if there is a predefined device for + * that address + */ +struct predefined * +scsi_get_predef(sc_link, maybe_more) + struct scsi_link *sc_link; + boolean *maybe_more; { - int upto,numents; + u_int8 unit = sc_link->scsibus; + u_int8 target = sc_link->target; + u_int8 lu = sc_link->lun; + struct scsi_adapter *scsi_adapter = sc_link->adapter; + u_int32 upto, numents; - numents = (sizeof(pd)/sizeof(struct predefined)) - 1; - - for(upto = 0;upto < numents;upto++) - { - if(pd[upto].scsibus != unit) + numents = (sizeof(pd) / sizeof(struct predefined)) - 1; + + for (upto = 0; upto < numents; upto++) { + if (pd[upto].scsibus != unit) continue; - if(pd[upto].dev != target) + if (pd[upto].dev != target) continue; - if(pd[upto].lu != lu) + if (pd[upto].lu != lu) continue; - + printf("%s%d targ %d lun %d: <%s> - PRECONFIGURED -\n" - ,scsi_switch->name - ,unit - ,target - ,lu - ,pd[upto].devname); + ,scsi_adapter->name + ,unit + ,target + ,lu + ,pd[upto].devname); *maybe_more = pd[upto].flags & SC_MORE_LUS; - return(&(pd[upto])); + return (&(pd[upto])); } - return((struct predefined *)0); + return ((struct predefined *) 0); } -/***********************************************\ -* given a target and lu, ask the device what * -* it is, and find the correct driver table * -* entry. * -\***********************************************/ -struct scsidevs *scsi_probedev(unit,target,lu,scsi_switch, maybe_more) - -struct scsi_switch *scsi_switch; -int unit,target,lu; -int *maybe_more; +/* + * given a target and lu, ask the device what + * it is, and find the correct driver table + * entry. + */ +struct scsidevs * +scsi_probedev(sc_link, maybe_more) + boolean *maybe_more; + struct scsi_link *sc_link; { - struct scsidevs *bestmatch = (struct scsidevs *)0; - char *dtype=(char *)0,*desc; - char *qtype; - static struct scsi_inquiry_data inqbuf; - int len,qualifier,type,remov; - char manu[32]; - char model[32]; - char version[32]; - - - bzero(&inqbuf,sizeof(inqbuf)); - /***********************************************\ - * Ask the device what it is * - \***********************************************/ -#ifdef DEBUG - if((target == 0) && (lu == 0)) - scsi_debug = 0xfff; + u_int8 unit = sc_link->adapter_unit; + u_int8 target = sc_link->target; + u_int8 lu = sc_link->lun; + struct scsi_adapter *scsi_adapter = sc_link->adapter; + struct scsidevs *bestmatch = (struct scsidevs *) 0; + char *dtype = (char *) 0, *desc; + char *qtype; + static struct scsi_inquiry_data inqbuf; + u_int32 len, qualifier, type; + boolean remov; + char manu[32]; + char model[32]; + char version[32]; + + bzero(&inqbuf, sizeof(inqbuf)); + /* + * Ask the device what it is + */ +#ifdef SCSIDEBUG + if ((target == DEBUGTARG) && (lu == DEBUGLUN)) + sc_link->flags |= (DEBUGLEVEL); else - scsi_debug = 0; -#endif DEBUG - if(scsi_ready( unit, - target, - lu, - scsi_switch, - SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) - { - return(struct scsidevs *)0; - } - if(scsi_inquire(unit, - target, - lu, - scsi_switch, - &inqbuf, - SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE) - { - return(struct scsidevs *)0; - } + sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4); +#endif /* SCSIDEBUG */ + /* catch unit attn */ + scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT); +#ifdef DOUBTFULL + switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) { + case 0: /* said it WAS ready */ + case EBUSY: /* replied 'NOT READY' but WAS present, continue */ + case ENXIO: + break; + case EIO: /* device timed out */ + case EINVAL: /* Lun not supported */ + default: + return (struct scsidevs *) 0; - /***********************************************\ - * note what BASIC type of device it is * - \***********************************************/ - if(scsi_debug & SHOWINQUIRY) - { - desc=(char *)&inqbuf; - printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n", - desc[0], desc[1], desc[2], desc[3], - desc[4], desc[5], desc[6], desc[7], - desc[8], desc[9], desc[10], desc[11], - desc[12]); + } +#endif /*DOUBTFULL*/ +#ifdef SCSI_2_DEF + /* some devices need to be told to go to SCSI2 */ + /* However some just explode if you tell them this.. leave it out */ + scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT); +#endif /*SCSI_2_DEF */ + + /* Now go ask the device all about itself */ + if (scsi_inquire(sc_link, &inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) { + return (struct scsidevs *) 0; } + /* + * note what BASIC type of device it is + */ type = inqbuf.device & SID_TYPE; qualifier = inqbuf.device & SID_QUAL; remov = inqbuf.dev_qual2 & SID_REMOVABLE; - - /* Any device qualifier that has - * the top bit set (qualifier&4 != 0) is vendor specific and - * won't match in this switch. + /* + * Any device qualifier that has the top bit set (qualifier&4 != 0) + * is vendor specific and won't match in this switch. */ - switch(qualifier) - { + switch (qualifier) { case SID_QUAL_LU_OK: - qtype=""; + qtype = ""; break; case SID_QUAL_LU_OFFLINE: - qtype=", Unit not Connected!"; + qtype = ", Unit not Connected!"; break; case SID_QUAL_RSVD: - qtype=", Reserved Peripheral Qualifier!"; + qtype = ", Reserved Peripheral Qualifier!"; *maybe_more = 1; - return (struct scsidevs *)0; + return (struct scsidevs *) 0; break; case SID_QUAL_BAD_LU: /* * Check for a non-existent unit. If the device is returning - * this much, then we must set the flag that has - * the searcher keep looking on other luns. - */ - qtype=", The Target can't support this Unit!"; + * this much, then we must set the flag that has + * the searchers keep looking on other luns. + */ + qtype = ", The Target can't support this Unit!"; *maybe_more = 1; - return (struct scsidevs *)0; + return (struct scsidevs *) 0; default: - dtype="vendor specific"; - qtype=""; + dtype = "vendor specific"; + qtype = ""; *maybe_more = 1; break; } - - if (dtype == 0) - { - switch(type) - { + if (dtype == 0) { + switch (type) { case T_DIRECT: - dtype="direct"; + dtype = "direct"; break; case T_SEQUENTIAL: - dtype="sequential"; + dtype = "sequential"; break; case T_PRINTER: - dtype="printer"; + dtype = "printer"; break; case T_PROCESSOR: - dtype="processor"; + dtype = "processor"; break; case T_READONLY: - dtype="readonly"; + dtype = "readonly"; break; case T_WORM: - dtype="worm"; + dtype = "worm"; break; case T_SCANNER: - dtype="scanner"; + dtype = "scanner"; break; case T_OPTICAL: - dtype="optical"; + dtype = "optical"; break; case T_CHANGER: - dtype="changer"; + dtype = "changer"; break; case T_COMM: - dtype="communication"; + dtype = "communication"; break; case T_NODEVICE: *maybe_more = 1; - return (struct scsidevs *)0; + return (struct scsidevs *) 0; default: - dtype="unknown"; + dtype = "unknown"; break; } - - } - /***********************************************\ - * Then if it's advanced enough, more detailed * - * information * - \***********************************************/ - if((inqbuf.version & SID_ANSII) > 0) - { - if ((len = inqbuf.additional_length - + ( (char *)inqbuf.unused - - (char *)&inqbuf)) - > (sizeof(struct scsi_inquiry_data) - 1)) - len = sizeof(struct scsi_inquiry_data) - 1; - desc=inqbuf.vendor; - desc[len-(desc - (char *)&inqbuf)] = 0; - strncpy(manu,inqbuf.vendor,8);manu[8]=0; - strncpy(model,inqbuf.product,16);model[16]=0; - strncpy(version,inqbuf.revision,4);version[4]=0; } - else - /***********************************************\ - * If not advanced enough, use default values * - \***********************************************/ + /* + * Then if it's advanced enough, more detailed + * information + */ + if ((inqbuf.version & SID_ANSII) > 0) { + if ((len = inqbuf.additional_length + + ((char *) inqbuf.unused + - (char *) &inqbuf)) + > (sizeof(struct scsi_inquiry_data) - 1)) + len = sizeof(struct scsi_inquiry_data) - 1; + desc = inqbuf.vendor; + desc[len - (desc - (char *) &inqbuf)] = 0; + strncpy(manu, inqbuf.vendor, 8); + manu[8] = 0; + strncpy(model, inqbuf.product, 16); + model[16] = 0; + strncpy(version, inqbuf.revision, 4); + version[4] = 0; + } else + /* + * If not advanced enough, use default values + */ { - desc="early protocol device"; - strncpy(manu,"unknown",8); - strncpy(model,"unknown",16); - strncpy(version,"????",4); + desc = "early protocol device"; + strncpy(manu, "unknown", 8); + strncpy(model, "unknown", 16); + strncpy(version, "????", 4); } printf("%s%d targ %d lun %d: type %d(%s) %s SCSI%d\n" - ,scsi_switch->name - ,unit - ,target - ,lu - ,type - ,dtype - ,remov?"removable":"fixed" - ,inqbuf.version & SID_ANSII - ); + ,scsi_adapter->name + ,unit + ,target + ,lu + ,type + ,dtype + ,remov ? "removable" : "fixed" + ,inqbuf.version & SID_ANSII + ); printf("%s%d targ %d lun %d: <%s%s%s>\n" - ,scsi_switch->name - ,unit - ,target - ,lu - ,manu - ,model - ,version - ); - if(qtype[0]) - { + ,scsi_adapter->name + ,unit + ,target + ,lu + ,manu + ,model + ,version + ); + if (qtype[0]) { printf("%s%d targ %d lun %d: qualifier %d(%s)\n" - ,scsi_switch->name - ,unit - ,target - ,lu - ,qualifier - ,qtype - ); + ,scsi_adapter->name + ,unit + ,target + ,lu + ,qualifier + ,qtype + ); } - /***********************************************\ - * Try make as good a match as possible with * - * available sub drivers * - \***********************************************/ - bestmatch = (selectdev(unit,target,lu,&scsi_switch, - qualifier,type,remov?T_REMOV:T_FIXED,manu,model,version)); - if((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) - { + /* + * Try make as good a match as possible with + * available sub drivers + */ + bestmatch = (selectdev( + qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version)); + if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) { *maybe_more = 1; } - return(bestmatch); + return (bestmatch); } - -/***********************************************\ -* Try make as good a match as possible with * -* available sub drivers * -\***********************************************/ -struct scsidevs -*selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev) -int unit,target,lu; -struct scsi_switch *dvr_switch; -int qualifier,type,remov; -char *manu,*model,*rev; +/* + * Try make as good a match as possible with + * available sub drivers + */ +struct scsidevs * +selectdev(qualifier, type, remov, manu, model, rev) + u_int32 qualifier, type; + boolean remov; + char *manu, *model, *rev; { - int numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1; - int count = 0; - int bestmatches = 0; - struct scsidevs *bestmatch = (struct scsidevs *)0; - struct scsidevs *thisentry = knowndevs; + u_int32 numents = (sizeof(knowndevs) / sizeof(struct scsidevs)) - 1; + u_int32 count = 0; + u_int32 bestmatches = 0; + struct scsidevs *bestmatch = (struct scsidevs *) 0; + struct scsidevs *thisentry = knowndevs; type |= qualifier; /* why? */ thisentry--; - while( count++ < numents) - { + while (count++ < numents) { thisentry++; - if(type != thisentry->type) - { + if (type != thisentry->type) { continue; } - if(bestmatches < 1) - { + if (bestmatches < 1) { bestmatches = 1; bestmatch = thisentry; } - if(remov != thisentry->removable) - { + if (remov != thisentry->removable) { continue; } - if(bestmatches < 2) - { + if (bestmatches < 2) { bestmatches = 2; bestmatch = thisentry; } - if(thisentry->flags & SC_SHOWME) - printf("\n%s-\n%s-",thisentry->manufacturer, manu); - if(strcmp(thisentry->manufacturer, manu)) - { + if (thisentry->flags & SC_SHOWME) + printf("\n%s-\n%s-", thisentry->manufacturer, manu); + if (strcmp(thisentry->manufacturer, manu)) { continue; } - if(bestmatches < 3) - { + if (bestmatches < 3) { bestmatches = 3; bestmatch = thisentry; } - if(thisentry->flags & SC_SHOWME) - printf("\n%s-\n%s-",thisentry->model, model); - if(strcmp(thisentry->model, model)) - { + if (thisentry->flags & SC_SHOWME) + printf("\n%s-\n%s-", thisentry->model, model); + if (strcmp(thisentry->model, model)) { continue; } - if(bestmatches < 4) - { + if (bestmatches < 4) { bestmatches = 4; bestmatch = thisentry; } - if(thisentry->flags & SC_SHOWME) - printf("\n%s-\n%s-",thisentry->version, rev); - if(strcmp(thisentry->version, rev)) - { + if (thisentry->flags & SC_SHOWME) + printf("\n%s-\n%s-", thisentry->version, rev); + if (strcmp(thisentry->version, rev)) { continue; } - if(bestmatches < 5) - { + if (bestmatches < 5) { bestmatches = 5; bestmatch = thisentry; break; } } - - if (bestmatch == (struct scsidevs *)0) - printf(" No explicit device driver match for \"%s %s\".\n", - manu, model); - - return(bestmatch); -} - -static int recurse = 0; -/***********************************************\ -* Do a scsi operation asking a device if it is * -* ready. Use the scsi_cmd routine in the switch * -* table. * -\***********************************************/ -scsi_ready(unit,target,lu,scsi_switch, flags) -struct scsi_switch *scsi_switch; -{ - struct scsi_test_unit_ready scsi_cmd; - struct scsi_xfer scsi_xfer; - volatile int rval; - int key; - - bzero(&scsi_cmd, sizeof(scsi_cmd)); - bzero(&scsi_xfer, sizeof(scsi_xfer)); - scsi_cmd.op_code = TEST_UNIT_READY; - - scsi_xfer.flags=flags | INUSE; - scsi_xfer.adapter=unit; - scsi_xfer.targ=target; - scsi_xfer.lu=lu; - scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd; - scsi_xfer.retries=8; - scsi_xfer.timeout=10000; - scsi_xfer.cmdlen=sizeof(scsi_cmd); - scsi_xfer.data=0; - scsi_xfer.datalen=0; - scsi_xfer.resid=0; - scsi_xfer.when_done=0; - scsi_xfer.done_arg=0; -retry: scsi_xfer.error=0; - /*******************************************************\ - * do not use interrupts * - \*******************************************************/ - rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer); - if (rval != COMPLETE) - { - if(scsi_debug) - { - printf("scsi error, rval = 0x%x\n",rval); - printf("code from driver: 0x%x\n",scsi_xfer.error); - } - switch(scsi_xfer.error) - { - case XS_SENSE: - /*******************************************************\ - * Any sense value is illegal except UNIT ATTENTION * - * In which case we need to check again to get the * - * correct response. * - *( especially exabytes) * - \*******************************************************/ - if(((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x70 ) - ||((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x71 )) - { - key = scsi_xfer.sense.ext.extended.flags & SSD_KEY ; - switch(key) - { - case 2: /* not ready BUT PRESENT! */ - return(COMPLETE); - case 6: - spinwait(1000); - if(scsi_xfer.retries--) - { - scsi_xfer.flags &= ~ITSDONE; - goto retry; - } - return(COMPLETE); - default: - if(scsi_debug) - printf("%d:%d,key=%x.", - target,lu,key); - } - } - return(HAD_ERROR); - case XS_BUSY: - spinwait(1000); - if(scsi_xfer.retries--) - { - scsi_xfer.flags &= ~ITSDONE; - goto retry; - } - return(COMPLETE); /* it's busy so it's there */ - case XS_TIMEOUT: - default: - return(HAD_ERROR); - } - } - return(COMPLETE); -} -/***********************************************\ -* Do a scsi operation asking a device what it is* -* Use the scsi_cmd routine in the switch table. * -\***********************************************/ -scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags) -struct scsi_switch *scsi_switch; -u_char *inqbuf; -{ - struct scsi_inquiry scsi_cmd; - struct scsi_xfer scsi_xfer; - volatile int rval; - - bzero(&scsi_cmd, sizeof(scsi_cmd)); - bzero(&scsi_xfer, sizeof(scsi_xfer)); - scsi_cmd.op_code = INQUIRY; - scsi_cmd.length = sizeof(struct scsi_inquiry_data); - - scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE; - scsi_xfer.adapter=unit; - scsi_xfer.targ=target; - scsi_xfer.lu=lu; - scsi_xfer.retries=8; - scsi_xfer.timeout=10000; - scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd; - scsi_xfer.cmdlen= sizeof(struct scsi_inquiry); - scsi_xfer.data=inqbuf; - scsi_xfer.datalen=sizeof(struct scsi_inquiry_data); - scsi_xfer.resid=sizeof(struct scsi_inquiry_data); - scsi_xfer.when_done=0; - scsi_xfer.done_arg=0; -retry: scsi_xfer.error=0; - /*******************************************************\ - * do not use interrupts * - \*******************************************************/ - if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE) - { - if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error); - switch(scsi_xfer.error) - { - case XS_NOERROR: - break; - case XS_SENSE: - /*******************************************************\ - * Any sense value is illegal except UNIT ATTENTION * - * In which case we need to check again to get the * - * correct response. * - *( especially exabytes) * - \*******************************************************/ - if(((scsi_xfer.sense.error_code & SSD_ERRCODE) == 0x70 ) - && ((scsi_xfer.sense.ext.extended.flags & SSD_KEY) == 6)) - { /* it's changed so it's there */ - spinwait(1000); - { - if(scsi_xfer.retries--) - { - scsi_xfer.flags &= ~ITSDONE; - goto retry; - } - } - return( COMPLETE); - } - return(HAD_ERROR); - case XS_BUSY: - spinwait(1000); - if(scsi_xfer.retries--) - { - scsi_xfer.flags &= ~ITSDONE; - goto retry; - } - case XS_TIMEOUT: - default: - return(HAD_ERROR); - } + if (bestmatch == (struct scsidevs *) 0) { +#if NUK > 0 + bestmatch = &unknowndev; +#else + printf("No explicit device driver match.\n"); +#endif } - return(COMPLETE); -} - - - - -/***********************************************\ -* Utility routines often used in SCSI stuff * -\***********************************************/ - -/***********************************************\ -* convert a physical address to 3 bytes, * -* MSB at the lowest address, * -* LSB at the highest. * -\***********************************************/ - -lto3b(val, bytes) -u_char *bytes; -{ - *bytes++ = (val&0xff0000)>>16; - *bytes++ = (val&0xff00)>>8; - *bytes = val&0xff; + return (bestmatch); } - -/***********************************************\ -* The reverse of lto3b * -\***********************************************/ -_3btol(bytes) -u_char *bytes; -{ - int rc; - rc = (*bytes++ << 16); - rc += (*bytes++ << 8); - rc += *bytes; - return(rc); -} - |