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