diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2007-05-27 06:04:39 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2007-05-27 06:04:39 +0000 |
commit | 6ecee977905fec92cda018a25f426843b211af40 (patch) | |
tree | 853aa87f21cdc3ba4ddde62e6bc0051a34698992 /sys/dev/pci | |
parent | 5e25f9ecff8fba6abb65cf470ea47711f268ac85 (diff) |
Attach ifp to che(4) by cheating a bit -- at least in dlg's opinion.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_che.c | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/sys/dev/pci/if_che.c b/sys/dev/pci/if_che.c index e4aea39461e..598acf9bcd4 100644 --- a/sys/dev/pci/if_che.c +++ b/sys/dev/pci/if_che.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_che.c,v 1.4 2007/05/27 05:52:35 dlg Exp $ */ +/* $OpenBSD: if_che.c,v 1.5 2007/05/27 06:04:38 claudio Exp $ */ /* * Copyright (c) 2007 Claudio Jeker <claudio@openbsd.org> @@ -179,6 +179,7 @@ struct che_attach_args { struct pci_attach_args *caa_pa; pci_intr_handle_t caa_ih; int caa_port; + u_int8_t caa_lladdr[ETHER_ADDR_LEN]; }; /* che itself */ @@ -188,7 +189,11 @@ struct che_softc { struct arpcom sc_ac; struct ifmedia sc_media; + struct cheg_softc *sc_cheg; + void *sc_ih; + + int sc_port; }; int che_match(struct device *, void *, void *); @@ -214,7 +219,12 @@ int che_read_eeprom(struct cheg_softc *, struct pci_attach_args *, pcireg_t, pcireg_t *); int che_get_vpd(struct cheg_softc *, struct pci_attach_args *, void *, size_t); +void che_conv_lladdr(char *, u_int8_t *); void che_reset(struct cheg_softc *); +int che_ioctl(struct ifnet *, u_long, caddr_t); +void che_watchdog(struct ifnet *); +void che_start(struct ifnet *); + /* bus_space wrappers */ u_int32_t che_read(struct cheg_softc *, bus_size_t); @@ -320,10 +330,19 @@ cheg_attach(struct device *parent, struct device *self, void *aux) FW_VERS_MAJOR(vers), FW_VERS_MINOR(vers), FW_VERS_MICRO(vers)); caa.caa_pa = pa; + che_conv_lladdr(vpd.na_data, caa.caa_lladdr); + for (i = 0; i < cd->cd_nports; i++) { caa.caa_port = i; config_found(self, &caa, cheg_print); + + /* + * The VPD EEPROM stores only the base Ethernet address for the + * card. The last octet is increased by one for every additional + * port. + */ + caa.caa_lladdr[5] += 1; } return; @@ -355,7 +374,33 @@ che_match(struct device *parent, void *match, void *aux) void che_attach(struct device *parent, struct device *self, void *aux) { - printf(": not done yet\n"); + struct cheg_softc *gsc = (struct cheg_softc *)parent; + struct che_softc *sc = (struct che_softc *)self; + struct che_attach_args *caa = aux; + struct ifnet *ifp; + + sc->sc_cheg = gsc; + + sc->sc_port = caa->caa_port; + bcopy(caa->caa_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); + + ifp = &sc->sc_ac.ac_if; + ifp->if_softc = sc; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = che_ioctl; + ifp->if_start = che_start; + ifp->if_watchdog = che_watchdog; + ifp->if_hardmtu = MCLBYTES - ETHER_HDR_LEN - ETHER_CRC_LEN; /* XXX */ + strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ); + IFQ_SET_MAXLEN(&ifp->if_snd, 400); + IFQ_SET_READY(&ifp->if_snd); + + /* XXX ifmedia */ + + if_attach(ifp); + ether_ifattach(ifp); + + printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr)); return; } @@ -472,6 +517,33 @@ che_get_vpd(struct cheg_softc *sc, struct pci_attach_args *pa, return (0); } +/* + * VPD mac addr is stored as ASCII string so we need to convert it to a + * sane representation form. + */ +void +che_conv_lladdr(char *mac, u_int8_t *lladdr) +{ + int i; + u_int8_t digit; + + bzero(lladdr, ETHER_ADDR_LEN); + + for (i = 0; i < ETHER_ADDR_LEN * 2; i++) { + if (mac[i] >= '0' && mac[i] <= '9') + digit = mac[i] - '0'; + else if (mac[i] >= 'A' && mac[i] <= 'F') + digit = mac[i] - 'A' + 10; + else if (mac[i] >= 'a' && mac[i] <= 'f') + digit = mac[i] - 'a' + 10; + + if (i & 1) + digit <<= 4; + + lladdr[i/2] |= digit; + } +} + void che_reset(struct cheg_softc *sc) { @@ -482,6 +554,24 @@ che_reset(struct cheg_softc *sc) delay(500); } +int +che_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) +{ + return (EIO); +} + +void +che_watchdog(struct ifnet *ifp) +{ + /* XXX */ +} + +void +che_start(struct ifnet *ifp) +{ + /* XXX */ +} + u_int32_t che_read(struct cheg_softc *sc, bus_size_t r) { |