xref: /netbsd-src/sys/dev/scsipi/scsiconf.c (revision da9817918ec7e88db2912a2882967c7570a83f47)
1 /*	$NetBSD: scsiconf.c,v 1.253 2009/05/12 14:44:31 cegger Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
9  * Simulation Facility, NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Originally written by Julian Elischer (julian@tfs.com)
35  * for TRW Financial Systems for use under the MACH(2.5) operating system.
36  *
37  * TRW Financial Systems, in accordance with their agreement with Carnegie
38  * Mellon University, makes this software available to CMU to distribute
39  * or use in any manner that they see fit as long as this message is kept with
40  * the software. For this reason TFS also grants any other persons or
41  * organisations permission to use or modify this software.
42  *
43  * TFS supplies this software to be publicly redistributed
44  * on the understanding that TFS is not responsible for the correct
45  * functioning of this software in any circumstances.
46  *
47  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
48  */
49 
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: scsiconf.c,v 1.253 2009/05/12 14:44:31 cegger Exp $");
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/kernel.h>
56 #include <sys/proc.h>
57 #include <sys/kthread.h>
58 #include <sys/malloc.h>
59 #include <sys/device.h>
60 #include <sys/conf.h>
61 #include <sys/fcntl.h>
62 #include <sys/scsiio.h>
63 #include <sys/queue.h>
64 #include <sys/simplelock.h>
65 
66 #include <dev/scsipi/scsi_all.h>
67 #include <dev/scsipi/scsipi_all.h>
68 #include <dev/scsipi/scsiconf.h>
69 
70 #include "locators.h"
71 
72 static const struct scsipi_periphsw scsi_probe_dev = {
73 	NULL,
74 	NULL,
75 	NULL,
76 	NULL,
77 };
78 
79 struct scsi_initq {
80 	struct scsipi_channel *sc_channel;
81 	TAILQ_ENTRY(scsi_initq) scsi_initq;
82 };
83 
84 static TAILQ_HEAD(, scsi_initq) scsi_initq_head =
85     TAILQ_HEAD_INITIALIZER(scsi_initq_head);
86 static struct simplelock scsibus_interlock = SIMPLELOCK_INITIALIZER;
87 
88 static int	scsi_probe_device(struct scsibus_softc *, int, int);
89 
90 static int	scsibusmatch(device_t, cfdata_t, void *);
91 static void	scsibusattach(device_t, device_t, void *);
92 static int	scsibusactivate(device_t, enum devact);
93 static int	scsibusdetach(device_t, int flags);
94 static int	scsibusrescan(device_t, const char *, const int *);
95 static void	scsidevdetached(device_t, device_t);
96 
97 CFATTACH_DECL3_NEW(scsibus, sizeof(struct scsibus_softc),
98     scsibusmatch, scsibusattach, scsibusdetach, scsibusactivate,
99     scsibusrescan, scsidevdetached, DVF_DETACH_SHUTDOWN);
100 
101 extern struct cfdriver scsibus_cd;
102 
103 static dev_type_open(scsibusopen);
104 static dev_type_close(scsibusclose);
105 static dev_type_ioctl(scsibusioctl);
106 
107 const struct cdevsw scsibus_cdevsw = {
108 	scsibusopen, scsibusclose, noread, nowrite, scsibusioctl,
109 	nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
110 };
111 
112 static int	scsibusprint(void *, const char *);
113 static void	scsibus_config(struct scsipi_channel *, void *);
114 
115 const struct scsipi_bustype scsi_bustype = {
116 	SCSIPI_BUSTYPE_SCSI,
117 	scsi_scsipi_cmd,
118 	scsipi_interpret_sense,
119 	scsi_print_addr,
120 	scsi_kill_pending,
121 };
122 
123 int
124 scsiprint(void *aux, const char *pnp)
125 {
126 	struct scsipi_channel *chan = aux;
127 	struct scsipi_adapter *adapt = chan->chan_adapter;
128 
129 	/* only "scsibus"es can attach to "scsi"s; easy. */
130 	if (pnp)
131 		aprint_normal("scsibus at %s", pnp);
132 
133 	/* don't print channel if the controller says there can be only one. */
134 	if (adapt->adapt_nchannels != 1)
135 		aprint_normal(" channel %d", chan->chan_channel);
136 
137 	return (UNCONF);
138 }
139 
140 static int
141 scsibusmatch(device_t parent, cfdata_t cf, void *aux)
142 {
143 	struct scsipi_channel *chan = aux;
144 
145 	if (chan->chan_bustype->bustype_type != SCSIPI_BUSTYPE_SCSI)
146 		return 0;
147 
148 	if (cf->cf_loc[SCSICF_CHANNEL] != chan->chan_channel &&
149 	    cf->cf_loc[SCSICF_CHANNEL] != SCSICF_CHANNEL_DEFAULT)
150 		return (0);
151 
152 	return (1);
153 }
154 
155 static void
156 scsibusattach(device_t parent, device_t self, void *aux)
157 {
158 	struct scsibus_softc *sc = device_private(self);
159 	struct scsipi_channel *chan = aux;
160 	struct scsi_initq *scsi_initq;
161 
162 	if (!pmf_device_register(self, NULL, NULL))
163 		aprint_error_dev(self, "couldn't establish power handler\n");
164 
165 	sc->sc_dev = self;
166 	sc->sc_channel = chan;
167 	chan->chan_name = device_xname(sc->sc_dev);
168 
169 	aprint_naive(": SCSI bus\n");
170 	aprint_normal(": %d target%s, %d lun%s per target\n",
171 	    chan->chan_ntargets,
172 	    chan->chan_ntargets == 1 ? "" : "s",
173 	    chan->chan_nluns,
174 	    chan->chan_nluns == 1 ? "" : "s");
175 
176 	if (scsipi_adapter_addref(chan->chan_adapter))
177 		return;
178 
179 	/* Initialize the channel structure first */
180 	chan->chan_init_cb = scsibus_config;
181 	chan->chan_init_cb_arg = sc;
182 
183 	scsi_initq = malloc(sizeof(struct scsi_initq), M_DEVBUF, M_WAITOK);
184 	scsi_initq->sc_channel = chan;
185 	TAILQ_INSERT_TAIL(&scsi_initq_head, scsi_initq, scsi_initq);
186         config_pending_incr();
187 	if (scsipi_channel_init(chan)) {
188 		aprint_error_dev(sc->sc_dev, "failed to init channel\n");
189 		return;
190 	}
191 }
192 
193 static void
194 scsibus_config(struct scsipi_channel *chan, void *arg)
195 {
196 	struct scsibus_softc *sc = arg;
197 	struct scsi_initq *scsi_initq;
198 
199 #ifndef SCSI_DELAY
200 #define SCSI_DELAY 2
201 #endif
202 	if ((chan->chan_flags & SCSIPI_CHAN_NOSETTLE) == 0 &&
203 	    SCSI_DELAY > 0) {
204 		aprint_normal_dev(sc->sc_dev,
205 		    "waiting %d seconds for devices to settle...\n",
206 		    SCSI_DELAY);
207 		/* ...an identifier we know no one will use... */
208 		(void) tsleep(scsibus_config, PRIBIO,
209 		    "scsidly", SCSI_DELAY * hz);
210 	}
211 
212 	/* Make sure the devices probe in scsibus order to avoid jitter. */
213 	simple_lock(&scsibus_interlock);
214 	for (;;) {
215 		scsi_initq = TAILQ_FIRST(&scsi_initq_head);
216 		if (scsi_initq->sc_channel == chan)
217 			break;
218 		ltsleep(&scsi_initq_head, PRIBIO, "scsi_initq", 0,
219 		    &scsibus_interlock);
220 	}
221 
222 	simple_unlock(&scsibus_interlock);
223 
224 	scsi_probe_bus(sc, -1, -1);
225 
226 	simple_lock(&scsibus_interlock);
227 	TAILQ_REMOVE(&scsi_initq_head, scsi_initq, scsi_initq);
228 	simple_unlock(&scsibus_interlock);
229 
230 	free(scsi_initq, M_DEVBUF);
231 	wakeup(&scsi_initq_head);
232 
233 	scsipi_adapter_delref(chan->chan_adapter);
234 
235 	config_pending_decr();
236 }
237 
238 static int
239 scsibusactivate(device_t self, enum devact act)
240 {
241 	struct scsibus_softc *sc = device_private(self);
242 	struct scsipi_channel *chan = sc->sc_channel;
243 	struct scsipi_periph *periph;
244 	int target, lun, error = 0, s;
245 
246 	s = splbio();
247 	switch (act) {
248 	case DVACT_ACTIVATE:
249 		error = EOPNOTSUPP;
250 		break;
251 
252 	case DVACT_DEACTIVATE:
253 		for (target = 0; target < chan->chan_ntargets;
254 		     target++) {
255 			if (target == chan->chan_id)
256 				continue;
257 			for (lun = 0; lun < chan->chan_nluns; lun++) {
258 				periph = scsipi_lookup_periph(chan,
259 				    target, lun);
260 				if (periph == NULL)
261 					continue;
262 				error = config_deactivate(periph->periph_dev);
263 				if (error)
264 					goto out;
265 			}
266 		}
267 		break;
268 	}
269  out:
270 	splx(s);
271 	return (error);
272 }
273 
274 static int
275 scsibusdetach(device_t self, int flags)
276 {
277 	struct scsibus_softc *sc = device_private(self);
278 	struct scsipi_channel *chan = sc->sc_channel;
279 	struct scsipi_periph *periph;
280 	int ctarget, clun;
281 	struct scsipi_xfer *xs;
282 	int error;
283 
284 	pmf_device_deregister(self);
285 
286 	/*
287 	 * Process outstanding commands (which will never complete as the
288 	 * controller is gone).
289 	 */
290 	for (ctarget = 0; ctarget < chan->chan_ntargets; ctarget++) {
291 		if (ctarget == chan->chan_id)
292 			continue;
293 		for (clun = 0; clun < chan->chan_nluns; clun++) {
294 			periph = scsipi_lookup_periph(chan, ctarget, clun);
295 			if (periph == NULL)
296 				continue;
297 			TAILQ_FOREACH(xs, &periph->periph_xferq, device_q) {
298 				callout_stop(&xs->xs_callout);
299 				xs->error = XS_DRIVER_STUFFUP;
300 				scsipi_done(xs);
301 			}
302 		}
303 	}
304 
305 	/*
306 	 * Detach all of the periphs.
307 	 */
308 	error = scsipi_target_detach(chan, -1, -1, flags);
309 
310 	/*
311 	 * Now shut down the channel.
312 	 * XXX only if no errors ?
313 	 */
314 	scsipi_channel_shutdown(chan);
315 	return (error);
316 }
317 
318 /*
319  * Probe the requested scsi bus. It must be already set up.
320  * target and lun optionally narrow the search if not -1
321  */
322 int
323 scsi_probe_bus(struct scsibus_softc *sc, int target, int lun)
324 {
325 	struct scsipi_channel *chan = sc->sc_channel;
326 	int maxtarget, mintarget, maxlun, minlun;
327 	int error;
328 
329 	if (target == -1) {
330 		maxtarget = chan->chan_ntargets - 1;
331 		mintarget = 0;
332 	} else {
333 		if (target < 0 || target >= chan->chan_ntargets)
334 			return (EINVAL);
335 		maxtarget = mintarget = target;
336 	}
337 
338 	if (lun == -1) {
339 		maxlun = chan->chan_nluns - 1;
340 		minlun = 0;
341 	} else {
342 		if (lun < 0 || lun >= chan->chan_nluns)
343 			return (EINVAL);
344 		maxlun = minlun = lun;
345 	}
346 
347 	/*
348 	 * Some HBAs provide an abstracted view of the bus; give them an
349 	 * oppertunity to re-scan it before we do.
350 	 */
351 	if (chan->chan_adapter->adapt_ioctl != NULL)
352 		(*chan->chan_adapter->adapt_ioctl)(chan, SCBUSIOLLSCAN, NULL,
353 		    0, curproc);
354 
355 	if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
356 		return (error);
357 	for (target = mintarget; target <= maxtarget; target++) {
358 		if (target == chan->chan_id)
359 			continue;
360 		for (lun = minlun; lun <= maxlun; lun++) {
361 			/*
362 			 * See if there's a device present, and configure it.
363 			 */
364 			if (scsi_probe_device(sc, target, lun) == 0)
365 				break;
366 			/* otherwise something says we should look further */
367 		}
368 
369 		/*
370 		 * Now that we've discovered all of the LUNs on this
371 		 * I_T Nexus, update the xfer mode for all of them
372 		 * that we know about.
373 		 */
374 		scsipi_set_xfer_mode(chan, target, 1);
375 	}
376 	scsipi_adapter_delref(chan->chan_adapter);
377 	return (0);
378 }
379 
380 static int
381 scsibusrescan(device_t sc, const char *ifattr,
382     const int *locators)
383 {
384 
385 	KASSERT(ifattr && !strcmp(ifattr, "scsibus"));
386 	KASSERT(locators);
387 
388 	return (scsi_probe_bus(device_private(sc),
389 		locators[SCSIBUSCF_TARGET], locators[SCSIBUSCF_LUN]));
390 }
391 
392 static void
393 scsidevdetached(device_t sc, device_t dev)
394 {
395 	struct scsibus_softc *ssc = device_private(sc);
396 	struct scsipi_channel *chan = ssc->sc_channel;
397 	struct scsipi_periph *periph;
398 	int target, lun;
399 
400 	target = device_locator(dev, SCSIBUSCF_TARGET);
401 	lun = device_locator(dev, SCSIBUSCF_LUN);
402 
403 	periph = scsipi_lookup_periph(chan, target, lun);
404 	KASSERT(periph->periph_dev == dev);
405 
406 	scsipi_remove_periph(chan, periph);
407 	free(periph, M_DEVBUF);
408 }
409 
410 /*
411  * Print out autoconfiguration information for a subdevice.
412  *
413  * This is a slight abuse of 'standard' autoconfiguration semantics,
414  * because 'print' functions don't normally print the colon and
415  * device information.  However, in this case that's better than
416  * either printing redundant information before the attach message,
417  * or having the device driver call a special function to print out
418  * the standard device information.
419  */
420 static int
421 scsibusprint(void *aux, const char *pnp)
422 {
423 	struct scsipibus_attach_args *sa = aux;
424 	struct scsipi_inquiry_pattern *inqbuf;
425 	u_int8_t type;
426 	const char *dtype;
427 	char vendor[33], product[65], revision[17];
428 	int target, lun;
429 
430 	if (pnp != NULL)
431 		aprint_normal("%s", pnp);
432 
433 	inqbuf = &sa->sa_inqbuf;
434 
435 	target = sa->sa_periph->periph_target;
436 	lun = sa->sa_periph->periph_lun;
437 	type = inqbuf->type & SID_TYPE;
438 
439 	dtype = scsipi_dtype(type);
440 
441 	scsipi_strvis(vendor, 33, inqbuf->vendor, 8);
442 	scsipi_strvis(product, 65, inqbuf->product, 16);
443 	scsipi_strvis(revision, 17, inqbuf->revision, 4);
444 
445 	aprint_normal(" target %d lun %d: <%s, %s, %s> %s %s",
446 	    target, lun, vendor, product, revision, dtype,
447 	    inqbuf->removable ? "removable" : "fixed");
448 
449 	return (UNCONF);
450 }
451 
452 static const struct scsi_quirk_inquiry_pattern scsi_quirk_patterns[] = {
453 	{{T_CDROM, T_REMOV,
454 	 "CHINON  ", "CD-ROM CDS-431  ", ""},     PQUIRK_NOLUNS},
455 	{{T_CDROM, T_REMOV,
456 	 "CHINON  ", "CD-ROM CDS-435  ", ""},     PQUIRK_NOLUNS},
457 	{{T_CDROM, T_REMOV,
458 	 "Chinon  ", "CD-ROM CDS-525  ", ""},     PQUIRK_NOLUNS},
459 	{{T_CDROM, T_REMOV,
460 	 "CHINON  ", "CD-ROM CDS-535  ", ""},     PQUIRK_NOLUNS},
461 	{{T_CDROM, T_REMOV,
462 	 "DEC     ", "RRD42   (C) DEC ", ""},     PQUIRK_NOLUNS},
463 	{{T_CDROM, T_REMOV,
464 	 "DENON   ", "DRD-25X         ", "V"},    PQUIRK_NOLUNS},
465 	{{T_CDROM, T_REMOV,
466 	 "GENERIC ", "CRD-BP2         ", ""},     PQUIRK_NOLUNS},
467 	{{T_CDROM, T_REMOV,
468 	 "HP      ", "C4324/C4325     ", ""},     PQUIRK_NOLUNS},
469 	{{T_CDROM, T_REMOV,
470 	 "IMS     ", "CDD521/10       ", "2.06"}, PQUIRK_NOLUNS},
471 	{{T_CDROM, T_REMOV,
472 	 "MATSHITA", "CD-ROM CR-5XX   ", "1.0b"}, PQUIRK_NOLUNS},
473 	{{T_CDROM, T_REMOV,
474 	 "MEDAVIS ", "RENO CD-ROMX2A  ", ""},     PQUIRK_NOLUNS},
475 	{{T_CDROM, T_REMOV,
476 	 "MEDIAVIS", "CDR-H93MV       ", "1.3"},  PQUIRK_NOLUNS},
477 	{{T_CDROM, T_REMOV,
478 	 "NEC     ", "CD-ROM DRIVE:502", ""},     PQUIRK_NOLUNS},
479 	{{T_CDROM, T_REMOV,
480 	 "NEC     ", "CD-ROM DRIVE:55 ", ""},     PQUIRK_NOLUNS},
481 	{{T_CDROM, T_REMOV,
482 	 "NEC     ", "CD-ROM DRIVE:83 ", ""},     PQUIRK_NOLUNS},
483 	{{T_CDROM, T_REMOV,
484 	 "NEC     ", "CD-ROM DRIVE:84 ", ""},     PQUIRK_NOLUNS},
485 	{{T_CDROM, T_REMOV,
486 	 "NEC     ", "CD-ROM DRIVE:841", ""},     PQUIRK_NOLUNS},
487         {{T_CDROM, T_REMOV,
488 	 "OLYMPUS ", "CDS620E         ", "1.1d"},
489 			       PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOCAPACITY},
490 	{{T_CDROM, T_REMOV,
491 	 "PIONEER ", "CD-ROM DR-124X  ", "1.01"}, PQUIRK_NOLUNS},
492         {{T_CDROM, T_REMOV,
493          "PLEXTOR ", "CD-ROM PX-4XCS  ", "1.01"},
494                                PQUIRK_NOLUNS|PQUIRK_NOSYNC},
495 	{{T_CDROM, T_REMOV,
496 	 "SONY    ", "CD-ROM CDU-541  ", ""},     PQUIRK_NOLUNS},
497 	{{T_CDROM, T_REMOV,
498 	 "SONY    ", "CD-ROM CDU-55S  ", ""},     PQUIRK_NOLUNS},
499 	{{T_CDROM, T_REMOV,
500 	 "SONY    ", "CD-ROM CDU-561  ", ""},     PQUIRK_NOLUNS},
501 	{{T_CDROM, T_REMOV,
502 	 "SONY    ", "CD-ROM CDU-76S", ""},
503 				PQUIRK_NOLUNS|PQUIRK_NOSYNC|PQUIRK_NOWIDE},
504 	{{T_CDROM, T_REMOV,
505 	 "SONY    ", "CD-ROM CDU-8003A", ""},     PQUIRK_NOLUNS},
506 	{{T_CDROM, T_REMOV,
507 	 "SONY    ", "CD-ROM CDU-8012 ", ""},     PQUIRK_NOLUNS},
508 	{{T_CDROM, T_REMOV,
509 	 "TEAC    ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
510 	{{T_CDROM, T_REMOV,
511 	 "TEAC    ", "CD-ROM CD-56S   ", "1.0B"}, PQUIRK_NOLUNS},
512 	{{T_CDROM, T_REMOV,
513 	 "TEXEL   ", "CD-ROM          ", "1.06"}, PQUIRK_NOLUNS},
514 	{{T_CDROM, T_REMOV,
515 	 "TEXEL   ", "CD-ROM DM-XX24 K", "1.09"}, PQUIRK_NOLUNS},
516 	{{T_CDROM, T_REMOV,
517 	 "TEXEL   ", "CD-ROM DM-XX24 K", "1.10"}, PQUIRK_NOLUNS},
518 	{{T_CDROM, T_REMOV,
519 	 "TOSHIBA ", "XM-4101TASUNSLCD", ""}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
520 	/* "IBM CDRM00201     !F" 0724 is an IBM OEM Toshiba XM-4101BME */
521 	{{T_CDROM, T_REMOV,
522 	 "IBM     ", "CDRM00201     !F", "0724"}, PQUIRK_NOLUNS|PQUIRK_NOSYNC},
523 	{{T_CDROM, T_REMOV,
524 	 "ShinaKen", "CD-ROM DM-3x1S",   "1.04"}, PQUIRK_NOLUNS},
525 	{{T_CDROM, T_REMOV,
526 	 "JVC     ", "R2626",            ""},     PQUIRK_NOLUNS},
527 	{{T_CDROM, T_REMOV,
528 	 "YAMAHA", "CRW8424S",           ""},     PQUIRK_NOLUNS},
529 	{{T_CDROM, T_REMOV,
530 	 "NEC     ", "CD-ROM DRIVE:222", ""},	  PQUIRK_NOLUNS|PQUIRK_NOSYNC},
531 
532 	{{T_DIRECT, T_FIXED,
533 	 "MICROP  ", "1588-15MBSUN0669", ""},     PQUIRK_AUTOSAVE},
534 	{{T_DIRECT, T_FIXED,
535 	 "MICROP  ", "2217-15MQ1091501", ""},     PQUIRK_NOSYNCCACHE},
536 	{{T_OPTICAL, T_REMOV,
537 	 "EPSON   ", "OMD-5010        ", "3.08"}, PQUIRK_NOLUNS},
538 	{{T_DIRECT, T_FIXED,
539 	 "ADAPTEC ", "AEC-4412BD",       "1.2A"}, PQUIRK_NOMODESENSE},
540 	{{T_DIRECT, T_FIXED,
541 	 "ADAPTEC ", "ACB-4000",         ""},     PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE|PQUIRK_NOMODESENSE},
542 	{{T_DIRECT, T_FIXED,
543 	 "DEC     ", "RZ55     (C) DEC", ""},     PQUIRK_AUTOSAVE},
544 	{{T_DIRECT, T_FIXED,
545 	 "EMULEX  ", "MD21/S2     ESDI", "A00"},
546 				PQUIRK_FORCELUNS|PQUIRK_AUTOSAVE},
547 	{{T_DIRECT, T_FIXED,
548 	 "MICROP",  "1548-15MZ1077801",  "HZ2P"}, PQUIRK_NOTAG},
549 	{{T_DIRECT, T_FIXED,
550 	 "HP      ", "C372",             ""},     PQUIRK_NOTAG},
551 	{{T_DIRECT, T_FIXED,
552 	 "IBMRAID ", "0662S",		 ""},     PQUIRK_AUTOSAVE},
553 	{{T_DIRECT, T_FIXED,
554 	 "IBM     ", "0663H",		 ""},     PQUIRK_AUTOSAVE},
555 	{{T_DIRECT, T_FIXED,
556 	 "IBM",	     "0664",		 ""},     PQUIRK_AUTOSAVE},
557 	{{T_DIRECT, T_FIXED,
558 	/* improperly report DT-only sync mode */
559 	 "IBM     ", "DXHS36D",		 ""},
560 				PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
561 	{{T_DIRECT, T_FIXED,
562 	 "IBM     ", "DXHS18Y",		 ""},
563 				PQUIRK_CAP_SYNC|PQUIRK_CAP_WIDE16},
564 	{{T_DIRECT, T_FIXED,
565 	 "IBM     ", "H3171-S2",	 ""},
566 				PQUIRK_NOLUNS|PQUIRK_AUTOSAVE},
567 	{{T_DIRECT, T_FIXED,
568 	 "IBM     ", "KZ-C",		 ""},	  PQUIRK_AUTOSAVE},
569 	/* Broken IBM disk */
570 	{{T_DIRECT, T_FIXED,
571 	 ""	   , "DFRSS2F",		 ""},	  PQUIRK_AUTOSAVE},
572 	{{T_DIRECT, T_FIXED,
573 	 "Initio  ", "",		 ""},	  PQUIRK_NOBIGMODESENSE},
574 	{{T_DIRECT, T_REMOV,
575 	 "MPL     ", "MC-DISK-        ", ""},     PQUIRK_NOLUNS},
576 	{{T_DIRECT, T_FIXED,
577 	 "MAXTOR  ", "XT-3280         ", ""},     PQUIRK_NOLUNS},
578 	{{T_DIRECT, T_FIXED,
579 	 "MAXTOR  ", "XT-4380S        ", ""},     PQUIRK_NOLUNS},
580 	{{T_DIRECT, T_FIXED,
581 	 "MAXTOR  ", "MXT-1240S       ", ""},     PQUIRK_NOLUNS},
582 	{{T_DIRECT, T_FIXED,
583 	 "MAXTOR  ", "XT-4170S        ", ""},     PQUIRK_NOLUNS},
584 	{{T_DIRECT, T_FIXED,
585 	 "MAXTOR  ", "XT-8760S",         ""},     PQUIRK_NOLUNS},
586 	{{T_DIRECT, T_FIXED,
587 	 "MAXTOR  ", "LXT-213S        ", ""},     PQUIRK_NOLUNS},
588 	{{T_DIRECT, T_FIXED,
589 	 "MAXTOR  ", "LXT-213S SUN0207", ""},     PQUIRK_NOLUNS},
590 	{{T_DIRECT, T_FIXED,
591 	 "MAXTOR  ", "LXT-200S        ", ""},     PQUIRK_NOLUNS},
592 	{{T_DIRECT, T_FIXED,
593 	 "MEGADRV ", "EV1000",           ""},     PQUIRK_NOMODESENSE},
594 	{{T_DIRECT, T_FIXED,
595 	 "MICROP", "1991-27MZ",          ""},     PQUIRK_NOTAG},
596 	{{T_DIRECT, T_FIXED,
597 	 "MST     ", "SnapLink        ", ""},     PQUIRK_NOLUNS},
598 	{{T_DIRECT, T_FIXED,
599 	 "NEC     ", "D3847           ", "0307"}, PQUIRK_NOLUNS},
600 	{{T_DIRECT, T_FIXED,
601 	 "QUANTUM ", "ELS85S          ", ""},     PQUIRK_AUTOSAVE},
602 	{{T_DIRECT, T_FIXED,
603 	 "QUANTUM ", "LPS525S         ", ""},     PQUIRK_NOLUNS},
604 	{{T_DIRECT, T_FIXED,
605 	 "QUANTUM ", "P105S 910-10-94x", ""},     PQUIRK_NOLUNS},
606 	{{T_DIRECT, T_FIXED,
607 	 "QUANTUM ", "PD1225S         ", ""},     PQUIRK_NOLUNS},
608 	{{T_DIRECT, T_FIXED,
609 	 "QUANTUM ", "PD210S   SUN0207", ""},     PQUIRK_NOLUNS},
610 	{{T_DIRECT, T_FIXED,
611 	 "QUANTUM ", "ATLAS IV 9 WLS", "0A0A"},   PQUIRK_CAP_NODT},
612 	{{T_DIRECT, T_FIXED,
613 	 "RODIME  ", "RO3000S         ", ""},     PQUIRK_NOLUNS},
614 	{{T_DIRECT, T_FIXED,
615 	 "SEAGATE ", "ST125N          ", ""},     PQUIRK_NOLUNS},
616 	{{T_DIRECT, T_FIXED,
617 	 "SEAGATE ", "ST157N          ", ""},     PQUIRK_NOLUNS},
618 	{{T_DIRECT, T_FIXED,
619 	 "SEAGATE ", "ST296           ", ""},     PQUIRK_NOLUNS},
620 	{{T_DIRECT, T_FIXED,
621 	 "SEAGATE ", "ST296N          ", ""},     PQUIRK_NOLUNS},
622 	{{T_DIRECT, T_FIXED,
623 	 "SEAGATE ", "ST318404LC      ", ""},     PQUIRK_NOLUNS},
624 	{{T_DIRECT, T_FIXED,
625 	 "SEAGATE ", "ST15150N        ", ""},     PQUIRK_NOTAG},
626 	{{T_DIRECT, T_FIXED,
627 	 "SEAGATE ", "ST19171",          ""},     PQUIRK_NOMODESENSE},
628 	{{T_DIRECT, T_FIXED,
629 	 "SEAGATE ", "ST32430N",         ""},     PQUIRK_CAP_SYNC},
630 	{{T_DIRECT, T_FIXED,
631 	 "SEAGATE ", "ST34501FC       ", ""},     PQUIRK_NOMODESENSE},
632 	{{T_DIRECT, T_FIXED,
633 	 "SEAGATE ", "SX910800N",        ""},     PQUIRK_NOTAG},
634 	{{T_DIRECT, T_FIXED,
635 	 "TOSHIBA ", "MK538FB         ", "6027"}, PQUIRK_NOLUNS},
636 	{{T_DIRECT, T_FIXED,
637 	 "MICROP  ", "1924",          ""},     PQUIRK_CAP_SYNC},
638 	{{T_DIRECT, T_FIXED,
639 	 "FUJITSU ", "M2266",         ""},     PQUIRK_CAP_SYNC},
640 	{{T_DIRECT, T_FIXED,
641 	 "FUJITSU ", "M2624S-512      ", ""},     PQUIRK_CAP_SYNC},
642 	{{T_DIRECT, T_FIXED,
643 	 "SEAGATE ", "SX336704LC"   , ""}, PQUIRK_CAP_SYNC | PQUIRK_CAP_WIDE16},
644 
645 	{{T_DIRECT, T_REMOV,
646 	 "IOMEGA", "ZIP 100",		 "J.03"}, PQUIRK_NOLUNS},
647 	{{T_DIRECT, T_REMOV,
648 	 "INSITE", "I325VM",             ""},     PQUIRK_NOLUNS},
649 
650 	/* XXX: QIC-36 tape behind Emulex adapter.  Very broken. */
651 	{{T_SEQUENTIAL, T_REMOV,
652 	 "        ", "                ", "    "}, PQUIRK_NOLUNS},
653 	{{T_SEQUENTIAL, T_REMOV,
654 	 "EMULEX  ", "MT-02 QIC       ", ""},     PQUIRK_NOLUNS},
655 	{{T_SEQUENTIAL, T_REMOV,
656 	 "CALIPER ", "CP150           ", ""},     PQUIRK_NOLUNS},
657 	{{T_SEQUENTIAL, T_REMOV,
658 	 "EXABYTE ", "EXB-8200        ", ""},     PQUIRK_NOLUNS},
659 	{{T_SEQUENTIAL, T_REMOV,
660 	 "SONY    ", "GY-10C          ", ""},     PQUIRK_NOLUNS},
661 	{{T_SEQUENTIAL, T_REMOV,
662 	 "SONY    ", "SDT-2000        ", "2.09"}, PQUIRK_NOLUNS},
663 	{{T_SEQUENTIAL, T_REMOV,
664 	 "SONY    ", "SDT-5000        ", "3."},   PQUIRK_NOSYNC|PQUIRK_NOWIDE},
665 	{{T_SEQUENTIAL, T_REMOV,
666 	 "SONY    ", "SDT-5200        ", "3."},   PQUIRK_NOLUNS},
667 	{{T_SEQUENTIAL, T_REMOV,
668 	 "TANDBERG", " TDC 3600       ", ""},     PQUIRK_NOLUNS},
669 	/* Following entry reported as a Tandberg 3600; ref. PR1933 */
670 	{{T_SEQUENTIAL, T_REMOV,
671 	 "ARCHIVE ", "VIPER 150  21247", ""},     PQUIRK_NOLUNS},
672 	/* Following entry for a Cipher ST150S; ref. PR4171 */
673 	{{T_SEQUENTIAL, T_REMOV,
674 	 "ARCHIVE ", "VIPER 1500 21247", "2.2G"}, PQUIRK_NOLUNS},
675 	{{T_SEQUENTIAL, T_REMOV,
676 	 "ARCHIVE ", "Python 28454-XXX", ""},     PQUIRK_NOLUNS},
677 	{{T_SEQUENTIAL, T_REMOV,
678 	 "WANGTEK ", "5099ES SCSI",      ""},     PQUIRK_NOLUNS},
679 	{{T_SEQUENTIAL, T_REMOV,
680 	 "WANGTEK ", "5150ES SCSI",      ""},     PQUIRK_NOLUNS},
681 	{{T_SEQUENTIAL, T_REMOV,
682 	 "WANGTEK ", "SCSI-36",		 ""},     PQUIRK_NOLUNS},
683 	{{T_SEQUENTIAL, T_REMOV,
684 	 "WangDAT ", "Model 1300      ", "02.4"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
685 	{{T_SEQUENTIAL, T_REMOV,
686 	 "WangDAT ", "Model 2600      ", "01.7"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
687 	{{T_SEQUENTIAL, T_REMOV,
688 	 "WangDAT ", "Model 3200      ", "02.2"}, PQUIRK_NOSYNC|PQUIRK_NOWIDE},
689 	{{T_SEQUENTIAL, T_REMOV,
690 	 "TEAC    ", "MT-2ST/N50      ", ""},     PQUIRK_NOLUNS},
691 
692 	{{T_SCANNER, T_FIXED,
693 	 "RICOH   ", "IS60            ", "1R08"}, PQUIRK_NOLUNS},
694 	{{T_SCANNER, T_FIXED,
695 	 "UMAX    ", "Astra 1200S     ", "V2.9"}, PQUIRK_NOLUNS},
696 	{{T_SCANNER, T_FIXED,
697 	 "UMAX    ", "Astra 1220S     ", ""},     PQUIRK_NOLUNS},
698 	{{T_SCANNER, T_FIXED,
699 	 "UMAX    ", "UMAX S-6E       ", "V2.0"}, PQUIRK_NOLUNS},
700 	{{T_SCANNER, T_FIXED,
701 	 "UMAX    ", "UMAX S-12       ", "V2.1"}, PQUIRK_NOLUNS},
702 	{{T_SCANNER, T_FIXED,
703 	 "ULTIMA  ", "A6000C          ", ""},     PQUIRK_NOLUNS},
704 	{{T_PROCESSOR, T_FIXED,
705 	 "ESG-SHV",  "SCA HSBP M15",     ""},     PQUIRK_NOLUNS},
706 	{{T_PROCESSOR, T_FIXED,
707 	 "SYMBIOS",  "",                 ""},     PQUIRK_NOLUNS},
708 	{{T_PROCESSOR, T_FIXED,
709 	 "LITRONIC", "PCMCIA          ", ""},     PQUIRK_NOLUNS},
710 	{{T_CHANGER, T_REMOV,
711 	 "SONY    ", "CDL1100         ", ""},     PQUIRK_NOLUNS},
712 	{{T_ENCLOSURE, T_FIXED,
713 	 "SUN     ", "SENA            ", ""},     PQUIRK_NOLUNS},
714 };
715 
716 /*
717  * given a target and lun, ask the device what
718  * it is, and find the correct driver table
719  * entry.
720  */
721 static int
722 scsi_probe_device(struct scsibus_softc *sc, int target, int lun)
723 {
724 	struct scsipi_channel *chan = sc->sc_channel;
725 	struct scsipi_periph *periph;
726 	struct scsipi_inquiry_data inqbuf;
727 	const struct scsi_quirk_inquiry_pattern *finger;
728 	int checkdtype, priority, docontinue, quirks;
729 	struct scsipibus_attach_args sa;
730 	cfdata_t cf;
731 	int locs[SCSIBUSCF_NLOCS];
732 	device_t chld;
733 
734 	/*
735 	 * Assume no more luns to search after this one.
736 	 * If we successfully get Inquiry data and after
737 	 * merging quirks we find we can probe for more
738 	 * luns, we will.
739 	 */
740 	docontinue = 0;
741 
742 	/* Skip this slot if it is already attached. */
743 	if (scsipi_lookup_periph(chan, target, lun) != NULL)
744 		return (docontinue);
745 
746 	periph = scsipi_alloc_periph(M_NOWAIT);
747 	if (periph == NULL) {
748 #ifdef	DIAGNOSTIC
749 		aprint_error_dev(sc->sc_dev,
750 		    "cannot allocate periph for target %d lun %d\n",
751 		    target, lun);
752 #endif
753 		return (ENOMEM);
754 	}
755 	periph->periph_channel = chan;
756 	periph->periph_switch = &scsi_probe_dev;
757 
758 	periph->periph_target = target;
759 	periph->periph_lun = lun;
760 	periph->periph_quirks = chan->chan_defquirks;
761 
762 #ifdef SCSIPI_DEBUG
763 	if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_SCSI &&
764 	    SCSIPI_DEBUG_TARGET == target &&
765 	    SCSIPI_DEBUG_LUN == lun)
766 		periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS;
767 #endif
768 
769 	/*
770 	 * Ask the device what it is
771 	 */
772 
773 #ifdef SCSI_2_DEF
774 	/* some devices need to be told to go to SCSI2 */
775 	/* However some just explode if you tell them this.. leave it out */
776 	scsi_change_def(periph, XS_CTL_DISCOVERY | XS_CTL_SILENT);
777 #endif /* SCSI_2_DEF */
778 
779 	/* Now go ask the device all about itself. */
780 	memset(&inqbuf, 0, sizeof(inqbuf));
781 	{
782 		u_int8_t *extension = &inqbuf.flags1;
783 		int len = 0;
784 		while (len < 3)
785 			extension[len++] = '\0';
786 		while (len < 3 + 28)
787 			extension[len++] = ' ';
788 		while (len < 3 + 28 + 20)
789 			extension[len++] = '\0';
790 		while (len < 3 + 28 + 20 + 1)
791 			extension[len++] = '\0';
792 		while (len < 3 + 28 + 20 + 1 + 1)
793 			extension[len++] = '\0';
794 		while (len < 3 + 28 + 20 + 1 + 1 + (8*2))
795 			extension[len++] = ' ';
796 	}
797 	if (scsipi_inquire(periph, &inqbuf,
798 	    XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK | XS_CTL_SILENT) != 0)
799 		goto bad;
800 
801 	periph->periph_type = inqbuf.device & SID_TYPE;
802 	if (inqbuf.dev_qual2 & SID_REMOVABLE)
803 		periph->periph_flags |= PERIPH_REMOVABLE;
804 	periph->periph_version = inqbuf.version & SID_ANSII;
805 
806 	/*
807 	 * Any device qualifier that has the top bit set (qualifier&4 != 0)
808 	 * is vendor specific and won't match in this switch.
809 	 * All we do here is throw out bad/negative responses.
810 	 */
811 	checkdtype = 0;
812 	switch (inqbuf.device & SID_QUAL) {
813 	case SID_QUAL_LU_PRESENT:
814 		checkdtype = 1;
815 		break;
816 
817 	case SID_QUAL_LU_NOTPRESENT:
818 	case SID_QUAL_reserved:
819 	case SID_QUAL_LU_NOT_SUPP:
820 		goto bad;
821 
822 	default:
823 		break;
824 	}
825 
826 	/* Let the adapter driver handle the device separatley if it wants. */
827 	if (chan->chan_adapter->adapt_accesschk != NULL &&
828 	    (*chan->chan_adapter->adapt_accesschk)(periph, &sa.sa_inqbuf))
829 		goto bad;
830 
831 	if (checkdtype) {
832 		switch (periph->periph_type) {
833 		case T_DIRECT:
834 		case T_SEQUENTIAL:
835 		case T_PRINTER:
836 		case T_PROCESSOR:
837 		case T_WORM:
838 		case T_CDROM:
839 		case T_SCANNER:
840 		case T_OPTICAL:
841 		case T_CHANGER:
842 		case T_COMM:
843 		case T_IT8_1:
844 		case T_IT8_2:
845 		case T_STORARRAY:
846 		case T_ENCLOSURE:
847 		case T_SIMPLE_DIRECT:
848 		case T_OPTIC_CARD_RW:
849 		case T_OBJECT_STORED:
850 		default:
851 			break;
852 		case T_NODEVICE:
853 			goto bad;
854 		}
855 	}
856 
857 	sa.sa_periph = periph;
858 	sa.sa_inqbuf.type = inqbuf.device;
859 	sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
860 	    T_REMOV : T_FIXED;
861 	sa.sa_inqbuf.vendor = inqbuf.vendor;
862 	sa.sa_inqbuf.product = inqbuf.product;
863 	sa.sa_inqbuf.revision = inqbuf.revision;
864 	sa.scsipi_info.scsi_version = inqbuf.version;
865 	sa.sa_inqptr = &inqbuf;
866 
867 	finger = scsipi_inqmatch(
868 	    &sa.sa_inqbuf, scsi_quirk_patterns,
869 	    sizeof(scsi_quirk_patterns)/sizeof(scsi_quirk_patterns[0]),
870 	    sizeof(scsi_quirk_patterns[0]), &priority);
871 
872 	if (finger != NULL)
873 		quirks = finger->quirks;
874 	else
875 		quirks = 0;
876 
877 	/*
878 	 * Determine the operating mode capabilities of the device.
879 	 */
880 	if (periph->periph_version >= 2) {
881 		if ((inqbuf.flags3 & SID_CmdQue) != 0 &&
882 		    (quirks & PQUIRK_NOTAG) == 0)
883 			periph->periph_cap |= PERIPH_CAP_TQING;
884 		if ((inqbuf.flags3 & SID_Linked) != 0)
885 			periph->periph_cap |= PERIPH_CAP_LINKCMDS;
886 		if ((inqbuf.flags3 & SID_Sync) != 0 &&
887 		    (quirks & PQUIRK_NOSYNC) == 0)
888 			periph->periph_cap |= PERIPH_CAP_SYNC;
889 		if ((inqbuf.flags3 & SID_WBus16) != 0 &&
890 		    (quirks & PQUIRK_NOWIDE) == 0)
891 			periph->periph_cap |= PERIPH_CAP_WIDE16;
892 		if ((inqbuf.flags3 & SID_WBus32) != 0 &&
893 		    (quirks & PQUIRK_NOWIDE) == 0)
894 			periph->periph_cap |= PERIPH_CAP_WIDE32;
895 		if ((inqbuf.flags3 & SID_SftRe) != 0)
896 			periph->periph_cap |= PERIPH_CAP_SFTRESET;
897 		if ((inqbuf.flags3 & SID_RelAdr) != 0)
898 			periph->periph_cap |= PERIPH_CAP_RELADR;
899 		/* SPC-2 */
900 		if (periph->periph_version >= 3 &&
901 		    !(quirks & PQUIRK_CAP_NODT)){
902 			/*
903 			 * Report ST clocking though CAP_WIDExx/CAP_SYNC.
904 			 * If the device only supports DT, clear these
905 			 * flags (DT implies SYNC and WIDE)
906 			 */
907 			switch (inqbuf.flags4 & SID_Clocking) {
908 			case SID_CLOCKING_DT_ONLY:
909 				periph->periph_cap &=
910 				    ~(PERIPH_CAP_SYNC |
911 				      PERIPH_CAP_WIDE16 |
912 				      PERIPH_CAP_WIDE32);
913 				/* FALLTHROUGH */
914 			case SID_CLOCKING_SD_DT:
915 				periph->periph_cap |= PERIPH_CAP_DT;
916 				break;
917 			default: /* ST only or invalid */
918 				/* nothing to do */
919 				break;
920 			}
921 		}
922 		if (periph->periph_version >= 3) {
923 			if (inqbuf.flags4 & SID_IUS)
924 				periph->periph_cap |= PERIPH_CAP_IUS;
925 			if (inqbuf.flags4 & SID_QAS)
926 				periph->periph_cap |= PERIPH_CAP_QAS;
927 		}
928 	}
929 	if (quirks & PQUIRK_CAP_SYNC)
930 		periph->periph_cap |= PERIPH_CAP_SYNC;
931 	if (quirks & PQUIRK_CAP_WIDE16)
932 		periph->periph_cap |= PERIPH_CAP_WIDE16;
933 
934 	/*
935 	 * Now apply any quirks from the table.
936 	 */
937 	periph->periph_quirks |= quirks;
938 	if (periph->periph_version == 0 &&
939 	    (periph->periph_quirks & PQUIRK_FORCELUNS) == 0)
940 		periph->periph_quirks |= PQUIRK_NOLUNS;
941 
942 	if ((periph->periph_quirks & PQUIRK_NOLUNS) == 0)
943 		docontinue = 1;
944 
945 	locs[SCSIBUSCF_TARGET] = target;
946 	locs[SCSIBUSCF_LUN] = lun;
947 
948 	if ((cf = config_search_loc(config_stdsubmatch, sc->sc_dev,
949 	     "scsibus", locs, &sa)) != NULL) {
950 		scsipi_insert_periph(chan, periph);
951 		/*
952 		 * XXX Can't assign periph_dev here, because we'll
953 		 * XXX need it before config_attach() returns.  Must
954 		 * XXX assign it in periph driver.
955 		 */
956 		chld = config_attach_loc(sc->sc_dev, cf, locs, &sa,
957 					 scsibusprint);
958 	} else {
959 		scsibusprint(&sa, device_xname(sc->sc_dev));
960 		aprint_normal(" not configured\n");
961 		goto bad;
962 	}
963 
964 	return (docontinue);
965 
966 bad:
967 	free(periph, M_DEVBUF);
968 	return (docontinue);
969 }
970 
971 /****** Entry points for user control of the SCSI bus. ******/
972 
973 static int
974 scsibusopen(dev_t dev, int flag, int fmt,
975     struct lwp *l)
976 {
977 	struct scsibus_softc *sc;
978 	int error, unit = minor(dev);
979 
980 	sc = device_lookup_private(&scsibus_cd, unit);
981 	if (sc == NULL)
982 		return (ENXIO);
983 
984 	if (sc->sc_flags & SCSIBUSF_OPEN)
985 		return (EBUSY);
986 
987 	if ((error = scsipi_adapter_addref(sc->sc_channel->chan_adapter)) != 0)
988 		return (error);
989 
990 	sc->sc_flags |= SCSIBUSF_OPEN;
991 
992 	return (0);
993 }
994 
995 static int
996 scsibusclose(dev_t dev, int flag, int fmt,
997     struct lwp *l)
998 {
999 	struct scsibus_softc *sc;
1000 
1001 	sc = device_lookup_private(&scsibus_cd, minor(dev));
1002 	scsipi_adapter_delref(sc->sc_channel->chan_adapter);
1003 
1004 	sc->sc_flags &= ~SCSIBUSF_OPEN;
1005 
1006 	return (0);
1007 }
1008 
1009 static int
1010 scsibusioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
1011 {
1012 	struct scsibus_softc *sc;
1013 	struct scsipi_channel *chan;
1014 	int error;
1015 
1016 	sc = device_lookup_private(&scsibus_cd, minor(dev));
1017 	chan = sc->sc_channel;
1018 
1019 	/*
1020 	 * Enforce write permission for ioctls that change the
1021 	 * state of the bus.  Host adapter specific ioctls must
1022 	 * be checked by the adapter driver.
1023 	 */
1024 	switch (cmd) {
1025 	case SCBUSIOSCAN:
1026 	case SCBUSIODETACH:
1027 	case SCBUSIORESET:
1028 		if ((flag & FWRITE) == 0)
1029 			return (EBADF);
1030 	}
1031 
1032 	switch (cmd) {
1033 	case SCBUSIOSCAN:
1034 	    {
1035 		struct scbusioscan_args *a =
1036 		    (struct scbusioscan_args *)addr;
1037 
1038 		error = scsi_probe_bus(sc, a->sa_target, a->sa_lun);
1039 		break;
1040 	    }
1041 
1042 	case SCBUSIODETACH:
1043 	    {
1044 		struct scbusiodetach_args *a =
1045 		    (struct scbusiodetach_args *)addr;
1046 
1047 		error = scsipi_target_detach(chan, a->sa_target, a->sa_lun, 0);
1048 		break;
1049 	    }
1050 
1051 
1052 	case SCBUSIORESET:
1053 		/* FALLTHROUGH */
1054 	default:
1055 		if (chan->chan_adapter->adapt_ioctl == NULL)
1056 			error = ENOTTY;
1057 		else
1058 			error = (*chan->chan_adapter->adapt_ioctl)(chan,
1059 			    cmd, addr, flag, l->l_proc);
1060 		break;
1061 	}
1062 
1063 	return (error);
1064 }
1065