Subject: wi0 on SMC 2632W
To: None <port-i386@netbsd.org>
From: Rafal Boni <rafal@mediaone.net>
List: port-i386
Date: 12/18/2000 16:33:03
So, in part because Seebs started playing with the wi driver on cheapo cards
and in part because a co-worker picked up a set of SMC 802.11 cards, I had to
check out and see if things worked with that card.
Taking Seebs' work and some changes from the patches by Bill Paul, I got the
card to the point where I could diff my changes against anoncvs.netbsd.org,
using the Airport that one of my other co-workers has on our network...
Here are the patches I used... All the credit goes to Seebs and Bill for the
hard work, I just attempted to distill a set of patches that would make this
specific card go.
There are still some gotchas:
(1) Still get timeout on wi_init.
(2) Get occasional 'wi_read[0xFC80] got X out of Y characters'
Where X,Y tend to be 4 and 1 or 49 and 16.
(3) The driver forces PRISMII mode currently, as the card ID's
itself as a Lucent WaveLan/IEEE card.
These patches also add the correct patches for if_wireg.h (Seebs had the
order reversed).
--rafal
Index: if_wi.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/if_wi.c,v
retrieving revision 1.41
diff -b -u -r1.41 if_wi.c
--- if_wi.c 2000/10/13 19:15:08 1.41
+++ if_wi.c 2000/12/18 21:19:02
@@ -320,6 +320,8 @@
static const u_int8_t empty_macaddr[ETHER_ADDR_LEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+ int i;
+ struct wi_ltv_serial serialno;
/* Enable the card. */
sc->sc_pf = pa->pf;
@@ -347,8 +349,11 @@
if (pp == NULL) {
/* should not happen */
sc->sc_prism2 = 0;
- } else
- sc->sc_prism2 = pp->pp_prism2;
+ } else {
+ printf("card is '%s'?\n", pp->pp_name ? pp->pp_name : "(null)");
+ /* sc->sc_prism2 = pp->pp_prism2; */
+ sc->sc_prism2 = 1;
+ }
callout_init(&sc->wi_inquire_ch);
@@ -360,10 +365,23 @@
wi_reset(sc);
memset(&mac, 0, sizeof(mac));
+ serialno.wi_type = WI_RID_SERIALNO;
+ serialno.wi_len = 12;
+ i = wi_read_record(sc, (struct wi_ltv_gen *)&serialno);
+ if (i) {
+ printf("read serial failed errno %d\n", i);
+ } else
+ for (i = 0; i < 12; ++i) {
+ printf("sn byte 0x%x: %02x\n", i, serialno.wi_serial[i]);
+ }
+
/* Read the station address. */
mac.wi_type = WI_RID_MAC_NODE;
- mac.wi_len = 4;
- wi_read_record(sc, (struct wi_ltv_gen *)&mac);
+ mac.wi_len = 7;
+ i = wi_read_record(sc, (struct wi_ltv_gen *)&mac);
+ if (i) {
+ printf("read mac failed errno %d\n", i);
+ }
memcpy(sc->sc_macaddr, mac.wi_mac_addr, ETHER_ADDR_LEN);
/*
@@ -740,7 +758,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++) {
@@ -772,8 +804,10 @@
static void wi_reset(sc)
struct wi_softc *sc;
{
- if (wi_cmd(sc, WI_CMD_INI, 0))
- printf("%s: init failed\n", sc->sc_dev.dv_xname);
+ int i;
+
+ if ((i = wi_cmd(sc, WI_CMD_INI, 0)))
+ printf("%s: init failed [errno %d]\n", sc->sc_dev.dv_xname, i);
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
@@ -811,12 +845,16 @@
}
/* Tell the NIC to enter record read mode. */
- if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
+ if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type)) {
+ printf("couldn't access record of type 0x%X\n", ltv->wi_type);
return(EIO);
+ }
/* Seek to the record. */
- if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
+ if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1)) {
+ printf("couldn't seek record of type 0x%X\n", ltv->wi_type);
return(EIO);
+ }
/*
* Read the length and record type and make sure they
@@ -824,11 +862,17 @@
* room to hold all of the returned data).
*/
len = CSR_READ_2(sc, WI_DATA1);
- if (len > ltv->wi_len)
+ if (len > ltv->wi_len) {
+ printf("wi_read [0x%X] got %d out of %d characters!\n",
+ ltv->wi_type, len, ltv->wi_len);
return(ENOSPC);
+ }
code = CSR_READ_2(sc, WI_DATA1);
- if (code != ltv->wi_type)
+ if (code != ltv->wi_type) {
+ printf("wi_read got type %X, expecting %X\n",
+ code, ltv->wi_type);
return(EIO);
+ }
ltv->wi_len = len;
ltv->wi_type = code;
@@ -925,6 +969,7 @@
ws.wi_str[5] = '\0';
error = wi_write_record(sc,
(struct wi_ltv_gen *)&ws);
+ wi_read_record(sc, (struct wi_ltv_gen *) &ws);
if (error)
return error;
}
@@ -1116,6 +1161,8 @@
mcast.wi_len = ((ETHER_ADDR_LEN / 2) * 16) + 1;
wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
+ mcast.wi_len = 16;
+ wi_read_record(sc, (struct wi_ltv_gen *)&mcast);
return;
}
@@ -1138,6 +1185,7 @@
mcast.wi_type = WI_RID_MCAST;
mcast.wi_len = ((ETHER_ADDR_LEN / 2) * i) + 1;
wi_write_record(sc, (struct wi_ltv_gen *)&mcast);
+ wi_read_record(sc, (struct wi_ltv_gen *)&mcast);
}
static int
@@ -1367,9 +1415,12 @@
error = wi_mgmt_xmit(sc, (caddr_t)&wreq.wi_val,
wreq.wi_len);
} else {
- if (sc->sc_enabled != 0)
+ if (sc->sc_enabled != 0) {
error = wi_write_record(sc,
(struct wi_ltv_gen *)&wreq);
+ wi_read_record(sc,
+ (struct wi_ltv_gen *)&wreq);
+ }
if (error == 0)
error = wi_setdef(sc, &wreq);
if (error == 0 && sc->sc_enabled != 0)
@@ -1494,6 +1545,7 @@
mac.wi_type = WI_RID_MAC_NODE;
memcpy(&mac.wi_mac_addr, sc->sc_macaddr, ETHER_ADDR_LEN);
wi_write_record(sc, (struct wi_ltv_gen *)&mac);
+ wi_read_record(sc, (struct wi_ltv_gen *)&mac);
/* Configure WEP. */
if (sc->wi_has_wep) {
@@ -1502,6 +1554,7 @@
sc->wi_keys.wi_len = (sizeof(struct wi_ltv_keys) / 2) + 1;
sc->wi_keys.wi_type = WI_RID_DEFLT_CRYPT_KEYS;
wi_write_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
+ wi_read_record(sc, (struct wi_ltv_gen *)&sc->wi_keys);
}
/* Initialize promisc mode. */
@@ -1808,10 +1861,14 @@
struct wi_req *wreq;
struct ieee80211_nwid *ws;
{
+ int ret;
wreq->wi_type = type;
wi_request_fill_ssid(wreq, ws);
- return (wi_write_record(sc, (struct wi_ltv_gen *)wreq));
+ ret = wi_write_record(sc, (struct wi_ltv_gen *)wreq);
+ wreq->wi_len = 20;
+ wi_read_record(sc, (struct wi_ltv_gen *)wreq);
+ return ret;
}
static int
@@ -1950,6 +2007,7 @@
wk->wi_type = WI_RID_DEFLT_CRYPT_KEYS;
if (sc->sc_enabled != 0) {
error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
+ wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
if (error)
return error;
}
@@ -1962,6 +2020,7 @@
wreq.wi_val[0] = nwkey->i_defkid - 1;
if (sc->sc_enabled != 0) {
error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
+ wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
if (error)
return error;
}
@@ -1973,6 +2032,7 @@
wreq.wi_val[0] = nwkey->i_wepon;
if (sc->sc_enabled != 0) {
error = wi_write_record(sc, (struct wi_ltv_gen *)&wreq);
+ wi_read_record(sc, (struct wi_ltv_gen *)&wreq);
if (error)
return error;
}
Index: if_wireg.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/if_wireg.h,v
retrieving revision 1.6
diff -b -u -r1.6 if_wireg.h
--- if_wireg.h 2000/05/23 08:41:49 1.6
+++ if_wireg.h 2000/12/18 21:19:06
@@ -296,6 +296,7 @@
g.wi_type = recno; \
g.wi_val = val; \
wi_write_record(sc, &g); \
+ wi_read_record(sc, &g); \
} while (0)
#define WI_SETSTR(recno, str) \
@@ -415,6 +416,12 @@
u_int16_t wi_len;
u_int16_t wi_type;
u_int8_t wi_mac_addr[6];
+};
+
+struct wi_ltv_serial {
+ u_int16_t wi_len;
+ u_int16_t wi_type;
+ u_int8_t wi_serial[12];
};
/*
----
Rafal Boni rafal@mediaone.net