Home | History | Annotate | Line # | Download | only in scsipi
scsiconf.c revision 1.1
      1  1.1  cgd /*
      2  1.1  cgd  * Written by Julian Elischer (julian (at) tfs.com)
      3  1.1  cgd  * for TRW Financial Systems for use under the MACH(2.5) operating system.
      4  1.1  cgd  *
      5  1.1  cgd  * TRW Financial Systems, in accordance with their agreement with Carnegie
      6  1.1  cgd  * Mellon University, makes this software available to CMU to distribute
      7  1.1  cgd  * or use in any manner that they see fit as long as this message is kept with
      8  1.1  cgd  * the software. For this reason TFS also grants any other persons or
      9  1.1  cgd  * organisations permission to use or modify this software.
     10  1.1  cgd  *
     11  1.1  cgd  * TFS supplies this software to be publicly redistributed
     12  1.1  cgd  * on the understanding that TFS is not responsible for the correct
     13  1.1  cgd  * functioning of this software in any circumstances.
     14  1.1  cgd  *
     15  1.1  cgd  *
     16  1.1  cgd  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
     17  1.1  cgd  * --------------------         -----   ----------------------
     18  1.1  cgd  * CURRENT PATCH LEVEL:         1       00098
     19  1.1  cgd  * --------------------         -----   ----------------------
     20  1.1  cgd  *
     21  1.1  cgd  * 16 Feb 93	Julian Elischer		ADDED for SCSI system
     22  1.1  cgd  */
     23  1.1  cgd 
     24  1.1  cgd /*
     25  1.1  cgd  * Ported to run under 386BSD by Julian Elischer (julian (at) tfs.com) Sept 1992
     26  1.1  cgd  */
     27  1.1  cgd 
     28  1.1  cgd /*
     29  1.1  cgd $Log:
     30  1.1  cgd *
     31  1.1  cgd */
     32  1.1  cgd #include <sys/types.h>
     33  1.1  cgd #include "st.h"
     34  1.1  cgd #include "sd.h"
     35  1.1  cgd #include "ch.h"
     36  1.1  cgd #include "cd.h"
     37  1.1  cgd 
     38  1.1  cgd #ifdef	MACH
     39  1.1  cgd #include <i386/machparam.h>
     40  1.1  cgd #endif	MACH
     41  1.1  cgd #include <scsi/scsi_all.h>
     42  1.1  cgd #include <scsi/scsiconf.h>
     43  1.1  cgd 
     44  1.1  cgd #if !defined(OSF) && !defined(__386BSD__)
     45  1.1  cgd #include "bll.h"
     46  1.1  cgd #include "cals.h"
     47  1.1  cgd #include "kil.h"
     48  1.1  cgd #else
     49  1.1  cgd #define	NBLL 0
     50  1.1  cgd #define	NCALS 0
     51  1.1  cgd #define	NKIL 0
     52  1.1  cgd #endif /* !defined(OSF) && !defined(__386BSD__) */
     53  1.1  cgd 
     54  1.1  cgd #if NSD > 0
     55  1.1  cgd extern	sdattach();
     56  1.1  cgd #endif NSD
     57  1.1  cgd #if NST > 0
     58  1.1  cgd extern	stattach();
     59  1.1  cgd #endif NST
     60  1.1  cgd #if NCH > 0
     61  1.1  cgd extern	chattach();
     62  1.1  cgd #endif NCH
     63  1.1  cgd #if NCD > 0
     64  1.1  cgd extern	cdattach();
     65  1.1  cgd #endif NCD
     66  1.1  cgd #if NBLL > 0
     67  1.1  cgd extern	bllattach();
     68  1.1  cgd #endif NBLL
     69  1.1  cgd #if NCALS > 0
     70  1.1  cgd extern	calsattach();
     71  1.1  cgd #endif NCALS
     72  1.1  cgd #if NKIL > 0
     73  1.1  cgd extern	kil_attach();
     74  1.1  cgd #endif NKIL
     75  1.1  cgd 
     76  1.1  cgd /***************************************************************\
     77  1.1  cgd * The structure of pre-configured devices that might be turned	*
     78  1.1  cgd * off and therefore may not show up				*
     79  1.1  cgd \***************************************************************/
     80  1.1  cgd struct	predefined
     81  1.1  cgd {
     82  1.1  cgd 	u_char	scsibus;
     83  1.1  cgd 	u_char	dev;
     84  1.1  cgd 	u_char	lu;
     85  1.1  cgd 	int	(*attach_rtn)();
     86  1.1  cgd 	char	*devname;
     87  1.1  cgd 	char	flags;
     88  1.1  cgd }
     89  1.1  cgd pd[] =
     90  1.1  cgd {
     91  1.1  cgd #ifdef EXAMPLE_PREDEFINE
     92  1.1  cgd #if NSD > 0
     93  1.1  cgd 	{0,0,0,sdattach,"sd",0},/* define a disk at scsibus=0 dev=0 lu=0 */
     94  1.1  cgd #endif NSD
     95  1.1  cgd #endif EXAMPLE_PREDEFINE
     96  1.1  cgd 	{0,9,9}			/*illegal dummy end entry */
     97  1.1  cgd };
     98  1.1  cgd 
     99  1.1  cgd 
    100  1.1  cgd /***************************************************************\
    101  1.1  cgd * The structure of known drivers for autoconfiguration		*
    102  1.1  cgd \***************************************************************/
    103  1.1  cgd static struct scsidevs
    104  1.1  cgd {
    105  1.1  cgd 	int type;
    106  1.1  cgd 	int removable;
    107  1.1  cgd 	char	*manufacturer;
    108  1.1  cgd 	char	*model;
    109  1.1  cgd 	char	*version;
    110  1.1  cgd 	int	(*attach_rtn)();
    111  1.1  cgd 	char	*devname;
    112  1.1  cgd 	char	flags;		/* 1 show my comparisons during boot(debug) */
    113  1.1  cgd }
    114  1.1  cgd #define SC_SHOWME	0x01
    115  1.1  cgd #define	SC_ONE_LU	0x00
    116  1.1  cgd #define	SC_MORE_LUS	0x02
    117  1.1  cgd knowndevs[] = {
    118  1.1  cgd #if NSD > 0
    119  1.1  cgd 	{ T_DIRECT,T_FIXED,"standard","any"
    120  1.1  cgd 			,"any",sdattach,"sd",SC_ONE_LU },
    121  1.1  cgd 	{ T_DIRECT,T_FIXED,"MAXTOR  ","XT-4170S        "
    122  1.1  cgd 			,"B5A ",sdattach,"mx1",SC_ONE_LU },
    123  1.1  cgd #endif NSD
    124  1.1  cgd #if NST > 0
    125  1.1  cgd 	{ T_SEQUENTIAL,T_REMOV,"standard","any"
    126  1.1  cgd 			,"any",stattach,"st",SC_ONE_LU },
    127  1.1  cgd #endif NST
    128  1.1  cgd #if NCALS > 0
    129  1.1  cgd 	{ T_PROCESSOR,T_FIXED,"standard","any"
    130  1.1  cgd 			,"any",calsattach,"cals",SC_MORE_LUS },
    131  1.1  cgd #endif NCALS
    132  1.1  cgd #if NCH > 0
    133  1.1  cgd 	{ T_CHANGER,T_REMOV,"standard","any"
    134  1.1  cgd 			,"any",chattach,"ch",SC_ONE_LU },
    135  1.1  cgd #endif NCH
    136  1.1  cgd #if NCD > 0
    137  1.1  cgd 	{ T_READONLY,T_REMOV,"SONY    ","CD-ROM CDU-8012 "
    138  1.1  cgd 			,"3.1a",cdattach,"cd",SC_ONE_LU },
    139  1.1  cgd #endif NCD
    140  1.1  cgd #if NBLL > 0
    141  1.1  cgd 	{ T_PROCESSOR,T_FIXED,"AEG     ","READER          "
    142  1.1  cgd 			,"V1.0",bllattach,"bll",SC_MORE_LUS },
    143  1.1  cgd #endif NBLL
    144  1.1  cgd #if NKIL > 0
    145  1.1  cgd 	{ T_SCANNER,T_FIXED,"KODAK   ","IL Scanner 900  "
    146  1.1  cgd 			,"any",kil_attach,"kil",SC_ONE_LU },
    147  1.1  cgd #endif NKIL
    148  1.1  cgd 
    149  1.1  cgd {0}
    150  1.1  cgd };
    151  1.1  cgd /***************************************************************\
    152  1.1  cgd * Declarations							*
    153  1.1  cgd \***************************************************************/
    154  1.1  cgd struct	predefined	*scsi_get_predef();
    155  1.1  cgd struct	scsidevs	*scsi_probedev();
    156  1.1  cgd struct	scsidevs	*selectdev();
    157  1.1  cgd 
    158  1.1  cgd /* controls debug level within the scsi subsystem */
    159  1.1  cgd /* see scsiconf.h for values			  */
    160  1.1  cgd int	scsi_debug	=	0x0;
    161  1.1  cgd int	scsibus		=	0x0; /* This is the Nth scsibus */
    162  1.1  cgd 
    163  1.1  cgd /***************************************************************\
    164  1.1  cgd * The routine called by the adapter boards to get all their	*
    165  1.1  cgd * devices configured in.					*
    166  1.1  cgd \***************************************************************/
    167  1.1  cgd scsi_attachdevs( unit, scsi_addr, scsi_switch)
    168  1.1  cgd int	unit,scsi_addr;
    169  1.1  cgd struct	scsi_switch	*scsi_switch;
    170  1.1  cgd {
    171  1.1  cgd 	int	targ,lun;
    172  1.1  cgd 	struct	scsidevs	*bestmatch = (struct scsidevs *)0;
    173  1.1  cgd 	struct	predefined *predef;
    174  1.1  cgd 	int maybe_more;
    175  1.1  cgd 
    176  1.1  cgd #ifdef	SCSI_DELAY
    177  1.1  cgd #if 	SCSI_DELAY > 2
    178  1.1  cgd 	printf("waiting for scsi devices to settle\n");
    179  1.1  cgd #else	SCSI_DELAY > 2
    180  1.1  cgd #define	SCSI_DELAY 15
    181  1.1  cgd #endif	SCSI_DELAY > 2
    182  1.1  cgd #else
    183  1.1  cgd #define SCSI_DELAY 2
    184  1.1  cgd #endif	SCSI_DELAY
    185  1.1  cgd 	spinwait(1000 * SCSI_DELAY);
    186  1.1  cgd 	targ = 0;
    187  1.1  cgd 	while(targ < 8)
    188  1.1  cgd 	{
    189  1.1  cgd 		maybe_more = 0; /* by default only check 1 lun */
    190  1.1  cgd 		if (targ == scsi_addr)
    191  1.1  cgd 		{
    192  1.1  cgd 			targ++;
    193  1.1  cgd 			continue;
    194  1.1  cgd 		}
    195  1.1  cgd 		lun = 0;
    196  1.1  cgd 		while(lun < 8)
    197  1.1  cgd 		{
    198  1.1  cgd 			predef = scsi_get_predef(scsibus
    199  1.1  cgd 						,targ
    200  1.1  cgd 						,lun
    201  1.1  cgd 						,&maybe_more);
    202  1.1  cgd 			bestmatch = scsi_probedev(unit
    203  1.1  cgd 						,targ
    204  1.1  cgd 						,lun
    205  1.1  cgd 						,scsi_switch
    206  1.1  cgd 						,&maybe_more);
    207  1.1  cgd 			if((bestmatch) && (predef)) /* both exist */
    208  1.1  cgd 			{
    209  1.1  cgd 				if(bestmatch->attach_rtn
    210  1.1  cgd 				    != predef->attach_rtn)
    211  1.1  cgd 				{
    212  1.1  cgd 				    printf("Clash in found/expected devices\n");
    213  1.1  cgd 				    printf("will link in FOUND\n");
    214  1.1  cgd 				}
    215  1.1  cgd 				(*(bestmatch->attach_rtn))(unit,
    216  1.1  cgd 						targ,
    217  1.1  cgd 						lun,
    218  1.1  cgd 						scsi_switch);
    219  1.1  cgd 			}
    220  1.1  cgd 			if((bestmatch) && (!predef)) /* just FOUND */
    221  1.1  cgd 			{
    222  1.1  cgd 				(*(bestmatch->attach_rtn))(unit,
    223  1.1  cgd 						targ,
    224  1.1  cgd 						lun,
    225  1.1  cgd 						scsi_switch);
    226  1.1  cgd 			}
    227  1.1  cgd 			if((!bestmatch) && (predef)) /* just predef */
    228  1.1  cgd 			{
    229  1.1  cgd 				(*(predef->attach_rtn))(unit,
    230  1.1  cgd 						targ,
    231  1.1  cgd 						lun,
    232  1.1  cgd 						scsi_switch);
    233  1.1  cgd 			}
    234  1.1  cgd 			if(!(maybe_more)) /* nothing suggests we'll find more */
    235  1.1  cgd 			{
    236  1.1  cgd 				break;	/* nothing here, skip to next targ */
    237  1.1  cgd 			}
    238  1.1  cgd 			/* otherwise something says we should look further*/
    239  1.1  cgd 			lun++;
    240  1.1  cgd 		}
    241  1.1  cgd 		targ++;
    242  1.1  cgd 	}
    243  1.1  cgd #if NGENSCSI > 0
    244  1.1  cgd 	/***************************************************************\
    245  1.1  cgd 	* If available hook up the generic scsi driver, letting it	*
    246  1.1  cgd 	* know which target is US. (i.e. illegal or at least special)	*
    247  1.1  cgd 	\***************************************************************/
    248  1.1  cgd 	genscsi_attach(unit,scsi_addr,0,scsi_switch);
    249  1.1  cgd #endif
    250  1.1  cgd 	scsibus++;	/* next time we are on the NEXT scsi bus */
    251  1.1  cgd }
    252  1.1  cgd 
    253  1.1  cgd /***********************************************\
    254  1.1  cgd * given a target and lu, check if there is a	*
    255  1.1  cgd * predefined device for that address		*
    256  1.1  cgd \***********************************************/
    257  1.1  cgd struct	predefined	*scsi_get_predef(unit,target,lu,maybe_more)
    258  1.1  cgd int	unit,target,lu,*maybe_more;
    259  1.1  cgd {
    260  1.1  cgd 	int upto,numents;
    261  1.1  cgd 
    262  1.1  cgd 	numents = (sizeof(pd)/sizeof(struct predefined)) - 1;
    263  1.1  cgd 
    264  1.1  cgd 	for(upto = 0;upto < numents;upto++)
    265  1.1  cgd 	{
    266  1.1  cgd 		if(pd[upto].scsibus != unit)
    267  1.1  cgd 			continue;
    268  1.1  cgd 		if(pd[upto].dev != target)
    269  1.1  cgd 			continue;
    270  1.1  cgd 		if(pd[upto].lu != lu)
    271  1.1  cgd 			continue;
    272  1.1  cgd 
    273  1.1  cgd 		printf("  dev%d,lu%d: %s - PRECONFIGURED -\n"
    274  1.1  cgd 			,target
    275  1.1  cgd 			,lu
    276  1.1  cgd 			,pd[upto].devname);
    277  1.1  cgd 		*maybe_more = pd[upto].flags & SC_MORE_LUS;
    278  1.1  cgd 		return(&(pd[upto]));
    279  1.1  cgd 	}
    280  1.1  cgd 	return((struct predefined *)0);
    281  1.1  cgd }
    282  1.1  cgd 
    283  1.1  cgd /***********************************************\
    284  1.1  cgd * given a target and lu, ask the device what	*
    285  1.1  cgd * it is, and find the correct driver table	*
    286  1.1  cgd * entry.					*
    287  1.1  cgd \***********************************************/
    288  1.1  cgd struct	scsidevs	*scsi_probedev(unit,target,lu,scsi_switch, maybe_more)
    289  1.1  cgd 
    290  1.1  cgd struct	scsi_switch *scsi_switch;
    291  1.1  cgd int	unit,target,lu;
    292  1.1  cgd int *maybe_more;
    293  1.1  cgd {
    294  1.1  cgd 	struct	scsidevs	*bestmatch = (struct scsidevs *)0;
    295  1.1  cgd 	char	*dtype=(char *)0,*desc;
    296  1.1  cgd 	char	*qtype;
    297  1.1  cgd 	static	struct scsi_inquiry_data	inqbuf;
    298  1.1  cgd 	int	len,qualifier,type,remov;
    299  1.1  cgd 	char	manu[32];
    300  1.1  cgd 	char	model[32];
    301  1.1  cgd 	char	version[32];
    302  1.1  cgd 
    303  1.1  cgd 
    304  1.1  cgd 	bzero(&inqbuf,sizeof(inqbuf));
    305  1.1  cgd 	/***********************************************\
    306  1.1  cgd 	* Ask the device what it is			*
    307  1.1  cgd 	\***********************************************/
    308  1.1  cgd #ifdef	DEBUG
    309  1.1  cgd 	if((target == 0) && (lu == 0))
    310  1.1  cgd 		scsi_debug = 0xfff;
    311  1.1  cgd 	else
    312  1.1  cgd 		scsi_debug = 0;
    313  1.1  cgd #endif	DEBUG
    314  1.1  cgd 	if(scsi_ready(	unit,
    315  1.1  cgd 			target,
    316  1.1  cgd 			lu,
    317  1.1  cgd 			scsi_switch,
    318  1.1  cgd 			SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
    319  1.1  cgd 	{
    320  1.1  cgd 		return(struct scsidevs *)0;
    321  1.1  cgd 	}
    322  1.1  cgd 	if(scsi_inquire(unit,
    323  1.1  cgd 			target,
    324  1.1  cgd 			lu,
    325  1.1  cgd 			scsi_switch,
    326  1.1  cgd 			&inqbuf,
    327  1.1  cgd 			SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
    328  1.1  cgd 	{
    329  1.1  cgd 		return(struct scsidevs *)0;
    330  1.1  cgd 	}
    331  1.1  cgd 
    332  1.1  cgd 	/***********************************************\
    333  1.1  cgd 	* note what BASIC type of device it is		*
    334  1.1  cgd 	\***********************************************/
    335  1.1  cgd 	if(scsi_debug & SHOWINQUIRY)
    336  1.1  cgd 	{
    337  1.1  cgd 		desc=(char *)&inqbuf;
    338  1.1  cgd 		printf("inq: %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
    339  1.1  cgd 		desc[0], desc[1], desc[2], desc[3],
    340  1.1  cgd 		desc[4], desc[5], desc[6], desc[7],
    341  1.1  cgd 		desc[8], desc[9], desc[10], desc[11],
    342  1.1  cgd 		desc[12]);
    343  1.1  cgd 	}
    344  1.1  cgd 
    345  1.1  cgd 	type = inqbuf.device_type;
    346  1.1  cgd 	qualifier = inqbuf.device_qualifier;
    347  1.1  cgd 	remov = inqbuf.removable;
    348  1.1  cgd 
    349  1.1  cgd 	/* Check for a non-existent unit.  If the device is returning
    350  1.1  cgd 	 * this much, then we must set the flag that has
    351  1.1  cgd 	 * the searcher keep looking on other luns.
    352  1.1  cgd 	 */
    353  1.1  cgd 	if (qualifier == 3 && type == T_NODEVICE)
    354  1.1  cgd 	{
    355  1.1  cgd 		*maybe_more = 1;
    356  1.1  cgd 		return (struct scsidevs *)0;
    357  1.1  cgd 	}
    358  1.1  cgd 
    359  1.1  cgd 	/* Any device qualifier that has
    360  1.1  cgd 	 * the top bit set (qualifier&4 != 0) is vendor specific and
    361  1.1  cgd 	 * won't match in this switch.
    362  1.1  cgd 	 */
    363  1.1  cgd 
    364  1.1  cgd 	switch(qualifier)
    365  1.1  cgd 	{
    366  1.1  cgd 		case 0:
    367  1.1  cgd 		qtype="";
    368  1.1  cgd 		break;
    369  1.1  cgd 		case 1:
    370  1.1  cgd 		qtype=", Unit not Connected!";
    371  1.1  cgd 		break;
    372  1.1  cgd 		case 2:
    373  1.1  cgd 		qtype=", Reserved Peripheral Qualifier!";
    374  1.1  cgd 		break;
    375  1.1  cgd 		case 3:
    376  1.1  cgd 		qtype=", The Target can't support this Unit!";
    377  1.1  cgd 		break;
    378  1.1  cgd 
    379  1.1  cgd 		default:
    380  1.1  cgd 		dtype="vendor specific";
    381  1.1  cgd 		qtype="";
    382  1.1  cgd 		*maybe_more = 1;
    383  1.1  cgd 		break;
    384  1.1  cgd 	}
    385  1.1  cgd 
    386  1.1  cgd 	if (dtype == 0)
    387  1.1  cgd 		switch(type)
    388  1.1  cgd 		{
    389  1.1  cgd 			case T_DIRECT:
    390  1.1  cgd 				dtype="direct";
    391  1.1  cgd 				break;
    392  1.1  cgd 			case T_SEQUENTIAL:
    393  1.1  cgd 				dtype="sequential";
    394  1.1  cgd 				break;
    395  1.1  cgd 			case T_PRINTER:
    396  1.1  cgd 				dtype="printer";
    397  1.1  cgd 				break;
    398  1.1  cgd 			case T_PROCESSOR:
    399  1.1  cgd 				dtype="processor";
    400  1.1  cgd 				break;
    401  1.1  cgd 			case T_READONLY:
    402  1.1  cgd 				dtype="readonly";
    403  1.1  cgd 				break;
    404  1.1  cgd 			case T_WORM:
    405  1.1  cgd 				dtype="worm";
    406  1.1  cgd 				break;
    407  1.1  cgd 			case T_SCANNER:
    408  1.1  cgd 				dtype="scanner";
    409  1.1  cgd 				break;
    410  1.1  cgd 			case T_OPTICAL:
    411  1.1  cgd 				dtype="optical";
    412  1.1  cgd 				break;
    413  1.1  cgd 			case T_CHANGER:
    414  1.1  cgd 				dtype="changer";
    415  1.1  cgd 				break;
    416  1.1  cgd 			case T_COMM:
    417  1.1  cgd 				dtype="communication";
    418  1.1  cgd 				break;
    419  1.1  cgd 			default:
    420  1.1  cgd 				dtype="unknown";
    421  1.1  cgd 				break;
    422  1.1  cgd 		}
    423  1.1  cgd 
    424  1.1  cgd 	/***********************************************\
    425  1.1  cgd 	* Then if it's advanced enough, more detailed	*
    426  1.1  cgd 	* information					*
    427  1.1  cgd 	\***********************************************/
    428  1.1  cgd 	if(inqbuf.ansii_version > 0)
    429  1.1  cgd 	{
    430  1.1  cgd 		if ((len = inqbuf.additional_length
    431  1.1  cgd 				+ ( (char *)inqbuf.unused
    432  1.1  cgd 				  - (char *)&inqbuf))
    433  1.1  cgd 			> (sizeof(struct scsi_inquiry_data) - 1))
    434  1.1  cgd 			len = sizeof(struct scsi_inquiry_data) - 1;
    435  1.1  cgd 		desc=inqbuf.vendor;
    436  1.1  cgd 		desc[len-(desc - (char *)&inqbuf)] = 0;
    437  1.1  cgd 		strncpy(manu,inqbuf.vendor,8);manu[8]=0;
    438  1.1  cgd 		strncpy(model,inqbuf.product,16);model[16]=0;
    439  1.1  cgd 		strncpy(version,inqbuf.revision,4);version[4]=0;
    440  1.1  cgd 	}
    441  1.1  cgd 	else
    442  1.1  cgd 	/***********************************************\
    443  1.1  cgd 	* If not advanced enough, use default values	*
    444  1.1  cgd 	\***********************************************/
    445  1.1  cgd 	{
    446  1.1  cgd 		desc="early protocol device";
    447  1.1  cgd 		strncpy(manu,"unknown",8);
    448  1.1  cgd 		strncpy(model,"unknown",16);
    449  1.1  cgd 		strncpy(version,"????",4);
    450  1.1  cgd 	}
    451  1.1  cgd 	printf("  dev%d,lu%d: type %d:%d(%s%s),%s '%s%s%s' scsi%d\n"
    452  1.1  cgd 		,target
    453  1.1  cgd 		,lu
    454  1.1  cgd 		,qualifier,type
    455  1.1  cgd 		,dtype,qtype
    456  1.1  cgd 		,remov?"removable":"fixed"
    457  1.1  cgd 		,manu
    458  1.1  cgd 		,model
    459  1.1  cgd 		,version
    460  1.1  cgd 		,inqbuf.ansii_version
    461  1.1  cgd 	);
    462  1.1  cgd 	/***********************************************\
    463  1.1  cgd 	* Try make as good a match as possible with	*
    464  1.1  cgd 	* available sub drivers	 			*
    465  1.1  cgd 	\***********************************************/
    466  1.1  cgd 	bestmatch = (selectdev(unit,target,lu,&scsi_switch,
    467  1.1  cgd 		qualifier,type,remov,manu,model,version));
    468  1.1  cgd 	if((bestmatch) && (bestmatch->flags & SC_MORE_LUS))
    469  1.1  cgd 	{
    470  1.1  cgd 		*maybe_more = 1;
    471  1.1  cgd 	}
    472  1.1  cgd 	return(bestmatch);
    473  1.1  cgd }
    474  1.1  cgd 
    475  1.1  cgd /***********************************************\
    476  1.1  cgd * Try make as good a match as possible with	*
    477  1.1  cgd * available sub drivers	 			*
    478  1.1  cgd \***********************************************/
    479  1.1  cgd struct	scsidevs
    480  1.1  cgd *selectdev(unit,target,lu,dvr_switch,qualifier,type,remov,manu,model,rev)
    481  1.1  cgd int	unit,target,lu;
    482  1.1  cgd struct	scsi_switch *dvr_switch;
    483  1.1  cgd int	qualifier,type,remov;
    484  1.1  cgd char	*manu,*model,*rev;
    485  1.1  cgd {
    486  1.1  cgd 	int	numents = (sizeof(knowndevs)/sizeof(struct scsidevs)) - 1;
    487  1.1  cgd 	int	count = 0;
    488  1.1  cgd 	int			bestmatches = 0;
    489  1.1  cgd 	struct	scsidevs	*bestmatch = (struct scsidevs *)0;
    490  1.1  cgd 	struct	scsidevs	*thisentry = knowndevs;
    491  1.1  cgd 
    492  1.1  cgd 	type |= (qualifier << 5);
    493  1.1  cgd 
    494  1.1  cgd 	thisentry--;
    495  1.1  cgd 	while( count++ < numents)
    496  1.1  cgd 	{
    497  1.1  cgd 		thisentry++;
    498  1.1  cgd 		if(type != thisentry->type)
    499  1.1  cgd 		{
    500  1.1  cgd 			continue;
    501  1.1  cgd 		}
    502  1.1  cgd 		if(bestmatches < 1)
    503  1.1  cgd 		{
    504  1.1  cgd 			bestmatches = 1;
    505  1.1  cgd 			bestmatch = thisentry;
    506  1.1  cgd 		}
    507  1.1  cgd 		if(remov != thisentry->removable)
    508  1.1  cgd 		{
    509  1.1  cgd 			continue;
    510  1.1  cgd 		}
    511  1.1  cgd 		if(bestmatches < 2)
    512  1.1  cgd 		{
    513  1.1  cgd 			bestmatches = 2;
    514  1.1  cgd 			bestmatch = thisentry;
    515  1.1  cgd 		}
    516  1.1  cgd 		if(thisentry->flags & SC_SHOWME)
    517  1.1  cgd 			printf("\n%s-\n%s-",thisentry->manufacturer, manu);
    518  1.1  cgd 		if(strcmp(thisentry->manufacturer, manu))
    519  1.1  cgd 		{
    520  1.1  cgd 			continue;
    521  1.1  cgd 		}
    522  1.1  cgd 		if(bestmatches < 3)
    523  1.1  cgd 		{
    524  1.1  cgd 			bestmatches = 3;
    525  1.1  cgd 			bestmatch = thisentry;
    526  1.1  cgd 		}
    527  1.1  cgd 		if(thisentry->flags & SC_SHOWME)
    528  1.1  cgd 			printf("\n%s-\n%s-",thisentry->model, model);
    529  1.1  cgd 		if(strcmp(thisentry->model, model))
    530  1.1  cgd 		{
    531  1.1  cgd 			continue;
    532  1.1  cgd 		}
    533  1.1  cgd 		if(bestmatches < 4)
    534  1.1  cgd 		{
    535  1.1  cgd 			bestmatches = 4;
    536  1.1  cgd 			bestmatch = thisentry;
    537  1.1  cgd 		}
    538  1.1  cgd 		if(thisentry->flags & SC_SHOWME)
    539  1.1  cgd 			printf("\n%s-\n%s-",thisentry->version, rev);
    540  1.1  cgd 		if(strcmp(thisentry->version, rev))
    541  1.1  cgd 		{
    542  1.1  cgd 			continue;
    543  1.1  cgd 		}
    544  1.1  cgd 		if(bestmatches < 5)
    545  1.1  cgd 		{
    546  1.1  cgd 			bestmatches = 5;
    547  1.1  cgd 			bestmatch = thisentry;
    548  1.1  cgd 			break;
    549  1.1  cgd 		}
    550  1.1  cgd 	}
    551  1.1  cgd 
    552  1.1  cgd 	if (bestmatch == (struct scsidevs *)0)
    553  1.1  cgd 		printf("	No explicit device driver match for \"%s %s\".\n",
    554  1.1  cgd 		manu, model);
    555  1.1  cgd 
    556  1.1  cgd 	return(bestmatch);
    557  1.1  cgd }
    558  1.1  cgd 
    559  1.1  cgd static	int recurse = 0;
    560  1.1  cgd /***********************************************\
    561  1.1  cgd * Do a scsi operation asking a device if it is	*
    562  1.1  cgd * ready. Use the scsi_cmd routine in the switch *
    563  1.1  cgd * table.					*
    564  1.1  cgd \***********************************************/
    565  1.1  cgd scsi_ready(unit,target,lu,scsi_switch, flags)
    566  1.1  cgd struct	scsi_switch *scsi_switch;
    567  1.1  cgd {
    568  1.1  cgd 	struct	scsi_test_unit_ready scsi_cmd;
    569  1.1  cgd 	struct	scsi_xfer scsi_xfer;
    570  1.1  cgd 	volatile int rval;
    571  1.1  cgd 	int	key;
    572  1.1  cgd 
    573  1.1  cgd 	bzero(&scsi_cmd, sizeof(scsi_cmd));
    574  1.1  cgd 	bzero(&scsi_xfer, sizeof(scsi_xfer));
    575  1.1  cgd 	scsi_cmd.op_code = TEST_UNIT_READY;
    576  1.1  cgd 
    577  1.1  cgd 	scsi_xfer.flags=flags | INUSE;
    578  1.1  cgd 	scsi_xfer.adapter=unit;
    579  1.1  cgd 	scsi_xfer.targ=target;
    580  1.1  cgd 	scsi_xfer.lu=lu;
    581  1.1  cgd 	scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
    582  1.1  cgd 	scsi_xfer.retries=8;
    583  1.1  cgd 	scsi_xfer.timeout=10000;
    584  1.1  cgd 	scsi_xfer.cmdlen=sizeof(scsi_cmd);
    585  1.1  cgd 	scsi_xfer.data=0;
    586  1.1  cgd 	scsi_xfer.datalen=0;
    587  1.1  cgd 	scsi_xfer.resid=0;
    588  1.1  cgd 	scsi_xfer.when_done=0;
    589  1.1  cgd 	scsi_xfer.done_arg=0;
    590  1.1  cgd retry:	scsi_xfer.error=0;
    591  1.1  cgd 	/*******************************************************\
    592  1.1  cgd 	* do not use interrupts					*
    593  1.1  cgd 	\*******************************************************/
    594  1.1  cgd 	rval = (*(scsi_switch->scsi_cmd))(&scsi_xfer);
    595  1.1  cgd 	if (rval != COMPLETE)
    596  1.1  cgd 	{
    597  1.1  cgd 		if(scsi_debug)
    598  1.1  cgd 		{
    599  1.1  cgd 			printf("scsi error, rval = 0x%x\n",rval);
    600  1.1  cgd 			printf("code from driver: 0x%x\n",scsi_xfer.error);
    601  1.1  cgd 		}
    602  1.1  cgd 		switch(scsi_xfer.error)
    603  1.1  cgd 		{
    604  1.1  cgd 		case	XS_SENSE:
    605  1.1  cgd 		/*******************************************************\
    606  1.1  cgd 		* Any sense value is illegal except UNIT ATTENTION	*
    607  1.1  cgd 		* In which case we need to check again to get the	*
    608  1.1  cgd 		* correct response.					*
    609  1.1  cgd 		*( especially exabytes)					*
    610  1.1  cgd 		\*******************************************************/
    611  1.1  cgd 			if(scsi_xfer.sense.error_class == 7 )
    612  1.1  cgd 			{
    613  1.1  cgd 				key = scsi_xfer.sense.ext.extended.sense_key ;
    614  1.1  cgd 				switch(key)
    615  1.1  cgd 				{
    616  1.1  cgd 				case	2:	/* not ready BUT PRESENT! */
    617  1.1  cgd 						return(COMPLETE);
    618  1.1  cgd 				case	6:
    619  1.1  cgd 					spinwait(1000);
    620  1.1  cgd 					if(scsi_xfer.retries--)
    621  1.1  cgd 					{
    622  1.1  cgd 						scsi_xfer.flags &= ~ITSDONE;
    623  1.1  cgd 						goto retry;
    624  1.1  cgd 					}
    625  1.1  cgd 					return(COMPLETE);
    626  1.1  cgd 				default:
    627  1.1  cgd 					if(scsi_debug)
    628  1.1  cgd 						printf("%d:%d,key=%x.",
    629  1.1  cgd 						target,lu,key);
    630  1.1  cgd 				}
    631  1.1  cgd 			}
    632  1.1  cgd 			return(HAD_ERROR);
    633  1.1  cgd 		case	XS_BUSY:
    634  1.1  cgd 			spinwait(1000);
    635  1.1  cgd 			if(scsi_xfer.retries--)
    636  1.1  cgd 			{
    637  1.1  cgd 				scsi_xfer.flags &= ~ITSDONE;
    638  1.1  cgd 				goto retry;
    639  1.1  cgd 			}
    640  1.1  cgd 			return(COMPLETE);	/* it's busy so it's there */
    641  1.1  cgd 		case	XS_TIMEOUT:
    642  1.1  cgd 		default:
    643  1.1  cgd 			return(HAD_ERROR);
    644  1.1  cgd 		}
    645  1.1  cgd 	}
    646  1.1  cgd 	return(COMPLETE);
    647  1.1  cgd }
    648  1.1  cgd /***********************************************\
    649  1.1  cgd * Do a scsi operation asking a device what it is*
    650  1.1  cgd * Use the scsi_cmd routine in the switch table.	*
    651  1.1  cgd \***********************************************/
    652  1.1  cgd scsi_inquire(unit,target,lu,scsi_switch,inqbuf, flags)
    653  1.1  cgd struct	scsi_switch *scsi_switch;
    654  1.1  cgd u_char	*inqbuf;
    655  1.1  cgd {
    656  1.1  cgd 	struct	scsi_inquiry scsi_cmd;
    657  1.1  cgd 	struct	scsi_xfer scsi_xfer;
    658  1.1  cgd 	volatile int rval;
    659  1.1  cgd 
    660  1.1  cgd 	bzero(&scsi_cmd, sizeof(scsi_cmd));
    661  1.1  cgd 	bzero(&scsi_xfer, sizeof(scsi_xfer));
    662  1.1  cgd 	scsi_cmd.op_code = INQUIRY;
    663  1.1  cgd 	scsi_cmd.length = sizeof(struct scsi_inquiry_data);
    664  1.1  cgd 
    665  1.1  cgd 	scsi_xfer.flags=flags | SCSI_DATA_IN | INUSE;
    666  1.1  cgd 	scsi_xfer.adapter=unit;
    667  1.1  cgd 	scsi_xfer.targ=target;
    668  1.1  cgd 	scsi_xfer.lu=lu;
    669  1.1  cgd 	scsi_xfer.retries=8;
    670  1.1  cgd 	scsi_xfer.timeout=10000;
    671  1.1  cgd 	scsi_xfer.cmd=(struct scsi_generic *)&scsi_cmd;
    672  1.1  cgd 	scsi_xfer.cmdlen= sizeof(struct scsi_inquiry);
    673  1.1  cgd 	scsi_xfer.data=inqbuf;
    674  1.1  cgd 	scsi_xfer.datalen=sizeof(struct scsi_inquiry_data);
    675  1.1  cgd 	scsi_xfer.resid=sizeof(struct scsi_inquiry_data);
    676  1.1  cgd 	scsi_xfer.when_done=0;
    677  1.1  cgd 	scsi_xfer.done_arg=0;
    678  1.1  cgd retry:	scsi_xfer.error=0;
    679  1.1  cgd 	/*******************************************************\
    680  1.1  cgd 	* do not use interrupts					*
    681  1.1  cgd 	\*******************************************************/
    682  1.1  cgd 	if ((*(scsi_switch->scsi_cmd))(&scsi_xfer) != COMPLETE)
    683  1.1  cgd 	{
    684  1.1  cgd 		if(scsi_debug) printf("inquiry had error(0x%x) ",scsi_xfer.error);
    685  1.1  cgd 		switch(scsi_xfer.error)
    686  1.1  cgd 		{
    687  1.1  cgd 		case	XS_NOERROR:
    688  1.1  cgd 			break;
    689  1.1  cgd 		case	XS_SENSE:
    690  1.1  cgd 		/*******************************************************\
    691  1.1  cgd 		* Any sense value is illegal except UNIT ATTENTION	*
    692  1.1  cgd 		* In which case we need to check again to get the	*
    693  1.1  cgd 		* correct response.					*
    694  1.1  cgd 		*( especially exabytes)					*
    695  1.1  cgd 		\*******************************************************/
    696  1.1  cgd 			if((scsi_xfer.sense.error_class == 7 )
    697  1.1  cgd 			 && (scsi_xfer.sense.ext.extended.sense_key == 6))
    698  1.1  cgd 			{ /* it's changed so it's there */
    699  1.1  cgd 				spinwait(1000);
    700  1.1  cgd 				{
    701  1.1  cgd 					if(scsi_xfer.retries--)
    702  1.1  cgd 					{
    703  1.1  cgd 						scsi_xfer.flags &= ~ITSDONE;
    704  1.1  cgd 						goto retry;
    705  1.1  cgd 					}
    706  1.1  cgd 				}
    707  1.1  cgd 				return( COMPLETE);
    708  1.1  cgd 			}
    709  1.1  cgd 			return(HAD_ERROR);
    710  1.1  cgd 		case	XS_BUSY:
    711  1.1  cgd 			spinwait(1000);
    712  1.1  cgd 			if(scsi_xfer.retries--)
    713  1.1  cgd 			{
    714  1.1  cgd 				scsi_xfer.flags &= ~ITSDONE;
    715  1.1  cgd 				goto retry;
    716  1.1  cgd 			}
    717  1.1  cgd 		case	XS_TIMEOUT:
    718  1.1  cgd 		default:
    719  1.1  cgd 			return(HAD_ERROR);
    720  1.1  cgd 		}
    721  1.1  cgd 	}
    722  1.1  cgd 	return(COMPLETE);
    723  1.1  cgd }
    724  1.1  cgd 
    725  1.1  cgd 
    726  1.1  cgd 
    727  1.1  cgd 
    728  1.1  cgd /***********************************************\
    729  1.1  cgd * Utility routines often used in SCSI stuff	*
    730  1.1  cgd \***********************************************/
    731  1.1  cgd 
    732  1.1  cgd /***********************************************\
    733  1.1  cgd * convert a physical address to 3 bytes, 	*
    734  1.1  cgd * MSB at the lowest address,			*
    735  1.1  cgd * LSB at the highest.				*
    736  1.1  cgd \***********************************************/
    737  1.1  cgd 
    738  1.1  cgd lto3b(val, bytes)
    739  1.1  cgd u_char *bytes;
    740  1.1  cgd {
    741  1.1  cgd 	*bytes++ = (val&0xff0000)>>16;
    742  1.1  cgd 	*bytes++ = (val&0xff00)>>8;
    743  1.1  cgd 	*bytes = val&0xff;
    744  1.1  cgd }
    745  1.1  cgd 
    746  1.1  cgd /***********************************************\
    747  1.1  cgd * The reverse of lto3b				*
    748  1.1  cgd \***********************************************/
    749  1.1  cgd _3btol(bytes)
    750  1.1  cgd u_char *bytes;
    751  1.1  cgd {
    752  1.1  cgd 	int rc;
    753  1.1  cgd 	rc = (*bytes++ << 16);
    754  1.1  cgd 	rc += (*bytes++ << 8);
    755  1.1  cgd 	rc += *bytes;
    756  1.1  cgd 	return(rc);
    757  1.1  cgd }
    758  1.1  cgd 
    759