PERFORCE change 132316 for review

Hans Petter Selasky hselasky at FreeBSD.org
Wed Jan 2 10:03:19 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=132316

Change 132316 by hselasky at hselasky_laptop001 on 2008/01/02 18:02:18

	
	Merge if_zyd.c from FreeBSD P4 head. The driver has been
	tested and confirmed to work. Additional bugfixes:
	 o receive frame length was not correctly adjusted
	 o added length check for incoming USB frames

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/if_zyd.c#30 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/if_zyd.c#30 (text+ko) ====

@@ -1,11 +1,9 @@
-#if 0
+/*	$OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $	*/
+/*	$NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $	*/
+/*	$FreeBSD: src/sys/dev/usb/if_zyd.c,v 1.11 2007/12/01 08:53:03 kevlo Exp $	*/
 
-XXX this driver needs to be updated !
-	XXX--	hps
-
-/*	$OpenBSD: if_zyd.c,v 1.27 2006/09/23 22:28:43 mglocker Exp $	*/
-
-/*
+/*-
+ * Copyright (c) 2006 by Damien Bergamini <damien.bergamini at free.fr>
  * Copyright (c) 2006 by Florian Stoehr <ich at florian-stoehr.de>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -22,10 +20,10 @@
  */
 
 #include <sys/cdefs.h>
-	__FBSDID("$FreeBSD: src/sys/dev/usb/if_zyd.c $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_zyd.c $");
 
 /*
- * ZyDAS ZD1211 USB WLAN driver
+ * ZyDAS ZD1211/ZD1211B USB WLAN driver
  *
  * NOTE: all function names beginning like "zyd_cfg_" can only
  * be called from within the config thread function !
@@ -49,13 +47,11 @@
 #include <net/if_types.h>
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
 #include <net80211/ieee80211_radiotap.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
+#include <net80211/ieee80211_proto.h>
+#include <net80211/ieee80211_node.h>
+#include <net80211/ieee80211_regdomain.h>
 
 #define	usbd_config_td_cc zyd_config_copy
 #define	usbd_config_td_softc zyd_softc
@@ -84,6 +80,9 @@
 #define	DPRINTF(...)
 #endif
 
+#undef INDEXES
+#define INDEXES(a) (sizeof(a) / sizeof((a)[0]))
+
 struct mq {				/* mini-queue */
 	struct mbuf *ifq_head;
 	struct mbuf *ifq_tail;
@@ -112,133 +111,132 @@
 static usbd_config_td_command_t zyd_cfg_pre_stop;
 static usbd_config_td_command_t zyd_cfg_stop;
 static usbd_config_td_command_t zyd_config_copy;
+static usbd_config_td_command_t zyd_cfg_scan_start;
+static usbd_config_td_command_t zyd_cfg_scan_end;
+static usbd_config_td_command_t zyd_cfg_set_rxfilter;
+static usbd_config_td_command_t zyd_cfg_amrr_timeout;
 
-static uint16_t zyd_getrealaddr(struct zyd_softc *sc, uint32_t mangled_addr);
-static void zyd_cfg_usbrequest(struct zyd_softc *sc, uint8_t type, uint8_t request, uint16_t value, uint16_t index, uint16_t length, uint8_t *data);
-static void zyd_cfg_usbrequestzc(struct zyd_softc *sc, struct zyd_control *zc);
-static void zyd_cfg_reset(struct zyd_softc *sc);
+static uint8_t zyd_plcp2ieee(uint8_t signal, uint8_t isofdm);
+static struct ieee80211_node * zyd_node_alloc_cb(struct ieee80211_node_table *nt);
+static void zyd_cfg_usbrequest(struct zyd_softc *sc, usb_device_request_t *req, uint8_t *data);
 static void zyd_cfg_usb_intr_read(struct zyd_softc *sc, void *data, uint32_t size);
-static void zyd_cfg_usb_intr_write(struct zyd_softc *sc, void *data, uint32_t size);
-static uint32_t zyd_addrinc(uint32_t addr);
-static void zyd_cfg_read16(struct zyd_softc *sc, uint32_t addr, uint16_t *value);
-static void zyd_cfg_read32(struct zyd_softc *sc, uint32_t addr, uint32_t *value);
-static void zyd_cfg_read16_multi(struct zyd_softc *sc, const uint32_t *addrs, uint16_t *data, uint8_t usecount);
-static void zyd_cfg_read32_multi(struct zyd_softc *sc, const uint32_t *addrs, uint32_t *data, uint8_t usecount);
-static void zyd_cfg_write16(struct zyd_softc *sc, uint32_t addr, uint16_t value);
-static void zyd_cfg_write32(struct zyd_softc *sc, uint32_t addr, uint32_t value);
-static void zyd_cfg_write16_multi(struct zyd_softc *sc, const uint32_t *addrs, uint16_t *data, uint8_t usecount);
-static void zyd_cfg_write32_multi(struct zyd_softc *sc, const uint32_t *addrs, uint32_t *data, uint8_t usecount);
-static void zyd_cfg_write16_batch(struct zyd_softc *sc, const struct zyd_adpairs16 *data, uint32_t count);
-static void zyd_cfg_write32_batch(struct zyd_softc *sc, const struct zyd_adpairs32 *data, uint32_t count);
-static void zyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value, uint8_t bits);
-static void zyd_cfg_stateoutput(struct zyd_softc *sc);
-static void zyd_rxframeproc(struct usbd_xfer *xfer, struct mq *mq, uint16_t offset, uint16_t len);
-static uint8_t zyd_cfg_uploadfirmware(struct zyd_softc *sc);
+static void zyd_cfg_usb_intr_write(struct zyd_softc *sc, const void *data, uint16_t code, uint32_t size);
+static void zyd_cfg_read16(struct zyd_softc *sc, uint16_t addr, uint16_t *value);
+static void zyd_cfg_read32(struct zyd_softc *sc, uint16_t addr, uint32_t *value);
+static void zyd_cfg_write16(struct zyd_softc *sc, uint16_t addr, uint16_t value);
+static void zyd_cfg_write32(struct zyd_softc *sc, uint16_t addr, uint32_t value);
+static void zyd_cfg_rfwrite(struct zyd_softc *sc, uint32_t value);
+static uint8_t zyd_cfg_uploadfirmware(struct zyd_softc *sc, const uint8_t *fw_ptr, uint32_t fw_len);
 static void zyd_cfg_lock_phy(struct zyd_softc *sc);
 static void zyd_cfg_unlock_phy(struct zyd_softc *sc);
