2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2000 Mitsuru IWASAKI
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 AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/socket.h>
38 #include <sys/module.h>
41 #include <machine/bus.h>
42 #include <machine/resource.h>
46 #include <net/if_arp.h>
47 #include <net/if_media.h>
49 #include <dev/ex/if_exreg.h>
50 #include <dev/ex/if_exvar.h>
52 #include <dev/pccard/pccardvar.h>
53 #include <dev/pccard/pccard_cis.h>
54 #include "pccarddevs.h"
56 static const struct pccard_product ex_pccard_products[] = {
57 PCMCIA_CARD(OLICOM, OC2220),
58 PCMCIA_CARD(OLICOM, OC2231),
59 PCMCIA_CARD(OLICOM, OC2232),
60 PCMCIA_CARD(INTEL, ETHEREXPPRO),
64 /* Bus Front End Functions */
65 static int ex_pccard_probe(device_t);
66 static int ex_pccard_attach(device_t);
69 ex_pccard_enet_ok(u_char *enaddr)
74 if (enaddr[0] == 0xff)
76 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
82 ex_pccard_silicom_cb(const struct pccard_tuple *tuple, void *arg)
87 if (tuple->code != CISTPL_FUNCE)
89 if (tuple->length != 15)
91 if (pccard_tuple_read_1(tuple, 6) != 6)
93 for (i = 0; i < 6; i++)
94 enaddr[i] = pccard_tuple_read_1(tuple, 7 + i);
99 ex_pccard_get_silicom_mac(device_t dev, u_char *ether_addr)
101 pccard_cis_scan(dev, ex_pccard_silicom_cb, ether_addr);
105 ex_pccard_probe(device_t dev)
107 const struct pccard_product *pp;
109 uint32_t fcn = PCCARD_FUNCTION_UNSPEC;
111 if ((pp = pccard_product_lookup(dev, ex_pccard_products,
112 sizeof(ex_pccard_products[0]), NULL)) == NULL)
114 if (pp->pp_name != NULL)
115 device_set_desc(dev, pp->pp_name);
117 * Olicom 22.8k and 33.6k modems need to activate the right
118 * CFE. The odd formula below replicates the sequence of cfes
119 * that have multiple resources:
120 * 9, 11, 13, 15, 0 + 9
121 * 25, 27, 29, 31, 16 + 9
122 * 41, 43, 45, 47, 32 + 9
123 * 57, 59, 61, 63 48 + 9
124 * (entries 8, 24, 40 and 56 are single resoruce cfes)
125 * Fortunately the code that enables and disables the multiple
126 * fuctions of the card won't mess with the lower bit for cards
127 * that aren't stanards conforming MFC cards (which these olicom
130 * Note: These cards still don't get interrupts for reasons
131 * unknown, even when the right cfe is selected. There's likely
132 * something in the CCR that needs to be manually tweaked, but
133 * the COR bits seem to all be used. Bit 0 and 3 are always set
134 * and the other bits select the config to use. Maybe one of those
135 * two bits needs to be cleared, or there's something else in the
136 * CCR that needs tweaking. The pattern of resources suggests
137 * bit 0 turns on the ethernet, however...
139 if (pp->pp_vendor == PCMCIA_VENDOR_OLICOM &&
140 (pp->pp_product == PCMCIA_PRODUCT_OLICOM_OC2231 ||
141 pp->pp_product == PCMCIA_PRODUCT_OLICOM_OC2232)) {
142 if (pccard_select_cfe(dev, 1) == 0)
144 for (i = 0; i < 4; i++) {
145 for (j = 0; j < 4; j++) {
146 printf("Trying %d %d\n", i, j);
147 if (pccard_select_cfe(dev,
148 (i << 4) + (j << 1) + 9) == 0)
152 /* Can't activate the net entries, punt */
156 * All other cards supported by this driver don't need specail
157 * treatment, so just filter based on the type of card. The
158 * special treatment ones are setup to 'fail safe' to a modem so
159 * this check would effectively filter them out as well.
161 error = pccard_get_function(dev, &fcn);
164 if (fcn != PCCARD_FUNCTION_NETWORK)
171 ex_pccard_attach(device_t dev)
173 struct ex_softc * sc = device_get_softc(dev);
175 u_char ether_addr[ETHER_ADDR_LEN];
181 if ((error = ex_alloc_resources(dev)) != 0) {
182 device_printf(dev, "ex_alloc_resources() failed!\n");
187 * Fill in several fields of the softc structure:
188 * - Hardware Ethernet address.
191 sc->irq_no = rman_get_start(sc->irq);
193 /* Try to get the ethernet address from the chip, then the CIS */
194 ex_get_address(sc, ether_addr);
195 if (!ex_pccard_enet_ok(ether_addr))
196 pccard_get_ether(dev, ether_addr);
197 if (!ex_pccard_enet_ok(ether_addr))
198 ex_pccard_get_silicom_mac(dev, ether_addr);
199 if (!ex_pccard_enet_ok(ether_addr)) {
200 device_printf(dev, "No NIC address found.\n");
204 bcopy(ether_addr, sc->enaddr, ETHER_ADDR_LEN);
206 if ((error = ex_attach(dev)) != 0) {
207 device_printf(dev, "ex_attach() failed!\n");
213 ex_release_resources(dev);
216 static device_method_t ex_pccard_methods[] = {
217 /* Device interface */
218 DEVMETHOD(device_probe, ex_pccard_probe),
219 DEVMETHOD(device_attach, ex_pccard_attach),
220 DEVMETHOD(device_detach, ex_detach),
225 static driver_t ex_pccard_driver = {
228 sizeof(struct ex_softc),
231 DRIVER_MODULE(ex, pccard, ex_pccard_driver, ex_devclass, 0, 0);
232 MODULE_DEPEND(ex, pccard, 1, 1, 1);
233 PCCARD_PNP_INFO(ex_pccard_products);