1 /* $NetBSD: ofisa.c,v 1.12 2002/10/02 16:34:30 thorpej Exp $ */ 2 3 /* 4 * Copyright 1997, 1998 5 * Digital Equipment Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and 8 * copied only in accordance with the following terms and conditions. 9 * Subject to these conditions, you may download, copy, install, 10 * use, modify and distribute this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce 14 * and retain this copyright notice and list of conditions as 15 * they appear in the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Digital Equipment Corporation. Neither the "Digital Equipment 19 * Corporation" name nor any trademark or logo of Digital Equipment 20 * Corporation may be used to endorse or promote products derived 21 * from this software without the prior written permission of 22 * Digital Equipment Corporation. 23 * 24 * 3) This software is provided "AS-IS" and any express or implied 25 * warranties, including but not limited to, any implied warranties 26 * of merchantability, fitness for a particular purpose, or 27 * non-infringement are disclaimed. In no event shall DIGITAL be 28 * liable for any damages whatsoever, and in particular, DIGITAL 29 * shall not be liable for special, indirect, consequential, or 30 * incidental damages or damages for lost profits, loss of 31 * revenue or loss of use, whether such damages arise in contract, 32 * negligence, tort, under statute, in equity, at law or otherwise, 33 * even if advised of the possibility of such damage. 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: ofisa.c,v 1.12 2002/10/02 16:34:30 thorpej Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/malloc.h> 43 #include <machine/bus.h> 44 #include <machine/intr.h> 45 46 #include <dev/ofw/openfirm.h> 47 #include <dev/isa/isavar.h> 48 #include <dev/ofisa/ofisavar.h> 49 50 #include "isadma.h" 51 52 #define OFW_MAX_STACK_BUF_SIZE 256 53 54 static int ofisamatch __P((struct device *, struct cfdata *, void *)); 55 static void ofisaattach __P((struct device *, struct device *, void *)); 56 57 CFATTACH_DECL(ofisa, sizeof(struct device), 58 ofisamatch, ofisaattach, NULL, NULL); 59 60 extern struct cfdriver ofisa_cd; 61 62 static int ofisaprint __P((void *, const char *)); 63 64 static int 65 ofisaprint(aux, pnp) 66 void *aux; 67 const char *pnp; 68 { 69 struct ofbus_attach_args *oba = aux; 70 char name[64]; 71 72 (void)of_packagename(oba->oba_phandle, name, sizeof name); 73 if (pnp) 74 printf("%s at %s", name, pnp); 75 else 76 printf(" (%s)", name); 77 return UNCONF; 78 } 79 80 int 81 ofisamatch(parent, cf, aux) 82 struct device *parent; 83 struct cfdata *cf; 84 void *aux; 85 { 86 struct ofbus_attach_args *oba = aux; 87 static const char *const compatible_strings[] = { "pnpPNP,a00", NULL }; 88 int rv = 0; 89 90 if (of_compatible(oba->oba_phandle, compatible_strings) != -1) 91 rv = 5; 92 93 #ifdef _OFISA_MD_MATCH 94 if (!rv) 95 rv = ofisa_md_match(parent, cf, aux); 96 #endif 97 98 return (rv); 99 } 100 101 void 102 ofisaattach(parent, self, aux) 103 struct device *parent, *self; 104 void *aux; 105 { 106 struct ofbus_attach_args *oba = aux; 107 struct isabus_attach_args iba; 108 struct ofisa_attach_args aa; 109 int child; 110 111 if (ofisa_get_isabus_data(oba->oba_phandle, &iba) < 0) { 112 printf(": couldn't get essential bus data\n"); 113 return; 114 } 115 116 printf("\n"); 117 118 #if NISADMA > 0 119 /* 120 * Initialize our DMA state. 121 */ 122 isa_dmainit(iba.iba_ic, iba.iba_iot, iba.iba_dmat, self); 123 #endif 124 125 for (child = OF_child(oba->oba_phandle); child; 126 child = OF_peer(child)) { 127 if (ofisa_ignore_child(oba->oba_phandle, child)) 128 continue; 129 130 bzero(&aa, sizeof aa); 131 132 aa.oba.oba_busname = "ofw"; /* XXX */ 133 aa.oba.oba_phandle = child; 134 aa.iot = iba.iba_iot; 135 aa.memt = iba.iba_memt; 136 aa.dmat = iba.iba_dmat; 137 aa.ic = iba.iba_ic; 138 139 config_found(self, &aa, ofisaprint); 140 } 141 } 142 143 int 144 ofisa_reg_count(phandle) 145 int phandle; 146 { 147 int len; 148 149 len = OF_getproplen(phandle, "reg"); 150 151 /* nonexistent or obviously malformed "reg" property */ 152 if (len < 0 || (len % 12) != 0) 153 return (-1); 154 return (len / 12); 155 } 156 157 int 158 ofisa_reg_get(phandle, descp, ndescs) 159 int phandle; 160 struct ofisa_reg_desc *descp; 161 int ndescs; 162 { 163 char *buf, *bp; 164 int i, proplen, allocated, rv; 165 166 i = ofisa_reg_count(phandle); 167 if (i < 0) 168 return (-1); 169 proplen = i * 12; 170 ndescs = min(ndescs, i); 171 172 i = ndescs * 12; 173 if (i > OFW_MAX_STACK_BUF_SIZE) { 174 buf = malloc(i, M_TEMP, M_WAITOK); 175 allocated = 1; 176 } else { 177 buf = alloca(i); 178 allocated = 0; 179 } 180 181 if (OF_getprop(phandle, "reg", buf, i) != proplen) { 182 rv = -1; 183 goto out; 184 } 185 186 for (i = 0, bp = buf; i < ndescs; i++, bp += 12) { 187 if (of_decode_int(&bp[0]) & 1) 188 descp[i].type = OFISA_REG_TYPE_IO; 189 else 190 descp[i].type = OFISA_REG_TYPE_MEM; 191 descp[i].addr = of_decode_int(&bp[4]); 192 descp[i].len = of_decode_int(&bp[8]); 193 } 194 rv = i; /* number of descriptors processed (== ndescs) */ 195 196 out: 197 if (allocated) 198 free(buf, M_TEMP); 199 return (rv); 200 } 201 202 void 203 ofisa_reg_print(descp, ndescs) 204 struct ofisa_reg_desc *descp; 205 int ndescs; 206 { 207 int i; 208 209 if (ndescs == 0) { 210 printf("none"); 211 return; 212 } 213 214 for (i = 0; i < ndescs; i++) { 215 printf("%s%s 0x%lx/%ld", i ? ", " : "", 216 descp[i].type == OFISA_REG_TYPE_IO ? "io" : "mem", 217 (long)descp[i].addr, (long)descp[i].len); 218 } 219 } 220 221 int 222 ofisa_intr_count(phandle) 223 int phandle; 224 { 225 int len; 226 227 len = OF_getproplen(phandle, "interrupts"); 228 229 /* nonexistent or obviously malformed "reg" property */ 230 if (len < 0 || (len % 8) != 0) 231 return (-1); 232 return (len / 8); 233 } 234 235 int 236 ofisa_intr_get(phandle, descp, ndescs) 237 int phandle; 238 struct ofisa_intr_desc *descp; 239 int ndescs; 240 { 241 char *buf, *bp; 242 int i, proplen, allocated, rv; 243 244 i = ofisa_intr_count(phandle); 245 if (i < 0) 246 return (-1); 247 proplen = i * 8; 248 ndescs = min(ndescs, i); 249 250 i = ndescs * 8; 251 if (i > OFW_MAX_STACK_BUF_SIZE) { 252 buf = malloc(i, M_TEMP, M_WAITOK); 253 allocated = 1; 254 } else { 255 buf = alloca(i); 256 allocated = 0; 257 } 258 259 if (OF_getprop(phandle, "interrupts", buf, i) != proplen) { 260 rv = -1; 261 goto out; 262 } 263 264 for (i = 0, bp = buf; i < ndescs; i++, bp += 8) { 265 descp[i].irq = of_decode_int(&bp[0]); 266 switch (of_decode_int(&bp[4])) { 267 case 0: 268 case 1: 269 descp[i].share = IST_LEVEL; 270 break; 271 case 2: 272 case 3: 273 descp[i].share = IST_EDGE; 274 break; 275 #ifdef DIAGNOSTIC 276 default: 277 /* Dunno what to do, so fail. */ 278 printf("ofisa_intr_get: unknown intrerrupt type %d\n", 279 of_decode_int(&bp[4])); 280 rv = -1; 281 goto out; 282 #endif 283 } 284 } 285 rv = i; /* number of descriptors processed (== ndescs) */ 286 287 out: 288 if (allocated) 289 free(buf, M_TEMP); 290 return (rv); 291 } 292 293 void 294 ofisa_intr_print(descp, ndescs) 295 struct ofisa_intr_desc *descp; 296 int ndescs; 297 { 298 int i; 299 300 if (ndescs == 0) { 301 printf("none"); 302 return; 303 } 304 305 for (i = 0; i < ndescs; i++) { 306 printf("%s%d (%s)", i ? ", " : "", descp[i].irq, 307 descp[i].share == IST_LEVEL ? "level" : "edge"); 308 } 309 } 310 311 int 312 ofisa_dma_count(phandle) 313 int phandle; 314 { 315 int len; 316 317 len = OF_getproplen(phandle, "dma"); 318 319 /* nonexistent or obviously malformed "reg" property */ 320 if (len < 0 || (len % 20) != 0) 321 return (-1); 322 return (len / 20); 323 } 324 325 int 326 ofisa_dma_get(phandle, descp, ndescs) 327 int phandle; 328 struct ofisa_dma_desc *descp; 329 int ndescs; 330 { 331 char *buf, *bp; 332 int i, proplen, allocated, rv; 333 334 i = ofisa_dma_count(phandle); 335 if (i < 0) 336 return (-1); 337 proplen = i * 20; 338 ndescs = min(ndescs, i); 339 340 i = ndescs * 20; 341 if (i > OFW_MAX_STACK_BUF_SIZE) { 342 buf = malloc(i, M_TEMP, M_WAITOK); 343 allocated = 1; 344 } else { 345 buf = alloca(i); 346 allocated = 0; 347 } 348 349 if (OF_getprop(phandle, "dma", buf, i) != proplen) { 350 rv = -1; 351 goto out; 352 } 353 354 for (i = 0, bp = buf; i < ndescs; i++, bp += 20) { 355 descp[i].drq = of_decode_int(&bp[0]); 356 descp[i].mode = of_decode_int(&bp[4]); 357 descp[i].width = of_decode_int(&bp[8]); 358 descp[i].countwidth = of_decode_int(&bp[12]); 359 descp[i].busmaster = of_decode_int(&bp[16]); 360 } 361 rv = i; /* number of descriptors processed (== ndescs) */ 362 363 out: 364 if (allocated) 365 free(buf, M_TEMP); 366 return (rv); 367 } 368 369 void 370 ofisa_dma_print(descp, ndescs) 371 struct ofisa_dma_desc *descp; 372 int ndescs; 373 { 374 char unkmode[16]; 375 const char *modestr; 376 int i; 377 378 if (ndescs == 0) { 379 printf("none"); 380 return; 381 } 382 383 for (i = 0; i < ndescs; i++) { 384 switch (descp[i].mode) { 385 case OFISA_DMA_MODE_COMPAT: 386 modestr = "compat"; 387 break; 388 case OFISA_DMA_MODE_A: 389 modestr = "A"; 390 break; 391 case OFISA_DMA_MODE_B: 392 modestr = "B"; 393 break; 394 case OFISA_DMA_MODE_F: 395 modestr = "F"; 396 break; 397 case OFISA_DMA_MODE_C: 398 modestr = "C"; 399 break; 400 default: 401 sprintf(unkmode, "??? (%d)", descp[i].mode); 402 modestr = unkmode; 403 break; 404 } 405 406 printf("%s%d %s mode %d-bit (%d-bit count)%s", i ? ", " : "", 407 descp[i].drq, modestr, descp[i].width, 408 descp[i].countwidth, 409 descp[i].busmaster ? " busmaster" : ""); 410 411 } 412 } 413