diff options
author | imp <imp@FreeBSD.org> | 2005-08-15 18:28:49 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2005-08-15 18:28:49 +0000 |
commit | 28016f6d565417605237115340be931eccc374ef (patch) | |
tree | ca9b33b02836348f958d86cd8fc80fb0cbed9eb0 /sys | |
parent | 4203da7e61ebc52ab92ebcc0076f1f973918b138 (diff) | |
download | FreeBSD-src-28016f6d565417605237115340be931eccc374ef.zip FreeBSD-src-28016f6d565417605237115340be931eccc374ef.tar.gz |
Some preliminary support for Megahertz XJEM and CCEM (same cards really)
combo cards.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sn/if_sn_pccard.c | 187 |
1 files changed, 159 insertions, 28 deletions
diff --git a/sys/dev/sn/if_sn_pccard.c b/sys/dev/sn/if_sn_pccard.c index 74577f7..ec603a7 100644 --- a/sys/dev/sn/if_sn_pccard.c +++ b/sys/dev/sn/if_sn_pccard.c @@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$"); #include <net/if_arp.h> #include <machine/bus.h> +#include <machine/resource.h> +#include <sys/rman.h> #include <dev/pccard/pccardvar.h> #include <dev/pccard/pccard_cis.h> @@ -53,29 +55,55 @@ __FBSDID("$FreeBSD$"); #include "card_if.h" #include "pccarddevs.h" +typedef int sn_get_enaddr_t(device_t dev, u_char *eaddr); +typedef int sn_activate_t(device_t dev); + +struct sn_sw +{ + int type; +#define SN_NORMAL 1 +#define SN_MEGAHERTZ 2 +#define SN_OSITECH 3 +#define SN_OSI_SOD 4 +#define SN_MOTO_MARINER 5 + char *typestr; + sn_get_enaddr_t *get_mac; + sn_activate_t *activate; +}; + +static sn_get_enaddr_t sn_pccard_normal_get_mac; +static sn_activate_t sn_pccard_normal_activate; +const static struct sn_sw sn_normal_sw = { + SN_NORMAL, "plain", + sn_pccard_normal_get_mac, + sn_pccard_normal_activate +}; + +static sn_get_enaddr_t sn_pccard_megahertz_get_mac; +static sn_activate_t sn_pccard_megahertz_activate; +const static struct sn_sw sn_mhz_sw = { + SN_MEGAHERTZ, "Megahertz", + sn_pccard_megahertz_get_mac, + sn_pccard_megahertz_activate +}; + static const struct sn_product { struct pccard_product prod; - int type; -#define SN_NORMAL 0 /* Normal, simple smc91cxx card */ -#define SN_MEGAHERTZ 1 -#define SN_MOTO_MARINER 2 -#define SN_OSI_SOD 3 -#define SN_OSITECH 4 - int flags; -#define SN_ALLOC_CLOSE 0x0001 + const struct sn_sw *sw; } sn_pccard_products[] = { - { PCMCIA_CARD(DSPSI, XJACK), SN_NORMAL }, + { PCMCIA_CARD(DSPSI, XJEM1144), &sn_mhz_sw }, + { PCMCIA_CARD(DSPSI, XJACK), &sn_normal_sw }, /* { PCMCIA_CARD(MOTOROLA, MARINER), SN_MOTO_MARINER }, */ - { PCMCIA_CARD(NEWMEDIA, BASICS), SN_NORMAL }, -/* { PCMCIA_CARD(MEGAHERTZ, VARIOUS), SN_MEGAHERTZ}, */ -/* { PCMCIA_CARD(MEGAHERTZ, XJEM3336), SN_MEGAHERTZ}, */ + { PCMCIA_CARD(NEWMEDIA, BASICS), &sn_normal_sw }, + { PCMCIA_CARD(MEGAHERTZ, VARIOUS), &sn_mhz_sw}, + { PCMCIA_CARD(MEGAHERTZ, XJEM3336), &sn_mhz_sw}, /* { PCMCIA_CARD(OSITECH, TRUMP_SOD), SN_OSI_SOD }, */ /* { PCMCIA_CARD(OSITECH, TRUMP_JOH), SN_OSITECH }, */ /* { PCMCIA_CARD(PSION, GOLDCARD), SN_OSITECH }, */ /* { PCMCIA_CARD(PSION, NETGLOBAL), SNI_OSI_SOD }, */ /* { PCMCIA_CARD(PSION, NETGLOBAL2), SN_OSITECH }, */ - { PCMCIA_CARD(SMC, 8020BT), SN_NORMAL }, - { PCMCIA_CARD(SMC, SMC91C96), SN_NORMAL }, + { PCMCIA_CARD(SMC, 8020BT), &sn_normal_sw }, + { PCMCIA_CARD(SMC, SMC91C96), &sn_normal_sw }, { { NULL } } }; @@ -108,9 +136,8 @@ sn_pccard_ascii_enaddr(const char *str, u_char *enet) { uint8_t digit; int i; - + memset(enet, 0, ETHER_ADDR_LEN); - for (i = 0, digit = 0; i < (ETHER_ADDR_LEN * 2); i++) { if (str[i] >= '0' && str[i] <= '9') digit |= str[i] - '0'; @@ -118,10 +145,8 @@ sn_pccard_ascii_enaddr(const char *str, u_char *enet) digit |= (str[i] - 'a') + 10; else if (str[i] >= 'A' && str[i] <= 'F') digit |= (str[i] - 'A') + 10; - else { - /* Bogus digit!! */ - return (0); - } + else + return (0); /* Bogus digit!! */ /* Compensate for ordering of digits. */ if (i & 1) { @@ -135,14 +160,10 @@ sn_pccard_ascii_enaddr(const char *str, u_char *enet) } static int -sn_pccard_attach(device_t dev) +sn_pccard_normal_get_mac(device_t dev, u_char *eaddr) { - struct sn_softc *sc = device_get_softc(dev); + int i, sum; const char *cisstr; - u_char eaddr[ETHER_ADDR_LEN]; - int i, err; - uint16_t w; - u_char sum; pccard_get_ether(dev, eaddr); for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) @@ -157,16 +178,126 @@ sn_pccard_attach(device_t dev) if (cisstr && strlen(cisstr) == ETHER_ADDR_LEN * 2) sum = sn_pccard_ascii_enaddr(cisstr, eaddr); } + return sum; +} + +static int +sn_pccard_normal_activate(device_t dev) +{ + int err; + + err = sn_activate(dev); + if (err) + sn_deactivate(dev); + return (err); +} + +static int +sn_pccard_megahertz_mac(const struct pccard_tuple *tuple, void *argp) +{ + uint8_t *enaddr = argp; + int i; + uint8_t buffer[ETHER_ADDR_LEN * 2]; + + /* Code 0x81 is Megahertz' special cis node contianing the MAC */ + if (tuple->code != 0x81) + return (0); + + /* Make sure this is a sane node, as ASCII digits */ + if (tuple->length != ETHER_ADDR_LEN * 2 + 1) + return (0); + + /* Copy the MAC ADDR and return success if decoded */ + for (i = 0; i < ETHER_ADDR_LEN * 2; i++) + buffer[i] = pccard_tuple_read_1(tuple, i); + return (sn_pccard_ascii_enaddr(buffer, enaddr)); +} + +static int +sn_pccard_megahertz_get_mac(device_t dev, u_char *eaddr) +{ + + if (sn_pccard_normal_get_mac(dev, eaddr)) + return 1; + /* + * If that fails, try the special CIS tuple 0x81 that the + * '3288 and '3336 cards have. That tuple specifies an ASCII + * string, ala CIS3 or CIS4 in the 'normal' cards. + */ + return CARD_CIS_SCAN(device_get_parent(dev), sn_pccard_megahertz_mac, + eaddr); +} + +static int +sn_pccard_megahertz_activate(device_t dev) +{ + int err; + struct sn_softc *sc = device_get_softc(dev); + u_long start; - /* Allocate resources so we can program the ether addr */ - sc->dev = dev; err = sn_activate(dev); if (err) { sn_deactivate(dev); return (err); } + /* + * CIS resource is the modem one, so save it away. + */ + sc->modem_rid = sc->port_rid; + sc->modem_res = sc->port_res; + + /* + * The MHz XJEM/CCEM series of cards just need to have any + * old resource allocated for the ethernet side of things, + * provided bit 0x80 isn't set in the address. That bit is + * evidentially reserved for modem function and is how the + * card steers the addresses internally. + */ + sc->port_res = NULL; + start = 0; + do + { + sc->port_rid = 1; + sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, + &sc->port_rid, start, ~0, SMC_IO_EXTENT, RF_ACTIVE); + if (sc->port_res == NULL) + break; + if (!(rman_get_start(sc->port_res) & 0x80)) + break; + start = rman_get_start(sc->port_res) + SMC_IO_EXTENT; + bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, + sc->port_res); + } while (start < 0xff80); + if (sc->port_res == NULL) { + sn_deactivate(dev); + return ENOMEM; + } + sc->bst = rman_get_bustag(sc->port_res); + sc->bsh = rman_get_bushandle(sc->port_res); + return 0; +} + +static int +sn_pccard_attach(device_t dev) +{ + struct sn_softc *sc = device_get_softc(dev); + u_char eaddr[ETHER_ADDR_LEN]; + int i, err; + uint16_t w; + u_char sum; + const struct sn_product *pp; + + pp = sn_pccard_lookup(dev); + sum = pp->sw->get_mac(dev, eaddr); + + /* Allocate resources so we can program the ether addr */ + sc->dev = dev; + err = pp->sw->activate(dev); + if (err != 0) + return (err); if (sum) { + printf("Programming sn card's addr\n"); SMC_SELECT_BANK(sc, 1); for (i = 0; i < 3; i++) { w = (uint16_t)eaddr[i * 2] | |