atapiconf.c revision 1.2.2.3 1 1.2.2.3 thorpej /* $NetBSD: atapiconf.c,v 1.2.2.3 1997/09/01 20:58:57 thorpej Exp $ */
2 1.2.2.2 thorpej
3 1.2.2.2 thorpej /*
4 1.2.2.2 thorpej * Copyright (c) 1996 Manuel Bouyer. All rights reserved.
5 1.2.2.2 thorpej *
6 1.2.2.2 thorpej * Redistribution and use in source and binary forms, with or without
7 1.2.2.2 thorpej * modification, are permitted provided that the following conditions
8 1.2.2.2 thorpej * are met:
9 1.2.2.2 thorpej * 1. Redistributions of source code must retain the above copyright
10 1.2.2.2 thorpej * notice, this list of conditions and the following disclaimer.
11 1.2.2.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright
12 1.2.2.2 thorpej * notice, this list of conditions and the following disclaimer in the
13 1.2.2.2 thorpej * documentation and/or other materials provided with the distribution.
14 1.2.2.2 thorpej * 3. All advertising materials mentioning features or use of this software
15 1.2.2.2 thorpej * must display the following acknowledgement:
16 1.2.2.2 thorpej * This product includes software developed by Manuel Bouyer.
17 1.2.2.2 thorpej * 4. The name of the author may not be used to endorse or promote products
18 1.2.2.2 thorpej * derived from this software without specific prior written permission.
19 1.2.2.2 thorpej *
20 1.2.2.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 1.2.2.2 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 1.2.2.2 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 1.2.2.2 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 1.2.2.2 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 1.2.2.2 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 1.2.2.2 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 1.2.2.2 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 1.2.2.2 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 1.2.2.2 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 1.2.2.2 thorpej */
31 1.2.2.2 thorpej
32 1.2.2.2 thorpej #include <sys/types.h>
33 1.2.2.2 thorpej #include <sys/param.h>
34 1.2.2.2 thorpej #include <sys/systm.h>
35 1.2.2.2 thorpej #include <sys/malloc.h>
36 1.2.2.2 thorpej #include <sys/device.h>
37 1.2.2.2 thorpej #include <sys/buf.h>
38 1.2.2.2 thorpej #include <sys/proc.h>
39 1.2.2.2 thorpej
40 1.2.2.2 thorpej #include <dev/scsipi/scsipi_all.h>
41 1.2.2.2 thorpej #include <dev/scsipi/scsi_all.h>
42 1.2.2.2 thorpej #include <dev/scsipi/scsipiconf.h>
43 1.2.2.2 thorpej #include <dev/scsipi/atapiconf.h>
44 1.2.2.2 thorpej #include "locators.h"
45 1.2.2.2 thorpej
46 1.2.2.2 thorpej #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
47 1.2.2.2 thorpej
48 1.2.2.2 thorpej struct atapibus_softc {
49 1.2.2.2 thorpej struct device sc_dev;
50 1.2.2.2 thorpej struct scsipi_link *adapter_link; /* proto supplied by adapter */
51 1.2.2.2 thorpej struct scsipi_link **sc_link; /* dynamically allocated */
52 1.2.2.2 thorpej };
53 1.2.2.2 thorpej
54 1.2.2.2 thorpej #ifdef __BROKEN_INDIRECT_CONFIG
55 1.2.2.2 thorpej int atapibusmatch __P((struct device *, void *, void *));
56 1.2.2.2 thorpej int atapibussubmatch __P((struct device *, void *, void *));
57 1.2.2.2 thorpej #else
58 1.2.2.2 thorpej int atapibusmatch __P((struct device *, struct cfdata *, void *));
59 1.2.2.2 thorpej int atapibussubmatch __P((struct device *, struct cfdata *, void *));
60 1.2.2.2 thorpej #endif
61 1.2.2.2 thorpej void atapibusattach __P((struct device *, struct device *, void *));
62 1.2.2.2 thorpej int atapiprint __P((void *, const char *));
63 1.2.2.2 thorpej
64 1.2.2.2 thorpej int atapi_probe_bus __P((int, int));
65 1.2.2.2 thorpej void atapi_probedev __P((struct atapibus_softc *, int ));
66 1.2.2.2 thorpej
67 1.2.2.2 thorpej struct cfattach atapibus_ca = {
68 1.2.2.2 thorpej sizeof(struct atapibus_softc), atapibusmatch, atapibusattach
69 1.2.2.2 thorpej };
70 1.2.2.2 thorpej
71 1.2.2.2 thorpej struct cfdriver atapibus_cd = {
72 1.2.2.2 thorpej NULL, "atapibus", DV_DULL
73 1.2.2.2 thorpej };
74 1.2.2.2 thorpej
75 1.2.2.2 thorpej int atapibusprint __P((void *, const char *));
76 1.2.2.2 thorpej
77 1.2.2.2 thorpej struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = {
78 1.2.2.2 thorpej {{T_CDROM, T_REMOV,
79 1.2.2.2 thorpej "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC},
80 1.2.2.2 thorpej {{T_CDROM, T_REMOV,
81 1.2.2.2 thorpej "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY},
82 1.2.2.2 thorpej {{T_CDROM, T_REMOV,
83 1.2.2.3 thorpej "SANYO CRD-254P", "", "1.02"}, ADEV_NOCAPACITY},
84 1.2.2.3 thorpej {{T_CDROM, T_REMOV,
85 1.2.2.2 thorpej "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK},
86 1.2.2.2 thorpej {{T_CDROM, T_REMOV,
87 1.2.2.2 thorpej "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR},
88 1.2.2.2 thorpej {{T_CDROM, T_REMOV,
89 1.2.2.2 thorpej "NEC CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR},
90 1.2.2.3 thorpej {{T_CDROM, T_REMOV,
91 1.2.2.3 thorpej "MATSHITA CR-574", "", "1.06"}, ADEV_NOCAPACITY},
92 1.2.2.2 thorpej };
93 1.2.2.2 thorpej
94 1.2.2.2 thorpej int
95 1.2.2.2 thorpej #ifdef __BROKEN_INDIRECT_CONFIG
96 1.2.2.2 thorpej atapibusmatch(parent, match, aux)
97 1.2.2.2 thorpej struct device *parent;
98 1.2.2.2 thorpej void *match, *aux;
99 1.2.2.2 thorpej {
100 1.2.2.2 thorpej #else
101 1.2.2.2 thorpej atapibusmatch(parent, cf, aux)
102 1.2.2.2 thorpej struct device *parent;
103 1.2.2.2 thorpej struct cfdata *cf;
104 1.2.2.2 thorpej void *aux;
105 1.2.2.2 thorpej {
106 1.2.2.2 thorpej #endif
107 1.2.2.2 thorpej struct scsipi_link *sc_link = aux;
108 1.2.2.2 thorpej
109 1.2.2.2 thorpej if (sc_link == NULL)
110 1.2.2.2 thorpej return 0;
111 1.2.2.2 thorpej if (sc_link->type != BUS_ATAPI)
112 1.2.2.2 thorpej return 0;
113 1.2.2.2 thorpej return 1;
114 1.2.2.2 thorpej }
115 1.2.2.2 thorpej
116 1.2.2.2 thorpej int
117 1.2.2.2 thorpej #ifdef __BROKEN_INDIRECT_CONFIG
118 1.2.2.2 thorpej atapibussubmatch(parent, match, aux)
119 1.2.2.2 thorpej struct device *parent;
120 1.2.2.2 thorpej void *match, *aux;
121 1.2.2.2 thorpej {
122 1.2.2.2 thorpej struct cfdata *cf = match;
123 1.2.2.2 thorpej #else
124 1.2.2.2 thorpej atapibussubmatch(parent, cf, aux)
125 1.2.2.2 thorpej struct device *parent;
126 1.2.2.2 thorpej struct cfdata *cf;
127 1.2.2.2 thorpej void *aux;
128 1.2.2.2 thorpej {
129 1.2.2.2 thorpej #endif
130 1.2.2.2 thorpej struct scsipibus_attach_args *sa = aux;
131 1.2.2.2 thorpej struct scsipi_link *sc_link = sa->sa_sc_link;
132 1.2.2.2 thorpej
133 1.2.2.2 thorpej if (cf->cf_loc[ATAPIBUSCF_DRIVE] != ATAPIBUSCF_DRIVE_DEFAULT &&
134 1.2.2.2 thorpej cf->cf_loc[ATAPIBUSCF_DRIVE] != sc_link->scsipi_atapi.drive)
135 1.2.2.2 thorpej return 0;
136 1.2.2.2 thorpej return ((*cf->cf_attach->ca_match)(parent, cf, aux));
137 1.2.2.2 thorpej }
138 1.2.2.2 thorpej
139 1.2.2.2 thorpej
140 1.2.2.2 thorpej #if 0
141 1.2.2.2 thorpej void
142 1.2.2.2 thorpej atapi_fixquirk(sc_link)
143 1.2.2.2 thorpej struct scsipi_link *ad_link;
144 1.2.2.2 thorpej {
145 1.2.2.2 thorpej struct atapi_identify *id = &ad_link->id;
146 1.2.2.2 thorpej struct atapi_quirk_inquiry_pattern *quirk;
147 1.2.2.2 thorpej
148 1.2.2.2 thorpej
149 1.2.2.2 thorpej /*
150 1.2.2.2 thorpej * Clean up the model name, serial and
151 1.2.2.2 thorpej * revision numbers.
152 1.2.2.2 thorpej */
153 1.2.2.2 thorpej btrim(id->model, sizeof(id->model));
154 1.2.2.2 thorpej btrim(id->serial_number, sizeof(id->serial_number));
155 1.2.2.2 thorpej btrim(id->firmware_revision, sizeof(id->firmware_revision));
156 1.2.2.2 thorpej
157 1.2.2.2 thorpej }
158 1.2.2.2 thorpej #endif
159 1.2.2.2 thorpej
160 1.2.2.2 thorpej
161 1.2.2.2 thorpej void
162 1.2.2.2 thorpej atapibusattach(parent, self, aux)
163 1.2.2.2 thorpej struct device *parent, *self;
164 1.2.2.2 thorpej void *aux;
165 1.2.2.2 thorpej {
166 1.2.2.2 thorpej struct atapibus_softc *ab = (struct atapibus_softc *)self;
167 1.2.2.2 thorpej struct scsipi_link *sc_link_proto = aux;
168 1.2.2.2 thorpej int nbytes;
169 1.2.2.2 thorpej
170 1.2.2.2 thorpej printf("\n");
171 1.2.2.2 thorpej
172 1.2.2.2 thorpej sc_link_proto->scsipi_atapi.atapibus = ab->sc_dev.dv_unit;
173 1.2.2.2 thorpej sc_link_proto->scsipi_cmd = atapi_scsipi_cmd;
174 1.2.2.2 thorpej sc_link_proto->scsipi_interpret_sense = atapi_interpret_sense;
175 1.2.2.2 thorpej sc_link_proto->sc_print_addr = atapi_print_addr;
176 1.2.2.2 thorpej
177 1.2.2.2 thorpej ab->adapter_link = sc_link_proto;
178 1.2.2.2 thorpej
179 1.2.2.2 thorpej nbytes = 2 * sizeof(struct scsipi_link **);
180 1.2.2.2 thorpej ab->sc_link = (struct scsipi_link **)malloc(nbytes, M_DEVBUF,
181 1.2.2.2 thorpej M_NOWAIT);
182 1.2.2.2 thorpej if (ab->sc_link == NULL)
183 1.2.2.2 thorpej panic("scsibusattach: can't allocate target links");
184 1.2.2.2 thorpej bzero(ab->sc_link, nbytes);
185 1.2.2.2 thorpej atapi_probe_bus(ab->sc_dev.dv_unit, -1);
186 1.2.2.2 thorpej }
187 1.2.2.2 thorpej
188 1.2.2.2 thorpej int
189 1.2.2.2 thorpej atapi_probe_bus(bus, target)
190 1.2.2.2 thorpej int bus, target;
191 1.2.2.2 thorpej {
192 1.2.2.2 thorpej int maxtarget, mintarget;
193 1.2.2.2 thorpej struct atapibus_softc *atapi;
194 1.2.2.2 thorpej if (bus < 0 || bus >= atapibus_cd.cd_ndevs)
195 1.2.2.2 thorpej return ENXIO;
196 1.2.2.2 thorpej atapi = atapibus_cd.cd_devs[bus];
197 1.2.2.2 thorpej if (!atapi)
198 1.2.2.2 thorpej return ENXIO;
199 1.2.2.2 thorpej
200 1.2.2.2 thorpej if (target == -1) {
201 1.2.2.2 thorpej maxtarget = 1;
202 1.2.2.2 thorpej mintarget = 0;
203 1.2.2.2 thorpej } else {
204 1.2.2.2 thorpej if (target < 0 || target > 1)
205 1.2.2.2 thorpej return ENXIO;
206 1.2.2.2 thorpej maxtarget = mintarget = target;
207 1.2.2.2 thorpej }
208 1.2.2.2 thorpej for (target = mintarget; target <= maxtarget; target++) {
209 1.2.2.2 thorpej atapi_probedev(atapi, target);
210 1.2.2.2 thorpej }
211 1.2.2.2 thorpej return 0;
212 1.2.2.2 thorpej }
213 1.2.2.2 thorpej
214 1.2.2.2 thorpej void
215 1.2.2.2 thorpej atapi_probedev(atapi, target)
216 1.2.2.2 thorpej struct atapibus_softc *atapi;
217 1.2.2.2 thorpej int target;
218 1.2.2.2 thorpej {
219 1.2.2.2 thorpej struct scsipi_link *sc_link;
220 1.2.2.2 thorpej struct scsipibus_attach_args sa;
221 1.2.2.2 thorpej struct atapi_identify ids;
222 1.2.2.2 thorpej struct atapi_identify *id = &ids;
223 1.2.2.2 thorpej struct cfdata *cf;
224 1.2.2.2 thorpej struct scsi_quirk_inquiry_pattern *finger;
225 1.2.2.2 thorpej int priority;
226 1.2.2.2 thorpej char serial_number[20], model[40], firmware_revision[8];
227 1.2.2.2 thorpej
228 1.2.2.2 thorpej /* skip if already attached */
229 1.2.2.2 thorpej if (atapi->sc_link[target])
230 1.2.2.2 thorpej return;
231 1.2.2.2 thorpej
232 1.2.2.2 thorpej if (wdc_atapi_get_params(atapi->adapter_link, target, id)) {
233 1.2.2.2 thorpej #ifdef ATAPI_DEBUG_PROBE
234 1.2.2.2 thorpej printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
235 1.2.2.2 thorpej atapi->sc_dev.dv_xname, target,
236 1.2.2.2 thorpej id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_MASK,
237 1.2.2.2 thorpej id->config.cmd_drq_rem & ATAPI_DRQ_MASK);
238 1.2.2.2 thorpej #endif
239 1.2.2.2 thorpej /*
240 1.2.2.2 thorpej * Shuffle string byte order.
241 1.2.2.2 thorpej * Mitsumi and NEC drives don't need this.
242 1.2.2.2 thorpej */
243 1.2.2.2 thorpej if (((id->model[0] == 'N' && id->model[1] == 'E') ||
244 1.2.2.2 thorpej (id->model[0] == 'F' && id->model[1] == 'X')) == 0)
245 1.2.2.2 thorpej bswap(id->model, sizeof(id->model));
246 1.2.2.2 thorpej bswap(id->serial_number, sizeof(id->serial_number));
247 1.2.2.2 thorpej bswap(id->firmware_revision, sizeof(id->firmware_revision));
248 1.2.2.2 thorpej
249 1.2.2.2 thorpej /*
250 1.2.2.2 thorpej * Allocate a device link and try and attach
251 1.2.2.2 thorpej * a driver to this device. If we fail, free
252 1.2.2.2 thorpej * the link.
253 1.2.2.2 thorpej */
254 1.2.2.2 thorpej sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
255 1.2.2.2 thorpej if (sc_link == NULL) {
256 1.2.2.2 thorpej printf("%s: can't allocate link for drive %d\n",
257 1.2.2.2 thorpej atapi->sc_dev.dv_xname, target);
258 1.2.2.2 thorpej return;
259 1.2.2.2 thorpej }
260 1.2.2.2 thorpej /* Fill in link. */
261 1.2.2.2 thorpej *sc_link = *atapi->adapter_link;
262 1.2.2.2 thorpej sc_link->scsipi_atapi.drive = target;
263 1.2.2.2 thorpej sc_link->device = NULL;
264 1.2.2.2 thorpej #if defined(SCSIDEBUG) && DEBUGTYPE == BUS_ATAPI
265 1.2.2.2 thorpej if (DEBUGTARGET == -1 || target == DEBUGTARGET)
266 1.2.2.2 thorpej sc_link->flags |= DEBUGLEVEL;
267 1.2.2.2 thorpej #endif /* SCSIDEBUG */
268 1.2.2.2 thorpej if (id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_16)
269 1.2.2.2 thorpej sc_link->scsipi_atapi.cap |= ACAP_LEN;
270 1.2.2.2 thorpej sc_link->scsipi_atapi.cap |=
271 1.2.2.2 thorpej (id->config.cmd_drq_rem & ATAPI_DRQ_MASK) << 3;
272 1.2.2.2 thorpej #if 0
273 1.2.2.2 thorpej bcopy(id, &ad_link->id, sizeof(*id));
274 1.2.2.2 thorpej /* Fix strings and look through the quirk table. */
275 1.2.2.2 thorpej atapi_fixquirk(ad_link, id);
276 1.2.2.2 thorpej #endif
277 1.2.2.2 thorpej sa.sa_sc_link = sc_link;
278 1.2.2.2 thorpej sa.sa_inqbuf.type = id->config.device_type & SID_TYPE;
279 1.2.2.2 thorpej sa.sa_inqbuf.removable =
280 1.2.2.2 thorpej id->config.cmd_drq_rem & ATAPI_REMOVABLE ?
281 1.2.2.2 thorpej T_REMOV : T_FIXED;
282 1.2.2.2 thorpej if (sa.sa_inqbuf.removable)
283 1.2.2.2 thorpej sc_link->flags |= SDEV_REMOVABLE;
284 1.2.2.2 thorpej scsipi_strvis(model, id->model, 40);
285 1.2.2.2 thorpej scsipi_strvis(serial_number, id->serial_number, 20);
286 1.2.2.2 thorpej scsipi_strvis(firmware_revision, id->firmware_revision, 8);
287 1.2.2.2 thorpej sa.sa_inqbuf.vendor = model;
288 1.2.2.2 thorpej sa.sa_inqbuf.product = serial_number;
289 1.2.2.2 thorpej sa.sa_inqbuf.revision = firmware_revision;
290 1.2.2.2 thorpej
291 1.2.2.2 thorpej finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch(
292 1.2.2.2 thorpej &sa.sa_inqbuf, (caddr_t)atapi_quirk_patterns,
293 1.2.2.2 thorpej sizeof(atapi_quirk_patterns) /
294 1.2.2.2 thorpej sizeof(atapi_quirk_patterns[0]),
295 1.2.2.2 thorpej sizeof(atapi_quirk_patterns[0]), &priority);
296 1.2.2.2 thorpej if (priority != 0)
297 1.2.2.2 thorpej sc_link->quirks |= finger->quirks;
298 1.2.2.2 thorpej
299 1.2.2.2 thorpej if ((cf = config_search(atapibussubmatch, &atapi->sc_dev,
300 1.2.2.2 thorpej &sa)) != 0) {
301 1.2.2.2 thorpej atapi->sc_link[target] = sc_link;
302 1.2.2.2 thorpej config_attach(&atapi->sc_dev, cf, &sa, atapibusprint);
303 1.2.2.2 thorpej return;
304 1.2.2.2 thorpej } else {
305 1.2.2.2 thorpej atapibusprint(&sa, atapi->sc_dev.dv_xname);
306 1.2.2.2 thorpej printf(" not configured\n");
307 1.2.2.2 thorpej free(sc_link, M_DEVBUF);
308 1.2.2.2 thorpej return;
309 1.2.2.2 thorpej }
310 1.2.2.2 thorpej
311 1.2.2.2 thorpej #if 0 /* WAS: */
312 1.2.2.2 thorpej /* Try to find a match. */
313 1.2.2.2 thorpej if (config_found(self, ad_link, atapiprint) == NULL)
314 1.2.2.2 thorpej free(ad_link, M_DEVBUF);
315 1.2.2.2 thorpej #endif
316 1.2.2.2 thorpej }
317 1.2.2.2 thorpej }
318 1.2.2.2 thorpej
319 1.2.2.2 thorpej int
320 1.2.2.2 thorpej atapibusprint(aux, pnp)
321 1.2.2.2 thorpej void *aux;
322 1.2.2.2 thorpej const char *pnp;
323 1.2.2.2 thorpej {
324 1.2.2.2 thorpej struct scsipibus_attach_args *sa = aux;
325 1.2.2.2 thorpej struct scsipi_inquiry_pattern *inqbuf;
326 1.2.2.2 thorpej char *dtype;
327 1.2.2.2 thorpej
328 1.2.2.2 thorpej if (pnp != NULL)
329 1.2.2.2 thorpej printf("%s", pnp);
330 1.2.2.2 thorpej
331 1.2.2.2 thorpej inqbuf = &sa->sa_inqbuf;
332 1.2.2.2 thorpej
333 1.2.2.2 thorpej dtype = scsipi_dtype(inqbuf->type & SID_TYPE);
334 1.2.2.2 thorpej printf(" drive %d: <%s, %s, %s> type %d %s %s",
335 1.2.2.2 thorpej sa->sa_sc_link->scsipi_atapi.drive,inqbuf->vendor,
336 1.2.2.2 thorpej inqbuf->product, inqbuf->revision, inqbuf->type, dtype,
337 1.2.2.2 thorpej inqbuf->removable ? "removable" : "fixed");
338 1.2.2.2 thorpej return (UNCONF);
339 1.2.2.2 thorpej }
340