-static void zyd_cfg_get_aw_pt_bi(struct zyd_softc *sc, struct zyd_aw_pt_bi *s);
-static void zyd_cfg_set_aw_pt_bi(struct zyd_softc *sc, struct zyd_aw_pt_bi *s);
 static void zyd_cfg_set_beacon_interval(struct zyd_softc *sc, uint32_t interval);
 static const char *zyd_rf_name(uint8_t type);
-static void zyd_cfg_read_rf_pa_types(struct zyd_softc *sc, uint8_t *rf_type, uint8_t *pa_type);
 static void zyd_cfg_rf_rfmd_init(struct zyd_softc *sc, struct zyd_rf *rf);
-static void zyd_cfg_rf_rfmd_switchradio(struct zyd_softc *sc, uint8_t onoff);
+static void zyd_cfg_rf_rfmd_switch_radio(struct zyd_softc *sc, uint8_t onoff);
 static void zyd_cfg_rf_rfmd_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, uint8_t channel);
-static void zyd_cfg_rf_al2230_switchradio(struct zyd_softc *sc, uint8_t onoff);
+static void zyd_cfg_rf_al2230_switch_radio(struct zyd_softc *sc, uint8_t onoff);
 static void zyd_cfg_rf_al2230_init(struct zyd_softc *sc, struct zyd_rf *rf);
+static void zyd_cfg_rf_al2230_init_b(struct zyd_softc *sc, struct zyd_rf *rf);
 static void zyd_cfg_rf_al2230_set_channel(struct zyd_softc *sc, struct zyd_rf *rf, uint8_t channel);
-static uint8_t zyd_cfg_rf_init_hw(struct zyd_softc *sc, struct zyd_rf *rf, uint8_t type);
+static uint8_t zyd_cfg_rf_init_hw(struct zyd_softc *sc, struct zyd_rf *rf);
 static uint8_t zyd_cfg_hw_init(struct zyd_softc *sc, struct ieee80211com *ic);
-static void zyd_cfg_get_e2p_mac_addr(struct zyd_softc *sc, struct zyd_macaddr *mac_addr);
 static void zyd_cfg_set_mac_addr(struct zyd_softc *sc, const uint8_t *addr);
-static void zyd_cfg_read_regdomain(struct zyd_softc *sc, uint8_t *regdomain);
-static uint8_t zyd_regdomain_supported(uint8_t regdomain);
-static void zyd_cfg_tblreader(struct zyd_softc *sc, uint8_t *values, size_t count, uint32_t e2p_addr, uint32_t guard);
-static void zyd_cfg_readcaltables(struct zyd_softc *sc);
-static uint8_t zyd_reset_channel(struct zyd_softc *sc);
-static void zyd_cfg_set_encryption_type(struct zyd_softc *sc, uint32_t type);
 static void zyd_cfg_switch_radio(struct zyd_softc *sc, uint8_t onoff);
-static void zyd_cfg_enable_hwint(struct zyd_softc *sc);
-static void zyd_cfg_disable_hwint(struct zyd_softc *sc);
-static void zyd_cfg_set_basic_rates(struct zyd_softc *sc, int mode);
-static void zyd_cfg_set_mandatory_rates(struct zyd_softc *sc, int mode);
-static void zyd_cfg_reset_mode(struct zyd_softc *sc);
 static void zyd_cfg_set_bssid(struct zyd_softc *sc, uint8_t *addr);
 static int zyd_media_change_cb(struct ifnet *ifp);
 static int zyd_newstate_cb(struct ieee80211com *ic, enum ieee80211_state nstate, int arg);
-static uint16_t zyd_txtime(uint16_t len, uint8_t rate, uint32_t flags);
 static uint8_t zyd_plcp_signal(uint8_t rate);
-static uint16_t zyd_calc_useclen(uint8_t rate, uint16_t len, uint8_t *service);
-static void zyd_setup_tx_desc(struct usbd_xfer *xfer, struct mbuf *m, uint16_t rate);
-static void zyd_cfg_dump_fw_registers(struct zyd_softc *sc);
-static uint8_t zyd_tx_frame(struct usbd_xfer *xfer, struct mbuf *m0, struct ieee80211_node *ni, uint8_t rate);
 static void zyd_start_transfers(struct zyd_softc *sc);
 static void zyd_start_cb(struct ifnet *ifp);
 static void zyd_init_cb(void *arg);
-static int zyd_reset_cb(struct ifnet *ifp);
 static int zyd_ioctl_cb(struct ifnet *ifp, u_long command, caddr_t data);
 static void zyd_watchdog(void *arg);
