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