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.
54 * $FreeBSD: src/sys/dev/exca/exca.c,v 1.19 2005/01/11 00:32:43 imp Exp $
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>
70 #include <bus/pccard/pccardreg.h>
71 #include <bus/pccard/pccardvar.h>
73 #include <dev/pccard/exca/excareg.h>
74 #include <dev/pccard/exca/excavar.h>
77 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args)
78 #define DPRINTF(fmt, args...) kprintf(fmt, ## args)
80 #define DEVPRINTF(dev, fmt, args...)
81 #define DPRINTF(fmt, args...)
85 static const char *chip_names[] =
88 "Intel i82365SL-A/B or clone",
89 "Intel i82365sl-DF step",
91 "Cirrus Logic PD6710",
92 "Cirrus logic PD6722",
93 "Cirrus Logic PD6729",
101 "IBM KING PCMCIA Controller"
105 static exca_getb_fn exca_mem_getb;
106 static exca_putb_fn exca_mem_putb;
107 static exca_getb_fn exca_io_getb;
108 static exca_putb_fn exca_io_putb;
112 #define EXCA_MEMINFO(NUM) { \
113 EXCA_SYSMEM_ADDR ## NUM ## _START_LSB, \
114 EXCA_SYSMEM_ADDR ## NUM ## _START_MSB, \
115 EXCA_SYSMEM_ADDR ## NUM ## _STOP_LSB, \
116 EXCA_SYSMEM_ADDR ## NUM ## _STOP_MSB, \
117 EXCA_SYSMEM_ADDR ## NUM ## _WIN, \
118 EXCA_CARDMEM_ADDR ## NUM ## _LSB, \
119 EXCA_CARDMEM_ADDR ## NUM ## _MSB, \
120 EXCA_ADDRWIN_ENABLE_MEM ## NUM, \
123 static struct mem_map_index_st {
124 int sysmem_start_lsb;
125 int sysmem_start_msb;
132 } mem_map_index[] = {
142 exca_mem_getb(struct exca_softc *sc, int reg)
144 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg));
148 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val)
150 bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val);
154 exca_io_getb(struct exca_softc *sc, int reg)
156 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset);
157 return (bus_space_read_1(sc->bst, sc->bsh, EXCA_REG_DATA));
161 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val)
163 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset);
164 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_DATA, val);
168 * Helper function. This will map the requested memory slot. We setup the
169 * map before we call this function. This is used to initially force the
170 * mapping, as well as later restore the mapping after it has been destroyed
171 * in some fashion (due to a power event typically).
174 exca_do_mem_map(struct exca_softc *sc, int win)
176 struct mem_map_index_st *map;
177 struct pccard_mem_handle *mem;
180 map = &mem_map_index[win];
182 offset = ((mem->cardaddr >> EXCA_CARDMEM_ADDRX_SHIFT) -
183 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT)) & 0x3fff;
184 exca_putb(sc, map->sysmem_start_lsb,
185 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT) & 0xff);
186 exca_putb(sc, map->sysmem_start_msb,
187 ((mem->addr >> (EXCA_SYSMEM_ADDRX_SHIFT + 8)) &
188 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
190 exca_putb(sc, map->sysmem_stop_lsb,
191 ((mem->addr + mem->realsize - 1) >>
192 EXCA_SYSMEM_ADDRX_SHIFT) & 0xff);
193 exca_putb(sc, map->sysmem_stop_msb,
194 (((mem->addr + mem->realsize - 1) >>
195 (EXCA_SYSMEM_ADDRX_SHIFT + 8)) &
196 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
197 EXCA_SYSMEM_ADDRX_STOP_MSB_WAIT2);
199 exca_putb(sc, map->sysmem_win,
200 (mem->addr >> EXCA_MEMREG_WIN_SHIFT) & 0xff);
202 exca_putb(sc, map->cardmem_lsb, offset & 0xff);
203 exca_putb(sc, map->cardmem_msb, (((offset >> 8) & 0xff) &
204 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK) |
205 ((mem->kind == PCCARD_A_MEM_ATTR) ?
206 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
209 if (mem->kind == PCCARD_A_MEM_ATTR)
210 kprintf("attribtue memory\n");
212 kprintf("common memory\n");
214 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->memenable |
215 EXCA_ADDRWIN_ENABLE_MEMCS16);
220 int r1, r2, r3, r4, r5, r6, r7;
221 r1 = exca_getb(sc, map->sysmem_start_msb);
222 r2 = exca_getb(sc, map->sysmem_start_lsb);
223 r3 = exca_getb(sc, map->sysmem_stop_msb);
224 r4 = exca_getb(sc, map->sysmem_stop_lsb);
225 r5 = exca_getb(sc, map->cardmem_msb);
226 r6 = exca_getb(sc, map->cardmem_lsb);
227 r7 = exca_getb(sc, map->sysmem_win);
228 kprintf("exca_do_mem_map win %d: %02x%02x %02x%02x "
229 "%02x%02x %02x (%08x+%06x.%06x*%06x)\n",
230 win, r1, r2, r3, r4, r5, r6, r7,
231 mem->addr, mem->size, mem->realsize,
238 * public interface to map a resource. kind is the type of memory to
239 * map (either common or attribute). Memory created via this interface
240 * starts out at card address 0. Since the only way to set this is
241 * to set it on a struct resource after it has been mapped, we're safe
242 * in maping this assumption. Note that resources can be remapped using
243 * exca_do_mem_map so that's how the card address can be set later.
246 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res)
250 for (win = 0; win < EXCA_MEM_WINS; win++) {
251 if ((sc->memalloc & (1 << win)) == 0) {
252 sc->memalloc |= (1 << win);
256 if (win >= EXCA_MEM_WINS)
258 if (((rman_get_start(res) >> EXCA_MEMREG_WIN_SHIFT) & 0xff) != 0 &&
259 (sc->flags & EXCA_HAS_MEMREG_WIN) == 0) {
260 device_printf(sc->dev, "Does not support mapping above 24M.");
264 sc->mem[win].cardaddr = 0;
265 sc->mem[win].memt = rman_get_bustag(res);
266 sc->mem[win].memh = rman_get_bushandle(res);
267 sc->mem[win].addr = rman_get_start(res);
268 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1;
269 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1;
270 sc->mem[win].realsize = sc->mem[win].realsize -
271 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
272 sc->mem[win].kind = kind;
273 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n",
274 win, sc->mem[win].addr, sc->mem[win].size, sc->mem[win].cardaddr);
275 exca_do_mem_map(sc, win);
281 * Private helper function. This turns off a given memory map that is in
282 * use. We do this by just clearing the enable bit in the pcic. If we needed
283 * to make memory unmapping/mapping pairs faster, we would have to store
284 * more state information about the pcic and then use that to intelligently
285 * to the map/unmap. However, since we don't do that sort of thing often
286 * (generally just at configure time), it isn't a case worth optimizing.
289 exca_mem_unmap(struct exca_softc *sc, int window)
291 if (window < 0 || window >= EXCA_MEM_WINS)
292 panic("exca_mem_unmap: window out of range");
294 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable);
295 sc->memalloc &= ~(1 << window);
299 * Find the map that we're using to hold the resoruce. This works well
300 * so long as the client drivers don't do silly things like map the same
301 * area mutliple times, or map both common and attribute memory at the
302 * same time. This latter restriction is a bug. We likely should just
303 * store a pointer to the res in the mem[x] data structure.
306 exca_mem_findmap(struct exca_softc *sc, struct resource *res)
310 for (win = 0; win < EXCA_MEM_WINS; win++) {
311 if (sc->mem[win].memt == rman_get_bustag(res) &&
312 sc->mem[win].addr == rman_get_start(res) &&
313 sc->mem[win].size == rman_get_size(res))
320 * Set the memory flag. This means that we are setting if the memory
321 * is coming from attribute memory or from common memory on the card.
322 * CIS entries are generally in attribute memory (although they can
323 * reside in common memory). Generally, this is the only use for attribute
324 * memory. However, some cards require their drivers to dance in both
325 * common and/or attribute memory and this interface (and setting the
326 * offset interface) exist for such cards.
329 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags)
333 win = exca_mem_findmap(sc, res);
335 device_printf(sc->dev,
336 "set_res_flags: specified resource not active\n");
340 sc->mem[win].kind = flags;
341 exca_do_mem_map(sc, win);
346 * Given a resource, go ahead and unmap it if we can find it in the
347 * resrouce list that's used.
350 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res)
354 win = exca_mem_findmap(sc, res);
357 exca_mem_unmap(sc, win);
362 * Set the offset of the memory. We use this for reading the CIS and
363 * frobbing the pccard's pccard registers (POR, etc). Some drivers
364 * need to access this functionality as well, since they have receive
365 * buffers defined in the attribute memory.
368 exca_mem_set_offset(struct exca_softc *sc, struct resource *res,
369 uint32_t cardaddr, uint32_t *deltap)
374 win = exca_mem_findmap(sc, res);
376 device_printf(sc->dev,
377 "set_memory_offset: specified resource not active\n");
380 sc->mem[win].cardaddr = rounddown2(cardaddr, EXCA_MEM_PAGESIZE);
381 delta = cardaddr % EXCA_MEM_PAGESIZE;
384 sc->mem[win].realsize = sc->mem[win].size + delta +
385 EXCA_MEM_PAGESIZE - 1;
386 sc->mem[win].realsize = sc->mem[win].realsize -
387 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
388 exca_do_mem_map(sc, win);
395 #define EXCA_IOINFO(NUM) { \
396 EXCA_IOADDR ## NUM ## _START_LSB, \
397 EXCA_IOADDR ## NUM ## _START_MSB, \
398 EXCA_IOADDR ## NUM ## _STOP_LSB, \
399 EXCA_IOADDR ## NUM ## _STOP_MSB, \
400 EXCA_ADDRWIN_ENABLE_IO ## NUM, \
401 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \
402 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \
403 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \
404 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \
406 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \
407 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
408 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \
409 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
410 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \
414 static struct io_map_index_st {
421 int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */
429 exca_do_io_map(struct exca_softc *sc, int win)
431 struct io_map_index_st *map;
433 struct pccard_io_handle *io;
435 map = &io_map_index[win];
437 exca_putb(sc, map->start_lsb, io->addr & 0xff);
438 exca_putb(sc, map->start_msb, (io->addr >> 8) & 0xff);
440 exca_putb(sc, map->stop_lsb, (io->addr + io->size - 1) & 0xff);
441 exca_putb(sc, map->stop_msb, ((io->addr + io->size - 1) >> 8) & 0xff);
443 exca_clrb(sc, EXCA_IOCTL, map->ioctlmask);
444 exca_setb(sc, EXCA_IOCTL, map->ioctlbits[io->width]);
446 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->ioenable);
450 r1 = exca_getb(sc, map->start_msb);
451 r2 = exca_getb(sc, map->start_lsb);
452 r3 = exca_getb(sc, map->stop_msb);
453 r4 = exca_getb(sc, map->stop_lsb);
454 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x "
455 "(%08x+%08x)\n", win, r1, r2, r3, r4,
462 exca_io_map(struct exca_softc *sc, int width, struct resource *r)
466 static char *width_names[] = { "auto", "io8", "io16"};
468 for (win=0; win < EXCA_IO_WINS; win++) {
469 if ((sc->ioalloc & (1 << win)) == 0) {
470 sc->ioalloc |= (1 << win);
474 if (win >= EXCA_IO_WINS)
477 sc->io[win].iot = rman_get_bustag(r);
478 sc->io[win].ioh = rman_get_bushandle(r);
479 sc->io[win].addr = rman_get_start(r);
480 sc->io[win].size = rman_get_end(r) - sc->io[win].addr + 1;
481 sc->io[win].flags = 0;
482 sc->io[win].width = width;
483 DPRINTF("exca_io_map window %d %s port %x+%x\n",
484 win, width_names[width], sc->io[win].addr,
486 exca_do_io_map(sc, win);
492 exca_io_unmap(struct exca_softc *sc, int window)
494 if (window >= EXCA_IO_WINS)
495 panic("exca_io_unmap: window out of range");
497 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, io_map_index[window].ioenable);
499 sc->ioalloc &= ~(1 << window);
501 sc->io[window].iot = 0;
502 sc->io[window].ioh = 0;
503 sc->io[window].addr = 0;
504 sc->io[window].size = 0;
505 sc->io[window].flags = 0;
506 sc->io[window].width = 0;
510 exca_io_findmap(struct exca_softc *sc, struct resource *res)
514 for (win = 0; win < EXCA_IO_WINS; win++) {
515 if (sc->io[win].iot == rman_get_bustag(res) &&
516 sc->io[win].addr == rman_get_start(res) &&
517 sc->io[win].size == rman_get_size(res))
525 exca_io_unmap_res(struct exca_softc *sc, struct resource *res)
529 win = exca_io_findmap(sc, res);
532 exca_io_unmap(sc, win);
539 * If interrupts are enabled, then we should be able to just wait for
540 * an interrupt routine to wake us up. Busy waiting shouldn't be
541 * necessary. Sadly, not all legacy ISA cards support an interrupt
542 * for the busy state transitions, at least according to their datasheets,
543 * so we busy wait a while here..
546 exca_wait_ready(struct exca_softc *sc)
549 DEVPRINTF(sc->dev, "exca_wait_ready: status 0x%02x\n",
550 exca_getb(sc, EXCA_IF_STATUS));
551 for (i = 0; i < 10000; i++) {
552 if (exca_getb(sc, EXCA_IF_STATUS) & EXCA_IF_STATUS_READY)
556 device_printf(sc->dev, "ready never happened, status = %02x\n",
557 exca_getb(sc, EXCA_IF_STATUS));
561 * Reset the card. Ideally, we'd do a lot of this via interrupts.
562 * However, many PC Cards will deassert the ready signal. This means
563 * that they are asserting an interrupt. This makes it hard to
564 * do anything but a busy wait here. One could argue that these
565 * such cards are broken, or that the bridge that allows this sort
566 * of interrupt through isn't quite what you'd want (and may be a standards
567 * violation). However, such arguing would leave a huge class of pc cards
568 * and bridges out of reach for use in the system.
570 * Maybe I should reevaluate the above based on the power bug I fixed
574 exca_reset(struct exca_softc *sc, device_t child)
578 /* enable socket i/o */
579 exca_setb(sc, EXCA_PWRCTL, EXCA_PWRCTL_OE);
581 exca_putb(sc, EXCA_INTR, EXCA_INTR_ENABLE);
582 /* hold reset for 30ms */
584 /* clear the reset flag */
585 exca_setb(sc, EXCA_INTR, EXCA_INTR_RESET);
586 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
591 /* disable all address windows */
592 exca_putb(sc, EXCA_ADDRWIN_ENABLE, 0);
594 exca_setb(sc, EXCA_INTR, EXCA_INTR_CARDTYPE_IO);
595 DEVPRINTF(sc->dev, "card type is io\n");
597 /* reinstall all the memory and io mappings */
598 for (win = 0; win < EXCA_MEM_WINS; ++win)
599 if (sc->memalloc & (1 << win))
600 exca_do_mem_map(sc, win);
601 for (win = 0; win < EXCA_IO_WINS; ++win)
602 if (sc->ioalloc & (1 << win))
603 exca_do_io_map(sc, win);
607 * Initialize the exca_softc data structure for the first time.
610 exca_init(struct exca_softc *sc, device_t dev,
611 bus_space_tag_t bst, bus_space_handle_t bsh, uint32_t offset)
620 sc->getb = exca_mem_getb;
621 sc->putb = exca_mem_putb;
625 * Is this socket valid?
628 exca_valid_slot(struct exca_softc *exca)
632 /* Assume the worst */
633 exca->chipset = EXCA_BOGUS;
636 * see if there's a PCMCIA controller here
637 * Intel PCMCIA controllers use 0x82 and 0x83
638 * IBM clone chips use 0x88 and 0x89, apparently
640 c = exca_getb(exca, EXCA_IDENT);
641 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO)
643 if ((c & EXCA_IDENT_ZERO) != 0)
645 switch (c & EXCA_IDENT_REV_MASK) {
649 case EXCA_IDENT_REV_I82365SLR0:
650 case EXCA_IDENT_REV_I82365SLR1:
651 exca->chipset = EXCA_I82365;
653 * Check for Vadem chips by unlocking their extra
654 * registers and looking for valid ID. Bit 3 in
655 * the ID register is normally 0, except when
656 * EXCA_VADEMREV is set. Other bridges appear
657 * to ignore this frobbing.
659 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
661 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
663 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
664 c = exca_getb(exca, EXCA_IDENT);
668 exca->chipset = EXCA_VG365;
671 exca->chipset = EXCA_VG465;
674 exca->chipset = EXCA_VG468;
677 exca->chipset = EXCA_VG469;
680 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
684 * Check for RICOH RF5C[23]96 PCMCIA Controller
686 c = exca_getb(exca, EXCA_RICOH_ID);
687 if (c == EXCA_RID_396) {
688 exca->chipset = EXCA_RF5C396;
690 } else if (c == EXCA_RID_296) {
691 exca->chipset = EXCA_RF5C296;
695 * Check for Cirrus logic chips.
697 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0);
698 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
699 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) ==
700 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) {
701 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
702 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
703 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS)
704 exca->chipset = EXCA_PD6722;
706 exca->chipset = EXCA_PD6710;
712 case EXCA_IDENT_REV_I82365SLDF:
714 * Intel i82365sl-DF step or maybe a vlsi 82c146
715 * we detected the vlsi case earlier, so if the controller
716 * isn't set, we know it is a i82365sl step D.
718 exca->chipset = EXCA_I82365SL_DF;
720 case EXCA_IDENT_REV_IBM1:
721 case EXCA_IDENT_REV_IBM2:
722 exca->chipset = EXCA_IBM;
724 case EXCA_IDENT_REV_IBM_KING:
725 exca->chipset = EXCA_IBM_KING;
734 * Probe the expected slots. We maybe should set the ID for each of these
735 * slots too while we're at it. But maybe that belongs to a separate
738 * The caller must guarantee that at least EXCA_NSLOTS are present in exca.
741 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot,
742 bus_space_handle_t ioh)
748 for (i = 0; i < EXCA_NSLOTS; i++) {
749 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE);
750 exca->getb = exca_io_getb;
751 exca->putb = exca_io_putb;
752 if (exca_valid_slot(&exca[i]))
759 exca_insert(struct exca_softc *exca)
761 if (exca->pccarddev != NULL) {
762 if (CARD_ATTACH_CARD(exca->pccarddev) != 0)
763 device_printf(exca->dev,
764 "PC Card card activation failed\n");
766 device_printf(exca->dev,
767 "PC Card inserted, but no pccard bus.\n");
773 exca_removal(struct exca_softc *exca)
775 if (exca->pccarddev != NULL)
776 CARD_DETACH_CARD(exca->pccarddev);
780 exca_activate_resource(struct exca_softc *exca, device_t child, int type,
781 int rid, struct resource *res)
784 if (!(rman_get_flags(res) & RF_ACTIVE)) { /* not already activated */
787 err = exca_io_map(exca, PCCARD_WIDTH_AUTO, res);
790 err = exca_mem_map(exca, PCCARD_A_MEM_COM, res);
800 return (BUS_ACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
805 exca_deactivate_resource(struct exca_softc *exca, device_t child, int type,
806 int rid, struct resource *res)
808 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */
811 if (exca_io_unmap_res(exca, res))
815 if (exca_mem_unmap_res(exca, res))
820 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
825 static struct resource *
826 exca_alloc_resource(struct exca_softc *sc, device_t child, int type, int *rid,
827 u_long start, u_long end, u_long count, uint flags)
829 struct resource *res = NULL;
834 if (start < cbb_start_mem)
835 start = cbb_start_mem;
838 flags = (flags & ~RF_ALIGNMENT_MASK) |
839 rman_make_alignment_flags(CBB_MEMALIGN);
842 if (start < cbb_start_16_io)
843 start = cbb_start_16_io;
848 tmp = rman_get_start(sc->irq_res);
849 if (start > tmp || end < tmp || count != 1) {
850 device_printf(child, "requested interrupt %ld-%ld,"
851 "count = %ld not supported by cbb\n",
855 flags |= RF_SHAREABLE;
856 start = end = rman_get_start(sc->irq_res);
859 res = BUS_ALLOC_RESOURCE(up, child, type, rid,
860 start, end, count, flags & ~RF_ACTIVE);
863 cbb_insert_res(sc, res, type, *rid);
864 if (flags & RF_ACTIVE) {
865 if (bus_activate_resource(child, type, *rid, res) != 0) {
866 bus_release_resource(child, type, *rid, res);
875 exca_release_resource(struct exca_softc *sc, device_t child, int type,
876 int rid, struct resource *res)
880 if (rman_get_flags(res) & RF_ACTIVE) {
881 error = bus_deactivate_resource(child, type, rid, res);
885 cbb_remove_res(sc, res);
886 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
892 exca_modevent(module_t mod, int cmd, void *arg)
897 DEV_MODULE(exca, exca_modevent, NULL);
898 MODULE_VERSION(exca, 1);