[BACK]Return to atapiconf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / scsipi

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>