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.
<[EMAIL PROTECTED]>                     Network Engineering Div.
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)

Reply via email to