if (sc->sc_sta_firmware_ver < 10000) sc->wi_cmd_count = 5000;
wi_attach(struct wi_softc *sc, struct wi_funcs *funcs){	struct wi_ltv_macaddr	mac;	struct wi_ltv_gen	gen;	struct ifnet		*ifp;	int			error;	sc->sc_funcs = funcs;	wi_reset(sc);	/* Read the station address. */	mac.wi_type = WI_RID_MAC_NODE;	mac.wi_len = 4;	error = wi_read_record(sc, (struct wi_ltv_gen *)&mac);	if (error) {		printf(": unable to read station address\n");		return (error);	}	bcopy((char *)&mac.wi_mac_addr, (char *)&sc->sc_arpcom.ac_enaddr,	    ETHER_ADDR_LEN);	wi_get_id(sc);	printf("address %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));	ifp = &sc->sc_arpcom.ac_if;	bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);	ifp->if_softc = sc;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;	ifp->if_ioctl = funcs->f_ioctl;	ifp->if_start = funcs->f_start;	ifp->if_watchdog = funcs->f_watchdog;	ifp->if_baudrate = 10000000;	IFQ_SET_READY(&ifp->if_snd);	(void)wi_set_ssid(&sc->wi_node_name, WI_DEFAULT_NODENAME,	    sizeof(WI_DEFAULT_NODENAME) - 1);	(void)wi_set_ssid(&sc->wi_net_name, WI_DEFAULT_NETNAME,	    sizeof(WI_DEFAULT_NETNAME) - 1);	(void)wi_set_ssid(&sc->wi_ibss_name, WI_DEFAULT_IBSS,	    sizeof(WI_DEFAULT_IBSS) - 1);	sc->wi_portnum = WI_DEFAULT_PORT;	sc->wi_ptype = WI_PORTTYPE_BSS;	sc->wi_ap_density = WI_DEFAULT_AP_DENSITY;	sc->wi_rts_thresh = WI_DEFAULT_RTS_THRESH;	sc->wi_tx_rate = WI_DEFAULT_TX_RATE;	sc->wi_max_data_len = WI_DEFAULT_DATALEN;	sc->wi_create_ibss = WI_DEFAULT_CREATE_IBSS;	sc->wi_pm_enabled = WI_DEFAULT_PM_ENABLED;	sc->wi_max_sleep = WI_DEFAULT_MAX_SLEEP;	sc->wi_roaming = WI_DEFAULT_ROAMING;	sc->wi_authtype = WI_DEFAULT_AUTHTYPE;	sc->wi_diversity = WI_DEFAULT_DIVERSITY;	sc->wi_crypto_algorithm = WI_CRYPTO_FIRMWARE_WEP;	/*	 * Read the default channel from the NIC. This may vary	 * depending on the country where the NIC was purchased, so	 * we can't hard-code a default and expect it to work for	 * everyone.	 */	gen.wi_type = WI_RID_OWN_CHNL;	gen.wi_len = 2;	if (wi_read_record(sc, &gen) == 0)		sc->wi_channel = letoh16(gen.wi_val);	else		sc->wi_channel = 3;	/*	 * Set flags based on firmware version.	 */	switch (sc->sc_firmware_type) {	case WI_LUCENT:		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;		if (sc->sc_sta_firmware_ver >= 60000)			sc->wi_flags |= WI_FLAGS_HAS_MOR;		if (sc->sc_sta_firmware_ver >= 60006) {			sc->wi_flags |= WI_FLAGS_HAS_IBSS;			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;		}		sc->wi_ibss_port = htole16(1);		break;	case WI_INTERSIL:		sc->wi_flags |= WI_FLAGS_HAS_ROAMING;		if (sc->sc_sta_firmware_ver >= 800) {#ifndef SMALL_KERNEL			if (sc->sc_sta_firmware_ver != 10402)				sc->wi_flags |= WI_FLAGS_HAS_HOSTAP;#endif			sc->wi_flags |= WI_FLAGS_HAS_IBSS;			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;		}		sc->wi_ibss_port = htole16(0);		break;	case WI_SYMBOL:		sc->wi_flags |= WI_FLAGS_HAS_DIVERSITY;		if (sc->sc_sta_firmware_ver >= 20000)			sc->wi_flags |= WI_FLAGS_HAS_IBSS;		if (sc->sc_sta_firmware_ver >= 25000)			sc->wi_flags |= WI_FLAGS_HAS_CREATE_IBSS;		sc->wi_ibss_port = htole16(4);		break;	}	/*	 * Find out if we support WEP on this card.	 */	gen.wi_type = WI_RID_WEP_AVAIL;	gen.wi_len = 2;	if (wi_read_record(sc, &gen) == 0 && gen.wi_val != htole16(0))		sc->wi_flags |= WI_FLAGS_HAS_WEP;	timeout_set(&sc->sc_timo, funcs->f_inquire, sc);	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));	/* Find supported rates. */	gen.wi_type = WI_RID_DATA_RATES;	gen.wi_len = 2;	if (wi_read_record(sc, &gen))		sc->wi_supprates = WI_SUPPRATES_1M | WI_SUPPRATES_2M |		    WI_SUPPRATES_5M | WI_SUPPRATES_11M;	else		sc->wi_supprates = gen.wi_val;	ifmedia_init(&sc->sc_media, 0, wi_media_change, wi_media_status);#define	ADD(m, c)	ifmedia_add(&sc->sc_media, (m), (c), NULL)	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0), 0);	ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_ADHOC, 0), 0);	if (sc->wi_flags & WI_FLAGS_HAS_IBSS)		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, IFM_IEEE80211_IBSS,		    0), 0);	if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,		    IFM_IEEE80211_IBSSMASTER, 0), 0);	if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO,		    IFM_IEEE80211_HOSTAP, 0), 0);	if (sc->wi_supprates & WI_SUPPRATES_1M) {		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1, 0, 0), 0);		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,		    IFM_IEEE80211_ADHOC, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,			    IFM_IEEE80211_IBSS, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,			    IFM_IEEE80211_IBSSMASTER, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS1,			    IFM_IEEE80211_HOSTAP, 0), 0);	}	if (sc->wi_supprates & WI_SUPPRATES_2M) {		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2, 0, 0), 0);		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,		    IFM_IEEE80211_ADHOC, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,			    IFM_IEEE80211_IBSS, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,			    IFM_IEEE80211_IBSSMASTER, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS2,			    IFM_IEEE80211_HOSTAP, 0), 0);	}	if (sc->wi_supprates & WI_SUPPRATES_5M) {		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5, 0, 0), 0);		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,		    IFM_IEEE80211_ADHOC, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,			    IFM_IEEE80211_IBSS, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,			    IFM_IEEE80211_IBSSMASTER, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS5,			    IFM_IEEE80211_HOSTAP, 0), 0);	}	if (sc->wi_supprates & WI_SUPPRATES_11M) {		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11, 0, 0), 0);		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,		    IFM_IEEE80211_ADHOC, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,			    IFM_IEEE80211_IBSS, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_CREATE_IBSS)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,			    IFM_IEEE80211_IBSSMASTER, 0), 0);		if (sc->wi_flags & WI_FLAGS_HAS_HOSTAP)			ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_IEEE80211_DS11,			    IFM_IEEE80211_HOSTAP, 0), 0);		ADD(IFM_MAKEWORD(IFM_IEEE80211, IFM_MANUAL, 0, 0), 0);	}#undef ADD	ifmedia_set(&sc->sc_media,	    IFM_MAKEWORD(IFM_IEEE80211, IFM_AUTO, 0, 0));	/*	 * Call MI attach routines.	 */	if_attach(ifp);	ether_ifattach(ifp);	printf("\n");	sc->wi_flags |= WI_FLAGS_ATTACHED;#if NBPFILTER > 0	BPFATTACH(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB,	    sizeof(struct ether_header));#endif	sc->sc_sdhook = shutdownhook_establish(wi_shutdown, sc);	wi_init(sc);	wi_stop(sc);	return (0);}