-static void zyd_next_scan(void *arg);
 static void zyd_end_of_commands(struct zyd_softc *sc);
+static void zyd_newassoc_cb(struct ieee80211_node *ni, int isnew);
+static void zyd_scan_start_cb(struct ieee80211com *ic);
+static void zyd_scan_end_cb(struct ieee80211com *ic);
+static void zyd_set_channel_cb(struct ieee80211com *ic);
+static void zyd_cfg_set_led(struct zyd_softc *sc, uint32_t which, uint8_t on);
 
-static const struct usb_devno zyd_devs[] = {
-	{USB_VENDOR_3COM2, USB_PRODUCT_3COM2_3CRUSB10075},
-	{USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WL54},
-	{USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL159G},
-	{USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050C},
-	{USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_TG54USB},
-	{USB_VENDOR_DRAYTEK, USB_PRODUCT_DRAYTEK_VIGOR550},
-	{USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GZL},
-	{USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54MINI},
-	{USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG760A},
-	{USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113},
-	{USB_VENDOR_SWEEX, USB_PRODUCT_SWEEX_ZD1211},
-	{USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_QUICKWLAN},
-	{USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211},
-	{USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_G240},
-	{USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB_A},
-	{USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB},
-	{USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR055G},
-	{USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211},
-	{USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_ZYAIRG220}
-};
+static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
+static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
 
