1 /*- 2 * Copyright (c) 2002-2005 M Warner Losh. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * This software may be derived from NetBSD i82365.c and other files with 25 * the following copyright: 26 * 27 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. All advertising materials mentioning features or use of this software 38 * must display the following acknowledgement: 39 * This product includes software developed by Marc Horowitz. 40 * 4. The name of the author may not be used to endorse or promote products 41 * derived from this software without specific prior written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 44 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 46 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 47 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 48 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 52 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 #include <sys/cdefs.h> 56 __FBSDID("$FreeBSD$"); 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/condvar.h> 61 #include <sys/errno.h> 62 #include <sys/kernel.h> 63 #include <sys/malloc.h> 64 #include <sys/queue.h> 65 #include <sys/module.h> 66 #include <sys/lock.h> 67 #include <sys/mutex.h> 68 #include <sys/conf.h> 69 70 #include <sys/bus.h> 71 #include <machine/bus.h> 72 #include <sys/rman.h> 73 #include <machine/resource.h> 74 75 #include <dev/pccard/pccardreg.h> 76 #include <dev/pccard/pccardvar.h> 77 78 #include <dev/exca/excareg.h> 79 #include <dev/exca/excavar.h> 80 81 #ifdef EXCA_DEBUG 82 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args) 83 #define DPRINTF(fmt, args...) printf(fmt, ## args) 84 #else 85 #define DEVPRINTF(dev, fmt, args...) 86 #define DPRINTF(fmt, args...) 87 #endif 88 89 static const char *chip_names[] = 90 { 91 "CardBus socket", 92 "Intel i82365SL-A/B or clone", 93 "Intel i82365sl-DF step", 94 "VLSI chip", 95 "Cirrus Logic PD6710", 96 "Cirrus logic PD6722", 97 "Cirrus Logic PD6729", 98 "Vadem 365", 99 "Vadem 465", 100 "Vadem 468", 101 "Vadem 469", 102 "Ricoh RF5C296", 103 "Ricoh RF5C396", 104 "IBM clone", 105 "IBM KING PCMCIA Controller" 106 }; 107 108 static exca_getb_fn exca_mem_getb; 109 static exca_putb_fn exca_mem_putb; 110 static exca_getb_fn exca_io_getb; 111 static exca_putb_fn exca_io_putb; 112 113 /* memory */ 114 115 #define EXCA_MEMINFO(NUM) { \ 116 EXCA_SYSMEM_ADDR ## NUM ## _START_LSB, \ 117 EXCA_SYSMEM_ADDR ## NUM ## _START_MSB, \ 118 EXCA_SYSMEM_ADDR ## NUM ## _STOP_LSB, \ 119 EXCA_SYSMEM_ADDR ## NUM ## _STOP_MSB, \ 120 EXCA_SYSMEM_ADDR ## NUM ## _WIN, \ 121 EXCA_CARDMEM_ADDR ## NUM ## _LSB, \ 122 EXCA_CARDMEM_ADDR ## NUM ## _MSB, \ 123 EXCA_ADDRWIN_ENABLE_MEM ## NUM, \ 124 } 125 126 static struct mem_map_index_st { 127 int sysmem_start_lsb; 128 int sysmem_start_msb; 129 int sysmem_stop_lsb; 130 int sysmem_stop_msb; 131 int sysmem_win; 132 int cardmem_lsb; 133 int cardmem_msb; 134 int memenable; 135 } mem_map_index[] = { 136 EXCA_MEMINFO(0), 137 EXCA_MEMINFO(1), 138 EXCA_MEMINFO(2), 139 EXCA_MEMINFO(3), 140 EXCA_MEMINFO(4) 141 }; 142 #undef EXCA_MEMINFO 143 144 static uint8_t 145 exca_mem_getb(struct exca_softc *sc, int reg) 146 { 147 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg)); 148 } 149 150 static void 151 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val) 152 { 153 bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val); 154 } 155 156 static uint8_t 157 exca_io_getb(struct exca_softc *sc, int reg) 158 { 159 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 160 return (bus_space_read_1(sc->bst, sc->bsh, EXCA_REG_DATA)); 161 } 162 163 static void 164 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val) 165 { 166 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 167 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_DATA, val); 168 } 169 170 /* 171 * Helper function. This will map the requested memory slot. We setup the 172 * map before we call this function. This is used to initially force the 173 * mapping, as well as later restore the mapping after it has been destroyed 174 * in some fashion (due to a power event typically). 175 */ 176 static void 177 exca_do_mem_map(struct exca_softc *sc, int win) 178 { 179 struct mem_map_index_st *map; 180 struct pccard_mem_handle *mem; 181 uint32_t offset; 182 uint32_t mem16; 183 uint32_t attrmem; 184 185 map = &mem_map_index[win]; 186 mem = &sc->mem[win]; 187 mem16 = (mem->kind & PCCARD_MEM_16BIT) ? 188 EXCA_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT : 0; 189 attrmem = (mem->kind & PCCARD_MEM_ATTR) ? 190 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0; 191 offset = ((mem->cardaddr >> EXCA_CARDMEM_ADDRX_SHIFT) - 192 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT)) & 0x3fff; 193 exca_putb(sc, map->sysmem_start_lsb, 194 mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT); 195 exca_putb(sc, map->sysmem_start_msb, 196 ((mem->addr >> (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 197 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | mem16); 198 199 exca_putb(sc, map->sysmem_stop_lsb, 200 (mem->addr + mem->realsize - 1) >> EXCA_SYSMEM_ADDRX_SHIFT); 201 exca_putb(sc, map->sysmem_stop_msb, 202 (((mem->addr + mem->realsize - 1) >> 203 (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 204 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | 205 EXCA_SYSMEM_ADDRX_STOP_MSB_WAIT2); 206 exca_putb(sc, map->sysmem_win, mem->addr >> EXCA_MEMREG_WIN_SHIFT); 207 208 exca_putb(sc, map->cardmem_lsb, offset & 0xff); 209 exca_putb(sc, map->cardmem_msb, ((offset >> 8) & 210 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK) | attrmem); 211 212 #ifdef EXCA_DEBUG 213 if (mem->kind & PCCARD_MEM_ATTR) 214 printf("attribtue memory\n"); 215 else 216 printf("common memory\n"); 217 #endif 218 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->memenable | 219 EXCA_ADDRWIN_ENABLE_MEMCS16); 220 221 DELAY(100); 222 #ifdef EXCA_DEBUG 223 { 224 int r1, r2, r3, r4, r5, r6, r7; 225 r1 = exca_getb(sc, map->sysmem_start_msb); 226 r2 = exca_getb(sc, map->sysmem_start_lsb); 227 r3 = exca_getb(sc, map->sysmem_stop_msb); 228 r4 = exca_getb(sc, map->sysmem_stop_lsb); 229 r5 = exca_getb(sc, map->cardmem_msb); 230 r6 = exca_getb(sc, map->cardmem_lsb); 231 r7 = exca_getb(sc, map->sysmem_win); 232 printf("exca_do_mem_map win %d: %02x%02x %02x%02x " 233 "%02x%02x %02x (%08x+%06x.%06x*%06x)\n", 234 win, r1, r2, r3, r4, r5, r6, r7, 235 mem->addr, mem->size, mem->realsize, 236 mem->cardaddr); 237 } 238 #endif 239 } 240 241 /* 242 * public interface to map a resource. kind is the type of memory to 243 * map (either common or attribute). Memory created via this interface 244 * starts out at card address 0. Since the only way to set this is 245 * to set it on a struct resource after it has been mapped, we're safe 246 * in maping this assumption. Note that resources can be remapped using 247 * exca_do_mem_map so that's how the card address can be set later. 248 */ 249 int 250 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res) 251 { 252 int win; 253 254 for (win = 0; win < EXCA_MEM_WINS; win++) { 255 if ((sc->memalloc & (1 << win)) == 0) { 256 sc->memalloc |= (1 << win); 257 break; 258 } 259 } 260 if (win >= EXCA_MEM_WINS) 261 return (ENOSPC); 262 if (((rman_get_start(res) >> EXCA_MEMREG_WIN_SHIFT) & 0xff) != 0 && 263 (sc->flags & EXCA_HAS_MEMREG_WIN) == 0) { 264 device_printf(sc->dev, "Does not support mapping above 24M."); 265 return (EINVAL); 266 } 267 268 sc->mem[win].cardaddr = 0; 269 sc->mem[win].memt = rman_get_bustag(res); 270 sc->mem[win].memh = rman_get_bushandle(res); 271 sc->mem[win].addr = rman_get_start(res); 272 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1; 273 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1; 274 sc->mem[win].realsize = sc->mem[win].realsize - 275 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 276 sc->mem[win].kind = kind; 277 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n", 278 win, sc->mem[win].addr, sc->mem[win].size, sc->mem[win].cardaddr); 279 exca_do_mem_map(sc, win); 280 281 return (0); 282 } 283 284 /* 285 * Private helper function. This turns off a given memory map that is in 286 * use. We do this by just clearing the enable bit in the pcic. If we needed 287 * to make memory unmapping/mapping pairs faster, we would have to store 288 * more state information about the pcic and then use that to intelligently 289 * to the map/unmap. However, since we don't do that sort of thing often 290 * (generally just at configure time), it isn't a case worth optimizing. 291 */ 292 static void 293 exca_mem_unmap(struct exca_softc *sc, int window) 294 { 295 if (window < 0 || window >= EXCA_MEM_WINS) 296 panic("exca_mem_unmap: window out of range"); 297 298 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable); 299 sc->memalloc &= ~(1 << window); 300 } 301 302 /* 303 * Find the map that we're using to hold the resource. This works well 304 * so long as the client drivers don't do silly things like map the same 305 * area mutliple times, or map both common and attribute memory at the 306 * same time. This latter restriction is a bug. We likely should just 307 * store a pointer to the res in the mem[x] data structure. 308 */ 309 static int 310 exca_mem_findmap(struct exca_softc *sc, struct resource *res) 311 { 312 int win; 313 314 for (win = 0; win < EXCA_MEM_WINS; win++) { 315 if (sc->mem[win].memt == rman_get_bustag(res) && 316 sc->mem[win].addr == rman_get_start(res) && 317 sc->mem[win].size == rman_get_size(res)) 318 return (win); 319 } 320 return (-1); 321 } 322 323 /* 324 * Set the memory flag. This means that we are setting if the memory 325 * is coming from attribute memory or from common memory on the card. 326 * CIS entries are generally in attribute memory (although they can 327 * reside in common memory). Generally, this is the only use for attribute 328 * memory. However, some cards require their drivers to dance in both 329 * common and/or attribute memory and this interface (and setting the 330 * offset interface) exist for such cards. 331 */ 332 int 333 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags) 334 { 335 int win; 336 337 win = exca_mem_findmap(sc, res); 338 if (win < 0) { 339 device_printf(sc->dev, 340 "set_res_flags: specified resource not active\n"); 341 return (ENOENT); 342 } 343 344 switch (flags) 345 { 346 case PCCARD_A_MEM_ATTR: 347 sc->mem[win].kind |= PCCARD_MEM_ATTR; 348 break; 349 case PCCARD_A_MEM_COM: 350 sc->mem[win].kind &= ~PCCARD_MEM_ATTR; 351 break; 352 case PCCARD_A_MEM_16BIT: 353 sc->mem[win].kind |= PCCARD_MEM_16BIT; 354 break; 355 case PCCARD_A_MEM_8BIT: 356 sc->mem[win].kind &= ~PCCARD_MEM_16BIT; 357 break; 358 } 359 exca_do_mem_map(sc, win); 360 return (0); 361 } 362 363 /* 364 * Given a resource, go ahead and unmap it if we can find it in the 365 * resrouce list that's used. 366 */ 367 int 368 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res) 369 { 370 int win; 371 372 win = exca_mem_findmap(sc, res); 373 if (win < 0) 374 return (ENOENT); 375 exca_mem_unmap(sc, win); 376 return (0); 377 } 378 379 /* 380 * Set the offset of the memory. We use this for reading the CIS and 381 * frobbing the pccard's pccard registers (CCR, etc). Some drivers 382 * need to access arbitrary attribute and common memory during their 383 * initialization and operation. 384 */ 385 int 386 exca_mem_set_offset(struct exca_softc *sc, struct resource *res, 387 uint32_t cardaddr, uint32_t *deltap) 388 { 389 int win; 390 uint32_t delta; 391 392 win = exca_mem_findmap(sc, res); 393 if (win < 0) { 394 device_printf(sc->dev, 395 "set_memory_offset: specified resource not active\n"); 396 return (ENOENT); 397 } 398 sc->mem[win].cardaddr = cardaddr & ~(EXCA_MEM_PAGESIZE - 1); 399 delta = cardaddr % EXCA_MEM_PAGESIZE; 400 if (deltap) 401 *deltap = delta; 402 sc->mem[win].realsize = sc->mem[win].size + delta + 403 EXCA_MEM_PAGESIZE - 1; 404 sc->mem[win].realsize = sc->mem[win].realsize - 405 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 406 exca_do_mem_map(sc, win); 407 return (0); 408 } 409 410 411 /* I/O */ 412 413 #define EXCA_IOINFO(NUM) { \ 414 EXCA_IOADDR ## NUM ## _START_LSB, \ 415 EXCA_IOADDR ## NUM ## _START_MSB, \ 416 EXCA_IOADDR ## NUM ## _STOP_LSB, \ 417 EXCA_IOADDR ## NUM ## _STOP_MSB, \ 418 EXCA_ADDRWIN_ENABLE_IO ## NUM, \ 419 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \ 420 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \ 421 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \ 422 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \ 423 { \ 424 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \ 425 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \ 426 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \ 427 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \ 428 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \ 429 } \ 430 } 431 432 static struct io_map_index_st { 433 int start_lsb; 434 int start_msb; 435 int stop_lsb; 436 int stop_msb; 437 int ioenable; 438 int ioctlmask; 439 int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */ 440 } io_map_index[] = { 441 EXCA_IOINFO(0), 442 EXCA_IOINFO(1), 443 }; 444 #undef EXCA_IOINFO 445 446 static void 447 exca_do_io_map(struct exca_softc *sc, int win) 448 { 449 struct io_map_index_st *map; 450 451 struct pccard_io_handle *io; 452 453 map = &io_map_index[win]; 454 io = &sc->io[win]; 455 exca_putb(sc, map->start_lsb, io->addr & 0xff); 456 exca_putb(sc, map->start_msb, (io->addr >> 8) & 0xff); 457 458 exca_putb(sc, map->stop_lsb, (io->addr + io->size - 1) & 0xff); 459 exca_putb(sc, map->stop_msb, ((io->addr + io->size - 1) >> 8) & 0xff); 460 461 exca_clrb(sc, EXCA_IOCTL, map->ioctlmask); 462 exca_setb(sc, EXCA_IOCTL, map->ioctlbits[io->width]); 463 464 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->ioenable); 465 #ifdef EXCA_DEBUG 466 { 467 int r1, r2, r3, r4; 468 r1 = exca_getb(sc, map->start_msb); 469 r2 = exca_getb(sc, map->start_lsb); 470 r3 = exca_getb(sc, map->stop_msb); 471 r4 = exca_getb(sc, map->stop_lsb); 472 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x " 473 "(%08x+%08x)\n", win, r1, r2, r3, r4, 474 io->addr, io->size); 475 } 476 #endif 477 } 478 479 int 480 exca_io_map(struct exca_softc *sc, int width, struct resource *r) 481 { 482 int win; 483 #ifdef EXCA_DEBUG 484 static char *width_names[] = { "auto", "io8", "io16"}; 485 #endif 486 for (win=0; win < EXCA_IO_WINS; win++) { 487 if ((sc->ioalloc & (1 << win)) == 0) { 488 sc->ioalloc |= (1 << win); 489 break; 490 } 491 } 492 if (win >= EXCA_IO_WINS) 493 return (ENOSPC); 494 495 sc->io[win].iot = rman_get_bustag(r); 496 sc->io[win].ioh = rman_get_bushandle(r); 497 sc->io[win].addr = rman_get_start(r); 498 sc->io[win].size = rman_get_end(r) - sc->io[win].addr + 1; 499 sc->io[win].flags = 0; 500 sc->io[win].width = width; 501 DPRINTF("exca_io_map window %d %s port %x+%x\n", 502 win, width_names[width], sc->io[win].addr, 503 sc->io[win].size); 504 exca_do_io_map(sc, win); 505 506 return (0); 507 } 508 509 static void 510 exca_io_unmap(struct exca_softc *sc, int window) 511 { 512 if (window >= EXCA_IO_WINS) 513 panic("exca_io_unmap: window out of range"); 514 515 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, io_map_index[window].ioenable); 516 517 sc->ioalloc &= ~(1 << window); 518 519 sc->io[window].iot = 0; 520 sc->io[window].ioh = 0; 521 sc->io[window].addr = 0; 522 sc->io[window].size = 0; 523 sc->io[window].flags = 0; 524 sc->io[window].width = 0; 525 } 526 527 static int 528 exca_io_findmap(struct exca_softc *sc, struct resource *res) 529 { 530 int win; 531 532 for (win = 0; win < EXCA_IO_WINS; win++) { 533 if (sc->io[win].iot == rman_get_bustag(res) && 534 sc->io[win].addr == rman_get_start(res) && 535 sc->io[win].size == rman_get_size(res)) 536 return (win); 537 } 538 return (-1); 539 } 540 541 542 int 543 exca_io_unmap_res(struct exca_softc *sc, struct resource *res) 544 { 545 int win; 546 547 win = exca_io_findmap(sc, res); 548 if (win < 0) 549 return (ENOENT); 550 exca_io_unmap(sc, win); 551 return (0); 552 } 553 554 /* Misc */ 555 556 /* 557 * If interrupts are enabled, then we should be able to just wait for 558 * an interrupt routine to wake us up. Busy waiting shouldn't be 559 * necessary. Sadly, not all legacy ISA cards support an interrupt 560 * for the busy state transitions, at least according to their datasheets, 561 * so we busy wait a while here.. 562 */ 563 static void 564 exca_wait_ready(struct exca_softc *sc) 565 { 566 int i; 567 DEVPRINTF(sc->dev, "exca_wait_ready: status 0x%02x\n", 568 exca_getb(sc, EXCA_IF_STATUS)); 569 for (i = 0; i < 10000; i++) { 570 if (exca_getb(sc, EXCA_IF_STATUS) & EXCA_IF_STATUS_READY) 571 return; 572 DELAY(500); 573 } 574 device_printf(sc->dev, "ready never happened, status = %02x\n", 575 exca_getb(sc, EXCA_IF_STATUS)); 576 } 577 578 /* 579 * Reset the card. Ideally, we'd do a lot of this via interrupts. 580 * However, many PC Cards will deassert the ready signal. This means 581 * that they are asserting an interrupt. This makes it hard to 582 * do anything but a busy wait here. One could argue that these 583 * such cards are broken, or that the bridge that allows this sort 584 * of interrupt through isn't quite what you'd want (and may be a standards 585 * violation). However, such arguing would leave a huge class of PC Cards 586 * and bridges out of reach for use in the system. 587 * 588 * Maybe I should reevaluate the above based on the power bug I fixed 589 * in OLDCARD. 590 */ 591 void 592 exca_reset(struct exca_softc *sc, device_t child) 593 { 594 int win; 595 596 /* enable socket i/o */ 597 exca_setb(sc, EXCA_PWRCTL, EXCA_PWRCTL_OE); 598 599 exca_putb(sc, EXCA_INTR, EXCA_INTR_ENABLE); 600 /* hold reset for 30ms */ 601 DELAY(30*1000); 602 /* clear the reset flag */ 603 exca_setb(sc, EXCA_INTR, EXCA_INTR_RESET); 604 /* wait 20ms as per PC Card standard (r2.01) section 4.3.6 */ 605 DELAY(20*1000); 606 607 exca_wait_ready(sc); 608 609 /* disable all address windows */ 610 exca_putb(sc, EXCA_ADDRWIN_ENABLE, 0); 611 612 exca_setb(sc, EXCA_INTR, EXCA_INTR_CARDTYPE_IO); 613 DEVPRINTF(sc->dev, "card type is io\n"); 614 615 /* reinstall all the memory and io mappings */ 616 for (win = 0; win < EXCA_MEM_WINS; ++win) 617 if (sc->memalloc & (1 << win)) 618 exca_do_mem_map(sc, win); 619 for (win = 0; win < EXCA_IO_WINS; ++win) 620 if (sc->ioalloc & (1 << win)) 621 exca_do_io_map(sc, win); 622 } 623 624 /* 625 * Initialize the exca_softc data structure for the first time. 626 */ 627 void 628 exca_init(struct exca_softc *sc, device_t dev, 629 bus_space_tag_t bst, bus_space_handle_t bsh, uint32_t offset) 630 { 631 sc->dev = dev; 632 sc->memalloc = 0; 633 sc->ioalloc = 0; 634 sc->bst = bst; 635 sc->bsh = bsh; 636 sc->offset = offset; 637 sc->flags = 0; 638 sc->getb = exca_mem_getb; 639 sc->putb = exca_mem_putb; 640 } 641 642 /* 643 * Is this socket valid? 644 */ 645 static int 646 exca_valid_slot(struct exca_softc *exca) 647 { 648 uint8_t c; 649 650 /* Assume the worst */ 651 exca->chipset = EXCA_BOGUS; 652 653 /* 654 * see if there's a PCMCIA controller here 655 * Intel PCMCIA controllers use 0x82 and 0x83 656 * IBM clone chips use 0x88 and 0x89, apparently 657 */ 658 c = exca_getb(exca, EXCA_IDENT); 659 DEVPRINTF(exca->dev, "Ident is %x\n", c); 660 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO) 661 return (0); 662 if ((c & EXCA_IDENT_ZERO) != 0) 663 return (0); 664 switch (c & EXCA_IDENT_REV_MASK) { 665 /* 666 * 82365 or clones. 667 */ 668 case EXCA_IDENT_REV_I82365SLR0: 669 case EXCA_IDENT_REV_I82365SLR1: 670 exca->chipset = EXCA_I82365; 671 /* 672 * Check for Vadem chips by unlocking their extra 673 * registers and looking for valid ID. Bit 3 in 674 * the ID register is normally 0, except when 675 * EXCA_VADEMREV is set. Other bridges appear 676 * to ignore this frobbing. 677 */ 678 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 679 EXCA_VADEM_COOKIE1); 680 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 681 EXCA_VADEM_COOKIE2); 682 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 683 c = exca_getb(exca, EXCA_IDENT); 684 if (c & 0x08) { 685 switch (c & 7) { 686 case 1: 687 exca->chipset = EXCA_VG365; 688 break; 689 case 2: 690 exca->chipset = EXCA_VG465; 691 break; 692 case 3: 693 exca->chipset = EXCA_VG468; 694 break; 695 default: 696 exca->chipset = EXCA_VG469; 697 break; 698 } 699 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 700 break; 701 } 702 /* 703 * Check for RICOH RF5C[23]96 PCMCIA Controller 704 */ 705 c = exca_getb(exca, EXCA_RICOH_ID); 706 if (c == EXCA_RID_396) { 707 exca->chipset = EXCA_RF5C396; 708 break; 709 } else if (c == EXCA_RID_296) { 710 exca->chipset = EXCA_RF5C296; 711 break; 712 } 713 /* 714 * Check for Cirrus logic chips. 715 */ 716 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0); 717 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 718 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 719 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) { 720 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 721 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) { 722 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS) 723 exca->chipset = EXCA_PD6722; 724 else 725 exca->chipset = EXCA_PD6710; 726 break; 727 } 728 } 729 break; 730 731 case EXCA_IDENT_REV_I82365SLDF: 732 /* 733 * Intel i82365sl-DF step or maybe a vlsi 82c146 734 * we detected the vlsi case earlier, so if the controller 735 * isn't set, we know it is a i82365sl step D. 736 */ 737 exca->chipset = EXCA_I82365SL_DF; 738 break; 739 case EXCA_IDENT_REV_IBM1: 740 case EXCA_IDENT_REV_IBM2: 741 exca->chipset = EXCA_IBM; 742 break; 743 case EXCA_IDENT_REV_IBM_KING: 744 exca->chipset = EXCA_IBM_KING; 745 break; 746 default: 747 return (0); 748 } 749 return (1); 750 } 751 752 /* 753 * Probe the expected slots. We maybe should set the ID for each of these 754 * slots too while we're at it. But maybe that belongs to a separate 755 * function. 756 * 757 * The caller must guarantee that at least EXCA_NSLOTS are present in exca. 758 */ 759 int 760 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot, 761 bus_space_handle_t ioh) 762 { 763 int err; 764 int i; 765 766 err = ENXIO; 767 for (i = 0; i < EXCA_NSLOTS; i++) { 768 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE); 769 exca->getb = exca_io_getb; 770 exca->putb = exca_io_putb; 771 if (exca_valid_slot(&exca[i])) { 772 device_set_desc(dev, chip_names[exca[i].chipset]); 773 err = 0; 774 } 775 } 776 return (err); 777 } 778 779 void 780 exca_insert(struct exca_softc *exca) 781 { 782 if (device_is_attached(exca->pccarddev)) { 783 if (CARD_ATTACH_CARD(exca->pccarddev) != 0) 784 device_printf(exca->dev, 785 "PC Card card activation failed\n"); 786 } else { 787 device_printf(exca->dev, 788 "PC Card inserted, but no pccard bus.\n"); 789 } 790 } 791 792 793 void 794 exca_removal(struct exca_softc *exca) 795 { 796 if (device_is_attached(exca->pccarddev)) 797 CARD_DETACH_CARD(exca->pccarddev); 798 } 799 800 int 801 exca_activate_resource(struct exca_softc *exca, device_t child, int type, 802 int rid, struct resource *res) 803 { 804 int err; 805 806 if (rman_get_flags(res) & RF_ACTIVE) 807 return (0); 808 err = BUS_ACTIVATE_RESOURCE(device_get_parent(exca->dev), child, 809 type, rid, res); 810 if (err) 811 return (err); 812 switch (type) { 813 case SYS_RES_IOPORT: 814 err = exca_io_map(exca, PCCARD_WIDTH_AUTO, res); 815 break; 816 case SYS_RES_MEMORY: 817 err = exca_mem_map(exca, 0, res); 818 break; 819 } 820 if (err) 821 BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child, 822 type, rid, res); 823 return (err); 824 } 825 826 int 827 exca_deactivate_resource(struct exca_softc *exca, device_t child, int type, 828 int rid, struct resource *res) 829 { 830 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */ 831 switch (type) { 832 case SYS_RES_IOPORT: 833 if (exca_io_unmap_res(exca, res)) 834 return (ENOENT); 835 break; 836 case SYS_RES_MEMORY: 837 if (exca_mem_unmap_res(exca, res)) 838 return (ENOENT); 839 break; 840 } 841 } 842 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child, 843 type, rid, res)); 844 } 845 846 #if 0 847 static struct resource * 848 exca_alloc_resource(struct exca_softc *sc, device_t child, int type, int *rid, 849 u_long start, u_long end, u_long count, uint flags) 850 { 851 struct resource *res = NULL; 852 int tmp; 853 854 switch (type) { 855 case SYS_RES_MEMORY: 856 if (start < cbb_start_mem) 857 start = cbb_start_mem; 858 if (end < start) 859 end = start; 860 flags = (flags & ~RF_ALIGNMENT_MASK) | 861 rman_make_alignment_flags(CBB_MEMALIGN); 862 break; 863 case SYS_RES_IOPORT: 864 if (start < cbb_start_16_io) 865 start = cbb_start_16_io; 866 if (end < start) 867 end = start; 868 break; 869 case SYS_RES_IRQ: 870 tmp = rman_get_start(sc->irq_res); 871 if (start > tmp || end < tmp || count != 1) { 872 device_printf(child, "requested interrupt %ld-%ld," 873 "count = %ld not supported by cbb\n", 874 start, end, count); 875 return (NULL); 876 } 877 flags |= RF_SHAREABLE; 878 start = end = rman_get_start(sc->irq_res); 879 break; 880 } 881 res = BUS_ALLOC_RESOURCE(up, child, type, rid, 882 start, end, count, flags & ~RF_ACTIVE); 883 if (res == NULL) 884 return (NULL); 885 cbb_insert_res(sc, res, type, *rid); 886 if (flags & RF_ACTIVE) { 887 if (bus_activate_resource(child, type, *rid, res) != 0) { 888 bus_release_resource(child, type, *rid, res); 889 return (NULL); 890 } 891 } 892 893 return (res); 894 } 895 896 static int 897 exca_release_resource(struct exca_softc *sc, device_t child, int type, 898 int rid, struct resource *res) 899 { 900 int error; 901 902 if (rman_get_flags(res) & RF_ACTIVE) { 903 error = bus_deactivate_resource(child, type, rid, res); 904 if (error != 0) 905 return (error); 906 } 907 cbb_remove_res(sc, res); 908 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child, 909 type, rid, res)); 910 } 911 #endif 912 913 static int 914 exca_modevent(module_t mod, int cmd, void *arg) 915 { 916 return 0; 917 } 918 919 DEV_MODULE(exca, exca_modevent, NULL); 920 MODULE_VERSION(exca, 1); 921