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 $
55 * $DragonFly: src/sys/dev/pccard/exca/exca.c,v 1.4 2007/07/05 12:08:54 sephe Exp $
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/errno.h>
61 #include <sys/kernel.h>
62 #include <sys/malloc.h>
63 #include <sys/queue.h>
64 #include <sys/module.h>
71 #include <bus/pccard/pccardreg.h>
72 #include <bus/pccard/pccardvar.h>
74 #include <dev/pccard/exca/excareg.h>
75 #include <dev/pccard/exca/excavar.h>
78 #define DEVPRINTF(dev, fmt, args...) device_printf((dev), (fmt), ## args)
79 #define DPRINTF(fmt, args...) kprintf(fmt, ## args)
81 #define DEVPRINTF(dev, fmt, args...)
82 #define DPRINTF(fmt, args...)
86 static const char *chip_names
[] =
89 "Intel i82365SL-A/B or clone",
90 "Intel i82365sl-DF step",
92 "Cirrus Logic PD6710",
93 "Cirrus logic PD6722",
94 "Cirrus Logic PD6729",
102 "IBM KING PCMCIA Controller"
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
;
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, \
124 static struct mem_map_index_st
{
125 int sysmem_start_lsb
;
126 int sysmem_start_msb
;
133 } mem_map_index
[] = {
143 exca_mem_getb(struct exca_softc
*sc
, int reg
)
145 return (bus_space_read_1(sc
->bst
, sc
->bsh
, sc
->offset
+ reg
));
149 exca_mem_putb(struct exca_softc
*sc
, int reg
, uint8_t val
)
151 bus_space_write_1(sc
->bst
, sc
->bsh
, sc
->offset
+ reg
, val
);
155 exca_io_getb(struct exca_softc
*sc
, int reg
)
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
));
162 exca_io_putb(struct exca_softc
*sc
, int reg
, uint8_t val
)
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
);
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).
175 exca_do_mem_map(struct exca_softc
*sc
, int win
)
177 struct mem_map_index_st
*map
;
178 struct pccard_mem_handle
*mem
;
181 map
= &mem_map_index
[win
];
183 offset
= ((mem
->cardaddr
>> EXCA_CARDMEM_ADDRX_SHIFT
) -
184 (mem
->addr
>> EXCA_SYSMEM_ADDRX_SHIFT
)) & 0x3fff;
185 exca_putb(sc
, map
->sysmem_start_lsb
,
186 (mem
->addr
>> EXCA_SYSMEM_ADDRX_SHIFT
) & 0xff);
187 exca_putb(sc
, map
->sysmem_start_msb
,
188 ((mem
->addr
>> (EXCA_SYSMEM_ADDRX_SHIFT
+ 8)) &
189 EXCA_SYSMEM_ADDRX_START_MSB_ADDR_MASK
));
191 exca_putb(sc
, map
->sysmem_stop_lsb
,
192 ((mem
->addr
+ mem
->realsize
- 1) >>
193 EXCA_SYSMEM_ADDRX_SHIFT
) & 0xff);
194 exca_putb(sc
, map
->sysmem_stop_msb
,
195 (((mem
->addr
+ mem
->realsize
- 1) >>
196 (EXCA_SYSMEM_ADDRX_SHIFT
+ 8)) &
197 EXCA_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK
) |
198 EXCA_SYSMEM_ADDRX_STOP_MSB_WAIT2
);
200 exca_putb(sc
, map
->sysmem_win
,
201 (mem
->addr
>> EXCA_MEMREG_WIN_SHIFT
) & 0xff);
203 exca_putb(sc
, map
->cardmem_lsb
, offset
& 0xff);
204 exca_putb(sc
, map
->cardmem_msb
, (((offset
>> 8) & 0xff) &
205 EXCA_CARDMEM_ADDRX_MSB_ADDR_MASK
) |
206 ((mem
->kind
== PCCARD_A_MEM_ATTR
) ?
207 EXCA_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR
: 0));
210 if (mem
->kind
== PCCARD_A_MEM_ATTR
)
211 kprintf("attribtue memory\n");
213 kprintf("common memory\n");
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 kprintf("exca_do_mem_map win %d: %02x%02x %02x%02x "
230 "%02x%02x %02x (%08x+%06x.%06x*%06x)\n",
231 win
, r1
, r2
, r3
, r4
, r5
, r6
, r7
,
232 mem
->addr
, mem
->size
, mem
->realsize
,
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 (((rman_get_start(res
) >> EXCA_MEMREG_WIN_SHIFT
) & 0xff) != 0 &&
260 (sc
->flags
& EXCA_HAS_MEMREG_WIN
) == 0) {
261 device_printf(sc
->dev
, "Does not support mapping above 24M.");
265 sc
->mem
[win
].cardaddr
= 0;
266 sc
->mem
[win
].memt
= rman_get_bustag(res
);
267 sc
->mem
[win
].memh
= rman_get_bushandle(res
);
268 sc
->mem
[win
].addr
= rman_get_start(res
);
269 sc
->mem
[win
].size
= rman_get_end(res
) - sc
->mem
[win
].addr
+ 1;
270 sc
->mem
[win
].realsize
= sc
->mem
[win
].size
+ EXCA_MEM_PAGESIZE
- 1;
271 sc
->mem
[win
].realsize
= sc
->mem
[win
].realsize
-
272 (sc
->mem
[win
].realsize
% EXCA_MEM_PAGESIZE
);
273 sc
->mem
[win
].kind
= kind
;
274 DPRINTF("exca_mem_map window %d bus %x+%x card addr %x\n",
275 win
, sc
->mem
[win
].addr
, sc
->mem
[win
].size
, sc
->mem
[win
].cardaddr
);
276 exca_do_mem_map(sc
, win
);
282 * Private helper function. This turns off a given memory map that is in
283 * use. We do this by just clearing the enable bit in the pcic. If we needed
284 * to make memory unmapping/mapping pairs faster, we would have to store
285 * more state information about the pcic and then use that to intelligently
286 * to the map/unmap. However, since we don't do that sort of thing often
287 * (generally just at configure time), it isn't a case worth optimizing.
290 exca_mem_unmap(struct exca_softc
*sc
, int window
)
292 if (window
< 0 || window
>= EXCA_MEM_WINS
)
293 panic("exca_mem_unmap: window out of range");
295 exca_clrb(sc
, EXCA_ADDRWIN_ENABLE
, mem_map_index
[window
].memenable
);
296 sc
->memalloc
&= ~(1 << window
);
300 * Find the map that we're using to hold the resoruce. This works well
301 * so long as the client drivers don't do silly things like map the same
302 * area mutliple times, or map both common and attribute memory at the
303 * same time. This latter restriction is a bug. We likely should just
304 * store a pointer to the res in the mem[x] data structure.
307 exca_mem_findmap(struct exca_softc
*sc
, struct resource
*res
)
311 for (win
= 0; win
< EXCA_MEM_WINS
; win
++) {
312 if (sc
->mem
[win
].memt
== rman_get_bustag(res
) &&
313 sc
->mem
[win
].addr
== rman_get_start(res
) &&
314 sc
->mem
[win
].size
== rman_get_size(res
))
321 * Set the memory flag. This means that we are setting if the memory
322 * is coming from attribute memory or from common memory on the card.
323 * CIS entries are generally in attribute memory (although they can
324 * reside in common memory). Generally, this is the only use for attribute
325 * memory. However, some cards require their drivers to dance in both
326 * common and/or attribute memory and this interface (and setting the
327 * offset interface) exist for such cards.
330 exca_mem_set_flags(struct exca_softc
*sc
, struct resource
*res
, uint32_t flags
)
334 win
= exca_mem_findmap(sc
, res
);
336 device_printf(sc
->dev
,
337 "set_res_flags: specified resource not active\n");
341 sc
->mem
[win
].kind
= flags
;
342 exca_do_mem_map(sc
, win
);
347 * Given a resource, go ahead and unmap it if we can find it in the
348 * resrouce list that's used.
351 exca_mem_unmap_res(struct exca_softc
*sc
, struct resource
*res
)
355 win
= exca_mem_findmap(sc
, res
);
358 exca_mem_unmap(sc
, win
);
363 * Set the offset of the memory. We use this for reading the CIS and
364 * frobbing the pccard's pccard registers (POR, etc). Some drivers
365 * need to access this functionality as well, since they have receive
366 * buffers defined in the attribute memory.
369 exca_mem_set_offset(struct exca_softc
*sc
, struct resource
*res
,
370 uint32_t cardaddr
, uint32_t *deltap
)
375 win
= exca_mem_findmap(sc
, res
);
377 device_printf(sc
->dev
,
378 "set_memory_offset: specified resource not active\n");
381 sc
->mem
[win
].cardaddr
= cardaddr
& ~(EXCA_MEM_PAGESIZE
- 1);
382 delta
= cardaddr
% EXCA_MEM_PAGESIZE
;
385 sc
->mem
[win
].realsize
= sc
->mem
[win
].size
+ delta
+
386 EXCA_MEM_PAGESIZE
- 1;
387 sc
->mem
[win
].realsize
= sc
->mem
[win
].realsize
-
388 (sc
->mem
[win
].realsize
% EXCA_MEM_PAGESIZE
);
389 exca_do_mem_map(sc
, win
);
396 #define EXCA_IOINFO(NUM) { \
397 EXCA_IOADDR ## NUM ## _START_LSB, \
398 EXCA_IOADDR ## NUM ## _START_MSB, \
399 EXCA_IOADDR ## NUM ## _STOP_LSB, \
400 EXCA_IOADDR ## NUM ## _STOP_MSB, \
401 EXCA_ADDRWIN_ENABLE_IO ## NUM, \
402 EXCA_IOCTL_IO ## NUM ## _WAITSTATE \
403 | EXCA_IOCTL_IO ## NUM ## _ZEROWAIT \
404 | EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_MASK \
405 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_MASK, \
407 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_CARD, \
408 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
409 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_8BIT, \
410 EXCA_IOCTL_IO ## NUM ## _IOCS16SRC_DATASIZE \
411 | EXCA_IOCTL_IO ## NUM ## _DATASIZE_16BIT, \
415 static struct io_map_index_st
{
422 int ioctlbits
[3]; /* indexed by PCCARD_WIDTH_* */
430 exca_do_io_map(struct exca_softc
*sc
, int win
)
432 struct io_map_index_st
*map
;
434 struct pccard_io_handle
*io
;
436 map
= &io_map_index
[win
];
438 exca_putb(sc
, map
->start_lsb
, io
->addr
& 0xff);
439 exca_putb(sc
, map
->start_msb
, (io
->addr
>> 8) & 0xff);
441 exca_putb(sc
, map
->stop_lsb
, (io
->addr
+ io
->size
- 1) & 0xff);
442 exca_putb(sc
, map
->stop_msb
, ((io
->addr
+ io
->size
- 1) >> 8) & 0xff);
444 exca_clrb(sc
, EXCA_IOCTL
, map
->ioctlmask
);
445 exca_setb(sc
, EXCA_IOCTL
, map
->ioctlbits
[io
->width
]);
447 exca_setb(sc
, EXCA_ADDRWIN_ENABLE
, map
->ioenable
);
451 r1
= exca_getb(sc
, map
->start_msb
);
452 r2
= exca_getb(sc
, map
->start_lsb
);
453 r3
= exca_getb(sc
, map
->stop_msb
);
454 r4
= exca_getb(sc
, map
->stop_lsb
);
455 DPRINTF("exca_do_io_map window %d: %02x%02x %02x%02x "
456 "(%08x+%08x)\n", win
, r1
, r2
, r3
, r4
,
463 exca_io_map(struct exca_softc
*sc
, int width
, struct resource
*r
)
467 static char *width_names
[] = { "auto", "io8", "io16"};
469 for (win
=0; win
< EXCA_IO_WINS
; win
++) {
470 if ((sc
->ioalloc
& (1 << win
)) == 0) {
471 sc
->ioalloc
|= (1 << win
);
475 if (win
>= EXCA_IO_WINS
)
478 sc
->io
[win
].iot
= rman_get_bustag(r
);
479 sc
->io
[win
].ioh
= rman_get_bushandle(r
);
480 sc
->io
[win
].addr
= rman_get_start(r
);
481 sc
->io
[win
].size
= rman_get_end(r
) - sc
->io
[win
].addr
+ 1;
482 sc
->io
[win
].flags
= 0;
483 sc
->io
[win
].width
= width
;
484 DPRINTF("exca_io_map window %d %s port %x+%x\n",
485 win
, width_names
[width
], sc
->io
[win
].addr
,
487 exca_do_io_map(sc
, win
);
493 exca_io_unmap(struct exca_softc
*sc
, int window
)
495 if (window
>= EXCA_IO_WINS
)
496 panic("exca_io_unmap: window out of range");
498 exca_clrb(sc
, EXCA_ADDRWIN_ENABLE
, io_map_index
[window
].ioenable
);
500 sc
->ioalloc
&= ~(1 << window
);
502 sc
->io
[window
].iot
= 0;
503 sc
->io
[window
].ioh
= 0;
504 sc
->io
[window
].addr
= 0;
505 sc
->io
[window
].size
= 0;
506 sc
->io
[window
].flags
= 0;
507 sc
->io
[window
].width
= 0;
511 exca_io_findmap(struct exca_softc
*sc
, struct resource
*res
)
515 for (win
= 0; win
< EXCA_IO_WINS
; win
++) {
516 if (sc
->io
[win
].iot
== rman_get_bustag(res
) &&
517 sc
->io
[win
].addr
== rman_get_start(res
) &&
518 sc
->io
[win
].size
== rman_get_size(res
))
526 exca_io_unmap_res(struct exca_softc
*sc
, struct resource
*res
)
530 win
= exca_io_findmap(sc
, res
);
533 exca_io_unmap(sc
, win
);
540 * If interrupts are enabled, then we should be able to just wait for
541 * an interrupt routine to wake us up. Busy waiting shouldn't be
542 * necessary. Sadly, not all legacy ISA cards support an interrupt
543 * for the busy state transitions, at least according to their datasheets,
544 * so we busy wait a while here..
547 exca_wait_ready(struct exca_softc
*sc
)
550 DEVPRINTF(sc
->dev
, "exca_wait_ready: status 0x%02x\n",
551 exca_getb(sc
, EXCA_IF_STATUS
));
552 for (i
= 0; i
< 10000; i
++) {
553 if (exca_getb(sc
, EXCA_IF_STATUS
) & EXCA_IF_STATUS_READY
)
557 device_printf(sc
->dev
, "ready never happened, status = %02x\n",
558 exca_getb(sc
, EXCA_IF_STATUS
));
562 * Reset the card. Ideally, we'd do a lot of this via interrupts.
563 * However, many PC Cards will deassert the ready signal. This means
564 * that they are asserting an interrupt. This makes it hard to
565 * do anything but a busy wait here. One could argue that these
566 * such cards are broken, or that the bridge that allows this sort
567 * of interrupt through isn't quite what you'd want (and may be a standards
568 * violation). However, such arguing would leave a huge class of pc cards
569 * and bridges out of reach for use in the system.
571 * Maybe I should reevaluate the above based on the power bug I fixed
575 exca_reset(struct exca_softc
*sc
, device_t child
)
579 /* enable socket i/o */
580 exca_setb(sc
, EXCA_PWRCTL
, EXCA_PWRCTL_OE
);
582 exca_putb(sc
, EXCA_INTR
, EXCA_INTR_ENABLE
);
583 /* hold reset for 30ms */
585 /* clear the reset flag */
586 exca_setb(sc
, EXCA_INTR
, EXCA_INTR_RESET
);
587 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
592 /* disable all address windows */
593 exca_putb(sc
, EXCA_ADDRWIN_ENABLE
, 0);
595 exca_setb(sc
, EXCA_INTR
, EXCA_INTR_CARDTYPE_IO
);
596 DEVPRINTF(sc
->dev
, "card type is io\n");
598 /* reinstall all the memory and io mappings */
599 for (win
= 0; win
< EXCA_MEM_WINS
; ++win
)
600 if (sc
->memalloc
& (1 << win
))
601 exca_do_mem_map(sc
, win
);
602 for (win
= 0; win
< EXCA_IO_WINS
; ++win
)
603 if (sc
->ioalloc
& (1 << win
))
604 exca_do_io_map(sc
, win
);
608 * Initialize the exca_softc data structure for the first time.
611 exca_init(struct exca_softc
*sc
, device_t dev
,
612 bus_space_tag_t bst
, bus_space_handle_t bsh
, uint32_t offset
)
621 sc
->getb
= exca_mem_getb
;
622 sc
->putb
= exca_mem_putb
;
626 * Is this socket valid?
629 exca_valid_slot(struct exca_softc
*exca
)
633 /* Assume the worst */
634 exca
->chipset
= EXCA_BOGUS
;
637 * see if there's a PCMCIA controller here
638 * Intel PCMCIA controllers use 0x82 and 0x83
639 * IBM clone chips use 0x88 and 0x89, apparently
641 c
= exca_getb(exca
, EXCA_IDENT
);
642 if ((c
& EXCA_IDENT_IFTYPE_MASK
) != EXCA_IDENT_IFTYPE_MEM_AND_IO
)
644 if ((c
& EXCA_IDENT_ZERO
) != 0)
646 switch (c
& EXCA_IDENT_REV_MASK
) {
650 case EXCA_IDENT_REV_I82365SLR0
:
651 case EXCA_IDENT_REV_I82365SLR1
:
652 exca
->chipset
= EXCA_I82365
;
654 * Check for Vadem chips by unlocking their extra
655 * registers and looking for valid ID. Bit 3 in
656 * the ID register is normally 0, except when
657 * EXCA_VADEMREV is set. Other bridges appear
658 * to ignore this frobbing.
660 bus_space_write_1(exca
->bst
, exca
->bsh
, EXCA_REG_INDEX
,
662 bus_space_write_1(exca
->bst
, exca
->bsh
, EXCA_REG_INDEX
,
664 exca_setb(exca
, EXCA_VADEM_VMISC
, EXCA_VADEM_REV
);
665 c
= exca_getb(exca
, EXCA_IDENT
);
669 exca
->chipset
= EXCA_VG365
;
672 exca
->chipset
= EXCA_VG465
;
675 exca
->chipset
= EXCA_VG468
;
678 exca
->chipset
= EXCA_VG469
;
681 exca_clrb(exca
, EXCA_VADEM_VMISC
, EXCA_VADEM_REV
);
685 * Check for RICOH RF5C[23]96 PCMCIA Controller
687 c
= exca_getb(exca
, EXCA_RICOH_ID
);
688 if (c
== EXCA_RID_396
) {
689 exca
->chipset
= EXCA_RF5C396
;
691 } else if (c
== EXCA_RID_296
) {
692 exca
->chipset
= EXCA_RF5C296
;
696 * Check for Cirrus logic chips.
698 exca_putb(exca
, EXCA_CIRRUS_CHIP_INFO
, 0);
699 c
= exca_getb(exca
, EXCA_CIRRUS_CHIP_INFO
);
700 if ((c
& EXCA_CIRRUS_CHIP_INFO_CHIP_ID
) ==
701 EXCA_CIRRUS_CHIP_INFO_CHIP_ID
) {
702 c
= exca_getb(exca
, EXCA_CIRRUS_CHIP_INFO
);
703 if ((c
& EXCA_CIRRUS_CHIP_INFO_CHIP_ID
) == 0) {
704 if (c
& EXCA_CIRRUS_CHIP_INFO_SLOTS
)
705 exca
->chipset
= EXCA_PD6722
;
707 exca
->chipset
= EXCA_PD6710
;
713 case EXCA_IDENT_REV_I82365SLDF
:
715 * Intel i82365sl-DF step or maybe a vlsi 82c146
716 * we detected the vlsi case earlier, so if the controller
717 * isn't set, we know it is a i82365sl step D.
719 exca
->chipset
= EXCA_I82365SL_DF
;
721 case EXCA_IDENT_REV_IBM1
:
722 case EXCA_IDENT_REV_IBM2
:
723 exca
->chipset
= EXCA_IBM
;
725 case EXCA_IDENT_REV_IBM_KING
:
726 exca
->chipset
= EXCA_IBM_KING
;
735 * Probe the expected slots. We maybe should set the ID for each of these
736 * slots too while we're at it. But maybe that belongs to a separate
739 * The caller must guarantee that at least EXCA_NSLOTS are present in exca.
742 exca_probe_slots(device_t dev
, struct exca_softc
*exca
, bus_space_tag_t iot
,
743 bus_space_handle_t ioh
)
749 for (i
= 0; i
< EXCA_NSLOTS
; i
++) {
750 exca_init(&exca
[i
], dev
, iot
, ioh
, i
* EXCA_SOCKET_SIZE
);
751 exca
->getb
= exca_io_getb
;
752 exca
->putb
= exca_io_putb
;
753 if (exca_valid_slot(&exca
[i
]))
760 exca_insert(struct exca_softc
*exca
)
762 if (exca
->pccarddev
!= NULL
) {
763 if (CARD_ATTACH_CARD(exca
->pccarddev
) != 0)
764 device_printf(exca
->dev
,
765 "PC Card card activation failed\n");
767 device_printf(exca
->dev
,
768 "PC Card inserted, but no pccard bus.\n");
774 exca_removal(struct exca_softc
*exca
)
776 if (exca
->pccarddev
!= NULL
)
777 CARD_DETACH_CARD(exca
->pccarddev
);
781 exca_activate_resource(struct exca_softc
*exca
, device_t child
, int type
,
782 int rid
, struct resource
*res
)
785 if (!(rman_get_flags(res
) & RF_ACTIVE
)) { /* not already activated */
788 err
= exca_io_map(exca
, PCCARD_WIDTH_AUTO
, res
);
791 err
= exca_mem_map(exca
, PCCARD_A_MEM_COM
, res
);
801 return (BUS_ACTIVATE_RESOURCE(device_get_parent(exca
->dev
), child
,
806 exca_deactivate_resource(struct exca_softc
*exca
, device_t child
, int type
,
807 int rid
, struct resource
*res
)
809 if (rman_get_flags(res
) & RF_ACTIVE
) { /* if activated */
812 if (exca_io_unmap_res(exca
, res
))
816 if (exca_mem_unmap_res(exca
, res
))
821 return (BUS_DEACTIVATE_RESOURCE(device_get_parent(exca
->dev
), child
,
826 static struct resource
*
827 exca_alloc_resource(struct exca_softc
*sc
, device_t child
, int type
, int *rid
,
828 u_long start
, u_long end
, u_long count
, uint flags
)
830 struct resource
*res
= NULL
;
835 if (start
< cbb_start_mem
)
836 start
= cbb_start_mem
;
839 flags
= (flags
& ~RF_ALIGNMENT_MASK
) |
840 rman_make_alignment_flags(CBB_MEMALIGN
);
843 if (start
< cbb_start_16_io
)
844 start
= cbb_start_16_io
;
849 tmp
= rman_get_start(sc
->irq_res
);
850 if (start
> tmp
|| end
< tmp
|| count
!= 1) {
851 device_printf(child
, "requested interrupt %ld-%ld,"
852 "count = %ld not supported by cbb\n",
856 flags
|= RF_SHAREABLE
;
857 start
= end
= rman_get_start(sc
->irq_res
);
860 res
= BUS_ALLOC_RESOURCE(up
, child
, type
, rid
,
861 start
, end
, count
, flags
& ~RF_ACTIVE
);
864 cbb_insert_res(sc
, res
, type
, *rid
);
865 if (flags
& RF_ACTIVE
) {
866 if (bus_activate_resource(child
, type
, *rid
, res
) != 0) {
867 bus_release_resource(child
, type
, *rid
, res
);
876 exca_release_resource(struct exca_softc
*sc
, device_t child
, int type
,
877 int rid
, struct resource
*res
)
881 if (rman_get_flags(res
) & RF_ACTIVE
) {
882 error
= bus_deactivate_resource(child
, type
, rid
, res
);
886 cbb_remove_res(sc
, res
);
887 return (BUS_RELEASE_RESOURCE(device_get_parent(brdev
), child
,
893 exca_modevent(module_t mod
, int cmd
, void *arg
)
898 DEV_MODULE(exca
, exca_modevent
, NULL
);
899 MODULE_VERSION(exca
, 1);