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