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/errno.h> 60 #include <sys/kernel.h> 61 #include <sys/malloc.h> 62 #include <sys/queue.h> 63 #include <sys/module.h> 64 #include <sys/conf.h> 65 66 #include <sys/bus.h> 67 #include <machine/bus.h> 68 #include <sys/rman.h> 69 #include <machine/resource.h> 70 71 #include <dev/pccard/pccardreg.h> 72 #include <dev/pccard/pccardvar.h> 73 74 #include <dev/exca/excareg.h> 75 #include <dev/exca/excavar.h> 76 77 #ifdef EXCA_DEBUG 78 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args) 79 #define DPRINTF(fmt, args...) printf(fmt, ## args) 80 #else 81 #define DEVPRINTF(dev, fmt, args...) 82 #define DPRINTF(fmt, args...) 83 #endif 84 85 #if 0 86 static const char *chip_names[] = 87 { 88 "CardBus socket", 89 "Intel i82365SL-A/B or clone", 90 "Intel i82365sl-DF step", 91 "VLSI chip", 92 "Cirrus Logic PD6710", 93 "Cirrus logic PD6722", 94 "Cirrus Logic PD6729", 95 "Vadem 365", 96 "Vadem 465", 97 "Vadem 468", 98 "Vadem 469", 99 "Ricoh RF5C296", 100 "Ricoh RF5C396", 101 "IBM clone", 102 "IBM KING PCMCIA Controller" 103 }; 104 #endif 105 106 static exca_getb_fn exca_mem_getb; 107 static exca_putb_fn exca_mem_putb; 108 static exca_getb_fn exca_io_getb; 109 static exca_putb_fn exca_io_putb; 110 111 /* memory */ 112 113 #define EXCA_MEMINFO(NUM) { \ 114 EXCA_SYSMEM_ADDR ## NUM ## _START_LSB, \ 115 EXCA_SYSMEM_ADDR ## NUM ## _START_MSB, \ 116 EXCA_SYSMEM_ADDR ## NUM ## _STOP_LSB, \ 117 EXCA_SYSMEM_ADDR ## NUM ## _STOP_MSB, \ 118 EXCA_SYSMEM_ADDR ## NUM ## _WIN, \ 119 EXCA_CARDMEM_ADDR ## NUM ## _LSB, \ 120 EXCA_CARDMEM_ADDR ## NUM ## _MSB, \ 121 EXCA_ADDRWIN_ENABLE_MEM ## NUM, \ 122 } 123 124 static struct mem_map_index_st { 125 int sysmem_start_lsb; 126 int sysmem_start_msb; 127 int sysmem_stop_lsb; 128 int sysmem_stop_msb; 129 int sysmem_win; 130 int cardmem_lsb; 131 int cardmem_msb; 132 int memenable; 133 } mem_map_index[] = { 134 EXCA_MEMINFO(0), 135 EXCA_MEMINFO(1), 136 EXCA_MEMINFO(2), 137 EXCA_MEMINFO(3), 138 EXCA_MEMINFO(4) 139 }; 140 #undef EXCA_MEMINFO 141 142 static uint8_t 143 exca_mem_getb(struct exca_softc *sc, int reg) 144 { 145 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg)); 146 } 147 148 static void 149 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val) 150 { 151 return (bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val)); 152 } 153 154 static uint8_t 155 exca_io_getb(struct exca_softc *sc, int reg) 156 { 157 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 158 return (bus_space_read_1(sc->bst, sc->bsh, EXCA_REG_DATA)); 159 } 160 161 static void 162 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val) 163 { 164 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset); 165 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_DATA, val); 166 } 167 168 /* 169 * Helper function. This will map the requested memory slot. We setup the 170 * map before we call this function. This is used to initially force the 171 * mapping, as well as later restore the mapping after it has been destroyed 172 * in some fashion (due to a power event typically). 173 */ 174 static void 175 exca_do_mem_map(struct exca_softc *sc, int win) 176 { 177 struct mem_map_index_st *map; 178 struct pccard_mem_handle *mem; 179 180 map = &mem_map_index[win]; 181 mem = &sc->mem[win]; 182 exca_putb(sc, map->sysmem_start_lsb, 183 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT) & 0xff); 184 exca_putb(sc, map->sysmem_start_msb, 185 ((mem->addr >> (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 186 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | 0x80); 187 188 exca_putb(sc, map->sysmem_stop_lsb, 189 ((mem->addr + mem->realsize - 1) >> 190 EXCA_SYSMEM_ADDRX_SHIFT) & 0xff); 191 exca_putb(sc, map->sysmem_stop_msb, 192 (((mem->addr + mem->realsize - 1) >> 193 (EXCA_SYSMEM_ADDRX_SHIFT + 8)) & 194 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) | 195 EXCA_SYSMEM_ADDRX_STOP_MSB_WAIT2); 196 197 exca_putb(sc, map->sysmem_win, 198 (mem->addr >> EXCA_MEMREG_WIN_SHIFT) & 0xff); 199 200 exca_putb(sc, map->cardmem_lsb, 201 (mem->offset >> EXCA_CARDMEM_ADDRX_SHIFT) & 0xff); 202 exca_putb(sc, map->cardmem_msb, 203 ((mem->offset >> (EXCA_CARDMEM_ADDRX_SHIFT + 8)) & 204 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK) | 205 ((mem->kind == PCCARD_MEM_ATTR) ? 206 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0)); 207 208 exca_setb(sc, EXCA_ADDRWIN_ENABLE, EXCA_ADDRWIN_ENABLE_MEMCS16 | 209 map->memenable); 210 211 DELAY(100); 212 #ifdef EXCA_DEBUG 213 { 214 int r1, r2, r3, r4, r5, r6, r7; 215 r1 = exca_getb(sc, map->sysmem_start_msb); 216 r2 = exca_getb(sc, map->sysmem_start_lsb); 217 r3 = exca_getb(sc, map->sysmem_stop_msb); 218 r4 = exca_getb(sc, map->sysmem_stop_lsb); 219 r5 = exca_getb(sc, map->cardmem_msb); 220 r6 = exca_getb(sc, map->cardmem_lsb); 221 r7 = exca_getb(sc, map->sysmem_win); 222 printf("exca_do_mem_map window %d: %02x%02x %02x%02x " 223 "%02x%02x %02x (%08x+%08x.%08x*%08lx)\n", 224 win, r1, r2, r3, r4, r5, r6, r7, 225 mem->addr, mem->size, mem->realsize, 226 mem->offset); 227 } 228 #endif 229 } 230 231 /* 232 * public interface to map a resource. kind is the type of memory to 233 * map (either common or attribute). Memory created via this interface 234 * starts out at card address 0. Since the only way to set this is 235 * to set it on a struct resource after it has been mapped, we're safe 236 * in maping this assumption. Note that resources can be remapped using 237 * exca_do_mem_map so that's how the card address can be set later. 238 */ 239 int 240 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res) 241 { 242 int win; 243 244 for (win = 0; win < EXCA_MEM_WINS; win++) { 245 if ((sc->memalloc & (1 << win)) == 0) { 246 sc->memalloc |= (1 << win); 247 break; 248 } 249 } 250 if (win >= EXCA_MEM_WINS) 251 return (1); 252 if (((rman_get_start(res) >> EXCA_CARDMEM_ADDRX_SHIFT) & 0xff) != 0 && 253 (sc->flags & EXCA_HAS_MEMREG_WIN) == 0) { 254 device_printf(sc->dev, "Does not support mapping above 24M."); 255 return (1); 256 } 257 258 sc->mem[win].cardaddr = 0; 259 sc->mem[win].memt = rman_get_bustag(res); 260 sc->mem[win].memh = rman_get_bushandle(res); 261 sc->mem[win].addr = rman_get_start(res); 262 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1; 263 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1; 264 sc->mem[win].realsize = sc->mem[win].realsize - 265 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 266 sc->mem[win].offset = (long)(sc->mem[win].addr); 267 sc->mem[win].kind = kind; 268 DPRINTF("exca_mem_map window %d bus %x+%x+%lx card addr %x\n", 269 win, sc->mem[win].addr, sc->mem[win].size, 270 sc->mem[win].offset, sc->mem[win].cardaddr); 271 exca_do_mem_map(sc, win); 272 273 return (0); 274 } 275 276 /* 277 * Private helper function. This turns off a given memory map that is in 278 * use. We do this by just clearing the enable bit in the pcic. If we needed 279 * to make memory unmapping/mapping pairs faster, we would have to store 280 * more state information about the pcic and then use that to intelligently 281 * to the map/unmap. However, since we don't do that sort of thing often 282 * (generally just at configure time), it isn't a case worth optimizing. 283 */ 284 static void 285 exca_mem_unmap(struct exca_softc *sc, int window) 286 { 287 if (window < 0 || window >= EXCA_MEM_WINS) 288 panic("exca_mem_unmap: window out of range"); 289 290 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable); 291 sc->memalloc &= ~(1 << window); 292 } 293 294 /* 295 * Find the map that we're using to hold the resoruce. This works well 296 * so long as the client drivers don't do silly things like map the same 297 * area mutliple times, or map both common and attribute memory at the 298 * same time. This latter restriction is a bug. We likely should just 299 * store a pointer to the res in the mem[x] data structure. 300 */ 301 static int 302 exca_mem_findmap(struct exca_softc *sc, struct resource *res) 303 { 304 int win; 305 306 for (win = 0; win < EXCA_MEM_WINS; win++) { 307 if (sc->mem[win].memt == rman_get_bustag(res) && 308 sc->mem[win].addr == rman_get_start(res) && 309 sc->mem[win].size == rman_get_size(res)) 310 return (win); 311 } 312 return (-1); 313 } 314 315 /* 316 * Set the memory flag. This means that we are setting if the memory 317 * is coming from attribute memory or from common memory on the card. 318 * CIS entries are generally in attribute memory (although they can 319 * reside in common memory). Generally, this is the only use for attribute 320 * memory. However, some cards require their drivers to dance in both 321 * common and/or attribute memory and this interface (and setting the 322 * offset interface) exist for such cards. 323 */ 324 int 325 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags) 326 { 327 int win; 328 329 win = exca_mem_findmap(sc, res); 330 if (win < 0) { 331 device_printf(sc->dev, 332 "set_res_flags: specified resource not active\n"); 333 return (ENOENT); 334 } 335 336 sc->mem[win].kind = flags; 337 exca_do_mem_map(sc, win); 338 return (0); 339 } 340 341 /* 342 * Given a resource, go ahead and unmap it if we can find it in the 343 * resrouce list that's used. 344 */ 345 int 346 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res) 347 { 348 int win; 349 350 win = exca_mem_findmap(sc, res); 351 if (win < 0) 352 return (ENOENT); 353 exca_mem_unmap(sc, win); 354 return (0); 355 } 356 357 /* 358 * Set the offset of the memory. We use this for reading the CIS and 359 * frobbing the pccard's pccard registers (POR, etc). Some drivers 360 * need to access this functionality as well, since they have receive 361 * buffers defined in the attribute memory. Thankfully, these cards 362 * are few and fare between. Some cards also have common memory that 363 * is large and only map a small portion of it at a time (but these cards 364 * are rare, the more common case being to have just a small amount 365 * of common memory that the driver needs to bcopy data from in order to 366 * get at it. 367 */ 368 int 369 exca_mem_set_offset(struct exca_softc *sc, struct resource *res, 370 uint32_t cardaddr, uint32_t *deltap) 371 { 372 int win; 373 uint32_t delta; 374 375 win = exca_mem_findmap(sc, res); 376 if (win < 0) { 377 device_printf(sc->dev, 378 "set_memory_offset: specified resource not active\n"); 379 return (ENOENT); 380 } 381 sc->mem[win].cardaddr = cardaddr; 382 delta = cardaddr % EXCA_MEM_PAGESIZE; 383 if (deltap) 384 *deltap = delta; 385 cardaddr -= delta; 386 sc->mem[win].realsize = sc->mem[win].size + delta + 387 EXCA_MEM_PAGESIZE - 1; 388 sc->mem[win].realsize = sc->mem[win].realsize - 389 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE); 390 sc->mem[win].offset = cardaddr - sc->mem[win].addr; 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 /* 640 * see if there's a PCMCIA controller here 641 * Intel PCMCIA controllers use 0x82 and 0x83 642 * IBM clone chips use 0x88 and 0x89, apparently 643 */ 644 c = exca_getb(exca, EXCA_IDENT); 645 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO) 646 return (0); 647 if ((c & EXCA_IDENT_ZERO) != 0) 648 return (0); 649 switch (c & EXCA_IDENT_REV_MASK) { 650 /* 651 * 82365 or clones. 652 */ 653 case EXCA_IDENT_REV_I82365SLR0: 654 case EXCA_IDENT_REV_I82365SLR1: 655 exca->chipset = EXCA_I82365; 656 /* 657 * Check for Vadem chips by unlocking their extra 658 * registers and looking for valid ID. Bit 3 in 659 * the ID register is normally 0, except when 660 * EXCA_VADEMREV is set. Other bridges appear 661 * to ignore this frobbing. 662 */ 663 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 664 EXCA_VADEM_COOKIE1); 665 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX, 666 EXCA_VADEM_COOKIE2); 667 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 668 c = exca_getb(exca, EXCA_IDENT); 669 if (c & 0x08) { 670 switch (c & 7) { 671 case 1: 672 exca->chipset = EXCA_VG365; 673 break; 674 case 2: 675 exca->chipset = EXCA_VG465; 676 break; 677 case 3: 678 exca->chipset = EXCA_VG468; 679 break; 680 default: 681 exca->chipset = EXCA_VG469; 682 break; 683 } 684 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV); 685 break; 686 } 687 /* 688 * Check for RICOH RF5C[23]96 PCMCIA Controller 689 */ 690 c = exca_getb(exca, EXCA_RICOH_ID); 691 if (c == EXCA_RID_396) { 692 exca->chipset = EXCA_RF5C396; 693 break; 694 } else if (c == EXCA_RID_296) { 695 exca->chipset = EXCA_RF5C296; 696 break; 697 } 698 /* 699 * Check for Cirrus logic chips. 700 */ 701 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0); 702 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 703 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 704 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) { 705 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO); 706 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) { 707 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS) 708 exca->chipset = EXCA_PD6722; 709 else 710 exca->chipset = EXCA_PD6710; 711 break; 712 } 713 } 714 break; 715 716 case EXCA_IDENT_REV_I82365SLDF: 717 /* 718 * Intel i82365sl-DF step or maybe a vlsi 82c146 719 * we detected the vlsi case earlier, so if the controller 720 * isn't set, we know it is a i82365sl step D. 721 */ 722 exca->chipset = EXCA_I82365SL_DF; 723 break; 724 case EXCA_IDENT_REV_IBM1: 725 case EXCA_IDENT_REV_IBM2: 726 exca->chipset = EXCA_IBM; 727 break; 728 case EXCA_IDENT_REV_IBM_KING: 729 exca->chipset = EXCA_IBM_KING; 730 break; 731 default: 732 return (0); 733 } 734 return (1); 735 } 736 737 /* 738 * Probe the expected slots. We maybe should set the ID for each of these 739 * slots too while we're at it. But maybe that belongs to a separate 740 * function. 741 * 742 * The caller must guarantee that at least EXCA_NSLOTS are present in exca. 743 */ 744 int 745 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot, 746 bus_space_handle_t ioh) 747 { 748 int err; 749 int i; 750 751 err = ENXIO; 752 for (i = 0; i < EXCA_NSLOTS; i++) { 753 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE); 754 exca->getb = exca_io_getb; 755 exca->putb = exca_io_putb; 756 if (exca_valid_slot(&exca[i])) 757 err = 0; 758 } 759 return (err); 760 } 761 762 static int 763 exca_modevent(module_t mod, int cmd, void *arg) 764 { 765 return 0; 766 } 767 768 DEV_MODULE(exca, exca_modevent, NULL); 769 MODULE_VERSION(exca, 1); 770