-/* Device, regardless of RF */
-static const struct zyd_adpairs16 zyd_def_cr[] = {
-	ZYD_DEF_CR
-};
+/* various supported device vendors/products */
+#define ZYD_ZD1211_DEV(v, p)	\
+	{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211 }
+#define ZYD_ZD1211B_DEV(v, p)	\
+	{ { USB_VENDOR_##v, USB_PRODUCT_##v##_##p }, ZYD_ZD1211B }
+static const struct zyd_type {
+	struct usb_devno	dev;
+	uint8_t			rev;
+#define ZYD_ZD1211	0
+#define ZYD_ZD1211B	1
+} zyd_devs[] = {
+	ZYD_ZD1211_DEV(3COM2,		3CRUSB10075),
+	ZYD_ZD1211_DEV(ABOCOM,		WL54),
+	ZYD_ZD1211_DEV(ASUS,		WL159G),
+	ZYD_ZD1211_DEV(CYBERTAN,	TG54USB),
+	ZYD_ZD1211_DEV(DRAYTEK,		VIGOR550),
+	ZYD_ZD1211_DEV(PLANEX2,		GWUS54GD),
+	ZYD_ZD1211_DEV(PLANEX2,		GWUS54GZL),
+	ZYD_ZD1211_DEV(PLANEX3,		GWUS54GZ),
+	ZYD_ZD1211_DEV(PLANEX3,		GWUS54MINI),
+	ZYD_ZD1211_DEV(SAGEM,		XG760A),
+	ZYD_ZD1211_DEV(SENAO,		NUB8301),
+	ZYD_ZD1211_DEV(SITECOMEU,	WL113),
+	ZYD_ZD1211_DEV(SWEEX,		ZD1211),
+	ZYD_ZD1211_DEV(TEKRAM,		QUICKWLAN),
+	ZYD_ZD1211_DEV(TEKRAM,		ZD1211_1),
+	ZYD_ZD1211_DEV(TEKRAM,		ZD1211_2),
+	ZYD_ZD1211_DEV(TWINMOS,		G240),
+	ZYD_ZD1211_DEV(UMEDIA,		ALL0298V2),
+	ZYD_ZD1211_DEV(UMEDIA,		TEW429UB_A),
+	ZYD_ZD1211_DEV(UMEDIA,		TEW429UB),
+	ZYD_ZD1211_DEV(WISTRONNEWEB,	UR055G),
+	ZYD_ZD1211_DEV(ZCOM,		ZD1211),
+	ZYD_ZD1211_DEV(ZYDAS,		ZD1211),
+	ZYD_ZD1211_DEV(ZYXEL,		AG225H),
+	ZYD_ZD1211_DEV(ZYXEL,		ZYAIRG220),
+	ZYD_ZD1211_DEV(ZYXEL,		G200V2),
 
-static const struct zyd_adpairs32 zyd_def_mac[] = {
-	ZYD_DEF_MAC
+	ZYD_ZD1211B_DEV(ACCTON,		SMCWUSBG),
+	ZYD_ZD1211B_DEV(ACCTON,		ZD1211B),
+	ZYD_ZD1211B_DEV(ASUS,		A9T_WIFI),
+	ZYD_ZD1211B_DEV(BELKIN,		F5D7050_V4000),
+	ZYD_ZD1211B_DEV(BELKIN,		ZD1211B),
+	ZYD_ZD1211B_DEV(CISCOLINKSYS,	WUSBF54G),
+	ZYD_ZD1211B_DEV(FIBERLINE,	WL430U),
+	ZYD_ZD1211B_DEV(MELCO,		KG54L),
+	ZYD_ZD1211B_DEV(PHILIPS,	SNU5600),
+	ZYD_ZD1211B_DEV(PLANEX2,	GW_US54GXS),
+	ZYD_ZD1211B_DEV(SAGEM,		XG76NA),
+	ZYD_ZD1211B_DEV(SITECOMEU,	ZD1211B),
+	ZYD_ZD1211B_DEV(UMEDIA,		TEW429UBC1),
+#if 0	/* Shall we needs? */
+	ZYD_ZD1211B_DEV(UNKNOWN1,	ZD1211B_1),
+	ZYD_ZD1211B_DEV(UNKNOWN1,	ZD1211B_2),
+	ZYD_ZD1211B_DEV(UNKNOWN2,	ZD1211B),
+	ZYD_ZD1211B_DEV(UNKNOWN3,	ZD1211B),
+#endif
+	ZYD_ZD1211B_DEV(USR,		USR5423),
+	ZYD_ZD1211B_DEV(VTECH,		ZD1211B),
+	ZYD_ZD1211B_DEV(ZCOM,		ZD1211B),
+	ZYD_ZD1211B_DEV(ZYDAS,		ZD1211B),
+	ZYD_ZD1211B_DEV(ZYXEL,		M202),
+	ZYD_ZD1211B_DEV(ZYXEL,		G220V2),
 };
+#define zyd_lookup(v, p)	\
+	((const struct zyd_type *)usb_lookup(zyd_devs, v, p))
 
-/* RF2959 */
-static const struct zyd_adpairs16 zyd_rfmd_cr[] = {
-	ZYD_RFMD_CR
-};
-
-static const uint32_t zyd_rfmd_rf[] = {
-	ZYD_RFMD_RF
-};
-
-/* AL2230 */
-static const struct zyd_adpairs16 zyd_al2230_cr[] = {
-	ZYD_AL2230_CR
-};
-
-static const uint32_t zyd_al2230_rf[] = {
-	ZYD_AL2230_RF
-};
-
-static const struct usbd_config zyd_config[ZYD_TR_MAX] = {
+static const struct usbd_config zyd_config[ZYD_N_TRANSFER] = {
 	[ZYD_TR_BULK_DT_WR] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = (MCLBYTES + sizeof(struct zyd_controlsetformat) + 1),
+		.bufsize = ZYD_MAX_TXBUFSZ,
 		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
 		.mh.callback = &zyd_bulk_write_callback,
-		.index = 0,
+		.ep_index = 0,
 		.mh.timeout = 10000,	/* 10 seconds */
 	},
 
@@ -246,10 +244,10 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = (MAX(MCLBYTES, 2312) + sizeof(struct zyd_rxleninfoapp)),
+		.bufsize = ZYX_MAX_RXBUFSZ,
 		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
 		.mh.callback = &zyd_bulk_read_callback,
-		.index = 0,
+		.ep_index = 0,
 	},
 
 	[ZYD_TR_BULK_CS_WR] = {
@@ -278,22 +276,21 @@
 		.type = UE_BULK_INTR,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = ZYD_INTR_BUF_SIZE,
+		.bufsize = sizeof(struct zyd_cmd),
 		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
 		.mh.callback = &zyd_intr_write_callback,
 		.mh.timeout = 1000,	/* 1 second */
-		.index = 1,
+		.ep_index = 1,
 	},
 
 	[ZYD_TR_INTR_DT_RD] = {
 		.type = UE_BULK_INTR,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = ZYD_INTR_BUF_SIZE,
+		.bufsize = sizeof(struct zyd_cmd),
 		.mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
 		.mh.callback = &zyd_intr_read_callback,
-		.mh.timeout = 1000,	/* 1 second */
-		.index = 1,
+		.ep_index = 1,
 	},
 
 	[ZYD_TR_INTR_CS_WR] = {
@@ -337,111 +334,61 @@
 DRIVER_MODULE(zyd, uhub, zyd_driver, zyd_devclass, usbd_driver_load, 0);
 MODULE_DEPEND(zyd, usb, 1, 1, 1);
 MODULE_DEPEND(zyd, wlan, 1, 1, 1);
+MODULE_DEPEND(zyd, wlan_amrr, 1, 1, 1);
 
-/*
- * Get the real address from a range-mangled address
- */
-static uint16_t
-zyd_getrealaddr(struct zyd_softc *sc, uint32_t mangled_addr)
+static uint8_t
+zyd_plcp2ieee(uint8_t signal, uint8_t isofdm)
 {
-	uint16_t add;
-	uint16_t res;
+       if (isofdm) {
+               static const uint8_t ofdmrates[16] =
+                   { 0, 0, 0, 0, 0, 0, 0, 96, 48, 24, 12, 108, 72, 36, 18 };
+               return ofdmrates[signal & 0xf];
+       } else {
+               static const uint8_t cckrates[16] =
+                   { 0, 0, 0, 0, 4, 0, 0, 11, 0, 0, 2, 0, 0, 0, 22, 0 };
+               return cckrates[signal & 0xf];
+       }
+}
 
-	add = 0;
-
-	switch (ZYD_GET_RANGE(mangled_addr)) {
-	case ZYD_RANGE_USB:
-		break;
-
-	case ZYD_RANGE_CTL:
-		add = ZYD_CTRL_START_ADDR;
-		break;
-
-	case ZYD_RANGE_E2P:
-		add = ZYD_E2P_START_ADDR;
-		break;
-
-	case ZYD_RANGE_FW:
-		add = sc->sc_firmware_base;
-		break;
-	}
-
-	res = (add + ZYD_GET_OFFS(mangled_addr));
-
-	return (res);
+/* ARGUSED */
+static struct ieee80211_node *
+zyd_node_alloc_cb(struct ieee80211_node_table *nt __unused)
+{
+	struct zyd_node *zn;
+	zn = malloc(sizeof(struct zyd_node), M_80211_NODE, M_WAITOK | M_ZERO);
+	return ((zn != NULL) ? (&zn->ni) : NULL);
 }
 
-
 /*
  * USB request basic wrapper
  */
 static void
-zyd_cfg_usbrequest(struct zyd_softc *sc, uint8_t type, uint8_t request,
-    uint16_t value, uint16_t index, uint16_t length, uint8_t *data)
+zyd_cfg_usbrequest(struct zyd_softc *sc, usb_device_request_t *req, uint8_t *data)
 {
-	usb_device_request_t req;
 	usbd_status_t err;
-
-	req.bmRequestType = type;
-	req.bRequest = request;
-	USETW(req.wValue, value);
-	USETW(req.wIndex, index);
-	USETW(req.wLength, length);
+	uint16_t length;
 
-	DPRINTF(sc, 20, "req=%02x val=%02x ind=%02x "
-	    "len=%02x\n", request,
-	    value, index, length);
-
 	if (usbd_config_td_is_gone(&(sc->sc_config_td))) {
 		goto error;
 	}
 	err = usbd_do_request_flags
-	    (sc->sc_udev, &(sc->sc_mtx), &req, data, 0, NULL, 10000);
+	    (sc->sc_udev, &(sc->sc_mtx), req, data, 0, NULL, 1000);
 
 	if (err) {
 
-		printf("%s: device request failed, err=%s "
-		    "(ignored)\n", sc->sc_name, usbd_errstr(err));
+		DPRINTF(sc, -1, "%s: device request failed, err=%s "
+			"(ignored)\n", sc->sc_name, usbd_errstr(err));
 
 error:
-		length = UGETW(req.wLength);
+		length = UGETW(req->wLength);
 
-		if ((req.bmRequestType & UT_READ) && length) {
+		if ((req->bmRequestType & UT_READ) && length) {
 			bzero(data, length);
 		}
 	}
 	return;
 }
 
-/*
- * Same, higher level
- */
-static void
-zyd_cfg_usbrequestzc(struct zyd_softc *sc, struct zyd_control *zc)
-{
-	return (zyd_cfg_usbrequest(sc, zc->type, zc->id, zc->value,
-	    zc->index, zc->length, zc->data));
-}
-
-/*
- * Issue a SET_CONFIGURATION command, which will reset the device.
- */
-static void
-zyd_cfg_reset(struct zyd_softc *sc)
-{
-	usbd_status_t err;
-
-	err = usbreq_set_config(sc->sc_udev, &(sc->sc_mtx), ZYD_CONFIG_NO);
-
-	if (err) {
-		DPRINTF(sc, 0, "reset failed (ignored)\n");
-	}
-	/* Wait a little while for the chip to get its brains in order. */
-	err = usbd_config_td_sleep(&(sc->sc_config_td), hz / 10);
-
-	return;
-}
-
 static void
 zyd_intr_read_clear_stall_callback(struct usbd_xfer *xfer)
 {
@@ -463,47 +410,148 @@
 zyd_intr_read_callback(struct usbd_xfer *xfer)
 {
 	struct zyd_softc *sc = xfer->priv_sc;
+	struct zyd_cmd *cmd = &(sc->sc_intr_ibuf);
+	uint32_t actlen;
+	uint32_t x;
 
 	switch (USBD_GET_STATE(xfer)) {
 	case USBD_ST_TRANSFERRED:
 
-		DPRINTF(sc, 2, "length=%d\n", xfer->actlen);
+		actlen = xfer->actlen;
+
+		DPRINTF(sc, 2, "length=%d\n", actlen);
+
+		if (actlen > sizeof(sc->sc_intr_ibuf)) {
+			actlen = sizeof(sc->sc_intr_ibuf);
+		}
+		usbd_copy_out(xfer->frbuffers + 0, 0,
+		    &(sc->sc_intr_ibuf), actlen);
 
-		if (xfer->actlen > sizeof(sc->sc_intr_ibuf)) {
-			xfer->actlen = sizeof(sc->sc_intr_ibuf);
+		switch(cmd->code) {
+		case htole16(ZYD_NOTIF_RETRYSTATUS):
+			goto handle_notif_retrystatus;
+		case htole16(ZYD_NOTIF_IORD):
+			goto handle_notif_iord;
+		default:
+			DPRINTF(sc, 1, "unknown indication: 0x%04x\n",
+			    le16toh(cmd->code));
 		}
-		usbd_copy_out(xfer->frbuffers + 0, 0, &(sc->sc_intr_ibuf),
-		    xfer->actlen);
-		goto wakeup;
+
+		/* fallthrough */
 
 	case USBD_ST_SETUP:
-
+	tr_setup:
 		if (sc->sc_flags & ZYD_FLAG_INTR_READ_STALL) {
 			usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_RD]);
-			goto wakeup;
-		}
-		if (sc->sc_intr_iwakeup) {
-			xfer->frlengths[0] = xfer->max_data_length;
-			usbd_start_hardware(xfer);
+			break;
 		}
-		return;
 
-wakeup:
-		sc->sc_intr_iwakeup = 0;
-		wakeup(&(sc->sc_intr_iwakeup));
-		return;
+		xfer->frlengths[0] = xfer->max_data_length;
+		usbd_start_hardware(xfer);
+		break;
 
 	default:			/* Error */
-		DPRINTF(sc, 2, "error=%d\n", xfer->error);
+		DPRINTF(sc, 2, "error = %s\n", 
+		   usbd_errstr(xfer->error));
 
 		if (xfer->error != USBD_CANCELLED) {
 			/* try to clear stall first */
 			sc->sc_flags |= ZYD_FLAG_INTR_READ_STALL;
 			usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_RD]);
+		} else {
+			/* tearing down */
+			if (sc->sc_intr_iwakeup) {
+				bzero(sc->sc_intr_ibuf.data, sc->sc_intr_ilen);
+				wakeup(&(sc->sc_intr_iwakeup));
+			}
 		}
-		goto wakeup;
+		break;
+	}
+	return;
+
+handle_notif_retrystatus: {
+
+	struct zyd_notif_retry *retry = (void *)(cmd->data);
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211_node *ni;
+
+	DPRINTF(sc, 0, "retry intr: rate=0x%x "
+		"addr=%02x:%02x:%02x:%02x:%02x:%02x count=%d (0x%x)\n",
+		le16toh(retry->rate), retry->macaddr[0], retry->macaddr[1], 
+		retry->macaddr[2], retry->macaddr[3], retry->macaddr[4],
+		retry->macaddr[5], le16toh(retry->count) & 0xff, 
+		le16toh(retry->count));
+
+	/*
+	 * Find the node to which the packet was sent and update its
+	 * retry statistics. In BSS mode, this node is the AP we're
+	 * associated to so no lookup is actually needed.
+	 */
+	if (ic->ic_opmode != IEEE80211_M_STA) {
+		ni = ieee80211_find_node(&ic->ic_sta, retry->macaddr);
+	} else {
+		ni = ic->ic_bss;
+	}
+	if (ni == NULL) {
+		goto tr_setup;
+	}
+
+	((struct zyd_node *)ni)->amn.amn_retrycnt++;
 
+	if (retry->count & htole16(0x100)) {
+		ifp->if_oerrors++;	/* too many retries */
 	}
+	goto tr_setup;
+}
+
+handle_notif_iord:
+
+	  if (*(uint16_t *)cmd->data == htole16(ZYD_CR_INTERRUPT)) {
+		goto tr_setup; /* HMAC interrupt */
+	  }
+
+	  if (actlen < 4) {
+		goto tr_setup; /* too short */
+	  }
+
+	  actlen -= 4;
+
+	  if (actlen != sc->sc_intr_ilen) {
+		DPRINTF(sc, -1, "unexpected length %u != %u\n",
+		    actlen, sc->sc_intr_ilen);
+		goto tr_setup; /* invalid length */
+	  }
+
+	  actlen /= 4;
+
+	  /* verify register values */
+	  for (x = 0; x != actlen; x++) {
+		if (sc->sc_intr_obuf.data[(2*x)] != 
+		    sc->sc_intr_ibuf.data[(4*x)]) {
+			/* invalid register */
+		  DPRINTF(sc, 0, "Invalid register (1)!\n");
+		  goto tr_setup;
+		}
+		if (sc->sc_intr_obuf.data[(2*x) + 1] != 
+		    sc->sc_intr_ibuf.data[(4*x) + 1]) {
+			/* invalid register */
+		  DPRINTF(sc, 0, "Invalid register (2)!\n");
+		  goto tr_setup;
+		}
+	  }
+
+	  if (sc->sc_intr_iwakeup) {
+	      sc->sc_intr_iwakeup = 0;
+	      wakeup(&(sc->sc_intr_iwakeup));
+	  } else {
+	      sc->sc_intr_iwakeup = 1;
+	  }
+	  /* 
+	   * We pause reading data from the interrupt endpoint until
+	   * the data has been picked up!
+	   */
+	  return;
 }
 
 /*
@@ -512,28 +560,48 @@
 static void
 zyd_cfg_usb_intr_read(struct zyd_softc *sc, void *data, uint32_t size)
 {
-	int error;
-
-	if (size > sizeof(sc->sc_intr_ibuf)) {
-		DPRINTF(sc, 0, "truncating transfer size!\n");
-		size = sizeof(sc->sc_intr_ibuf);
+	if (size > sizeof(sc->sc_intr_ibuf.data)) {
+		DPRINTF(sc, -1, "truncating transfer size!\n");
+		size = sizeof(sc->sc_intr_ibuf.data);
 	}
 	if (usbd_config_td_is_gone(&(sc->sc_config_td))) {
 		bzero(data, size);
 		goto done;
 	}
+
+	if (sc->sc_intr_iwakeup) {
+	    DPRINTF(sc, 0, "got data already!\n");
+	    sc->sc_intr_iwakeup = 0;
+	    goto got_data;
+	}
+
+	/* else wait for data */
+
 	sc->sc_intr_iwakeup = 1;
+	sc->sc_intr_ilen = size;
 
-	bzero(&(sc->sc_intr_ibuf), size);
-
 	usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_RD]);
 
-	if (sc->sc_intr_iwakeup) {
-		error = mtx_sleep(&(sc->sc_intr_iwakeup), &(sc->sc_mtx), 0,
-		    "zyd isleep", 0);
+	while (sc->sc_intr_iwakeup) {
+		if (mtx_sleep(&(sc->sc_intr_iwakeup), &(sc->sc_mtx), 0,
+		    "zyd-ird", hz/2)) {
+			/* should not happen */
+		}
+	if (usbd_config_td_is_gone(&(sc->sc_config_td))) {
+		sc->sc_intr_iwakeup = 0;
+		bzero(data, size);
+		goto done;
+	}
 	}
-	bcopy(&(sc->sc_intr_ibuf), data, size);
+
+got_data:
+	bcopy(sc->sc_intr_ibuf.data, data, size);
 
+	/* 
+	 * We have fetched the data from the shared buffer and it is
+	 * safe to restart the interrupt transfer!
+	 */
+	usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_RD]);
 done:
 	return;
 }
