1/*	$NetBSD: isapnpdebug.c,v 1.11 2008/04/28 20:23:53 martin 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.11 2008/04/28 20:23:53 martin 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 */
51void
52isapnp_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 */
86void
87isapnp_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 */
100void
101isapnp_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 */
124void
125isapnp_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 */
179void
180isapnp_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
211void
212isapnp_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 */
240void
241isapnp_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 */
360void
361isapnp_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