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>