1 /* $NetBSD: atapiconf.c,v 1.80 2009/10/19 18:41:16 bouyer Exp $ */
4 * Copyright (c) 1996, 2001 Manuel Bouyer. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.80 2009/10/19 18:41:16 bouyer Exp $");
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/malloc.h>
33 #include <sys/device.h>
36 #include <sys/kthread.h>
38 #include <dev/scsipi/scsipi_all.h>
39 #include <dev/scsipi/scsipiconf.h>
40 #include <dev/scsipi/atapiconf.h>
44 #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
47 const struct scsipi_periphsw atapi_probe_periphsw
= {
54 static int atapibusmatch(device_t
, cfdata_t
, void *);
55 static void atapibusattach(device_t
, device_t
, void *);
56 static int atapibusdetach(device_t
, int flags
);
57 static void atapibuschilddet(device_t
, device_t
);
59 static int atapibussubmatch(device_t
, cfdata_t
, const int *, void *);
61 static int atapi_probe_bus(struct atapibus_softc
*, int);
63 static int atapibusprint(void *, const char *);
65 CFATTACH_DECL3_NEW(atapibus
, sizeof(struct atapibus_softc
),
66 atapibusmatch
, atapibusattach
, atapibusdetach
, NULL
, NULL
,
67 atapibuschilddet
, DVF_DETACH_SHUTDOWN
);
69 extern struct cfdriver atapibus_cd
;
71 static const struct scsi_quirk_inquiry_pattern atapi_quirk_patterns
[] = {
73 "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, PQUIRK_NOTUR
},
75 "CR-2801TE", "", "1.07"}, PQUIRK_NOSENSE
},
77 "CREATIVECD3630E", "", "AC101"}, PQUIRK_NOSENSE
},
79 "FX320S", "", "q01"}, PQUIRK_NOSENSE
},
81 "GCD-R580B", "", "1.00"}, PQUIRK_LITTLETOC
},
83 "HITACHI CDR-7730", "", "0008a"}, PQUIRK_NOSENSE
},
85 "MATSHITA CR-574", "", "1.02"}, PQUIRK_NOCAPACITY
},
87 "MATSHITA CR-574", "", "1.06"}, PQUIRK_NOCAPACITY
},
89 "Memorex CRW-2642", "", "1.0g"}, PQUIRK_NOSENSE
},
91 "NEC CD-ROM DRIVE:273", "", "4.21"}, PQUIRK_NOTUR
},
93 "SANYO CRD-256P", "", "1.02"}, PQUIRK_NOCAPACITY
},
95 "SANYO CRD-254P", "", "1.02"}, PQUIRK_NOCAPACITY
},
97 "SANYO CRD-S54P", "", "1.08"}, PQUIRK_NOCAPACITY
},
99 "CD-ROM CDR-S1", "", "1.70"}, PQUIRK_NOCAPACITY
}, /* Sanyo */
101 "CD-ROM CDR-N16", "", "1.25"}, PQUIRK_NOCAPACITY
}, /* Sanyo */
105 atapiprint(void *aux
, const char *pnp
)
108 aprint_normal("atapibus at %s", pnp
);
113 atapibusmatch(device_t parent
, cfdata_t cf
, void *aux
)
115 struct scsipi_channel
*chan
= aux
;
120 if (chan
->chan_bustype
->bustype_type
!= SCSIPI_BUSTYPE_ATAPI
)
127 atapibussubmatch(device_t parent
, cfdata_t cf
, const int *ldesc
, void *aux
)
129 struct scsipibus_attach_args
*sa
= aux
;
130 struct scsipi_periph
*periph
= sa
->sa_periph
;
132 if (cf
->cf_loc
[ATAPIBUSCF_DRIVE
] != ATAPIBUSCF_DRIVE_DEFAULT
&&
133 cf
->cf_loc
[ATAPIBUSCF_DRIVE
] != periph
->periph_target
)
135 return (config_match(parent
, cf
, aux
));
139 atapibusattach(device_t parent
, device_t self
, void *aux
)
141 struct atapibus_softc
*sc
= device_private(self
);
142 struct scsipi_channel
*chan
= aux
;
144 sc
->sc_channel
= chan
;
147 chan
->chan_name
= device_xname(sc
->sc_dev
);
149 /* ATAPI has no LUNs. */
150 chan
->chan_nluns
= 1;
152 aprint_normal(": %d targets\n", chan
->chan_ntargets
);
154 /* Initialize the channel. */
155 chan
->chan_init_cb
= NULL
;
156 chan
->chan_init_cb_arg
= NULL
;
157 scsipi_channel_init(chan
);
159 if (!pmf_device_register(self
, NULL
, NULL
))
160 aprint_error_dev(self
, "couldn't establish power handler\n");
162 /* Probe the bus for devices. */
163 atapi_probe_bus(sc
, -1);
167 atapibuschilddet(device_t self
, device_t child
)
169 struct atapibus_softc
*sc
= device_private(self
);
170 struct scsipi_channel
*chan
= sc
->sc_channel
;
171 struct scsipi_periph
*periph
;
174 for (target
= 0; target
< chan
->chan_ntargets
; target
++) {
175 periph
= scsipi_lookup_periph(chan
, target
, 0);
176 if (periph
== NULL
|| periph
->periph_dev
!= child
)
178 scsipi_remove_periph(chan
, periph
);
179 free(periph
, M_DEVBUF
);
185 atapibusdetach(device_t self
, int flags
)
187 struct atapibus_softc
*sc
= device_private(self
);
188 struct scsipi_channel
*chan
= sc
->sc_channel
;
189 struct scsipi_periph
*periph
;
193 * Shut down the channel.
195 scsipi_channel_shutdown(chan
);
198 * Now detach all of the periphs.
200 for (target
= 0; target
< chan
->chan_ntargets
; target
++) {
201 periph
= scsipi_lookup_periph(chan
, target
, 0);
204 error
= config_detach(periph
->periph_dev
, flags
);
207 KASSERT(scsipi_lookup_periph(chan
, target
, 0) == NULL
);
213 atapi_probe_bus(struct atapibus_softc
*sc
, int target
)
215 struct scsipi_channel
*chan
= sc
->sc_channel
;
216 int maxtarget
, mintarget
;
218 struct atapi_adapter
*atapi_adapter
;
224 if (target
< 0 || target
>= chan
->chan_ntargets
)
226 maxtarget
= mintarget
= target
;
229 if ((error
= scsipi_adapter_addref(chan
->chan_adapter
)) != 0)
231 atapi_adapter
= (struct atapi_adapter
*)chan
->chan_adapter
;
232 for (target
= mintarget
; target
<= maxtarget
; target
++)
233 atapi_adapter
->atapi_probe_device(sc
, target
);
234 scsipi_adapter_delref(chan
->chan_adapter
);
239 atapi_probe_device(struct atapibus_softc
*sc
, int target
,
240 struct scsipi_periph
*periph
, struct scsipibus_attach_args
*sa
)
242 struct scsipi_channel
*chan
= sc
->sc_channel
;
243 const struct scsi_quirk_inquiry_pattern
*finger
;
245 int priority
, quirks
;
247 finger
= scsipi_inqmatch(
248 &sa
->sa_inqbuf
, (const void *)atapi_quirk_patterns
,
249 sizeof(atapi_quirk_patterns
) /
250 sizeof(atapi_quirk_patterns
[0]),
251 sizeof(atapi_quirk_patterns
[0]), &priority
);
254 quirks
= finger
->quirks
;
259 * Now apply any quirks from the table.
261 periph
->periph_quirks
|= quirks
;
263 if ((cf
= config_search_ia(atapibussubmatch
, sc
->sc_dev
,
264 "atapibus", sa
)) != 0) {
265 scsipi_insert_periph(chan
, periph
);
267 * XXX Can't assign periph_dev here, because we'll
268 * XXX need it before config_attach() returns. Must
269 * XXX assign it in periph driver.
271 return config_attach(sc
->sc_dev
, cf
, sa
,
274 atapibusprint(sa
, device_xname(sc
->sc_dev
));
275 printf(" not configured\n");
276 free(periph
, M_DEVBUF
);
282 atapibusprint(void *aux
, const char *pnp
)
284 struct scsipibus_attach_args
*sa
= aux
;
285 struct scsipi_inquiry_pattern
*inqbuf
;
289 aprint_normal("%s", pnp
);
291 inqbuf
= &sa
->sa_inqbuf
;
293 dtype
= scsipi_dtype(inqbuf
->type
& SID_TYPE
);
294 aprint_normal(" drive %d: <%s, %s, %s> %s %s",
295 sa
->sa_periph
->periph_target
, inqbuf
->vendor
,
296 inqbuf
->product
, inqbuf
->revision
, dtype
,
297 inqbuf
->removable
? "removable" : "fixed");