1 1.15 thorpej /* $NetBSD: pnpbus.c,v 1.15 2021/08/07 16:19:03 thorpej Exp $ */ 2 1.1 garbled 3 1.1 garbled /*- 4 1.1 garbled * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 garbled * All rights reserved. 6 1.1 garbled * 7 1.1 garbled * This code is derived from software contributed to The NetBSD Foundation 8 1.1 garbled * by Tim Rightnour 9 1.1 garbled * 10 1.1 garbled * Redistribution and use in source and binary forms, with or without 11 1.1 garbled * modification, are permitted provided that the following conditions 12 1.1 garbled * are met: 13 1.1 garbled * 1. Redistributions of source code must retain the above copyright 14 1.1 garbled * notice, this list of conditions and the following disclaimer. 15 1.1 garbled * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 garbled * notice, this list of conditions and the following disclaimer in the 17 1.1 garbled * documentation and/or other materials provided with the distribution. 18 1.1 garbled * 19 1.1 garbled * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 garbled * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 garbled * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 garbled * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 garbled * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 garbled * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 garbled * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 garbled * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 garbled * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 garbled * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 garbled * POSSIBILITY OF SUCH DAMAGE. 30 1.1 garbled */ 31 1.1 garbled 32 1.1 garbled #include <sys/cdefs.h> 33 1.15 thorpej __KERNEL_RCSID(0, "$NetBSD: pnpbus.c,v 1.15 2021/08/07 16:19:03 thorpej Exp $"); 34 1.1 garbled 35 1.1 garbled #include <sys/param.h> 36 1.1 garbled #include <sys/systm.h> 37 1.1 garbled #include <sys/device.h> 38 1.1 garbled #include <sys/extent.h> 39 1.13 thorpej #include <sys/kmem.h> 40 1.1 garbled 41 1.11 dyoung #include <sys/bus.h> 42 1.1 garbled #include <machine/pio.h> 43 1.1 garbled #include <machine/intr.h> 44 1.1 garbled #include <machine/platform.h> 45 1.1 garbled #include <machine/residual.h> 46 1.1 garbled #include <machine/pnp.h> 47 1.1 garbled #include <machine/isa_machdep.h> 48 1.5 garbled #include <machine/chpidpnp.h> 49 1.1 garbled 50 1.1 garbled #include <dev/isa/isareg.h> 51 1.1 garbled 52 1.1 garbled #include <prep/pnpbus/pnpbusvar.h> 53 1.1 garbled 54 1.6 garbled #include "isadma.h" 55 1.6 garbled 56 1.10 matt static int pnpbus_match(device_t, cfdata_t, void *); 57 1.10 matt static void pnpbus_attach(device_t, device_t, void *); 58 1.1 garbled static int pnpbus_print(void *, const char *); 59 1.10 matt static int pnpbus_search(device_t, cfdata_t, const int *, void *); 60 1.1 garbled 61 1.10 matt CFATTACH_DECL_NEW(pnpbus, sizeof(struct pnpbus_softc), 62 1.1 garbled pnpbus_match, pnpbus_attach, NULL, NULL); 63 1.1 garbled 64 1.1 garbled struct pnpbus_softc *pnpbus_softc; 65 1.1 garbled extern struct cfdriver pnpbus_cd; 66 1.1 garbled 67 1.1 garbled static int 68 1.10 matt pnpbus_match(device_t parent, cfdata_t cf, void *aux) 69 1.1 garbled { 70 1.8 garbled struct pnpbus_attach_args *paa = aux; 71 1.8 garbled 72 1.8 garbled if (paa->paa_name != NULL && strcmp(paa->paa_name, "pnpbus") == 0) 73 1.8 garbled return 1; 74 1.8 garbled return 0; 75 1.1 garbled } 76 1.1 garbled 77 1.1 garbled static void 78 1.10 matt pnpbus_attach(device_t parent, device_t self, void *aux) 79 1.1 garbled { 80 1.10 matt struct pnpbus_softc *sc = device_private(self); 81 1.1 garbled struct pnpbus_attach_args *paa = aux; 82 1.1 garbled 83 1.7 garbled aprint_normal("\n"); 84 1.1 garbled 85 1.1 garbled pnpbus_softc = sc; 86 1.10 matt sc->sc_dev = self; 87 1.1 garbled sc->sc_ic = paa->paa_ic; 88 1.1 garbled sc->sc_iot = paa->paa_iot; 89 1.1 garbled sc->sc_memt = paa->paa_memt; 90 1.6 garbled sc->sc_dmat = paa->paa_dmat; 91 1.6 garbled 92 1.6 garbled #if NISADMA > 0 93 1.6 garbled isa_dmainit(sc->sc_ic, sc->sc_iot, sc->sc_dmat, self); 94 1.6 garbled #endif 95 1.1 garbled 96 1.14 thorpej config_search(self, aux, 97 1.15 thorpej CFARGS(.search = pnpbus_search)); 98 1.1 garbled } 99 1.1 garbled 100 1.1 garbled static int 101 1.1 garbled pnp_newirq(void *v, struct pnpresources *r, int size) 102 1.1 garbled { 103 1.1 garbled struct _S4_Pack *p = v; 104 1.1 garbled struct pnpbus_irq *irq; 105 1.1 garbled 106 1.13 thorpej irq = kmem_alloc(sizeof(struct pnpbus_irq), KM_SLEEP); 107 1.1 garbled 108 1.1 garbled irq->mask = le16dec(&p->IRQMask[0]); 109 1.2 garbled 110 1.1 garbled if (size > 2) 111 1.1 garbled irq->flags = p->IRQInfo; 112 1.1 garbled else 113 1.3 garbled irq->flags = 0x1; 114 1.1 garbled 115 1.1 garbled SIMPLEQ_INSERT_TAIL(&r->irq, irq, next); 116 1.1 garbled r->numirq++; 117 1.1 garbled 118 1.1 garbled return 0; 119 1.1 garbled } 120 1.1 garbled 121 1.1 garbled static int 122 1.1 garbled pnp_newdma(void *v, struct pnpresources *r, int size) 123 1.1 garbled { 124 1.1 garbled struct _S5_Pack *p = v; 125 1.1 garbled struct pnpbus_dma *dma; 126 1.1 garbled 127 1.13 thorpej dma = kmem_alloc(sizeof(struct pnpbus_dma), KM_SLEEP); 128 1.1 garbled 129 1.1 garbled dma->mask = le16dec(&p->DMAMask); 130 1.1 garbled if (size > 2) 131 1.1 garbled dma->flags = p->DMAInfo; 132 1.1 garbled else 133 1.1 garbled dma->flags = 0x01; 134 1.1 garbled 135 1.1 garbled SIMPLEQ_INSERT_TAIL(&r->dma, dma, next); 136 1.1 garbled r->numdma++; 137 1.1 garbled 138 1.1 garbled return 0; 139 1.1 garbled } 140 1.1 garbled 141 1.1 garbled static int 142 1.1 garbled pnp_newioport(void *v, struct pnpresources *r, int size) 143 1.1 garbled { 144 1.1 garbled struct _S8_Pack *p = v; 145 1.1 garbled struct pnpbus_io *io; 146 1.1 garbled uint16_t mask; 147 1.1 garbled 148 1.13 thorpej io = kmem_alloc(sizeof(struct pnpbus_io), KM_SLEEP); 149 1.1 garbled mask = p->IOInfo & ISAAddr16bit ? 0xffff : 0x03ff; 150 1.1 garbled io->minbase = (p->RangeMin[0] | (p->RangeMin[1] << 8)) & mask; 151 1.1 garbled io->maxbase = (p->RangeMax[0] | (p->RangeMax[1] << 8)) & mask; 152 1.1 garbled io->align = p->IOAlign; 153 1.1 garbled io->len = p->IONum; 154 1.1 garbled io->flags = p->IOInfo; 155 1.1 garbled 156 1.1 garbled SIMPLEQ_INSERT_TAIL(&r->io, io, next); 157 1.1 garbled r->numio++; 158 1.1 garbled 159 1.1 garbled return 0; 160 1.1 garbled } 161 1.1 garbled 162 1.1 garbled static int 163 1.2 garbled pnp_newfixedioport(void *v, struct pnpresources *r, int size) 164 1.2 garbled { 165 1.2 garbled struct _S9_Pack *p = v; 166 1.2 garbled struct pnpbus_io *io; 167 1.2 garbled 168 1.13 thorpej io = kmem_alloc(sizeof(struct pnpbus_io), KM_SLEEP); 169 1.2 garbled io->minbase = (p->Range[0] | (p->Range[1] << 8)) & 0x3ff; 170 1.2 garbled io->len = p->IONum; 171 1.2 garbled io->maxbase = -1; 172 1.2 garbled io->flags = 0; 173 1.2 garbled io->align = 1; 174 1.2 garbled 175 1.2 garbled SIMPLEQ_INSERT_TAIL(&r->io, io, next); 176 1.2 garbled r->numio++; 177 1.2 garbled 178 1.2 garbled return 0; 179 1.2 garbled } 180 1.2 garbled 181 1.2 garbled static int 182 1.5 garbled pnp_newiomem(void *v, struct pnpresources *r, int size) 183 1.5 garbled { 184 1.5 garbled struct pnpbus_mem *mem; 185 1.5 garbled struct _L1_Pack *pack = v; 186 1.5 garbled 187 1.5 garbled if (pack->Count0 >= 0x9) { 188 1.13 thorpej mem = kmem_alloc(sizeof(struct pnpbus_mem), KM_SLEEP); 189 1.5 garbled mem->minbase = (pack->Data[2] << 16) | (pack->Data[1] << 8); 190 1.5 garbled mem->maxbase = (pack->Data[4] << 16) | (pack->Data[3] << 8); 191 1.5 garbled mem->align = (pack->Data[6] << 8) | pack->Data[5]; 192 1.5 garbled mem->len = (pack->Data[8] << 16) | (pack->Data[7] << 8); 193 1.5 garbled mem->flags = pack->Data[0]; 194 1.5 garbled SIMPLEQ_INSERT_TAIL(&r->iomem, mem, next); 195 1.5 garbled r->numiomem++; 196 1.5 garbled return 0; 197 1.5 garbled } 198 1.5 garbled return -1; 199 1.5 garbled } 200 1.5 garbled 201 1.5 garbled static int 202 1.1 garbled pnp_newaddr(void *v, struct pnpresources *r, int size) 203 1.1 garbled { 204 1.1 garbled struct pnpbus_io *io; 205 1.1 garbled struct pnpbus_mem *mem; 206 1.1 garbled struct _L4_Pack *pack = v; 207 1.1 garbled struct _L4_PPCPack *p = &pack->L4_Data.L4_PPCPack; 208 1.1 garbled 209 1.1 garbled if (p->PPCData[0] == 1) {/* type IO */ 210 1.13 thorpej io = kmem_alloc(sizeof(struct pnpbus_io), KM_SLEEP); 211 1.1 garbled io->minbase = (uint16_t)le64dec(&p->PPCData[4]); 212 1.1 garbled io->maxbase = -1; 213 1.1 garbled io->align = p->PPCData[1]; 214 1.1 garbled io->len = (uint16_t)le64dec(&p->PPCData[12]); 215 1.1 garbled io->flags = 0; 216 1.1 garbled SIMPLEQ_INSERT_TAIL(&r->io, io, next); 217 1.1 garbled r->numio++; 218 1.1 garbled 219 1.1 garbled return 0; 220 1.1 garbled } else if (p->PPCData[0] == 2) { 221 1.13 thorpej mem = kmem_alloc(sizeof(struct pnpbus_mem), KM_SLEEP); 222 1.1 garbled mem->minbase = (uint32_t)le64dec(&p->PPCData[4]); 223 1.1 garbled mem->maxbase = -1; 224 1.1 garbled mem->align = p->PPCData[1]; 225 1.1 garbled mem->len = (uint32_t)le64dec(&p->PPCData[12]); 226 1.1 garbled mem->flags = 0; 227 1.1 garbled SIMPLEQ_INSERT_TAIL(&r->mem, mem, next); 228 1.1 garbled r->nummem++; 229 1.1 garbled 230 1.1 garbled return 0; 231 1.1 garbled } else 232 1.1 garbled return -1; 233 1.1 garbled } 234 1.1 garbled 235 1.1 garbled static int 236 1.1 garbled pnp_newcompatid(void *v, struct pnpresources *r, int size) 237 1.1 garbled { 238 1.1 garbled struct _S3_Pack *p = v; 239 1.1 garbled struct pnpbus_compatid *id; 240 1.1 garbled uint32_t cid; 241 1.1 garbled 242 1.13 thorpej id = kmem_alloc(sizeof(*id), KM_SLEEP); 243 1.1 garbled cid = le32dec(p->CompatId); 244 1.1 garbled pnp_devid_to_string(cid, id->idstr); 245 1.1 garbled id->next = r->compatids; 246 1.1 garbled r->compatids = id; 247 1.1 garbled 248 1.1 garbled return 0; 249 1.1 garbled } 250 1.1 garbled 251 1.1 garbled /* 252 1.1 garbled * Call if match succeeds. This way we don't allocate lots of ram 253 1.1 garbled * for structures we never use if the device isn't attached. 254 1.1 garbled */ 255 1.1 garbled 256 1.1 garbled int 257 1.1 garbled pnpbus_scan(struct pnpbus_dev_attach_args *pna, PPC_DEVICE *dev) 258 1.1 garbled { 259 1.1 garbled struct pnpresources *r = &pna->pna_res; 260 1.1 garbled uint32_t l; 261 1.1 garbled uint8_t *p, *q; 262 1.1 garbled void *v; 263 1.1 garbled int tag, size, item; 264 1.1 garbled 265 1.1 garbled l = be32toh(dev->AllocatedOffset); 266 1.1 garbled p = res->DevicePnPHeap + l; 267 1.1 garbled 268 1.1 garbled if (p == NULL) 269 1.1 garbled return -1; 270 1.1 garbled 271 1.1 garbled for (; p[0] != END_TAG; p += size) { 272 1.1 garbled tag = *p; 273 1.1 garbled v = p; 274 1.1 garbled if (tag_type(p[0]) == PNP_SMALL) { 275 1.1 garbled size = tag_small_count(tag) + 1; 276 1.1 garbled item = tag_small_item_name(tag); 277 1.1 garbled switch (item) { 278 1.1 garbled case IRQFormat: 279 1.1 garbled pnp_newirq(v, r, size); 280 1.1 garbled break; 281 1.1 garbled case DMAFormat: 282 1.1 garbled pnp_newdma(v, r, size); 283 1.1 garbled break; 284 1.1 garbled case IOPort: 285 1.1 garbled pnp_newioport(v, r, size); 286 1.1 garbled break; 287 1.2 garbled case FixedIOPort: 288 1.2 garbled pnp_newfixedioport(v, r, size); 289 1.2 garbled break; 290 1.1 garbled } 291 1.1 garbled } else { 292 1.1 garbled struct _L4_Pack *pack = v; 293 1.1 garbled struct _L4_PPCPack *pa = &pack->L4_Data.L4_PPCPack; 294 1.1 garbled 295 1.1 garbled q = p; 296 1.1 garbled size = (q[1] | (q[2] << 8)) + 3 /* tag + length */; 297 1.1 garbled item = tag_large_item_name(tag); 298 1.1 garbled if (item == LargeVendorItem && 299 1.1 garbled pa->Type == LV_GenericAddress) 300 1.1 garbled pnp_newaddr(v, r, size); 301 1.5 garbled else if (item == MemoryRange) 302 1.5 garbled pnp_newiomem(v, r, size); 303 1.1 garbled } 304 1.1 garbled } 305 1.1 garbled 306 1.1 garbled /* scan for compatid's */ 307 1.1 garbled 308 1.1 garbled l = be32toh(dev->CompatibleOffset); 309 1.1 garbled p = res->DevicePnPHeap + l; 310 1.1 garbled 311 1.1 garbled if (p == NULL) 312 1.1 garbled return -1; 313 1.1 garbled 314 1.1 garbled for (; p[0] != END_TAG; p += size) { 315 1.1 garbled tag = *p; 316 1.1 garbled v = p; 317 1.1 garbled if (tag_type(p[0]) == PNP_SMALL) { 318 1.1 garbled size = tag_small_count(tag) + 1; 319 1.1 garbled item = tag_small_item_name(tag); 320 1.1 garbled switch (item) { 321 1.1 garbled case CompatibleDevice: 322 1.1 garbled pnp_newcompatid(v, r, size); 323 1.1 garbled break; 324 1.1 garbled } 325 1.1 garbled } else { 326 1.1 garbled q = p; 327 1.1 garbled size = (q[1] | (q[2] << 8)) + 3 /* tag + length */; 328 1.1 garbled } 329 1.1 garbled } 330 1.1 garbled return 0; 331 1.1 garbled } 332 1.1 garbled 333 1.1 garbled /* 334 1.1 garbled * Setup the basic pna structure. 335 1.1 garbled */ 336 1.1 garbled 337 1.1 garbled static void 338 1.1 garbled pnp_getpna(struct pnpbus_dev_attach_args *pna, struct pnpbus_attach_args *paa, 339 1.1 garbled PPC_DEVICE *dev) 340 1.1 garbled { 341 1.1 garbled DEVICE_ID *id = &dev->DeviceId; 342 1.1 garbled struct pnpresources *r = &pna->pna_res; 343 1.5 garbled ChipIDPack *pack; 344 1.5 garbled uint32_t l; 345 1.5 garbled uint8_t *p; 346 1.5 garbled void *v; 347 1.5 garbled int tag, size, item; 348 1.1 garbled 349 1.1 garbled l = be32toh(dev->AllocatedOffset); 350 1.5 garbled p = res->DevicePnPHeap + l; 351 1.1 garbled 352 1.1 garbled pna->pna_iot = paa->paa_iot; 353 1.1 garbled pna->pna_memt = paa->paa_memt; 354 1.1 garbled pna->pna_ic = paa->paa_ic; 355 1.6 garbled pna->pna_dmat = paa->paa_dmat; 356 1.1 garbled pnp_devid_to_string(id->DevId, pna->pna_devid); 357 1.4 garbled pna->basetype = id->BaseType; 358 1.4 garbled pna->subtype = id->SubType; 359 1.4 garbled pna->interface = id->Interface; 360 1.1 garbled pna->pna_ppc_dev = dev; 361 1.1 garbled memset(r, 0, sizeof(*r)); 362 1.1 garbled SIMPLEQ_INIT(&r->mem); 363 1.1 garbled SIMPLEQ_INIT(&r->io); 364 1.1 garbled SIMPLEQ_INIT(&r->irq); 365 1.1 garbled SIMPLEQ_INIT(&r->dma); 366 1.5 garbled SIMPLEQ_INIT(&r->iomem); 367 1.5 garbled if (p == NULL) 368 1.5 garbled return; 369 1.5 garbled /* otherwise, we start looking for chipid's */ 370 1.5 garbled for (; p[0] != END_TAG; p += size) { 371 1.5 garbled tag = *p; 372 1.5 garbled v = p; 373 1.5 garbled if (tag_type(p[0]) == PNP_SMALL) { 374 1.5 garbled size = tag_small_count(tag) + 1; 375 1.5 garbled item = tag_small_item_name(tag); 376 1.5 garbled if (item != SmallVendorItem || p[1] != 1) 377 1.5 garbled continue; 378 1.5 garbled pack = v; 379 1.5 garbled pna->chipid = le16dec(&pack->Name[0]); 380 1.5 garbled pna->chipmfg0 = pack->VendorID0; 381 1.5 garbled pna->chipmfg1 = pack->VendorID1; 382 1.5 garbled break; 383 1.5 garbled } else { 384 1.5 garbled /* Large */ 385 1.5 garbled size = (p[1] | (p[2] << 8)) + 3 /* tag + length */; 386 1.5 garbled } 387 1.5 garbled } 388 1.1 garbled } 389 1.1 garbled 390 1.1 garbled static int 391 1.10 matt pnpbus_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 392 1.1 garbled { 393 1.1 garbled struct pnpbus_dev_attach_args pna; 394 1.1 garbled struct pnpbus_attach_args *paa = aux; 395 1.1 garbled PPC_DEVICE *ppc_dev; 396 1.1 garbled int i; 397 1.1 garbled uint32_t ndev; 398 1.1 garbled 399 1.1 garbled ndev = be32toh(res->ActualNumDevices); 400 1.1 garbled ppc_dev = res->Devices; 401 1.1 garbled 402 1.1 garbled for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) { 403 1.1 garbled pnp_getpna(&pna, paa, &ppc_dev[i]); 404 1.14 thorpej if (config_probe(parent, cf, &pna)) 405 1.14 thorpej config_attach(parent, cf, &pna, pnpbus_print, 406 1.15 thorpej CFARGS_NONE); 407 1.1 garbled } 408 1.1 garbled 409 1.1 garbled return 0; 410 1.1 garbled } 411 1.1 garbled 412 1.1 garbled static void 413 1.1 garbled pnpbus_printres(struct pnpresources *r) 414 1.1 garbled { 415 1.1 garbled struct pnpbus_io *io; 416 1.1 garbled struct pnpbus_mem *mem; 417 1.1 garbled struct pnpbus_irq *irq; 418 1.1 garbled struct pnpbus_dma *dma; 419 1.1 garbled int p = 0; 420 1.1 garbled 421 1.1 garbled if (!SIMPLEQ_EMPTY(&r->mem)) { 422 1.1 garbled aprint_normal("mem"); 423 1.1 garbled SIMPLEQ_FOREACH(mem, &r->mem, next) { 424 1.1 garbled aprint_normal(" 0x%x", mem->minbase); 425 1.1 garbled if (mem->len > 1) 426 1.1 garbled aprint_normal("-0x%x", 427 1.1 garbled mem->minbase + mem->len - 1); 428 1.1 garbled } 429 1.1 garbled p++; 430 1.1 garbled } 431 1.1 garbled if (!SIMPLEQ_EMPTY(&r->io)) { 432 1.1 garbled if (p++) 433 1.1 garbled aprint_normal(", "); 434 1.1 garbled aprint_normal("port"); 435 1.1 garbled SIMPLEQ_FOREACH(io, &r->io, next) { 436 1.1 garbled aprint_normal(" 0x%x", io->minbase); 437 1.1 garbled if (io->len > 1) 438 1.1 garbled aprint_normal("-0x%x", 439 1.1 garbled io->minbase + io->len - 1); 440 1.1 garbled } 441 1.1 garbled } 442 1.5 garbled if (!SIMPLEQ_EMPTY(&r->iomem)) { 443 1.5 garbled if (p++) 444 1.5 garbled aprint_normal(", "); 445 1.5 garbled aprint_normal("iomem"); 446 1.5 garbled SIMPLEQ_FOREACH(mem, &r->iomem, next) { 447 1.5 garbled aprint_normal(" 0x%x", mem->minbase); 448 1.5 garbled if (mem->len > 1) 449 1.5 garbled aprint_normal("-0x%x", 450 1.5 garbled mem->minbase + mem->len - 1); 451 1.5 garbled } 452 1.5 garbled p++; 453 1.5 garbled } 454 1.1 garbled if (!SIMPLEQ_EMPTY(&r->irq)) { 455 1.1 garbled if (p++) 456 1.1 garbled aprint_normal(", "); 457 1.1 garbled aprint_normal("irq"); 458 1.1 garbled SIMPLEQ_FOREACH(irq, &r->irq, next) { 459 1.1 garbled aprint_normal(" %d", ffs(irq->mask) - 1); 460 1.1 garbled } 461 1.1 garbled } 462 1.1 garbled if (!SIMPLEQ_EMPTY(&r->dma)) { 463 1.1 garbled if (p++) 464 1.1 garbled aprint_normal(", "); 465 1.1 garbled aprint_normal("DMA"); 466 1.1 garbled SIMPLEQ_FOREACH(dma, &r->dma, next) { 467 1.1 garbled aprint_normal(" %d", ffs(dma->mask) - 1); 468 1.1 garbled } 469 1.1 garbled } 470 1.1 garbled } 471 1.1 garbled 472 1.2 garbled void 473 1.2 garbled pnpbus_print_devres(struct pnpbus_dev_attach_args *pna) 474 1.2 garbled { 475 1.2 garbled aprint_normal(": "); 476 1.2 garbled pnpbus_printres(&pna->pna_res); 477 1.2 garbled } 478 1.2 garbled 479 1.1 garbled static int 480 1.1 garbled pnpbus_print(void *args, const char *name) 481 1.1 garbled { 482 1.1 garbled struct pnpbus_dev_attach_args *pna = args; 483 1.1 garbled 484 1.2 garbled pnpbus_print_devres(pna); 485 1.1 garbled return (UNCONF); 486 1.1 garbled } 487 1.1 garbled 488 1.1 garbled /* 489 1.1 garbled * Set up an interrupt handler to start being called. 490 1.1 garbled */ 491 1.1 garbled void * 492 1.8 garbled pnpbus_intr_establish(int idx, int level, int tover, int (*ih_fun)(void *), 493 1.1 garbled void *ih_arg, struct pnpresources *r) 494 1.1 garbled { 495 1.1 garbled struct pnpbus_irq *irq; 496 1.1 garbled int irqnum, type; 497 1.1 garbled 498 1.1 garbled if (idx >= r->numirq) 499 1.1 garbled return 0; 500 1.1 garbled 501 1.1 garbled irq = SIMPLEQ_FIRST(&r->irq); 502 1.1 garbled while (idx--) 503 1.1 garbled irq = SIMPLEQ_NEXT(irq, next); 504 1.1 garbled 505 1.1 garbled irqnum = ffs(irq->mask) - 1; 506 1.1 garbled type = (irq->flags & 0x0c) ? IST_LEVEL : IST_EDGE; 507 1.8 garbled if (tover != IST_PNP) 508 1.8 garbled type = tover; 509 1.1 garbled 510 1.1 garbled return (void *)intr_establish(irqnum, type, level, ih_fun, ih_arg); 511 1.1 garbled } 512 1.1 garbled 513 1.1 garbled /* 514 1.1 garbled * Deregister an interrupt handler. 515 1.1 garbled */ 516 1.1 garbled void 517 1.1 garbled pnpbus_intr_disestablish(void *arg) 518 1.1 garbled { 519 1.1 garbled 520 1.1 garbled intr_disestablish(arg); 521 1.1 garbled } 522 1.1 garbled 523 1.1 garbled int 524 1.1 garbled pnpbus_getirqnum(struct pnpresources *r, int idx, int *irqp, int *istp) 525 1.1 garbled { 526 1.1 garbled struct pnpbus_irq *irq; 527 1.1 garbled 528 1.1 garbled if (idx >= r->numirq) 529 1.1 garbled return EINVAL; 530 1.1 garbled 531 1.1 garbled irq = SIMPLEQ_FIRST(&r->irq); 532 1.1 garbled while (idx--) 533 1.1 garbled irq = SIMPLEQ_NEXT(irq, next); 534 1.1 garbled 535 1.1 garbled if (irqp != NULL) 536 1.1 garbled *irqp = ffs(irq->mask) - 1; 537 1.1 garbled if (istp != NULL) 538 1.1 garbled *istp = (irq->flags &0x0c) ? IST_LEVEL : IST_EDGE; 539 1.1 garbled return 0; 540 1.1 garbled } 541 1.1 garbled 542 1.1 garbled int 543 1.1 garbled pnpbus_getdmachan(struct pnpresources *r, int idx, int *chanp) 544 1.1 garbled { 545 1.1 garbled struct pnpbus_dma *dma; 546 1.1 garbled 547 1.1 garbled if (idx >= r->numdma) 548 1.1 garbled return EINVAL; 549 1.1 garbled 550 1.1 garbled dma = SIMPLEQ_FIRST(&r->dma); 551 1.1 garbled while (idx--) 552 1.1 garbled dma = SIMPLEQ_NEXT(dma, next); 553 1.1 garbled 554 1.1 garbled if (chanp != NULL) 555 1.1 garbled *chanp = ffs(dma->mask) - 1; 556 1.1 garbled return 0; 557 1.1 garbled } 558 1.1 garbled 559 1.1 garbled int 560 1.1 garbled pnpbus_getioport(struct pnpresources *r, int idx, int *basep, int *sizep) 561 1.1 garbled { 562 1.1 garbled struct pnpbus_io *io; 563 1.1 garbled 564 1.1 garbled if (idx >= r->numio) 565 1.1 garbled return EINVAL; 566 1.1 garbled 567 1.1 garbled io = SIMPLEQ_FIRST(&r->io); 568 1.1 garbled while (idx--) 569 1.1 garbled io = SIMPLEQ_NEXT(io, next); 570 1.1 garbled 571 1.1 garbled if (basep) 572 1.1 garbled *basep = io->minbase; 573 1.1 garbled if (sizep) 574 1.1 garbled *sizep = io->len; 575 1.1 garbled return 0; 576 1.1 garbled } 577 1.1 garbled 578 1.1 garbled int 579 1.1 garbled pnpbus_io_map(struct pnpresources *r, int idx, bus_space_tag_t *tagp, 580 1.1 garbled bus_space_handle_t *hdlp) 581 1.1 garbled { 582 1.1 garbled struct pnpbus_io *io; 583 1.1 garbled 584 1.1 garbled if (idx >= r->numio) 585 1.1 garbled return EINVAL; 586 1.1 garbled 587 1.1 garbled io = SIMPLEQ_FIRST(&r->io); 588 1.1 garbled while (idx--) 589 1.1 garbled io = SIMPLEQ_NEXT(io, next); 590 1.1 garbled 591 1.7 garbled *tagp = &genppc_isa_io_space_tag; 592 1.7 garbled return (bus_space_map(&genppc_isa_io_space_tag, io->minbase, io->len, 593 1.1 garbled 0, hdlp)); 594 1.1 garbled } 595 1.1 garbled 596 1.1 garbled void 597 1.1 garbled pnpbus_io_unmap(struct pnpresources *r, int idx, bus_space_tag_t tag, 598 1.1 garbled bus_space_handle_t hdl) 599 1.1 garbled { 600 1.1 garbled struct pnpbus_io *io; 601 1.1 garbled 602 1.1 garbled if (idx >= r->numio) 603 1.1 garbled return; 604 1.1 garbled 605 1.1 garbled io = SIMPLEQ_FIRST(&r->io); 606 1.1 garbled while (idx--) 607 1.1 garbled io = SIMPLEQ_NEXT(io, next); 608 1.1 garbled 609 1.1 garbled bus_space_unmap(tag, hdl, io->len); 610 1.1 garbled } 611 1.5 garbled 612 1.5 garbled int 613 1.5 garbled pnpbus_getiomem(struct pnpresources *r, int idx, int *basep, int *sizep) 614 1.5 garbled { 615 1.5 garbled struct pnpbus_mem *mem; 616 1.5 garbled 617 1.5 garbled if (idx >= r->numiomem) 618 1.5 garbled return EINVAL; 619 1.5 garbled 620 1.5 garbled mem = SIMPLEQ_FIRST(&r->iomem); 621 1.5 garbled while (idx--) 622 1.5 garbled mem = SIMPLEQ_NEXT(mem, next); 623 1.5 garbled 624 1.5 garbled if (basep) 625 1.5 garbled *basep = mem->minbase; 626 1.5 garbled if (sizep) 627 1.5 garbled *sizep = mem->len; 628 1.5 garbled return 0; 629 1.5 garbled } 630 1.5 garbled 631 1.5 garbled int 632 1.5 garbled pnpbus_iomem_map(struct pnpresources *r, int idx, bus_space_tag_t *tagp, 633 1.5 garbled bus_space_handle_t *hdlp) 634 1.5 garbled { 635 1.5 garbled struct pnpbus_mem *mem; 636 1.5 garbled 637 1.5 garbled if (idx >= r->numiomem) 638 1.5 garbled return EINVAL; 639 1.5 garbled 640 1.5 garbled mem = SIMPLEQ_FIRST(&r->iomem); 641 1.5 garbled while (idx--) 642 1.5 garbled mem = SIMPLEQ_NEXT(mem, next); 643 1.5 garbled 644 1.7 garbled *tagp = &genppc_isa_mem_space_tag; 645 1.7 garbled return (bus_space_map(&genppc_isa_mem_space_tag, mem->minbase, mem->len, 646 1.5 garbled 0, hdlp)); 647 1.5 garbled } 648 1.5 garbled 649 1.5 garbled void 650 1.5 garbled pnpbus_iomem_unmap(struct pnpresources *r, int idx, bus_space_tag_t tag, 651 1.5 garbled bus_space_handle_t hdl) 652 1.5 garbled { 653 1.5 garbled struct pnpbus_mem *mem; 654 1.5 garbled 655 1.5 garbled if (idx >= r->numiomem) 656 1.5 garbled return; 657 1.5 garbled 658 1.5 garbled mem = SIMPLEQ_FIRST(&r->mem); 659 1.5 garbled while (idx--) 660 1.5 garbled mem = SIMPLEQ_NEXT(mem, next); 661 1.5 garbled 662 1.5 garbled bus_space_unmap(tag, hdl, mem->len); 663 1.5 garbled } 664