isapnpres.c revision 1.2 1 1.2 mycroft /* $NetBSD: isapnpres.c,v 1.2 1997/01/22 23:51:38 mycroft Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (c) 1996 Christos Zoulas. All rights reserved.
5 1.1 christos *
6 1.1 christos * Redistribution and use in source and binary forms, with or without
7 1.1 christos * modification, are permitted provided that the following conditions
8 1.1 christos * are met:
9 1.1 christos * 1. Redistributions of source code must retain the above copyright
10 1.1 christos * notice, this list of conditions and the following disclaimer.
11 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 christos * notice, this list of conditions and the following disclaimer in the
13 1.1 christos * documentation and/or other materials provided with the distribution.
14 1.1 christos * 3. All advertising materials mentioning features or use of this software
15 1.1 christos * must display the following acknowledgement:
16 1.1 christos * This product includes software developed by Christos Zoulas.
17 1.1 christos * 4. The name of the author may not be used to endorse or promote products
18 1.1 christos * derived from this software without specific prior written permission.
19 1.1 christos *
20 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 1.1 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 1.1 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 1.1 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 1.1 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 1.1 christos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 1.1 christos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 1.1 christos */
31 1.1 christos
32 1.1 christos /*
33 1.1 christos * Resource parser for Plug and Play cards.
34 1.1 christos */
35 1.1 christos
36 1.1 christos #include <sys/param.h>
37 1.1 christos #include <sys/systm.h>
38 1.1 christos #include <sys/device.h>
39 1.1 christos #include <sys/malloc.h>
40 1.1 christos
41 1.1 christos #include <machine/bus.h>
42 1.1 christos
43 1.1 christos #include <dev/isa/isavar.h>
44 1.1 christos
45 1.1 christos #include <dev/isapnp/isapnpreg.h>
46 1.1 christos #include <dev/isapnp/isapnpvar.h>
47 1.1 christos
48 1.1 christos
49 1.1 christos static int isapnp_wait_status __P((struct isapnp_softc *));
50 1.1 christos static struct isapnp_attach_args *isapnp_process_tag __P((u_char, u_char,
51 1.1 christos u_char *, struct isapnp_attach_args *));
52 1.1 christos
53 1.1 christos
54 1.1 christos /* isapnp_wait_status():
55 1.1 christos * Wait for the next byte of resource data to become available
56 1.1 christos */
57 1.1 christos static int
58 1.1 christos isapnp_wait_status(sc)
59 1.1 christos struct isapnp_softc *sc;
60 1.1 christos {
61 1.1 christos int i;
62 1.1 christos
63 1.1 christos for (i = 0; i < 10; i++) {
64 1.1 christos if (isapnp_read_reg(sc, ISAPNP_STATUS) & 1)
65 1.1 christos return 0;
66 1.2 mycroft DELAY(100);
67 1.1 christos }
68 1.1 christos return 1;
69 1.1 christos }
70 1.1 christos
71 1.1 christos /* isapnp_process_tag():
72 1.1 christos * Process a resource tag
73 1.1 christos */
74 1.1 christos static struct isapnp_attach_args *
75 1.1 christos isapnp_process_tag(tag, len, buf, pa)
76 1.1 christos u_char tag, len, *buf;
77 1.1 christos struct isapnp_attach_args *pa;
78 1.1 christos {
79 1.1 christos struct isapnp_attach_args *npa;
80 1.1 christos char str[64];
81 1.1 christos struct isapnp_region *r;
82 1.1 christos struct isapnp_pin *p;
83 1.1 christos
84 1.1 christos #define COPY(a, b) strncpy((a), (b), sizeof(a)), (a)[sizeof(a) - 1] = '\0'
85 1.1 christos
86 1.1 christos switch (tag) {
87 1.1 christos case ISAPNP_TAG_VERSION_NUM:
88 1.1 christos DPRINTF(("PnP version %d.%d, Vendor version %d.%d\n",
89 1.1 christos buf[0] >> 4, buf[0] & 0xf, buf[1] >> 4, buf[1] & 0xf));
90 1.1 christos break;
91 1.1 christos
92 1.1 christos case ISAPNP_TAG_LOGICAL_DEV_ID:
93 1.1 christos (void) isapnp_id_to_vendor(str, buf);
94 1.1 christos DPRINTF(("Logical device id %s\n", str));
95 1.1 christos COPY(pa->ipa_devlogic, str);
96 1.1 christos break;
97 1.1 christos
98 1.1 christos case ISAPNP_TAG_COMPAT_DEV_ID:
99 1.1 christos (void) isapnp_id_to_vendor(str, buf);
100 1.1 christos DPRINTF(("Compatible device id %s\n", str));
101 1.1 christos break;
102 1.1 christos
103 1.1 christos case ISAPNP_TAG_IRQ_FORMAT:
104 1.1 christos if (len < 2)
105 1.1 christos break;
106 1.1 christos
107 1.1 christos if (len != 3)
108 1.1 christos buf[2] = ISAPNP_IRQTYPE_EDGE_PLUS;
109 1.1 christos
110 1.1 christos p = &pa->ipa_irq[pa->ipa_nirq++];
111 1.1 christos p->bits = buf[0] | (buf[1] << 8);
112 1.1 christos p->flags = buf[2];
113 1.1 christos #ifdef DEBUG_ISAPNP
114 1.1 christos isapnp_print_irq("", p);
115 1.1 christos #endif
116 1.1 christos break;
117 1.1 christos
118 1.1 christos case ISAPNP_TAG_DMA_FORMAT:
119 1.1 christos if (buf[0] == 0)
120 1.1 christos break;
121 1.1 christos
122 1.1 christos p = &pa->ipa_drq[pa->ipa_ndrq++];
123 1.1 christos p->bits = buf[0];
124 1.1 christos p->flags = buf[1];
125 1.1 christos #ifdef DEBUG_ISAPNP
126 1.1 christos isapnp_print_drq("", p);
127 1.1 christos #endif
128 1.1 christos break;
129 1.1 christos
130 1.1 christos case ISAPNP_TAG_DEP_START:
131 1.1 christos if (len == 0)
132 1.1 christos buf[0] = ISAPNP_DEP_ACCEPTABLE;
133 1.1 christos if (pa->ipa_pref != ISAPNP_DEP_UNSET) {
134 1.1 christos npa = ISAPNP_MALLOC(sizeof(*npa));
135 1.1 christos memset(npa, 0, sizeof(*npa));
136 1.1 christos memcpy(npa->ipa_devident, pa->ipa_devident,
137 1.1 christos sizeof(pa->ipa_devident));
138 1.1 christos memcpy(npa->ipa_devlogic, pa->ipa_devlogic,
139 1.1 christos sizeof(pa->ipa_devlogic));
140 1.1 christos memcpy(npa->ipa_devclass, pa->ipa_devclass,
141 1.1 christos sizeof(pa->ipa_devclass));
142 1.1 christos pa->ipa_next = npa;
143 1.1 christos pa = npa;
144 1.1 christos }
145 1.1 christos pa->ipa_pref = buf[0];
146 1.1 christos #ifdef DEBUG_ISAPNP
147 1.1 christos isapnp_print_dep_start(">>> Start dependent functions ",
148 1.1 christos pa->ipa_pref);
149 1.1 christos #endif
150 1.1 christos break;
151 1.1 christos
152 1.1 christos case ISAPNP_TAG_DEP_END:
153 1.1 christos DPRINTF(("<<<End dependend functions\n"));
154 1.1 christos npa = ISAPNP_MALLOC(sizeof(*npa));
155 1.1 christos memset(npa, 0, sizeof(*npa));
156 1.1 christos npa->ipa_pref = ISAPNP_DEP_UNSET;
157 1.1 christos memcpy(npa->ipa_devident, pa->ipa_devident,
158 1.1 christos sizeof(pa->ipa_devident));
159 1.1 christos
160 1.1 christos pa->ipa_next = npa;
161 1.1 christos pa = npa;
162 1.1 christos break;
163 1.1 christos
164 1.1 christos case ISAPNP_TAG_IO_PORT_DESC:
165 1.1 christos r = &pa->ipa_io[pa->ipa_nio++];
166 1.1 christos r->flags = buf[0];
167 1.1 christos r->minbase = (buf[2] << 8) | buf[1];
168 1.1 christos r->maxbase = (buf[4] << 8) | buf[3];
169 1.1 christos r->align = buf[5];
170 1.1 christos r->length = buf[6];
171 1.1 christos
172 1.1 christos #ifdef DEBUG_ISAPNP
173 1.1 christos isapnp_print_io("", r);
174 1.1 christos #endif
175 1.1 christos break;
176 1.1 christos
177 1.1 christos case ISAPNP_TAG_FIXED_IO_PORT_DESC:
178 1.1 christos r = &pa->ipa_io[pa->ipa_nio++];
179 1.1 christos r->flags = 0;
180 1.1 christos r->minbase = (buf[2] << 8) | buf[1];
181 1.1 christos r->maxbase = r->minbase;
182 1.1 christos r->align = 1;
183 1.1 christos r->length = buf[3];
184 1.1 christos
185 1.1 christos #ifdef DEBUG_ISAPNP
186 1.1 christos isapnp_print_io("FIXED", r);
187 1.1 christos #endif
188 1.1 christos break;
189 1.1 christos
190 1.1 christos case ISAPNP_TAG_RESERVED1:
191 1.1 christos case ISAPNP_TAG_RESERVED2:
192 1.1 christos case ISAPNP_TAG_RESERVED3:
193 1.1 christos case ISAPNP_TAG_RESERVED4:
194 1.1 christos break;
195 1.1 christos
196 1.1 christos case ISAPNP_TAG_VENDOR_DEF:
197 1.1 christos break;
198 1.1 christos
199 1.1 christos case ISAPNP_TAG_END:
200 1.1 christos break;
201 1.1 christos
202 1.1 christos case ISAPNP_TAG_MEM_RANGE_DESC:
203 1.1 christos r = &pa->ipa_mem[pa->ipa_nmem++];
204 1.1 christos r->minbase = (buf[2] << 8) | buf[1];
205 1.1 christos r->maxbase = (buf[4] << 8) | buf[3];
206 1.1 christos r->align = (buf[6] << 8) | buf[5];
207 1.1 christos r->length = (buf[8] << 8) | buf[7];
208 1.1 christos #ifdef DEBUG_ISAPNP
209 1.1 christos isapnp_print_mem("16 bit", r);
210 1.1 christos #endif
211 1.1 christos break;
212 1.1 christos
213 1.1 christos case ISAPNP_TAG_ANSI_IDENT_STRING:
214 1.1 christos buf[len] = '\0';
215 1.1 christos DPRINTF(("ANSI Ident: %s\n", buf));
216 1.1 christos if (pa->ipa_devident[0] == '\0')
217 1.1 christos COPY(pa->ipa_devident, buf);
218 1.1 christos else
219 1.1 christos COPY(pa->ipa_devclass, buf);
220 1.1 christos break;
221 1.1 christos
222 1.1 christos case ISAPNP_TAG_UNICODE_IDENT_STRING:
223 1.1 christos buf[len] = '\0';
224 1.1 christos DPRINTF(("Unicode Ident: %s\n", buf));
225 1.1 christos break;
226 1.1 christos
227 1.1 christos case ISAPNP_TAG_VENDOR_DEFINED:
228 1.1 christos break;
229 1.1 christos
230 1.1 christos case ISAPNP_TAG_MEM32_RANGE_DESC:
231 1.1 christos r = &pa->ipa_mem32[pa->ipa_nmem32++];
232 1.1 christos r->flags = buf[0];
233 1.1 christos r->minbase = (buf[4] << 24) | (buf[3] << 16) |
234 1.1 christos (buf[2] << 8) | buf[1];
235 1.1 christos r->maxbase = (buf[8] << 24) | (buf[7] << 16) |
236 1.1 christos (buf[6] << 8) | buf[5];
237 1.1 christos r->align = (buf[12] << 24) | (buf[11] << 16) |
238 1.1 christos (buf[10] << 8) | buf[9];
239 1.1 christos r->length = (buf[16] << 24) | (buf[15] << 16) |
240 1.1 christos (buf[14] << 8) | buf[13];
241 1.1 christos #ifdef DEBUG_ISAPNP
242 1.1 christos isapnp_print_mem("32 bit", r);
243 1.1 christos #endif
244 1.1 christos break;
245 1.1 christos
246 1.1 christos case ISAPNP_TAG_FIXED_MEM32_RANGE_DESC:
247 1.1 christos r = &pa->ipa_mem32[pa->ipa_nmem32++];
248 1.1 christos r->flags = buf[0];
249 1.1 christos r->minbase = (buf[4] << 24) | (buf[3] << 16) |
250 1.1 christos (buf[2] << 8) | buf[1];
251 1.1 christos r->maxbase = r->minbase;
252 1.1 christos r->align = 1;
253 1.1 christos r->length = (buf[8] << 24) | (buf[7] << 16) |
254 1.1 christos (buf[6] << 8) | buf[5];
255 1.1 christos #ifdef DEBUG_ISAPNP
256 1.1 christos isapnp_print_mem("FIXED 32 bit", r);
257 1.1 christos #endif
258 1.1 christos break;
259 1.1 christos
260 1.1 christos default:
261 1.1 christos #ifdef DEBUG_ISAPNP
262 1.1 christos {
263 1.1 christos int i;
264 1.1 christos printf("tag %.2x, len %d: ", tag, len);
265 1.1 christos for (i = 0; i < len; i++)
266 1.1 christos printf("%.2x ", buf[i]);
267 1.1 christos printf("\n");
268 1.1 christos }
269 1.1 christos #endif
270 1.1 christos break;
271 1.1 christos }
272 1.1 christos return pa;
273 1.1 christos }
274 1.1 christos
275 1.1 christos
276 1.1 christos /* isapnp_get_resource():
277 1.1 christos * Read the resources for card c
278 1.1 christos */
279 1.1 christos struct isapnp_attach_args *
280 1.1 christos isapnp_get_resource(sc, c)
281 1.1 christos struct isapnp_softc *sc;
282 1.1 christos int c;
283 1.1 christos {
284 1.1 christos u_char d, tag;
285 1.1 christos u_short len;
286 1.1 christos int i;
287 1.1 christos struct isapnp_attach_args *ipa, *pa;
288 1.1 christos
289 1.1 christos pa = ipa = ISAPNP_MALLOC(sizeof(*ipa));
290 1.1 christos memset(ipa, 0, sizeof(*ipa));
291 1.1 christos pa->ipa_pref = ISAPNP_DEP_UNSET;
292 1.1 christos
293 1.1 christos for (i = 0; i < ISAPNP_SERIAL_SIZE; i++) {
294 1.1 christos if (isapnp_wait_status(sc))
295 1.1 christos goto bad;
296 1.1 christos
297 1.1 christos d = isapnp_read_reg(sc, ISAPNP_RESOURCE_DATA);
298 1.1 christos
299 1.1 christos if (d != sc->sc_id[c][i] && i != ISAPNP_SERIAL_SIZE - 1) {
300 1.1 christos printf("isapnp: card %d violates PnP spec; byte %d\n",
301 1.1 christos c + 1, i);
302 1.1 christos break;
303 1.1 christos }
304 1.1 christos }
305 1.1 christos
306 1.1 christos do {
307 1.1 christos u_char buf[ISAPNP_MAX_TAGSIZE], *p;
308 1.1 christos
309 1.1 christos memset(buf, 0, sizeof(buf));
310 1.1 christos
311 1.1 christos #define NEXT_BYTE \
312 1.1 christos if (isapnp_wait_status(sc)) \
313 1.1 christos goto bad; \
314 1.1 christos d = isapnp_read_reg(sc, ISAPNP_RESOURCE_DATA);
315 1.1 christos
316 1.1 christos NEXT_BYTE;
317 1.1 christos
318 1.1 christos if (d & ISAPNP_LARGE_TAG) {
319 1.1 christos tag = d;
320 1.1 christos NEXT_BYTE;
321 1.1 christos buf[0] = d;
322 1.1 christos NEXT_BYTE;
323 1.1 christos buf[1] = d;
324 1.1 christos len = (buf[1] << 8) | buf[0];
325 1.1 christos }
326 1.1 christos else {
327 1.1 christos tag = (d >> 3) & 0xf;
328 1.1 christos len = d & 0x7;
329 1.1 christos }
330 1.1 christos
331 1.1 christos for (p = buf, i = 0; i < len; i++) {
332 1.1 christos NEXT_BYTE;
333 1.1 christos if (i < ISAPNP_MAX_TAGSIZE)
334 1.1 christos *p++ = d;
335 1.1 christos }
336 1.1 christos
337 1.1 christos if (len >= ISAPNP_MAX_TAGSIZE) {
338 1.1 christos printf("isapnp: Maximum tag size exceeded, card %d\n",
339 1.1 christos c + 1);
340 1.1 christos len = ISAPNP_MAX_TAGSIZE;
341 1.1 christos }
342 1.1 christos
343 1.1 christos pa = isapnp_process_tag(tag, len, buf, pa);
344 1.1 christos }
345 1.1 christos while (tag != ISAPNP_TAG_END);
346 1.1 christos return ipa;
347 1.1 christos bad:
348 1.1 christos while (ipa) {
349 1.1 christos pa = ipa->ipa_next;
350 1.1 christos ISAPNP_FREE(ipa);
351 1.1 christos ipa = pa;
352 1.1 christos }
353 1.1 christos printf("isapnp: Resource timeout, card %d\n", c + 1);
354 1.1 christos return NULL;
355 1.1 christos }
356