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