Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pcmcia / if_tr_pcmcia.c
blob0703dfc24b08b16cc28e117233e3aa7faf5c2dc1
1 /* $NetBSD: if_tr_pcmcia.c,v 1.23 2009/05/12 14:42:18 cegger Exp $ */
3 /*
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
9 * are met:
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>
43 #include <sys/mbuf.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>
51 #include <net/if.h>
52 #include <net/if_dl.h>
53 #include <net/if_ether.h>
54 #include <net/if_media.h>
56 #include <sys/bus.h>
57 #include <sys/intr.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
73 #endif
74 #ifndef TR_PCMCIA_MMIO_ADDR
75 #define TR_PCMCIA_MMIO_ADDR 0xcc000
76 #endif
78 struct tr_pcmcia_softc {
79 struct tr_softc sc_tr;
81 struct pcmcia_io_handle sc_pioh;
82 int sc_pio_window;
83 struct pcmcia_mem_handle sc_sramh;
84 int sc_sram_window;
85 struct pcmcia_mem_handle sc_mmioh;
86 int sc_mmio_window;
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);
102 static int
103 tr_pcmcia_match(device_t parent, cfdata_t match,
104 void *aux)
106 struct pcmcia_attach_args *pa = aux;
108 if (pa->manufacturer == PCMCIA_VENDOR_IBM)
109 switch (pa->product) {
110 case PCMCIA_PRODUCT_IBM_TROPIC:
111 return 1;
114 return 0;
117 static void
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;
124 bus_size_t offset;
126 psc->sc_pf = pa->pf;
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");
133 return;
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");
139 goto fail1;
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");
144 goto fail2;
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");
149 goto fail3;
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");
154 goto fail4;
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");
159 goto fail5;
160 return;
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");
165 goto fail6;
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;
184 tr_pcmcia_setup(sc);
185 if (tr_reset(sc) == 0)
186 (void)tr_attach(sc);
188 pcmcia_function_disable(pa->pf);
189 sc->sc_enabled = 0;
190 return;
192 fail6:
193 pcmcia_mem_free(psc->sc_pf, &psc->sc_mmioh);
194 fail5:
195 pcmcia_mem_unmap(psc->sc_pf, psc->sc_sram_window);
196 fail4:
197 pcmcia_mem_free(psc->sc_pf, &psc->sc_sramh);
198 fail3:
199 pcmcia_io_unmap(psc->sc_pf, psc->sc_pio_window);
200 fail2:
201 pcmcia_io_free(psc->sc_pf, &psc->sc_pioh);
202 fail1:
203 pcmcia_function_disable(pa->pf);
204 sc->sc_enabled = 0;
207 static int
208 tr_pcmcia_enable(struct tr_softc *sc)
210 struct tr_pcmcia_softc *psc = (struct tr_pcmcia_softc *) sc;
211 int ret;
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");
216 return 1;
219 ret = pcmcia_function_enable(psc->sc_pf);
220 if (ret != 0)
221 return ret;
223 tr_pcmcia_setup(sc);
225 if (tr_reset(sc))
226 return 1;
227 if (tr_config(sc))
228 return 1;
230 return 0;
233 static void
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);
242 static int
243 tr_pcmcia_mediachange(struct tr_softc *sc)
245 int setspeed = 0;
247 if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_TOKEN)
248 return EINVAL;
250 switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
251 case IFM_TOK_STP16:
252 case IFM_TOK_UTP16:
253 if ((sc->sc_init_status & RSP_16) == 0)
254 setspeed = 1;
255 break;
256 case IFM_TOK_STP4:
257 case IFM_TOK_UTP4:
258 if ((sc->sc_init_status & RSP_16) != 0)
259 setspeed = 1;
260 break;
262 if (setspeed != 0) {
263 tr_stop(sc);
264 if (sc->sc_enabled)
265 tr_pcmcia_disable(sc);
266 sc->sc_init_status ^= RSP_16; /* XXX 100 Mbit/s */
267 if (sc->sc_enabled)
268 tr_pcmcia_enable(sc);
271 * XXX Handle Early Token Release !!!!
274 return 0;
278 * XXX Copy of tropic_mediastatus()
280 static void
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;
292 int rv;
294 rv = tr_detach(self, flags);
296 if (rv == 0) {
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);
305 return rv;
308 static void
309 tr_pcmcia_setup(struct tr_softc *sc)
311 int s;
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));
319 /* XXX Magick */
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);