1 /* $NetBSD: if_tr_pcmcia.c,v 1.23 2009/05/12 14:42:18 cegger Exp $ */
4 * Copyright (c) 2000 Soren S. Jorvang. All rights reserved.
5 * Copyright (c) 2000 Onno van der Linden. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * PCMCIA attachment for the following Tropic-based cards.
31 * o IBM Token Ring 16/4 Credit Card Adapter
32 * o IBM Token Ring Auto 16/4 Credit Card Adapter
33 * o IBM Turbo 16/4 Token Ring PC Card
34 * o 3Com TokenLink Velocity PC Card
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: if_tr_pcmcia.c,v 1.23 2009/05/12 14:42:18 cegger Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/callout.h>
44 #include <sys/socket.h>
45 #include <sys/ioctl.h>
46 #include <sys/errno.h>
47 #include <sys/syslog.h>
48 #include <sys/select.h>
49 #include <sys/device.h>
52 #include <net/if_dl.h>
53 #include <net/if_ether.h>
54 #include <net/if_media.h>
59 #include <dev/ic/tropicreg.h>
60 #include <dev/ic/tropicvar.h>
62 #include <dev/pcmcia/pcmciareg.h>
63 #include <dev/pcmcia/pcmciavar.h>
64 #include <dev/pcmcia/pcmciadevs.h>
66 #define TR_SRAM_SIZE (16 * 1024) /* Really 64KB, but conserve iomem. */
69 * XXX How do host/PCMCIA/cbb memory spaces actually relate?
71 #ifndef TR_PCMCIA_SRAM_ADDR
72 #define TR_PCMCIA_SRAM_ADDR 0xc8000
74 #ifndef TR_PCMCIA_MMIO_ADDR
75 #define TR_PCMCIA_MMIO_ADDR 0xcc000
78 struct tr_pcmcia_softc
{
79 struct tr_softc sc_tr
;
81 struct pcmcia_io_handle sc_pioh
;
83 struct pcmcia_mem_handle sc_sramh
;
85 struct pcmcia_mem_handle sc_mmioh
;
87 struct pcmcia_function
*sc_pf
;
90 static int tr_pcmcia_match(device_t
, cfdata_t
, void *);
91 static void tr_pcmcia_attach(device_t
, device_t
, void *);
92 static int tr_pcmcia_detach(device_t
, int);
93 static int tr_pcmcia_enable(struct tr_softc
*);
94 static int tr_pcmcia_mediachange(struct tr_softc
*);
95 static void tr_pcmcia_mediastatus(struct tr_softc
*, struct ifmediareq
*);
96 static void tr_pcmcia_disable(struct tr_softc
*);
97 static void tr_pcmcia_setup(struct tr_softc
*);
99 CFATTACH_DECL(tr_pcmcia
, sizeof(struct tr_pcmcia_softc
),
100 tr_pcmcia_match
, tr_pcmcia_attach
, tr_pcmcia_detach
, tr_activate
);
103 tr_pcmcia_match(device_t parent
, cfdata_t match
,
106 struct pcmcia_attach_args
*pa
= aux
;
108 if (pa
->manufacturer
== PCMCIA_VENDOR_IBM
)
109 switch (pa
->product
) {
110 case PCMCIA_PRODUCT_IBM_TROPIC
:
118 tr_pcmcia_attach(device_t parent
, device_t self
, void *aux
)
120 struct tr_pcmcia_softc
*psc
= (void *)self
;
121 struct tr_softc
*sc
= &psc
->sc_tr
;
122 struct pcmcia_attach_args
*pa
= aux
;
123 struct pcmcia_config_entry
*cfe
;
128 cfe
= SIMPLEQ_FIRST(&pa
->pf
->cfe_head
);
130 pcmcia_function_init(pa
->pf
, cfe
);
131 if (pcmcia_function_enable(pa
->pf
) != 0) {
132 aprint_error_dev(self
, "function enable failed\n");
136 if (pcmcia_io_alloc(pa
->pf
, cfe
->iospace
[0].start
,
137 cfe
->iospace
[0].length
, cfe
->iospace
[0].length
, &psc
->sc_pioh
) != 0) {
138 aprint_error_dev(self
, "can't allocate pio space\n");
141 if (pcmcia_io_map(psc
->sc_pf
, PCMCIA_WIDTH_IO8
, /* XXX _AUTO? */
142 &psc
->sc_pioh
, &psc
->sc_pio_window
) != 0) {
143 aprint_error_dev(self
, "can't map pio space\n");
147 if (pcmcia_mem_alloc(psc
->sc_pf
, TR_SRAM_SIZE
, &psc
->sc_sramh
) != 0) {
148 aprint_error_dev(self
, "can't allocate sram space\n");
151 if (pcmcia_mem_map(psc
->sc_pf
, PCMCIA_MEM_COMMON
, TR_PCMCIA_SRAM_ADDR
,
152 TR_SRAM_SIZE
, &psc
->sc_sramh
, &offset
, &psc
->sc_sram_window
) != 0) {
153 aprint_error_dev(self
, "can't map sram space\n");
157 if (pcmcia_mem_alloc(psc
->sc_pf
, TR_MMIO_SIZE
, &psc
->sc_mmioh
) != 0) {
158 aprint_error_dev(self
, "can't allocate mmio space\n");
162 if (pcmcia_mem_map(psc
->sc_pf
, PCMCIA_MEM_COMMON
, TR_PCMCIA_MMIO_ADDR
,
163 TR_MMIO_SIZE
, &psc
->sc_mmioh
, &offset
, &psc
->sc_mmio_window
) != 0) {
164 aprint_error_dev(self
, "can't map mmio space\n");
168 sc
->sc_piot
= psc
->sc_pioh
.iot
;
169 sc
->sc_pioh
= psc
->sc_pioh
.ioh
;
170 sc
->sc_memt
= psc
->sc_sramh
.memt
;
171 sc
->sc_sramh
= psc
->sc_sramh
.memh
;
172 sc
->sc_mmioh
= psc
->sc_mmioh
.memh
;
173 sc
->sc_init_status
= RSP_16
;
174 sc
->sc_memwinsz
= TR_SRAM_SIZE
;
175 sc
->sc_memsize
= TR_SRAM_SIZE
;
176 sc
->sc_memreserved
= 0;
177 sc
->sc_aca
= TR_ACA_OFFSET
;
178 sc
->sc_maddr
= TR_PCMCIA_SRAM_ADDR
;
179 sc
->sc_mediastatus
= tr_pcmcia_mediastatus
;
180 sc
->sc_mediachange
= tr_pcmcia_mediachange
;
181 sc
->sc_enable
= tr_pcmcia_enable
;
182 sc
->sc_disable
= tr_pcmcia_disable
;
185 if (tr_reset(sc
) == 0)
188 pcmcia_function_disable(pa
->pf
);
193 pcmcia_mem_free(psc
->sc_pf
, &psc
->sc_mmioh
);
195 pcmcia_mem_unmap(psc
->sc_pf
, psc
->sc_sram_window
);
197 pcmcia_mem_free(psc
->sc_pf
, &psc
->sc_sramh
);
199 pcmcia_io_unmap(psc
->sc_pf
, psc
->sc_pio_window
);
201 pcmcia_io_free(psc
->sc_pf
, &psc
->sc_pioh
);
203 pcmcia_function_disable(pa
->pf
);
208 tr_pcmcia_enable(struct tr_softc
*sc
)
210 struct tr_pcmcia_softc
*psc
= (struct tr_pcmcia_softc
*) sc
;
213 sc
->sc_ih
= pcmcia_intr_establish(psc
->sc_pf
, IPL_NET
, tr_intr
, psc
);
214 if (sc
->sc_ih
== NULL
) {
215 aprint_error_dev(&psc
->sc_tr
.sc_dev
, "couldn't establish interrupt\n");
219 ret
= pcmcia_function_enable(psc
->sc_pf
);
234 tr_pcmcia_disable(struct tr_softc
*sc
)
236 struct tr_pcmcia_softc
*psc
= (struct tr_pcmcia_softc
*) sc
;
238 pcmcia_function_disable(psc
->sc_pf
);
239 pcmcia_intr_disestablish(psc
->sc_pf
, sc
->sc_ih
);
243 tr_pcmcia_mediachange(struct tr_softc
*sc
)
247 if (IFM_TYPE(sc
->sc_media
.ifm_media
) != IFM_TOKEN
)
250 switch (IFM_SUBTYPE(sc
->sc_media
.ifm_media
)) {
253 if ((sc
->sc_init_status
& RSP_16
) == 0)
258 if ((sc
->sc_init_status
& RSP_16
) != 0)
265 tr_pcmcia_disable(sc
);
266 sc
->sc_init_status
^= RSP_16
; /* XXX 100 Mbit/s */
268 tr_pcmcia_enable(sc
);
271 * XXX Handle Early Token Release !!!!
278 * XXX Copy of tropic_mediastatus()
281 tr_pcmcia_mediastatus(struct tr_softc
*sc
, struct ifmediareq
*ifmr
)
283 struct ifmedia
*ifm
= &sc
->sc_media
;
285 ifmr
->ifm_active
= ifm
->ifm_cur
->ifm_media
;
289 tr_pcmcia_detach(device_t self
, int flags
)
291 struct tr_pcmcia_softc
*psc
= (struct tr_pcmcia_softc
*)self
;
294 rv
= tr_detach(self
, flags
);
297 pcmcia_mem_unmap(psc
->sc_pf
, psc
->sc_mmio_window
);
298 pcmcia_mem_free(psc
->sc_pf
, &psc
->sc_mmioh
);
299 pcmcia_mem_unmap(psc
->sc_pf
, psc
->sc_sram_window
);
300 pcmcia_mem_free(psc
->sc_pf
, &psc
->sc_sramh
);
301 pcmcia_io_unmap(psc
->sc_pf
, psc
->sc_pio_window
);
302 pcmcia_io_free(psc
->sc_pf
, &psc
->sc_pioh
);
309 tr_pcmcia_setup(struct tr_softc
*sc
)
313 bus_space_write_1(sc
->sc_piot
, sc
->sc_pioh
, 0,
314 (TR_PCMCIA_MMIO_ADDR
>> 16) & 0x0f);
316 bus_space_write_1(sc
->sc_piot
, sc
->sc_pioh
, 0,
317 0x10 | ((TR_PCMCIA_MMIO_ADDR
>> 12) & 0x0e));
320 bus_space_write_1(sc
->sc_piot
, sc
->sc_pioh
, 0, 0x20 | 0x06);
322 /* 0 << 2 for 8K, 1 << 2 for 16K, 2 << 2 for 32K, 3 << 2 for 64K */
323 /* 0 << 1 for 4Mbit/s, 1 << 1 for 16Mbit/s */
324 /* 0 for primary, 1 for alternate */
325 s
= sc
->sc_init_status
& RSP_16
? (1 << 1) : (0 << 1);
326 bus_space_write_1(sc
->sc_piot
, sc
->sc_pioh
, 0, 0x30 | 0x04 | s
);
328 /* Release the card. */
329 bus_space_write_1(sc
->sc_piot
, sc
->sc_pioh
, 0, 0x40);