Annotation of sys/dev/cardbus/cardbus_map.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: cardbus_map.c,v 1.7 2006/07/31 11:06:27 mickey Exp $ */
! 2: /* $NetBSD: cardbus_map.c,v 1.10 2000/03/07 00:31:46 mycroft Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1999 and 2000
! 6: * HAYAKAWA Koichi. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. All advertising materials mentioning features or use of this software
! 17: * must display the following acknowledgement:
! 18: * This product includes software developed by HAYAKAWA Koichi.
! 19: * 4. The name of the author may not be used to endorse or promote products
! 20: * derived from this software without specific prior written permission.
! 21: *
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 33: * POSSIBILITY OF SUCH DAMAGE.
! 34: */
! 35:
! 36:
! 37: #include <sys/param.h>
! 38: #include <sys/systm.h>
! 39: #include <sys/device.h>
! 40:
! 41: #include <machine/bus.h>
! 42:
! 43: #include <dev/cardbus/cardbusvar.h>
! 44:
! 45: #include <dev/pci/pcireg.h> /* XXX */
! 46:
! 47: #if defined DEBUG && !defined CARDBUS_MAP_DEBUG
! 48: #define CARDBUS_MAP_DEBUG
! 49: #endif
! 50:
! 51: #if defined CARDBUS_MAP_DEBUG
! 52: #define STATIC
! 53: #define DPRINTF(a) printf a
! 54: #else
! 55: #define STATIC static
! 56: #define DPRINTF(a)
! 57: #endif
! 58:
! 59:
! 60: static int cardbus_io_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
! 61: cardbustag_t, int, cardbusreg_t, bus_addr_t *, bus_size_t *,
! 62: int *);
! 63: static int cardbus_mem_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
! 64: cardbustag_t, int, cardbusreg_t, bus_addr_t *, bus_size_t *,
! 65: int *);
! 66:
! 67: int
! 68: cardbus_mapreg_probe(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
! 69: cardbustag_t tag, int reg, pcireg_t *typep)
! 70: {
! 71: pcireg_t address, mask;
! 72: int s;
! 73:
! 74: s = splhigh();
! 75: address = cardbus_conf_read(cc, cf, tag, reg);
! 76: cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
! 77: mask = cardbus_conf_read(cc, cf, tag, reg);
! 78: cardbus_conf_write(cc, cf, tag, reg, address);
! 79: splx(s);
! 80:
! 81: if (mask == 0) /* unimplemented mapping register */
! 82: return (0);
! 83:
! 84: if (typep)
! 85: *typep = _PCI_MAPREG_TYPEBITS(address);
! 86: return (1);
! 87: }
! 88:
! 89: /*
! 90: * static int cardbus_io_find(cardbus_chipset_tag_t cc,
! 91: * cardbus_function_tag_t cf, cardbustag_t tag,
! 92: * int reg, cardbusreg_t type, bus_addr_t *basep,
! 93: * bus_size_t *sizep, int *flagsp)
! 94: * This code is stolen from sys/dev/pci_map.c.
! 95: */
! 96: static int
! 97: cardbus_io_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
! 98: cardbustag_t tag, int reg, cardbusreg_t type, bus_addr_t *basep,
! 99: bus_size_t *sizep, int *flagsp)
! 100: {
! 101: cardbusreg_t address, mask;
! 102: int s;
! 103:
! 104: /* EXT ROM is able to map on memory space ONLY. */
! 105: if (reg == CARDBUS_ROM_REG)
! 106: return (1);
! 107:
! 108: if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
! 109: panic("cardbus_io_find: bad request");
! 110: }
! 111:
! 112: /*
! 113: * Section 6.2.5.1, `Address Maps', tells us that:
! 114: *
! 115: * 1) The builtin software should have already mapped the device in a
! 116: * reasonable way.
! 117: *
! 118: * 2) A device which wants 2^n bytes of memory will hardwire the bottom
! 119: * n bits of the address to 0. As recommended, we write all 1s and see
! 120: * what we get back.
! 121: */
! 122: s = splhigh();
! 123: address = cardbus_conf_read(cc, cf, tag, reg);
! 124: cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
! 125: mask = cardbus_conf_read(cc, cf, tag, reg);
! 126: cardbus_conf_write(cc, cf, tag, reg, address);
! 127: splx(s);
! 128:
! 129: if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
! 130: printf("cardbus_io_find: expected type i/o, found mem\n");
! 131: return (1);
! 132: }
! 133:
! 134: if (PCI_MAPREG_IO_SIZE(mask) == 0) {
! 135: printf("cardbus_io_find: void region\n");
! 136: return (1);
! 137: }
! 138:
! 139: if (basep != 0)
! 140: *basep = PCI_MAPREG_IO_ADDR(address);
! 141: if (sizep != 0)
! 142: *sizep = PCI_MAPREG_IO_SIZE(mask);
! 143: if (flagsp != 0)
! 144: *flagsp = 0;
! 145:
! 146: return (0);
! 147: }
! 148:
! 149: /*
! 150: * static int cardbus_mem_find(cardbus_chipset_tag_t cc,
! 151: * cardbus_function_tag_t cf, cardbustag_t tag,
! 152: * int reg, cardbusreg_t type, bus_addr_t *basep,
! 153: * bus_size_t *sizep, int *flagsp)
! 154: * This code is stolen from sys/dev/pci_map.c.
! 155: */
! 156: static int
! 157: cardbus_mem_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
! 158: cardbustag_t tag, int reg, cardbusreg_t type, bus_addr_t *basep,
! 159: bus_size_t *sizep, int *flagsp)
! 160: {
! 161: cardbusreg_t address, mask;
! 162: int s;
! 163:
! 164: if (reg != CARDBUS_ROM_REG &&
! 165: (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) {
! 166: panic("cardbus_mem_find: bad request");
! 167: }
! 168:
! 169: /*
! 170: * Section 6.2.5.1, `Address Maps', tells us that:
! 171: *
! 172: * 1) The builtin software should have already mapped the device in a
! 173: * reasonable way.
! 174: *
! 175: * 2) A device which wants 2^n bytes of memory will hardwire the bottom
! 176: * n bits of the address to 0. As recommended, we write all 1s and see
! 177: * what we get back.
! 178: */
! 179: s = splhigh();
! 180: address = cardbus_conf_read(cc, cf, tag, reg);
! 181: cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
! 182: mask = cardbus_conf_read(cc, cf, tag, reg);
! 183: cardbus_conf_write(cc, cf, tag, reg, address);
! 184: splx(s);
! 185:
! 186: if (reg != CARDBUS_ROM_REG) {
! 187: /* memory space BAR */
! 188:
! 189: if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
! 190: printf("cardbus_mem_find: expected type mem, "
! 191: "found i/o\n");
! 192: return (1);
! 193: }
! 194: if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
! 195: printf("cardbus_mem_find: expected mem type %08x, "
! 196: "found %08x\n", PCI_MAPREG_MEM_TYPE(type),
! 197: PCI_MAPREG_MEM_TYPE(address));
! 198: return (1);
! 199: }
! 200: }
! 201:
! 202: if (PCI_MAPREG_MEM_SIZE(mask) == 0) {
! 203: printf("cardbus_mem_find: void region\n");
! 204: return (1);
! 205: }
! 206:
! 207: switch (PCI_MAPREG_MEM_TYPE(address)) {
! 208: case PCI_MAPREG_MEM_TYPE_32BIT:
! 209: case PCI_MAPREG_MEM_TYPE_32BIT_1M:
! 210: break;
! 211: case PCI_MAPREG_MEM_TYPE_64BIT:
! 212: printf("cardbus_mem_find: 64-bit memory mapping register\n");
! 213: return (1);
! 214: default:
! 215: printf("cardbus_mem_find: reserved mapping register type\n");
! 216: return (1);
! 217: }
! 218:
! 219: if (basep != 0)
! 220: *basep = PCI_MAPREG_MEM_ADDR(address);
! 221: if (sizep != 0)
! 222: *sizep = PCI_MAPREG_MEM_SIZE(mask);
! 223: if (flagsp != 0) {
! 224: *flagsp =
! 225: #ifdef BUS_SPACE_MAP_PREFETCHABLE
! 226: PCI_MAPREG_MEM_PREFETCHABLE(address) ?
! 227: BUS_SPACE_MAP_PREFETCHABLE :
! 228: #endif
! 229: 0;
! 230: }
! 231:
! 232: return (0);
! 233: }
! 234:
! 235: /*
! 236: * int cardbus_mapreg_map(struct cardbus_softc *, int, int, cardbusreg_t,
! 237: * int bus_space_tag_t *, bus_space_handle_t *,
! 238: * bus_addr_t *, bus_size_t *)
! 239: * This function maps bus-space on the value of Base Address
! 240: * Register (BAR) indexed by the argument `reg' (the second argument).
! 241: * When the value of the BAR is not valid, such as 0x00000000, a new
! 242: * address should be allocated for the BAR and new address values is
! 243: * written on the BAR.
! 244: */
! 245: int
! 246: cardbus_mapreg_map(struct cardbus_softc *sc, int func, int reg,
! 247: cardbusreg_t type, int busflags, bus_space_tag_t *tagp,
! 248: bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
! 249: {
! 250: cardbus_chipset_tag_t cc = sc->sc_cc;
! 251: cardbus_function_tag_t cf = sc->sc_cf;
! 252: bus_space_tag_t bustag;
! 253: rbus_tag_t rbustag;
! 254: bus_space_handle_t handle;
! 255: bus_addr_t base;
! 256: bus_size_t size;
! 257: int flags;
! 258: int status = 0;
! 259:
! 260: cardbustag_t tag = cardbus_make_tag(cc, cf, sc->sc_bus,
! 261: sc->sc_device, func);
! 262:
! 263: DPRINTF(("cardbus_mapreg_map called: %s %x\n", sc->sc_dev.dv_xname,
! 264: type));
! 265:
! 266: if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
! 267: if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size,
! 268: &flags))
! 269: status = 1;
! 270: bustag = sc->sc_iot;
! 271: rbustag = sc->sc_rbus_iot;
! 272: } else {
! 273: if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size,
! 274: &flags))
! 275: status = 1;
! 276: bustag = sc->sc_memt;
! 277: rbustag = sc->sc_rbus_memt;
! 278: }
! 279: if (status == 0) {
! 280: bus_addr_t mask = size - 1;
! 281: if (base != 0)
! 282: mask = 0xffffffff;
! 283: if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask,
! 284: size, busflags | flags, &base, &handle)) {
! 285: panic("io alloc");
! 286: }
! 287: }
! 288: cardbus_conf_write(cc, cf, tag, reg, base);
! 289:
! 290: DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base));
! 291:
! 292: if (tagp != 0)
! 293: *tagp = bustag;
! 294: if (handlep != 0)
! 295: *handlep = handle;
! 296: if (basep != 0)
! 297: *basep = base;
! 298: if (sizep != 0)
! 299: *sizep = size;
! 300: cardbus_free_tag(cc, cf, tag);
! 301:
! 302: return (0);
! 303: }
! 304:
! 305: /*
! 306: * int cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
! 307: * bus_space_tag_t tag, bus_space_handle_t handle,
! 308: * bus_size_t size)
! 309: *
! 310: * This function releases bus-space region and close memory or io
! 311: * window on the bridge.
! 312: *
! 313: * Arguments:
! 314: * struct cardbus_softc *sc; the pointer to the device structure of cardbus.
! 315: * int func; the number of function on the device.
! 316: * int reg; the offset of BAR register.
! 317: */
! 318: int
! 319: cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
! 320: bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
! 321: {
! 322: cardbus_chipset_tag_t cc = sc->sc_cc;
! 323: cardbus_function_tag_t cf = sc->sc_cf;
! 324: int st = 1;
! 325: cardbustag_t cardbustag;
! 326: rbus_tag_t rbustag;
! 327:
! 328: if (sc->sc_iot == tag) {
! 329: /* bus space is io space */
! 330: DPRINTF(("%s: unmap i/o space\n", sc->sc_dev.dv_xname));
! 331: rbustag = sc->sc_rbus_iot;
! 332: } else if (sc->sc_memt == tag) {
! 333: /* bus space is memory space */
! 334: DPRINTF(("%s: unmap mem space\n", sc->sc_dev.dv_xname));
! 335: rbustag = sc->sc_rbus_memt;
! 336: } else
! 337: return (1);
! 338:
! 339: cardbustag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, func);
! 340:
! 341: cardbus_conf_write(cc, cf, cardbustag, reg, 0);
! 342:
! 343: (*cf->cardbus_space_free)(cc, rbustag, handle, size);
! 344:
! 345: cardbus_free_tag(cc, cf, cardbustag);
! 346:
! 347: return (st);
! 348: }
! 349:
! 350: /*
! 351: * int cardbus_save_bar(cardbus_devfunc_t);
! 352: *
! 353: * This function saves the Base Address Registers at the CardBus
! 354: * function denoted by the argument.
! 355: */
! 356: int
! 357: cardbus_save_bar(cardbus_devfunc_t ct)
! 358: {
! 359: cardbustag_t tag = Cardbus_make_tag(ct);
! 360: cardbus_chipset_tag_t cc = ct->ct_cc;
! 361: cardbus_function_tag_t cf = ct->ct_cf;
! 362:
! 363: ct->ct_bar[0] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE0_REG);
! 364: ct->ct_bar[1] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE1_REG);
! 365: ct->ct_bar[2] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE2_REG);
! 366: ct->ct_bar[3] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE3_REG);
! 367: ct->ct_bar[4] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE4_REG);
! 368: ct->ct_bar[5] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE5_REG);
! 369:
! 370: DPRINTF(("cardbus_save_bar: %x %x\n", ct->ct_bar[0], ct->ct_bar[1]));
! 371:
! 372: Cardbus_free_tag(ct, tag);
! 373:
! 374: return (0);
! 375: }
! 376:
! 377: /*
! 378: * int cardbus_restore_bar(cardbus_devfunc_t);
! 379: *
! 380: * This function saves the Base Address Registers at the CardBus
! 381: * function denoted by the argument.
! 382: */
! 383: int
! 384: cardbus_restore_bar(cardbus_devfunc_t ct)
! 385: {
! 386: cardbustag_t tag = Cardbus_make_tag(ct);
! 387: cardbus_chipset_tag_t cc = ct->ct_cc;
! 388: cardbus_function_tag_t cf = ct->ct_cf;
! 389:
! 390: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, ct->ct_bar[0]);
! 391: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, ct->ct_bar[1]);
! 392: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, ct->ct_bar[2]);
! 393: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, ct->ct_bar[3]);
! 394: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, ct->ct_bar[4]);
! 395: cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, ct->ct_bar[5]);
! 396:
! 397: Cardbus_free_tag(ct, tag);
! 398:
! 399: return (0);
! 400: }
CVSweb