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