Annotation of sys/arch/hp300/dev/isabr.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: isabr.c,v 1.2 2007/01/14 17:54:45 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2007 Miodrag Vallat.
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice, this permission notice, and the disclaimer below
! 9: * 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 USE, DATA OR PROFITS, WHETHER IN AN
! 16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: /*
! 21: * HP 9000/4xx model `t' single ISA slot attachment
! 22: */
! 23:
! 24: #include <sys/param.h>
! 25: #include <sys/systm.h>
! 26: #include <sys/device.h>
! 27: #include <sys/extent.h>
! 28: #include <sys/malloc.h>
! 29:
! 30: #include <machine/autoconf.h>
! 31: #include <machine/bus.h>
! 32: #include <machine/cpu.h>
! 33: #include <machine/hp300spu.h>
! 34:
! 35: #include <uvm/uvm_extern.h>
! 36:
! 37: #include <dev/isa/isareg.h>
! 38: #include <dev/isa/isavar.h>
! 39:
! 40: #include <hp300/dev/frodoreg.h>
! 41: #include <hp300/dev/frodovar.h>
! 42: #include <hp300/dev/isabrreg.h>
! 43:
! 44: int isabr_match(struct device *, void *, void *);
! 45: void isabr_attach(struct device *, struct device *, void *);
! 46: int isabr_print(void *, const char *);
! 47:
! 48: struct isabr_softc {
! 49: struct device sc_dev;
! 50: struct extent *sc_io_extent;
! 51: struct extent *sc_mem_extent;
! 52: };
! 53:
! 54: struct cfattach isabr_ca = {
! 55: sizeof(struct isabr_softc), isabr_match, isabr_attach
! 56: };
! 57:
! 58: struct cfdriver isabr_cd = {
! 59: NULL, "isabr", DV_DULL
! 60: };
! 61:
! 62: struct isabr_softc *isabr;
! 63:
! 64: int isabr_bus_space_setup(struct isabr_softc *, struct frodo_attach_args *,
! 65: struct isabus_attach_args *);
! 66:
! 67: int
! 68: isabr_match(struct device *parent, void *match, void *aux)
! 69: {
! 70: struct frodo_attach_args *fa = aux;
! 71: static int isa_matched = 0;
! 72:
! 73: if (isa_matched != 0)
! 74: return (0);
! 75:
! 76: if (strcmp(fa->fa_name, isabr_cd.cd_name) != 0)
! 77: return (0);
! 78:
! 79: /*
! 80: * We assume parent has checked our physical existence for us.
! 81: */
! 82:
! 83: return (isa_matched = 1);
! 84: }
! 85:
! 86: void
! 87: isabr_attach(struct device *parent, struct device *self, void *aux)
! 88: {
! 89: struct isabus_attach_args iba;
! 90: struct isabr_softc *sc = (struct isabr_softc *)self;
! 91: struct frodo_attach_args *faa = (struct frodo_attach_args *)aux;
! 92:
! 93: bzero(&iba, sizeof(iba));
! 94:
! 95: if (isabr_bus_space_setup(sc, faa, &iba) != 0) {
! 96: printf(": can not initialize bus_space\n");
! 97: return;
! 98: }
! 99: printf("\n");
! 100:
! 101: iba.iba_busname = "isa";
! 102: config_found(self, &iba, isabr_print);
! 103: }
! 104:
! 105: int
! 106: isabr_print(void *aux, const char *pnp)
! 107: {
! 108: if (pnp)
! 109: printf("isa at %s", pnp);
! 110: return (UNCONF);
! 111: }
! 112:
! 113: /*
! 114: * ISA support functions
! 115: */
! 116:
! 117: void
! 118: isa_attach_hook(struct device *parent, struct device *self,
! 119: struct isabus_attach_args *iba)
! 120: {
! 121: iba->iba_ic = parent; /* isabr0 */
! 122: }
! 123:
! 124: /*
! 125: * Interrupt handling.
! 126: *
! 127: * We are currently registering ISA interrupt handlers as Frodo interrupt
! 128: * handlers directly. We can because model `t' only have a single slot.
! 129: *
! 130: * Eventually this should be replaced with an isabr interrupt dispatcher,
! 131: * allowing multiple interrupts on the same Frodo line. This would also
! 132: * move the ISA-specific acknowledge out of non-ISA Frodo lines processing.
! 133: * And this would allow a real intr_disestablish function.
! 134: */
! 135: void *
! 136: isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
! 137: int (*handler)(void *), void *arg, char *name)
! 138: {
! 139: struct isabr_softc *sc = (struct isabr_softc *)ic;
! 140: struct isr *isr;
! 141: int fline;
! 142:
! 143: /*
! 144: * Frodo is configured for edge interrupts.
! 145: */
! 146: if (type != IST_EDGE) {
! 147: #ifdef DIAGNOSTIC
! 148: printf("%s: non-edge interrupt type not supported on hp300\n",
! 149: name);
! 150: #endif
! 151: return (NULL);
! 152: }
! 153:
! 154: switch (irq) {
! 155: case 3:
! 156: case 4:
! 157: case 5:
! 158: case 6:
! 159: fline = FRODO_INTR_ILOW;
! 160: break;
! 161: case 7:
! 162: case 9:
! 163: case 10:
! 164: case 11:
! 165: fline = FRODO_INTR_IMID;
! 166: break;
! 167: case 12:
! 168: case 14:
! 169: case 15:
! 170: fline = FRODO_INTR_IHI;
! 171: break;
! 172: default:
! 173: #ifdef DIAGNOSTIC
! 174: printf("%s: ISA irq %d not available on " MACHINE "\n", name);
! 175: #endif
! 176: return (NULL);
! 177: }
! 178:
! 179: isr = (struct isr *)malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
! 180: if (isr == NULL)
! 181: return (NULL);
! 182:
! 183: isr->isr_func = handler;
! 184: isr->isr_arg = arg;
! 185: isr->isr_priority = level;
! 186:
! 187: if (frodo_intr_establish(sc->sc_dev.dv_parent, fline, isr, name) == 0)
! 188: return (isr);
! 189:
! 190: free(isr, M_DEVBUF);
! 191: return (NULL);
! 192: }
! 193:
! 194: void
! 195: isa_intr_disestablish(isa_chipset_tag_t ic, void *cookie)
! 196: {
! 197: #if 0
! 198: struct isabr_softc *sc = (struct isabr_softc *)ic;
! 199: struct isr *isr = cookie;
! 200:
! 201: /* XXX how to find fline back? */
! 202: frodo_intr_disestablish(sc->dv_parent, fline);
! 203: free(isr, M_DEVBUF);
! 204: #else
! 205: panic("isa_intr_disestablish");
! 206: #endif
! 207: }
! 208:
! 209: /*
! 210: * Implementation of bus_space mapping for the hp300 isa slot.
! 211: *
! 212: * Everything is memory mapped, but the I/O space is scattered for better
! 213: * userland access control granularity, should we ever provide iopl
! 214: * facilities, thus i/o space accesses need their own routines set, while
! 215: * memory space simply reuse the ``canonical'' bus_space routines.
! 216: *
! 217: * For the I/O space, all bus_space_map allocations are extended to a 8 ports
! 218: * granularity, so that they span entire, contiguous pages; the handle value
! 219: * however needs to keep track of the in-page offset if the first port is
! 220: * not aligned to a ``line'' boundary.
! 221: *
! 222: * I.e, a bus_space_map(0x302, 0xe) call will map the 0x300-0x30f area,
! 223: * and return a pointer the 0x302 port. Access routines will then, from
! 224: * this pointer, construct a (0x300, 0x02) tuple, which they can use to
! 225: * access the remainder of the range.
! 226: */
! 227:
! 228: /*
! 229: * ISA I/O space
! 230: */
! 231:
! 232: int hp300_isa_io_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
! 233: void hp300_isa_io_unmap(bus_space_handle_t, bus_size_t);
! 234: int hp300_isa_io_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
! 235: bus_space_handle_t *);
! 236: void * hp300_isa_io_vaddr(bus_space_handle_t);
! 237:
! 238: u_int8_t hp300_isa_io_bsr1(bus_space_handle_t, bus_size_t);
! 239: u_int16_t hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
! 240: u_int32_t hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
! 241: u_int16_t __hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
! 242: u_int32_t __hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
! 243: void hp300_isa_io_bsrm1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 244: void hp300_isa_io_bsrm2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
! 245: void hp300_isa_io_bsrm4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
! 246: void hp300_isa_io_bsrrm2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 247: void hp300_isa_io_bsrrm4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 248: void hp300_isa_io_bsrr1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 249: void hp300_isa_io_bsrr2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
! 250: void hp300_isa_io_bsrr4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
! 251: void hp300_isa_io_bsrrr2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 252: void hp300_isa_io_bsrrr4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
! 253: void hp300_isa_io_bsw1(bus_space_handle_t, bus_size_t, u_int8_t);
! 254: void hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
! 255: void hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
! 256: void __hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
! 257: void __hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
! 258: void hp300_isa_io_bswm1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 259: void hp300_isa_io_bswm2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
! 260: void hp300_isa_io_bswm4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
! 261: void hp300_isa_io_bswrm2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 262: void hp300_isa_io_bswrm4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 263: void hp300_isa_io_bswr1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 264: void hp300_isa_io_bswr2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
! 265: void hp300_isa_io_bswr4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
! 266: void hp300_isa_io_bswrr2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 267: void hp300_isa_io_bswrr4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
! 268: void hp300_isa_io_bssm1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
! 269: void hp300_isa_io_bssm2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
! 270: void hp300_isa_io_bssm4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
! 271: void hp300_isa_io_bssr1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
! 272: void hp300_isa_io_bssr2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
! 273: void hp300_isa_io_bssr4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
! 274:
! 275: struct hp300_bus_space_tag hp300_isa_io_tag = {
! 276: hp300_isa_io_map,
! 277: hp300_isa_io_unmap,
! 278: hp300_isa_io_subregion,
! 279: hp300_isa_io_vaddr,
! 280:
! 281: hp300_isa_io_bsr1,
! 282: hp300_isa_io_bsr2,
! 283: hp300_isa_io_bsr4,
! 284:
! 285: hp300_isa_io_bsrm1,
! 286: hp300_isa_io_bsrm2,
! 287: hp300_isa_io_bsrm4,
! 288:
! 289: hp300_isa_io_bsrrm2,
! 290: hp300_isa_io_bsrrm4,
! 291:
! 292: hp300_isa_io_bsrr1,
! 293: hp300_isa_io_bsrr2,
! 294: hp300_isa_io_bsrr4,
! 295:
! 296: hp300_isa_io_bsrrr2,
! 297: hp300_isa_io_bsrrr4,
! 298:
! 299: hp300_isa_io_bsw1,
! 300: hp300_isa_io_bsw2,
! 301: hp300_isa_io_bsw4,
! 302:
! 303: hp300_isa_io_bswm1,
! 304: hp300_isa_io_bswm2,
! 305: hp300_isa_io_bswm4,
! 306:
! 307: hp300_isa_io_bswrm2,
! 308: hp300_isa_io_bswrm4,
! 309:
! 310: hp300_isa_io_bswr1,
! 311: hp300_isa_io_bswr2,
! 312: hp300_isa_io_bswr4,
! 313:
! 314: hp300_isa_io_bswrr2,
! 315: hp300_isa_io_bswrr4,
! 316:
! 317: hp300_isa_io_bssm1,
! 318: hp300_isa_io_bssm2,
! 319: hp300_isa_io_bssm4,
! 320:
! 321: hp300_isa_io_bssr1,
! 322: hp300_isa_io_bssr2,
! 323: hp300_isa_io_bssr4
! 324: };
! 325:
! 326: int
! 327: hp300_isa_io_map(bus_addr_t bpa, bus_size_t size, int flags,
! 328: bus_space_handle_t *bshp)
! 329: {
! 330: int error;
! 331: u_int iobase, iosize, npg;
! 332: vaddr_t va;
! 333: paddr_t pa;
! 334:
! 335: #ifdef DEBUG
! 336: printf("isa_io_map(%04x, %04x)", bpa, size);
! 337: #endif
! 338:
! 339: /*
! 340: * Reserve the range in the allocation extent.
! 341: */
! 342: if (bpa < IO_ISABEGIN || bpa + size > IO_ISAEND + 1) {
! 343: #ifdef DEBUG
! 344: printf(" outside available range\n");
! 345: #endif
! 346: return (ERANGE);
! 347: }
! 348: error = extent_alloc_region(isabr->sc_io_extent, bpa, size,
! 349: EX_MALLOCOK);
! 350: if (error != 0) {
! 351: #ifdef DEBUG
! 352: printf(" overlaps extent\n");
! 353: #endif
! 354: return (error);
! 355: }
! 356:
! 357: /*
! 358: * Round the allocation to a multiple of 8 bytes, to end up
! 359: * with entire pages.
! 360: */
! 361: iobase = bpa & ~(ISABR_IOPORT_LINE - 1);
! 362: iosize = ((bpa + size + (ISABR_IOPORT_LINE - 1)) &
! 363: ~(ISABR_IOPORT_LINE - 1)) - iobase;
! 364:
! 365: /*
! 366: * Compute how many pages will be necessary to map this range.
! 367: */
! 368: npg = iosize / ISABR_IOPORT_LINE;
! 369: #ifdef DEBUG
! 370: printf("->(%04x, %04x)=%d@", iobase, iosize, npg);
! 371: #endif
! 372:
! 373: /*
! 374: * Allocate virtual address space to map this space in.
! 375: */
! 376: va = uvm_km_valloc(kernel_map, ptoa(npg));
! 377: if (va == 0) {
! 378: #ifdef DEBUG
! 379: printf("NULL\n");
! 380: #endif
! 381: extent_free(isabr->sc_io_extent, bpa, size, EX_MALLOCOK);
! 382: return (ENOMEM);
! 383: }
! 384:
! 385: *bshp = (bus_space_handle_t)(va + (bpa - iobase));
! 386:
! 387: pa = ISABR_IOPORT_BASE + ISAADDR(iobase);
! 388: #ifdef DEBUG
! 389: printf("%08x (ret %08x) pa %08x\n", va, *bshp, pa);
! 390: #endif
! 391:
! 392: while (npg != 0) {
! 393: pmap_kenter_cache(va, pa, PG_RW | PG_CI);
! 394: npg--;
! 395: va += PAGE_SIZE;
! 396: pa += PAGE_SIZE;
! 397: }
! 398: pmap_update(pmap_kernel());
! 399:
! 400: return (0);
! 401: }
! 402:
! 403: void
! 404: hp300_isa_io_unmap(bus_space_handle_t bsh, bus_size_t size)
! 405: {
! 406: u_int iobase, iosize, npg;
! 407: vaddr_t va;
! 408: paddr_t pa;
! 409:
! 410: #ifdef DEBUG
! 411: printf("isa_io_unmap(%08x, %04x)", bsh, size);
! 412: #endif
! 413:
! 414: /*
! 415: * Find the pa matching this allocation, and the I/O port base
! 416: * from it.
! 417: */
! 418: va = (vaddr_t)bsh;
! 419: if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) {
! 420: #ifdef DEBUG
! 421: printf("-> no pa\n");
! 422: #endif
! 423: return; /* XXX be vocal? */
! 424: }
! 425:
! 426: #ifdef DEBUG
! 427: printf("-> pa %08x ", pa);
! 428: #endif
! 429: pa -= ISABR_IOPORT_BASE;
! 430: iobase = ISAPORT(pa);
! 431: if (iobase < IO_ISABEGIN || iobase > IO_ISAEND) {
! 432: #ifdef DEBUG
! 433: printf("iobase %08x???\n", iobase);
! 434: #endif
! 435: return; /* XXX be vocal? */
! 436: }
! 437:
! 438: iosize = size + (iobase & (ISABR_IOPORT_LINE - 1)) +
! 439: (ISABR_IOPORT_LINE - 1);
! 440: npg = iosize / ISABR_IOPORT_LINE;
! 441: #ifdef DEBUG
! 442: printf(" range %04x-%04x: %d\n", iobase, size, npg);
! 443: #endif
! 444:
! 445: pmap_kremove(va, ptoa(npg));
! 446: pmap_update(pmap_kernel());
! 447: uvm_km_free(kernel_map, va, ptoa(npg));
! 448:
! 449: (void)extent_free(isabr->sc_io_extent, (u_long)iobase, size,
! 450: EX_MALLOCOK);
! 451: }
! 452:
! 453: /*
! 454: * Round down an I/O space bus_space_handle, so that it points to the
! 455: * beginning of a page.
! 456: * This is gonna be hell when we support ports above 0x400.
! 457: */
! 458: #define REALIGN_IO_HANDLE(h, o) \
! 459: do { \
! 460: u_int tmp; \
! 461: tmp = (h) & (ISABR_IOPORT_LINE - 1); \
! 462: (h) -= tmp; \
! 463: (o) += tmp; \
! 464: } while (0)
! 465:
! 466: /* ARGSUSED */
! 467: int
! 468: hp300_isa_io_subregion(bus_space_handle_t bsh, bus_size_t offset,
! 469: bus_size_t size, bus_space_handle_t *nbshp)
! 470: {
! 471: REALIGN_IO_HANDLE(bsh, offset);
! 472: bsh += ISAADDR(offset);
! 473: *nbshp = bsh;
! 474: return (0);
! 475: }
! 476:
! 477: void *
! 478: hp300_isa_io_vaddr(bus_space_handle_t h)
! 479: {
! 480: return (NULL);
! 481: }
! 482:
! 483: /* bus_space_read_X */
! 484:
! 485: u_int8_t
! 486: hp300_isa_io_bsr1(bus_space_handle_t bsh, bus_size_t offset)
! 487: {
! 488: vaddr_t va;
! 489: u_int8_t rc;
! 490:
! 491: REALIGN_IO_HANDLE(bsh, offset);
! 492: va = (vaddr_t)bsh + ISAADDR(offset);
! 493: rc = *(volatile u_int8_t *)va;
! 494: #ifdef DEBUG
! 495: printf("R%03x(%x):%02x\t", offset, va, rc);
! 496: #endif
! 497: return (rc);
! 498: }
! 499:
! 500: u_int16_t
! 501: __hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
! 502: {
! 503: u_int16_t rc;
! 504: vaddr_t va;
! 505:
! 506: if (offset & 1) {
! 507: rc = hp300_isa_io_bsr1(bsh, offset + 1) << 8;
! 508: rc |= hp300_isa_io_bsr1(bsh, offset);
! 509: } else {
! 510: REALIGN_IO_HANDLE(bsh, offset);
! 511: va = (vaddr_t)bsh + ISAADDR(offset);
! 512: rc = *(volatile u_int16_t *)va;
! 513: }
! 514: #ifdef DEBUG
! 515: printf("R%03x:%04x\t", offset, rc);
! 516: #endif
! 517: return (rc);
! 518: }
! 519:
! 520: u_int16_t
! 521: hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
! 522: {
! 523: u_int16_t rc;
! 524:
! 525: rc = __hp300_isa_io_bsr2(bsh, offset);
! 526: return (letoh16(rc));
! 527: }
! 528:
! 529: u_int32_t
! 530: __hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
! 531: {
! 532: u_int32_t rc;
! 533: vaddr_t va;
! 534:
! 535: if (offset & 3) {
! 536: rc = hp300_isa_io_bsr1(bsh, offset + 3) << 24;
! 537: rc |= hp300_isa_io_bsr1(bsh, offset + 2) << 16;
! 538: rc |= hp300_isa_io_bsr1(bsh, offset + 1) << 8;
! 539: rc |= hp300_isa_io_bsr1(bsh, offset);
! 540: } else {
! 541: REALIGN_IO_HANDLE(bsh, offset);
! 542: va = (vaddr_t)bsh + ISAADDR(offset);
! 543: rc = *(volatile u_int32_t *)va;
! 544: }
! 545: #ifdef DEBUG
! 546: printf("R%03x:%08x\t", offset, rc);
! 547: #endif
! 548: return (rc);
! 549: }
! 550:
! 551: u_int32_t
! 552: hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
! 553: {
! 554: u_int32_t rc;
! 555:
! 556: rc = __hp300_isa_io_bsr4(bsh, offset);
! 557: return (letoh32(rc));
! 558: }
! 559:
! 560: /* bus_space_read_multi_X */
! 561:
! 562: void
! 563: hp300_isa_io_bsrm1(bus_space_handle_t h, bus_size_t offset,
! 564: u_int8_t *a, size_t c)
! 565: {
! 566: while ((int)--c >= 0)
! 567: *a++ = hp300_isa_io_bsr1(h, offset);
! 568: }
! 569:
! 570: void
! 571: hp300_isa_io_bsrm2(bus_space_handle_t h, bus_size_t offset,
! 572: u_int16_t *a, size_t c)
! 573: {
! 574: while ((int)--c >= 0)
! 575: *a++ = hp300_isa_io_bsr2(h, offset);
! 576: }
! 577:
! 578: void
! 579: hp300_isa_io_bsrm4(bus_space_handle_t h, bus_size_t offset,
! 580: u_int32_t *a, size_t c)
! 581: {
! 582: while ((int)--c >= 0)
! 583: *a++ = hp300_isa_io_bsr4(h, offset);
! 584: }
! 585:
! 586: /* bus_space_read_raw_multi_X */
! 587:
! 588: void
! 589: hp300_isa_io_bsrrm2(bus_space_handle_t h, bus_size_t offset,
! 590: u_int8_t *a, size_t c)
! 591: {
! 592: while ((int)--c >= 0) {
! 593: *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
! 594: a += 2;
! 595: }
! 596: }
! 597:
! 598: void
! 599: hp300_isa_io_bsrrm4(bus_space_handle_t h, bus_size_t offset,
! 600: u_int8_t *a, size_t c)
! 601: {
! 602: while ((int)--c >= 0) {
! 603: *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
! 604: a += 4;
! 605: }
! 606: }
! 607:
! 608: /* bus_space_read_region_X */
! 609:
! 610: void
! 611: hp300_isa_io_bsrr1(bus_space_handle_t h, bus_size_t offset,
! 612: u_int8_t *a, size_t c)
! 613: {
! 614: while ((int)--c >= 0)
! 615: *a++ = hp300_isa_io_bsr1(h, offset++);
! 616: }
! 617:
! 618: void
! 619: hp300_isa_io_bsrr2(bus_space_handle_t h, bus_size_t offset,
! 620: u_int16_t *a, size_t c)
! 621: {
! 622: while ((int)--c >= 0) {
! 623: *a++ = hp300_isa_io_bsr2(h, offset);
! 624: offset += 2;
! 625: }
! 626: }
! 627:
! 628: void
! 629: hp300_isa_io_bsrr4(bus_space_handle_t h, bus_size_t offset,
! 630: u_int32_t *a, size_t c)
! 631: {
! 632: while ((int)--c >= 0) {
! 633: *a++ = hp300_isa_io_bsr4(h, offset);
! 634: offset += 4;
! 635: }
! 636: }
! 637:
! 638: /* bus_space_read_raw_region_X */
! 639:
! 640: void
! 641: hp300_isa_io_bsrrr2(bus_space_handle_t h, bus_size_t offset,
! 642: u_int8_t *a, size_t c)
! 643: {
! 644: c >>= 1;
! 645: while ((int)--c >= 0) {
! 646: *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
! 647: offset += 2;
! 648: a += 2;
! 649: }
! 650: }
! 651:
! 652: void
! 653: hp300_isa_io_bsrrr4(bus_space_handle_t h, bus_size_t offset,
! 654: u_int8_t *a, size_t c)
! 655: {
! 656: c >>= 2;
! 657: while ((int)--c >= 0) {
! 658: *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
! 659: offset += 4;
! 660: a += 4;
! 661: }
! 662: }
! 663:
! 664: /* bus_space_write_X */
! 665:
! 666: void
! 667: hp300_isa_io_bsw1(bus_space_handle_t h, bus_size_t offset, u_int8_t v)
! 668: {
! 669: vaddr_t va;
! 670:
! 671: REALIGN_IO_HANDLE(h, offset);
! 672: va = (vaddr_t)h + ISAADDR(offset);
! 673: *(volatile u_int8_t *)va = v;
! 674: #ifdef DEBUG
! 675: printf("W%03x:%02x\t", offset, v);
! 676: #endif
! 677: }
! 678:
! 679: void
! 680: __hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
! 681: {
! 682: vaddr_t va;
! 683:
! 684: if (offset & 1) {
! 685: hp300_isa_io_bsw1(h, offset + 1, v >> 8);
! 686: hp300_isa_io_bsw1(h, offset, v);
! 687: } else {
! 688: REALIGN_IO_HANDLE(h, offset);
! 689: va = (vaddr_t)h + ISAADDR(offset);
! 690: *(volatile u_int16_t *)va = v;
! 691: }
! 692: #ifdef DEBUG
! 693: printf("W%03x:%04x\t", offset, v);
! 694: #endif
! 695: }
! 696:
! 697: void
! 698: hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
! 699: {
! 700: __hp300_isa_io_bsw2(h, offset, htole16(v));
! 701: }
! 702:
! 703: void
! 704: __hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
! 705: {
! 706: vaddr_t va;
! 707:
! 708: if (offset & 3) {
! 709: hp300_isa_io_bsw1(h, offset + 3, v >> 24);
! 710: hp300_isa_io_bsw1(h, offset + 2, v >> 16);
! 711: hp300_isa_io_bsw1(h, offset + 1, v >> 8);
! 712: hp300_isa_io_bsw1(h, offset, v);
! 713: } else {
! 714: REALIGN_IO_HANDLE(h, offset);
! 715: va = (vaddr_t)h + ISAADDR(offset);
! 716: *(volatile u_int32_t *)va = v;
! 717: }
! 718: #ifdef DEBUG
! 719: printf("W%03x:%08x\t", offset, v);
! 720: #endif
! 721: }
! 722:
! 723: void
! 724: hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
! 725: {
! 726: __hp300_isa_io_bsw4(h, offset, htole32(v));
! 727: }
! 728:
! 729: /* bus_space_write_multi_X */
! 730:
! 731: void
! 732: hp300_isa_io_bswm1(bus_space_handle_t h, bus_size_t offset,
! 733: const u_int8_t *a, size_t c)
! 734: {
! 735: while ((int)--c >= 0)
! 736: hp300_isa_io_bsw1(h, offset, *a++);
! 737: }
! 738:
! 739: void
! 740: hp300_isa_io_bswm2(bus_space_handle_t h, bus_size_t offset,
! 741: const u_int16_t *a, size_t c)
! 742: {
! 743: while ((int)--c >= 0)
! 744: hp300_isa_io_bsw2(h, offset, *a++);
! 745: }
! 746:
! 747: void
! 748: hp300_isa_io_bswm4(bus_space_handle_t h, bus_size_t offset,
! 749: const u_int32_t *a, size_t c)
! 750: {
! 751: while ((int)--c >= 0)
! 752: hp300_isa_io_bsw4(h, offset, *a++);
! 753: }
! 754:
! 755: /* bus_space_write_raw_multi_X */
! 756:
! 757: void
! 758: hp300_isa_io_bswrm2(bus_space_handle_t h, bus_size_t offset,
! 759: const u_int8_t *a, size_t c)
! 760: {
! 761: while ((int)--c >= 0) {
! 762: __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
! 763: a += 2;
! 764: }
! 765: }
! 766:
! 767: void
! 768: hp300_isa_io_bswrm4(bus_space_handle_t h, bus_size_t offset,
! 769: const u_int8_t *a, size_t c)
! 770: {
! 771: while ((int)--c >= 0) {
! 772: __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
! 773: a += 4;
! 774: }
! 775: }
! 776:
! 777: /* bus_space_write_region_X */
! 778:
! 779: void
! 780: hp300_isa_io_bswr1(bus_space_handle_t h, bus_size_t offset,
! 781: const u_int8_t *a, size_t c)
! 782: {
! 783: while ((int)--c >= 0)
! 784: hp300_isa_io_bsw1(h, offset++, *a++);
! 785: }
! 786:
! 787: void
! 788: hp300_isa_io_bswr2(bus_space_handle_t h, bus_size_t offset,
! 789: const u_int16_t *a, size_t c)
! 790: {
! 791: while ((int)--c >= 0) {
! 792: hp300_isa_io_bsw2(h, offset, *a++);
! 793: offset += 2;
! 794: }
! 795: }
! 796:
! 797: void
! 798: hp300_isa_io_bswr4(bus_space_handle_t h, bus_size_t offset,
! 799: const u_int32_t *a, size_t c)
! 800: {
! 801: while ((int)--c >= 0) {
! 802: hp300_isa_io_bsw4(h, offset, *a++);
! 803: offset += 4;
! 804: }
! 805: }
! 806:
! 807: /* bus_space_write_raw_region_X */
! 808:
! 809: void
! 810: hp300_isa_io_bswrr2(bus_space_handle_t h, bus_size_t offset,
! 811: const u_int8_t *a, size_t c)
! 812: {
! 813: c >>= 1;
! 814: while ((int)--c >= 0) {
! 815: __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
! 816: offset += 2;
! 817: a += 2;
! 818: }
! 819: }
! 820:
! 821: void
! 822: hp300_isa_io_bswrr4(bus_space_handle_t h, bus_size_t offset,
! 823: const u_int8_t *a, size_t c)
! 824: {
! 825: c >>= 2;
! 826: while ((int)--c >= 0) {
! 827: __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
! 828: offset += 4;
! 829: a += 4;
! 830: }
! 831: }
! 832:
! 833: /* bus_space_set_multi_X */
! 834:
! 835: void
! 836: hp300_isa_io_bssm1(bus_space_handle_t h, bus_size_t offset,
! 837: u_int8_t v, size_t c)
! 838: {
! 839: while ((int)--c >= 0)
! 840: hp300_isa_io_bsw1(h, offset, v);
! 841: }
! 842:
! 843: void
! 844: hp300_isa_io_bssm2(bus_space_handle_t h, bus_size_t offset,
! 845: u_int16_t v, size_t c)
! 846: {
! 847: while ((int)--c >= 0)
! 848: hp300_isa_io_bsw2(h, offset, v);
! 849: }
! 850:
! 851: void
! 852: hp300_isa_io_bssm4(bus_space_handle_t h, bus_size_t offset,
! 853: u_int32_t v, size_t c)
! 854: {
! 855: while ((int)--c >= 0)
! 856: hp300_isa_io_bsw4(h, offset, v);
! 857: }
! 858:
! 859: /* bus_space_set_region_X */
! 860:
! 861: void
! 862: hp300_isa_io_bssr1(bus_space_handle_t h, bus_size_t offset,
! 863: u_int8_t v, size_t c)
! 864: {
! 865: while ((int)--c >= 0)
! 866: hp300_isa_io_bsw1(h, offset++, v);
! 867: }
! 868:
! 869: void
! 870: hp300_isa_io_bssr2(bus_space_handle_t h, bus_size_t offset,
! 871: u_int16_t v, size_t c)
! 872: {
! 873: while ((int)--c >= 0) {
! 874: hp300_isa_io_bsw2(h, offset, v);
! 875: offset += 2;
! 876: }
! 877: }
! 878:
! 879: void
! 880: hp300_isa_io_bssr4(bus_space_handle_t h, bus_size_t offset,
! 881: u_int32_t v, size_t c)
! 882: {
! 883: while ((int)--c >= 0) {
! 884: hp300_isa_io_bsw4(h, offset, v);
! 885: offset += 4;
! 886: }
! 887: }
! 888:
! 889: /*
! 890: * ISA memory space
! 891: */
! 892:
! 893: int hp300_isa_mem_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
! 894: void hp300_isa_mem_unmap(bus_space_handle_t, bus_size_t);
! 895:
! 896: int
! 897: hp300_isa_mem_map(bus_addr_t bpa, bus_size_t size, int flags,
! 898: bus_space_handle_t *bshp)
! 899: {
! 900: int error;
! 901: bus_addr_t membase;
! 902: bus_size_t rsize;
! 903: vaddr_t va;
! 904: paddr_t pa;
! 905: pt_entry_t template;
! 906:
! 907: /*
! 908: * Reserve the range in the allocation extent.
! 909: */
! 910: if (bpa < IOM_BEGIN || bpa + size > IOM_END)
! 911: return (ERANGE);
! 912: error = extent_alloc_region(isabr->sc_mem_extent, bpa, size,
! 913: EX_MALLOCOK);
! 914: if (error != 0)
! 915: return (error);
! 916:
! 917: /*
! 918: * Allocate virtual address space to map this space in.
! 919: */
! 920: membase = trunc_page(bpa);
! 921: rsize = round_page(bpa + size) - membase;
! 922: va = uvm_km_valloc(kernel_map, rsize);
! 923: if (va == 0) {
! 924: extent_free(isabr->sc_mem_extent, bpa, size, EX_MALLOCOK);
! 925: return (ENOMEM);
! 926: }
! 927:
! 928: *bshp = (bus_space_handle_t)(va + (bpa - membase));
! 929:
! 930: pa = membase + (ISABR_IOMEM_BASE - IOM_BEGIN);
! 931:
! 932: if (flags & BUS_SPACE_MAP_CACHEABLE)
! 933: template = PG_RW;
! 934: else
! 935: template = PG_RW | PG_CI;
! 936:
! 937: while (rsize != 0) {
! 938: pmap_kenter_cache(va, pa, template);
! 939: rsize -= PAGE_SIZE;
! 940: va += PAGE_SIZE;
! 941: pa += PAGE_SIZE;
! 942: }
! 943: pmap_update(pmap_kernel());
! 944:
! 945: return (0);
! 946: }
! 947:
! 948: void
! 949: hp300_isa_mem_unmap(bus_space_handle_t bsh, bus_size_t size)
! 950: {
! 951: vaddr_t va;
! 952: vsize_t rsize;
! 953:
! 954: va = trunc_page((vaddr_t)bsh);
! 955: rsize = round_page((vaddr_t)bsh + size) - va;
! 956:
! 957: pmap_kremove(va, rsize);
! 958: pmap_update(pmap_kernel());
! 959: uvm_km_free(kernel_map, va, rsize);
! 960:
! 961: (void)extent_free(isabr->sc_mem_extent, (u_long)bsh, size, EX_MALLOCOK);
! 962: }
! 963:
! 964: struct hp300_bus_space_tag hp300_isa_mem_tag; /* will be filled in */
! 965:
! 966: /*
! 967: * ISA bus_space initialization.
! 968: * This creates the necessary accounting elements and initializes the
! 969: * memory space bus_space_tag.
! 970: */
! 971:
! 972: int
! 973: isabr_bus_space_setup(struct isabr_softc *sc, struct frodo_attach_args *faa,
! 974: struct isabus_attach_args *iba)
! 975: {
! 976: /*
! 977: * Create the space extents.
! 978: * We only use them to prevent multiple allocations of the same areas.
! 979: */
! 980:
! 981: sc->sc_io_extent = extent_create("isa_io", IO_ISABEGIN,
! 982: IO_ISAEND + 1, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
! 983: if (sc->sc_io_extent == NULL)
! 984: return (ENOMEM);
! 985:
! 986: sc->sc_mem_extent = extent_create("isa_mem", IOM_BEGIN,
! 987: IOM_END, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
! 988: if (sc->sc_mem_extent == NULL) {
! 989: extent_destroy(sc->sc_io_extent);
! 990: return (ENOMEM);
! 991: }
! 992:
! 993: iba->iba_iot = &hp300_isa_io_tag;
! 994: bcopy(faa->fa_tag, &hp300_isa_mem_tag,
! 995: sizeof(struct hp300_bus_space_tag));
! 996: hp300_isa_mem_tag.bs_map = hp300_isa_mem_map;
! 997: hp300_isa_mem_tag.bs_unmap = hp300_isa_mem_unmap;
! 998: iba->iba_memt = &hp300_isa_mem_tag;
! 999:
! 1000: isabr = sc;
! 1001:
! 1002: return (0);
! 1003: }
CVSweb