/* * reset and restart the SONIC. Called in case of fatal * hardware/software errors. */ static void snreset(struct sn_softc *sc) { snstop(sc); sninit(sc); }
static int snioctl(struct ifnet *ifp, u_long cmd, void *data) { struct ifaddr *ifa; struct sn_softc *sc = ifp->if_softc; int s = splnet(), err = 0; int temp; switch (cmd) { case SIOCINITIFADDR: ifa = (struct ifaddr *)data; ifp->if_flags |= IFF_UP; (void)sninit(sc); switch (ifa->ifa_addr->sa_family) { #ifdef INET case AF_INET: arp_ifinit(ifp, ifa); break; #endif default: break; } break; case SIOCSIFFLAGS: if ((err = ifioctl_common(ifp, cmd, data)) != 0) break; if ((ifp->if_flags & IFF_UP) == 0 && (ifp->if_flags & IFF_RUNNING) != 0) { /* * If interface is marked down and it is running, * then stop it. */ snstop(sc); ifp->if_flags &= ~IFF_RUNNING; } else if ((ifp->if_flags & IFF_UP) != 0 && (ifp->if_flags & IFF_RUNNING) == 0) { /* * If interface is marked up and it is stopped, * then start it. */ (void)sninit(sc); } else { /* * reset the interface to pick up any other changes * in flags */ temp = ifp->if_flags & IFF_UP; snreset(sc); ifp->if_flags |= temp; snstart(ifp); } break; case SIOCADDMULTI: case SIOCDELMULTI: if ((err = ether_ioctl(ifp, cmd, data)) == ENETRESET) { /* * Multicast list has changed; set the hardware * filter accordingly. But remember UP flag! */ if (ifp->if_flags & IFF_RUNNING) { temp = ifp->if_flags & IFF_UP; snreset(sc); ifp->if_flags |= temp; } err = 0; } break; default: err = ether_ioctl(ifp, cmd, data); break; } splx(s); return err; }
int sn_attach(device_t dev) { struct sn_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; u_short i; u_char *p; int rev; u_short address; int j; int error; sn_activate(dev); snstop(sc); sc->dev = dev; sc->pages_wanted = -1; device_printf(dev, " "); SMC_SELECT_BANK(3); rev = inw(BASE + REVISION_REG_W); if (chip_ids[(rev >> 4) & 0xF]) kprintf("%s ", chip_ids[(rev >> 4) & 0xF]); SMC_SELECT_BANK(1); i = inw(BASE + CONFIG_REG_W); kprintf("%s\n", i & CR_AUI_SELECT ? "AUI" : "UTP"); if (sc->pccard_enaddr) for (j = 0; j < 3; j++) { u_short w; w = (u_short)sc->arpcom.ac_enaddr[j * 2] | (((u_short)sc->arpcom.ac_enaddr[j * 2 + 1]) << 8); outw(BASE + IAR_ADDR0_REG_W + j * 2, w); } /* * Read the station address from the chip. The MAC address is bank 1, * regs 4 - 9 */ SMC_SELECT_BANK(1); p = (u_char *) & sc->arpcom.ac_enaddr; for (i = 0; i < 6; i += 2) { address = inw(BASE + IAR_ADDR0_REG_W + i); p[i + 1] = address >> 8; p[i] = address & 0xFF; } ifp->if_softc = sc; if_initname(ifp, "sn", device_get_unit(dev)); ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = snstart; ifp->if_ioctl = snioctl; ifp->if_watchdog = snwatchdog; ifp->if_init = sninit; ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); ifq_set_ready(&ifp->if_snd); ifp->if_timer = 0; ether_ifattach(ifp, sc->arpcom.ac_enaddr, NULL); ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->irq_res)); error = bus_setup_intr(dev, sc->irq_res, INTR_MPSAFE, sn_intr, sc, &sc->intrhand, ifp->if_serializer); if (error) { ether_ifdetach(ifp); sn_deactivate(dev); return error; } return 0; }