@@ -575,15 +643,11 @@
 			xfer->frlengths[0] = sc->sc_intr_olen;
 			usbd_start_hardware(xfer);
 		}
-		return;
+		break;
 
-wakeup:
-		sc->sc_intr_owakeup = 0;
-		wakeup(&(sc->sc_intr_owakeup));
-		return;
-
 	default:			/* Error */
-		DPRINTF(sc, 2, "error=%d\n", xfer->error);
+		DPRINTF(sc, 2, "error = %s\n", 
+		   usbd_errstr(xfer->error));
 
 		if (xfer->error != USBD_CANCELLED) {
 			/* try to clear stall first */
@@ -591,8 +655,15 @@
 			usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_CS_WR]);
 		}
 		goto wakeup;
+	}
+	return;
 
+wakeup:
+	if (sc->sc_intr_owakeup) {
+	sc->sc_intr_owakeup = 0;
+	wakeup(&(sc->sc_intr_owakeup));
 	}
+	return;
 }
 
 /*
@@ -602,431 +673,222 @@
  * full speed mode, EP4 is bulk out, not interrupt out.
  */
 static void
-zyd_cfg_usb_intr_write(struct zyd_softc *sc, void *data, uint32_t size)
+zyd_cfg_usb_intr_write(struct zyd_softc *sc, const void *data, 
+uint16_t code, uint32_t size)
 {
-	int error;
-
-	if (size > sizeof(sc->sc_intr_obuf)) {
-		DPRINTF(sc, 0, "truncating transfer size!\n");
-		size = sizeof(sc->sc_intr_obuf);
+	if (size > sizeof(sc->sc_intr_obuf.data)) {
+		DPRINTF(sc, -1, "truncating transfer size!\n");
+		size = sizeof(sc->sc_intr_obuf.data);
 	}
 	if (usbd_config_td_is_gone(&(sc->sc_config_td))) {
 		goto done;
 	}
-	sc->sc_intr_olen = size;
+	sc->sc_intr_olen = size + 2;
 	sc->sc_intr_owakeup = 1;
 
-	bcopy(data, sc->sc_intr_obuf, size);
+	sc->sc_intr_obuf.code = htole16(code);
+	bcopy(data, sc->sc_intr_obuf.data, size);
 
 	usbd_transfer_start(sc->sc_xfer[ZYD_TR_INTR_DT_WR]);
 
-	if (sc->sc_intr_owakeup) {
-		error = mtx_sleep(&(sc->sc_intr_owakeup), &(sc->sc_mtx), 0,
-		    "zyd osleep", 0);
+	while (sc->sc_intr_owakeup) {
+	  if (mtx_sleep(&(sc->sc_intr_owakeup), &(sc->sc_mtx), 0,
+		"zyd-iwr", hz/2)) {
+	  }
+
+	  if (usbd_config_td_is_gone(&(sc->sc_config_td))) {
+	        sc->sc_intr_owakeup = 0;
+		goto done;
+	  }
 	}
 done:
 	return;
 }
 
-/*
- * Offset correction (all ranges except CTL use word addressing)
- */
-static uint32_t
-zyd_addrinc(uint32_t addr)
-{
-	uint32_t range = ZYD_GET_RANGE(addr);
-	uint32_t offs = ZYD_GET_OFFS(addr);
-
-	offs += (range == ZYD_RANGE_CTL) ? 2 : 1;
-
-	return (range | offs);
-}
-
-/*
- * Read a single 16-bit register
- */
 static void
-zyd_cfg_read16(struct zyd_softc *sc, uint32_t addr, uint16_t *value)
+zyd_cfg_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, uint16_t ilen,
+    void *odata, uint16_t olen, uint16_t flags)
 {
-	zyd_cfg_read16_multi(sc, &addr, value, 1);
-	return;
-}
+	zyd_cfg_usb_intr_write(sc, idata, code, ilen);
 
-/*
- * Read a single 32-bit register
- */
-static void
-zyd_cfg_read32(struct zyd_softc *sc, uint32_t addr, uint32_t *value)
-{
-	zyd_cfg_read32_multi(sc, &addr, value, 1);
+	if (flags & ZYD_CMD_FLAG_READ) {
+		zyd_cfg_usb_intr_read(sc, odata, olen);
+	}
 	return;
 }
 
-/*
- * Read up to 15 16-bit registers (newer firmware versions)
- */
 static void
-zyd_cfg_read16_multi(struct zyd_softc *sc, const uint32_t *addrs, uint16_t *data,
-    uint8_t usecount)
+zyd_cfg_read16(struct zyd_softc *sc, uint16_t addr, uint16_t *value)
 {
-	struct zyd_intoutmultiread in;
-	struct zyd_intinmultioutput op;
-	uint8_t i;
-
-	memset(&in, 0, sizeof(struct zyd_intoutmultiread));
-	memset(&op, 0, sizeof(struct zyd_intinmultioutput));
-
-	USETW(in.id, ZYD_CMD_IORDREQ);
-
-	for (i = 0; i < usecount; i++)
-		USETW(in.addr[i], zyd_getrealaddr(sc, addrs[i]));
-
-	zyd_cfg_usb_intr_write(sc, &in, (2 + (usecount * 2)));
-	zyd_cfg_usb_intr_read(sc, &op, (2 + (usecount * 4)));
-
-	for (i = 0; i < usecount; i++) {
-		data[i] = UGETW(op.registers[i].data);
-	}
+	struct zyd_pair tmp[1];
+	addr = htole16(addr);
+	zyd_cfg_cmd(sc, ZYD_CMD_IORD, &addr, sizeof(addr),
+	   tmp, sizeof(tmp), ZYD_CMD_FLAG_READ);
+	*value = le16toh(tmp[0].val);
 	return;
 }
 
-/*
- * Read up to 7 32-bit registers (newer firmware versions)
- */
 static void
-zyd_cfg_read32_multi(struct zyd_softc *sc, const uint32_t *addrs, uint32_t *data,
-    uint8_t usecount)
+zyd_cfg_read32(struct zyd_softc *sc, uint16_t addr, uint32_t *value)
 {
-	struct zyd_intoutmultiread in;
-	struct zyd_intinmultioutput op;
-	uint8_t i;
-	uint8_t realcount;
+	struct zyd_pair tmp[2];
+	uint16_t regs[2];
 
-	realcount = usecount * 2;
+	regs[0] = ZYD_REG32_HI(addr);
+	regs[1] = ZYD_REG32_LO(addr);
+	regs[0] = htole16(regs[0]);
+	regs[1] = htole16(regs[1]);
 
-	memset(&in, 0, sizeof(struct zyd_intoutmultiread));
-	memset(&op, 0, sizeof(struct zyd_intinmultioutput));
-
-	USETW(in.id, ZYD_CMD_IORDREQ);
-
-	for (i = 0; i < usecount; i++) {
-		/* high word is first */
-		USETW(in.addr[i * 2], zyd_getrealaddr(sc, zyd_addrinc(addrs[i])));
-		USETW(in.addr[(i * 2) + 1], zyd_getrealaddr(sc, addrs[i]));
-	}
-
-	zyd_cfg_usb_intr_write(sc, &in, (2 + (realcount * 2)));
-	zyd_cfg_usb_intr_read(sc, &op, (2 + (realcount * 4)));
-
-	for (i = 0; i < usecount; i++) {
-		data[i] =
-		    (UGETW(op.registers[i * 2].data) << 16) |
-		    UGETW(op.registers[(i * 2) + 1].data);
-	}
+	zyd_cfg_cmd(sc, ZYD_CMD_IORD, regs, sizeof(regs), 
+	  tmp, sizeof(tmp), ZYD_CMD_FLAG_READ);
+	*value = (le16toh(tmp[0].val) << 16) | le16toh(tmp[1].val);
 	return;
 }
 
-/*
- * Write a single 16-bit register
- */
 static void
-zyd_cfg_write16(struct zyd_softc *sc, uint32_t addr, uint16_t value)
+zyd_cfg_write16(struct zyd_softc *sc, uint16_t reg, uint16_t val)
 {
-	zyd_cfg_write16_multi(sc, &addr, &value, 1);
-	return;
-}
+	struct zyd_pair pair[1];
 
-/*
- * Write a single 32-bit register
- */
-static void
-zyd_cfg_write32(struct zyd_softc *sc, uint32_t addr, uint32_t value)
-{
-	zyd_cfg_write32_multi(sc, &addr, &value, 1);
-	return;
-}
+	pair[0].reg = htole16(reg);
+	pair[0].val = htole16(val);
 
-/*
- * Write up to 15 16-bit registers (newer firmware versions)
- */
-static void
-zyd_cfg_write16_multi(struct zyd_softc *sc, const uint32_t *addrs, uint16_t *data,
-    uint8_t usecount)
-{
-	struct zyd_intoutmultiwrite mw;
-	uint8_t i;
-
-	memset(&mw, 0, sizeof(struct zyd_intoutmultiwrite));
-
-	USETW(mw.id, ZYD_CMD_IOWRREQ);
-
-	for (i = 0; i < usecount; i++) {
-		USETW(mw.registers[i].addr, zyd_getrealaddr(sc, addrs[i]));
-		USETW(mw.registers[i].data, data[i]);
-	}
-
-	zyd_cfg_usb_intr_write(sc, &mw, (2 + (usecount * 4)));
+	zyd_cfg_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0);
 	return;
 }
 
