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