1 /* 2 * Copyright (c) 2002 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 #if 0 90 static const char *chip_names[] = 91 { 92 "CardBus socket", 93 "Intel i82365SL-A/B or clone", 94 "Intel i82365sl-DF step", 95 "VLSI chip", 96 "Cirrus Logic PD6710", 97 "Cirrus logic PD6722", 98 "Cirrus Logic PD6729", 99 "Vadem 365", 100 "Vadem 465", 101 "Vadem 468", 102 "Vadem 469", 103 "Ricoh RF5C296", 104 "Ricoh RF5C396", 105 "IBM clone", 106 "IBM KING PCMCIA Controller" 107 }; 108 #endif 109 110 static exca_getb_fn exca_mem_getb; 111 static exca_putb_fn exca_mem_putb; 112 static exca_getb_fn exca_io_getb; 113 static exca_putb_fn exca_io_putb; 114 115 /* memory */ 116 117 #define EXCA_MEMINFO(NUM) { \ 118 EXCA_SYSMEM_ADDR ## NUM ## _START_LSB, \ 119 EXCA_SYSMEM_ADDR ## NUM ## _START_MSB, \ 120 EXCA_SYSMEM_ADDR ## NUM ## _STOP_LSB, \ 121 EXCA_SYSMEM_ADDR ## NUM ## _STOP_MSB, \ 122 EXCA_SYSMEM_ADDR ## NUM ## _WIN, \ 123 EXCA_CARDMEM_ADDR ## NUM ## _LSB, \ 124 EXCA_CARDMEM_ADDR ## NUM ## _MSB, \ 125 EXCA_ADDRWIN_ENABLE_MEM ## NUM, \ 126 } 127 128 static struct mem_map_index_st { 129 int sysmem_start_lsb; 130 int sysmem_start_msb; 131 int sysmem_stop_lsb; 132 int sysmem_stop_msb; 133 int sysmem_win; 134 int cardmem_lsb; 135 int cardmem_msb; 136 int memenable; 137 } mem_map_index[] = { 138 EXCA_MEMINFO(0), 139 EXCA_MEMINFO(1), 140 EXCA_MEMINFO(2), 141 EXCA_MEMINFO(3), 142 EXCA_MEMINFO(4) 143 }; 144 #undef EXCA_MEMINFO 145 146 static uint8_t 147 exca_mem_getb(struct exca_softc *sc, int reg) 148 { 149 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg)); 150 } 151 152 static void 153 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val) 154 { 155 bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val); 156 } 157 158 static uint8_t 159 exca_io_getb(struct exca_softc *sc, int reg) 160 { 161 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 162 return (bus_space_read_1(sc->bst, sc->bsh, EXCA_REG_DATA)); 163 } 164 165 static void 166 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val) 167 { 168 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 169 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_DATA, val); 170 } 171 172 /* 173 * Helper function. This will map the requested memory slot. We setup the 174 * map before we call this function. This is used to initially force the 175 * mapping, as well as later restore the mapping after it has been destroyed 176 * in some fashion (due to a power event typically). 177 */ 178 static void 179 exca_do_mem_map(struct exca_softc *sc, int win) 180 { 181 struct mem_map_index_st *map; 182 struct pccard_mem_handle *mem; 183 184 map = &mem_map_index[win]; 185 mem = &sc->mem[win]; 186 exca_putb(sc, map->sysmem_start_lsb, 187 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT) & 0xff); 188 exca_putb(sc, map->sysmem_start_msb, 189 ((mem->addr >> (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 190 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK)); 191 192 exca_putb(sc, map->sysmem_stop_lsb, 193 ((mem->addr + mem->realsize - 1) >> 194 EXCA_SYSMEM_ADDRX_SHIFT) & 0xff); 195 exca_putb(sc, map->sysmem_stop_msb, 196 (((mem->addr + mem->realsize - 1) >> 197 (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 198 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK)); 199 200 exca_putb(sc, map->sysmem_win, 201 (mem->addr >> EXCA_MEMREG_WIN_SHIFT) & 0xff); 202 203 exca_putb(sc, map->cardmem_lsb, 204 (mem->cardaddr >> EXCA_CARDMEM_ADDRX_SHIFT) & 0xff); 205 exca_putb(sc, map->cardmem_msb, 206 ((mem->cardaddr >> (EXCA_CARDMEM_ADDRX_SHIFT + 8)) & 207 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK) | 208 ((mem->kind == PCCARD_A_MEM_ATTR) ? 209 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); 210 211 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->memenable); 212 #ifdef EXCA_DEBUG 213 if (mem->kind == PCCARD_A_MEM_ATTR) 214 printf("attribtue memory\n"); 215 else 216 printf("common memory\n"); 217 #endif 218 exca_setb(sc, EXCA_ADDRWIN_ENABLE, EXCA_ADDRWIN_ENABLE_MEMCS16); 219 220 DELAY(100); 221 #ifdef EXCA_DEBUG 222 { 223 int r1, r2, r3, r4, r5, r6, r7; 224 r1 = exca_getb(sc, map->sysmem_start_msb); 225 r2 = exca_getb(sc, map->sysmem_start_lsb); 226 r3 = exca_getb(sc, map->sysmem_stop_msb); 227 r4 = exca_getb(sc, map->sysmem_stop_lsb); 228 r5 = exca_getb(sc, map->cardmem_msb); 229 r6 = exca_getb(sc, map->cardmem_lsb); 230 r7 = exca_getb(sc, map->sysmem_win); 231 printf("exca_do_mem_map window %d: %02x%02x %02x%02x " 232 "%02x%02x %02x (%08x+%08x.%08x*%08x)\n", 233 win, r1, r2, r3, r4, r5, r6, r7, 234 mem->addr, mem->size, mem->realsize, 235 mem->cardaddr); 236 } 237 #endif 238 } 239 240 /* 241 * public interface to map a resource. kind is the type of memory to 242 * map (either common or attribute). Memory created via this interface 243 * starts out at card address 0. Since the only way to set this is 244 * to set it on a struct resource after it has been mapped, we're safe 245 * in maping this assumption. Note that resources can be remapped using 246 * exca_do_mem_map so that's how the card address can be set later. 247 */ 248 int 249 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res) 250 { 251 int win; 252 253 for (win = 0; win < EXCA_MEM_WINS; win++) { 254 if ((sc->memalloc & (1 << win)) == 0) { 255 sc->memalloc |= (1 << win); 256 break; 257 } 258 } 259 if (win >= EXCA_MEM_WINS) 260 return (1); 261 if (((rman_get_start(res) >> EXCA_CARDMEM_ADDRX_SHIFT) & 0xff) != 0 && 262 (sc->flags & EXCA_HAS_MEMREG_WIN) == 0) { 263 device_printf(sc->dev, "Does not support mapping above 24M."); 264 return (1); 265 } 266 267 sc->mem[win].cardaddr = 0; 268 sc->mem[win].memt = rman_get_bustag(res); 269 sc->mem[win].memh = rman_get_bushandle(res); 270 sc->mem[win].addr = rman_get_start(res); 271 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1; 272 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1; 273 sc->mem[win].realsize = sc->mem[win].realsize - 274 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 275 sc->mem[win].kind = kind; 276 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n", 277 win, sc->mem[win].addr, sc->mem[win].size, sc->mem[win].cardaddr); 278 exca_do_mem_map(sc, win); 279 280 return (0); 281 } 282 283 /* 284 * Private helper function. This turns off a given memory map that is in 285 * use. We do this by just clearing the enable bit in the pcic. If we needed 286 * to make memory unmapping/mapping pairs faster, we would have to store 287 * more state information about the pcic and then use that to intelligently 288 * to the map/unmap. However, since we don't do that sort of thing often 289 * (generally just at configure time), it isn't a case worth optimizing. 290 */ 291 static void 292 exca_mem_unmap(struct exca_softc *sc, int window) 293 { 294 if (window < 0 || window >= EXCA_MEM_WINS) 295 panic("exca_mem_unmap: window out of range"); 296 297 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable); 298 sc->memalloc &= ~(1 << window); 299 } 300 301 /* 302 * Find the map that we're using to hold the resoruce. This works well 303 * so long as the client drivers don't do silly things like map the same 304 * area mutliple times, or map both common and attribute memory at the 305 * same time. This latter restriction is a bug. We likely should just 306 * store a pointer to the res in the mem[x] data structure. 307 */ 308 static int 309 exca_mem_findmap(struct exca_softc *sc, struct resource *res) 310 { 311 int win; 312 313 for (win = 0; win < EXCA_MEM_WINS; win++) { 314 if (sc->mem[win].memt == rman_get_bustag(res) && 315 sc->mem[win].addr == rman_get_start(res) && 316 sc->mem[win].size == rman_get_size(res)) 317 return (win); 318 } 319 return (-1); 320 } 321 322 /* 323 * Set the memory flag. This means that we are setting if the memory 324 * is coming from attribute memory or from common memory on the card. 325 * CIS entries are generally in attribute memory (although they can 326 * reside in common memory). Generally, this is the only use for attribute 327 * memory. However, some cards require their drivers to dance in both 328 * common and/or attribute memory and this interface (and setting the 329 * offset interface) exist for such cards. 330 */ 331 int 332 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags) 333 { 334 int win; 335 336 win = exca_mem_findmap(sc, res); 337 if (win < 0) { 338 device_printf(sc->dev, 339 "set_res_flags: specified resource not active\n"); 340 return (ENOENT); 341 } 342 343 sc->mem[win].kind = flags; 344 exca_do_mem_map(sc, win); 345 return (0); 346 } 347 348 /* 349 * Given a resource, go ahead and unmap it if we can find it in the 350 * resrouce list that's used. 351 */ 352 int 353 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res) 354 { 355 int win; 356 357 win = exca_mem_findmap(sc, res); 358 if (win < 0) 359 return (ENOENT); 360 exca_mem_unmap(sc, win); 361 return (0); 362 } 363 364 /* 365 * Set the offset of the memory. We use this for reading the CIS and 366 * frobbing the pccard's pccard registers (POR, etc). Some drivers 367 * need to access this functionality as well, since they have receive 368 * buffers defined in the attribute memory. 369 */ 370 int 371 exca_mem_set_offset(struct exca_softc *sc, struct resource *res, 372 uint32_t cardaddr, uint32_t *deltap) 373 { 374 int win; 375 uint32_t delta; 376 377 win = exca_mem_findmap(sc, res); 378 if (win < 0) { 379 device_printf(sc->dev, 380 "set_memory_offset: specified resource not active\n"); 381 return (ENOENT); 382 } 383 sc->mem[win].cardaddr = cardaddr & ~(EXCA_MEM_PAGESIZE - 1); 384 delta = cardaddr % EXCA_MEM_PAGESIZE; 385 if (deltap) 386 *deltap = delta; 387 sc->mem[win].realsize = sc->mem[win].size + delta + 388 EXCA_MEM_PAGESIZE - 1; 389 sc->mem[win].realsize = sc->mem[win].realsize - 390 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 391 exca_do_mem_map(sc, win); 392 return (0); 393 } 394 395 396 /* I/O */ 397 398 #define EXCA_IOINFO(NUM) { \ 399 EXCA_IOADDR ## NUM ## _START_LSB, \ 400 EXCA_IOADDR ## NUM ## _START_MSB, \ 401 EXCA_IOADDR ## NUM ## _STOP_LSB, \ 402 EXCA_IOADDR ## NUM ## _STOP_MSB, \ 403 EXCA_ADDRWIN_ENABLE_IO ## NUM, \ 404 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \ 405 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \ 406 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \ 407 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \ 408 { \ 409 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \ 410 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \ 411 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \ 412 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \ 413 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \ 414 } \ 415 } 416 417 static struct io_map_index_st { 418 int start_lsb; 419 int start_msb; 420 int stop_lsb; 421 int stop_msb; 422 int ioenable; 423 int ioctlmask; 424 int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */ 425 } io_map_index[] = { 426 EXCA_IOINFO(0), 427 EXCA_IOINFO(1), 428 }; 429 #undef EXCA_IOINFO 430 431 static void 432 exca_do_io_map(struct exca_softc *sc, int win) 433 { 434 struct io_map_index_st *map; 435 436 struct pccard_io_handle *io; 437 438 map = &io_map_index[win]; 439 io = &sc->io[win]; 440 exca_putb(sc, map->start_lsb, io->addr & 0xff); 441 exca_putb(sc, map->start_msb, (io->addr >> 8) & 0xff); 442 443 exca_putb(sc, map->stop_lsb, (io->addr + io->size - 1) & 0xff); 444 exca_putb(sc, map->stop_msb, ((io->addr + io->size - 1) >> 8) & 0xff); 445 446 exca_clrb(sc, EXCA_IOCTL, map->ioctlmask); 447 exca_setb(sc, EXCA_IOCTL, map->ioctlbits[io->width]); 448 449 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->ioenable); 450 #ifdef EXCA_DEBUG 451 { 452 int r1, r2, r3, r4; 453 r1 = exca_getb(sc, map->start_msb); 454 r2 = exca_getb(sc, map->start_lsb); 455 r3 = exca_getb(sc, map->stop_msb); 456 r4 = exca_getb(sc, map->stop_lsb); 457 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x " 458 "(%08x+%08x)\n", win, r1, r2, r3, r4, 459 io->addr, io->size); 460 } 461 #endif 462 } 463 464 int 465 exca_io_map(struct exca_softc *sc, int width, struct resource *r) 466 { 467 int win; 468 #ifdef EXCA_DEBUG 469 static char *width_names[] = { "auto", "io8", "io16"}; 470 #endif 471 for (win=0; win < EXCA_IO_WINS; win++) { 472 if ((sc->ioalloc & (1 << win)) == 0) { 473 sc->ioalloc |= (1 << win); 474 break; 475 } 476 } 477 if (win >= EXCA_IO_WINS) 478 return (1); 479 480 sc->io[win].iot = rman_get_bustag(r); 481 sc->io[win].ioh = rman_get_bushandle(r); 482 sc->io[win].addr = rman_get_start(r); 483 sc->io[win].size = rman_get_end(r) - sc->io[win].addr + 1; 484 sc->io[win].flags = 0; 485 sc->io[win].width = width; 486 DPRINTF("exca_io_map window %d %s port %x+%x\n", 487 win, width_names[width], sc->io[win].addr, 488 sc->io[win].size); 489 exca_do_io_map(sc, win); 490 491 return (0); 492 } 493 494 static void 495 exca_io_unmap(struct exca_softc *sc, int window) 496 { 497 if (window >= EXCA_IO_WINS) 498 panic("exca_io_unmap: window out of range"); 499 500 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, io_map_index[window].ioenable); 501 502 sc->ioalloc &= ~(1 << window); 503 504 sc->io[window].iot = 0; 505 sc->io[window].ioh = 0; 506 sc->io[window].addr = 0; 507 sc->io[window].size = 0; 508 sc->io[window].flags = 0; 509 sc->io[window].width = 0; 510 } 511 512 static int 513 exca_io_findmap(struct exca_softc *sc, struct resource *res) 514 { 515 int win; 516 517 for (win = 0; win < EXCA_IO_WINS; win++) { 518 if (sc->io[win].iot == rman_get_bustag(res) && 519 sc->io[win].addr == rman_get_start(res) && 520 sc->io[win].size == rman_get_size(res)) 521 return (win); 522 } 523 return (-1); 524 } 525 526 527 int 528 exca_io_unmap_res(struct exca_softc *sc, struct resource *res) 529 { 530 int win; 531 532 win = exca_io_findmap(sc, res); 533 if (win < 0) 534 return (ENOENT); 535 exca_io_unmap(sc, win); 536 return (0); 537 } 538 539 /* Misc */ 540 541 /* 542 * If interrupts are enabled, then we should be able to just wait for 543 * an interrupt routine to wake us up. Busy waiting shouldn't be 544 * necessary. Sadly, not all legacy ISA cards support an interrupt 545 * for the busy state transitions, at least according to their datasheets, 546 * so we busy wait a while here.. 547 */ 548 static void 549 exca_wait_ready(struct exca_softc *sc) 550 { 551 int i; 552 DEVPRINTF(sc->dev, "exca_wait_ready: status 0x%02x\n", 553 exca_getb(sc, EXCA_IF_STATUS)); 554 for (i = 0; i < 10000; i++) { 555 if (exca_getb(sc, EXCA_IF_STATUS) & EXCA_IF_STATUS_READY) 556 return; 557 DELAY(500); 558 } 559 device_printf(sc->dev, "ready never happened, status = %02x\n", 560 exca_getb(sc, EXCA_IF_STATUS)); 561 } 562 563 /* 564 * Reset the card. Ideally, we'd do a lot of this via interrupts. 565 * However, many PC Cards will deassert the ready signal. This means 566 * that they are asserting an interrupt. This makes it hard to 567 * do anything but a busy wait here. One could argue that these 568 * such cards are broken, or that the bridge that allows this sort 569 * of interrupt through isn't quite what you'd want (and may be a standards 570 * violation). However, such arguing would leave a huge class of pc cards 571 * and bridges out of reach for use in the system. 572 * 573 * Maybe I should reevaluate the above based on the power bug I fixed 574 * in OLDCARD. 575 */ 576 void 577 exca_reset(struct exca_softc *sc, device_t child) 578 { 579 int cardtype; 580 int win; 581 582 /* enable socket i/o */ 583 exca_setb(sc, EXCA_PWRCTL, EXCA_PWRCTL_OE); 584 585 exca_putb(sc, EXCA_INTR, EXCA_INTR_ENABLE); 586 /* hold reset for 30ms */ 587 DELAY(30*1000); 588 /* clear the reset flag */ 589 exca_setb(sc, EXCA_INTR, EXCA_INTR_RESET); 590 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ 591 DELAY(20*1000); 592 593 exca_wait_ready(sc); 594 595 /* disable all address windows */ 596 exca_putb(sc, EXCA_ADDRWIN_ENABLE, 0); 597 598 CARD_GET_TYPE(child, &cardtype); 599 exca_setb(sc, EXCA_INTR, (cardtype == PCCARD_IFTYPE_IO) ? 600 EXCA_INTR_CARDTYPE_IO : EXCA_INTR_CARDTYPE_MEM); 601 DEVPRINTF(sc->dev, "card type is %s\n", 602 (cardtype == PCCARD_IFTYPE_IO) ? "io" : "mem"); 603 604 /* reinstall all the memory and io mappings */ 605 for (win = 0; win < EXCA_MEM_WINS; ++win) 606 if (sc->memalloc & (1 << win)) 607 exca_do_mem_map(sc, win); 608 for (win = 0; win < EXCA_IO_WINS; ++win) 609 if (sc->ioalloc & (1 << win)) 610 exca_do_io_map(sc, win); 611 } 612 613 /* 614 * Initialize the exca_softc data structure for the first time. 615 */ 616 void 617 exca_init(struct exca_softc *sc, device_t dev, 618 bus_space_tag_t bst, bus_space_handle_t bsh, uint32_t offset) 619 { 620 sc->dev = dev; 621 sc->memalloc = 0; 622 sc->ioalloc = 0; 623 sc->bst = bst; 624 sc->bsh = bsh; 625 sc->offset = offset; 626 sc->flags = 0; 627 sc->getb = exca_mem_getb; 628 sc->putb = exca_mem_putb; 629 } 630 631 /* 632 * Is this socket valid? 633 */ 634 static int 635 exca_valid_slot(struct exca_softc *exca) 636 { 637 uint8_t c; 638 639 /* Assume the worst */ 640 exca->chipset = EXCA_BOGUS; 641 642 /* 643 * see if there's a PCMCIA controller here 644 * Intel PCMCIA controllers use 0x82 and 0x83 645 * IBM clone chips use 0x88 and 0x89, apparently 646 */ 647 c = exca_getb(exca, EXCA_IDENT); 648 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO) 649 return (0); 650 if ((c & EXCA_IDENT_ZERO) != 0) 651 return (0); 652 switch (c & EXCA_IDENT_REV_MASK) { 653 /* 654 * 82365 or clones. 655 */ 656 case EXCA_IDENT_REV_I82365SLR0: 657 case EXCA_IDENT_REV_I82365SLR1: 658 exca->chipset = EXCA_I82365; 659 /* 660 * Check for Vadem chips by unlocking their extra 661 * registers and looking for valid ID. Bit 3 in 662 * the ID register is normally 0, except when 663 * EXCA_VADEMREV is set. Other bridges appear 664 * to ignore this frobbing. 665 */ 666 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 667 EXCA_VADEM_COOKIE1); 668 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 669 EXCA_VADEM_COOKIE2); 670 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 671 c = exca_getb(exca, EXCA_IDENT); 672 if (c & 0x08) { 673 switch (c & 7) { 674 case 1: 675 exca->chipset = EXCA_VG365; 676 break; 677 case 2: 678 exca->chipset = EXCA_VG465; 679 break; 680 case 3: 681 exca->chipset = EXCA_VG468; 682 break; 683 default: 684 exca->chipset = EXCA_VG469; 685 break; 686 } 687 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 688 break; 689 } 690 /* 691 * Check for RICOH RF5C[23]96 PCMCIA Controller 692 */ 693 c = exca_getb(exca, EXCA_RICOH_ID); 694 if (c == EXCA_RID_396) { 695 exca->chipset = EXCA_RF5C396; 696 break; 697 } else if (c == EXCA_RID_296) { 698 exca->chipset = EXCA_RF5C296; 699 break; 700 } 701 /* 702 * Check for Cirrus logic chips. 703 */ 704 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0); 705 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 706 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 707 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) { 708 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 709 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) { 710 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS) 711 exca->chipset = EXCA_PD6722; 712 else 713 exca->chipset = EXCA_PD6710; 714 break; 715 } 716 } 717 break; 718 719 case EXCA_IDENT_REV_I82365SLDF: 720 /* 721 * Intel i82365sl-DF step or maybe a vlsi 82c146 722 * we detected the vlsi case earlier, so if the controller 723 * isn't set, we know it is a i82365sl step D. 724 */ 725 exca->chipset = EXCA_I82365SL_DF; 726 break; 727 case EXCA_IDENT_REV_IBM1: 728 case EXCA_IDENT_REV_IBM2: 729 exca->chipset = EXCA_IBM; 730 break; 731 case EXCA_IDENT_REV_IBM_KING: 732 exca->chipset = EXCA_IBM_KING; 733 break; 734 default: 735 return (0); 736 } 737 return (1); 738 } 739 740 /* 741 * Probe the expected slots. We maybe should set the ID for each of these 742 * slots too while we're at it. But maybe that belongs to a separate 743 * function. 744 * 745 * The caller must guarantee that at least EXCA_NSLOTS are present in exca. 746 */ 747 int 748 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot, 749 bus_space_handle_t ioh) 750 { 751 int err; 752 int i; 753 754 err = ENXIO; 755 for (i = 0; i < EXCA_NSLOTS; i++) { 756 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE); 757 exca->getb = exca_io_getb; 758 exca->putb = exca_io_putb; 759 if (exca_valid_slot(&exca[i])) 760 err = 0; 761 } 762 return (err); 763 } 764 765 void 766 exca_insert(struct exca_softc *exca) 767 { 768 if (exca->pccarddev != NULL) { 769 if (CARD_ATTACH_CARD(exca->pccarddev) != 0) 770 device_printf(exca->dev, 771 "PC Card card activation failed\n"); 772 } else { 773 device_printf(exca->dev, 774 "PC Card inserted, but no pccard bus.\n"); 775 } 776 } 777 778 779 void 780 exca_removal(struct exca_softc *exca) 781 { 782 if (exca->pccarddev != NULL) 783 CARD_DETACH_CARD(exca->pccarddev); 784 } 785 786 int 787 exca_activate_resource(struct exca_softc *exca, device_t child, int type, 788 int rid, struct resource *res) 789 { 790 int err; 791 if (!(rman_get_flags(res) & RF_ACTIVE)) { /* not already activated */ 792 switch (type) { 793 case SYS_RES_IOPORT: 794 err = exca_io_map(exca, PCCARD_WIDTH_AUTO, res); 795 break; 796 case SYS_RES_MEMORY: 797 err = exca_mem_map(exca, PCCARD_A_MEM_COM, res); 798 break; 799 default: 800 err = 0; 801 break; 802 } 803 if (err) 804 return (err); 805 806 } 807 return (BUS_ACTIVATE_RESOURCE(device_get_parent(exca->dev), child, 808 type, rid, res)); 809 } 810 811 int 812 exca_deactivate_resource(struct exca_softc *exca, device_t child, int type, 813 int rid, struct resource *res) 814 { 815 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */ 816 switch (type) { 817 case SYS_RES_IOPORT: 818 if (exca_io_unmap_res(exca, res)) 819 return (ENOENT); 820 break; 821 case SYS_RES_MEMORY: 822 if (exca_mem_unmap_res(exca, res)) 823 return (ENOENT); 824 break; 825 } 826 } 827 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child, 828 type, rid, res)); 829 } 830 831 static int 832 exca_modevent(module_t mod, int cmd, void *arg) 833 { 834 return 0; 835 } 836 837 DEV_MODULE(exca, exca_modevent, NULL); 838 MODULE_VERSION(exca, 1); 839