1 /* $NetBSD: ofisa.c,v 1.25 2016/12/09 17:18:35 christos 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.25 2016/12/09 17:18:35 christos 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, small[OFW_MAX_STACK_BUF_SIZE]; 153 int i, proplen, 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 } else { 165 buf = small; 166 } 167 168 if (OF_getprop(phandle, "reg", buf, i) != proplen) { 169 rv = -1; 170 goto out; 171 } 172 173 for (i = 0, bp = buf; i < ndescs; i++, bp += 12) { 174 if (of_decode_int(&bp[0]) & 1) 175 descp[i].type = OFISA_REG_TYPE_IO; 176 else 177 descp[i].type = OFISA_REG_TYPE_MEM; 178 descp[i].addr = of_decode_int(&bp[4]); 179 descp[i].len = of_decode_int(&bp[8]); 180 } 181 rv = i; /* number of descriptors processed (== ndescs) */ 182 183 out: 184 if (buf != small) 185 free(buf, M_TEMP); 186 return (rv); 187 } 188 189 void 190 ofisa_reg_print(struct ofisa_reg_desc *descp, int ndescs) 191 { 192 int i; 193 194 if (ndescs == 0) { 195 printf("none"); 196 return; 197 } 198 199 for (i = 0; i < ndescs; i++) { 200 printf("%s%s 0x%lx/%ld", i ? ", " : "", 201 descp[i].type == OFISA_REG_TYPE_IO ? "io" : "mem", 202 (long)descp[i].addr, (long)descp[i].len); 203 } 204 } 205 206 int 207 ofisa_intr_count(int phandle) 208 { 209 int len; 210 211 len = OF_getproplen(phandle, "interrupts"); 212 213 /* nonexistent or obviously malformed "reg" property */ 214 if (len < 0 || (len % 8) != 0) 215 return (-1); 216 return (len / 8); 217 } 218 219 int 220 ofisa_intr_get(int phandle, struct ofisa_intr_desc *descp, int ndescs) 221 { 222 char *buf, *bp, small[OFW_MAX_STACK_BUF_SIZE]; 223 int i, proplen, rv; 224 225 i = ofisa_intr_count(phandle); 226 if (i < 0) 227 return (-1); 228 proplen = i * 8; 229 ndescs = min(ndescs, i); 230 231 i = ndescs * 8; 232 if (i > OFW_MAX_STACK_BUF_SIZE) { 233 buf = malloc(i, M_TEMP, M_WAITOK); 234 } else { 235 buf = small; 236 } 237 238 if (OF_getprop(phandle, "interrupts", buf, i) != proplen) { 239 rv = -1; 240 goto out; 241 } 242 243 for (i = 0, bp = buf; i < ndescs; i++, bp += 8) { 244 descp[i].irq = of_decode_int(&bp[0]); 245 switch (of_decode_int(&bp[4])) { 246 case 0: 247 case 1: 248 descp[i].share = IST_LEVEL; 249 break; 250 case 2: 251 case 3: 252 descp[i].share = IST_EDGE; 253 break; 254 #ifdef DIAGNOSTIC 255 default: 256 /* Dunno what to do, so fail. */ 257 printf("ofisa_intr_get: unknown interrupt type %d\n", 258 of_decode_int(&bp[4])); 259 rv = -1; 260 goto out; 261 #endif 262 } 263 } 264 rv = i; /* number of descriptors processed (== ndescs) */ 265 266 out: 267 if (buf != small) 268 free(buf, M_TEMP); 269 return (rv); 270 } 271 272 void 273 ofisa_intr_print(struct ofisa_intr_desc *descp, int ndescs) 274 { 275 int i; 276 277 if (ndescs == 0) { 278 printf("none"); 279 return; 280 } 281 282 for (i = 0; i < ndescs; i++) { 283 printf("%s%d (%s)", i ? ", " : "", descp[i].irq, 284 descp[i].share == IST_LEVEL ? "level" : "edge"); 285 } 286 } 287 288 int 289 ofisa_dma_count(int phandle) 290 { 291 int len; 292 293 len = OF_getproplen(phandle, "dma"); 294 295 /* nonexistent or obviously malformed "reg" property */ 296 if (len < 0 || (len % 20) != 0) 297 return (-1); 298 return (len / 20); 299 } 300 301 int 302 ofisa_dma_get(int phandle, struct ofisa_dma_desc *descp, int ndescs) 303 { 304 char *buf, *bp, small[OFW_MAX_STACK_BUF_SIZE]; 305 int i, proplen, rv; 306 307 i = ofisa_dma_count(phandle); 308 if (i < 0) 309 return (-1); 310 proplen = i * 20; 311 ndescs = min(ndescs, i); 312 313 i = ndescs * 20; 314 if (i > OFW_MAX_STACK_BUF_SIZE) { 315 buf = malloc(i, M_TEMP, M_WAITOK); 316 } else { 317 buf = small; 318 } 319 320 if (OF_getprop(phandle, "dma", buf, i) != proplen) { 321 rv = -1; 322 goto out; 323 } 324 325 for (i = 0, bp = buf; i < ndescs; i++, bp += 20) { 326 descp[i].drq = of_decode_int(&bp[0]); 327 descp[i].mode = of_decode_int(&bp[4]); 328 descp[i].width = of_decode_int(&bp[8]); 329 descp[i].countwidth = of_decode_int(&bp[12]); 330 descp[i].busmaster = of_decode_int(&bp[16]); 331 } 332 rv = i; /* number of descriptors processed (== ndescs) */ 333 334 out: 335 if (buf != small) 336 free(buf, M_TEMP); 337 return (rv); 338 } 339 340 void 341 ofisa_dma_print(struct ofisa_dma_desc *descp, int ndescs) 342 { 343 char unkmode[16]; 344 const char *modestr; 345 int i; 346 347 if (ndescs == 0) { 348 printf("none"); 349 return; 350 } 351 352 for (i = 0; i < ndescs; i++) { 353 switch (descp[i].mode) { 354 case OFISA_DMA_MODE_COMPAT: 355 modestr = "compat"; 356 break; 357 case OFISA_DMA_MODE_A: 358 modestr = "A"; 359 break; 360 case OFISA_DMA_MODE_B: 361 modestr = "B"; 362 break; 363 case OFISA_DMA_MODE_F: 364 modestr = "F"; 365 break; 366 case OFISA_DMA_MODE_C: 367 modestr = "C"; 368 break; 369 default: 370 snprintf(unkmode, sizeof(unkmode), "??? (%d)", 371 descp[i].mode); 372 modestr = unkmode; 373 break; 374 } 375 376 printf("%s%d %s mode %d-bit (%d-bit count)%s", i ? ", " : "", 377 descp[i].drq, modestr, descp[i].width, 378 descp[i].countwidth, 379 descp[i].busmaster ? " busmaster" : ""); 380 381 } 382 } 383 384 void 385 ofisa_print_model(device_t self, int phandle) 386 { 387 char *model, small[OFW_MAX_STACK_BUF_SIZE]; 388 int n = OF_getproplen(phandle, "model"); 389 390 if (n <= 0) 391 return; 392 393 if (n > OFW_MAX_STACK_BUF_SIZE) { 394 model = malloc(n, M_TEMP, M_WAITOK); 395 } else { 396 model = small; 397 } 398 399 if (OF_getprop(phandle, "model", model, n) != n) 400 goto out; 401 402 aprint_normal(": %s\n", model); 403 if (self) 404 aprint_normal_dev(self, ""); 405 out: 406 if (model != small) 407 free(model, M_TEMP); 408 } 409