Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2001 20:47:55 -0700
From:      Brooks Davis <brooks@one-eyed-alien.net>
To:        audit@freebsd.org, mobile@freebsd.org
Subject:   review request: an(4) patches
Message-ID:  <20010621204755.A18153@Odin.AC.HMC.Edu>

next in thread | raw e-mail | index | archive | help

--ew6BAiZeqk4r7MaW
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

I'd like to request a review of the attached patch to the an driver
before I commit it.  It corrects a number of minor problems with the
output of ifconfig status for an cards as well as insuring that changes
in the length of resources on the cards (from firmware upgrades, etc)
don't smash the kernel's stack.  Once this patch has spent a week or so
in -current we'll be ready for the 802.11 ifconfig support MFC.

-- Brooks

Index: if_aironet_ieee.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/an/if_aironet_ieee.h,v
retrieving revision 1.5
diff -u -r1.5 if_aironet_ieee.h
--- if_aironet_ieee.h	2001/05/26 09:26:58	1.5
+++ if_aironet_ieee.h	2001/06/01 23:24:42
@@ -528,7 +528,7 @@
 	u_int16_t		an_max_noise_prev_sec;	/* 0x7A */
 	u_int16_t		an_avg_noise_prev_min;	/* 0x7C */
 	u_int16_t		an_max_noise_prev_min;	/* 0x7E */
-	u_int16_t		an_spare[3];
+	u_int16_t		an_spare[5];
 };
=20
 #define AN_STATUS_OPMODE_CONFIGURED		0x0001
Index: if_an.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/an/if_an.c,v
retrieving revision 1.18
diff -u -r1.18 if_an.c
--- if_an.c	2001/06/15 00:10:30	1.18
+++ if_an.c	2001/06/22 03:43:18
@@ -162,9 +162,13 @@
 					struct mbuf *, unsigned short));
 #endif
=20
+static void an_dump_record	__P((struct an_softc *,struct an_ltv_gen *,
+				char *));
+
 static int an_media_change	__P((struct ifnet *));
 static void an_media_status	__P((struct ifnet *, struct ifmediareq *));
=20
+static int	an_dump=3D0;
 /*=20
  * We probe for an Aironet 4500/4800 card by attempting to
  * read the default SSID list. On reset, the first entry in
@@ -511,7 +515,7 @@
 	int			status;
 {
 	struct ifnet		*ifp;
-	int			id;
+	int			id, i;
=20
 	/* TX DONE enable lan monitor DJA
 	   an_enable_sniff();
@@ -529,12 +533,13 @@
 	} else
 		ifp->if_opackets++;
=20
-	if (id !=3D sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons])
-		printf("an%d: id mismatch: expected %x, got %x\n",
-		    sc->an_unit,
-		    sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons], id);
+	for (i =3D 0; i < AN_TX_RING_CNT; i++ ) {
+		if (id =3D=3D sc->an_rdata.an_tx_ring[i]) {
+			sc->an_rdata.an_tx_ring[i] =3D 0;
+			break;
+		}
+	}
=20
-	sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons] =3D 0;
 	AN_INC(sc->an_rdata.an_tx_cons, AN_TX_RING_CNT);
=20
 	return;
@@ -720,9 +725,10 @@
 	struct an_ltv_gen	*ltv;
 {
 	u_int16_t		*ptr;
+	u_int8_t		*ptr2;
 	int			i, len;
=20
-	if (ltv->an_len =3D=3D 0 || ltv->an_type =3D=3D 0)
+	if (ltv->an_len <=3D 2 || ltv->an_type =3D=3D 0)
 		return(EINVAL);
=20
 	/* Tell the NIC to enter record read mode. */
@@ -741,20 +747,29 @@
 	 * Read the length and record type and make sure they
 	 * match what we expect (this verifies that we have enough
 	 * room to hold all of the returned data).
+	 * Length includes type but not length.
 	 */
 	len =3D CSR_READ_2(sc, AN_DATA1);
-	if (len > (ltv->an_len - 2)) {
+	if (len > (ltv->an_len-2)) {
 		printf("an%d: record length mismatch -- expected %d, "
-		    "got %d\n", sc->an_unit, (ltv->an_len - 2), len);
-		len =3D (ltv->an_len - 2);
+		    "got %d for Rid %x\n", sc->an_unit,
+		    ltv->an_len-2, len, ltv->an_type);
+		len =3D ltv->an_len -2;
+	}else{
+		ltv->an_len =3D len +2;
 	}
