atapiconf.c revision 1.1.2.2 1 /* $NetBSD: atapiconf.c,v 1.1.2.2 1997/07/01 22:37:08 thorpej Exp $ */
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>
38 #include <sys/proc.h>
39
40 #include <dev/scsipi/scsipi_all.h>
41 #include <dev/scsipi/scsi_all.h>
42 #include <dev/scsipi/scsipiconf.h>
43 #include <dev/scsipi/atapiconf.h>
44
45 #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
46
47 struct atapibus_softc {
48 struct device sc_dev;
49 struct scsipi_link *adapter_link; /* proto supplied by adapter */
50 struct scsipi_link **sc_link; /* dynamically allocated */
51 };
52
53 #ifdef __BROKEN_INDIRECT_CONFIG
54 int atapibusmatch __P((struct device *, void *, void *));
55 int atapibussubmatch __P((struct device *, void *, void *));
56 #else
57 int atapibusmatch __P((struct device *, struct cfdata *, void *));
58 int atapibussubmatch __P((struct device *, struct cfdata *, void *));
59 #endif
60 void atapibusattach __P((struct device *, struct device *, void *));
61 int atapiprint __P((void *, const char *));
62
63 int atapi_probe_bus __P((int, int));
64 void atapi_probedev __P((struct atapibus_softc *, int ));
65
66 struct cfattach atapibus_ca = {
67 sizeof(struct atapibus_softc), atapibusmatch, atapibusattach
68 };
69
70 struct cfdriver atapibus_cd = {
71 NULL, "atapibus", DV_DULL
72 };
73
74 int atapibusprint __P((void *, const char *));
75
76 struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = {
77 {{T_CDROM, T_REMOV,
78 "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC},
79 {{T_CDROM, T_REMOV,
80 "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY},
81 {{T_CDROM, T_REMOV,
82 "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK},
83 {{T_CDROM, T_REMOV,
84 "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR},
85 {{T_CDROM, T_REMOV,
86 "NEC CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR},
87 };
88
89 int
90 #ifdef __BROKEN_INDIRECT_CONFIG
91 atapibusmatch(parent, match, aux)
92 struct device *parent;
93 void *match, *aux;
94 {
95 #else
96 atapibusmatch(parent, cf, aux)
97 struct device *parent;
98 struct cfdata *cf;
99 void *aux;
100 {
101 #endif
102 struct scsipi_link *sc_link = aux;
103
104 if (sc_link == NULL)
105 return 0;
106 if (sc_link->type != BUS_ATAPI)
107 return 0;
108 return 1;
109 }
110
111 int
112 #ifdef __BROKEN_INDIRECT_CONFIG
113 atapibussubmatch(parent, match, aux)
114 struct device *parent;
115 void *match, *aux;
116 {
117 struct cfdata *cf = match;
118 #else
119 atapibussubmatch(parent, cf, aux)
120 struct device *parent;
121 struct cfdata *cf;
122 void *aux;
123 {
124 #endif
125 struct scsipibus_attach_args *sa = aux;
126 struct scsipi_link *sc_link = sa->sa_sc_link;
127
128 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sc_link->scsipi_atapi.drive)
129 return 0;
130 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
131 }
132
133
134 #if 0
135 void
136 atapi_fixquirk(sc_link)
137 struct scsipi_link *ad_link;
138 {
139 struct atapi_identify *id = &ad_link->id;
140 struct atapi_quirk_inquiry_pattern *quirk;
141
142
143 /*
144 * Clean up the model name, serial and
145 * revision numbers.
146 */
147 btrim(id->model, sizeof(id->model));
148 btrim(id->serial_number, sizeof(id->serial_number));
149 btrim(id->firmware_revision, sizeof(id->firmware_revision));
150
151 }
152 #endif
153
154
155 void
156 atapibusattach(parent, self, aux)
157 struct device *parent, *self;
158 void *aux;
159 {
160 struct atapibus_softc *ab = (struct atapibus_softc *)self;
161 struct scsipi_link *sc_link_proto = aux;
162 int nbytes;
163
164 printf("\n");
165
166 sc_link_proto->scsipi_atapi.atapibus = ab->sc_dev.dv_unit;
167 sc_link_proto->scsipi_cmd = atapi_scsipi_cmd;
168 sc_link_proto->scsipi_interpret_sense = atapi_interpret_sense;
169 sc_link_proto->sc_print_addr = atapi_print_addr;
170
171 ab->adapter_link = sc_link_proto;
172
173 nbytes = 2 * sizeof(struct scsipi_link **);
174 ab->sc_link = (struct scsipi_link **)malloc(nbytes, M_DEVBUF,
175 M_NOWAIT);
176 if (ab->sc_link == NULL)
177 panic("scsibusattach: can't allocate target links");
178 bzero(ab->sc_link, nbytes);
179 atapi_probe_bus(ab->sc_dev.dv_unit, -1);
180 }
181
182 int
183 atapi_probe_bus(bus, target)
184 int bus, target;
185 {
186 int maxtarget, mintarget;
187 struct atapibus_softc *atapi;
188 if (bus < 0 || bus >= atapibus_cd.cd_ndevs)
189 return ENXIO;
190 atapi = atapibus_cd.cd_devs[bus];
191 if (!atapi)
192 return ENXIO;
193
194 if (target == -1) {
195 maxtarget = 1;
196 mintarget = 0;
197 } else {
198 if (target < 0 || target > 1)
199 return ENXIO;
200 maxtarget = mintarget = target;
201 }
202 for (target = mintarget; target <= maxtarget; target++) {
203 atapi_probedev(atapi, target);
204 }
205 return 0;
206 }
207
208 void
209 atapi_probedev(atapi, target)
210 struct atapibus_softc *atapi;
211 int target;
212 {
213 struct scsipi_link *sc_link;
214 struct scsipibus_attach_args sa;
215 struct atapi_identify ids;
216 struct atapi_identify *id = &ids;
217 struct cfdata *cf;
218 struct scsi_quirk_inquiry_pattern *finger;
219 int priority;
220 char serial_number[20], model[40], firmware_revision[8];
221
222 /* skip if already attached */
223 if (atapi->sc_link[target])
224 return;
225
226 if (wdc_atapi_get_params(atapi->adapter_link, target, id)) {
227 #ifdef ATAPI_DEBUG_PROBE
228 printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n",
229 atapi->sc_dev.dv_xname, target,
230 id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_MASK,
231 id->config.cmd_drq_rem & ATAPI_DRQ_MASK);
232 #endif
233 /*
234 * Shuffle string byte order.
235 * Mitsumi and NEC drives don't need this.
236 */
237 if (((id->model[0] == 'N' && id->model[1] == 'E') ||
238 (id->model[0] == 'F' && id->model[1] == 'X')) == 0)
239 bswap(id->model, sizeof(id->model));
240 bswap(id->serial_number, sizeof(id->serial_number));
241 bswap(id->firmware_revision, sizeof(id->firmware_revision));
242
243 /*
244 * Allocate a device link and try and attach
245 * a driver to this device. If we fail, free
246 * the link.
247 */
248 sc_link = malloc(sizeof(*sc_link), M_DEVBUF, M_NOWAIT);
249 if (sc_link == NULL) {
250 printf("%s: can't allocate link for drive %d\n",
251 atapi->sc_dev.dv_xname, target);
252 return;
253 }
254 /* Fill in link. */
255 *sc_link = *atapi->adapter_link;
256 sc_link->scsipi_atapi.drive = target;
257 sc_link->device = NULL;
258 #if defined(SCSIDEBUG) && DEBUGTYPE == BUS_ATAPI
259 if (DEBUGTARGET == -1 || target == DEBUGTARGET)
260 sc_link->flags |= DEBUGLEVEL;
261 #endif /* SCSIDEBUG */
262 if (id->config.cmd_drq_rem & ATAPI_PACKET_SIZE_16)
263 sc_link->scsipi_atapi.cap |= ACAP_LEN;
264 sc_link->scsipi_atapi.cap |=
265 (id->config.cmd_drq_rem & ATAPI_DRQ_MASK) << 3;
266 #if 0
267 bcopy(id, &ad_link->id, sizeof(*id));
268 /* Fix strings and look through the quirk table. */
269 atapi_fixquirk(ad_link, id);
270 #endif
271 sa.sa_sc_link = sc_link;
272 sa.sa_inqbuf.type = id->config.device_type & SID_TYPE;
273 sa.sa_inqbuf.removable =
274 id->config.cmd_drq_rem & ATAPI_REMOVABLE ?
275 T_REMOV : T_FIXED;
276 if (sa.sa_inqbuf.removable)
277 sc_link->flags |= SDEV_REMOVABLE;
278 scsipi_strvis(model, id->model, 40);
279 scsipi_strvis(serial_number, id->serial_number, 20);
280 scsipi_strvis(firmware_revision, id->firmware_revision, 8);
281 sa.sa_inqbuf.vendor = model;
282 sa.sa_inqbuf.product = serial_number;
283 sa.sa_inqbuf.revision = firmware_revision;
284
285 finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch(
286 &sa.sa_inqbuf, (caddr_t)atapi_quirk_patterns,
287 sizeof(atapi_quirk_patterns) /
288 sizeof(atapi_quirk_patterns[0]),
289 sizeof(atapi_quirk_patterns[0]), &priority);
290 if (priority != 0)
291 sc_link->quirks |= finger->quirks;
292
293 if ((cf = config_search(atapibussubmatch, &atapi->sc_dev,
294 &sa)) != 0) {
295 atapi->sc_link[target] = sc_link;
296 config_attach(&atapi->sc_dev, cf, &sa, atapibusprint);
297 return;
298 } else {
299 atapibusprint(&sa, atapi->sc_dev.dv_xname);
300 printf(" not configured\n");
301 free(sc_link, M_DEVBUF);
302 return;
303 }
304
305 #if 0 /* WAS: */
306 /* Try to find a match. */
307 if (config_found(self, ad_link, atapiprint) == NULL)
308 free(ad_link, M_DEVBUF);
309 #endif
310 }
311 }
312
313 int
314 atapibusprint(aux, pnp)
315 void *aux;
316 const char *pnp;
317 {
318 struct scsipibus_attach_args *sa = aux;
319 struct scsipi_inquiry_pattern *inqbuf;
320 char *dtype;
321
322 if (pnp != NULL)
323 printf("%s", pnp);
324
325 inqbuf = &sa->sa_inqbuf;
326
327 dtype = scsipi_dtype(inqbuf->type & SID_TYPE);
328 printf(" drive %d: <%s, %s, %s> type %d %s %s",
329 sa->sa_sc_link->scsipi_atapi.drive,inqbuf->vendor,
330 inqbuf->product, inqbuf->revision, inqbuf->type, dtype,
331 inqbuf->removable ? "removable" : "fixed");
332 return (UNCONF);
333 }
334