2 * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD
4 * Copyright (c) 2002-2005 M. Warner Losh <imp@FreeBSD.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
26 * This software may be derived from NetBSD i82365.c and other files with
27 * the following copyright:
29 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
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.
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.
57 #include <sys/cdefs.h>
58 __FBSDID("$FreeBSD$");
60 #include <sys/param.h>
61 #include <sys/systm.h>
62 #include <sys/condvar.h>
63 #include <sys/errno.h>
64 #include <sys/kernel.h>
65 #include <sys/malloc.h>
66 #include <sys/queue.h>
67 #include <sys/module.h>
69 #include <sys/mutex.h>
73 #include <machine/bus.h>
75 #include <machine/resource.h>
77 #include <dev/pccard/pccardreg.h>
78 #include <dev/pccard/pccardvar.h>
80 #include <dev/exca/excareg.h>
81 #include <dev/exca/excavar.h>
84 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args)
85 #define DPRINTF(fmt, args...) printf(fmt, ## args)
87 #define DEVPRINTF(dev, fmt, args...)
88 #define DPRINTF(fmt, args...)
91 static const char *chip_names[] =
94 "Intel i82365SL-A/B or clone",
95 "Intel i82365sl-DF step",
97 "Cirrus Logic PD6710",
98 "Cirrus logic PD6722",
99 "Cirrus Logic PD6729",
107 "IBM KING PCMCIA Controller"
110 static exca_getb_fn exca_mem_getb;
111 static exca_putb_fn exca_mem_putb;
112 static exca_getb_fn exca_io_getb;
113 static exca_putb_fn exca_io_putb;
117 #define EXCA_MEMINFO(NUM) { \
118 EXCA_SYSMEM_ADDR ## NUM ## _START_LSB, \
119 EXCA_SYSMEM_ADDR ## NUM ## _START_MSB, \
120 EXCA_SYSMEM_ADDR ## NUM ## _STOP_LSB, \
121 EXCA_SYSMEM_ADDR ## NUM ## _STOP_MSB, \
122 EXCA_SYSMEM_ADDR ## NUM ## _WIN, \
123 EXCA_CARDMEM_ADDR ## NUM ## _LSB, \
124 EXCA_CARDMEM_ADDR ## NUM ## _MSB, \
125 EXCA_ADDRWIN_ENABLE_MEM ## NUM, \
128 static struct mem_map_index_st {
129 int sysmem_start_lsb;
130 int sysmem_start_msb;
137 } mem_map_index[] = {
147 exca_mem_getb(struct exca_softc *sc, int reg)
149 return (bus_space_read_1(sc->bst, sc->bsh, sc->offset + reg));
153 exca_mem_putb(struct exca_softc *sc, int reg, uint8_t val)
155 bus_space_write_1(sc->bst, sc->bsh, sc->offset + reg, val);
159 exca_io_getb(struct exca_softc *sc, int reg)
161 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset);
162 return (bus_space_read_1(sc->bst, sc->bsh, EXCA_REG_DATA));
166 exca_io_putb(struct exca_softc *sc, int reg, uint8_t val)
168 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_INDEX, reg + sc->offset);
169 bus_space_write_1(sc->bst, sc->bsh, EXCA_REG_DATA, val);
173 * Helper function. This will map the requested memory slot. We setup the
174 * map before we call this function. This is used to initially force the
175 * mapping, as well as later restore the mapping after it has been destroyed
176 * in some fashion (due to a power event typically).
179 exca_do_mem_map(struct exca_softc *sc, int win)
181 struct mem_map_index_st *map;
182 struct pccard_mem_handle *mem;
187 map = &mem_map_index[win];
189 mem16 = (mem->kind & PCCARD_MEM_16BIT) ?
190 EXCA_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT : 0;
191 attrmem = (mem->kind & PCCARD_MEM_ATTR) ?
192 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0;
193 offset = ((mem->cardaddr >> EXCA_CARDMEM_ADDRX_SHIFT) -
194 (mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT)) & 0x3fff;
195 exca_putb(sc, map->sysmem_start_lsb,
196 mem->addr >> EXCA_SYSMEM_ADDRX_SHIFT);
197 exca_putb(sc, map->sysmem_start_msb,
198 ((mem->addr >> (EXCA_SYSMEM_ADDRX_SHIFT + 8)) &
199 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | mem16);
201 exca_putb(sc, map->sysmem_stop_lsb,
202 (mem->addr + mem->realsize - 1) >> EXCA_SYSMEM_ADDRX_SHIFT);
203 exca_putb(sc, map->sysmem_stop_msb,
204 (((mem->addr + mem->realsize - 1) >>
205 (EXCA_SYSMEM_ADDRX_SHIFT + 8)) &
206 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
207 EXCA_SYSMEM_ADDRX_STOP_MSB_WAIT2);
208 exca_putb(sc, map->sysmem_win, mem->addr >> EXCA_MEMREG_WIN_SHIFT);
210 exca_putb(sc, map->cardmem_lsb, offset & 0xff);
211 exca_putb(sc, map->cardmem_msb, ((offset >> 8) &
212 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK) | attrmem);
214 DPRINTF("%s %d-bit memory",
215 mem->kind & PCCARD_MEM_ATTR ? "attribute" : "common",
216 mem->kind & PCCARD_MEM_16BIT ? 16 : 8);
217 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->memenable |
218 EXCA_ADDRWIN_ENABLE_MEMCS16);
223 int r1, r2, r3, r4, r5, r6, r7;
224 r1 = exca_getb(sc, map->sysmem_start_msb);
225 r2 = exca_getb(sc, map->sysmem_start_lsb);
226 r3 = exca_getb(sc, map->sysmem_stop_msb);
227 r4 = exca_getb(sc, map->sysmem_stop_lsb);
228 r5 = exca_getb(sc, map->cardmem_msb);
229 r6 = exca_getb(sc, map->cardmem_lsb);
230 r7 = exca_getb(sc, map->sysmem_win);
231 printf("exca_do_mem_map win %d: %#02x%#02x %#02x%#02x "
232 "%#02x%#02x %#02x (%#08x+%#06x.%#06x*%#06x) flags %#x\n",
233 win, r1, r2, r3, r4, r5, r6, r7,
234 mem->addr, mem->size, mem->realsize,
235 mem->cardaddr, mem->kind);
241 * public interface to map a resource. kind is the type of memory to
242 * map (either common or attribute). Memory created via this interface
243 * starts out at card address 0. Since the only way to set this is
244 * to set it on a struct resource after it has been mapped, we're safe
245 * in maping this assumption. Note that resources can be remapped using
246 * exca_do_mem_map so that's how the card address can be set later.
249 exca_mem_map(struct exca_softc *sc, int kind, struct resource *res)
253 for (win = 0; win < EXCA_MEM_WINS; win++) {
254 if ((sc->memalloc & (1 << win)) == 0) {
255 sc->memalloc |= (1 << win);
259 if (win >= EXCA_MEM_WINS)
261 if (sc->flags & EXCA_HAS_MEMREG_WIN) {
263 if (rman_get_start(res) >> (EXCA_MEMREG_WIN_SHIFT + 8) != 0) {
264 device_printf(sc->dev,
265 "Does not support mapping above 4GB.");
270 if (rman_get_start(res) >> EXCA_MEMREG_WIN_SHIFT != 0) {
271 device_printf(sc->dev,
272 "Does not support mapping above 16M.");
277 sc->mem[win].cardaddr = 0;
278 sc->mem[win].memt = rman_get_bustag(res);
279 sc->mem[win].memh = rman_get_bushandle(res);
280 sc->mem[win].addr = rman_get_start(res);
281 sc->mem[win].size = rman_get_end(res) - sc->mem[win].addr + 1;
282 sc->mem[win].realsize = sc->mem[win].size + EXCA_MEM_PAGESIZE - 1;
283 sc->mem[win].realsize = sc->mem[win].realsize -
284 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
285 sc->mem[win].kind = kind;
286 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n",
287 win, sc->mem[win].addr, sc->mem[win].size, sc->mem[win].cardaddr);
288 exca_do_mem_map(sc, win);
294 * Private helper function. This turns off a given memory map that is in
295 * use. We do this by just clearing the enable bit in the pcic. If we needed
296 * to make memory unmapping/mapping pairs faster, we would have to store
297 * more state information about the pcic and then use that to intelligently
298 * to the map/unmap. However, since we don't do that sort of thing often
299 * (generally just at configure time), it isn't a case worth optimizing.
302 exca_mem_unmap(struct exca_softc *sc, int window)
304 if (window < 0 || window >= EXCA_MEM_WINS)
305 panic("exca_mem_unmap: window out of range");
307 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, mem_map_index[window].memenable);
308 sc->memalloc &= ~(1 << window);
312 * Find the map that we're using to hold the resource. This works well
313 * so long as the client drivers don't do silly things like map the same
314 * area mutliple times, or map both common and attribute memory at the
315 * same time. This latter restriction is a bug. We likely should just
316 * store a pointer to the res in the mem[x] data structure.
319 exca_mem_findmap(struct exca_softc *sc, struct resource *res)
323 for (win = 0; win < EXCA_MEM_WINS; win++) {
324 if (sc->mem[win].memt == rman_get_bustag(res) &&
325 sc->mem[win].addr == rman_get_start(res) &&
326 sc->mem[win].size == rman_get_size(res))
333 * Set the memory flag. This means that we are setting if the memory
334 * is coming from attribute memory or from common memory on the card.
335 * CIS entries are generally in attribute memory (although they can
336 * reside in common memory). Generally, this is the only use for attribute
337 * memory. However, some cards require their drivers to dance in both
338 * common and/or attribute memory and this interface (and setting the
339 * offset interface) exist for such cards.
342 exca_mem_set_flags(struct exca_softc *sc, struct resource *res, uint32_t flags)
346 win = exca_mem_findmap(sc, res);
348 device_printf(sc->dev,
349 "set_res_flags: specified resource not active\n");
355 case PCCARD_A_MEM_ATTR:
356 sc->mem[win].kind |= PCCARD_MEM_ATTR;
358 case PCCARD_A_MEM_COM:
359 sc->mem[win].kind &= ~PCCARD_MEM_ATTR;
361 case PCCARD_A_MEM_16BIT:
362 sc->mem[win].kind |= PCCARD_MEM_16BIT;
364 case PCCARD_A_MEM_8BIT:
365 sc->mem[win].kind &= ~PCCARD_MEM_16BIT;
368 exca_do_mem_map(sc, win);
373 * Given a resource, go ahead and unmap it if we can find it in the
374 * resrouce list that's used.
377 exca_mem_unmap_res(struct exca_softc *sc, struct resource *res)
381 win = exca_mem_findmap(sc, res);
384 exca_mem_unmap(sc, win);
389 * Set the offset of the memory. We use this for reading the CIS and
390 * frobbing the pccard's pccard registers (CCR, etc). Some drivers
391 * need to access arbitrary attribute and common memory during their
392 * initialization and operation.
395 exca_mem_set_offset(struct exca_softc *sc, struct resource *res,
396 uint32_t cardaddr, uint32_t *deltap)
401 win = exca_mem_findmap(sc, res);
403 device_printf(sc->dev,
404 "set_memory_offset: specified resource not active\n");
407 sc->mem[win].cardaddr = rounddown2(cardaddr, EXCA_MEM_PAGESIZE);
408 delta = cardaddr % EXCA_MEM_PAGESIZE;
411 sc->mem[win].realsize = sc->mem[win].size + delta +
412 EXCA_MEM_PAGESIZE - 1;
413 sc->mem[win].realsize = sc->mem[win].realsize -
414 (sc->mem[win].realsize % EXCA_MEM_PAGESIZE);
415 exca_do_mem_map(sc, win);
422 #define EXCA_IOINFO(NUM) { \
423 EXCA_IOADDR ## NUM ## _START_LSB, \
424 EXCA_IOADDR ## NUM ## _START_MSB, \
425 EXCA_IOADDR ## NUM ## _STOP_LSB, \
426 EXCA_IOADDR ## NUM ## _STOP_MSB, \
427 EXCA_ADDRWIN_ENABLE_IO ## NUM, \
428 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \
429 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \
430 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \
431 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \
433 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \
434 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
435 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \
436 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
437 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \
441 static struct io_map_index_st {
448 int ioctlbits[3]; /* indexed by PCCARD_WIDTH_* */
456 exca_do_io_map(struct exca_softc *sc, int win)
458 struct io_map_index_st *map;
460 struct pccard_io_handle *io;
462 map = &io_map_index[win];
464 exca_putb(sc, map->start_lsb, io->addr & 0xff);
465 exca_putb(sc, map->start_msb, (io->addr >> 8) & 0xff);
467 exca_putb(sc, map->stop_lsb, (io->addr + io->size - 1) & 0xff);
468 exca_putb(sc, map->stop_msb, ((io->addr + io->size - 1) >> 8) & 0xff);
470 exca_clrb(sc, EXCA_IOCTL, map->ioctlmask);
471 exca_setb(sc, EXCA_IOCTL, map->ioctlbits[io->width]);
473 exca_setb(sc, EXCA_ADDRWIN_ENABLE, map->ioenable);
477 r1 = exca_getb(sc, map->start_msb);
478 r2 = exca_getb(sc, map->start_lsb);
479 r3 = exca_getb(sc, map->stop_msb);
480 r4 = exca_getb(sc, map->stop_lsb);
481 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x "
482 "(%08x+%08x)\n", win, r1, r2, r3, r4,
489 exca_io_map(struct exca_softc *sc, int width, struct resource *r)
493 static char *width_names[] = { "auto", "io8", "io16"};
495 for (win=0; win < EXCA_IO_WINS; win++) {
496 if ((sc->ioalloc & (1 << win)) == 0) {
497 sc->ioalloc |= (1 << win);
501 if (win >= EXCA_IO_WINS)
504 sc->io[win].iot = rman_get_bustag(r);
505 sc->io[win].ioh = rman_get_bushandle(r);
506 sc->io[win].addr = rman_get_start(r);
507 sc->io[win].size = rman_get_end(r) - sc->io[win].addr + 1;
508 sc->io[win].flags = 0;
509 sc->io[win].width = width;
510 DPRINTF("exca_io_map window %d %s port %x+%x\n",
511 win, width_names[width], sc->io[win].addr,
513 exca_do_io_map(sc, win);
519 exca_io_unmap(struct exca_softc *sc, int window)
521 if (window >= EXCA_IO_WINS)
522 panic("exca_io_unmap: window out of range");
524 exca_clrb(sc, EXCA_ADDRWIN_ENABLE, io_map_index[window].ioenable);
526 sc->ioalloc &= ~(1 << window);
528 sc->io[window].iot = 0;
529 sc->io[window].ioh = 0;
530 sc->io[window].addr = 0;
531 sc->io[window].size = 0;
532 sc->io[window].flags = 0;
533 sc->io[window].width = 0;
537 exca_io_findmap(struct exca_softc *sc, struct resource *res)
541 for (win = 0; win < EXCA_IO_WINS; win++) {
542 if (sc->io[win].iot == rman_get_bustag(res) &&
543 sc->io[win].addr == rman_get_start(res) &&
544 sc->io[win].size == rman_get_size(res))
552 exca_io_unmap_res(struct exca_softc *sc, struct resource *res)
556 win = exca_io_findmap(sc, res);
559 exca_io_unmap(sc, win);
566 * If interrupts are enabled, then we should be able to just wait for
567 * an interrupt routine to wake us up. Busy waiting shouldn't be
568 * necessary. Sadly, not all legacy ISA cards support an interrupt
569 * for the busy state transitions, at least according to their datasheets,
570 * so we busy wait a while here..
573 exca_wait_ready(struct exca_softc *sc)
576 DEVPRINTF(sc->dev, "exca_wait_ready: status 0x%02x\n",
577 exca_getb(sc, EXCA_IF_STATUS));
578 for (i = 0; i < 10000; i++) {
579 if (exca_getb(sc, EXCA_IF_STATUS) & EXCA_IF_STATUS_READY)
583 device_printf(sc->dev, "ready never happened, status = %02x\n",
584 exca_getb(sc, EXCA_IF_STATUS));
588 * Reset the card. Ideally, we'd do a lot of this via interrupts.
589 * However, many PC Cards will deassert the ready signal. This means
590 * that they are asserting an interrupt. This makes it hard to
591 * do anything but a busy wait here. One could argue that these
592 * such cards are broken, or that the bridge that allows this sort
593 * of interrupt through isn't quite what you'd want (and may be a standards
594 * violation). However, such arguing would leave a huge class of PC Cards
595 * and bridges out of reach for use in the system.
597 * Maybe I should reevaluate the above based on the power bug I fixed
601 exca_reset(struct exca_softc *sc, device_t child)
605 /* enable socket i/o */
606 exca_setb(sc, EXCA_PWRCTL, EXCA_PWRCTL_OE);
608 exca_putb(sc, EXCA_INTR, EXCA_INTR_ENABLE);
609 /* hold reset for 30ms */
611 /* clear the reset flag */
612 exca_setb(sc, EXCA_INTR, EXCA_INTR_RESET);
613 /* wait 20ms as per PC Card standard (r2.01) section 4.3.6 */
618 /* disable all address windows */
619 exca_putb(sc, EXCA_ADDRWIN_ENABLE, 0);
621 exca_setb(sc, EXCA_INTR, EXCA_INTR_CARDTYPE_IO);
622 DEVPRINTF(sc->dev, "card type is io\n");
624 /* reinstall all the memory and io mappings */
625 for (win = 0; win < EXCA_MEM_WINS; ++win)
626 if (sc->memalloc & (1 << win))
627 exca_do_mem_map(sc, win);
628 for (win = 0; win < EXCA_IO_WINS; ++win)
629 if (sc->ioalloc & (1 << win))
630 exca_do_io_map(sc, win);
634 * Initialize the exca_softc data structure for the first time.
637 exca_init(struct exca_softc *sc, device_t dev,
638 bus_space_tag_t bst, bus_space_handle_t bsh, uint32_t offset)
647 sc->getb = exca_mem_getb;
648 sc->putb = exca_mem_putb;
649 sc->pccarddev = device_add_child(dev, "pccard", -1);
650 if (sc->pccarddev == NULL)
651 DEVPRINTF(brdev, "WARNING: cannot add pccard bus.\n");
652 else if (device_probe_and_attach(sc->pccarddev) != 0)
653 DEVPRINTF(brdev, "WARNING: cannot attach pccard bus.\n");
657 * Is this socket valid?
660 exca_valid_slot(struct exca_softc *exca)
664 /* Assume the worst */
665 exca->chipset = EXCA_BOGUS;
668 * see if there's a PCMCIA controller here
669 * Intel PCMCIA controllers use 0x82 and 0x83
670 * IBM clone chips use 0x88 and 0x89, apparently
672 c = exca_getb(exca, EXCA_IDENT);
673 DEVPRINTF(exca->dev, "Ident is %x\n", c);
674 if ((c & EXCA_IDENT_IFTYPE_MASK) != EXCA_IDENT_IFTYPE_MEM_AND_IO)
676 if ((c & EXCA_IDENT_ZERO) != 0)
678 switch (c & EXCA_IDENT_REV_MASK) {
682 case EXCA_IDENT_REV_I82365SLR0:
683 case EXCA_IDENT_REV_I82365SLR1:
684 exca->chipset = EXCA_I82365;
686 * Check for Vadem chips by unlocking their extra
687 * registers and looking for valid ID. Bit 3 in
688 * the ID register is normally 0, except when
689 * EXCA_VADEMREV is set. Other bridges appear
690 * to ignore this frobbing.
692 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
694 bus_space_write_1(exca->bst, exca->bsh, EXCA_REG_INDEX,
696 exca_setb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
697 c = exca_getb(exca, EXCA_IDENT);
701 exca->chipset = EXCA_VG365;
704 exca->chipset = EXCA_VG465;
707 exca->chipset = EXCA_VG468;
710 exca->chipset = EXCA_VG469;
713 exca_clrb(exca, EXCA_VADEM_VMISC, EXCA_VADEM_REV);
717 * Check for RICOH RF5C[23]96 PCMCIA Controller
719 c = exca_getb(exca, EXCA_RICOH_ID);
720 if (c == EXCA_RID_396) {
721 exca->chipset = EXCA_RF5C396;
723 } else if (c == EXCA_RID_296) {
724 exca->chipset = EXCA_RF5C296;
728 * Check for Cirrus logic chips.
730 exca_putb(exca, EXCA_CIRRUS_CHIP_INFO, 0);
731 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
732 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) ==
733 EXCA_CIRRUS_CHIP_INFO_CHIP_ID) {
734 c = exca_getb(exca, EXCA_CIRRUS_CHIP_INFO);
735 if ((c & EXCA_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
736 if (c & EXCA_CIRRUS_CHIP_INFO_SLOTS)
737 exca->chipset = EXCA_PD6722;
739 exca->chipset = EXCA_PD6710;
745 case EXCA_IDENT_REV_I82365SLDF:
747 * Intel i82365sl-DF step or maybe a vlsi 82c146
748 * we detected the vlsi case earlier, so if the controller
749 * isn't set, we know it is a i82365sl step D.
750 * XXXX Except we didn't -- this is a regression but VLSI
751 * controllers are super hard to find these days for testing.
753 exca->chipset = EXCA_I82365SL_DF;
755 case EXCA_IDENT_REV_IBM1:
756 case EXCA_IDENT_REV_IBM2:
757 exca->chipset = EXCA_IBM;
759 case EXCA_IDENT_REV_IBM_KING:
760 exca->chipset = EXCA_IBM_KING;
769 * Probe the expected slots. We maybe should set the ID for each of these
770 * slots too while we're at it. But maybe that belongs to a separate
773 * The caller must guarantee that at least EXCA_NSLOTS are present in exca.
776 exca_probe_slots(device_t dev, struct exca_softc *exca, bus_space_tag_t iot,
777 bus_space_handle_t ioh)
783 for (i = 0; i < EXCA_NSLOTS; i++) {
784 exca_init(&exca[i], dev, iot, ioh, i * EXCA_SOCKET_SIZE);
785 exca->getb = exca_io_getb;
786 exca->putb = exca_io_putb;
787 if (exca_valid_slot(&exca[i])) {
788 device_set_desc(dev, chip_names[exca[i].chipset]);
796 exca_insert(struct exca_softc *exca)
798 if (device_is_attached(exca->pccarddev)) {
799 if (CARD_ATTACH_CARD(exca->pccarddev) != 0)
800 device_printf(exca->dev,
801 "PC Card card activation failed\n");
803 device_printf(exca->dev,
804 "PC Card inserted, but no pccard bus.\n");
810 exca_removal(struct exca_softc *exca)
812 if (device_is_attached(exca->pccarddev))
813 CARD_DETACH_CARD(exca->pccarddev);
817 exca_activate_resource(struct exca_softc *exca, device_t child, int type,
818 int rid, struct resource *res)
822 if (rman_get_flags(res) & RF_ACTIVE)
824 err = BUS_ACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
830 err = exca_io_map(exca, PCCARD_WIDTH_AUTO, res);
833 err = exca_mem_map(exca, 0, res);
837 BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
843 exca_deactivate_resource(struct exca_softc *exca, device_t child, int type,
844 int rid, struct resource *res)
846 if (rman_get_flags(res) & RF_ACTIVE) { /* if activated */
849 if (exca_io_unmap_res(exca, res))
853 if (exca_mem_unmap_res(exca, res))
858 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca->dev), child,
863 static struct resource *
864 exca_alloc_resource(struct exca_softc *sc, device_t child, int type, int *rid,
865 u_long start, u_long end, u_long count, uint flags)
867 struct resource *res = NULL;
872 if (start < cbb_start_mem)
873 start = cbb_start_mem;
876 flags = (flags & ~RF_ALIGNMENT_MASK) |
877 rman_make_alignment_flags(CBB_MEMALIGN);
880 if (start < cbb_start_16_io)
881 start = cbb_start_16_io;
886 tmp = rman_get_start(sc->irq_res);
887 if (start > tmp || end < tmp || count != 1) {
888 device_printf(child, "requested interrupt %ld-%ld,"
889 "count = %ld not supported by cbb\n",
893 flags |= RF_SHAREABLE;
894 start = end = rman_get_start(sc->irq_res);
897 res = BUS_ALLOC_RESOURCE(up, child, type, rid,
898 start, end, count, flags & ~RF_ACTIVE);
901 cbb_insert_res(sc, res, type, *rid);
902 if (flags & RF_ACTIVE) {
903 if (bus_activate_resource(child, type, *rid, res) != 0) {
904 bus_release_resource(child, type, *rid, res);
913 exca_release_resource(struct exca_softc *sc, device_t child, int type,
914 int rid, struct resource *res)
918 if (rman_get_flags(res) & RF_ACTIVE) {
919 error = bus_deactivate_resource(child, type, rid, res);
923 cbb_remove_res(sc, res);
924 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev), child,
930 exca_modevent(module_t mod, int cmd, void *arg)
935 DEV_MODULE(exca, exca_modevent, NULL);
936 MODULE_VERSION(exca, 1);