diff options
Diffstat (limited to 'sys/scsi/scsiconf.c')
-rw-r--r-- | sys/scsi/scsiconf.c | 781 |
1 files changed, 0 insertions, 781 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c deleted file mode 100644 index 70765b0..0000000 --- a/sys/scsi/scsiconf.c +++ /dev/null @@ -1,781 +0,0 @@ -/* - * Written by Julian Elischer (julian@tfs.com) - * for TRW Financial Systems for use under the MACH(2.5) operating system. - * - * TRW Financial Systems, in accordance with their agreement with Carnegie - * Mellon University, makes this software available to CMU to distribute - * or use in any manner that they see fit as long as this message is kept with - * the software. For this reason TFS also grants any other persons or - * organisations permission to use or modify this software. - * - * TFS supplies this software to be publicly redistributed - * on the understanding that TFS is not responsible for the correct - * functioning of this software in any circumstances. - * - * 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 $ - */ - -#include <sys/types.h> -#include "st.h" -#include "sd.h" -#include "ch.h" -#include "cd.h" -#include "sg.h" - -#ifdef MACH -#include <i386/machparam.h> -#endif MACH -#include <scsi/scsi_all.h> -#include <scsi/scsiconf.h> - -#if !defined(OSF) && !defined(__386BSD__) -#include "bll.h" -#include "cals.h" -#include "kil.h" -#else -#define NBLL 0 -#define NCALS 0 -#define NKIL 0 -#endif /* !defined(OSF) && !defined(__386BSD__) */ - -#if NSD > 0 -extern sdattach(); -#endif NSD -#if NST > 0 -extern stattach(); -#endif NST -#if NCH > 0 -extern chattach(); -#endif NCH -#if NCD > 0 -extern cdattach(); -#endif NCD -#if NBLL > 0 -extern bllattach(); -#endif NBLL -#if NCALS > 0 -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[] = -{ -#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 */ -}; - - -/***************************************************************\ -* 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 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 -#if NST > 0 - { 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 -#if NCH > 0 - { 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 -#if NBLL > 0 - { 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 - -{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; -{ - int targ,lun; - struct scsidevs *bestmatch = (struct scsidevs *)0; - struct predefined *predef; - int maybe_more; - -#ifdef SCSI_DELAY -#if 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 -#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++; - 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"); - } - (*(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 predef */ - { - (*(predef->attach_rtn))(unit, - targ, - lun, - scsi_switch); - } - if(!(maybe_more)) /* nothing suggests we'll find more */ - { - break; /* nothing here, skip to next targ */ - } - /* otherwise something says we should look further*/ - lun++; - } - 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 */ -} - -/***********************************************\ -* 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; -{ - int upto,numents; - - numents = (sizeof(pd)/sizeof(struct predefined)) - 1; - - for(upto = 0;upto < numents;upto++) - { - if(pd[upto].scsibus != unit) - continue; - if(pd[upto].dev != target) - continue; - 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); - *maybe_more = pd[upto].flags & SC_MORE_LUS; - return(&(pd[upto])); - } - 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; -{ - 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; - 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; - } - - /***********************************************\ - * 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]); - } - - 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. - */ - - switch(qualifier) - { - case SID_QUAL_LU_OK: - qtype=""; - break; - - case SID_QUAL_LU_OFFLINE: - qtype=", Unit not Connected!"; - break; - - case SID_QUAL_RSVD: - qtype=", Reserved Peripheral Qualifier!"; - *maybe_more = 1; - 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!"; - *maybe_more = 1; - return (struct scsidevs *)0; - - default: - dtype="vendor specific"; - qtype=""; - *maybe_more = 1; - break; - } - - if (dtype == 0) - { - switch(type) - { - case T_DIRECT: - dtype="direct"; - break; - case T_SEQUENTIAL: - dtype="sequential"; - break; - case T_PRINTER: - dtype="printer"; - break; - case T_PROCESSOR: - dtype="processor"; - break; - case T_READONLY: - dtype="readonly"; - break; - case T_WORM: - dtype="worm"; - break; - case T_SCANNER: - dtype="scanner"; - break; - case T_OPTICAL: - dtype="optical"; - break; - case T_CHANGER: - dtype="changer"; - break; - case T_COMM: - dtype="communication"; - break; - case T_NODEVICE: - *maybe_more = 1; - return (struct scsidevs *)0; - default: - 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 * - \***********************************************/ - { - 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 - ); - printf("%s%d targ %d lun %d: <%s%s%s>\n" - ,scsi_switch->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 - ); - } - /***********************************************\ - * 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)) - { - *maybe_more = 1; - } - 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; -{ - int numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1; - int count = 0; - int bestmatches = 0; - struct scsidevs *bestmatch = (struct scsidevs *)0; - struct scsidevs *thisentry = knowndevs; - - type |= qualifier; /* why? */ - - thisentry--; - while( count++ < numents) - { - thisentry++; - if(type != thisentry->type) - { - continue; - } - if(bestmatches < 1) - { - bestmatches = 1; - bestmatch = thisentry; - } - if(remov != thisentry->removable) - { - continue; - } - 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)) - { - continue; - } - 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)) - { - continue; - } - 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)) - { - continue; - } - 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); - } - } - 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; -} - -/***********************************************\ -* The reverse of lto3b * -\***********************************************/ -_3btol(bytes) -u_char *bytes; -{ - int rc; - rc = (*bytes++ << 16); - rc += (*bytes++ << 8); - rc += *bytes; - return(rc); -} - |