2 * Copyright (c) 2002-2005 M Warner Losh. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
24 * This software may be derived from NetBSD i82365.c and other files with
25 * the following copyright:
27 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
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.
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.
55 #include <sys/cdefs.h>
56 __FBSDID("$FreeBSD$");
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>
67 #include <sys/mutex.h>
71 #include <machine/bus.h>
73 #include <machine/resource.h>
75 #include <dev/pccard/pccardreg.h>
76 #include <dev/pccard/pccardvar.h>
78 #include <dev/exca/excareg.h>
79 #include <dev/exca/excavar.h>
82 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args)
83 #define DPRINTF(fmt, args...) printf(fmt, ## args)
85 #define DEVPRINTF(dev, fmt, args...)
86 #define DPRINTF(fmt, args...)
89 static const char *chip_names[] =
92 "Intel i82365SL-A/B or clone",
93 "Intel i82365sl-DF step",
95 "Cirrus Logic PD6710",
96 "Cirrus logic PD6722",
97 "Cirrus Logic PD6729",
105 "IBM KING PCMCIA Controller"
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;
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, \
126 static struct mem_map_index_st {
127 int sysmem_start_lsb;
128 int sysmem_start_msb;
135 } mem_map_index[] = {
145 exca_mem_getb(struct exca_softc *sc, int reg)
147 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg));
151 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val)
153 bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val);
157 exca_io_getb(struct exca_softc *sc, int reg)
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));
164 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val)
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);
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).
177 exca_do_mem_map(struct exca_softc *sc, int win)
179 struct mem_map_index_st *map;
180 struct pccard_mem_handle *mem;
185 map = &mem_map_index[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);
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);
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);
212 DPRINTF("%s %d-bit memory",
213 mem->kind & PCCARD_MEM_ATTR ? "attribute" : "common",
214 mem->kind & PCCARD_MEM_16BIT ? 16 : 8);
215 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->memenable |
216 EXCA_ADDRWIN_ENABLE_MEMCS16);
221 int r1, r2, r3, r4, r5, r6, r7;
222 r1 = exca_getb(sc, map->sysmem_start_msb);
223 r2 = exca_getb(sc, map->sysmem_start_lsb);
224 r3 = exca_getb(sc, map->sysmem_stop_msb);
225 r4 = exca_getb(sc, map->sysmem_stop_lsb);
226 r5 = exca_getb(sc, map->cardmem_msb);
227 r6 = exca_getb(sc, map->cardmem_lsb);
228 r7 = exca_getb(sc, map->sysmem_win);
229 printf("exca_do_mem_map win %d: %#02x%#02x %#02x%#02x "
230 "%#02x%#02x %#02x (%#08x+%#06x.%#06x*%#06x) flags %#x\n",
231 win, r1, r2, r3, r4, r5, r6, r7,
232 mem->addr, mem->size, mem->realsize,
233 mem->cardaddr, mem->kind);
239 * public interface to map a resource. kind is the type of memory to
240 * map (either common or attribute). Memory created via this interface
241 * starts out at card address 0. Since the only way to set this is
242 * to set it on a struct resource after it has been mapped, we're safe
243 * in maping this assumption. Note that resources can be remapped using
244 * exca_do_mem_map so that's how the card address can be set later.
247 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res)
251 for (win = 0; win < EXCA_MEM_WINS; win++) {
252 if ((sc->memalloc & (1 << win)) == 0) {
253 sc->memalloc |= (1 << win);
257 if (win >= EXCA_MEM_WINS)
259 if (sc->flags & EXCA_HAS_MEMREG_WIN) {
261 if (rman_get_start(res) >> (EXCA_MEMREG_WIN_SHIFT + 8) != 0) {
262 device_printf(sc->dev,
263 "Does not support mapping above 4GB.");
268 if (rman_get_start(res) >> EXCA_MEMREG_WIN_SHIFT != 0) {
269 device_printf(sc->dev,
270 "Does not support mapping above 16M.");
275 sc->mem[win].cardaddr = 0;
276 sc->mem[win].memt = rman_get_bustag(res);
277 sc->mem[win].memh = rman_get_bushandle(res);
278 sc->mem[win].addr = rman_get_start(res);
279 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1;
280 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1;
281 sc->mem[win].realsize = sc->mem[win].realsize -
282 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
283 sc->mem[win].kind = kind;
284 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n",
285 win, sc->mem[win].addr, sc->mem[win].size, sc->mem[win].cardaddr);
286 exca_do_mem_map(sc, win);
292 * Private helper function. This turns off a given memory map that is in
293 * use. We do this by just clearing the enable bit in the pcic. If we needed
294 * to make memory unmapping/mapping pairs faster, we would have to store
295 * more state information about the pcic and then use that to intelligently
296 * to the map/unmap. However, since we don't do that sort of thing often
297 * (generally just at configure time), it isn't a case worth optimizing.
300 exca_mem_unmap(struct exca_softc *sc, int window)
302 if (window < 0 || window >= EXCA_MEM_WINS)
303 panic("exca_mem_unmap: window out of range");
305 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable);
306 sc->memalloc &= ~(1 << window);
310 * Find the map that we're using to hold the resource. This works well
311 * so long as the client drivers don't do silly things like map the same
312 * area mutliple times, or map both common and attribute memory at the
313 * same time. This latter restriction is a bug. We likely should just
314 * store a pointer to the res in the mem[x] data structure.
317 exca_mem_findmap(struct exca_softc *sc, struct resource *res)
321 for (win = 0; win < EXCA_MEM_WINS; win++) {
322 if (sc->mem[win].memt == rman_get_bustag(res) &&
323 sc->mem[win].addr == rman_get_start(res) &&
324 sc->mem[win].size == rman_get_size(res))
331 * Set the memory flag. This means that we are setting if the memory
332 * is coming from attribute memory or from common memory on the card.
333 * CIS entries are generally in attribute memory (although they can
334 * reside in common memory). Generally, this is the only use for attribute
335 * memory. However, some cards require their drivers to dance in both
336 * common and/or attribute memory and this interface (and setting the
337 * offset interface) exist for such cards.
340 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags)
344 win = exca_mem_findmap(sc, res);
346 device_printf(sc->dev,
347 "set_res_flags: specified resource not active\n");
353 case PCCARD_A_MEM_ATTR:
354 sc->mem[win].kind |= PCCARD_MEM_ATTR;
356 case PCCARD_A_MEM_COM:
357 sc->mem[win].kind &= ~PCCARD_MEM_ATTR;
359 case PCCARD_A_MEM_16BIT:
360 sc->mem[win].kind |= PCCARD_MEM_16BIT;
362 case PCCARD_A_MEM_8BIT:
363 sc->mem[win].kind &= ~PCCARD_MEM_16BIT;
366 exca_do_mem_map(sc, win);
371 * Given a resource, go ahead and unmap it if we can find it in the
372 * resrouce list that's used.
375 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res)
379 win = exca_mem_findmap(sc, res);
382 exca_mem_unmap(sc, win);
387 * Set the offset of the memory. We use this for reading the CIS and
388 * frobbing the pccard's pccard registers (CCR, etc). Some drivers
389 * need to access arbitrary attribute and common memory during their
390 * initialization and operation.
393 exca_mem_set_offset(struct exca_softc *sc, struct resource *res,
394 uint32_t cardaddr, uint32_t *deltap)
399 win = exca_mem_findmap(sc, res);
401 device_printf(sc->dev,
402 "set_memory_offset: specified resource not active\n");
405 sc->mem[win].cardaddr = cardaddr & ~(EXCA_MEM_PAGESIZE - 1);
406 delta = cardaddr % EXCA_MEM_PAGESIZE;
409 sc->mem[win].realsize = sc->mem[win].size + delta +
410 EXCA_MEM_PAGESIZE - 1;
411 sc->mem[win].realsize = sc->mem[win].realsize -
412 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
413 exca_do_mem_map(sc, win);
420 #define EXCA_IOINFO(NUM) { \
421 EXCA_IOADDR ## NUM ## _START_LSB, \
422 EXCA_IOADDR ## NUM ## _START_MSB, \
423 EXCA_IOADDR ## NUM ## _STOP_LSB, \
424 EXCA_IOADDR ## NUM ## _STOP_MSB, \
425 EXCA_ADDRWIN_ENABLE_IO ## NUM, \
426 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \
427 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \
428 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \
429 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \
431 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \
432 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
433 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \
434 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
435 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \
439 static struct io_map_index_st {
446 int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */
454 exca_do_io_map(struct exca_softc *sc, int win)
456 struct io_map_index_st *map;
458 struct pccard_io_handle *io;
460 map = &io_map_index[win];
462 exca_putb(sc, map->start_lsb, io->addr & 0xff);
463 exca_putb(sc, map->start_msb, (io->addr >> 8) & 0xff);
465 exca_putb(sc, map->stop_lsb, (io->addr + io->size - 1) & 0xff);
466 exca_putb(sc, map->stop_msb, ((io->addr + io->size - 1) >> 8) & 0xff);
468 exca_clrb(sc, EXCA_IOCTL, map->ioctlmask);
469 exca_setb(sc, EXCA_IOCTL, map->ioctlbits[io->width]);
471 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->ioenable);
475 r1 = exca_getb(sc, map->start_msb);
476 r2 = exca_getb(sc, map->start_lsb);
477 r3 = exca_getb(sc, map->stop_msb);
478 r4 = exca_getb(sc, map->stop_lsb);
479 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x "
480 "(%08x+%08x)\n", win, r1, r2, r3, r4,
487 exca_io_map(struct exca_softc *sc, int width, struct resource *r)
491 static char *width_names[] = { "auto", "io8", "io16"};
493 for (win=0; win < EXCA_IO_WINS; win++) {
494 if ((sc->ioalloc & (1 << win)) == 0) {
495 sc->ioalloc |= (1 << win);
499 if (win >= EXCA_IO_WINS)
502 sc->io[win].iot = rman_get_bustag(r);
503 sc->io[win].ioh = rman_get_bushandle(r);
504 sc->io[win].addr = rman_get_start(r);
505 sc->io[win].size = rman_get_end(r) - sc->io[win].addr + 1;
506 sc->io[win].flags = 0;
507 sc->io[win].width = width;
508 DPRINTF("exca_io_map window %d %s port %x+%x\n",
509 win, width_names[width], sc->io[win].addr,
511 exca_do_io_map(sc, win);
517 exca_io_unmap(struct exca_softc *sc, int window)
519 if (window >= EXCA_IO_WINS)
520 panic("exca_io_unmap: window out of range");
522 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, io_map_index[window].ioenable);
524 sc->ioalloc &= ~(1 << window);
526 sc->io[window].iot = 0;
527 sc->io[window].ioh = 0;
528 sc->io[window].addr = 0;
529 sc->io[window].size = 0;
530 sc->io[window].flags = 0;
531 sc->io[window].width = 0;
535 exca_io_findmap(struct exca_softc *sc, struct resource *res)
539 for (win = 0; win < EXCA_IO_WINS; win++) {
540 if (sc->io[win].iot == rman_get_bustag(res) &&
541 sc->io[win].addr == rman_get_start(res) &&
542 sc->io[win].size == rman_get_size(res))
550 exca_io_unmap_res(struct exca_softc *sc, struct resource *res)
554 win = exca_io_findmap(sc, res);
557 exca_io_unmap(sc, win);
564 * If interrupts are enabled, then we should be able to just wait for
565 * an interrupt routine to wake us up. Busy waiting shouldn't be
566 * necessary. Sadly, not all legacy ISA cards support an interrupt
567 * for the busy state transitions, at least according to their datasheets,
568 * so we busy wait a while here..
571 exca_wait_ready(struct exca_softc *sc)
574 DEVPRINTF(sc->dev, "exca_wait_ready: status 0x%02x\n",
575 exca_getb(sc, EXCA_IF_STATUS));
576 for (i = 0; i < 10000; i++) {
577 if (exca_getb(sc, EXCA_IF_STATUS) & EXCA_IF_STATUS_READY)
581 device_printf(sc->dev, "ready never happened, status = %02x\n",
582 exca_getb(sc, EXCA_IF_STATUS));
586 * Reset the card. Ideally, we'd do a lot of this via interrupts.
587 * However, many PC Cards will deassert the ready signal. This means
588 * that they are asserting an interrupt. This makes it hard to
589 * do anything but a busy wait here. One could argue that these
590 * such cards are broken, or that the bridge that allows this sort
591 * of interrupt through isn't quite what you'd want (and may be a standards
592 * violation). However, such arguing would leave a huge class of PC Cards
593 * and bridges out of reach for use in the system.
595 * Maybe I should reevaluate the above based on the power bug I fixed
599 exca_reset(struct exca_softc *sc, device_t child)
603 /* enable socket i/o */
604 exca_setb(sc, EXCA_PWRCTL, EXCA_PWRCTL_OE);
606 exca_putb(sc, EXCA_INTR, EXCA_INTR_ENABLE);
607 /* hold reset for 30ms */
609 /* clear the reset flag */
610 exca_setb(sc, EXCA_INTR, EXCA_INTR_RESET);
611 /* wait 20ms as per PC Card standard (r2.01) section 4.3.6 */
616 /* disable all address windows */
617 exca_putb(sc, EXCA_ADDRWIN_ENABLE, 0);
619 exca_setb(sc, EXCA_INTR, EXCA_INTR_CARDTYPE_IO);
620 DEVPRINTF(sc->dev, "card type is io\n");
622 /* reinstall all the memory and io mappings */
623 for (win = 0; win < EXCA_MEM_WINS; ++win)
624 if (sc->memalloc & (1 << win))
625 exca_do_mem_map(sc, win);
626 for (win = 0; win < EXCA_IO_WINS; ++win)
627 if (sc->ioalloc & (1 << win))
628 exca_do_io_map(sc, win);
632 * Initialize the exca_softc data structure for the first time.
635 exca_init(struct exca_softc *sc, device_t dev,
636 bus_space_tag_t bst, bus_space_handle_t bsh, uint32_t offset)
645 sc->getb = exca_mem_getb;
646 sc->putb = exca_mem_putb;
650 * Is this socket valid?
653 exca_valid_slot(struct exca_softc *exca)
657 /* Assume the worst */
658 exca->chipset = EXCA_BOGUS;
661 * see if there's a PCMCIA controller here
662 * Intel PCMCIA controllers use 0x82 and 0x83
663 * IBM clone chips use 0x88 and 0x89, apparently
665 c = exca_getb(exca, EXCA_IDENT);
666 DEVPRINTF(exca->dev, "Ident is %x\n", c);
667 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO)
669 if ((c & EXCA_IDENT_ZERO) != 0)
671 switch (c & EXCA_IDENT_REV_MASK) {
675 case EXCA_IDENT_REV_I82365SLR0:
676 case EXCA_IDENT_REV_I82365SLR1:
677 exca->chipset = EXCA_I82365;
679 * Check for Vadem chips by unlocking their extra
680 * registers and looking for valid ID. Bit 3 in
681 * the ID register is normally 0, except when
682 * EXCA_VADEMREV is set. Other bridges appear
683 * to ignore this frobbing.
685 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
687 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
689 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
690 c = exca_getb(exca, EXCA_IDENT);
694 exca->chipset = EXCA_VG365;
697 exca->chipset = EXCA_VG465;
700 exca->chipset = EXCA_VG468;
703 exca->chipset = EXCA_VG469;
706 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
710 * Check for RICOH RF5C[23]96 PCMCIA Controller
712 c = exca_getb(exca, EXCA_RICOH_ID);
713 if (c == EXCA_RID_396) {
714 exca->chipset = EXCA_RF5C396;
716 } else if (c == EXCA_RID_296) {
717 exca->chipset = EXCA_RF5C296;
721 * Check for Cirrus logic chips.
723 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0);
724 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
725 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) ==
726 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) {
727 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
728 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
729 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS)
730 exca->chipset = EXCA_PD6722;
732 exca->chipset = EXCA_PD6710;
738 case EXCA_IDENT_REV_I82365SLDF:
740 * Intel i82365sl-DF step or maybe a vlsi 82c146
741 * we detected the vlsi case earlier, so if the controller
742 * isn't set, we know it is a i82365sl step D.
744 exca->chipset = EXCA_I82365SL_DF;
746 case EXCA_IDENT_REV_IBM1:
747 case EXCA_IDENT_REV_IBM2:
748 exca->chipset = EXCA_IBM;
750 case EXCA_IDENT_REV_IBM_KING:
751 exca->chipset = EXCA_IBM_KING;
760 * Probe the expected slots. We maybe should set the ID for each of these
761 * slots too while we're at it. But maybe that belongs to a separate
764 * The caller must guarantee that at least EXCA_NSLOTS are present in exca.
767 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot,
768 bus_space_handle_t ioh)
774 for (i = 0; i < EXCA_NSLOTS; i++) {
775 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE);
776 exca->getb = exca_io_getb;
777 exca->putb = exca_io_putb;
778 if (exca_valid_slot(&exca[i])) {
779 device_set_desc(dev, chip_names[exca[i].chipset]);
787 exca_insert(struct exca_softc *exca)
789 if (device_is_attached(exca->pccarddev)) {
790 if (CARD_ATTACH_CARD(exca->pccarddev) != 0)
791 device_printf(exca->dev,
792 "PC Card card activation failed\n");
794 device_printf(exca->dev,
795 "PC Card inserted, but no pccard bus.\n");
801 exca_removal(struct exca_softc *exca)
803 if (device_is_attached(exca->pccarddev))
804 CARD_DETACH_CARD(exca->pccarddev);
808 exca_activate_resource(struct exca_softc *exca, device_t child, int type,
809 int rid, struct resource *res)
813 if (rman_get_flags(res) & RF_ACTIVE)
815 err = BUS_ACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
821 err = exca_io_map(exca, PCCARD_WIDTH_AUTO, res);
824 err = exca_mem_map(exca, 0, res);
828 BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
834 exca_deactivate_resource(struct exca_softc *exca, device_t child, int type,
835 int rid, struct resource *res)
837 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */
840 if (exca_io_unmap_res(exca, res))
844 if (exca_mem_unmap_res(exca, res))
849 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
854 static struct resource *
855 exca_alloc_resource(struct exca_softc *sc, device_t child, int type, int *rid,
856 u_long start, u_long end, u_long count, uint flags)
858 struct resource *res = NULL;
863 if (start < cbb_start_mem)
864 start = cbb_start_mem;
867 flags = (flags & ~RF_ALIGNMENT_MASK) |
868 rman_make_alignment_flags(CBB_MEMALIGN);
871 if (start < cbb_start_16_io)
872 start = cbb_start_16_io;
877 tmp = rman_get_start(sc->irq_res);
878 if (start > tmp || end < tmp || count != 1) {
879 device_printf(child, "requested interrupt %ld-%ld,"
880 "count = %ld not supported by cbb\n",
884 flags |= RF_SHAREABLE;
885 start = end = rman_get_start(sc->irq_res);
888 res = BUS_ALLOC_RESOURCE(up, child, type, rid,
889 start, end, count, flags & ~RF_ACTIVE);
892 cbb_insert_res(sc, res, type, *rid);
893 if (flags & RF_ACTIVE) {
894 if (bus_activate_resource(child, type, *rid, res) != 0) {
895 bus_release_resource(child, type, *rid, res);
904 exca_release_resource(struct exca_softc *sc, device_t child, int type,
905 int rid, struct resource *res)
909 if (rman_get_flags(res) & RF_ACTIVE) {
910 error = bus_deactivate_resource(child, type, rid, res);
914 cbb_remove_res(sc, res);
915 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
921 exca_modevent(module_t mod, int cmd, void *arg)
926 DEV_MODULE(exca, exca_modevent, NULL);
927 MODULE_VERSION(exca, 1);