Annotation of sys/arch/hppa64/hppa64/mainbus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mainbus.c,v 1.4 2007/05/29 21:00:50 jason Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
! 16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #include "power.h"
! 21:
! 22: #undef BTLBDEBUG
! 23:
! 24: #include <sys/param.h>
! 25: #include <sys/systm.h>
! 26: #include <sys/device.h>
! 27: #include <sys/reboot.h>
! 28: #include <sys/extent.h>
! 29: #include <sys/mbuf.h>
! 30:
! 31: #include <uvm/uvm.h>
! 32: #include <uvm/uvm_page.h>
! 33:
! 34: #include <machine/pdc.h>
! 35: #include <machine/iomod.h>
! 36: #include <machine/autoconf.h>
! 37:
! 38: struct mainbus_softc {
! 39: struct device sc_dv;
! 40:
! 41: hppa_hpa_t sc_hpa;
! 42: };
! 43:
! 44: int mbmatch(struct device *, void *, void *);
! 45: void mbattach(struct device *, struct device *, void *);
! 46:
! 47: struct cfattach mainbus_ca = {
! 48: sizeof(struct mainbus_softc), mbmatch, mbattach
! 49: };
! 50:
! 51: struct cfdriver mainbus_cd = {
! 52: NULL, "mainbus", DV_DULL
! 53: };
! 54:
! 55: struct pdc_hpa pdc_hpa PDC_ALIGNMENT;
! 56: struct pdc_power_info pdc_power_info PDC_ALIGNMENT;
! 57:
! 58: /* from machdep.c */
! 59: extern struct extent *hppa_ex;
! 60:
! 61: int
! 62: mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
! 63: bus_space_handle_t *bshp)
! 64: {
! 65: paddr_t spa, epa;
! 66: int bank, off;
! 67:
! 68: if ((bank = vm_physseg_find(atop(bpa), &off)) >= 0)
! 69: panic("mbus_add_mapping: mapping real memory @0x%lx", bpa);
! 70:
! 71: for (spa = trunc_page(bpa), epa = bpa + size;
! 72: spa < epa; spa += PAGE_SIZE)
! 73: pmap_kenter_pa(spa, spa, UVM_PROT_RW);
! 74:
! 75: *bshp = bpa;
! 76: return (0);
! 77: }
! 78:
! 79: int
! 80: mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
! 81: int flags, bus_space_handle_t *bshp)
! 82: {
! 83: int error;
! 84:
! 85: bpa &= HPPA_PHYSMAP;
! 86: if ((error = extent_alloc_region(hppa_ex, bpa, size, EX_NOWAIT)))
! 87: return (error);
! 88:
! 89: if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
! 90: if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
! 91: printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
! 92: bpa, size);
! 93: printf("bus_space_map: can't free region\n");
! 94: }
! 95: }
! 96:
! 97: return error;
! 98: }
! 99:
! 100: void
! 101: mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
! 102: {
! 103: u_long sva, eva;
! 104:
! 105: sva = trunc_page(bsh);
! 106: eva = round_page(bsh + size);
! 107:
! 108: #ifdef DIAGNOSTIC
! 109: if (eva <= sva)
! 110: panic("bus_space_unmap: overflow");
! 111: #endif
! 112:
! 113: pmap_kremove(sva, eva - sva);
! 114:
! 115: if (extent_free(hppa_ex, bsh, size, EX_NOWAIT)) {
! 116: printf("bus_space_unmap: ps 0x%lx, size 0x%lx\n",
! 117: bsh, size);
! 118: printf("bus_space_unmap: can't free region\n");
! 119: }
! 120: }
! 121:
! 122: int
! 123: mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
! 124: bus_size_t align, bus_size_t boundary, int flags,
! 125: bus_addr_t *addrp, bus_space_handle_t *bshp)
! 126: {
! 127: bus_addr_t bpa;
! 128: int error;
! 129:
! 130: rstart &= HPPA_PHYSMAP;
! 131: rend &= HPPA_PHYSMAP;
! 132: if (rstart < hppa_ex->ex_start || rend > hppa_ex->ex_end)
! 133: panic("bus_space_alloc: bad region start/end");
! 134:
! 135: if ((error = extent_alloc_subregion(hppa_ex, rstart, rend, size,
! 136: align, 0, boundary, EX_NOWAIT, &bpa)))
! 137: return (error);
! 138:
! 139: if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
! 140: if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
! 141: printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
! 142: bpa, size);
! 143: printf("bus_space_alloc: can't free region\n");
! 144: }
! 145: }
! 146:
! 147: *addrp = bpa | ~HPPA_PHYSMAP;
! 148: return (error);
! 149: }
! 150:
! 151: void
! 152: mbus_free(void *v, bus_space_handle_t h, bus_size_t size)
! 153: {
! 154: /* bus_space_unmap() does all that we need to do. */
! 155: mbus_unmap(v, h, size);
! 156: }
! 157:
! 158: int
! 159: mbus_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
! 160: bus_size_t size, bus_space_handle_t *nbshp)
! 161: {
! 162: *nbshp = bsh + offset;
! 163: return (0);
! 164: }
! 165:
! 166: void
! 167: mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
! 168: {
! 169: sync_caches();
! 170: }
! 171:
! 172: struct hppa64_bus_space_tag hppa_bustag = {
! 173: NULL,
! 174:
! 175: mbus_map, mbus_unmap, mbus_subregion, mbus_alloc, mbus_free,
! 176: mbus_barrier,
! 177: };
! 178:
! 179: int
! 180: mbus_dmamap_create(void *v, bus_size_t size, int nsegments,
! 181: bus_size_t maxsegsz, bus_size_t boundary, int flags,
! 182: bus_dmamap_t *dmamp)
! 183: {
! 184: struct hppa64_bus_dmamap *map;
! 185: size_t mapsize;
! 186:
! 187: mapsize = sizeof(*map) + (sizeof(bus_dma_segment_t) * (nsegments - 1));
! 188: map = malloc(mapsize, M_DEVBUF,
! 189: (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK);
! 190: if (!map)
! 191: return (ENOMEM);
! 192:
! 193: bzero(map, mapsize);
! 194: map->_dm_size = size;
! 195: map->_dm_segcnt = nsegments;
! 196: map->_dm_maxsegsz = maxsegsz;
! 197: map->_dm_boundary = boundary;
! 198: map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
! 199: map->dm_mapsize = 0;
! 200: map->dm_nsegs = 0;
! 201:
! 202: *dmamp = map;
! 203: return (0);
! 204: }
! 205:
! 206: void
! 207: mbus_dmamap_unload(void *v, bus_dmamap_t map)
! 208: {
! 209: map->dm_mapsize = 0;
! 210: map->dm_nsegs = 0;
! 211: }
! 212:
! 213: void
! 214: mbus_dmamap_destroy(void *v, bus_dmamap_t map)
! 215: {
! 216: if (map->dm_mapsize != 0)
! 217: mbus_dmamap_unload(v, map);
! 218:
! 219: free(map, M_DEVBUF);
! 220: }
! 221:
! 222: /*
! 223: * Utility function to load a linear buffer. lastaddrp holds state
! 224: * between invocations (for multiple-buffer loads). segp contains
! 225: * the starting segment on entrance, and the ending segment on exit.
! 226: * first indicates if this is the first invocation of this function.
! 227: */
! 228: int
! 229: _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
! 230: bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
! 231: int *segp, int first)
! 232: {
! 233: bus_size_t sgsize;
! 234: bus_addr_t curaddr, lastaddr, baddr, bmask;
! 235: vaddr_t vaddr = (vaddr_t)buf;
! 236: int seg;
! 237: pmap_t pmap;
! 238:
! 239: pmap = p? p->p_vmspace->vm_map.pmap : pmap_kernel();
! 240: lastaddr = *lastaddrp;
! 241: bmask = ~(map->_dm_boundary - 1);
! 242:
! 243: for (seg = *segp; buflen > 0 ; ) {
! 244: /*
! 245: * Get the physical address for this segment.
! 246: */
! 247: pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
! 248:
! 249: /*
! 250: * Compute the segment size, and adjust counts.
! 251: */
! 252: sgsize = PAGE_SIZE - ((u_long)vaddr & PAGE_MASK);
! 253: if (buflen < sgsize)
! 254: sgsize = buflen;
! 255:
! 256: /*
! 257: * Make sure we don't cross any boundaries.
! 258: */
! 259: if (map->_dm_boundary > 0) {
! 260: baddr = (curaddr + map->_dm_boundary) & bmask;
! 261: if (sgsize > (baddr - curaddr))
! 262: sgsize = (baddr - curaddr);
! 263: }
! 264:
! 265: /*
! 266: * Insert chunk into a segment, coalescing with
! 267: * previous segment if possible.
! 268: */
! 269: if (first) {
! 270: map->dm_segs[seg].ds_addr = curaddr;
! 271: map->dm_segs[seg].ds_len = sgsize;
! 272: map->dm_segs[seg]._ds_va = vaddr;
! 273: first = 0;
! 274: } else {
! 275: if (curaddr == lastaddr &&
! 276: (map->dm_segs[seg].ds_len + sgsize) <=
! 277: map->_dm_maxsegsz &&
! 278: (map->_dm_boundary == 0 ||
! 279: (map->dm_segs[seg].ds_addr & bmask) ==
! 280: (curaddr & bmask)))
! 281: map->dm_segs[seg].ds_len += sgsize;
! 282: else {
! 283: if (++seg >= map->_dm_segcnt)
! 284: break;
! 285: map->dm_segs[seg].ds_addr = curaddr;
! 286: map->dm_segs[seg].ds_len = sgsize;
! 287: map->dm_segs[seg]._ds_va = vaddr;
! 288: }
! 289: }
! 290:
! 291: lastaddr = curaddr + sgsize;
! 292: vaddr += sgsize;
! 293: buflen -= sgsize;
! 294: }
! 295:
! 296: *segp = seg;
! 297: *lastaddrp = lastaddr;
! 298:
! 299: /*
! 300: * Did we fit?
! 301: */
! 302: if (buflen != 0)
! 303: return (EFBIG); /* XXX better return value here? */
! 304: return (0);
! 305: }
! 306:
! 307: int
! 308: mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
! 309: struct proc *p, int flags)
! 310: {
! 311: paddr_t lastaddr;
! 312: int seg, error;
! 313:
! 314: /*
! 315: * Make sure that on error condition we return "no valid mappings".
! 316: */
! 317: map->dm_nsegs = 0;
! 318: map->dm_mapsize = 0;
! 319:
! 320: if (size > map->_dm_size)
! 321: return (EINVAL);
! 322:
! 323: seg = 0;
! 324: lastaddr = 0;
! 325: error = _bus_dmamap_load_buffer(NULL, map, addr, size, p, flags,
! 326: &lastaddr, &seg, 1);
! 327: if (error == 0) {
! 328: map->dm_mapsize = size;
! 329: map->dm_nsegs = seg + 1;
! 330: }
! 331:
! 332: return (0);
! 333: }
! 334:
! 335: int
! 336: mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m0, int flags)
! 337: {
! 338: paddr_t lastaddr;
! 339: int seg, error, first;
! 340: struct mbuf *m;
! 341:
! 342: map->dm_mapsize = 0;
! 343: map->dm_nsegs = 0;
! 344:
! 345: #ifdef DIAGNOSTIC
! 346: if ((m0->m_flags & M_PKTHDR) == 0)
! 347: panic("_bus_dmamap_load_mbuf: no packet header");
! 348: #endif
! 349:
! 350: if (m0->m_pkthdr.len > map->_dm_size)
! 351: return (EINVAL);
! 352:
! 353: first = 1;
! 354: seg = 0;
! 355: error = 0;
! 356: lastaddr = 0;
! 357: for (m = m0; m != NULL && error == 0; m = m->m_next) {
! 358: error = _bus_dmamap_load_buffer(NULL, map, m->m_data, m->m_len,
! 359: NULL, flags, &lastaddr, &seg, first);
! 360: first = 0;
! 361: }
! 362: if (error == 0) {
! 363: map->dm_mapsize = m0->m_pkthdr.len;
! 364: map->dm_nsegs = seg + 1;
! 365: }
! 366:
! 367: return (error);
! 368: }
! 369:
! 370: int
! 371: mbus_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
! 372: {
! 373: paddr_t lastaddr;
! 374: int seg, i, error, first;
! 375: bus_size_t minlen, resid;
! 376: struct proc *p = NULL;
! 377: struct iovec *iov;
! 378: caddr_t addr;
! 379:
! 380: /*
! 381: * Make sure that on error condition we return "no valid mappings".
! 382: */
! 383: map->dm_mapsize = 0;
! 384: map->dm_nsegs = 0;
! 385:
! 386: resid = uio->uio_resid;
! 387: iov = uio->uio_iov;
! 388:
! 389: if (resid > map->_dm_size)
! 390: return (EINVAL);
! 391:
! 392: if (uio->uio_segflg == UIO_USERSPACE) {
! 393: p = uio->uio_procp;
! 394: #ifdef DIAGNOSTIC
! 395: if (p == NULL)
! 396: panic("_bus_dmamap_load_uio: USERSPACE but no proc");
! 397: #endif
! 398: }
! 399:
! 400: first = 1;
! 401: seg = 0;
! 402: error = 0;
! 403: lastaddr = 0;
! 404: for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
! 405: /*
! 406: * Now at the first iovec to load. Load each iovec
! 407: * until we have exhausted the residual count.
! 408: */
! 409: minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
! 410: addr = (caddr_t)iov[i].iov_base;
! 411:
! 412: error = _bus_dmamap_load_buffer(NULL, map, addr, minlen,
! 413: p, flags, &lastaddr, &seg, first);
! 414: first = 0;
! 415:
! 416: resid -= minlen;
! 417: }
! 418: if (error == 0) {
! 419: map->dm_mapsize = uio->uio_resid;
! 420: map->dm_nsegs = seg + 1;
! 421: }
! 422: return (error);
! 423: }
! 424:
! 425: int
! 426: mbus_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
! 427: int nsegs, bus_size_t size, int flags)
! 428: {
! 429: if (nsegs > map->_dm_segcnt || size > map->_dm_size)
! 430: return (EINVAL);
! 431:
! 432: /*
! 433: * Make sure we don't cross any boundaries.
! 434: */
! 435: if (map->_dm_boundary) {
! 436: bus_addr_t bmask = ~(map->_dm_boundary - 1);
! 437: int i;
! 438:
! 439: for (i = 0; i < nsegs; i++) {
! 440: if (segs[i].ds_len > map->_dm_maxsegsz)
! 441: return (EINVAL);
! 442: if ((segs[i].ds_addr & bmask) !=
! 443: ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
! 444: return (EINVAL);
! 445: }
! 446: }
! 447:
! 448: bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
! 449: map->dm_nsegs = nsegs;
! 450: map->dm_mapsize = size;
! 451: return (0);
! 452: }
! 453:
! 454: void
! 455: mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, bus_size_t len,
! 456: int ops)
! 457: {
! 458: bus_dma_segment_t *ps = map->dm_segs,
! 459: *es = &map->dm_segs[map->dm_nsegs];
! 460:
! 461: if (off >= map->_dm_size)
! 462: return;
! 463:
! 464: if ((off + len) > map->_dm_size)
! 465: len = map->_dm_size - off;
! 466:
! 467: for (; len && ps < es; ps++)
! 468: if (off > ps->ds_len)
! 469: off -= ps->ds_len;
! 470: else {
! 471: bus_size_t l = ps->ds_len - off;
! 472: if (l > len)
! 473: l = len;
! 474: fdcache(HPPA_SID_KERNEL, ps->_ds_va + off, l);
! 475: len -= l;
! 476: off = 0;
! 477: }
! 478:
! 479: /* for either operation sync the shit away */
! 480: sync_caches();
! 481: }
! 482:
! 483: int
! 484: mbus_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
! 485: bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
! 486: int *rsegs, int flags)
! 487: {
! 488: extern paddr_t avail_end;
! 489: struct pglist pglist;
! 490: struct vm_page *pg;
! 491:
! 492: size = round_page(size);
! 493:
! 494: TAILQ_INIT(&pglist);
! 495: if (uvm_pglistalloc(size, 0, avail_end, alignment, boundary,
! 496: &pglist, 1, flags & BUS_DMA_NOWAIT))
! 497: return (ENOMEM);
! 498:
! 499: pg = TAILQ_FIRST(&pglist);
! 500: segs[0]._ds_va = segs[0].ds_addr = VM_PAGE_TO_PHYS(pg);
! 501: segs[0].ds_len = size;
! 502: *rsegs = 1;
! 503:
! 504: for(; pg; pg = TAILQ_NEXT(pg, pageq))
! 505: /* XXX for now */
! 506: pmap_changebit(pg, PTE_UNCACHABLE, 0);
! 507: pmap_update(pmap_kernel());
! 508:
! 509: return (0);
! 510: }
! 511:
! 512: void
! 513: mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
! 514: {
! 515: struct pglist pglist;
! 516: paddr_t pa, epa;
! 517:
! 518: TAILQ_INIT(&pglist);
! 519: for(; nsegs--; segs++)
! 520: for (pa = segs->ds_addr, epa = pa + segs->ds_len;
! 521: pa < epa; pa += PAGE_SIZE) {
! 522: struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
! 523: if (!pg)
! 524: panic("mbus_dmamem_free: no page for pa");
! 525: TAILQ_INSERT_TAIL(&pglist, pg, pageq);
! 526: }
! 527: uvm_pglistfree(&pglist);
! 528: }
! 529:
! 530: int
! 531: mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
! 532: caddr_t *kvap, int flags)
! 533: {
! 534: *kvap = (caddr_t)segs[0].ds_addr;
! 535: return 0;
! 536: }
! 537:
! 538: void
! 539: mbus_dmamem_unmap(void *v, caddr_t kva, size_t size)
! 540: {
! 541: }
! 542:
! 543: paddr_t
! 544: mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
! 545: int prot, int flags)
! 546: {
! 547: panic("_dmamem_mmap: not implemented");
! 548: }
! 549:
! 550: const struct hppa64_bus_dma_tag hppa_dmatag = {
! 551: NULL,
! 552: mbus_dmamap_create, mbus_dmamap_destroy,
! 553: mbus_dmamap_load, mbus_dmamap_load_mbuf,
! 554: mbus_dmamap_load_uio, mbus_dmamap_load_raw,
! 555: mbus_dmamap_unload, mbus_dmamap_sync,
! 556:
! 557: mbus_dmamem_alloc, mbus_dmamem_free, mbus_dmamem_map,
! 558: mbus_dmamem_unmap, mbus_dmamem_mmap
! 559: };
! 560:
! 561: int
! 562: mbmatch(parent, cfdata, aux)
! 563: struct device *parent;
! 564: void *cfdata;
! 565: void *aux;
! 566: {
! 567: struct cfdata *cf = cfdata;
! 568:
! 569: /* there will be only one */
! 570: if (cf->cf_unit)
! 571: return 0;
! 572:
! 573: return 1;
! 574: }
! 575:
! 576: void
! 577: mbattach(parent, self, aux)
! 578: struct device *parent;
! 579: struct device *self;
! 580: void *aux;
! 581: {
! 582: struct mainbus_softc *sc = (struct mainbus_softc *)self;
! 583: struct confargs nca;
! 584: bus_space_handle_t ioh;
! 585: bus_addr_t hpa;
! 586:
! 587: /* fetch the "default" cpu hpa */
! 588: if (pdc_call((iodcio_t)pdc, 0, PDC_HPA, PDC_HPA_DFLT, &pdc_hpa) < 0)
! 589: panic("mbattach: PDC_HPA failed");
! 590: hpa = pdc_hpa.hpa | 0xffffffff00000000UL;
! 591:
! 592: printf(" [flex %lx]\n", hpa & HPPA_FLEX_MASK);
! 593:
! 594: /* map all the way till the end of the memory */
! 595: if (bus_space_map(&hppa_bustag, hpa, HPPA_PHYSEND - hpa + 1, 0, &ioh))
! 596: panic("mbattach: cannot map mainbus IO space");
! 597:
! 598: /*
! 599: * Local-Broadcast the HPA to all modules on this bus
! 600: */
! 601: ((struct iomod *)(HPPA_LBCAST & HPPA_PHYSMAP))->io_flex =
! 602: (hpa & HPPA_FLEX_MASK) | DMA_ENABLE;
! 603:
! 604: sc->sc_hpa = hpa;
! 605:
! 606: /* PDC first */
! 607: bzero (&nca, sizeof(nca));
! 608: nca.ca_name = "pdc";
! 609: nca.ca_iot = &hppa_bustag;
! 610: nca.ca_dmatag = &hppa_dmatag;
! 611: config_found(self, &nca, mbprint);
! 612:
! 613: #if NPOWER > 0
! 614: /* get some power */
! 615: bzero (&nca, sizeof(nca));
! 616: nca.ca_name = "power";
! 617: nca.ca_irq = -1;
! 618: if (!pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER,
! 619: PDC_SOFT_POWER_INFO, &pdc_power_info, 0)) {
! 620: nca.ca_iot = &hppa_bustag;
! 621: nca.ca_hpa = pdc_power_info.addr;
! 622: nca.ca_hpamask = HPPA_IOBEGIN;
! 623: }
! 624: config_found(self, &nca, mbprint);
! 625: #endif
! 626:
! 627: bzero (&nca, sizeof(nca));
! 628: nca.ca_iot = &hppa_bustag;
! 629: nca.ca_dmatag = &hppa_dmatag;
! 630: nca.ca_mod = -1;
! 631: pdc_scan(self, &nca);
! 632: }
! 633:
! 634: /*
! 635: * retrive CPU #N HPA value
! 636: */
! 637: hppa_hpa_t
! 638: cpu_gethpa(n)
! 639: int n;
! 640: {
! 641: struct mainbus_softc *sc;
! 642:
! 643: sc = mainbus_cd.cd_devs[0];
! 644:
! 645: return sc->sc_hpa;
! 646: }
! 647:
! 648: int
! 649: mbprint(aux, pnp)
! 650: void *aux;
! 651: const char *pnp;
! 652: {
! 653: struct confargs *ca = aux;
! 654:
! 655: if (pnp)
! 656: printf("\"%s\" at %s", ca->ca_name, pnp);
! 657:
! 658: if (ca->ca_hpa)
! 659: printf(" hpa %lx", ca->ca_hpa);
! 660:
! 661: return (UNCONF);
! 662: }
CVSweb