]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/dev/fe/if_fe_pccard.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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 <machine/resource.h>
36 #include <sys/rman.h>
37
38 #include <net/ethernet.h>
39 #include <net/if.h>
40 #include <net/if_mib.h>
41 #include <net/if_media.h>
42
43 #include <netinet/in.h>
44 #include <netinet/if_ether.h>
45
46 #include <dev/fe/mb86960.h>
47 #include <dev/fe/if_fereg.h>
48 #include <dev/fe/if_fevar.h>
49
50 #include <dev/pccard/pccardvar.h>
51 #include <dev/pccard/pccard_cis.h>
52
53 #include "card_if.h"
54 #include "pccarddevs.h"
55
56 /*
57  *      PC Card (PCMCIA) specific code.
58  */
59 static int fe_pccard_probe(device_t);
60 static int fe_pccard_attach(device_t);
61 static int fe_pccard_detach(device_t);
62
63 static const struct fe_pccard_product {
64         struct pccard_product mpp_product;
65         int mpp_flags;
66 #define MPP_MBH10302 1
67 #define MPP_ANYFUNC 2
68 } fe_pccard_products[] = {
69         /* These need to be first */
70         { PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 },
71         { PCMCIA_CARD(FUJITSU2, FMV_J182), 0 },
72         { PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 },
73         { PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 },
74         /* These need to be second */
75         { PCMCIA_CARD(TDK, LAK_CD021BX), 0 }, 
76         { PCMCIA_CARD(TDK, LAK_CF010), 0 }, 
77 #if 0 /* XXX 86960-based? */
78         { PCMCIA_CARD(TDK, LAK_DFL9610), 0 }, 
79 #endif
80         { PCMCIA_CARD(CONTEC, CNETPC), 0 },
81         { PCMCIA_CARD(FUJITSU, LA501), 0 },
82         { PCMCIA_CARD(FUJITSU, LA10S), 0 },
83         { PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */
84         { PCMCIA_CARD(RATOC, REX_R280), 0 },
85         { PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC },
86         { { NULL } }
87 };
88
89 static int
90 fe_pccard_probe(device_t dev)
91 {
92         int             error;
93         uint32_t        fcn = PCCARD_FUNCTION_UNSPEC;
94         const struct fe_pccard_product *pp;
95
96         if ((pp = (const struct fe_pccard_product *)pccard_product_lookup(dev,
97             (const struct pccard_product *)fe_pccard_products,
98             sizeof(fe_pccard_products[0]), NULL)) != NULL) {
99                 if (pp->mpp_product.pp_name != NULL)
100                         device_set_desc(dev, pp->mpp_product.pp_name);
101                 if (pp->mpp_flags & MPP_ANYFUNC)
102                         return (0);
103                 /* Make sure we're a network function */
104                 error = pccard_get_function(dev, &fcn);
105                 if (error != 0)
106                         return (error);
107                 if (fcn != PCCARD_FUNCTION_NETWORK)
108                         return (ENXIO);
109                 return (0);
110         }
111         return (ENXIO);
112 }
113
114 static device_method_t fe_pccard_methods[] = {
115         /* Device interface */
116         DEVMETHOD(device_probe,         fe_pccard_probe),
117         DEVMETHOD(device_attach,        fe_pccard_attach),
118         DEVMETHOD(device_detach,        fe_pccard_detach),
119
120         { 0, 0 }
121 };
122
123 static driver_t fe_pccard_driver = {
124         "fe",
125         fe_pccard_methods,
126         sizeof (struct fe_softc)
127 };
128
129 DRIVER_MODULE(fe, pccard, fe_pccard_driver, fe_devclass, 0, 0);
130
131 static int fe_probe_mbh(device_t, const struct fe_pccard_product *);
132 static int fe_probe_tdk(device_t, const struct fe_pccard_product *);
133 /*
134  *      Initialize the device - called from Slot manager.
135  */
136 static int
137 fe_pccard_attach(device_t dev)
138 {
139         struct fe_softc *sc;
140         const struct fe_pccard_product *pp;
141         int error;
142
143         /* Prepare for the device probe process.  */
144         sc = device_get_softc(dev);
145         sc->sc_unit = device_get_unit(dev);
146
147         pp = (const struct fe_pccard_product *) pccard_product_lookup(dev,
148             (const struct pccard_product *)fe_pccard_products,
149             sizeof(fe_pccard_products[0]), NULL);
150         if (pp == NULL)
151                 return (ENXIO);
152
153         if (pp->mpp_flags & MPP_MBH10302)
154                 error = fe_probe_mbh(dev, pp);
155         else
156                 error = fe_probe_tdk(dev, pp);
157         if (error != 0) {
158                 fe_release_resource(dev);
159                 return (error);
160         }
161         error = fe_alloc_irq(dev, 0);
162         if (error != 0) {
163                 fe_release_resource(dev);
164                 return (error);
165         }
166         return (fe_attach(dev));
167 }
168
169 /*
170  *      feunload - unload the driver and clear the table.
171  */
172 static int
173 fe_pccard_detach(device_t dev)
174 {
175         struct fe_softc *sc = device_get_softc(dev);
176         struct ifnet *ifp = sc->ifp;
177
178         fe_stop(sc);
179         ether_ifdetach(ifp);
180         bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
181         if_free(ifp);
182         fe_release_resource(dev);
183
184         return 0;
185 }
186
187
188 /*
189  * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface.
190  * Note that this is for 10302 only; MBH10304 is handled by fe_probe_tdk().
191  */
192 static void
193 fe_init_mbh(struct fe_softc *sc)
194 {
195         /* Minimal initialization of 86960.  */
196         DELAY(200);
197         fe_outb(sc, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE);
198         DELAY(200);
199
200         /* Disable all interrupts.  */
201         fe_outb(sc, FE_DLCR2, 0);
202         fe_outb(sc, FE_DLCR3, 0);
203
204         /* Enable master interrupt flag.  */
205         fe_outb(sc, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE);
206 }
207
208 static int
209 fe_probe_mbh(device_t dev, const struct fe_pccard_product *pp)
210 {
211         struct fe_softc *sc = device_get_softc(dev);
212
213         static struct fe_simple_probe_struct probe_table [] = {
214                 { FE_DLCR2, 0x58, 0x00 },
215                 { FE_DLCR4, 0x08, 0x00 },
216                 { FE_DLCR6, 0xFF, 0xB6 },
217                 { 0 }
218         };
219
220         /* MBH10302 occupies 32 I/O addresses. */
221         if (fe_alloc_port(dev, 32))
222                 return ENXIO;
223
224         /* Fill the softc struct with default values.  */
225         fe_softc_defaults(sc);
226
227         /*
228          * See if MBH10302 is on its address.
229          * I'm not sure the following probe code works.  FIXME.
230          */
231         if (!fe_simple_probe(sc, probe_table))
232                 return ENXIO;
233
234         /* Get our station address from EEPROM.  */
235         fe_inblk(sc, FE_MBH10, sc->enaddr, ETHER_ADDR_LEN);
236
237         /* Make sure we got a valid station address.  */
238         if (!fe_valid_Ether_p(sc->enaddr, 0))
239                 return ENXIO;
240
241         /* Determine the card type.  */
242         sc->type = FE_TYPE_MBH;
243         sc->typestr = "MBH10302 (PCMCIA)";
244
245         /* We seems to need our own IDENT bits...  FIXME.  */
246         sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;
247
248         /* Setup hooks.  We need a special initialization procedure.  */
249         sc->init = fe_init_mbh;
250
251         return 0;
252 }
253
254 static int
255 sn_pccard_xircom_mac(const struct pccard_tuple *tuple, void *argp)
256 {
257         uint8_t *enaddr = argp;
258         int i;
259
260 #if 1
261         /*
262          * We fail to map the CIS twice, for reasons unknown.  We
263          * may fix this in the future by loading the CIS with a sane
264          * CIS from userland.
265          */
266         static uint8_t defaultmac[ETHER_ADDR_LEN] = {
267                 0x00, 0x80, 0xc7, 0xed, 0x16, 0x7b};
268
269         /* Copy the MAC ADDR and return success */
270         for (i = 0; i < ETHER_ADDR_LEN; i++)
271                 enaddr[i] = defaultmac[i];
272 #else
273         /* FUNCE is not after FUNCID, so we gotta go find it */
274         if (tuple->code != 0x22)
275                 return (0);
276
277         /* Make sure this is a sane node */
278         if (tuple->length < ETHER_ADDR_LEN + 3)
279                 return (0);
280
281         /* Copy the MAC ADDR and return success */
282         for (i = 0; i < ETHER_ADDR_LEN; i++)
283                 enaddr[i] = pccard_tuple_read_1(tuple, i + 3);
284 #endif
285         return (1);
286 }
287
288 /*
289  * Probe and initialization for TDK/CONTEC PCMCIA Ethernet interface.
290  * by MASUI Kenji <masui@cs.titech.ac.jp>
291  *
292  * (Contec uses TDK Ethenet chip -- hosokawa)
293  *
294  * This version of fe_probe_tdk has been rewrote to handle
295  * *generic* PC Card implementation of Fujitsu MB8696x family.  The
296  * name _tdk is just for a historical reason. :-)
297  */
298 static int
299 fe_probe_tdk (device_t dev, const struct fe_pccard_product *pp)
300 {
301         struct fe_softc *sc = device_get_softc(dev);
302
303         static struct fe_simple_probe_struct probe_table [] = {
304                 { FE_DLCR2, 0x10, 0x00 },
305                 { FE_DLCR4, 0x08, 0x00 },
306             /*  { FE_DLCR5, 0x80, 0x00 },       Does not work well.  */
307                 { 0 }
308         };
309
310
311         /* C-NET(PC)C occupies 16 I/O addresses. */
312         if (fe_alloc_port(dev, 16))
313                 return ENXIO;
314
315         /* Fill the softc struct with default values.  */
316         fe_softc_defaults(sc);
317
318         /*
319          * See if C-NET(PC)C is on its address.
320          */
321         if (!fe_simple_probe(sc, probe_table))
322                 return ENXIO;
323
324         /* Determine the card type.  */
325         sc->type = FE_TYPE_TDK;
326         sc->typestr = "Generic MB8696x/78Q837x Ethernet (PCMCIA)";
327
328         pccard_get_ether(dev, sc->enaddr);
329
330         /* Make sure we got a valid station address.  */
331         if (!fe_valid_Ether_p(sc->enaddr, 0)) {
332                 pccard_cis_scan(dev, sn_pccard_xircom_mac, sc->enaddr);
333         }
334
335         /* Make sure we got a valid station address.  */
336         if (!fe_valid_Ether_p(sc->enaddr, 0))
337                 return ENXIO;
338
339         return 0;
340 }