Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Dec 2000 15:55:32 +0900
From:      YAMAMOTO Shigeru <shigeru@iij.ad.jp>
To:        freebsd-mobile@FreeBSD.ORG, freebsd-current@FreeBSD.ORG
Subject:   patch for wi driver
Message-ID:  <20001211155532C.shigeru@iij.ad.jp>

next in thread | raw e-mail | index | archive | help
----Next_Part(Mon_Dec_11_15:51:58_2000_406)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi, all.
I send a patch for wi driver.

Some cases, we have errors,
'wi0: tx buffer allocation failed'
and
'wi0: mgmt. buffer allocation failed'

Thease errors are caused by bugs in wi driver.
#Current wi driver has initialization and resource allocation mistakes.

And this patch includes WEP support code for PrismII chip.
Original WEP support code was writen by Onoe at NetBSD.
But WEP support code does not work many PrismII based cards on FreeBSD.
We need more hack.

Thanks,
-------
YAMAMOTO Shigeru			Internet Initiative Japan Inc.
<shigeru@iij.ad.jp>			Network Engineering Div.

----Next_Part(Mon_Dec_11_15:51:58_2000_406)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="wi.diff"

Index: if_wi.c
===================================================================
RCS file: /share/cvsup/FreeBSD/current/usr/src/sys/i386/isa/if_wi.c,v
retrieving revision 1.29
diff -u -r1.29 if_wi.c
--- if_wi.c	2000/11/30 18:52:31	1.29
+++ if_wi.c	2000/12/11 04:46:37
@@ -231,10 +231,34 @@
 	struct wi_ltv_gen	gen;
 	struct ifnet		*ifp;
 	int			error;
+	u_int32_t		flags;
 
 	sc = device_get_softc(dev);
 	ifp = &sc->arpcom.ac_if;
 
