1 /*        $NetBSD: isapnpdebug.c,v 1.12 2009/03/14 15:36:18 dsl Exp $ */
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: isapnpdebug.c,v 1.12 2009/03/14 15:36:18 dsl Exp $");
34 
35 #ifdef DEBUG_ISAPNP
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 
41 #include <sys/bus.h>
42 
43 #include <dev/isa/isavar.h>
44 
45 #include <dev/isapnp/isapnpreg.h>
46 #include <dev/isapnp/isapnpvar.h>
47 
48 /* isapnp_print_mem():
49  *        Print a memory tag
50  */
51 void
isapnp_print_mem(const char * str,const struct isapnp_region * mem)52 isapnp_print_mem(const char *str, const struct isapnp_region *mem)
53 {
54           printf("%sMemory: %s,%sshadowable,decode-%s,%scacheable,%s", str,
55               (mem->flags & ISAPNP_MEMATTR_ROM) ? "ROM," : "RAM,",
56               (mem->flags & ISAPNP_MEMATTR_SHADOWABLE) ? "" : "non-",
57               (mem->flags & ISAPNP_MEMATTR_HIGH_ADDR) ?
58                     "high-addr," : "range-len,",
59               (mem->flags & ISAPNP_MEMATTR_CACHEABLE) ? "" : "non-",
60               (mem->flags & ISAPNP_MEMATTR_WRITABLE) ?
61                     "writable," : "read-only,");
62 
63           switch (mem->flags & ISAPNP_MEMWIDTH_MASK) {
64           case ISAPNP_MEMWIDTH_8:
65                     printf("8-bit ");
66                     break;
67           case ISAPNP_MEMWIDTH_16:
68                     printf("16-bit ");
69                     break;
70           case ISAPNP_MEMWIDTH_8_16:
71                     printf("8/16-bit ");
72                     break;
73           case ISAPNP_MEMWIDTH_32:
74                     printf("32-bit ");
75                     break;
76           }
77 
78           printf("min 0x%x, max 0x%x, ", mem->minbase, mem->maxbase);
79           printf("align 0x%x, length 0x%x\n", mem->align, mem->length);
80 }
81 
82 
83 /* isapnp_print_io():
84  *        Print an io tag
85  */
86 void
isapnp_print_io(const char * str,const struct isapnp_region * io)87 isapnp_print_io(const char *str, const struct isapnp_region *io)
88 {
89           printf("%d %sIO Ports: %d address bits, alignment %d ",
90               io->length, str, (io->flags & ISAPNP_IOFLAGS_16) ? 16 : 10,
91               io->align);
92 
93           printf("min 0x%x, max 0x%x\n", io->minbase, io->maxbase);
94 }
95 
96 
97 /* isapnp_print_irq():
98  *        Print an irq tag
99  */
100 void
isapnp_print_irq(const char * str,const struct isapnp_pin * irq)101 isapnp_print_irq(const char *str, const struct isapnp_pin *irq)
102 {
103           int i;
104 
105           printf("%sIRQ's supported: ", str);
106           for (i = 0; i < 16; i++)
107                     if (irq->bits & (1 << i))
108                         printf("%d ", i);
109 
110           if (irq->flags & ISAPNP_IRQTYPE_EDGE_PLUS)
111                     printf("E+");
112           if (irq->flags & ISAPNP_IRQTYPE_EDGE_MINUS)
113                     printf("E-");
114           if (irq->flags & ISAPNP_IRQTYPE_LEVEL_PLUS)
115                     printf("L+");
116           if (irq->flags & ISAPNP_IRQTYPE_LEVEL_MINUS)
117                     printf("L-");
118           printf("\n");
119 }
120 
121 /* isapnp_print_drq():
122  *        Print a drq tag
123  */
124 void
isapnp_print_drq(const char * str,const struct isapnp_pin * drq)125 isapnp_print_drq(const char *str, const struct isapnp_pin *drq)
126 {
127           int i;
128           u_char flags = drq->flags;
129 
130           printf("%sDRQ's supported: ", str);
131           for (i = 0; i < 8; i++)
132                     if (drq->bits & (1 << i))
133                         printf("%d ", i);
134 
135           printf("Width: ");
136           switch (flags & ISAPNP_DMAWIDTH_MASK) {
137           case ISAPNP_DMAWIDTH_8:
138                     printf("8-bit ");
139                     break;
140           case ISAPNP_DMAWIDTH_8_16:
141                     printf("8/16-bit ");
142                     break;
143           case ISAPNP_DMAWIDTH_16:
144                     printf("16-bit ");
145                     break;
146           case ISAPNP_DMAWIDTH_RESERVED:
147                     printf("Reserved ");
148                     break;
149           }
150 
151           printf("Speed: ");
152           switch (flags & ISAPNP_DMASPEED_MASK) {
153           case ISAPNP_DMASPEED_COMPAT:
154                     printf("compat ");
155                     break;
156           case ISAPNP_DMASPEED_A:
157                     printf("A ");
158                     break;
159           case ISAPNP_DMASPEED_B:
160                     printf("B ");
161                     break;
162           case ISAPNP_DMASPEED_F:
163                     printf("F ");
164                     break;
165           }
166 
167           if (flags & ISAPNP_DMAATTR_MASK)
168                     printf("Attributes: %s%s%s",
169                         (flags & ISAPNP_DMAATTR_BUS_MASTER) ?  "bus master " : "",
170                         (flags & ISAPNP_DMAATTR_INCR_8) ?  "incr 8 " : "",
171                         (flags & ISAPNP_DMAATTR_INCR_16) ?  "incr 16 " : "");
172           printf("\n");
173 }
174 
175 
176 /* isapnp_print_dep_start():
177  *        Print a start dependencies tag
178  */
179 void
isapnp_print_dep_start(const char * str,const u_char pref)180 isapnp_print_dep_start(const char *str, const u_char pref)
181 {
182 
183           printf("%sconfig: ", str);
184           switch (pref) {
185           case ISAPNP_DEP_PREFERRED:
186                     printf("preferred\n");
187                     break;
188 
189           case ISAPNP_DEP_ACCEPTABLE:
190                     printf("acceptable\n");
191                     break;
192 
193           case ISAPNP_DEP_FUNCTIONAL:
194                     printf("functional\n");
195                     break;
196 
197           case ISAPNP_DEP_UNSET:                  /* Used internally */
198                     printf("unset\n");
199                     break;
200 
201           case ISAPNP_DEP_CONFLICTING:  /* Used internally */
202                     printf("conflicting\n");
203                     break;
204 
205           default:
206                     printf("invalid\n");
207                     break;
208           }
209 }
210 
211 void
isapnp_print_attach(const struct isapnp_attach_args * pa)212 isapnp_print_attach(const struct isapnp_attach_args *pa)
213 {
214           int i;
215 
216           printf("Found <%s, %s, %s, %s> ", pa->ipa_devident,
217               pa->ipa_devlogic, pa->ipa_devcompat, pa->ipa_devclass);
218           isapnp_print_dep_start("", pa->ipa_pref);
219 
220           for (i = 0; i < pa->ipa_nio; i++)
221                     isapnp_print_io("", &pa->ipa_io[i]);
222 
223           for (i = 0; i < pa->ipa_nmem; i++)
224                     isapnp_print_mem("", &pa->ipa_mem[i]);
225 
226           for (i = 0; i < pa->ipa_nirq; i++)
227                     isapnp_print_irq("", &pa->ipa_irq[i]);
228 
229           for (i = 0; i < pa->ipa_ndrq; i++)
230                     isapnp_print_drq("", &pa->ipa_drq[i]);
231 
232           for (i = 0; i < pa->ipa_nmem32; i++)
233                     isapnp_print_mem("", &pa->ipa_mem32[i]);
234 }
235 
236 
237 /* isapnp_get_config():
238  *        Get the current configuration of the card
239  */
240 void
isapnp_get_config(struct isapnp_softc * sc,struct isapnp_attach_args * pa)241 isapnp_get_config(struct isapnp_softc *sc, struct isapnp_attach_args *pa)
242 {
243           int i;
244           u_char v0, v1, v2, v3;
245           static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC;
246           static u_char isapnp_io_range[] = ISAPNP_IO_DESC;
247           static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC;
248           static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC;
249           static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC;
250           struct isapnp_region *r;
251           struct isapnp_pin *p;
252 
253           memset(pa, 0, sizeof(*pa));
254 
255           for (i = 0; i < sizeof(isapnp_io_range); i++) {
256                     r = &pa->ipa_io[i];
257                     v0 = isapnp_read_reg(sc,
258                         isapnp_io_range[i] + ISAPNP_IO_BASE_15_8);
259                     v1 = isapnp_read_reg(sc,
260                         isapnp_io_range[i] + ISAPNP_IO_BASE_7_0);
261                     r->base = (v0 << 8) | v1;
262                     if (r->base == 0)
263                               break;
264           }
265           pa->ipa_nio = i;
266 
267           for (i = 0; i < sizeof(isapnp_mem_range); i++) {
268                     r = &pa->ipa_mem[i];
269                     v0 = isapnp_read_reg(sc,
270                         isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16);
271                     v1 = isapnp_read_reg(sc,
272                         isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8);
273                     r->base = (v0 << 16) | (v1 << 8);
274                     if (r->base == 0)
275                               break;
276 
277                     v0 = isapnp_read_reg(sc,
278                         isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16);
279                     v1 = isapnp_read_reg(sc,
280                         isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8);
281                     r->length = (v0 << 16) | (v1 << 8);
282                     v0 = isapnp_read_reg(sc,
283                         isapnp_mem_range[i] + ISAPNP_MEM_CONTROL);
284                     r->flags = 0;
285                     if (v0 & ISAPNP_MEM_CONTROL_LIMIT)
286                               r->flags |= ISAPNP_MEMATTR_HIGH_ADDR;
287                     if (v0 & ISAPNP_MEM_CONTROL_16)
288                               r->flags |= ISAPNP_MEMWIDTH_16;
289           }
290           pa->ipa_nmem = i;
291 
292           for (i = 0; i < sizeof(isapnp_irq_range); i++) {
293                     v0 = isapnp_read_reg(sc,
294                         isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER);
295                     p = &pa->ipa_irq[i];
296                     p->num = v0 & 0xf;
297                     if (p->num == 0)
298                               break;
299 
300                     switch (v0 & (ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH)) {
301                     case ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH:
302                         p->flags = ISAPNP_IRQTYPE_LEVEL_PLUS;
303                         break;
304                     case ISAPNP_IRQ_HIGH:
305                         p->flags = ISAPNP_IRQTYPE_EDGE_PLUS;
306                         break;
307                     case ISAPNP_IRQ_LEVEL:
308                         p->flags = ISAPNP_IRQTYPE_LEVEL_MINUS;
309                         break;
310                     default:
311                         p->flags = ISAPNP_IRQTYPE_EDGE_MINUS;
312                         break;
313                     }
314           }
315           pa->ipa_nirq = i;
316 
317           for (i = 0; i < sizeof(isapnp_drq_range); i++) {
318                     v0 = isapnp_read_reg(sc, isapnp_drq_range[i]);
319                     p = &pa->ipa_drq[i];
320                     p->num = v0 & 0xf;
321                     if (p->num == 4)
322                               break;
323           }
324           pa->ipa_ndrq = i;
325 
326           for (i = 0; i < sizeof(isapnp_mem32_range); i++) {
327                     r = &pa->ipa_mem32[i];
328                     v0 = isapnp_read_reg(sc,
329                         isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24);
330                     v1 = isapnp_read_reg(sc,
331                         isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16);
332                     v2 = isapnp_read_reg(sc,
333                         isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8);
334                     v3 = isapnp_read_reg(sc,
335                         isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0);
336                     r->base = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
337                     if (r->base == 0)
338                               break;
339 
340                     v0 = isapnp_read_reg(sc,
341                         isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24);
342                     v1 = isapnp_read_reg(sc,
343                         isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16);
344                     v2 = isapnp_read_reg(sc,
345                         isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8);
346                     v3 = isapnp_read_reg(sc,
347                         isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0);
348                     r->length = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3;
349                     v0 = isapnp_read_reg(sc,
350                         isapnp_mem_range[i] + ISAPNP_MEM_CONTROL);
351                     r->flags = v0;
352           }
353           pa->ipa_nmem32 = i;
354 }
355 
356 
357 /* isapnp_print_config():
358  *        Print the current configuration of the card
359  */
360 void
isapnp_print_config(const struct isapnp_attach_args * pa)361 isapnp_print_config(const struct isapnp_attach_args *pa)
362 {
363           int i;
364           const struct isapnp_region *r;
365           const struct isapnp_pin *p;
366 
367           printf("Register configuration:\n");
368           if (pa->ipa_nio)
369                     for (i = 0; i < pa->ipa_nio; i++) {
370                               r = &pa->ipa_io[i];
371                               printf("io[%d]: 0x%x/%d\n", i, r->base, r->length);
372                     }
373 
374           if (pa->ipa_nmem)
375                     for (i = 0; i < pa->ipa_nmem; i++) {
376                               r = &pa->ipa_mem[i];
377                               printf("mem[%d]: 0x%x/%d\n", i, r->base, r->length);
378                     }
379 
380           if (pa->ipa_nirq)
381                     for (i = 0; i < pa->ipa_nirq; i++) {
382                               p = &pa->ipa_irq[i];
383                               printf("irq[%d]: %d\n", i, p->num);
384                     }
385 
386           if (pa->ipa_ndrq)
387                     for (i = 0; i < pa->ipa_ndrq; i++) {
388                               p = &pa->ipa_drq[i];
389                               printf("drq[%d]: %d\n", i, p->num);
390                     }
391 
392           if (pa->ipa_nmem32)
393                     for (i = 0; i < pa->ipa_nmem32; i++) {
394                               r = &pa->ipa_mem32[i];
395                               printf("mem32[%d]: 0x%x/%d\n", i, r->base, r->length);
396                     }
397 }
398 
399 #endif
400