-/*
- * Write up to 7 32-bit registers (newer firmware versions)
- */
 static void
-zyd_cfg_write32_multi(struct zyd_softc *sc, const uint32_t *addrs, uint32_t *data,
-    uint8_t usecount)
+zyd_cfg_write32(struct zyd_softc *sc, uint16_t reg, uint32_t val)
 {
-	struct zyd_intoutmultiwrite mw;
-	uint8_t i;
-	uint8_t realcount;
+	struct zyd_pair pair[2];
 
-	realcount = usecount * 2;
+	pair[0].reg = htole16(ZYD_REG32_HI(reg));
+	pair[0].val = htole16(val >> 16);
+	pair[1].reg = htole16(ZYD_REG32_LO(reg));
+	pair[1].val = htole16(val & 0xffff);
 
-	memset(&mw, 0, sizeof(struct zyd_intoutmultiwrite));
-
-	USETW(mw.id, ZYD_CMD_IOWRREQ);
-
-	for (i = 0; i < usecount; i++) {
-		/* high word is first */
-		USETW(mw.registers[i * 2].addr, zyd_getrealaddr(sc, zyd_addrinc(addrs[i])));
-		USETW(mw.registers[i * 2].data, (*data >> 16));
-
-		USETW(mw.registers[(i * 2) + 1].addr, zyd_getrealaddr(sc, addrs[i]));
-		USETW(mw.registers[(i * 2) + 1].data, (*data));
-	}
-
-	zyd_cfg_usb_intr_write(sc, &mw, (2 + (realcount * 4)));
+	zyd_cfg_cmd(sc, ZYD_CMD_IOWR, pair, sizeof(pair), NULL, 0, 0);
 	return;
 }
 
-/*
- * Batch write 16-bit data
- */
+/*------------------------------------------------------------------------*
+ *	zyd_cfg_rfwrite - write RF registers
+ *------------------------------------------------------------------------*/

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list