+	/*
+	 *	XXX: quick hack to support Prism II chip.
+	 *	Currently, we need to set a flags in pccard.conf to specify
+	 *	which type chip is used.
+	 *
+	 *	We need to replace this code in a future.
+	 *	It is better to use CIS than using a flag.
+	 */
+	flags = device_get_flags(dev);
+#define	WI_FLAGS_PRISM2	0x10000
+	if (flags & WI_FLAGS_PRISM2) {
+		sc->wi_prism2 = 1;
+		if (bootverbose) {
+			device_printf(dev, "found PrismII chip\n");
+		}
+	}
+	else {
+		sc->wi_prism2 = 0;
+		if (bootverbose) {
+			device_printf(dev, "found Lucent chip\n");
+		}
+	}
+
 	error = wi_alloc(dev);
 	if (error) {
 		device_printf(dev, "wi_alloc() failed! (%d)\n", error);
@@ -320,6 +344,12 @@
 	wi_read_record(sc, &gen);
 	sc->wi_has_wep = gen.wi_val;
 
+	if (bootverbose) {
+		device_printf(sc->dev,
+				__FUNCTION__ ":wi_has_wep = %d\n",
+				sc->wi_has_wep);
+	}
+
 	bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
 
 	wi_init(sc);
@@ -589,7 +619,21 @@
 {
 	int			i, s = 0;
 
+	/* wait for the busy bit to clear */
+	for (i = 0; i < WI_TIMEOUT; i++) {
+		if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
+			break;
+		}
+		DELAY(10*1000);	/* 10 m sec */
+	}
+
+	if (i == WI_TIMEOUT) {
+		return(ETIMEDOUT);
+	}
+
 	CSR_WRITE_2(sc, WI_PARAM0, val);
+	CSR_WRITE_2(sc, WI_PARAM1, 0);
+	CSR_WRITE_2(sc, WI_PARAM2, 0);
 	CSR_WRITE_2(sc, WI_COMMAND, cmd);
 
 	for (i = 0; i < WI_TIMEOUT; i++) {
@@ -621,11 +665,12 @@
 static void wi_reset(sc)
 	struct wi_softc		*sc;
 {
+#ifdef foo
 	wi_cmd(sc, WI_CMD_INI, 0);
 	DELAY(100000);
 	wi_cmd(sc, WI_CMD_INI, 0);
+#endif
 	DELAY(100000);
-#ifdef foo
 	if (wi_cmd(sc, WI_CMD_INI, 0))
 		device_printf(sc->dev, "init failed\n");
 	CSR_WRITE_2(sc, WI_INT_EN, 0);
@@ -633,7 +678,7 @@
 
 	/* Calibrate timer. */
 	WI_SETVAL(WI_RID_TICK_TIME, 8);
-#endif
+
 	return;
 }
 
@@ -646,6 +691,23 @@
 {
 	u_int16_t		*ptr;
 	int			i, len, code;
+	struct wi_ltv_gen	*oltv, p2ltv;
+
+	oltv = ltv;
+	if (sc->wi_prism2) {
+		switch (ltv->wi_type) {
+		case WI_RID_ENCRYPTION:
+			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+			p2ltv.wi_len = 2;
+			ltv = &p2ltv;
+			break;
+		case WI_RID_TX_CRYPT_KEY:
+			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+			p2ltv.wi_len = 2;
+			ltv = &p2ltv;
+			break;
+		}
+	}
 
 	/* Tell the NIC to enter record read mode. */
 	if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
@@ -675,6 +737,35 @@
 	for (i = 0; i < ltv->wi_len - 1; i++)
 		ptr[i] = CSR_READ_2(sc, WI_DATA1);
 
+	if (sc->wi_prism2) {
+		switch (oltv->wi_type) {
+		case WI_RID_TX_RATE:
+		case WI_RID_CUR_TX_RATE:
+			switch (ltv->wi_val) {
+			case 1: oltv->wi_val = 1; break;
+			case 2: oltv->wi_val = 2; break;
+			case 3:	oltv->wi_val = 6; break;
+			case 4: oltv->wi_val = 5; break;
+			case 7: oltv->wi_val = 7; break;
+			case 8: oltv->wi_val = 11; break;
+			case 15: oltv->wi_val = 3; break;
+			default: oltv->wi_val = 0x100 + ltv->wi_val; break;
+			}
+			break;
+		case WI_RID_ENCRYPTION:
+			oltv->wi_len = 2;
+			if (ltv->wi_val & 0x01)
+				oltv->wi_val = 1;
+			else
+				oltv->wi_val = 0;
+			break;
+		case WI_RID_TX_CRYPT_KEY:
+			oltv->wi_len = 2;
+			oltv->wi_val = ltv->wi_val;
+			break;
+		}
+	}
+
 	return(0);
 }
 
@@ -687,6 +778,59 @@
 {
 	u_int16_t		*ptr;
 	int			i;
+	struct wi_ltv_gen	p2ltv;
+
+	if (sc->wi_prism2) {
+		switch (ltv->wi_type) {
+		case WI_RID_TX_RATE:
+			p2ltv.wi_type = WI_RID_TX_RATE;
+			p2ltv.wi_len = 2;
+			switch (ltv->wi_val) {
+			case 1: p2ltv.wi_val = 1; break;
+			case 2: p2ltv.wi_val = 2; break;
+			case 3:	p2ltv.wi_val = 15; break;
+			case 5: p2ltv.wi_val = 4; break;
+			case 6: p2ltv.wi_val = 3; break;
+			case 7: p2ltv.wi_val = 7; break;
+			case 11: p2ltv.wi_val = 8; break;
+			default: return EINVAL;
+			}
+			ltv = &p2ltv;
+			break;
+		case WI_RID_ENCRYPTION:
+			p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+			p2ltv.wi_len = 2;
+			if (ltv->wi_val)
+				p2ltv.wi_val = 0x03;
+			else
+				p2ltv.wi_val = 0x90;
+			ltv = &p2ltv;
+			break;
+		case WI_RID_TX_CRYPT_KEY:
+			p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+			p2ltv.wi_len = 2;
+			p2ltv.wi_val = ltv->wi_val;
+			ltv = &p2ltv;
+			break;
+		case WI_RID_DEFLT_CRYPT_KEYS:
+		    {
+			int error;
+			struct wi_ltv_str	ws;
+			struct wi_ltv_keys	*wk = (struct wi_ltv_keys *)ltv;
+			for (i = 0; i < 4; i++) {
+				ws.wi_len = 4;
+				ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
+				memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
+				ws.wi_str[5] = '\0';
+				error = wi_write_record(sc,
+				    (struct wi_ltv_gen *)&ws);
+				if (error)
+					return error;
+			}
+			return 0;
+		    }
+		}
+	}
 
 	if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
 		return(EIO);
@@ -1362,7 +1506,8 @@
 
 	rid = 0;
 	sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
-					0, ~0, 1, RF_ACTIVE);
+				0, ~0, (1 << 6),
+				rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
 	if (!sc->iobase) {
 		device_printf(dev, "No I/O space?!\n");
 		return (ENXIO);
Index: if_wireg.h
===================================================================
RCS file: /share/cvsup/FreeBSD/current/usr/src/sys/i386/isa/if_wireg.h,v
retrieving revision 1.9
diff -u -r1.9 if_wireg.h
--- if_wireg.h	2000/10/13 20:33:24	1.9
+++ if_wireg.h	2000/12/11 04:48:15
@@ -66,6 +66,13 @@
 #define WI_RID_DEFLT_CRYPT_KEYS	0xFCB0
 #define WI_RID_TX_CRYPT_KEY	0xFCB1
 #define WI_RID_WEP_AVAIL	0xFD4F
+#define WI_RID_P2_TX_CRYPT_KEY	0xFC23
+#define WI_RID_P2_CRYPT_KEY0	0xFC24
+#define WI_RID_P2_CRYPT_KEY1	0xFC25
+#define WI_RID_P2_CRYPT_KEY2	0xFC26
+#define WI_RID_P2_CRYPT_KEY3	0xFC27
+#define WI_RID_P2_ENCRYPTION	0xFC28
+#define WI_RID_CUR_TX_RATE	0xFD44 /* current TX rate */
 struct wi_key {
 	u_int16_t		wi_keylen;
 	u_int8_t		wi_keydat[14];
@@ -118,6 +125,7 @@
 #endif
 	struct callout_handle	wi_stat_ch;
 	struct mtx		wi_mtx;
+	int			wi_prism2;	/* set to 1 if it uses a Prism II chip */
 };
 
 #define	WI_LOCK(_sc)		mtx_enter(&(_sc)->wi_mtx, MTX_DEF)

----Next_Part(Mon_Dec_11_15:51:58_2000_406)----


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001211155532C.shigeru>