]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/fe/if_fe_pccard.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / fe / if_fe_pccard.c
1 /*-
2  * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
3  *
4  * This software may be used, modified, copied, distributed, and sold, in
5  * both source and binary form provided that the above copyright, these
6  * terms and the following disclaimer are retained.  The name of the author
7  * and/or the contributor may not be used to endorse or promote products
8  * derived from this software without specific prior written permission.
9  *
10  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``AS IS'' AND
11  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTOR BE LIABLE
14  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
15  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION.
17  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
19  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
20  * SUCH DAMAGE.
21  *
22  */
23
24 #include <sys/cdefs.h>
25 __FBSDID("$FreeBSD$");
26
27 #include <sys/param.h>
28 #include <sys/kernel.h>
29 #include <sys/socket.h>
30 #include <sys/systm.h>
31 #include <sys/module.h>
32
33 #include <sys/bus.h>
34 #include <machine/bus.h>
35 #include <sys/rman.h>
36
37 #include <net/ethernet.h>
38 #include <net/if.h>
39 #include <net/if_mib.h>
40 #include <net/if_media.h>
41
42 #include <netinet/in.h>
43 #include <netinet/if_ether.h>
44
45 #include <dev/fe/mb86960.h>
46 #include <dev/fe/if_fereg.h>
47 #include <dev/fe/if_fevar.h>
48
49 #include <dev/pccard/pccardvar.h>
50 #include <dev/pccard/pccard_cis.h>
51
52 #include "card_if.h"
53 #include "pccarddevs.h"
54
55 /*
56  *      PC Card (PCMCIA) specific code.
57  */
58 static int fe_pccard_probe(device_t);
59 static int fe_pccard_attach(device_t);
60 static int fe_pccard_detach(device_t);
61
62 static const struct fe_pccard_product {
63         struct pccard_product mpp_product;
64         int mpp_flags;
65         int mpp_cfe;
66 #define MPP_MBH10302 1
67 #define MPP_ANYFUNC 2
68 #define MPP_SKIP_TO_CFE 4
69 } fe_pccard_products[] = {
70         /* These need to be first */
71         { PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 },
72         { PCMCIA_CARD(FUJITSU2, FMV_J182), 0 },
73         { PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 },
74         { PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 },
75         /* These need to be second */
76         { PCMCIA_CARD(TDK, LAK_CD011), 0 }, 
77         { PCMCIA_CARD(TDK, LAK_CD021BX), 0 }, 
78         { PCMCIA_CARD(TDK, LAK_CF010), 0 }, 
79 #if 0 /* XXX 86960-based? */
80         { PCMCIA_CARD(TDK, LAK_DFL9610), 0 }, 
81 #endif
82         { PCMCIA_CARD(CONTEC, CNETPC), MPP_SKIP_TO_CFE, 2 },
83         { PCMCIA_CARD(FUJITSU, LA501), 0 },
84         { PCMCIA_CARD(FUJITSU, LA10S), 0 },
85         { PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */
86         { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE, 10 },
87         { PCMCIA_CARD(RATOC, REX_R280), 0 },
88         { PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC },
89         { { NULL } }
90 };
91
92 static int
93 fe_pccard_probe(device_t dev)
94 {
95         int             error;
96         uint32_t        fcn = PCCARD_FUNCTION_UNSPEC;
97         const struct fe_pccard_product *pp;
98         int i;
99
100         if ((pp = (const struct fe_pccard_product *)pccard_product_lookup(dev,
101                  (const struct pccard_product *)fe_pccard_products,
102                  sizeof(fe_pccard_products[0]), NULL)) != NULL) {
103                 if (pp->mpp_product.pp_name != NULL)
104                         device_set_desc(dev, pp->mpp_product.pp_name);
105                 if (pp->mpp_flags & MPP_ANYFUNC)
106                         return (0);
107                 /* Make sure we're a network function */
108                 error = pccard_get_function(dev, &fcn);
109                 if (error != 0)
110                         return (error);
111                 if (fcn != PCCARD_FUNCTION_NETWORK)
112                         return (ENXIO);
113                 if (pp->mpp_flags & MPP_SKIP_TO_CFE) {
114                         for (i = pp->mpp_cfe; i < 32; i++) {
115                                 if (pccard_select_cfe(dev, i) == 0)
116                                         goto good;
117                         }
118                         device_printf(dev,
119                             "Failed to map CFE %d or higher\n", pp->mpp_cfe);
120                         return ENXIO;
121                 }
122         good:;
123                 return (0);
124         }
125         return (ENXIO);
126 }
127
128 static device_method_t fe_pccard_methods[] = {
129         /* Device interface */
130         DEVMETHOD(device_probe,         fe_pccard_probe),
131         DEVMETHOD(device_attach,        fe_pccard_attach),
132         DEVMETHOD(device_detach,        fe_pccard_detach),
133
134         { 0, 0 }
135 };
136
137 static driver_t fe_pccard_driver = {
138         "fe",
139         fe_pccard_methods,
140         sizeof (struct fe_softc)
141 };
142
143 DRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0);
144 MODULE_DEPEND(fe, pccard, 1, 1, 1);
145
146 static int fe_probe_mbh(device_t, const struct fe_pccard_product *);
147 static int fe_probe_tdk(device_t, const struct fe_pccard_product *);
148
149 static int
150 fe_pccard_attach(device_t dev)
151 {
152         struct fe_softc *sc;
153         const struct fe_pccard_product *pp;
154         int error;
155
156         /* Prepare for the device probe process.  */
157         sc = device_get_softc(dev);
158         sc->sc_unit = device_get_unit(dev);
159
160         pp = (const struct fe_pccard_product *) pccard_product_lookup(dev,
161             (const struct pccard_product *)fe_pccard_products,
162             sizeof(fe_pccard_products[0]), NULL);
163         if (pp == NULL)
164                 return (ENXIO);
165
166         if (pp->mpp_flags & MPP_MBH10302)
167                 error = fe_probe_mbh(dev, pp);
168         else
169                 error = fe_probe_tdk(dev, pp);
170         if (error != 0) {
171                 fe_release_resource(dev);
172                 return (error);
173         }
174         error = fe_alloc_irq(dev, 0);
175         if (error != 0) {
176                 fe_release_resource(dev);
177                 return (error);
178         }
179         return (fe_attach(dev));
180 }
181
182 /*
183  *      feunload - unload the driver and clear the table.
184  */
185 static int
186 fe_pccard_detach(device_t dev)
187 {
188         struct fe_softc *sc = device_get_softc(dev);
189         struct ifnet *ifp = sc->ifp;
190
191         FE_LOCK(sc);
192         fe_stop(sc);
193         FE_UNLOCK(sc);
194         callout_drain(&sc->timer);
195         ether_ifdetach(ifp);
196         bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
197         if_free(ifp);
198         fe_release_resource(dev);
199         mtx_destroy(&sc->lock);
200
201         return 0;
202 }
203
204
205 /*
206  * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface.
207  * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk().
208  */
209 static void
210 fe_init_mbh(struct fe_softc *sc)
211 {
212         /* Minimal initialization of 86960.  */
213         DELAY(200);
214         fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
215         DELAY(200);
216
217         /* Disable all interrupts.  */
218         fe_outb(sc, FE_DLCR2, 0);
219         fe_outb(sc, FE_DLCR3, 0);
220
221         /* Enable master interrupt flag.  */
222         fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE);
223 }
224
225 static int
226 fe_probe_mbh(device_t dev, const struct fe_pccard_product *pp)
227 {
228         struct fe_softc *sc = device_get_softc(dev);
229
230         static struct fe_simple_probe_struct probe_table [] = {
231                 { FE_DLCR2, 0x58, 0x00 },
232                 { FE_DLCR4, 0x08, 0x00 },
233                 { FE_DLCR6, 0xFF, 0xB6 },
234                 { 0 }
235         };
236
237         /* MBH10302 occupies 32 I/O addresses. */
238         if (fe_alloc_port(dev, 32))
239                 return ENXIO;
240
241         /* Fill the softc struct with default values.  */
242         fe_softc_defaults(sc);
243
244         /*
245          * See if MBH10302 is on its address.
246          * I'm not sure the following probe code works.  FIXME.
247          */
248         if (!fe_simple_probe(sc, probe_table))
249                 return ENXIO;
250
251         /* Get our station address from EEPROM.  */
252         fe_inblk(sc, FE_MBH10, sc->enaddr, ETHER_ADDR_LEN);
253
254         /* Make sure we got a valid station address.  */
255         if (!fe_valid_Ether_p(sc->enaddr, 0))
256                 return ENXIO;
257
258         /* Determine the card type.  */
259         sc->type = FE_TYPE_MBH;
260         sc->typestr = "MBH10302 (PCMCIA)";
261
262         /* We seems to need our own IDENT bits...  FIXME.  */
263         sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
264
265         /* Setup hooks.  We need a special initialization procedure.  */
266         sc->init = fe_init_mbh;
267
268         return 0;
269 }
270
271 static int
272 fe_pccard_xircom_mac(const struct pccard_tuple *tuple, void *argp)
273 {
274         uint8_t *enaddr = argp;
275         int i;
276
277 #if 1
278         /*
279          * We fail to map the CIS twice, for reasons unknown.  We
280          * may fix this in the future by loading the CIS with a sane
281          * CIS from userland.
282          */
283         static uint8_t defaultmac[ETHER_ADDR_LEN] = {
284                 0x00, 0x80, 0xc7, 0xed, 0x16, 0x7b};
285
286         /* Copy the MAC ADDR and return success */
287         for (i = 0; i < ETHER_ADDR_LEN; i++)
288                 enaddr[i] = defaultmac[i];
289 #else
290         /* FUNCE is not after FUNCID, so we gotta go find it */
291         if (tuple->code != 0x22)
292                 return (0);
293
294         /* Make sure this is a sane node */
295         if (tuple->length < ETHER_ADDR_LEN + 3)
296                 return (0);
297
298         /* Copy the MAC ADDR and return success */
299         for (i = 0; i < ETHER_ADDR_LEN; i++)
300                 enaddr[i] = pccard_tuple_read_1(tuple, i + 3);
301 #endif
302         return (1);
303 }
304
305 /*
306  * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface.
307  * by MASUI Kenji <masui@cs.titech.ac.jp>
308  *
309  * (Contec uses TDK Ethernet chip -- hosokawa)
310  *
311  * This version of fe_probe_tdk has been rewrote to handle
312  * *generic* PC Card implementation of Fujitsu MB8696x family.  The
313  * name _tdk is just for a historical reason. :-)
314  */
315 static int
316 fe_probe_tdk (device_t dev, const struct fe_pccard_product *pp)
317 {
318         struct fe_softc *sc = device_get_softc(dev);
319
320         static struct fe_simple_probe_struct probe_table [] = {
321                 { FE_DLCR2, 0x10, 0x00 },
322                 { FE_DLCR4, 0x08, 0x00 },
323 /*              { FE_DLCR5, 0x80, 0x00 },       Does not work well.  */
324                 { 0 }
325         };
326
327
328         /* C-NET(PC)C occupies 16 I/O addresses. */
329         if (fe_alloc_port(dev, 16))
330                 return ENXIO;
331
332         /* Fill the softc struct with default values.  */
333         fe_softc_defaults(sc);
334
335         /*
336          * See if C-NET(PC)C is on its address.
337          */
338         if (!fe_simple_probe(sc, probe_table))
339                 return ENXIO;
340
341         /* Determine the card type.  */
342         sc->type = FE_TYPE_TDK;
343         sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)";
344
345         pccard_get_ether(dev, sc->enaddr);
346
347         /* Make sure we got a valid station address.  */
348         if (!fe_valid_Ether_p(sc->enaddr, 0)) {
349                 pccard_cis_scan(dev, fe_pccard_xircom_mac, sc->enaddr);
350         }
351
352         /* Make sure we got a valid station address.  */
353         if (!fe_valid_Ether_p(sc->enaddr, 0))
354                 return ENXIO;
355
356         return 0;
357 }