Annotation of sys/arch/mvme88k/dev/mainbus.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mainbus.c,v 1.22 2007/02/11 12:41:29 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 1998 Steve Murphree, Jr.
! 4: * Copyright (c) 2004, Miodrag Vallat.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: * 1. Redistributions of source code must retain the above copyright
! 10: * notice, this list of conditions and the following disclaimer.
! 11: * 2. Redistributions in binary form must reproduce the above copyright
! 12: * notice, this list of conditions and the following disclaimer in the
! 13: * documentation and/or other materials provided with the distribution.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 16: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 18: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 19: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 20: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 21: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 23: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 24: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 25: * POSSIBILITY OF SUCH DAMAGE.
! 26: */
! 27:
! 28: #include <sys/param.h>
! 29: #include <sys/systm.h>
! 30: #include <sys/reboot.h>
! 31: #include <sys/conf.h>
! 32: #include <sys/device.h>
! 33: #include <sys/disklabel.h>
! 34: #include <sys/extent.h>
! 35: #include <sys/malloc.h>
! 36:
! 37: #include <uvm/uvm_extern.h>
! 38:
! 39: #include <machine/bus.h>
! 40: #include <machine/autoconf.h>
! 41: #include <machine/cmmu.h>
! 42: #include <machine/cpu.h>
! 43:
! 44: #ifdef M88100
! 45: #include <machine/m8820x.h>
! 46: #endif
! 47: #ifdef MVME187
! 48: #include <machine/mvme187.h>
! 49: #endif
! 50: #ifdef MVME188
! 51: #include <machine/mvme188.h>
! 52: #endif
! 53: #ifdef MVME197
! 54: #include <machine/mvme197.h>
! 55: #endif
! 56:
! 57: void mainbus_attach(struct device *, struct device *, void *);
! 58: int mainbus_match(struct device *, void *, void *);
! 59: int mainbus_print(void *, const char *);
! 60: int mainbus_scan(struct device *, void *, void *);
! 61:
! 62: /*
! 63: * bus_space routines for 1:1 obio mappings
! 64: */
! 65:
! 66: int mainbus_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
! 67: void mainbus_unmap(bus_space_handle_t, bus_size_t);
! 68: int mainbus_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
! 69: bus_space_handle_t *);
! 70: void *mainbus_vaddr(bus_space_handle_t);
! 71:
! 72: const struct mvme88k_bus_space_tag mainbus_bustag = {
! 73: mainbus_map,
! 74: mainbus_unmap,
! 75: mainbus_subregion,
! 76: mainbus_vaddr
! 77: };
! 78:
! 79: bus_addr_t bs_obio_start;
! 80: bus_addr_t bs_obio_end;
! 81: struct extent *bs_extent;
! 82:
! 83: /*
! 84: * Obio (internal IO) space is mapped 1:1 (see pmap_bootstrap() for details).
! 85: *
! 86: * However, sram attaches as a child of mainbus, but does not reside in
! 87: * internal IO space. As a result, we have to allow both 1:1 and regular
! 88: * translations, depending upon the address to map.
! 89: */
! 90:
! 91: int
! 92: mainbus_map(bus_addr_t addr, bus_size_t size, int flags,
! 93: bus_space_handle_t *ret)
! 94: {
! 95: vaddr_t map;
! 96:
! 97: map = mapiodev((paddr_t)addr, size);
! 98: if (map == NULL)
! 99: return ENOMEM;
! 100:
! 101: *ret = (bus_space_handle_t)map;
! 102: return 0;
! 103: }
! 104:
! 105: void
! 106: mainbus_unmap(bus_space_handle_t handle, bus_size_t size)
! 107: {
! 108: /* XXX what to do for non-obio mappings? */
! 109: }
! 110:
! 111: int
! 112: mainbus_subregion(bus_space_handle_t handle, bus_addr_t offset,
! 113: bus_size_t size, bus_space_handle_t *ret)
! 114: {
! 115: *ret = handle + offset;
! 116: return (0);
! 117: }
! 118:
! 119: void *
! 120: mainbus_vaddr(bus_space_handle_t handle)
! 121: {
! 122: return (void *)handle;
! 123: }
! 124:
! 125: /*
! 126: * Map a range [pa, pa+size) in the given map to a kernel address
! 127: * in iomap space.
! 128: *
! 129: * Note: To be flexible, I did not put a restriction on the alignment
! 130: * of pa. However, it is advisable to have pa page aligned since otherwise,
! 131: * we might have several mappings for a given chunk of the IO page.
! 132: */
! 133: vaddr_t
! 134: mapiodev(paddr_t addr, int _size)
! 135: {
! 136: vaddr_t va, iova, off;
! 137: paddr_t pa, epa;
! 138: psize_t size;
! 139: int s, error;
! 140:
! 141: /* sanity checks */
! 142: if (_size <= 0)
! 143: return NULL;
! 144: size = (psize_t)_size;
! 145: epa = addr + size;
! 146: if (epa < addr && epa != 0)
! 147: return NULL;
! 148:
! 149: /* check for 1:1 mapping */
! 150: if (addr >= bs_obio_start) {
! 151: if (bs_obio_end == 0 || epa <= bs_obio_end)
! 152: return ((vaddr_t)addr);
! 153: else if (addr <= bs_obio_end)
! 154: /* accross obio and non-obio, not supported */
! 155: return NULL;
! 156: }
! 157:
! 158: pa = trunc_page(addr);
! 159: off = addr & PGOFSET;
! 160: size = round_page(off + size);
! 161:
! 162: s = splhigh();
! 163: error = extent_alloc_region(bs_extent, atop(pa), atop(size),
! 164: EX_MALLOCOK | (cold ? 0 : EX_WAITSPACE));
! 165: splx(s);
! 166:
! 167: if (error != 0)
! 168: return NULL;
! 169:
! 170: va = uvm_km_valloc(kernel_map, size);
! 171: if (va == 0) {
! 172: extent_free(bs_extent, atop(pa), atop(size),
! 173: EX_MALLOCOK | (cold ? 0 : EX_WAITSPACE));
! 174: return NULL;
! 175: }
! 176:
! 177: iova = va + off;
! 178: while (size != 0) {
! 179: pmap_enter(pmap_kernel(), va, pa, UVM_PROT_RW,
! 180: UVM_PROT_RW | PMAP_WIRED);
! 181: size -= PAGE_SIZE;
! 182: va += PAGE_SIZE;
! 183: pa += PAGE_SIZE;
! 184: }
! 185: pmap_update(pmap_kernel());
! 186:
! 187: return (iova);
! 188: }
! 189:
! 190: /*
! 191: * Free up the mapping in iomap.
! 192: */
! 193: void
! 194: unmapiodev(vaddr_t va, int _size)
! 195: {
! 196: vaddr_t eva, kva, off;
! 197: vsize_t size;
! 198: paddr_t pa;
! 199: int s, error;
! 200:
! 201: /* sanity checks */
! 202: if (_size <= 0)
! 203: return;
! 204: size = (vsize_t)_size;
! 205: eva = va + size;
! 206: if (eva < va && eva != 0)
! 207: return;
! 208:
! 209: /* check for 1:1 mapping */
! 210: if (va >= bs_obio_start) {
! 211: if (bs_obio_end == 0 || eva <= bs_obio_end)
! 212: return;
! 213: else if (va <= bs_obio_end)
! 214: /* accross obio and non-obio, not supported */
! 215: return;
! 216: }
! 217:
! 218: off = va & PGOFSET;
! 219: kva = trunc_page(va);
! 220: size = round_page(off + size);
! 221:
! 222: if (pmap_extract(pmap_kernel(), kva, &pa) == FALSE)
! 223: panic("unmapiodev(%p,%p)", kva, size);
! 224:
! 225: pmap_remove(pmap_kernel(), kva, kva + size);
! 226: pmap_update(pmap_kernel());
! 227: uvm_km_free(kernel_map, kva, size);
! 228:
! 229: s = splhigh();
! 230: error = extent_free(bs_extent, atop(pa), atop(size),
! 231: EX_MALLOCOK | (cold ? 0 : EX_WAITSPACE));
! 232: #ifdef DIAGNOSTIC
! 233: if (error != 0)
! 234: printf("unmapiodev(%p pa %p, %p): extent_free failed\n",
! 235: kva, pa, size);
! 236: #endif
! 237: splx(s);
! 238: }
! 239:
! 240: /*
! 241: * Configuration glue
! 242: */
! 243:
! 244: struct cfattach mainbus_ca = {
! 245: sizeof(struct device), mainbus_match, mainbus_attach
! 246: };
! 247:
! 248: struct cfdriver mainbus_cd = {
! 249: NULL, "mainbus", DV_DULL
! 250: };
! 251:
! 252: int
! 253: mainbus_match(struct device *parent, void *cf, void *args)
! 254: {
! 255: return (1);
! 256: }
! 257:
! 258: int
! 259: mainbus_print(void *args, const char *bus)
! 260: {
! 261: struct confargs *ca = args;
! 262:
! 263: if (ca->ca_paddr != -1)
! 264: printf(" addr 0x%x", ca->ca_paddr);
! 265: return (UNCONF);
! 266: }
! 267:
! 268: int
! 269: mainbus_scan(struct device *parent, void *child, void *args)
! 270: {
! 271: struct cfdata *cf = child;
! 272: struct confargs oca;
! 273:
! 274: bzero(&oca, sizeof oca);
! 275: oca.ca_iot = &mainbus_bustag;
! 276: oca.ca_dmat = 0; /* XXX no need for a meaningful value yet */
! 277: oca.ca_bustype = BUS_MAIN;
! 278: oca.ca_paddr = cf->cf_loc[0];
! 279: oca.ca_ipl = -1;
! 280: oca.ca_name = cf->cf_driver->cd_name;
! 281: if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0)
! 282: return (0);
! 283: config_attach(parent, cf, &oca, mainbus_print);
! 284: return (1);
! 285: }
! 286:
! 287: void
! 288: mainbus_attach(struct device *parent, struct device *self, void *args)
! 289: {
! 290: extern char cpu_model[];
! 291:
! 292: printf(": %s\n", cpu_model);
! 293:
! 294: /*
! 295: * Display cpu/mmu details for the main processor.
! 296: */
! 297: cpu_configuration_print(1);
! 298:
! 299: /*
! 300: * Initialize an extent to keep track of I/O mappings.
! 301: */
! 302: #ifdef M88100
! 303: if (CPU_IS88100) {
! 304: bs_obio_start = BATC8_VA; /* hardwired BATC */
! 305: bs_obio_end = 0;
! 306: }
! 307: #endif
! 308: #ifdef MVME197
! 309: if (CPU_IS88110) {
! 310: bs_obio_start = OBIO197_START;
! 311: bs_obio_end = OBIO197_START + OBIO197_SIZE;
! 312: }
! 313: #endif
! 314: bs_extent = extent_create("bus_space", atop(physmem),
! 315: 1 + atop(0U - PAGE_SIZE), M_DEVBUF, NULL, 0, EX_NOWAIT);
! 316: if (bs_extent == NULL)
! 317: panic("unable to allocate bus_space extent");
! 318:
! 319: (void)config_search(mainbus_scan, self, args);
! 320: }
CVSweb