Annotation of src/sys/dev/scsipi/atapiconf.c, Revision 1.28.2.10
1.28.2.10! bouyer 1: /* $NetBSD: atapiconf.c,v 1.28.2.9 2001/03/27 15:32:16 bouyer Exp $ */
1.2 bouyer 2:
3: /*
4: * Copyright (c) 1996 Manuel Bouyer. All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by Manuel Bouyer.
17: * 4. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: #include <sys/types.h>
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/malloc.h>
36: #include <sys/device.h>
37: #include <sys/buf.h>
1.4 enami 38: #include <sys/proc.h>
1.28.2.1 thorpej 39: #include <sys/kthread.h>
1.2 bouyer 40:
1.13 bouyer 41: #include <dev/ata/atavar.h>
1.2 bouyer 42: #include <dev/scsipi/scsipi_all.h>
1.9 cgd 43: #include <dev/scsipi/atapi_all.h>
1.2 bouyer 44: #include <dev/scsipi/scsipiconf.h>
45: #include <dev/scsipi/atapiconf.h>
1.4 enami 46:
1.2 bouyer 47: #include "locators.h"
48:
49: #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
1.27 enami 50: #define MAX_TARGET 1
1.2 bouyer 51:
1.28.2.1 thorpej 52: const struct scsipi_periphsw atapi_probe_periphsw = {
53: NULL,
54: NULL,
55: NULL,
56: NULL,
57: };
58:
1.2 bouyer 59: int atapibusmatch __P((struct device *, struct cfdata *, void *));
60: void atapibusattach __P((struct device *, struct device *, void *));
1.27 enami 61: int atapibusactivate __P((struct device *, enum devact));
62: int atapibusdetach __P((struct device *, int flags));
63:
1.28.2.1 thorpej 64: int atapibussubmatch __P((struct device *, struct cfdata *, void *));
65:
66: int atapi_probe_bus __P((struct atapibus_softc *, int));
1.2 bouyer 67:
68: struct cfattach atapibus_ca = {
1.27 enami 69: sizeof(struct atapibus_softc), atapibusmatch, atapibusattach,
70: atapibusdetach, atapibusactivate,
1.2 bouyer 71: };
72:
1.8 thorpej 73: extern struct cfdriver atapibus_cd;
1.2 bouyer 74:
75: int atapibusprint __P((void *, const char *));
76:
1.28.2.7 bouyer 77: const struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = {
1.2 bouyer 78: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 79: "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, PQUIRK_NOTUR},
1.2 bouyer 80: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 81: "BCD-16X 1997-04-25", "", "VER 2.2"}, PQUIRK_NOSTARTUNIT},
1.26 bouyer 82: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 83: "BCD-24X 1997-06-27", "", "VER 2.0"}, PQUIRK_NOSTARTUNIT},
1.22 bouyer 84: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 85: "CR-2801TE", "", "1.07"}, PQUIRK_NOSENSE},
1.23 bouyer 86: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 87: "CREATIVECD3630E", "", "AC101"}, PQUIRK_NOSENSE},
1.2 bouyer 88: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 89: "FX320S", "", "q01"}, PQUIRK_NOSENSE},
1.21 bouyer 90: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 91: "GCD-R580B", "", "1.00"}, PQUIRK_LITTLETOC},
1.24 bouyer 92: {{T_CDROM, T_REMOV,
1.28.2.6 bouyer 93: "HITACHI CDR-7730", "", "0008a"}, PQUIRK_NOSENSE},
94: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 95: "MATSHITA CR-574", "", "1.02"}, PQUIRK_NOCAPACITY},
1.3 bouyer 96: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 97: "MATSHITA CR-574", "", "1.06"}, PQUIRK_NOCAPACITY},
1.7 bouyer 98: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 99: "Memorex CRW-2642", "", "1.0g"}, PQUIRK_NOSENSE},
1.7 bouyer 100: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 101: "NEC CD-ROM DRIVE:273", "", "4.21"}, PQUIRK_NOTUR},
1.2 bouyer 102: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 103: "SANYO CRD-256P", "", "1.02"}, PQUIRK_NOCAPACITY},
1.2 bouyer 104: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 105: "SANYO CRD-254P", "", "1.02"}, PQUIRK_NOCAPACITY},
1.3 bouyer 106: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 107: "SANYO CRD-S54P", "", "1.08"}, PQUIRK_NOCAPACITY},
1.5 bouyer 108: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 109: "CD-ROM CDR-S1", "", "1.70"}, PQUIRK_NOCAPACITY}, /* Sanyo */
1.18 bouyer 110: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 111: "CD-ROM CDR-N16", "", "1.25"}, PQUIRK_NOCAPACITY}, /* Sanyo */
1.20 bouyer 112: {{T_CDROM, T_REMOV,
1.28.2.1 thorpej 113: "UJDCD8730", "", "1.14"}, PQUIRK_NODOORLOCK}, /* Acer */
1.28.2.9 bouyer 114: {{T_DIRECT, T_REMOV, /* Panasonic MultiMediaCard */
115: "04DA", "1B00", "0010"}, PQUIRK_BYTE5_ZERO |
116: PQUIRK_NO_FLEX_PAGE },
1.28.2.10! bouyer 117: {{T_DIRECT, T_REMOV, /* ZiO! MultiMediaCard */
! 118: "eUSB", "MultiMediaCard", ""}, PQUIRK_NO_FLEX_PAGE },
1.2 bouyer 119: };
120:
121: int
122: atapibusmatch(parent, cf, aux)
123: struct device *parent;
124: struct cfdata *cf;
125: void *aux;
126: {
1.28.2.1 thorpej 127: struct ata_atapi_attach *aa = aux;
1.2 bouyer 128:
1.28.2.1 thorpej 129: if (aa == NULL)
1.4 enami 130: return (0);
1.28.2.1 thorpej 131:
132: if (aa->aa_type != T_ATAPI)
1.4 enami 133: return (0);
1.28.2.1 thorpej 134:
135: if (cf->cf_loc[ATAPICF_CHANNEL] != aa->aa_channel &&
1.13 bouyer 136: cf->cf_loc[ATAPICF_CHANNEL] != ATAPICF_CHANNEL_DEFAULT)
1.28.2.1 thorpej 137: return (0);
138:
1.4 enami 139: return (1);
1.2 bouyer 140: }
141:
142: int
143: atapibussubmatch(parent, cf, aux)
144: struct device *parent;
145: struct cfdata *cf;
146: void *aux;
147: {
148: struct scsipibus_attach_args *sa = aux;
1.28.2.1 thorpej 149: struct scsipi_periph *periph = sa->sa_periph;
1.2 bouyer 150:
151: if (cf->cf_loc[ATAPIBUSCF_DRIVE] != ATAPIBUSCF_DRIVE_DEFAULT &&
1.28.2.1 thorpej 152: cf->cf_loc[ATAPIBUSCF_DRIVE] != periph->periph_target)
1.4 enami 153: return (0);
1.2 bouyer 154: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
155: }
156:
157: void
158: atapibusattach(parent, self, aux)
1.4 enami 159: struct device *parent, *self;
160: void *aux;
1.2 bouyer 161: {
1.28.2.1 thorpej 162: struct atapibus_softc *sc = (void *) self;
163: struct ata_atapi_attach *aa = aux;
164: struct scsipi_channel *chan = aa->aa_bus_private;
165:
166: sc->sc_channel = chan;
167: sc->sc_drvs = aa->aa_drv_data;
168:
169: /* ATAPI has no LUNs. */
170: chan->chan_nluns = 1;
171: printf(": %d targets\n", chan->chan_ntargets);
172:
173: /* Initialize the channel. */
174: scsipi_channel_init(chan);
175:
176: /* Probe the bus for devices. */
177: atapi_probe_bus(sc, -1);
1.27 enami 178: }
179:
180: int
181: atapibusactivate(self, act)
182: struct device *self;
183: enum devact act;
184: {
1.28.2.1 thorpej 185: struct atapibus_softc *sc = (void *) self;
186: struct scsipi_channel *chan = sc->sc_channel;
187: struct scsipi_periph *periph;
1.27 enami 188: int target, error = 0, s;
189:
190: s = splbio();
191: switch (act) {
192: case DVACT_ACTIVATE:
193: error = EOPNOTSUPP;
194: break;
195:
196: case DVACT_DEACTIVATE:
1.28.2.1 thorpej 197: for (target = 0; target < chan->chan_ntargets; target++) {
1.28.2.5 thorpej 198: periph = scsipi_lookup_periph(chan, target, 0);
1.28.2.1 thorpej 199: if (periph == NULL)
1.27 enami 200: continue;
1.28.2.1 thorpej 201: error = config_deactivate(periph->periph_dev);
202: if (error)
1.27 enami 203: goto out;
204: }
205: break;
206: }
207: out:
208: splx(s);
209: return (error);
210: }
211:
212: int
213: atapibusdetach(self, flags)
214: struct device *self;
215: int flags;
216: {
1.28.2.1 thorpej 217: struct atapibus_softc *sc = (void *)self;
218: struct scsipi_channel *chan = sc->sc_channel;
219: struct scsipi_periph *periph;
1.27 enami 220: int target, error;
221:
1.28.2.5 thorpej 222: /*
223: * Shut down the channel.
224: */
225: scsipi_channel_shutdown(chan);
226:
227: /*
228: * Now detach all of the periphs.
229: */
1.28.2.1 thorpej 230: for (target = 0; target < chan->chan_ntargets; target++) {
1.28.2.5 thorpej 231: periph = scsipi_lookup_periph(chan, target, 0);
1.28.2.1 thorpej 232: if (periph == NULL)
1.27 enami 233: continue;
1.28.2.1 thorpej 234: error = config_detach(periph->periph_dev, flags);
235: if (error)
1.27 enami 236: return (error);
237:
238: /*
239: * We have successfully detached the child. Drop the
240: * direct reference for the child so that wdcdetach
241: * won't call detach routine twice.
242: */
243: #ifdef DIAGNOSTIC
1.28.2.1 thorpej 244: if (periph->periph_dev != sc->sc_drvs[target].drv_softc)
1.27 enami 245: panic("softc mismatch");
246: #endif
247: sc->sc_drvs[target].drv_softc = NULL;
248:
1.28.2.5 thorpej 249: scsipi_remove_periph(chan, periph);
1.28.2.1 thorpej 250: free(periph, M_DEVBUF);
1.27 enami 251: }
252: return (0);
1.2 bouyer 253: }
254:
1.4 enami 255: int
1.28.2.1 thorpej 256: atapi_probe_bus(sc, target)
257: struct atapibus_softc *sc;
258: int target;
1.2 bouyer 259: {
1.28.2.1 thorpej 260: struct scsipi_channel *chan = sc->sc_channel;
1.2 bouyer 261: int maxtarget, mintarget;
1.15 thorpej 262: int error;
1.28.2.6 bouyer 263: struct atapi_adapter *atapi_adapter;
1.4 enami 264:
1.2 bouyer 265: if (target == -1) {
266: maxtarget = 1;
267: mintarget = 0;
268: } else {
1.28.2.1 thorpej 269: if (target < 0 || target >= chan->chan_ntargets)
1.4 enami 270: return (ENXIO);
1.2 bouyer 271: maxtarget = mintarget = target;
272: }
1.28.2.1 thorpej 273:
274: if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
1.15 thorpej 275: return (error);
1.28.2.6 bouyer 276: atapi_adapter = (struct atapi_adapter*)chan->chan_adapter;
1.4 enami 277: for (target = mintarget; target <= maxtarget; target++)
1.28.2.6 bouyer 278: atapi_adapter->atapi_probe_device(sc, target);
1.28.2.1 thorpej 279: scsipi_adapter_delref(chan->chan_adapter);
1.4 enami 280: return (0);
1.2 bouyer 281: }
282:
1.28.2.6 bouyer 283: void *
284: atapi_probe_device(sc, target, periph, sa)
1.28.2.1 thorpej 285: struct atapibus_softc *sc;
1.2 bouyer 286: int target;
1.28.2.6 bouyer 287: struct scsipi_periph *periph;
288: struct scsipibus_attach_args *sa;
1.2 bouyer 289: {
1.28.2.1 thorpej 290: struct scsipi_channel *chan = sc->sc_channel;
1.2 bouyer 291: struct scsi_quirk_inquiry_pattern *finger;
1.28.2.1 thorpej 292: struct cfdata *cf;
293: int priority, quirks;
1.2 bouyer 294:
1.28.2.6 bouyer 295: finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch(
296: &sa->sa_inqbuf, (caddr_t)atapi_quirk_patterns,
297: sizeof(atapi_quirk_patterns) /
298: sizeof(atapi_quirk_patterns[0]),
299: sizeof(atapi_quirk_patterns[0]), &priority);
300:
301: if (finger != NULL)
302: quirks = finger->quirks;
303: else
304: quirks = 0;
1.28.2.1 thorpej 305:
1.28.2.6 bouyer 306: /*
307: * Now apply any quirks from the table.
308: */
309: periph->periph_quirks |= quirks;
1.28.2.1 thorpej 310:
1.28.2.6 bouyer 311: if ((cf = config_search(atapibussubmatch, &sc->sc_dev,
312: sa)) != 0) {
313: scsipi_insert_periph(chan, periph);
1.28.2.1 thorpej 314: /*
1.28.2.6 bouyer 315: * XXX Can't assign periph_dev here, because we'll
316: * XXX need it before config_attach() returns. Must
317: * XXX assign it in periph driver.
1.28.2.1 thorpej 318: */
1.28.2.6 bouyer 319: return config_attach(&sc->sc_dev, cf, sa,
320: atapibusprint);
321: } else {
322: atapibusprint(&sa, sc->sc_dev.dv_xname);
323: printf(" not configured\n");
324: free(periph, M_DEVBUF);
325: return NULL;
1.2 bouyer 326: }
327: }
328:
329: int
330: atapibusprint(aux, pnp)
331: void *aux;
332: const char *pnp;
333: {
334: struct scsipibus_attach_args *sa = aux;
335: struct scsipi_inquiry_pattern *inqbuf;
336: char *dtype;
337:
338: if (pnp != NULL)
339: printf("%s", pnp);
340:
341: inqbuf = &sa->sa_inqbuf;
342:
343: dtype = scsipi_dtype(inqbuf->type & SID_TYPE);
344: printf(" drive %d: <%s, %s, %s> type %d %s %s",
1.28.2.1 thorpej 345: sa->sa_periph->periph_target ,inqbuf->vendor,
1.2 bouyer 346: inqbuf->product, inqbuf->revision, inqbuf->type, dtype,
347: inqbuf->removable ? "removable" : "fixed");
348: return (UNCONF);
349: }
CVSweb <webmaster@jp.NetBSD.org>