=20
-	ltv->an_len =3D len;
-
 	/* Now read the data. */
+	len -=3D 2;	/* skip the type */
 	ptr =3D &ltv->an_val;
-	for (i =3D 0; i < (ltv->an_len - 2) >> 1; i++)
-		ptr[i] =3D CSR_READ_2(sc, AN_DATA1);
+	for (i =3D len; i > 1; i-=3D2)
+		*ptr++ =3D CSR_READ_2(sc, AN_DATA1);
+	if (i){
+		ptr2 =3D (u_int8_t *)ptr;
+		*ptr2 =3D CSR_READ_1(sc, AN_DATA1);
+	}
+	if (an_dump)
+		an_dump_record(sc, ltv, "Read");
=20
 	return(0);
 }
@@ -767,19 +782,32 @@
 	struct an_ltv_gen	*ltv;
 {
 	u_int16_t		*ptr;
-	int			i;
+	u_int8_t		*ptr2;
+	int			i, len;
+
+	if (an_dump)
+		an_dump_record(sc, ltv, "Write");
=20
 	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type))
 		return(EIO);
-
+	=09
 	if (an_seek(sc, ltv->an_type, 0, AN_BAP1))
 		return(EIO);
=20
-	CSR_WRITE_2(sc, AN_DATA1, ltv->an_len-2);
+	/*
+	 * Length includes type but not length.
+	 */
+	len =3D ltv->an_len-2;
+	CSR_WRITE_2(sc, AN_DATA1, len);
 =09
+	len -=3D 2;	/* skip the type */
 	ptr =3D &ltv->an_val;
-	for (i =3D 0; i < (ltv->an_len - 4) >> 1; i++)
-		CSR_WRITE_2(sc, AN_DATA1, ptr[i]);
+	for (i=3Dlen; i > 1; i-=3D2)
+		CSR_WRITE_2(sc, AN_DATA1, *ptr++);
+	if (i){
+		ptr2 =3D (u_int8_t *)ptr;
+		CSR_WRITE_1(sc, AN_DATA0, *ptr2);
+	}
=20
 	if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_WRITE, ltv->an_type))
 		return(EIO);
@@ -787,6 +815,50 @@
 	return(0);
 }
=20
+static void an_dump_record(sc, ltv, string)
+	struct an_softc		*sc;
+	struct an_ltv_gen	*ltv;
+	char			*string;
+{
+	u_int8_t		*ptr2;
+	int			len;
+	int			i;
+	int			count =3D 0;
+	char			buf[17], temp;
+
+	len =3D ltv->an_len-4;
+	printf("an%d: RID %4x, Length %4d, Mode %s\n",=20
+		sc->an_unit, ltv->an_type, ltv->an_len-4, string);
+
+	if(an_dump =3D=3D 1 || (an_dump =3D=3D ltv->an_type)){
+		printf("an%d:\t", sc->an_unit);
+		bzero(buf,sizeof(buf));
+
+		ptr2 =3D (u_int8_t *)&ltv->an_val;
+		for (i=3Dlen; i>0; i--){
+			printf("%02x ", *ptr2);
+
+			temp=3D*ptr2++;
+			if(temp>=3D' ' && temp <=3D'~')
+				buf[count]=3Dtemp;
+			else if(temp>=3D'A' && temp <=3D'Z')
+				buf[count]=3Dtemp;
+			else
+				buf[count]=3D'.';
+			if(++count =3D=3D 16){
+				count =3D 0;
+				printf("%s\n",buf);
+				printf("an%d:\t", sc->an_unit);
+				bzero(buf,sizeof(buf));
+			}
+		}
+		for(; count !=3D 16; count++){
+			printf("   ");
+		}
+		printf(" %s\n",buf);
+	}
+}
+
 static int an_seek(sc, id, off, chan)
 	struct an_softc		*sc;
 	int			id, off, chan;
@@ -838,12 +910,11 @@
 	}
=20
 	ptr =3D (u_int16_t *)buf;
