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