Home | History | Annotate | Line # | Download | only in scsipi
scsiconf.c revision 1.7
      1  1.1      cgd /*
      2  1.1      cgd  * Written by Julian Elischer (julian (at) tfs.com)
      3  1.5  deraadt  * for TRW Financial Systems for use under the MACH(2.5) operating system.
      4  1.2  deraadt  * Hacked by Theo de Raadt <deraadt (at) fsa.ca>
      5  1.1      cgd  *
      6  1.1      cgd  * TRW Financial Systems, in accordance with their agreement with Carnegie
      7  1.1      cgd  * Mellon University, makes this software available to CMU to distribute
      8  1.1      cgd  * or use in any manner that they see fit as long as this message is kept with
      9  1.1      cgd  * the software. For this reason TFS also grants any other persons or
     10  1.1      cgd  * organisations permission to use or modify this software.
     11  1.1      cgd  *
     12  1.1      cgd  * TFS supplies this software to be publicly redistributed
     13  1.1      cgd  * on the understanding that TFS is not responsible for the correct
     14  1.1      cgd  * functioning of this software in any circumstances.
     15  1.7      cgd  *
     16  1.7      cgd  *	$Id: scsiconf.c,v 1.7 1993/05/20 03:46:36 cgd Exp $
     17  1.1      cgd  */
     18  1.1      cgd 
     19  1.2  deraadt #include "sys/types.h"
     20  1.2  deraadt #include "sys/param.h"
     21  1.2  deraadt #include "sys/systm.h"
     22  1.2  deraadt #include "sys/errno.h"
     23  1.2  deraadt #include "sys/ioctl.h"
     24  1.2  deraadt #include "sys/buf.h"
     25  1.2  deraadt #include "sys/proc.h"
     26  1.2  deraadt #include "sys/user.h"
     27  1.2  deraadt #include "sys/dkbad.h"
     28  1.2  deraadt #include "sys/disklabel.h"
     29  1.2  deraadt #include "scsi/scsi_all.h"
     30  1.2  deraadt #include "scsi/scsiconf.h"
     31  1.1      cgd 
     32  1.1      cgd #include "st.h"
     33  1.1      cgd #include "sd.h"
     34  1.1      cgd #include "ch.h"
     35  1.1      cgd #include "cd.h"
     36  1.1      cgd #define	NBLL 0
     37  1.1      cgd #define	NCALS 0
     38  1.1      cgd #define	NKIL 0
     39  1.1      cgd 
     40  1.1      cgd #if NSD > 0
     41  1.2  deraadt extern int sdattach();
     42  1.1      cgd #endif NSD
     43  1.1      cgd #if NST > 0
     44  1.2  deraadt extern int stattach();
     45  1.1      cgd #endif NST
     46  1.1      cgd #if NCH > 0
     47  1.2  deraadt extern int chattach();
     48  1.1      cgd #endif NCH
     49  1.1      cgd #if NCD > 0
     50  1.2  deraadt extern int cdattach();
     51  1.1      cgd #endif NCD
     52  1.1      cgd #if NBLL > 0
     53  1.2  deraadt extern int bllattach();
     54  1.1      cgd #endif NBLL
     55  1.1      cgd #if NCALS > 0
     56  1.2  deraadt extern int calsattach();
     57  1.1      cgd #endif NCALS
     58  1.1      cgd #if NKIL > 0
     59  1.2  deraadt extern int kil_attach();
     60  1.1      cgd #endif NKIL
     61  1.1      cgd 
     62  1.2  deraadt struct scsidevs knowndevs[] = {
     63  1.1      cgd #if NSD > 0
     64  1.2  deraadt 	{
     65  1.2  deraadt 		SC_TSD, T_DIRECT, T_FIXED, "standard", "any" ,"any",
     66  1.2  deraadt 		sdattach, "sd" ,SC_ONE_LU
     67  1.2  deraadt 	}, {
     68  1.2  deraadt 		SC_TSD, T_DIRECT, T_FIXED, "MAXTOR  ", "XT-4170S	", "B5A ",
     69  1.2  deraadt 		sdattach, "mx1", SC_ONE_LU
     70  1.2  deraadt 	},
     71  1.1      cgd #endif NSD
     72  1.1      cgd #if NST > 0
     73  1.2  deraadt 	{
     74  1.2  deraadt 		SC_TST, T_SEQUENTIAL, T_REMOV, "standard", "any", "any",
     75  1.2  deraadt 		stattach, "st" ,SC_ONE_LU
     76  1.2  deraadt 	},
     77  1.1      cgd #endif NST
     78  1.2  deraadt #if NCD > 0
     79  1.2  deraadt 	{
     80  1.2  deraadt 		SC_TCD, T_READONLY, T_REMOV, "SONY    ", "CD-ROM CDU-8012 ", "3.1a",
     81  1.2  deraadt 		cdattach, "cd", SC_ONE_LU
     82  1.2  deraadt 	},
     83  1.2  deraadt #endif NCD
     84  1.1      cgd #if NCALS > 0
     85  1.2  deraadt 	{
     86  1.2  deraadt 		-1, T_PROCESSOR, T_FIXED, "standard" , "any" ,"any",
     87  1.2  deraadt 		calsattach, "cals", SC_MORE_LUS
     88  1.2  deraadt 	},
     89  1.1      cgd #endif NCALS
     90  1.1      cgd #if NCH > 0
     91  1.2  deraadt 	{
     92  1.2  deraadt 		-1, T_CHANGER, T_REMOV, "standard", "any", "any",
     93  1.2  deraadt 		chattach, "ch", SC_ONE_LU
     94  1.2  deraadt 	},
     95  1.1      cgd #endif NCH
     96  1.1      cgd #if NBLL > 0
     97  1.2  deraadt 	{
     98  1.2  deraadt 		-1, T_PROCESSOR, T_FIXED, "AEG     ", "READER	  ", "V1.0",
     99  1.2  deraadt 		bllattach, "bll", SC_MORE_LUS
    100  1.2  deraadt 	},
    101  1.1      cgd #endif NBLL
    102  1.1      cgd #if NKIL > 0
    103  1.2  deraadt 	{
    104  1.2  deraadt 		-1, T_SCANNER, T_FIXED, "KODAK   ", "IL Scanner 900  ", "any",
    105  1.2  deraadt 		kil_attach, "kil", SC_ONE_LU
    106  1.2  deraadt 	},
    107  1.1      cgd #endif NKIL
    108  1.2  deraadt };
    109  1.2  deraadt 
    110  1.2  deraadt /* controls debug level within the scsi subsystem: see scsiconf.h */
    111  1.2  deraadt int scsi_debug	= 0;
    112  1.1      cgd 
    113  1.2  deraadt struct scsidevs *
    114  1.2  deraadt scsi_probe(int masunit, struct scsi_switch *sw, int physid, int type, int want)
    115  1.1      cgd {
    116  1.2  deraadt 	static struct scsi_inquiry_data inqbuf;
    117  1.2  deraadt 	struct scsidevs *ret = (struct scsidevs *)0;
    118  1.2  deraadt 	int targ = physid >> 3;
    119  1.2  deraadt 	int lun = physid & 7;
    120  1.2  deraadt 	char *qtype=NULL, *dtype=NULL, *desc;
    121  1.2  deraadt 	char manu[9], model[17], revision[5];
    122  1.2  deraadt 	int len;
    123  1.2  deraadt 
    124  1.2  deraadt 	bzero(&inqbuf, sizeof inqbuf);
    125  1.2  deraadt 
    126  1.2  deraadt 	/*printf("probe: %s%d targ %d lun %d\n",
    127  1.2  deraadt 		sw->name, masunit, targ, lun);*/
    128  1.2  deraadt 
    129  1.2  deraadt 	if( scsi_ready(masunit, targ, lun, sw,
    130  1.2  deraadt 	    SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
    131  1.5  deraadt 		return (struct scsidevs *)0;
    132  1.2  deraadt 
    133  1.2  deraadt 	if( scsi_inquire(masunit, targ, lun, sw, (u_char *)&inqbuf,
    134  1.2  deraadt 	    SCSI_NOSLEEP | SCSI_NOMASK) != COMPLETE)
    135  1.5  deraadt 		return (struct scsidevs *)0;
    136  1.2  deraadt 
    137  1.2  deraadt 	if( inqbuf.device_qualifier==3 && inqbuf.device_type==T_NODEVICE)
    138  1.5  deraadt 		return (struct scsidevs *)0;
    139  1.2  deraadt 
    140  1.2  deraadt 	switch(inqbuf.device_qualifier) {
    141  1.2  deraadt 	case 0:
    142  1.2  deraadt 		qtype = "";
    143  1.2  deraadt 		break;
    144  1.2  deraadt 	case 1:
    145  1.2  deraadt 		qtype = "Unit not Connected!";
    146  1.2  deraadt 		break;
    147  1.2  deraadt 	case 2:
    148  1.2  deraadt 		qtype =", Reserved Peripheral Qualifier!";
    149  1.2  deraadt 		break;
    150  1.2  deraadt 	case 3:
    151  1.2  deraadt 		qtype = ", The Target can't support this Unit!";
    152  1.2  deraadt 		break;
    153  1.2  deraadt 	default:
    154  1.2  deraadt 		dtype = "vendor specific";
    155  1.2  deraadt 		qtype = "";
    156  1.2  deraadt 		break;
    157  1.2  deraadt 	}
    158  1.2  deraadt 
    159  1.2  deraadt 	if (dtype == NULL) {
    160  1.2  deraadt 		switch(inqbuf.device_type) {
    161  1.2  deraadt 		case T_DIRECT:
    162  1.2  deraadt 			dtype = "direct";
    163  1.2  deraadt 			break;
    164  1.2  deraadt 		case T_SEQUENTIAL:
    165  1.2  deraadt 			dtype = "seq";
    166  1.2  deraadt 			break;
    167  1.2  deraadt 		case T_PRINTER:
    168  1.2  deraadt 			dtype = "pr";
    169  1.2  deraadt 			break;
    170  1.2  deraadt 		case T_PROCESSOR:
    171  1.2  deraadt 			dtype = "cpu";
    172  1.2  deraadt 			break;
    173  1.2  deraadt 		case T_READONLY:
    174  1.2  deraadt 			dtype = "ro";
    175  1.2  deraadt 			break;
    176  1.2  deraadt 		case T_WORM:
    177  1.2  deraadt 			dtype = "worm";
    178  1.2  deraadt 			break;
    179  1.2  deraadt 		case T_SCANNER:
    180  1.2  deraadt 			dtype = "scan";
    181  1.2  deraadt 			break;
    182  1.2  deraadt 		case T_OPTICAL:
    183  1.2  deraadt 			dtype = "optic";
    184  1.2  deraadt 			break;
    185  1.2  deraadt 		case T_CHANGER:
    186  1.2  deraadt 			dtype = "changer";
    187  1.2  deraadt 			break;
    188  1.2  deraadt 		case T_COMM:
    189  1.2  deraadt 			dtype = "comm";
    190  1.2  deraadt 			break;
    191  1.2  deraadt 		default:
    192  1.2  deraadt 			dtype = "???";
    193  1.2  deraadt 			break;
    194  1.1      cgd 		}
    195  1.1      cgd 	}
    196  1.2  deraadt 
    197  1.2  deraadt 	if(inqbuf.ansii_version > 0) {
    198  1.2  deraadt 		len = inqbuf.additional_length +
    199  1.2  deraadt 			((char *)inqbuf.unused - (char *)&inqbuf);
    200  1.2  deraadt 		if( len > sizeof(struct scsi_inquiry_data) - 1)
    201  1.2  deraadt 			len = sizeof(struct scsi_inquiry_data) - 1;
    202  1.2  deraadt 		desc = inqbuf.vendor;
    203  1.2  deraadt 		desc[len-(desc-(char *)&inqbuf)] = 0;
    204  1.2  deraadt 		strncpy(manu, inqbuf.vendor, sizeof inqbuf.vendor);
    205  1.2  deraadt 		manu[sizeof inqbuf.vendor] = '\0';
    206  1.2  deraadt 		strncpy(model, inqbuf.product, sizeof inqbuf.product);
    207  1.2  deraadt 		model[sizeof inqbuf.product] = '\0';
    208  1.3  mycroft 		strncpy(revision, inqbuf.revision, sizeof inqbuf.revision);
    209  1.3  mycroft 		revision[sizeof inqbuf.revision] = '\0';
    210  1.2  deraadt 	} else {
    211  1.2  deraadt 		desc = "early protocol device";
    212  1.2  deraadt 		strcpy(manu, "????");
    213  1.2  deraadt 		strcpy(model, "");
    214  1.3  mycroft 		strcpy(revision, "");
    215  1.2  deraadt 	}
    216  1.2  deraadt 
    217  1.2  deraadt 	if(want)
    218  1.2  deraadt 		goto print;
    219  1.2  deraadt 
    220  1.2  deraadt 	ret = selectdev(masunit, targ, lun, sw, inqbuf.device_qualifier,
    221  1.3  mycroft 		inqbuf.device_type, inqbuf.removable, manu, model, revision, type);
    222  1.2  deraadt 	if(sw->printed[targ] & (1<<lun))
    223  1.2  deraadt 		return ret;
    224  1.2  deraadt 
    225  1.2  deraadt print:
    226  1.2  deraadt 	printf("%s%d targ %d lun %d: type %d(%s) %s <%s%s%s> SCSI%d\n",
    227  1.2  deraadt 		sw->name, masunit, targ, lun,
    228  1.2  deraadt 		inqbuf.device_type, dtype,
    229  1.2  deraadt 		inqbuf.removable ? "removable" : "fixed",
    230  1.3  mycroft 		manu, model, revision, inqbuf.ansii_version);
    231  1.2  deraadt 	if(qtype[0])
    232  1.2  deraadt 		printf("%s%d targ %d lun %d: qualifier %d(%s)\n",
    233  1.2  deraadt 			sw->name, masunit, targ, lun,
    234  1.2  deraadt 			inqbuf.device_qualifier, qtype);
    235  1.2  deraadt 	return ret;
    236  1.1      cgd }
    237  1.1      cgd 
    238  1.2  deraadt void
    239  1.2  deraadt scsi_warn(int masunit, int mytarg, struct scsi_switch *sw)
    240  1.1      cgd {
    241  1.2  deraadt 	struct scsidevs *match = (struct scsidevs *)0;
    242  1.2  deraadt 	int physid;
    243  1.2  deraadt 	int targ, lun;
    244  1.1      cgd 
    245  1.2  deraadt 	for(targ=0; targ<8; targ++) {
    246  1.2  deraadt 		if(targ==mytarg)
    247  1.1      cgd 			continue;
    248  1.2  deraadt 		for(lun=0; lun<8; lun++) {
    249  1.2  deraadt 			/* check if device already used, or empty */
    250  1.2  deraadt 			if( sw->empty[targ] & (1<<lun) )
    251  1.2  deraadt 				continue;
    252  1.2  deraadt 			if( sw->used[targ] & (1<<lun) )
    253  1.2  deraadt 				continue;
    254  1.2  deraadt 
    255  1.2  deraadt 			physid = targ*8 + lun;
    256  1.2  deraadt 			match = scsi_probe(masunit, sw, physid, 0, 0);
    257  1.2  deraadt 
    258  1.2  deraadt 			if(match == (struct scsidevs *)-1) {
    259  1.2  deraadt 				if(lun==0)
    260  1.2  deraadt 					sw->empty[targ] = 0xff;
    261  1.2  deraadt 				else
    262  1.2  deraadt 					sw->empty[targ] = 0xff;
    263  1.2  deraadt 				continue;
    264  1.2  deraadt 			}
    265  1.2  deraadt 			if(match) {
    266  1.2  deraadt 				targ = physid >> 3;
    267  1.2  deraadt 				lun = physid & 7;
    268  1.2  deraadt 				if(match->flags & SC_MORE_LUS)
    269  1.2  deraadt 					sw->empty[targ] |= (1<<lun);
    270  1.2  deraadt 				else
    271  1.2  deraadt 					sw->empty[targ] = 0xff;
    272  1.2  deraadt 			}
    273  1.2  deraadt 		}
    274  1.1      cgd 	}
    275  1.1      cgd }
    276  1.1      cgd 
    277  1.2  deraadt /*
    278  1.2  deraadt  * not quite perfect. If we have two "drive ?" entries, this will
    279  1.2  deraadt  * probe through all the devices twice. It should have realized that
    280  1.2  deraadt  * any device that is not found the first time won't exist later on.
    281  1.2  deraadt  */
    282  1.2  deraadt int
    283  1.2  deraadt scsi_attach(int masunit, int mytarg, struct scsi_switch *sw,
    284  1.2  deraadt 	int *physid, int *unit, int type)
    285  1.1      cgd {
    286  1.2  deraadt 	struct scsidevs *match = (struct scsidevs *)0;
    287  1.2  deraadt 	int targ, lun;
    288  1.2  deraadt 	int ret=0;
    289  1.2  deraadt 
    290  1.2  deraadt 	/*printf("%s%d probing at targ %d lun %d..\n",
    291  1.2  deraadt 		sw->name, masunit, *physid >> 3, *physid & 7);*/
    292  1.1      cgd 
    293  1.2  deraadt 	if( *physid!=-1 ) {
    294  1.2  deraadt 		targ = *physid >> 3;
    295  1.2  deraadt 		lun = *physid & 7;
    296  1.1      cgd 
    297  1.2  deraadt 		if( (sw->empty[targ] & (1<<lun)) || (sw->used[targ] & (1<<lun)) )
    298  1.5  deraadt 			return 0;
    299  1.1      cgd 
    300  1.2  deraadt 		match = scsi_probe(masunit, sw, *physid, type, 0);
    301  1.2  deraadt 		if(match == (struct scsidevs *)-1) {
    302  1.2  deraadt 			match = (struct scsidevs *)0;
    303  1.2  deraadt 			if(lun==0)
    304  1.2  deraadt 				sw->empty[targ] = 0xff;
    305  1.2  deraadt 			else
    306  1.2  deraadt 				sw->empty[targ] |= (1<<lun);
    307  1.5  deraadt 			return 0;
    308  1.2  deraadt 		}
    309  1.1      cgd 
    310  1.2  deraadt 		sw->printed[targ] |= (1<<lun);
    311  1.2  deraadt 		if(!match)
    312  1.5  deraadt 			return 0;
    313  1.1      cgd 
    314  1.6  deraadt 		ret = (*(match->attach_rtn))(masunit, sw, *physid, unit);
    315  1.2  deraadt 		goto success;
    316  1.1      cgd 	}
    317  1.1      cgd 
    318  1.2  deraadt 	for(targ=0; targ<8; targ++) {
    319  1.2  deraadt 		if(targ==mytarg)
    320  1.2  deraadt 			continue;
    321  1.2  deraadt 		for(lun=0; lun<8; lun++) {
    322  1.2  deraadt 			if( (sw->empty[targ] & (1<<lun)) || (sw->used[targ] & (1<<lun)) )
    323  1.2  deraadt 				continue;
    324  1.2  deraadt 
    325  1.2  deraadt 			*physid = targ*8 + lun;
    326  1.2  deraadt 			match = scsi_probe(masunit, sw, *physid, type, 0);
    327  1.2  deraadt 			if( match==(struct scsidevs *)-1) {
    328  1.2  deraadt 				if(lun==0)
    329  1.2  deraadt 					sw->empty[targ] = 0xff;
    330  1.2  deraadt 				else
    331  1.2  deraadt 					sw->empty[targ] |= (1<<lun);
    332  1.2  deraadt 				match = (struct scsidevs *)0;
    333  1.2  deraadt 				continue;
    334  1.2  deraadt 			}
    335  1.2  deraadt 			if(!match) {
    336  1.2  deraadt 				sw->printed[targ] |= (1<<lun);
    337  1.4  deraadt 				break;
    338  1.2  deraadt 			}
    339  1.6  deraadt 			ret = (*(match->attach_rtn))(masunit, sw, *physid, unit);
    340  1.5  deraadt 			if(ret)
    341  1.2  deraadt 				goto success;
    342  1.5  deraadt 			return 0;
    343  1.2  deraadt 		}
    344  1.2  deraadt 	}
    345  1.2  deraadt 	*physid = -1;	/* failed... */
    346  1.5  deraadt 	return 0;
    347  1.2  deraadt 
    348  1.2  deraadt success:
    349  1.2  deraadt 	targ = *physid >> 3;
    350  1.2  deraadt 	lun = *physid & 7;
    351  1.2  deraadt 	if(match->flags & SC_MORE_LUS) {
    352  1.2  deraadt 		sw->used[targ] |= (1<<lun);
    353  1.2  deraadt 		sw->printed[targ] |= (1<<lun);
    354  1.2  deraadt 	} else {
    355  1.2  deraadt 		sw->used[targ] = 0xff;
    356  1.2  deraadt 		sw->printed[targ] = 0xff;
    357  1.1      cgd 	}
    358  1.5  deraadt 	return ret;
    359  1.1      cgd }
    360  1.1      cgd 
    361  1.2  deraadt /*
    362  1.2  deraadt  * Try make as good a match as possible with
    363  1.2  deraadt  * available sub drivers
    364  1.2  deraadt  */
    365  1.2  deraadt struct scsidevs *
    366  1.2  deraadt selectdev(int unit, int target, int lu, struct scsi_switch *sw, int qual,
    367  1.2  deraadt 	int dtype, int remov, char *manu, char *model, char *rev, int type)
    368  1.2  deraadt {
    369  1.2  deraadt 	struct scsidevs *sdbest = (struct scsidevs *)0;
    370  1.2  deraadt 	struct scsidevs *sdent = knowndevs;
    371  1.2  deraadt 	int numents = sizeof(knowndevs)/sizeof(struct scsidevs);
    372  1.2  deraadt 	int count = 0, sdbestes = 0;
    373  1.2  deraadt 
    374  1.2  deraadt 	dtype |= (qual << 5);
    375  1.2  deraadt 
    376  1.2  deraadt 	sdent--;
    377  1.2  deraadt 	while( count++ < numents) {
    378  1.2  deraadt 		sdent++;
    379  1.2  deraadt 		if(dtype != sdent->dtype)
    380  1.2  deraadt 			continue;
    381  1.2  deraadt 		if(type != sdent->type)
    382  1.1      cgd 			continue;
    383  1.2  deraadt 		if(sdbestes < 1) {
    384  1.2  deraadt 			sdbestes = 1;
    385  1.2  deraadt 			sdbest = sdent;
    386  1.1      cgd 		}
    387  1.2  deraadt 		if(remov != sdent->removable)
    388  1.1      cgd 			continue;
    389  1.2  deraadt 		if(sdbestes < 2) {
    390  1.2  deraadt 			sdbestes = 2;
    391  1.2  deraadt 			sdbest = sdent;
    392  1.2  deraadt 		}
    393  1.2  deraadt 		if(sdent->flags & SC_SHOWME)
    394  1.2  deraadt 			printf("\n%s-\n%s-", sdent->manufacturer, manu);
    395  1.2  deraadt 		if(strcmp(sdent->manufacturer, manu))
    396  1.1      cgd 			continue;
    397  1.2  deraadt 		if(sdbestes < 3) {
    398  1.2  deraadt 			sdbestes = 3;
    399  1.2  deraadt 			sdbest = sdent;
    400  1.2  deraadt 		}
    401  1.2  deraadt 		if(sdent->flags & SC_SHOWME)
    402  1.2  deraadt 			printf("\n%s-\n%s-",sdent->model, model);
    403  1.2  deraadt 		if(strcmp(sdent->model, model))
    404  1.1      cgd 			continue;
    405  1.2  deraadt 		if(sdbestes < 4) {
    406  1.2  deraadt 			sdbestes = 4;
    407  1.2  deraadt 			sdbest = sdent;
    408  1.2  deraadt 		}
    409  1.2  deraadt 		if(sdent->flags & SC_SHOWME)
    410  1.2  deraadt 			printf("\n%s-\n%s-",sdent->version, rev);
    411  1.2  deraadt 		if(strcmp(sdent->version, rev))
    412  1.1      cgd 			continue;
    413  1.2  deraadt 		if(sdbestes < 5) {
    414  1.2  deraadt 			sdbestes = 5;
    415  1.2  deraadt 			sdbest = sdent;
    416  1.1      cgd 			break;
    417  1.1      cgd 		}
    418  1.1      cgd 	}
    419  1.2  deraadt 	return sdbest;
    420  1.1      cgd }
    421  1.1      cgd 
    422  1.2  deraadt /*
    423  1.2  deraadt  * Do a scsi operation asking a device if it is
    424  1.2  deraadt  * ready. Use the scsi_cmd routine in the switch
    425  1.2  deraadt  * table.
    426  1.2  deraadt  */
    427  1.2  deraadt int
    428  1.2  deraadt scsi_ready(int unit, int target, int lu,
    429  1.2  deraadt 	struct scsi_switch *sw, int flags)
    430  1.1      cgd {
    431  1.2  deraadt 	struct scsi_test_unit_ready scsi_cmd;
    432  1.2  deraadt 	struct scsi_xfer scsi_xfer;
    433  1.1      cgd 	volatile int rval;
    434  1.2  deraadt 	int key;
    435  1.1      cgd 
    436  1.1      cgd 	bzero(&scsi_cmd, sizeof(scsi_cmd));
    437  1.1      cgd 	bzero(&scsi_xfer, sizeof(scsi_xfer));
    438  1.1      cgd 	scsi_cmd.op_code = TEST_UNIT_READY;
    439  1.1      cgd 
    440  1.2  deraadt 	scsi_xfer.flags = flags | INUSE;
    441  1.2  deraadt 	scsi_xfer.adapter = unit;
    442  1.2  deraadt 	scsi_xfer.targ = target;
    443  1.2  deraadt 	scsi_xfer.lu = lu;
    444  1.2  deraadt 	scsi_xfer.cmd = (struct scsi_generic *)&scsi_cmd;
    445  1.2  deraadt 	scsi_xfer.retries = 8;
    446  1.2  deraadt 	scsi_xfer.timeout = 10000;
    447  1.2  deraadt 	scsi_xfer.cmdlen = sizeof(scsi_cmd);
    448  1.2  deraadt 	scsi_xfer.data = 0;
    449  1.2  deraadt 	scsi_xfer.datalen = 0;
    450  1.2  deraadt 	scsi_xfer.resid = 0;
    451  1.2  deraadt 	scsi_xfer.when_done = 0;
    452  1.2  deraadt 	scsi_xfer.done_arg = 0;
    453  1.2  deraadt retry:	scsi_xfer.error = 0;
    454  1.2  deraadt 
    455  1.2  deraadt 	/* don't use interrupts! */
    456  1.2  deraadt 
    457  1.2  deraadt 	rval = (*(sw->scsi_cmd))(&scsi_xfer);
    458  1.2  deraadt 	if (rval != COMPLETE) {
    459  1.2  deraadt 		if(scsi_debug) {
    460  1.2  deraadt 			printf("scsi error, rval = 0x%x\n", rval);
    461  1.2  deraadt 			printf("code from driver: 0x%x\n", scsi_xfer.error);
    462  1.2  deraadt 		}
    463  1.2  deraadt 		switch(scsi_xfer.error) {
    464  1.2  deraadt 		case XS_SENSE:
    465  1.2  deraadt 			/*
    466  1.2  deraadt 			 * Any sense value is illegal except UNIT ATTENTION
    467  1.2  deraadt 			 * In which case we need to check again to get the
    468  1.2  deraadt 			 * correct response. (especially exabytes)
    469  1.2  deraadt 			 */
    470  1.2  deraadt 			if(scsi_xfer.sense.error_class == 7 ) {
    471  1.1      cgd 				key = scsi_xfer.sense.ext.extended.sense_key ;
    472  1.2  deraadt 				switch(key) {
    473  1.2  deraadt 				case 2:	/* not ready BUT PRESENT! */
    474  1.2  deraadt 					return(COMPLETE);
    475  1.2  deraadt 				case 6:
    476  1.1      cgd 					spinwait(1000);
    477  1.2  deraadt 					if(scsi_xfer.retries--) {
    478  1.1      cgd 						scsi_xfer.flags &= ~ITSDONE;
    479  1.1      cgd 						goto retry;
    480  1.1      cgd 					}
    481  1.1      cgd 					return(COMPLETE);
    482  1.1      cgd 				default:
    483  1.1      cgd 					if(scsi_debug)
    484  1.2  deraadt 						printf("%d:%d,key=%x.", target,
    485  1.2  deraadt 							lu, key);
    486  1.1      cgd 				}
    487  1.1      cgd 			}
    488  1.1      cgd 			return(HAD_ERROR);
    489  1.2  deraadt 		case XS_BUSY:
    490  1.1      cgd 			spinwait(1000);
    491  1.2  deraadt 			if(scsi_xfer.retries--) {
    492  1.1      cgd 				scsi_xfer.flags &= ~ITSDONE;
    493  1.1      cgd 				goto retry;
    494  1.1      cgd 			}
    495  1.2  deraadt 			return COMPLETE;	/* it's busy so it's there */
    496  1.2  deraadt 		case XS_TIMEOUT:
    497  1.1      cgd 		default:
    498  1.2  deraadt 			return HAD_ERROR;
    499  1.1      cgd 		}
    500  1.1      cgd 	}
    501  1.2  deraadt 	return COMPLETE;
    502  1.1      cgd }
    503  1.2  deraadt 
    504  1.2  deraadt /*
    505  1.2  deraadt  * Do a scsi operation asking a device what it is
    506  1.2  deraadt  * Use the scsi_cmd routine in the switch table.
    507  1.2  deraadt  */
    508  1.2  deraadt int
    509  1.2  deraadt scsi_inquire(int unit, int target, int lu, struct scsi_switch *sw,
    510  1.2  deraadt 	u_char *inqbuf, int flags)
    511  1.1      cgd {
    512  1.2  deraadt 	struct scsi_inquiry scsi_cmd;
    513  1.2  deraadt 	struct scsi_xfer scsi_xfer;
    514  1.1      cgd 
    515  1.1      cgd 	bzero(&scsi_cmd, sizeof(scsi_cmd));
    516  1.1      cgd 	bzero(&scsi_xfer, sizeof(scsi_xfer));
    517  1.1      cgd 	scsi_cmd.op_code = INQUIRY;
    518  1.1      cgd 	scsi_cmd.length = sizeof(struct scsi_inquiry_data);
    519  1.1      cgd 
    520  1.2  deraadt 	scsi_xfer.flags = flags | SCSI_DATA_IN | INUSE;
    521  1.2  deraadt 	scsi_xfer.adapter = unit;
    522  1.2  deraadt 	scsi_xfer.targ = target;
    523  1.2  deraadt 	scsi_xfer.lu = lu;
    524  1.2  deraadt 	scsi_xfer.retries = 8;
    525  1.2  deraadt 	scsi_xfer.timeout = 10000;
    526  1.2  deraadt 	scsi_xfer.cmd = (struct scsi_generic *)&scsi_cmd;
    527  1.2  deraadt 	scsi_xfer.cmdlen =  sizeof(struct scsi_inquiry);
    528  1.2  deraadt 	scsi_xfer.data = inqbuf;
    529  1.2  deraadt 	scsi_xfer.datalen = sizeof(struct scsi_inquiry_data);
    530  1.2  deraadt 	scsi_xfer.resid = sizeof(struct scsi_inquiry_data);
    531  1.2  deraadt 	scsi_xfer.when_done = 0;
    532  1.2  deraadt 	scsi_xfer.done_arg = 0;
    533  1.2  deraadt 
    534  1.2  deraadt retry:
    535  1.2  deraadt 	scsi_xfer.error=0;
    536  1.2  deraadt 	/* don't use interrupts! */
    537  1.2  deraadt 
    538  1.2  deraadt 	if ((*(sw->scsi_cmd))(&scsi_xfer) != COMPLETE) {
    539  1.2  deraadt 		if(scsi_debug)
    540  1.2  deraadt 			printf("inquiry had error(0x%x) ",scsi_xfer.error);
    541  1.2  deraadt 		switch(scsi_xfer.error) {
    542  1.2  deraadt 		case XS_NOERROR:
    543  1.2  deraadt 			break;
    544  1.2  deraadt 		case XS_SENSE:
    545  1.2  deraadt 			/*
    546  1.2  deraadt 			 * Any sense value is illegal except UNIT ATTENTION
    547  1.2  deraadt 			 * In which case we need to check again to get the
    548  1.2  deraadt 			 * correct response. (especially exabytes)
    549  1.2  deraadt 			 */
    550  1.2  deraadt 			if( scsi_xfer.sense.error_class==7 &&
    551  1.2  deraadt 			    scsi_xfer.sense.ext.extended.sense_key==6) {
    552  1.2  deraadt 				/* it's changed so it's there */
    553  1.1      cgd 				spinwait(1000);
    554  1.2  deraadt 				if(scsi_xfer.retries--) {
    555  1.2  deraadt 					scsi_xfer.flags &= ~ITSDONE;
    556  1.2  deraadt 					goto retry;
    557  1.1      cgd 				}
    558  1.2  deraadt 				return COMPLETE;
    559  1.1      cgd 			}
    560  1.2  deraadt 			return HAD_ERROR;
    561  1.2  deraadt 		case XS_BUSY:
    562  1.1      cgd 			spinwait(1000);
    563  1.2  deraadt 			if(scsi_xfer.retries--) {
    564  1.1      cgd 				scsi_xfer.flags &= ~ITSDONE;
    565  1.1      cgd 				goto retry;
    566  1.1      cgd 			}
    567  1.2  deraadt 		case XS_TIMEOUT:
    568  1.1      cgd 		default:
    569  1.1      cgd 			return(HAD_ERROR);
    570  1.1      cgd 		}
    571  1.1      cgd 	}
    572  1.2  deraadt 	return COMPLETE;
    573  1.1      cgd }
    574  1.1      cgd 
    575  1.2  deraadt /*
    576  1.2  deraadt  * convert a physical address to 3 bytes,
    577  1.2  deraadt  * MSB at the lowest address,
    578  1.2  deraadt  * LSB at the highest.
    579  1.2  deraadt  */
    580  1.2  deraadt void
    581  1.2  deraadt lto3b(u_long val, u_char *bytes)
    582  1.1      cgd {
    583  1.1      cgd 	*bytes++ = (val&0xff0000)>>16;
    584  1.1      cgd 	*bytes++ = (val&0xff00)>>8;
    585  1.1      cgd 	*bytes = val&0xff;
    586  1.1      cgd }
    587  1.1      cgd 
    588  1.2  deraadt /*
    589  1.2  deraadt  * The reverse of lto3b
    590  1.2  deraadt  */
    591  1.2  deraadt u_long
    592  1.2  deraadt _3btol(u_char *bytes)
    593  1.1      cgd {
    594  1.2  deraadt 	u_long rc;
    595  1.2  deraadt 
    596  1.1      cgd 	rc = (*bytes++ << 16);
    597  1.1      cgd 	rc += (*bytes++ << 8);
    598  1.1      cgd 	rc += *bytes;
    599  1.2  deraadt 	return rc;
    600  1.1      cgd }
    601  1.1      cgd 
    602