1 /* $NetBSD: ofisa.c,v 1.8 2001/11/13 07:29:45 lukem 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.8 2001/11/13 07:29:45 lukem 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 struct cfattach ofisa_ca = { 58 sizeof(struct device), ofisamatch, ofisaattach 59 }; 60 61 extern struct cfdriver ofisa_cd; 62 63 static int ofisaprint __P((void *, const char *)); 64 65 static int 66 ofisaprint(aux, pnp) 67 void *aux; 68 const char *pnp; 69 { 70 struct ofbus_attach_args *oba = aux; 71 char name[64]; 72 73 (void)of_packagename(oba->oba_phandle, name, sizeof name); 74 if (pnp) 75 printf("%s at %s", name, pnp); 76 else 77 printf(" (%s)", name); 78 return UNCONF; 79 } 80 81 int 82 ofisamatch(parent, cf, aux) 83 struct device *parent; 84 struct cfdata *cf; 85 void *aux; 86 { 87 struct ofbus_attach_args *oba = aux; 88 const char *compatible_strings[] = { "pnpPNP,a00", NULL }; 89 int rv = 0; 90 91 if (of_compatible(oba->oba_phandle, compatible_strings) != -1) 92 rv = 5; 93 94 #ifdef _OFISA_MD_MATCH 95 if (!rv) 96 rv = ofisa_md_match(parent, cf, aux); 97 #endif 98 99 return (rv); 100 } 101 102 void 103 ofisaattach(parent, self, aux) 104 struct device *parent, *self; 105 void *aux; 106 { 107 struct ofbus_attach_args *oba = aux; 108 struct isabus_attach_args iba; 109 struct ofisa_attach_args aa; 110 int child; 111 112 if (ofisa_get_isabus_data(oba->oba_phandle, &iba) < 0) { 113 printf(": couldn't get essential bus data\n"); 114 return; 115 } 116 117 printf("\n"); 118 119 #if NISADMA > 0 120 /* 121 * Initialize our DMA state. 122 */ 123 isa_dmainit(iba.iba_ic, iba.iba_iot, iba.iba_dmat, self); 124 #endif 125 126 for (child = OF_child(oba->oba_phandle); child; 127 child = OF_peer(child)) { 128 if (ofisa_ignore_child(oba->oba_phandle, child)) 129 continue; 130 131 bzero(&aa, sizeof aa); 132 133 aa.oba.oba_busname = "ofw"; /* XXX */ 134 aa.oba.oba_phandle = child; 135 aa.iot = iba.iba_iot; 136 aa.memt = iba.iba_memt; 137 aa.dmat = iba.iba_dmat; 138 aa.ic = iba.iba_ic; 139 140 config_found(self, &aa, ofisaprint); 141 } 142 } 143 144 int 145 ofisa_reg_count(phandle) 146 int phandle; 147 { 148 int len; 149 150 len = OF_getproplen(phandle, "reg"); 151 152 /* nonexistent or obviously malformed "reg" property */ 153 if (len < 0 || (len % 12) != 0) 154 return (-1); 155 return (len / 12); 156 } 157 158 int 159 ofisa_reg_get(phandle, descp, ndescs) 160 int phandle; 161 struct ofisa_reg_desc *descp; 162 int ndescs; 163 { 164 char *buf, *bp; 165 int i, proplen, allocated, rv; 166 167 i = ofisa_reg_count(phandle); 168 if (i < 0) 169 return (-1); 170 proplen = i * 12; 171 ndescs = min(ndescs, i); 172 173 i = ndescs * 12; 174 if (i > OFW_MAX_STACK_BUF_SIZE) { 175 buf = malloc(i, M_TEMP, M_WAITOK); 176 allocated = 1; 177 } else { 178 buf = alloca(i); 179 allocated = 0; 180 } 181 182 if (OF_getprop(phandle, "reg", buf, i) != proplen) { 183 rv = -1; 184 goto out; 185 } 186 187 for (i = 0, bp = buf; i < ndescs; i++, bp += 12) { 188 if (of_decode_int(&bp[0]) & 1) 189 descp[i].type = OFISA_REG_TYPE_IO; 190 else 191 descp[i].type = OFISA_REG_TYPE_MEM; 192 descp[i].addr = of_decode_int(&bp[4]); 193 descp[i].len = of_decode_int(&bp[8]); 194 } 195 rv = i; /* number of descriptors processed (== ndescs) */ 196 197 out: 198 if (allocated) 199 free(buf, M_TEMP); 200 return (rv); 201 } 202 203 void 204 ofisa_reg_print(descp, ndescs) 205 struct ofisa_reg_desc *descp; 206 int ndescs; 207 { 208 int i; 209 210 if (ndescs == 0) { 211 printf("none"); 212 return; 213 } 214 215 for (i = 0; i < ndescs; i++) { 216 printf("%s%s 0x%lx/%ld", i ? ", " : "", 217 descp[i].type == OFISA_REG_TYPE_IO ? "io" : "mem", 218 (long)descp[i].addr, (long)descp[i].len); 219 } 220 } 221 222 int 223 ofisa_intr_count(phandle) 224 int phandle; 225 { 226 int len; 227 228 len = OF_getproplen(phandle, "interrupts"); 229 230 /* nonexistent or obviously malformed "reg" property */ 231 if (len < 0 || (len % 8) != 0) 232 return (-1); 233 return (len / 8); 234 } 235 236 int 237 ofisa_intr_get(phandle, descp, ndescs) 238 int phandle; 239 struct ofisa_intr_desc *descp; 240 int ndescs; 241 { 242 char *buf, *bp; 243 int i, proplen, allocated, rv; 244 245 i = ofisa_intr_count(phandle); 246 if (i < 0) 247 return (-1); 248 proplen = i * 8; 249 ndescs = min(ndescs, i); 250 251 i = ndescs * 8; 252 if (i > OFW_MAX_STACK_BUF_SIZE) { 253 buf = malloc(i, M_TEMP, M_WAITOK); 254 allocated = 1; 255 } else { 256 buf = alloca(i); 257 allocated = 0; 258 } 259 260 if (OF_getprop(phandle, "interrupts", buf, i) != proplen) { 261 rv = -1; 262 goto out; 263 } 264 265 for (i = 0, bp = buf; i < ndescs; i++, bp += 8) { 266 descp[i].irq = of_decode_int(&bp[0]); 267 switch (of_decode_int(&bp[4])) { 268 case 0: 269 case 1: 270 descp[i].share = IST_LEVEL; 271 break; 272 case 2: 273 case 3: 274 descp[i].share = IST_EDGE; 275 break; 276 #ifdef DIAGNOSTIC 277 default: 278 /* Dunno what to do, so fail. */ 279 printf("ofisa_intr_get: unknown intrerrupt type %d\n", 280 of_decode_int(&bp[4])); 281 rv = -1; 282 goto out; 283 #endif 284 } 285 } 286 rv = i; /* number of descriptors processed (== ndescs) */ 287 288 out: 289 if (allocated) 290 free(buf, M_TEMP); 291 return (rv); 292 } 293 294 void 295 ofisa_intr_print(descp, ndescs) 296 struct ofisa_intr_desc *descp; 297 int ndescs; 298 { 299 int i; 300 301 if (ndescs == 0) { 302 printf("none"); 303 return; 304 } 305 306 for (i = 0; i < ndescs; i++) { 307 printf("%s%d (%s)", i ? ", " : "", descp[i].irq, 308 descp[i].share == IST_LEVEL ? "level" : "edge"); 309 } 310 } 311 312 int 313 ofisa_dma_count(phandle) 314 int phandle; 315 { 316 int len; 317 318 len = OF_getproplen(phandle, "dma"); 319 320 /* nonexistent or obviously malformed "reg" property */ 321 if (len < 0 || (len % 20) != 0) 322 return (-1); 323 return (len / 20); 324 } 325 326 int 327 ofisa_dma_get(phandle, descp, ndescs) 328 int phandle; 329 struct ofisa_dma_desc *descp; 330 int ndescs; 331 { 332 char *buf, *bp; 333 int i, proplen, allocated, rv; 334 335 i = ofisa_dma_count(phandle); 336 if (i < 0) 337 return (-1); 338 proplen = i * 20; 339 ndescs = min(ndescs, i); 340 341 i = ndescs * 20; 342 if (i > OFW_MAX_STACK_BUF_SIZE) { 343 buf = malloc(i, M_TEMP, M_WAITOK); 344 allocated = 1; 345 } else { 346 buf = alloca(i); 347 allocated = 0; 348 } 349 350 if (OF_getprop(phandle, "dma", buf, i) != proplen) { 351 rv = -1; 352 goto out; 353 } 354 355 for (i = 0, bp = buf; i < ndescs; i++, bp += 20) { 356 descp[i].drq = of_decode_int(&bp[0]); 357 descp[i].mode = of_decode_int(&bp[4]); 358 descp[i].width = of_decode_int(&bp[8]); 359 descp[i].countwidth = of_decode_int(&bp[12]); 360 descp[i].busmaster = of_decode_int(&bp[16]); 361 } 362 rv = i; /* number of descriptors processed (== ndescs) */ 363 364 out: 365 if (allocated) 366 free(buf, M_TEMP); 367 return (rv); 368 } 369 370 void 371 ofisa_dma_print(descp, ndescs) 372 struct ofisa_dma_desc *descp; 373 int ndescs; 374 { 375 char unkmode[16]; 376 const char *modestr; 377 int i; 378 379 if (ndescs == 0) { 380 printf("none"); 381 return; 382 } 383 384 for (i = 0; i < ndescs; i++) { 385 switch (descp[i].mode) { 386 case OFISA_DMA_MODE_COMPAT: 387 modestr = "compat"; 388 break; 389 case OFISA_DMA_MODE_A: 390 modestr = "A"; 391 break; 392 case OFISA_DMA_MODE_B: 393 modestr = "B"; 394 break; 395 case OFISA_DMA_MODE_F: 396 modestr = "F"; 397 break; 398 case OFISA_DMA_MODE_C: 399 modestr = "C"; 400 break; 401 default: 402 sprintf(unkmode, "??? (%d)", descp[i].mode); 403 modestr = unkmode; 404 break; 405 } 406 407 printf("%s%d %s mode %d-bit (%d-bit count)%s", i ? ", " : "", 408 descp[i].drq, modestr, descp[i].width, 409 descp[i].countwidth, 410 descp[i].busmaster ? " busmaster" : ""); 411 412 } 413 } 414