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 */ 51 void 52 isapnp_print_mem(str, mem) 53 const char *str; 54 const struct isapnp_region *mem; 55 { 56 printf("%sMemory: %s,%sshadowable,decode-%s,%scacheable,%s", str, 57 (mem->flags & ISAPNP_MEMATTR_ROM) ? "ROM," : "RAM,", 58 (mem->flags & ISAPNP_MEMATTR_SHADOWABLE) ? "" : "non-", 59 (mem->flags & ISAPNP_MEMATTR_HIGH_ADDR) ? 60 "high-addr," : "range-len,", 61 (mem->flags & ISAPNP_MEMATTR_CACHEABLE) ? "" : "non-", 62 (mem->flags & ISAPNP_MEMATTR_WRITABLE) ? 63 "writable," : "read-only,"); 64 65 switch (mem->flags & ISAPNP_MEMWIDTH_MASK) { 66 case ISAPNP_MEMWIDTH_8: 67 printf("8-bit "); 68 break; 69 case ISAPNP_MEMWIDTH_16: 70 printf("16-bit "); 71 break; 72 case ISAPNP_MEMWIDTH_8_16: 73 printf("8/16-bit "); 74 break; 75 case ISAPNP_MEMWIDTH_32: 76 printf("32-bit "); 77 break; 78 } 79 80 printf("min 0x%x, max 0x%x, ", mem->minbase, mem->maxbase); 81 printf("align 0x%x, length 0x%x\n", mem->align, mem->length); 82 } 83 84 85 /* isapnp_print_io(): 86 * Print an io tag 87 */ 88 void 89 isapnp_print_io(str, io) 90 const char *str; 91 const struct isapnp_region *io; 92 { 93 printf("%d %sIO Ports: %d address bits, alignment %d ", 94 io->length, str, (io->flags & ISAPNP_IOFLAGS_16) ? 16 : 10, 95 io->align); 96 97 printf("min 0x%x, max 0x%x\n", io->minbase, io->maxbase); 98 } 99 100 101 /* isapnp_print_irq(): 102 * Print an irq tag 103 */ 104 void 105 isapnp_print_irq(str, irq) 106 const char *str; 107 const struct isapnp_pin *irq; 108 { 109 int i; 110 111 printf("%sIRQ's supported: ", str); 112 for (i = 0; i < 16; i++) 113 if (irq->bits & (1 << i)) 114 printf("%d ", i); 115 116 if (irq->flags & ISAPNP_IRQTYPE_EDGE_PLUS) 117 printf("E+"); 118 if (irq->flags & ISAPNP_IRQTYPE_EDGE_MINUS) 119 printf("E-"); 120 if (irq->flags & ISAPNP_IRQTYPE_LEVEL_PLUS) 121 printf("L+"); 122 if (irq->flags & ISAPNP_IRQTYPE_LEVEL_MINUS) 123 printf("L-"); 124 printf("\n"); 125 } 126 127 /* isapnp_print_drq(): 128 * Print a drq tag 129 */ 130 void 131 isapnp_print_drq(str, drq) 132 const char *str; 133 const struct isapnp_pin *drq; 134 { 135 int i; 136 u_char flags = drq->flags; 137 138 printf("%sDRQ's supported: ", str); 139 for (i = 0; i < 8; i++) 140 if (drq->bits & (1 << i)) 141 printf("%d ", i); 142 143 printf("Width: "); 144 switch (flags & ISAPNP_DMAWIDTH_MASK) { 145 case ISAPNP_DMAWIDTH_8: 146 printf("8-bit "); 147 break; 148 case ISAPNP_DMAWIDTH_8_16: 149 printf("8/16-bit "); 150 break; 151 case ISAPNP_DMAWIDTH_16: 152 printf("16-bit "); 153 break; 154 case ISAPNP_DMAWIDTH_RESERVED: 155 printf("Reserved "); 156 break; 157 } 158 159 printf("Speed: "); 160 switch (flags & ISAPNP_DMASPEED_MASK) { 161 case ISAPNP_DMASPEED_COMPAT: 162 printf("compat "); 163 break; 164 case ISAPNP_DMASPEED_A: 165 printf("A "); 166 break; 167 case ISAPNP_DMASPEED_B: 168 printf("B "); 169 break; 170 case ISAPNP_DMASPEED_F: 171 printf("F "); 172 break; 173 } 174 175 if (flags & ISAPNP_DMAATTR_MASK) 176 printf("Attributes: %s%s%s", 177 (flags & ISAPNP_DMAATTR_BUS_MASTER) ? "bus master " : "", 178 (flags & ISAPNP_DMAATTR_INCR_8) ? "incr 8 " : "", 179 (flags & ISAPNP_DMAATTR_INCR_16) ? "incr 16 " : ""); 180 printf("\n"); 181 } 182 183 184 /* isapnp_print_dep_start(): 185 * Print a start dependencies tag 186 */ 187 void 188 isapnp_print_dep_start(str, pref) 189 const char *str; 190 const u_char pref; 191 { 192 193 printf("%sconfig: ", str); 194 switch (pref) { 195 case ISAPNP_DEP_PREFERRED: 196 printf("preferred\n"); 197 break; 198 199 case ISAPNP_DEP_ACCEPTABLE: 200 printf("acceptable\n"); 201 break; 202 203 case ISAPNP_DEP_FUNCTIONAL: 204 printf("functional\n"); 205 break; 206 207 case ISAPNP_DEP_UNSET: /* Used internally */ 208 printf("unset\n"); 209 break; 210 211 case ISAPNP_DEP_CONFLICTING: /* Used internally */ 212 printf("conflicting\n"); 213 break; 214 215 default: 216 printf("invalid\n"); 217 break; 218 } 219 } 220 221 void 222 isapnp_print_attach(pa) 223 const struct isapnp_attach_args *pa; 224 { 225 int i; 226 227 printf("Found <%s, %s, %s, %s> ", pa->ipa_devident, 228 pa->ipa_devlogic, pa->ipa_devcompat, pa->ipa_devclass); 229 isapnp_print_dep_start("", pa->ipa_pref); 230 231 for (i = 0; i < pa->ipa_nio; i++) 232 isapnp_print_io("", &pa->ipa_io[i]); 233 234 for (i = 0; i < pa->ipa_nmem; i++) 235 isapnp_print_mem("", &pa->ipa_mem[i]); 236 237 for (i = 0; i < pa->ipa_nirq; i++) 238 isapnp_print_irq("", &pa->ipa_irq[i]); 239 240 for (i = 0; i < pa->ipa_ndrq; i++) 241 isapnp_print_drq("", &pa->ipa_drq[i]); 242 243 for (i = 0; i < pa->ipa_nmem32; i++) 244 isapnp_print_mem("", &pa->ipa_mem32[i]); 245 } 246 247 248 /* isapnp_get_config(): 249 * Get the current configuration of the card 250 */ 251 void 252 isapnp_get_config(sc, pa) 253 struct isapnp_softc *sc; 254 struct isapnp_attach_args *pa; 255 { 256 int i; 257 u_char v0, v1, v2, v3; 258 static u_char isapnp_mem_range[] = ISAPNP_MEM_DESC; 259 static u_char isapnp_io_range[] = ISAPNP_IO_DESC; 260 static u_char isapnp_irq_range[] = ISAPNP_IRQ_DESC; 261 static u_char isapnp_drq_range[] = ISAPNP_DRQ_DESC; 262 static u_char isapnp_mem32_range[] = ISAPNP_MEM32_DESC; 263 struct isapnp_region *r; 264 struct isapnp_pin *p; 265 266 memset(pa, 0, sizeof(*pa)); 267 268 for (i = 0; i < sizeof(isapnp_io_range); i++) { 269 r = &pa->ipa_io[i]; 270 v0 = isapnp_read_reg(sc, 271 isapnp_io_range[i] + ISAPNP_IO_BASE_15_8); 272 v1 = isapnp_read_reg(sc, 273 isapnp_io_range[i] + ISAPNP_IO_BASE_7_0); 274 r->base = (v0 << 8) | v1; 275 if (r->base == 0) 276 break; 277 } 278 pa->ipa_nio = i; 279 280 for (i = 0; i < sizeof(isapnp_mem_range); i++) { 281 r = &pa->ipa_mem[i]; 282 v0 = isapnp_read_reg(sc, 283 isapnp_mem_range[i] + ISAPNP_MEM_BASE_23_16); 284 v1 = isapnp_read_reg(sc, 285 isapnp_mem_range[i] + ISAPNP_MEM_BASE_15_8); 286 r->base = (v0 << 16) | (v1 << 8); 287 if (r->base == 0) 288 break; 289 290 v0 = isapnp_read_reg(sc, 291 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_23_16); 292 v1 = isapnp_read_reg(sc, 293 isapnp_mem_range[i] + ISAPNP_MEM_LRANGE_15_8); 294 r->length = (v0 << 16) | (v1 << 8); 295 v0 = isapnp_read_reg(sc, 296 isapnp_mem_range[i] + ISAPNP_MEM_CONTROL); 297 r->flags = 0; 298 if (v0 & ISAPNP_MEM_CONTROL_LIMIT) 299 r->flags |= ISAPNP_MEMATTR_HIGH_ADDR; 300 if (v0 & ISAPNP_MEM_CONTROL_16) 301 r->flags |= ISAPNP_MEMWIDTH_16; 302 } 303 pa->ipa_nmem = i; 304 305 for (i = 0; i < sizeof(isapnp_irq_range); i++) { 306 v0 = isapnp_read_reg(sc, 307 isapnp_irq_range[i] + ISAPNP_IRQ_NUMBER); 308 p = &pa->ipa_irq[i]; 309 p->num = v0 & 0xf; 310 if (p->num == 0) 311 break; 312 313 switch (v0 & (ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH)) { 314 case ISAPNP_IRQ_LEVEL|ISAPNP_IRQ_HIGH: 315 p->flags = ISAPNP_IRQTYPE_LEVEL_PLUS; 316 break; 317 case ISAPNP_IRQ_HIGH: 318 p->flags = ISAPNP_IRQTYPE_EDGE_PLUS; 319 break; 320 case ISAPNP_IRQ_LEVEL: 321 p->flags = ISAPNP_IRQTYPE_LEVEL_MINUS; 322 break; 323 default: 324 p->flags = ISAPNP_IRQTYPE_EDGE_MINUS; 325 break; 326 } 327 } 328 pa->ipa_nirq = i; 329 330 for (i = 0; i < sizeof(isapnp_drq_range); i++) { 331 v0 = isapnp_read_reg(sc, isapnp_drq_range[i]); 332 p = &pa->ipa_drq[i]; 333 p->num = v0 & 0xf; 334 if (p->num == 4) 335 break; 336 } 337 pa->ipa_ndrq = i; 338 339 for (i = 0; i < sizeof(isapnp_mem32_range); i++) { 340 r = &pa->ipa_mem32[i]; 341 v0 = isapnp_read_reg(sc, 342 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_31_24); 343 v1 = isapnp_read_reg(sc, 344 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_23_16); 345 v2 = isapnp_read_reg(sc, 346 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_15_8); 347 v3 = isapnp_read_reg(sc, 348 isapnp_mem32_range[i] + ISAPNP_MEM32_BASE_7_0); 349 r->base = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; 350 if (r->base == 0) 351 break; 352 353 v0 = isapnp_read_reg(sc, 354 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_31_24); 355 v1 = isapnp_read_reg(sc, 356 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_23_16); 357 v2 = isapnp_read_reg(sc, 358 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_15_8); 359 v3 = isapnp_read_reg(sc, 360 isapnp_mem32_range[i] + ISAPNP_MEM32_LRANGE_7_0); 361 r->length = (v0 << 24) | (v1 << 16) | (v2 << 8) | v3; 362 v0 = isapnp_read_reg(sc, 363 isapnp_mem_range[i] + ISAPNP_MEM_CONTROL); 364 r->flags = v0; 365 } 366 pa->ipa_nmem32 = i; 367 } 368 369 370 /* isapnp_print_config(): 371 * Print the current configuration of the card 372 */ 373 void 374 isapnp_print_config(pa) 375 const struct isapnp_attach_args *pa; 376 { 377 int i; 378 const struct isapnp_region *r; 379 const struct isapnp_pin *p; 380 381 printf("Register configuration:\n"); 382 if (pa->ipa_nio) 383 for (i = 0; i < pa->ipa_nio; i++) { 384 r = &pa->ipa_io[i]; 385 printf("io[%d]: 0x%x/%d\n", i, r->base, r->length); 386 } 387 388 if (pa->ipa_nmem) 389 for (i = 0; i < pa->ipa_nmem; i++) { 390 r = &pa->ipa_mem[i]; 391 printf("mem[%d]: 0x%x/%d\n", i, r->base, r->length); 392 } 393 394 if (pa->ipa_nirq) 395 for (i = 0; i < pa->ipa_nirq; i++) { 396 p = &pa->ipa_irq[i]; 397 printf("irq[%d]: %d\n", i, p->num); 398 } 399 400 if (pa->ipa_ndrq) 401 for (i = 0; i < pa->ipa_ndrq; i++) { 402 p = &pa->ipa_drq[i]; 403 printf("drq[%d]: %d\n", i, p->num); 404 } 405 406 if (pa->ipa_nmem32) 407 for (i = 0; i < pa->ipa_nmem32; i++) { 408 r = &pa->ipa_mem32[i]; 409 printf("mem32[%d]: 0x%x/%d\n", i, r->base, r->length); 410 } 411 } 412 413 #endif 414