FreeBSD/Linux Kernel Cross Reference
sys/scsi/scsiconf.c
1 /*
2 * Written by Julian Elischer (julian@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 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
16 *
17 * New configuration setup: dufault@hda.com
18 *
19 * $FreeBSD: src/sys/scsi/scsiconf.c,v 1.64.2.27 1999/09/05 08:21:46 peter Exp $
20 */
21
22 #include "opt_scsi.h"
23
24 #include <sys/types.h>
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/stat.h>
28 #include <sys/malloc.h>
29 #include <sys/conf.h>
30 #ifdef PC98
31 #include <sys/device.h>
32 #endif
33
34 #include <machine/clock.h>
35
36 #include "scbus.h"
37
38 #include "sd.h"
39 #include "st.h"
40 #include "cd.h"
41 #include "ch.h"
42 #include "od.h"
43 #include "worm.h"
44
45 #include "su.h"
46 #include "sctarg.h"
47
48 #include <scsi/scsi_all.h>
49 #include <scsi/scsiconf.h>
50
51 static struct extend_array *extend_new __P((void));
52 static void extend_release __P((struct extend_array *ea, int index));
53 static void *extend_set __P((struct extend_array *ea, int index, void *value));
54
55 /*
56 * XXX SCSI_DEVICE_ENTRIES() generates extern switches but it should
57 * generate static switches except for this. Separate macros are
58 * probably required for the extern and static parts.
59 */
60 extern struct scsi_device uk_switch;
61
62 /***********************************************************************
63 * Extensible arrays: Use a realloc like implementation to permit
64 * the arrays to be extend. These are set up to be moved out
65 * of this file if needed elsewhere.
66 */
67 struct extend_array
68 {
69 int nelem;
70 void **ps;
71 };
72
73 static void make_readable __P((char *to, char *from, size_t n));
74 static int match __P((char *pattern, char *name));
75 static int scsi_bus_conf __P((struct scsi_link *sc_link_proto));
76
77 static void *
78 extend_alloc(size_t s)
79 {
80 void *p = malloc(s, M_DEVBUF, M_NOWAIT);
81 if (!p)
82 panic("extend_alloc: malloc failed.");
83 return p;
84 }
85
86 static void
87 extend_free(void *p) { free(p, M_DEVBUF); }
88
89 /* EXTEND_CHUNK: Number of extend slots to allocate whenever we need a new
90 * one.
91 */
92 #ifndef EXTEND_CHUNK
93 #define EXTEND_CHUNK 8
94 #endif
95
96 static struct extend_array *
97 extend_new(void)
98 {
99 struct extend_array *p = extend_alloc(sizeof(*p));
100 if (p) {
101 p->nelem = 0;
102 p->ps = 0;
103 }
104
105 return p;
106 }
107
108 static void *
109 extend_set(struct extend_array *ea, int index, void *value)
110 {
111 if (index >= ea->nelem) {
112 void **space;
113 space = extend_alloc(sizeof(void *) * (index + EXTEND_CHUNK));
114 bzero(space, sizeof(void *) * (index + EXTEND_CHUNK));
115
116 /* Make sure we have something to copy before we copy it */
117 if (ea->nelem) {
118 bcopy(ea->ps, space, sizeof(void *) * ea->nelem);
119 extend_free(ea->ps);
120 }
121
122 ea->ps = space;
123 ea->nelem = index + EXTEND_CHUNK;
124 }
125 if (ea->ps[index]) {
126 printf("extend_set: entry %d already has storage.\n", index);
127 return 0;
128 }
129 else
130 ea->ps[index] = value;
131
132 return value;
133 }
134
135 void *
136 extend_get(struct extend_array *ea, int index)
137 {
138 if (ea == NULL || index >= ea->nelem || index < 0)
139 return NULL;
140 return ea->ps[index];
141 }
142
143 static void
144 extend_release(struct extend_array *ea, int index)
145 {
146 void *p = extend_get(ea, index);
147 if (p) {
148 ea->ps[index] = 0;
149 }
150 }
151
152 /***********************************************************************
153 * This extend_array holds an array of "scsibus_data" pointers.
154 * One of these is allocated and filled in for each scsi bus.
155 * it holds pointers to allow the scsi bus to get to the driver
156 * that is running each LUN on the bus
157 * it also has a template entry which is the prototype struct
158 * supplied by the adapter driver, this is used to initialise
159 * the others, before they have the rest of the fields filled in
160 */
161
162 static struct extend_array *scbusses;
163
164 /*
165 * The structure of known drivers for autoconfiguration
166 */
167 struct scsidevs {
168 u_int32_t type;
169 u_int32_t driver; /* normally the same as type */
170 boolean removable;
171 char *manufacturer;
172 char *model;
173 char *version;
174 char *devname;
175 char flags; /* 1 show my comparisons during boot(debug) */
176 u_int16_t quirks;
177 void *devmodes;
178 };
179
180 #define SC_SHOWME 0x01
181 #define SC_ONE_LU 0x00
182 #define SC_MORE_LUS 0x02
183
184 static struct scsidevs unknowndev =
185 {
186 T_UNKNOWN, T_UNKNOWN, 0, "*", "*", "*",
187 "uk", SC_MORE_LUS
188 };
189 static st_modes mode_tandberg3600 =
190 {
191 {0, 0, 0}, /* minor 0,1,2,3 */
192 {0, ST_Q_FORCE_VAR_MODE, QIC_525}, /* minor 4,5,6,7 */
193 {0, 0, QIC_150}, /* minor 8,9,10,11 */
194 {0, 0, QIC_120} /* minor 12,13,14,15 */
195 };
196 static st_modes mode_tandberg4200 =
197 {
198 {0, 0, 0}, /* minor 0,1,2,3 */
199 {0, ST_Q_FORCE_VAR_MODE, 0}, /* minor 4,5,6,7 */
200 {0, 0, QIC_150}, /* minor 8,9,10,11 */
201 {0, 0, QIC_120} /* minor 12,13,14,15 */
202 };
203 static st_modes mode_archive2525 =
204 {
205 {0, ST_Q_SNS_HLP, 0}, /* minor 0,1,2,3 */
206 {0, ST_Q_SNS_HLP, QIC_525}, /* minor 4,5,6,7 */
207 {0, 0, QIC_150}, /* minor 8,9,10,11 */
208 {0, 0, QIC_120} /* minor 12,13,14,15 */
209 };
210 static st_modes mode_archive150 =
211 {
212 {0, 0, 0}, /* minor 0,1,2,3 */
213 {0, 0, QIC_150}, /* minor 4,5,6,7 */
214 {0, 0, QIC_120}, /* minor 8,9,10,11 */
215 {0, 0, QIC_24} /* minor 12,13,14,15 */
216 };
217 static st_modes mode_wangtek5525 =
218 {
219 {0, 0, 0}, /* minor 0,1,2,3 */
220 {0, ST_Q_BLKSIZ, QIC_525}, /* minor 4,5,6,7 */
221 {0, 0, QIC_150}, /* minor 8,9,10,11 */
222 {0, 0, QIC_120} /* minor 12,13,14,15 */
223 };
224 static st_modes mode_wangdat1300 =
225 {
226 {0, 0, 0}, /* minor 0,1,2,3 */
227 {512, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 4,5,6,7 */
228 {1024, ST_Q_FORCE_FIXED_MODE, DDS}, /* minor 8,9,10,11 */
229 {0, ST_Q_FORCE_VAR_MODE, DDS} /* minor 12,13,14,15 */
230 };
231 static st_modes mode_unktape =
232 {
233 {0, 0, 0}, /* minor 0,1,2,3 */
234 {512, ST_Q_FORCE_FIXED_MODE, QIC_24}, /* minor 4,5,6,7 */
235 {0, ST_Q_FORCE_VAR_MODE, HALFINCH_1600}, /* minor 8,9,10,11 */
236 {0, ST_Q_FORCE_VAR_MODE, HALFINCH_6250} /* minor 12,13,14,15 */
237 };
238
239 /***********************************************************************
240 * A list of known devices and their "quirks". Matching is based
241 * first on device type, then on the manufacturer, model, and revision
242 * strings returned by the device. The returned strings are fixed lengths
243 * of 8, 16 and 4 bytes respectively. In the matching pattern, a
244 * question mark (?) matches any single character and a trailing
245 * asterisk (*) matches remaining characters. For patterns shorter
246 * than their respective fields, trailing spaces are implied.
247 */
248
249 static struct scsidevs knowndevs[] =
250 {
251 #if NOD > 0
252 {
253 T_OPTICAL, T_OPTICAL, T_REMOV, "MATSHITA", "PD-1 LF-100*", "*",
254 "od", SC_MORE_LUS
255 },
256 {
257 T_DIRECT, T_OPTICAL, T_REMOV, "SONY", "SMO-*", "*",
258 "od", SC_MORE_LUS
259 },
260 {
261 T_DIRECT, T_OPTICAL, T_REMOV, "MOST", "RMD-5200-S", "*",
262 "od", SC_ONE_LU
263 },
264 {
265 T_DIRECT, T_OPTICAL, T_REMOV, "RICOH", "RO-*", "*",
266 "od", SC_ONE_LU
267 },
268 #endif /* NOD */
269 #if NSD > 0
270 {
271 T_DIRECT, T_DIRECT, T_FIXED, "EMULEX", "MD21*" , "*",
272 "sd", SC_MORE_LUS
273 },
274 {
275 T_DIRECT, T_DIRECT, T_FIXED, "IFT", "*" , "*",
276 "sd", SC_MORE_LUS
277 },
278 {
279 T_DIRECT, T_DIRECT, T_REMOV, "iomega", "jaz*", "*",
280 "sd", SC_ONE_LU, SD_Q_NO_TAGS
281 },
282 #endif /* NSD */
283 #if NST > 0
284 {
285 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 3600", "*",
286 "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_tandberg3600
287 },
288 {
289 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "TANDBERG", " TDC 42*", "*",
290 "st", SC_ONE_LU, ST_Q_SNS_HLP|ST_Q_NO_1024, mode_tandberg4200
291 },
292 {
293 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 2525*", "-005",
294 "st", SC_ONE_LU, 0, mode_archive2525
295 },
296 {
297 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "VIPER 150 *", "*",
298 "st", SC_ONE_LU, ST_Q_NEEDS_PAGE_0, mode_archive150
299 },
300 {
301 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WANGTEK", "5525ES*", "*",
302 "st", SC_ONE_LU, 0, mode_wangtek5525
303 },
304 {
305 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "WangDAT", "Model 1300", "*",
306 "st", SC_ONE_LU, 0, mode_wangdat1300
307 },
308 {
309 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "DEC", "DLT2700", "*",
310 "st", SC_MORE_LUS, 0
311 },
312 {
313 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "Quantum", "DLT*", "*",
314 "st", SC_MORE_LUS, 0
315 },
316 {
317 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SUN", "DLT*", "*",
318 "st", SC_MORE_LUS, 0
319 },
320 {
321 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1553A*", "*",
322 "st", SC_MORE_LUS, 0
323 },
324 {
325 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "HP", "C1557A", "*",
326 "st", SC_MORE_LUS, 0
327 },
328 {
329 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
330 "st", SC_MORE_LUS, 0
331 },
332 {
333 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
334 "st", SC_MORE_LUS, 0
335 },
336 {
337 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "SONY", "TSL-7000", "*",
338 "st", SC_MORE_LUS, 0
339 },
340 #endif /* NST */
341 #if NCH > 0
342 /*
343 * The <ARCHIVE, Python 28849-XXX, 4.98> is a SCSI changer device
344 * with an Archive Python DAT drive built-in. The tape appears
345 * at LUN 0 and the changer at LUN 1.
346 * This entry should not be needed at all.
347 */
348 {
349 T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "Python 28849-*", "*",
350 "ch", SC_MORE_LUS
351 },
352 {
353 T_CHANGER, T_CHANGER, T_REMOV, "ARCHIVE", "4586XX 28887-*", "*",
354 "ch", SC_MORE_LUS
355 },
356 {
357 T_CHANGER, T_CHANGER, T_REMOV, "SONY", "TSL-7000", "*",
358 "ch", SC_MORE_LUS
359 },
360 #endif /* NCH */
361 #if NCD > 0
362 #ifndef UKTEST /* make cdroms unrecognised to test the uk driver */
363 /*
364 * CDU-8003A aka Apple CDROM-300.
365 */
366 {
367 T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8003A", "1.9a",
368 "cd", SC_ONE_LU
369 },
370 {
371 T_READONLY, T_READONLY, T_REMOV, "SONY", "CD-ROM CDU-8012", "3.1a",
372 "cd", SC_ONE_LU
373 },
374 {
375 T_READONLY, T_READONLY, T_REMOV, "PIONEER", "CD-ROM DRM-6??*" ,"*",
376 "cd", SC_MORE_LUS, CD_Q_NO_TOUCH
377 },
378 {
379 T_READONLY, T_READONLY, T_REMOV, "NRC", "MBR-7*" ,"*",
380 "cd", SC_MORE_LUS
381 },
382 {
383 T_READONLY, T_READONLY, T_REMOV, "CHINON", "CD-ROM CDS-535","*",
384 "cd", SC_ONE_LU, CD_Q_BCD_TRACKS
385 },
386 /*
387 * Note: My drive with v1.0 firmware "forgets" to generate scsi parity
388 * when answering probes.. :-( EVIL!! You need to disable scsi parity
389 * checking in order to find out that it answers to all 7 LUNS. :-(
390 * -Peter
391 */
392 {
393 T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:55","*",
394 "cd", SC_ONE_LU
395 },
396 /*
397 * Same with the OEM version of this drive (1.0 firmware).
398 * -Paul
399 */
400 {
401 T_READONLY, T_READONLY, T_REMOV, "NEC", "CD-ROM DRIVE:210","*",
402 "cd", SC_ONE_LU
403 },
404 /*
405 * Doobe-doo-be doooo
406 * -Mary
407 */
408 {
409 T_READONLY, T_READONLY, T_REMOV, "NAKAMICH", "MJ-*" ,"*",
410 "cd", SC_MORE_LUS
411 },
412 /* yet another changer */
413 {
414 T_READONLY, T_READONLY, T_REMOV, "REGAL", "CDC-4*" ,"*",
415 "cd", SC_MORE_LUS
416 },
417 /* IODATA CD-C68E 6 CD changer */
418 {
419 T_READONLY, T_READONLY, T_REMOV, "IODATA", "CD-C68E" ,"*",
420 "cd", SC_MORE_LUS
421 },
422 #endif /* !UKTEST */
423 #endif /* NCD */
424 #if NWORM > 0
425 {
426 T_READONLY, T_WORM, T_REMOV, "HP", "C4324/C4325", "*",
427 "worm", SC_ONE_LU
428 },
429 {
430 T_READONLY, T_WORM, T_REMOV, "HP", "CD-Writer 6020", "*",
431 "worm", SC_ONE_LU
432 },
433 {
434 /* That's the Philips drive, in case anybody wonders... */
435 T_READONLY, T_WORM, T_REMOV, "IMS", "CDD2000*", "*",
436 "worm", SC_ONE_LU
437 },
438 {
439 /* Here's another Philips drive... */
440 T_READONLY, T_WORM, T_REMOV, "PHILIPS", "CDD2*", "*",
441 "worm", SC_ONE_LU
442 },
443 /*
444 * The Plasmon's are dual-faced: they appear as T_WORM if the
445 * drive is empty, or a CD-R medium is in the drive, and they
446 * announce theirselves as T_READONLY if a CD-ROM (or fixated
447 * CD-R) is there. This record catches the latter case, while
448 * the former one falls under the terms of the generic T_WORM
449 * below.
450 */
451 {
452 T_READONLY, T_WORM, T_REMOV, "PLASMON", "RF41*", "*",
453 "worm", SC_ONE_LU
454 },
455 #endif /* NWORM */
456
457 /*
458 * Wildcard entries. Keep them down here below all device
459 * specific entries, so the above ones can override the type
460 * driver if necessary.
461 */
462 #if NOD > 0
463 {
464 T_OPTICAL, T_OPTICAL, T_REMOV, "*", "*", "*",
465 "od", SC_ONE_LU
466 },
467 #endif /* NOD */
468 #if NSD > 0
469 {
470 T_DIRECT, T_DIRECT, T_FIXED, "*", "*", "*",
471 "sd", SC_ONE_LU
472 },
473 {
474 T_DIRECT, T_DIRECT, T_REMOV, "*", "*", "*",
475 "sd", SC_ONE_LU
476 },
477 #endif /* NSD */
478 #if NST > 0
479 {
480 T_SEQUENTIAL, T_SEQUENTIAL, T_REMOV, "*", "*", "*",
481 "st", SC_ONE_LU, 0, mode_unktape
482 },
483 #endif /* NST */
484 #if NCH > 0
485 /*
486 * Due to the way media changers are working, they are most
487 * likely always on a different LUN than the transfer element
488 * device. Thus, it should be safe to always probe all LUNs
489 * on them.
490 */
491 {
492 T_CHANGER, T_CHANGER, T_REMOV, "*", "*", "*",
493 "ch", SC_MORE_LUS
494 },
495 #endif /* NCH */
496 #if NCD > 0 && !defined(UKTEST)
497 {
498 T_READONLY, T_READONLY, T_REMOV, "*", "*", "*",
499 "cd", SC_ONE_LU
500 },
501 #endif /* NCD */
502 #if NWORM > 0
503 {
504 T_WORM, T_WORM, T_REMOV, "*", "*", "*",
505 "worm", SC_ONE_LU
506 },
507 #endif /* NWORM */
508 {
509 0
510 }
511 };
512
513 /*
514 * Declarations
515 */
516 static struct scsidevs *scsi_probedev __P((struct scsi_link *sc_link,
517 boolean *maybe_more, int *type_p));
518 static struct scsidevs *scsi_selectdev __P((u_int32_t qualifier, u_int32_t type,
519 boolean remov, char *manu, char *model,
520 char *rev));
521
522 /* XXX dufault@hda.com
523 * This scsi_device doesn't have the scsi_data_size.
524 * This is used during probe.
525 */
526 static struct scsi_device probe_switch =
527 {
528 NULL,
529 NULL,
530 NULL,
531 NULL,
532 "probe",
533 };
534
535 static int free_bus; /* First bus not wired down */
536
537 static struct scsi_device *device_list;
538 static int next_free_type = T_NTYPES;
539
540 /* Register new functions at the head of the list. That allows
541 * you to replace a standard driver with a new one.
542 *
543 * You can't register the exact device (the same in memory structure)
544 * more than once - the list links are part of the structure. That is
545 * prevented.
546 *
547 * Custom devices should always be registered as type "-1". Then
548 * the next available type number will be allocated for it.
549 *
550 * Be careful not to register a type as 0 unless you really mean to
551 * replace the disk driver.
552 *
553 * This is usually called only by the "device_init" function generated
554 * automatically in the SCSI_DEVICE_ENTRIES macro.
555 */
556
557 void
558 scsi_device_register(struct scsi_device *sd)
559 {
560 /* Not only is it pointless to add the same device more than once
561 * but it will also screw up the list.
562 */
563 struct scsi_device *is_there;
564 for (is_there = device_list; is_there; is_there = is_there->next)
565 if (is_there == sd)
566 return;
567
568 if (sd->type == -1)
569 sd->type = next_free_type++;
570
571 sd->next = device_list;
572 device_list = sd;
573
574 if (sd->links == 0)
575 sd->links = extend_new();
576 }
577
578 static struct scsi_device *
579 scsi_device_lookup(int type)
580 {
581 struct scsi_device *sd;
582
583 for (sd = device_list; sd; sd = sd->next)
584 if (sd->type == type)
585 return sd;
586
587 return &uk_switch;
588 }
589
590 static struct scsi_device *
591 scsi_device_lookup_by_name(char *name)
592 {
593 struct scsi_device *sd;
594
595 for (sd = device_list; sd; sd = sd->next)
596 if (strcmp(sd->name, name) == 0)
597 return sd;
598
599 return &uk_switch;
600 }
601
602 /* Macro that lets us know something is specified.
603 */
604 #define IS_SPECIFIED(ARG) (ARG != SCCONF_UNSPEC && ARG != SCCONF_ANY)
605
606 /* scsi_init: Do all the one time processing. This initializes the
607 * type drivers and initializes the configuration.
608 */
609 static void
610 scsi_init(void)
611 {
612 static int done = 0;
613 if(!done) {
614 int i;
615
616 done = 1;
617
618 scbusses = extend_new();
619
620 /* First call all type initialization functions.
621 */
622 ukinit(); /* We always have the unknown device. */
623
624 for (i = 0; scsi_tinit[i]; i++)
625 (*scsi_tinit[i])();
626
627 /* Lowest free bus for auto-configure is one
628 * more than the first one not
629 * specified in config:
630 */
631 for (i = 0; scsi_cinit[i].driver; i++)
632 if (IS_SPECIFIED(scsi_cinit[i].scbus) &&
633 free_bus <= scsi_cinit[i].scbus)
634 free_bus = scsi_cinit[i].scbus + 1;
635
636 /* Lowest free unit for each type for auto-configure is one
637 * more than the first one not specified in the config file:
638 */
639 for (i = 0; scsi_dinit[i].name; i++) {
640 struct scsi_device_config *sdc = scsi_dinit + i;
641 struct scsi_device *sd =
642 scsi_device_lookup_by_name(sdc->name);
643
644 /* This is a little tricky: We don't want "sd 4" to match as
645 * a wired down device, but we do want "sd 4 target 5" or
646 * even "sd 4 scbus 1" to match.
647 */
648 if (IS_SPECIFIED(sdc->unit) &&
649 (IS_SPECIFIED(sdc->target) || IS_SPECIFIED(sdc->cunit)) &&
650 sd->free_unit <= sdc->unit)
651 sd->free_unit = sdc->unit + 1;
652 }
653 }
654 }
655
656 /* scsi_bus_conf: Figure out which bus this is. If it is wired in config
657 * use that. Otherwise use the next free one.
658 */
659 static int
660 scsi_bus_conf(sc_link_proto)
661 struct scsi_link *sc_link_proto;
662 {
663 int i;
664 int bus;
665
666 /* Which bus is this? Try to find a match in the "scsi_cinit"
667 * table. If it isn't wired down auto-configure it at the
668 * next available bus.
669 */
670
671 bus = SCCONF_UNSPEC;
672 for (i = 0; scsi_cinit[i].driver; i++) {
673 if (IS_SPECIFIED(scsi_cinit[i].scbus))
674 {
675 if (!strcmp(sc_link_proto->adapter->name, scsi_cinit[i].driver)
676 &&(sc_link_proto->adapter_unit == scsi_cinit[i].unit))
677 {
678 if (IS_SPECIFIED(scsi_cinit[i].bus)) {
679 if (sc_link_proto->adapter_bus==scsi_cinit[i].bus){
680 bus = scsi_cinit[i].scbus;
681 break;
682 }
683 }
684 else if (sc_link_proto->adapter_bus == 0) {
685 /* Backwards compatibility for single bus cards */
686 bus = scsi_cinit[i].scbus;
687 break;
688 }
689 else {
690 printf("Ambiguous scbus configuration for %s%d "
691 "bus %d, cannot wire down. The kernel "
692 "config entry for scbus%d should specify "
693 "a controller bus.\n"
694 "Scbus will be assigned dynamically.\n",
695 sc_link_proto->adapter->name,
696 sc_link_proto->adapter_unit,
697 sc_link_proto->adapter_bus,
698 sc_link_proto->adapter_bus );
699 break;
700 }
701 }
702 }
703 }
704
705
706 if (bus == SCCONF_UNSPEC)
707 bus = free_bus++;
708 else if (bootverbose)
709 printf("Choosing drivers for scbus configured at %d\n", bus);
710
711 return bus;
712 }
713
714 /* scsi_assign_unit: Look through the structure generated by config.
715 * See if there is a fixed assignment for this unit. If there isn't,
716 * assign the next free unit.
717 */
718 static int
719 scsi_assign_unit(struct scsi_link *sc_link)
720 {
721 int i;
722 int found;
723 #ifdef PC98
724 struct cfdata cf;
725 cf.cf_flags = 0;
726 #endif
727
728 found = 0;
729 for (i = 0; scsi_dinit[i].name; i++) {
730 if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
731 sc_link->target == scsi_dinit[i].target &&
732 (
733 (sc_link->lun == scsi_dinit[i].lun) ||
734 (sc_link->lun == 0 && scsi_dinit[i].lun == SCCONF_UNSPEC)
735 ) &&
736 sc_link->scsibus == scsi_dinit[i].cunit) {
737 sc_link->dev_unit = scsi_dinit[i].unit;
738 found = 1;
739 #ifdef PC98
740 cf.cf_flags = scsi_dinit[i].flags;
741 #endif
742 if (bootverbose)
743 printf("%s is configured at %d\n",
744 sc_link->device->name, sc_link->dev_unit);
745 break;
746 }
747 }
748
749 if (!found)
750 sc_link->dev_unit = sc_link->device->free_unit++;
751
752 #ifdef PC98
753 if (!found) {
754 for (i = 0; scsi_dinit[i].name; i++) {
755 if ((strcmp(sc_link->device->name, scsi_dinit[i].name) == 0) &&
756 (scsi_dinit[i].target == SCCONF_UNSPEC))
757 cf.cf_flags = scsi_dinit[i].flags;
758 }
759 }
760 if (sc_link->adapter->open_target_lu)
761 (*(sc_link->adapter->open_target_lu))(sc_link, &cf);
762 #endif
763
764 return sc_link->dev_unit;
765 }
766
767
768 #if NSCTARG > 0
769 /* The SCSI target configuration is simpler. If an entry is present
770 * we just return the bus, target and lun for that unit.
771 */
772 static void
773 scsi_sctarg_lookup(char *name, int unit, int *target, int *lun, int *bus)
774 {
775 int i;
776
777 *bus = SCCONF_UNSPEC;
778 *target = SCCONF_UNSPEC;
779 *lun = SCCONF_UNSPEC;
780
781 for (i = 0; scsi_dinit[i].name; i++) {
782 if ((strcmp(name, scsi_dinit[i].name) == 0) &&
783 unit == scsi_dinit[i].unit)
784 {
785 *bus = scsi_dinit[i].cunit;
786 *target = scsi_dinit[i].target;
787 *lun = scsi_dinit[i].lun;
788 }
789 }
790 }
791 #endif /* NSCTARG > 0 */
792
793 void
794 scsi_configure_start(void)
795 {
796 scsi_init();
797 }
798
799 #if NSCTARG > 0
800 static errval scsi_attach_sctarg __P((void));
801 #endif
802
803 void
804 scsi_configure_finish(void)
805 {
806
807 #if NSCTARG > 0
808 scsi_attach_sctarg();
809 #endif
810
811 }
812
813 /*
814 * scsi_attachdevs is the routine called by the adapter boards
815 * to get all their devices configured in.
816 */
817 void
818 scsi_attachdevs(scbus)
819 struct scsibus_data *scbus;
820 {
821 int scsibus;
822 struct scsi_link *sc_link_proto = scbus->adapter_link;
823
824 if ( (scsibus = scsi_bus_conf(sc_link_proto)) == -1) {
825 return;
826 }
827 /*
828 * if the adapter didn't give us this, set a default
829 * (compatibility with old adapter drivers)
830 */
831 if(!(sc_link_proto->opennings)) {
832 sc_link_proto->opennings = 1;
833 }
834 sc_link_proto->scsibus = scsibus;
835 /*
836 * Allocate our target-lun space.
837 */
838 scbus->sc_link = (struct scsi_link *(*)[][8])malloc(
839 sizeof(struct scsi_link *[scbus->maxtarg + 1][8]),
840 M_TEMP, M_NOWAIT);
841 if(scbus == 0 || scbus->sc_link == 0
842 || extend_set(scbusses, scsibus, scbus) == 0) {
843 panic("scsi_attachdevs: malloc");
844 }
845 bzero(scbus->sc_link, sizeof(struct scsi_link*[scbus->maxtarg + 1][8]));
846 #if defined(SCSI_DELAY) && SCSI_DELAY > 2
847 printf("%s%d waiting for scsi devices to settle\n",
848 sc_link_proto->adapter->name, sc_link_proto->adapter_unit);
849 #else /* SCSI_DELAY > 2 */
850 #undef SCSI_DELAY
851 #define SCSI_DELAY 2
852 #endif /* SCSI_DELAY */
853 DELAY(1000000 * SCSI_DELAY);
854 scsi_probe_bus(scsibus,-1,-1);
855 }
856
857 /*
858 * Probe the requested scsi bus. It must be already set up.
859 * -1 requests all set up scsi busses.
860 * targ and lun optionally narrow the search if not -1
861 */
862 errval
863 scsi_probe_busses(int bus, int targ, int lun)
864 {
865 if (bus == -1) {
866 for(bus = 0; bus < scbusses->nelem; bus++) {
867 scsi_probe_bus(bus, targ, lun);
868 }
869 return 0;
870 } else {
871 return scsi_probe_bus(bus, targ, lun);
872 }
873 }
874
875 /* scsi_alloc_unit: Register a scsi_data pointer for a given
876 * unit in a given scsi_device structure.
877 *
878 * XXX dufault@hda.com: I still don't like the way this reallocs stuff -
879 * but at least now it is collected in one place instead of existing
880 * in multiple type drivers. I'd like it better if we had it do a
881 * second pass after it knew the sizes of everything and set up everything
882 * at once.
883 */
884 static int
885 scsi_alloc_unit(struct scsi_link *sc_link)
886 {
887 u_int32_t unit;
888 struct scsi_data *sd;
889 struct scsi_device *dsw;
890
891 unit = sc_link->dev_unit;
892 dsw = sc_link->device;
893
894 /*
895 * allocate the per unit data area
896 */
897 if (dsw->sizeof_scsi_data)
898 {
899 sd = malloc(dsw->sizeof_scsi_data, M_DEVBUF, M_NOWAIT);
900 if (!sd) {
901 printf("%s%ld: malloc failed for scsi_data\n",
902 sc_link->device->name, unit);
903 return 0;
904 }
905 bzero(sd, dsw->sizeof_scsi_data);
906 }
907 else
908 sd = 0;
909
910 sc_link->sd = sd;
911
912 if (extend_set(dsw->links, unit, (void *)sc_link) == 0) {
913 printf("%s%ld: Can't store link pointer.\n",
914 sc_link->device->name, unit);
915 free(sd, M_DEVBUF);
916 return 0;
917 }
918
919 return 1;
920 }
921
922 static void
923 scsi_free_unit(struct scsi_link *sc_link)
924 {
925 if (sc_link->sd)
926 {
927 free(sc_link->sd, M_DEVBUF);
928 sc_link->sd = 0;
929 }
930 extend_release(sc_link->device->links, sc_link->dev_unit);
931 }
932
933 #if NSCTARG > 0
934
935 /* XXX: It is a bug that the sc_link has this information
936 * about the adapter in it. The sc_link should refer to
937 * a structure that is host adpater specific. That will also
938 * pull all knowledge of an sc_link out of the adapter drivers.
939 */
940
941 errval
942 scsi_set_bus(int bus, struct scsi_link *sc_link)
943 {
944 struct scsi_link *ad_link;
945 struct scsibus_data *scsibus_data;
946
947 if (bus < 0 || bus > scbusses->nelem) {
948 return ENXIO;
949 }
950
951 scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
952
953 if(!scsibus_data) {
954 return ENXIO;
955 }
956
957 ad_link = scsibus_data->adapter_link;
958
959 sc_link->adapter_unit = ad_link->adapter_unit;
960 sc_link->adapter_targ = ad_link->adapter_targ;
961 sc_link->adapter = ad_link->adapter;
962 sc_link->device = ad_link->device;
963 sc_link->flags = ad_link->flags;
964
965 return 0;
966 }
967
968 /*
969 * Allocate and attach as many SCSI target devices as configured.
970 * There are two ways that you can configure the target device:
971 * 1. In the configuration file. That is handled here.
972 * 2. Via the minor number. That takes precedence over the config file.
973 */
974 static errval
975 scsi_attach_sctarg()
976 {
977 struct scsi_link *sc_link = NULL;
978 int dev_unit;
979 struct scsi_device *sctarg = scsi_device_lookup(T_TARGET);
980
981 if (sctarg == 0) {
982 return ENXIO;
983 }
984
985 for (dev_unit = 0; dev_unit < NSCTARG; dev_unit++) {
986
987 int target, lun, bus;
988
989 /* If we don't have a link block allocate one.
990 */
991 if (!sc_link) {
992 sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
993 }
994
995 scsi_sctarg_lookup(sctarg->name, dev_unit, &target, &lun, &bus);
996
997 if (IS_SPECIFIED(bus)) {
998 struct scsibus_data *scsibus_data;
999
1000 if (bus < 0 || bus > scbusses->nelem) {
1001 printf("%s%d: configured on illegal bus %d.\n",
1002 sctarg->name, dev_unit, bus);
1003 continue;
1004 }
1005
1006 scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
1007
1008 if(!scsibus_data) {
1009 printf("%s%d: no bus %d.\n", sctarg->name, dev_unit, bus);
1010 continue;
1011 }
1012
1013 *sc_link = *scsibus_data->adapter_link; /* struct copy */
1014 sc_link->target = target;
1015 sc_link->lun = lun;
1016 }
1017 else {
1018 /* This will be configured in the open routine.
1019 */
1020 sc_link->scsibus = SCCONF_UNSPEC;
1021 sc_link->target = SCCONF_UNSPEC;
1022 sc_link->lun = SCCONF_UNSPEC;
1023 }
1024
1025 sc_link->quirks = 0;
1026 sc_link->device = sctarg;
1027 sc_link->dev_unit = dev_unit;
1028
1029 if (scsi_alloc_unit(sc_link)) {
1030
1031 if (scsi_device_attach(sc_link) == 0) {
1032 sc_link = NULL; /* it's been used */
1033 }
1034 else
1035 scsi_free_unit(sc_link);
1036 }
1037 }
1038
1039 if (sc_link) {
1040 free(sc_link, M_TEMP);
1041 }
1042
1043 return 0;
1044 }
1045 #endif /* NSCTARG > 0 */
1046
1047 /*
1048 * Allocate a scsibus_data structure
1049 * The target/lun area is dynamically allocated in scsi_attachdevs after
1050 * the controller driver has a chance to update the maxtarg field.
1051 */
1052 struct scsibus_data*
1053 scsi_alloc_bus()
1054 {
1055 struct scsibus_data *scbus;
1056 /*
1057 * Prepare the scsibus_data area for the upperlevel
1058 * scsi code.
1059 */
1060 scbus = malloc(sizeof(struct scsibus_data), M_TEMP, M_NOWAIT);
1061 if(!scbus) {
1062 printf("scsi_alloc_bus: - cannot malloc!\n");
1063 return NULL;
1064 }
1065 bzero(scbus, sizeof(struct scsibus_data));
1066 /* Setup the defaults */
1067 scbus->maxtarg = 7;
1068 scbus->maxlun = 7;
1069 return scbus;
1070 }
1071
1072 /*
1073 * Probe the requested scsi bus. It must be already set up.
1074 * targ and lun optionally narrow the search if not -1
1075 */
1076 errval
1077 scsi_probe_bus(int bus, int targ, int lun)
1078 {
1079 struct scsibus_data *scsibus_data ;
1080 int maxtarg,mintarg,maxlun,minlun;
1081 struct scsi_link *sc_link_proto;
1082 u_int8_t scsi_addr ;
1083 struct scsidevs *bestmatch = NULL;
1084 struct scsi_link *sc_link = NULL;
1085 boolean maybe_more;
1086 int type;
1087
1088 if ((bus < 0 ) || ( bus >= scbusses->nelem)) {
1089 return ENXIO;
1090 }
1091 scsibus_data = (struct scsibus_data *)extend_get(scbusses, bus);
1092 if(!scsibus_data) return ENXIO;
1093 sc_link_proto = scsibus_data->adapter_link;
1094 scsi_addr = sc_link_proto->adapter_targ;
1095 if(targ == -1){
1096 maxtarg = scsibus_data->maxtarg;
1097 mintarg = 0;
1098 } else {
1099 if((targ < 0 ) || (targ > scsibus_data->maxtarg)) return EINVAL;
1100 maxtarg = mintarg = targ;
1101 }
1102
1103 if(lun == -1){
1104 maxlun = scsibus_data->maxlun;
1105 minlun = 0;
1106 } else {
1107 if((lun < 0 ) || (lun > scsibus_data->maxlun)) return EINVAL;
1108 maxlun = minlun = lun;
1109 }
1110
1111 for ( targ = mintarg;targ <= maxtarg; targ++) {
1112 maybe_more = 0; /* by default only check 1 lun */
1113 if (targ == scsi_addr) {
1114 continue;
1115 }
1116 for ( lun = minlun; lun <= maxlun ;lun++) {
1117 /*
1118 * The spot appears to already have something
1119 * linked in, skip past it. Must be doing a 'reprobe'
1120 */
1121 if((*scsibus_data->sc_link)[targ][lun])
1122 {/* don't do this one, but check other luns */
1123 maybe_more = 1;
1124 continue;
1125 }
1126 /*
1127 * If we presently don't have a link block
1128 * then allocate one to use while probing
1129 */
1130 if (!sc_link) {
1131 sc_link = malloc(sizeof(*sc_link), M_TEMP, M_NOWAIT);
1132 }
1133 *sc_link = *sc_link_proto; /* struct copy */
1134 sc_link->device = &probe_switch;
1135 sc_link->target = targ;
1136 sc_link->lun = lun;
1137 sc_link->quirks = 0;
1138 bestmatch = scsi_probedev(sc_link, &maybe_more, &type);
1139 if (bestmatch) {
1140 sc_link->quirks = bestmatch->quirks;
1141 sc_link->devmodes = bestmatch->devmodes;
1142 } else {
1143 sc_link->quirks = 0;
1144 sc_link->devmodes = NULL;
1145 }
1146 if (bestmatch) { /* FOUND */
1147 sc_link->device = scsi_device_lookup(type);
1148
1149 (void)scsi_assign_unit(sc_link);
1150
1151 if (scsi_alloc_unit(sc_link)) {
1152
1153 if (scsi_device_attach(sc_link) == 0) {
1154 (*scsibus_data->sc_link)[targ][lun] = sc_link;
1155 sc_link = NULL; /* it's been used */
1156 }
1157 else
1158 scsi_free_unit(sc_link);
1159 }
1160 }
1161
1162 if (!(maybe_more)) { /* nothing suggests we'll find more */
1163 break; /* nothing here, skip to next targ */
1164 }
1165 /* otherwise something says we should look further */
1166 }
1167 }
1168 if (sc_link) {
1169 free(sc_link, M_TEMP);
1170 }
1171 return 0;
1172 }
1173
1174 /* Return the scsi_link for this device, if any.
1175 */
1176 struct scsi_link *
1177 scsi_link_get(bus, targ, lun)
1178 int bus;
1179 int targ;
1180 int lun;
1181 {
1182 struct scsibus_data *scsibus_data =
1183 (struct scsibus_data *)extend_get(scbusses, bus);
1184 return (scsibus_data) ? (*scsibus_data->sc_link)[targ][lun] : 0;
1185 }
1186
1187 /* make_readable: Make the inquiry data readable. Anything less than a ' '
1188 * is made a '?' and trailing spaces are removed.
1189 */
1190 static void
1191 make_readable(to, from, n)
1192 char *to;
1193 char *from;
1194 size_t n;
1195 {
1196 int i;
1197
1198 for (i = 0; from[i] && i < n - 1; i++) {
1199 if (from[i] < ' ')
1200 to[i]='?';
1201 else
1202 to[i] = from[i];
1203 }
1204
1205 while (i && to[i - 1] == ' ')
1206 i--;
1207
1208 to[i] = 0;
1209 }
1210
1211 /*
1212 * given a target and lu, ask the device what
1213 * it is, and find the correct driver table
1214 * entry.
1215 */
1216 static struct scsidevs *
1217 scsi_probedev(sc_link, maybe_more, type_p)
1218 boolean *maybe_more;
1219 struct scsi_link *sc_link;
1220 int *type_p;
1221 {
1222 u_int8_t target = sc_link->target;
1223 u_int8_t lu = sc_link->lun;
1224 struct scsidevs *bestmatch = (struct scsidevs *) 0;
1225 int dtype = 0;
1226 char *desc;
1227 char *qtype;
1228 struct scsi_inquiry_data *inqbuf;
1229 u_int32_t len, qualifier, type;
1230 boolean remov;
1231 char manu[8 + 1];
1232 char model[16 + 1];
1233 char version[4 + 1];
1234
1235 inqbuf = &sc_link->inqbuf;
1236
1237 bzero(inqbuf, sizeof(*inqbuf));
1238 /*
1239 * Ask the device what it is
1240 */
1241 #ifdef SCSIDEBUG
1242 if ((target == DEBUGTARG) && (lu == DEBUGLUN))
1243 sc_link->flags |= (DEBUGLEVEL);
1244 else
1245 sc_link->flags &= ~(SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4);
1246 #endif /* SCSIDEBUG */
1247 /* catch unit attn */
1248 scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
1249 #ifdef DOUBTFULL
1250 switch (scsi_test_unit_ready(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT)) {
1251 case 0: /* said it WAS ready */
1252 case EBUSY: /* replied 'NOT READY' but WAS present, continue */
1253 case ENXIO:
1254 break;
1255 case EIO: /* device timed out */
1256 case EINVAL: /* Lun not supported */
1257 default:
1258 return (struct scsidevs *) 0;
1259
1260 }
1261 #endif /*DOUBTFULL*/
1262 #ifdef SCSI_2_DEF
1263 /* some devices need to be told to go to SCSI2 */
1264 /* However some just explode if you tell them this.. leave it out */
1265 scsi_change_def(sc_link, SCSI_NOSLEEP | SCSI_NOMASK | SCSI_SILENT);
1266 #endif /*SCSI_2_DEF */
1267
1268 /* Now go ask the device all about itself */
1269 if (scsi_inquire(sc_link, inqbuf, SCSI_NOSLEEP | SCSI_NOMASK) != 0) {
1270 return (struct scsidevs *) 0;
1271 }
1272
1273 /*
1274 * note what BASIC type of device it is
1275 */
1276 type = inqbuf->device & SID_TYPE;
1277 qualifier = inqbuf->device & SID_QUAL;
1278 remov = inqbuf->dev_qual2 & SID_REMOVABLE;
1279
1280 /*
1281 * Any device qualifier that has the top bit set (qualifier&4 != 0)
1282 * is vendor specific and will match in the default of this switch.
1283 */
1284
1285 switch ((int)qualifier) {
1286 case SID_QUAL_LU_OK:
1287 qtype = "";
1288 break;
1289
1290 case SID_QUAL_LU_OFFLINE:
1291 qtype = "Supported device currently not connected";
1292 break;
1293
1294 case SID_QUAL_RSVD: /* Peripheral qualifier reserved in SCSI-2 spec */
1295 *maybe_more = 1;
1296 return (struct scsidevs *) 0;
1297
1298 case SID_QUAL_BAD_LU: /* Target can not support a device on this unit */
1299 /*
1300 * Check for a non-existent unit. If the device is returning
1301 * this much, then we must set the flag that has
1302 * the searchers keep looking on other luns.
1303 */
1304 *maybe_more = 1;
1305 return (struct scsidevs *) 0;
1306
1307 default:
1308 dtype = 1;
1309 qtype = "Vendor specific peripheral qualifier";
1310 *maybe_more = 1;
1311 break;
1312 }
1313
1314 if (dtype == 0) {
1315 if (type == T_NODEVICE) {
1316 *maybe_more = 1;
1317 return (struct scsidevs *) 0;
1318 }
1319 dtype = 1;
1320 }
1321 /*
1322 * Then if it's advanced enough, more detailed
1323 * information
1324 */
1325 if ((inqbuf->version & SID_ANSII) > 0) {
1326 if ((len = inqbuf->additional_length
1327 + ((char *) inqbuf->unused
1328 - (char *) inqbuf))
1329 > (sizeof(struct scsi_inquiry_data) - 1))
1330 len = sizeof(struct scsi_inquiry_data) - 1;
1331 desc = inqbuf->vendor;
1332 desc[len - (desc - (char *) inqbuf)] = 0;
1333 make_readable(manu, inqbuf->vendor, sizeof(manu));
1334 make_readable(model, inqbuf->product, sizeof(model));
1335 make_readable(version, inqbuf->revision, sizeof(version));
1336 } else {
1337 /*
1338 * If not advanced enough, use default values
1339 */
1340 desc = "early protocol device";
1341 make_readable(manu, "unknown", sizeof(manu));
1342 make_readable(model, "unknown", sizeof(model));
1343 make_readable(version, "????", sizeof(version));
1344 type = T_UNKNOWN;
1345 }
1346
1347 sc_print_start(sc_link);
1348
1349 printf("\"%s %s %s\" ", manu, model, version );
1350 printf("type %ld %sSCSI %d"
1351 ,type
1352 ,remov ? "removable " : "fixed "
1353 ,inqbuf->version & SID_ANSII
1354 );
1355 if (qtype[0]) {
1356 sc_print_addr(sc_link);
1357 printf(" qualifier %ld: %s" ,qualifier ,qtype);
1358 }
1359
1360 printf("\n");
1361 sc_print_finish();
1362
1363 /*
1364 * Try make as good a match as possible with
1365 * available sub drivers
1366 */
1367 bestmatch = (scsi_selectdev(
1368 qualifier, type, remov ? T_REMOV : T_FIXED, manu, model, version));
1369 if ((bestmatch) && (bestmatch->flags & SC_MORE_LUS)) {
1370 *maybe_more = 1;
1371 }
1372
1373 /* If the device is unknown then we should be trying to look up a
1374 * type driver based on the inquiry type.
1375 */
1376 if (bestmatch == &unknowndev)
1377 *type_p = type;
1378 else
1379 *type_p =
1380 bestmatch->driver;
1381 return bestmatch;
1382 }
1383
1384 /* Try to find the major number for a device during attach.
1385 */
1386 dev_t
1387 scsi_dev_lookup(d_open)
1388 d_open_t *d_open;
1389 {
1390 int i;
1391
1392 dev_t d = NODEV;
1393
1394 for (i = 0; i < nchrdev; i++)
1395 if (cdevsw[i] && cdevsw[i]->d_open == d_open)
1396 {
1397 d = makedev(i, 0);
1398 break;
1399 }
1400
1401 return d;
1402 }
1403
1404 /*
1405 * Compare name with pattern, return 0 on match.
1406 * Short pattern matches trailing blanks in name,
1407 * wildcard '*' in pattern matches rest of name
1408 */
1409 static int
1410 match(pattern, name)
1411 char *pattern;
1412 char *name;
1413 {
1414 char c;
1415 while (c = *pattern++)
1416 {
1417 if (c == '*') return 0;
1418 if ((c == '?') && (*name > ' ')) continue;
1419 if (c != *name++) return 1;
1420 }
1421 while (c = *name++)
1422 {
1423 if (c != ' ') return 1;
1424 }
1425 return 0;
1426 }
1427
1428 /*
1429 * Try make as good a match as possible with
1430 * available sub drivers
1431 */
1432 static struct scsidevs *
1433 scsi_selectdev(qualifier, type, remov, manu, model, rev)
1434 u_int32_t qualifier, type;
1435 boolean remov;
1436 char *manu, *model, *rev;
1437 {
1438 struct scsidevs *bestmatch = NULL;
1439 struct scsidevs *thisentry;
1440
1441 type |= qualifier; /* why? */
1442
1443 for ( thisentry = knowndevs; thisentry->manufacturer; thisentry++ )
1444 {
1445 if (type != thisentry->type) {
1446 continue;
1447 }
1448 if (remov != thisentry->removable) {
1449 continue;
1450 }
1451
1452 if (thisentry->flags & SC_SHOWME)
1453 printf("\n%s-\n%s-", thisentry->manufacturer, manu);
1454 if (match(thisentry->manufacturer, manu)) {
1455 continue;
1456 }
1457 if (thisentry->flags & SC_SHOWME)
1458 printf("\n%s-\n%s-", thisentry->model, model);
1459 if (match(thisentry->model, model)) {
1460 continue;
1461 }
1462 if (thisentry->flags & SC_SHOWME)
1463 printf("\n%s-\n%s-", thisentry->version, rev);
1464 if (match(thisentry->version, rev)) {
1465 continue;
1466 }
1467 bestmatch = thisentry;
1468 break;
1469 }
1470 if (bestmatch == (struct scsidevs *) 0) {
1471 bestmatch = &unknowndev;
1472 }
1473 return (bestmatch);
1474 }
Cache object: 70de9f2889ec8149a3f44c5331aa6aec
|