-	for (i =3D 0; i < len / 2; i++)
-		ptr[i] =3D CSR_READ_2(sc, AN_DATA1);
-	i*=3D2;
-	if (i<len){
-	        ptr2 =3D (u_int8_t *)buf;
-	        ptr2[i] =3D CSR_READ_1(sc, AN_DATA1);
+	for (i =3D len; i > 1; i-=3D2)
+		*ptr++ =3D CSR_READ_2(sc, AN_DATA1);
+	if (i){
+		ptr2 =3D (u_int8_t *)ptr;
+		*ptr2 =3D CSR_READ_1(sc, AN_DATA1);
 	}
=20
 	return(0);
@@ -865,12 +936,11 @@
 	}
=20
 	ptr =3D (u_int16_t *)buf;
-	for (i =3D 0; i < (len / 2); i++)
-		CSR_WRITE_2(sc, AN_DATA0, ptr[i]);
-	i*=3D2;
-	if (i<len){
-	        ptr2 =3D (u_int8_t *)buf;
-	        CSR_WRITE_1(sc, AN_DATA0, ptr2[i]);
+	for (i =3D len; i > 1; i-=3D2)
+		CSR_WRITE_2(sc, AN_DATA0, *ptr++);
+	if (i){
+	        ptr2 =3D (u_int8_t *)ptr;
+	        CSR_WRITE_1(sc, AN_DATA0, *ptr2);
 	}
=20
 	return(0);
@@ -1190,16 +1260,16 @@
 			len =3D 0;
 			if(ireq->i_val < 4) {
 				areq.an_type =3D AN_RID_WEP_TEMP;
-				for(i=3D0; i<4; i++) {
-					areq.an_len =3D sizeof(areq);
+				for(i=3D0; i<5; i++) {
 					if (an_read_record(sc,
 					    (struct an_ltv_gen *)&areq)) {
 						error =3D EINVAL;
 						break;
 					}
-					len =3D key->klen;
-					if(i =3D=3D ireq->i_val)
+					if(key->kindex =3D=3D 0xffff)
 						break;
+					if(key->kindex =3D=3D ireq->i_val)
+						len =3D key->klen;
 					/* Required to get next entry */
 					areq.an_type =3D AN_RID_WEP_PERM;
 				}
@@ -1219,6 +1289,25 @@
 			ireq->i_val =3D 8;
 			break;
 		case IEEE80211_IOC_WEPTXKEY:
+			/*
+			 * For some strange reason, you have to read all
+			 * keys before you can read the txkey.
+			 */
+			areq.an_type =3D AN_RID_WEP_TEMP;
+			for(i=3D0; i<5; i++) {
+				if (an_read_record(sc,
+				    (struct an_ltv_gen *)&areq)) {
+					error =3D EINVAL;
+					break;
+				}
+				if(key->kindex =3D=3D 0xffff)
+					break;
+				/* Required to get next entry */
+				areq.an_type =3D AN_RID_WEP_PERM;
+			}
+			if(error)
+				break;
+
 			areq.an_type =3D AN_RID_WEP_PERM;
 			key->kindex =3D 0xffff;
 			if (an_read_record(sc,
Index: if_anreg.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /home/ncvs/src/sys/dev/an/if_anreg.h,v
retrieving revision 1.7
diff -u -r1.7 if_anreg.h
--- if_anreg.h	2001/05/26 09:26:58	1.7
+++ if_anreg.h	2001/06/01 23:24:42
@@ -532,7 +532,7 @@
 	u_int16_t		an_max_noise_prev_sec;	/* 0x7A */
 	u_int16_t		an_avg_noise_prev_min;	/* 0x7C */
 	u_int16_t		an_max_noise_prev_min;	/* 0x7E */
-	u_int16_t		an_spare[3];
+	u_int16_t		an_spare[5];
 };
=20
 #define AN_STATUS_OPMODE_CONFIGURED		0x0001

--=20
Any statement of the form "X is the one, true Y" is FALSE.
PGP fingerprint 655D 519C 26A7 82E7 2529  9BF0 5D8E 8BE9 F238 1AD4

--ew6BAiZeqk4r7MaW
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQE7Mr/pXY6L6fI4GtQRAmBDAJwNPkSvxJW/X4TbsEzYeCdxxNdT/wCg09n1
q4qyjZvd+m2pLXhFZssD494=
=pkgJ
-----END PGP SIGNATURE-----

--ew6BAiZeqk4r7MaW--

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?20010621204755.A18153>