Annotation of src/sys/dev/scsipi/atapiconf.c, Revision 1.73.2.1
1.73.2.1! ad 1: /* $NetBSD: atapiconf.c,v 1.74 2007/12/09 20:28:22 jmcneill Exp $ */
1.2 bouyer 2:
3: /*
1.46 bouyer 4: * Copyright (c) 1996, 2001 Manuel Bouyer. All rights reserved.
1.2 bouyer 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: */
1.42 lukem 31:
32: #include <sys/cdefs.h>
1.73.2.1! ad 33: __KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.74 2007/12/09 20:28:22 jmcneill Exp $");
1.2 bouyer 34:
35: #include <sys/param.h>
36: #include <sys/systm.h>
37: #include <sys/malloc.h>
38: #include <sys/device.h>
39: #include <sys/buf.h>
1.4 enami 40: #include <sys/proc.h>
1.39 bouyer 41: #include <sys/kthread.h>
1.2 bouyer 42:
43: #include <dev/scsipi/scsipi_all.h>
1.39 bouyer 44: #include <dev/scsipi/scsipiconf.h>
1.2 bouyer 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.39 bouyer 52: const struct scsipi_periphsw atapi_probe_periphsw = {
53: NULL,
54: NULL,
55: NULL,
56: NULL,
57: };
58:
1.64 thorpej 59: static int atapibusmatch(struct device *, struct cfdata *, void *);
60: static void atapibusattach(struct device *, struct device *, void *);
61: static int atapibusactivate(struct device *, enum devact);
62: static int atapibusdetach(struct device *, int flags);
1.2 bouyer 63:
1.66 drochner 64: static int atapibussubmatch(struct device *, struct cfdata *,
1.68 drochner 65: const int *, void *);
1.39 bouyer 66:
1.64 thorpej 67: static int atapi_probe_bus(struct atapibus_softc *, int);
68:
69: static int atapibusprint(void *, const char *);
1.2 bouyer 70:
1.52 thorpej 71: CFATTACH_DECL(atapibus, sizeof(struct atapibus_softc),
1.53 thorpej 72: atapibusmatch, atapibusattach, atapibusdetach, atapibusactivate);
1.2 bouyer 73:
1.8 thorpej 74: extern struct cfdriver atapibus_cd;
1.2 bouyer 75:
1.64 thorpej 76: static const struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = {
1.2 bouyer 77: {{T_CDROM, T_REMOV,
1.39 bouyer 78: "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, PQUIRK_NOTUR},
1.22 bouyer 79: {{T_CDROM, T_REMOV,
1.39 bouyer 80: "CR-2801TE", "", "1.07"}, PQUIRK_NOSENSE},
1.23 bouyer 81: {{T_CDROM, T_REMOV,
1.39 bouyer 82: "CREATIVECD3630E", "", "AC101"}, PQUIRK_NOSENSE},
1.2 bouyer 83: {{T_CDROM, T_REMOV,
1.39 bouyer 84: "FX320S", "", "q01"}, PQUIRK_NOSENSE},
1.21 bouyer 85: {{T_CDROM, T_REMOV,
1.39 bouyer 86: "GCD-R580B", "", "1.00"}, PQUIRK_LITTLETOC},
1.31 jdolecek 87: {{T_CDROM, T_REMOV,
1.39 bouyer 88: "HITACHI CDR-7730", "", "0008a"}, PQUIRK_NOSENSE},
1.24 bouyer 89: {{T_CDROM, T_REMOV,
1.39 bouyer 90: "MATSHITA CR-574", "", "1.02"}, PQUIRK_NOCAPACITY},
1.3 bouyer 91: {{T_CDROM, T_REMOV,
1.39 bouyer 92: "MATSHITA CR-574", "", "1.06"}, PQUIRK_NOCAPACITY},
1.7 bouyer 93: {{T_CDROM, T_REMOV,
1.39 bouyer 94: "Memorex CRW-2642", "", "1.0g"}, PQUIRK_NOSENSE},
1.7 bouyer 95: {{T_CDROM, T_REMOV,
1.39 bouyer 96: "NEC CD-ROM DRIVE:273", "", "4.21"}, PQUIRK_NOTUR},
1.2 bouyer 97: {{T_CDROM, T_REMOV,
1.39 bouyer 98: "SANYO CRD-256P", "", "1.02"}, PQUIRK_NOCAPACITY},
1.2 bouyer 99: {{T_CDROM, T_REMOV,
1.39 bouyer 100: "SANYO CRD-254P", "", "1.02"}, PQUIRK_NOCAPACITY},
1.3 bouyer 101: {{T_CDROM, T_REMOV,
1.39 bouyer 102: "SANYO CRD-S54P", "", "1.08"}, PQUIRK_NOCAPACITY},
1.5 bouyer 103: {{T_CDROM, T_REMOV,
1.39 bouyer 104: "CD-ROM CDR-S1", "", "1.70"}, PQUIRK_NOCAPACITY}, /* Sanyo */
1.18 bouyer 105: {{T_CDROM, T_REMOV,
1.39 bouyer 106: "CD-ROM CDR-N16", "", "1.25"}, PQUIRK_NOCAPACITY}, /* Sanyo */
1.2 bouyer 107: };
108:
109: int
1.72 christos 110: atapiprint(void *aux, const char *pnp)
1.44 bouyer 111: {
112: if (pnp)
1.55 thorpej 113: aprint_normal("atapibus at %s", pnp);
1.44 bouyer 114: return (UNCONF);
115: }
116:
1.64 thorpej 117: static int
1.72 christos 118: atapibusmatch(struct device *parent, struct cfdata *cf,
1.71 christos 119: void *aux)
1.2 bouyer 120: {
1.44 bouyer 121: struct scsipi_channel *chan = aux;
1.2 bouyer 122:
1.44 bouyer 123: if (chan == NULL)
1.4 enami 124: return (0);
1.39 bouyer 125:
1.44 bouyer 126: if (chan->chan_bustype->bustype_type != SCSIPI_BUSTYPE_ATAPI)
1.39 bouyer 127: return (0);
128:
1.4 enami 129: return (1);
1.2 bouyer 130: }
131:
1.64 thorpej 132: static int
1.66 drochner 133: atapibussubmatch(struct device *parent, struct cfdata *cf,
1.72 christos 134: const int *ldesc, void *aux)
1.2 bouyer 135: {
136: struct scsipibus_attach_args *sa = aux;
1.39 bouyer 137: struct scsipi_periph *periph = sa->sa_periph;
1.2 bouyer 138:
139: if (cf->cf_loc[ATAPIBUSCF_DRIVE] != ATAPIBUSCF_DRIVE_DEFAULT &&
1.39 bouyer 140: cf->cf_loc[ATAPIBUSCF_DRIVE] != periph->periph_target)
1.4 enami 141: return (0);
1.50 thorpej 142: return (config_match(parent, cf, aux));
1.2 bouyer 143: }
144:
1.64 thorpej 145: static void
1.72 christos 146: atapibusattach(struct device *parent, struct device *self, void *aux)
1.2 bouyer 147: {
1.70 thorpej 148: struct atapibus_softc *sc = device_private(self);
1.44 bouyer 149: struct scsipi_channel *chan = aux;
1.39 bouyer 150:
151: sc->sc_channel = chan;
1.48 bouyer 152:
153: chan->chan_name = sc->sc_dev.dv_xname;
1.39 bouyer 154:
155: /* ATAPI has no LUNs. */
156: chan->chan_nluns = 1;
1.73 jmcneill 157: aprint_naive("\n");
158: aprint_normal(": %d targets\n", chan->chan_ntargets);
1.39 bouyer 159:
160: /* Initialize the channel. */
1.49 jmc 161: chan->chan_init_cb = NULL;
162: chan->chan_init_cb_arg = NULL;
1.39 bouyer 163: scsipi_channel_init(chan);
164:
1.73.2.1! ad 165: if (!pmf_device_register(self, NULL, NULL))
! 166: aprint_error_dev(self, "couldn't establish power handler\n");
! 167:
1.39 bouyer 168: /* Probe the bus for devices. */
169: atapi_probe_bus(sc, -1);
1.27 enami 170: }
171:
1.64 thorpej 172: static int
173: atapibusactivate(struct device *self, enum devact act)
1.27 enami 174: {
1.70 thorpej 175: struct atapibus_softc *sc = device_private(self);
1.39 bouyer 176: struct scsipi_channel *chan = sc->sc_channel;
177: struct scsipi_periph *periph;
1.27 enami 178: int target, error = 0, s;
179:
180: s = splbio();
181: switch (act) {
182: case DVACT_ACTIVATE:
183: error = EOPNOTSUPP;
184: break;
185:
186: case DVACT_DEACTIVATE:
1.39 bouyer 187: for (target = 0; target < chan->chan_ntargets; target++) {
188: periph = scsipi_lookup_periph(chan, target, 0);
189: if (periph == NULL)
1.27 enami 190: continue;
1.39 bouyer 191: error = config_deactivate(periph->periph_dev);
192: if (error)
1.27 enami 193: goto out;
194: }
195: break;
196: }
197: out:
198: splx(s);
199: return (error);
200: }
201:
1.64 thorpej 202: static int
203: atapibusdetach(struct device *self, int flags)
1.27 enami 204: {
1.70 thorpej 205: struct atapibus_softc *sc = device_private(self);
1.39 bouyer 206: struct scsipi_channel *chan = sc->sc_channel;
207: struct scsipi_periph *periph;
1.27 enami 208: int target, error;
209:
1.39 bouyer 210: /*
211: * Shut down the channel.
212: */
213: scsipi_channel_shutdown(chan);
214:
215: /*
216: * Now detach all of the periphs.
217: */
218: for (target = 0; target < chan->chan_ntargets; target++) {
219: periph = scsipi_lookup_periph(chan, target, 0);
220: if (periph == NULL)
1.27 enami 221: continue;
1.39 bouyer 222: error = config_detach(periph->periph_dev, flags);
223: if (error)
1.27 enami 224: return (error);
225:
1.39 bouyer 226: scsipi_remove_periph(chan, periph);
227: free(periph, M_DEVBUF);
1.27 enami 228: }
229: return (0);
1.2 bouyer 230: }
231:
1.64 thorpej 232: static int
233: atapi_probe_bus(struct atapibus_softc *sc, int target)
1.2 bouyer 234: {
1.39 bouyer 235: struct scsipi_channel *chan = sc->sc_channel;
1.2 bouyer 236: int maxtarget, mintarget;
1.15 thorpej 237: int error;
1.34 bouyer 238: struct atapi_adapter *atapi_adapter;
1.4 enami 239:
1.2 bouyer 240: if (target == -1) {
241: maxtarget = 1;
242: mintarget = 0;
243: } else {
1.39 bouyer 244: if (target < 0 || target >= chan->chan_ntargets)
1.4 enami 245: return (ENXIO);
1.2 bouyer 246: maxtarget = mintarget = target;
247: }
1.39 bouyer 248:
249: if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
1.15 thorpej 250: return (error);
1.39 bouyer 251: atapi_adapter = (struct atapi_adapter*)chan->chan_adapter;
1.4 enami 252: for (target = mintarget; target <= maxtarget; target++)
1.39 bouyer 253: atapi_adapter->atapi_probe_device(sc, target);
254: scsipi_adapter_delref(chan->chan_adapter);
1.4 enami 255: return (0);
1.2 bouyer 256: }
257:
1.34 bouyer 258: void *
1.72 christos 259: atapi_probe_device(struct atapibus_softc *sc, int target,
1.64 thorpej 260: struct scsipi_periph *periph, struct scsipibus_attach_args *sa)
1.2 bouyer 261: {
1.39 bouyer 262: struct scsipi_channel *chan = sc->sc_channel;
1.67 christos 263: const struct scsi_quirk_inquiry_pattern *finger;
1.2 bouyer 264: struct cfdata *cf;
1.39 bouyer 265: int priority, quirks;
1.2 bouyer 266:
1.67 christos 267: finger = scsipi_inqmatch(
268: &sa->sa_inqbuf, (const void *)atapi_quirk_patterns,
1.34 bouyer 269: sizeof(atapi_quirk_patterns) /
270: sizeof(atapi_quirk_patterns[0]),
271: sizeof(atapi_quirk_patterns[0]), &priority);
272:
1.39 bouyer 273: if (finger != NULL)
274: quirks = finger->quirks;
275: else
276: quirks = 0;
277:
278: /*
279: * Now apply any quirks from the table.
280: */
281: periph->periph_quirks |= quirks;
282:
1.66 drochner 283: if ((cf = config_search_ia(atapibussubmatch, &sc->sc_dev,
284: "atapibus", sa)) != 0) {
1.39 bouyer 285: scsipi_insert_periph(chan, periph);
286: /*
287: * XXX Can't assign periph_dev here, because we'll
288: * XXX need it before config_attach() returns. Must
289: * XXX assign it in periph driver.
290: */
291: return config_attach(&sc->sc_dev, cf, sa,
292: atapibusprint);
1.34 bouyer 293: } else {
1.41 enami 294: atapibusprint(sa, sc->sc_dev.dv_xname);
1.34 bouyer 295: printf(" not configured\n");
1.39 bouyer 296: free(periph, M_DEVBUF);
297: return NULL;
1.2 bouyer 298: }
299: }
300:
1.64 thorpej 301: static int
302: atapibusprint(void *aux, const char *pnp)
1.2 bouyer 303: {
304: struct scsipibus_attach_args *sa = aux;
305: struct scsipi_inquiry_pattern *inqbuf;
1.65 thorpej 306: const char *dtype;
1.2 bouyer 307:
308: if (pnp != NULL)
1.55 thorpej 309: aprint_normal("%s", pnp);
1.2 bouyer 310:
311: inqbuf = &sa->sa_inqbuf;
312:
313: dtype = scsipi_dtype(inqbuf->type & SID_TYPE);
1.55 thorpej 314: aprint_normal(" drive %d: <%s, %s, %s> %s %s",
1.54 soren 315: sa->sa_periph->periph_target, inqbuf->vendor,
316: inqbuf->product, inqbuf->revision, dtype,
1.2 bouyer 317: inqbuf->removable ? "removable" : "fixed");
318: return (UNCONF);
319: }
CVSweb <webmaster@jp.NetBSD.org>