2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1999 M. Warner Losh <imp@village.org>
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.
28 * Modifications for Megahertz X-Jack Ethernet Card (XJ-10BT)
30 * Copyright (c) 1996 by Tatsumi Hosokawa <hosokawa@jp.FreeBSD.org>
31 * BSD-nomads, Tokyo, Japan.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/socket.h>
42 #include <sys/systm.h>
44 #include <net/ethernet.h>
46 #include <net/if_arp.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
52 #include <dev/pccard/pccardvar.h>
53 #include <dev/pccard/pccard_cis.h>
54 #include <dev/sn/if_snreg.h>
55 #include <dev/sn/if_snvar.h>
58 #include "pccarddevs.h"
60 typedef int sn_get_enaddr_t(device_t dev, u_char *eaddr);
61 typedef int sn_activate_t(device_t dev);
67 #define SN_MEGAHERTZ 2
70 #define SN_MOTO_MARINER 5
72 sn_get_enaddr_t *get_mac;
73 sn_activate_t *activate;
76 static sn_get_enaddr_t sn_pccard_normal_get_mac;
77 static sn_activate_t sn_pccard_normal_activate;
78 const static struct sn_sw sn_normal_sw = {
80 sn_pccard_normal_get_mac,
81 sn_pccard_normal_activate
84 static sn_get_enaddr_t sn_pccard_megahertz_get_mac;
85 static sn_activate_t sn_pccard_megahertz_activate;
86 const static struct sn_sw sn_mhz_sw = {
87 SN_MEGAHERTZ, "Megahertz",
88 sn_pccard_megahertz_get_mac,
89 sn_pccard_megahertz_activate
92 static const struct sn_product {
93 struct pccard_product prod;
94 const struct sn_sw *sw;
95 } sn_pccard_products[] = {
96 { PCMCIA_CARD(DSPSI, XJEM1144), &sn_mhz_sw },
97 { PCMCIA_CARD(DSPSI, XJACK), &sn_normal_sw },
98 /* { PCMCIA_CARD(MOTOROLA, MARINER), SN_MOTO_MARINER }, */
99 { PCMCIA_CARD(NEWMEDIA, BASICS), &sn_normal_sw },
100 { PCMCIA_CARD(MEGAHERTZ, VARIOUS), &sn_mhz_sw},
101 { PCMCIA_CARD(MEGAHERTZ, XJEM3336), &sn_mhz_sw},
102 /* { PCMCIA_CARD(OSITECH, TRUMP_SOD), SN_OSI_SOD }, */
103 /* { PCMCIA_CARD(OSITECH, TRUMP_JOH), SN_OSITECH }, */
104 /* { PCMCIA_CARD(PSION, GOLDCARD), SN_OSITECH }, */
105 /* { PCMCIA_CARD(PSION, NETGLOBAL), SNI_OSI_SOD }, */
106 /* { PCMCIA_CARD(PSION, NETGLOBAL2), SN_OSITECH }, */
107 { PCMCIA_CARD(SMC, 8020BT), &sn_normal_sw },
108 { PCMCIA_CARD(SMC, SMC91C96), &sn_normal_sw },
113 static const struct sn_product *
114 sn_pccard_lookup(device_t dev)
117 return ((const struct sn_product *)
118 pccard_product_lookup(dev,
119 (const struct pccard_product *)sn_pccard_products,
120 sizeof(sn_pccard_products[0]), NULL));
124 sn_pccard_probe(device_t dev)
126 const struct sn_product *pp;
128 if ((pp = sn_pccard_lookup(dev)) != NULL) {
129 if (pp->prod.pp_name != NULL)
130 device_set_desc(dev, pp->prod.pp_name);
137 sn_pccard_ascii_enaddr(const char *str, u_char *enet)
142 memset(enet, 0, ETHER_ADDR_LEN);
143 for (i = 0, digit = 0; i < (ETHER_ADDR_LEN * 2); i++) {
144 if (str[i] >= '0' && str[i] <= '9')
145 digit |= str[i] - '0';
146 else if (str[i] >= 'a' && str[i] <= 'f')
147 digit |= (str[i] - 'a') + 10;
148 else if (str[i] >= 'A' && str[i] <= 'F')
149 digit |= (str[i] - 'A') + 10;
151 return (0); /* Bogus digit!! */
153 /* Compensate for ordering of digits. */
155 enet[i >> 1] = digit;
165 sn_pccard_normal_get_mac(device_t dev, u_char *eaddr)
170 pccard_get_ether(dev, eaddr);
171 for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
174 pccard_get_cis3_str(dev, &cisstr);
175 if (cisstr && strlen(cisstr) == ETHER_ADDR_LEN * 2)
176 sum = sn_pccard_ascii_enaddr(cisstr, eaddr);
179 pccard_get_cis4_str(dev, &cisstr);
180 if (cisstr && strlen(cisstr) == ETHER_ADDR_LEN * 2)
181 sum = sn_pccard_ascii_enaddr(cisstr, eaddr);
187 sn_pccard_normal_activate(device_t dev)
191 err = sn_activate(dev);
198 sn_pccard_megahertz_mac(const struct pccard_tuple *tuple, void *argp)
200 uint8_t *enaddr = argp;
202 uint8_t buffer[ETHER_ADDR_LEN * 2];
204 /* Code 0x81 is Megahertz' special cis node contianing the MAC */
205 if (tuple->code != 0x81)
208 /* Make sure this is a sane node, as ASCII digits */
209 if (tuple->length != ETHER_ADDR_LEN * 2 + 1)
212 /* Copy the MAC ADDR and return success if decoded */
213 for (i = 0; i < ETHER_ADDR_LEN * 2; i++)
214 buffer[i] = pccard_tuple_read_1(tuple, i);
215 return (sn_pccard_ascii_enaddr(buffer, enaddr));
219 sn_pccard_megahertz_get_mac(device_t dev, u_char *eaddr)
222 if (sn_pccard_normal_get_mac(dev, eaddr))
225 * If that fails, try the special CIS tuple 0x81 that the
226 * '3288 and '3336 cards have. That tuple specifies an ASCII
227 * string, ala CIS3 or CIS4 in the 'normal' cards.
229 return (pccard_cis_scan(dev, sn_pccard_megahertz_mac, eaddr));
233 sn_pccard_megahertz_activate(device_t dev)
236 struct sn_softc *sc = device_get_softc(dev);
239 err = sn_activate(dev);
245 * CIS resource is the modem one, so save it away.
247 sc->modem_rid = sc->port_rid;
248 sc->modem_res = sc->port_res;
251 * The MHz XJEM/CCEM series of cards just need to have any
252 * old resource allocated for the ethernet side of things,
253 * provided bit 0x80 isn't set in the address. That bit is
254 * evidentially reserved for modem function and is how the
255 * card steers the addresses internally.
262 sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
263 &sc->port_rid, start, ~0, SMC_IO_EXTENT, RF_ACTIVE);
264 if (sc->port_res == NULL)
266 if (!(rman_get_start(sc->port_res) & 0x80))
268 start = rman_get_start(sc->port_res) + SMC_IO_EXTENT;
269 bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
271 } while (start < 0xff80);
272 if (sc->port_res == NULL) {
280 sn_pccard_attach(device_t dev)
282 struct sn_softc *sc = device_get_softc(dev);
283 u_char eaddr[ETHER_ADDR_LEN];
287 const struct sn_product *pp;
289 pp = sn_pccard_lookup(dev);
290 sum = pp->sw->get_mac(dev, eaddr);
292 /* Allocate resources so we can program the ether addr */
294 err = pp->sw->activate(dev);
299 printf("Programming sn card's addr\n");
300 SMC_SELECT_BANK(sc, 1);
301 for (i = 0; i < 3; i++) {
302 w = (uint16_t)eaddr[i * 2] |
303 (((uint16_t)eaddr[i * 2 + 1]) << 8);
304 CSR_WRITE_2(sc, IAR_ADDR0_REG_W + i * 2, w);
307 err = sn_attach(dev);
313 static device_method_t sn_pccard_methods[] = {
314 /* Device interface */
315 DEVMETHOD(device_probe, sn_pccard_probe),
316 DEVMETHOD(device_attach, sn_pccard_attach),
317 DEVMETHOD(device_detach, sn_detach),
322 static driver_t sn_pccard_driver = {
325 sizeof(struct sn_softc),
328 extern devclass_t sn_devclass;
330 DRIVER_MODULE(sn, pccard, sn_pccard_driver, sn_devclass, 0, 0);
331 MODULE_DEPEND(sn, ether, 1, 1, 1);
332 PCCARD_PNP_INFO(sn_pccard_products);