00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 #define __WLANDRV_C__
00080 
00081 #include <compiler.h>
00082 #include <stdio.h>
00083 #include <stddef.h>
00084 #include <string.h>
00085 
00086 #include <sys/timer.h>
00087 #include <sys/thread.h>
00088 #include <sys/event.h>
00089 #include <errno.h>
00090 #include <netinet/if_ether.h>
00091 #include <net/ether.h>
00092 #include <net/if_var.h>
00093 #include <dev/irqreg.h>
00094 
00095 #include <dev/wlantypes.h>
00096 #include <dev/pcmcia.h>
00097 #include <dev/wlancfg.h>
00098 #include <dev/wlan.h>
00099 #include <dev/wlandrv.h>
00100 
00101 
00102 
00103 
00104 #if (_DEBUG >= 1)
00105 #define Debug(_x)     if (bDebugState ) printf _x
00106 #define Debug2(_x)    if (bDebugState > 1) printf _x
00107 #define panic         printf
00108 #else
00109 #define Debug(_x)
00110 #define Debug2(_x)
00111 #define panic
00112 #endif
00113 
00114 #define WI_LOCK(sc)           NutEventWait(&hDeviceSemaphore,0)
00115 #define WI_UNLOCK(sc)         NutEventPost(&hDeviceSemaphore)
00116 
00117 #define ieee80211_new_state(_a,_b,_c)  _a->ic_state=_b
00118 #define isset(_a,_b)                  (*_a & (1<<_b))
00119 
00120 #define CSR_WRITE_2(_a,_b,_c) pcmcia_WriteReg(_b,_c)
00121 #define CSR_READ_2(_a,_b)     pcmcia_ReadReg(_b)
00122 
00123 
00124 
00125 
00126 #define WLAN_MIN_ETHERNET_FRAME_LEN     60
00127 #define WLAN_MAX_ETHERNET_FRAME_LEN     1514
00128 #define WLAN_ETHERNET_HEADER_LEN                14
00129 
00130 
00131 
00132 
00133 #define WI_INTRS  (WI_EV_RX | WI_EV_ALLOC | WI_EV_INFO)
00134 
00135 struct wi_card_ident {
00136     u_int16_t card_id;
00137     char *card_name;
00138     u_int8_t firm_type;
00139 };
00140 
00141 struct ieee80211_frame_addr4 {
00142     u_int8_t i_fc[2];
00143     u_int8_t i_dur[2];
00144     u_int8_t i_addr1[IEEE80211_ADDR_LEN];
00145     u_int8_t i_addr2[IEEE80211_ADDR_LEN];
00146     u_int8_t i_addr3[IEEE80211_ADDR_LEN];
00147     u_int8_t i_seq[2];
00148     u_int8_t i_addr4[IEEE80211_ADDR_LEN];
00149 };
00150 
00151 
00152 
00153 
00154 struct wi_frame {
00155     u_int16_t wi_status;        
00156     u_int16_t wi_rx_tstamp1;    
00157     u_int16_t wi_rx_tstamp0;    
00158     u_int8_t wi_rx_silence;     
00159     u_int8_t wi_rx_signal;      
00160     u_int8_t wi_rx_rate;        
00161     u_int8_t wi_rx_flow;        
00162     u_int8_t wi_tx_rtry;        
00163     u_int8_t wi_tx_rate;        
00164     u_int16_t wi_tx_ctl;        
00165     struct ieee80211_frame_addr4 wi_whdr;       
00166     u_int16_t wi_dat_len;       
00167     struct ether_header wi_ehdr;        
00168 };
00169 
00170 
00171 
00172 
00173 struct wi_ssid {
00174     u_int16_t wi_len;
00175     u_int8_t wi_ssid[32];
00176 };
00177 
00178 
00179 
00180 
00181 typedef struct {
00182     u_int16_t DSAPSSAP;
00183     u_int16_t Control;
00184     u_int16_t MustZero;
00185     u_int16_t Type;
00186 } LLCS_SNAP_HEADER;
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 static HANDLE hDeviceSemaphore;
00196 static BYTE bDebugState = 0;
00197 
00198 struct wi_card_ident wi_card_ident[] = {
00199     
00200 
00201 
00202 #if (WLAN_SUPPORT_LUCENT >= 1)
00203     {WI_NIC_LUCENT_ID, WI_NIC_LUCENT_STR, WI_LUCENT},
00204     {WI_NIC_SONY_ID, WI_NIC_SONY_STR, WI_LUCENT},
00205     {WI_NIC_LUCENT_EMB_ID, WI_NIC_LUCENT_EMB_STR, WI_LUCENT},
00206 #endif                          
00207 
00208 #if (WLAN_SUPPORT_INTERSIL >= 1)
00209     {WI_NIC_EVB2_ID, WI_NIC_EVB2_STR, WI_INTERSIL},
00210     {WI_NIC_HWB3763_ID, WI_NIC_HWB3763_STR, WI_INTERSIL},
00211     {WI_NIC_HWB3163_ID, WI_NIC_HWB3163_STR, WI_INTERSIL},
00212     {WI_NIC_HWB3163B_ID, WI_NIC_HWB3163B_STR, WI_INTERSIL},
00213     {WI_NIC_EVB3_ID, WI_NIC_EVB3_STR, WI_INTERSIL},
00214     {WI_NIC_HWB1153_ID, WI_NIC_HWB1153_STR, WI_INTERSIL},
00215     {WI_NIC_P2_SST_ID, WI_NIC_P2_SST_STR, WI_INTERSIL},
00216     {WI_NIC_EVB2_SST_ID, WI_NIC_EVB2_SST_STR, WI_INTERSIL},
00217     {WI_NIC_3842_EVA_ID, WI_NIC_3842_EVA_STR, WI_INTERSIL},
00218     {WI_NIC_3842_PCMCIA_AMD_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL},
00219     {WI_NIC_3842_PCMCIA_SST_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL},
00220     {WI_NIC_3842_PCMCIA_ATL_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL},
00221     {WI_NIC_3842_PCMCIA_ATS_ID, WI_NIC_3842_PCMCIA_STR, WI_INTERSIL},
00222     {WI_NIC_3842_MINI_AMD_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL},
00223     {WI_NIC_3842_MINI_SST_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL},
00224     {WI_NIC_3842_MINI_ATL_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL},
00225     {WI_NIC_3842_MINI_ATS_ID, WI_NIC_3842_MINI_STR, WI_INTERSIL},
00226     {WI_NIC_3842_PCI_AMD_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL},
00227     {WI_NIC_3842_PCI_SST_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL},
00228     {WI_NIC_3842_PCI_ATS_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL},
00229     {WI_NIC_3842_PCI_ATL_ID, WI_NIC_3842_PCI_STR, WI_INTERSIL},
00230     {WI_NIC_P3_PCMCIA_AMD_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL},
00231     {WI_NIC_P3_PCMCIA_SST_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL},
00232     {WI_NIC_P3_PCMCIA_ATL_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL},
00233     {WI_NIC_P3_PCMCIA_ATS_ID, WI_NIC_P3_PCMCIA_STR, WI_INTERSIL},
00234     {WI_NIC_P3_MINI_AMD_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL},
00235     {WI_NIC_P3_MINI_SST_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL},
00236     {WI_NIC_P3_MINI_ATL_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL},
00237     {WI_NIC_P3_MINI_ATS_ID, WI_NIC_P3_MINI_STR, WI_INTERSIL},
00238 #endif                          
00239     {0, NULL, 0},
00240 };
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 static void DELAY(u_int32_t delay_us)
00251 {
00252     delay_us = delay_us / 1000;
00253     delay_us++;
00254     NutSleep(delay_us);
00255 }
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 void DumpWlanData(BYTE * pBuffer, WORD wBufferSize)
00265 {
00266     u_int16_t x, MaxX = 16;
00267     u_int16_t y, MaxY;
00268     u_int16_t Size;
00269 
00270     if (bDebugState != 0) {
00271         Size = 0;
00272         MaxY = (wBufferSize / 16) + 1;
00273         for (y = 0; y < MaxY; y++) {
00274             Debug(("%04X: ", (y * 16)));
00275             for (x = 0; x < MaxX; x++) {
00276                 Debug(("%02X ", pBuffer[Size]));
00277                 Size++;
00278 
00279                 if (Size >= wBufferSize) {
00280                     Debug(("\r\n"));
00281                     return;
00282                 }
00283             }
00284             Debug(("\r\n"));
00285         }
00286     }
00287 }
00288 
00289 
00290 
00291 
00292 static int wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
00293 {
00294     unsigned long i;            
00295     unsigned int s = 0;                 
00296     static volatile int count = 0;
00297 
00298     if (sc->wi_gone) {
00299         return (ENODEV);
00300     }
00301 
00302     
00303     
00304     
00305     
00306     count++;
00307 
00308     
00309 
00310 
00311     for (i = sc->wi_cmd_count; i > 0; i--) {    
00312         if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
00313             break;
00314         }
00315         DELAY(1 * 1000);        
00316     }
00317     if (i == 0) {
00318         Debug(("wi_cmd: busy bit won't clear.\n"));
00319         sc->wi_gone = 1;
00320         count--;
00321         return (ETIMEDOUT);
00322     }
00323 
00324     CSR_WRITE_2(sc, WI_PARAM0, val0);
00325     CSR_WRITE_2(sc, WI_PARAM1, val1);
00326     CSR_WRITE_2(sc, WI_PARAM2, val2);
00327     CSR_WRITE_2(sc, WI_COMMAND, cmd);
00328 
00329     if (cmd == WI_CMD_INI) {
00330         
00331 
00332 
00333         
00334         DELAY(250UL * 1000UL);  
00335     }
00336     for (i = 0; i < WI_TIMEOUT; i++) {
00337         
00338 
00339 
00340 
00341         s = CSR_READ_2(sc, WI_EVENT_STAT);
00342         if (s & WI_EV_CMD) {
00343             
00344 
00345 
00346             s = CSR_READ_2(sc, WI_STATUS);
00347             CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_CMD);
00348             if (s & WI_STAT_CMD_RESULT) {
00349                 count--;
00350                 return (EIO);
00351             }
00352             break;
00353         }
00354         DELAY(WI_DELAY);
00355     }
00356 
00357     count--;
00358     if (i == WI_TIMEOUT) {
00359         Debug(("timeout in wi_cmd 0x%04x; event status 0x%04x\n", cmd, s));
00360         if (s == 0xffff) {
00361             sc->wi_gone = 1;
00362         }
00363         return (ETIMEDOUT);
00364     }
00365     return (0);
00366 }
00367 
00368 
00369 
00370 
00371 void wi_stop(struct wi_softc *sc, int disable)
00372 {
00373     struct ieee80211com *ic = &sc->sc_ic;
00374 
00375     DELAY(100000);
00376 
00377     ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
00378     if (sc->sc_enabled && !sc->wi_gone) {
00379         CSR_WRITE_2(sc, WI_INT_EN, 0);
00380         wi_cmd(sc, WI_CMD_DISABLE | sc->sc_portnum, 0, 0, 0);
00381         if (disable) {
00382             sc->sc_enabled = 0;
00383         }
00384     } else {
00385         if (sc->wi_gone && disable) {   
00386             sc->sc_enabled = 0;
00387         }
00388     }
00389 
00390     sc->sc_tx_timer = 0;
00391     sc->sc_scan_timer = 0;
00392 }
00393 
00394 
00395 
00396 
00397 static int wi_seek_bap(struct wi_softc *sc, int id, int off)
00398 {
00399     long i;                     
00400     unsigned int status;                
00401 
00402     CSR_WRITE_2(sc, WI_SEL0, id);
00403     CSR_WRITE_2(sc, WI_OFF0, off);
00404 
00405     for (i = 0;; i++) {
00406         status = CSR_READ_2(sc, WI_OFF0);
00407         if ((status & WI_OFF_BUSY) == 0) {
00408             break;
00409         }
00410         if (i == WI_TIMEOUT) {
00411             Debug(("timeout in wi_seek to %x/%x\n", id, off));
00412             sc->sc_bap_off = WI_OFF_ERR;        
00413             if (status == 0xffff) {
00414                 sc->wi_gone = 1;
00415             }
00416             return ETIMEDOUT;
00417         }
00418         DELAY(1);
00419     }
00420     if (status & WI_OFF_ERR) {
00421         Debug(("failed in wi_seek to %x/%x\n", id, off));
00422         sc->sc_bap_off = WI_OFF_ERR;    
00423         return EIO;
00424     }
00425     sc->sc_bap_id = id;
00426     sc->sc_bap_off = off;
00427     return 0;
00428 }
00429 
00430 
00431 
00432 
00433 static int wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
00434 {
00435     u_int16_t *ptr;
00436     int i, error, cnt;
00437 
00438     if (buflen == 0) {
00439         return 0;
00440     }
00441     if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
00442         if ((error = wi_seek_bap(sc, id, off)) != 0) {
00443             return error;
00444         }
00445     }
00446     cnt = (buflen + 1) / 2;
00447     ptr = (u_int16_t *) buf;
00448     for (i = 0; i < cnt; i++) {
00449         *ptr++ = CSR_READ_2(sc, WI_DATA0);
00450     }
00451     sc->sc_bap_off += cnt * 2;
00452     return 0;
00453 }
00454 
00455 
00456 
00457 
00458 static int wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
00459 {
00460     u_int16_t *ptr;
00461     int i, error, cnt;
00462 
00463     if (buflen == 0) {
00464         return 0;
00465     }
00466 #ifdef WI_HERMES_AUTOINC_WAR
00467   again:
00468 #endif
00469     if (id != sc->sc_bap_id || off != sc->sc_bap_off) {
00470         if ((error = wi_seek_bap(sc, id, off)) != 0) {
00471             return error;
00472         }
00473     }
00474     cnt = (buflen + 1) / 2;
00475     ptr = (u_int16_t *) buf;
00476     for (i = 0; i < cnt; i++) {
00477         CSR_WRITE_2(sc, WI_DATA0, ptr[i]);
00478     }
00479     sc->sc_bap_off += cnt * 2;
00480 
00481 #ifdef WI_HERMES_AUTOINC_WAR
00482     
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495     if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {
00496         CSR_WRITE_2(sc, WI_DATA0, 0x1234);
00497         CSR_WRITE_2(sc, WI_DATA0, 0x5678);
00498         wi_seek_bap(sc, id, sc->sc_bap_off);
00499         sc->sc_bap_off = WI_OFF_ERR;    
00500         if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || CSR_READ_2(sc, WI_DATA0) != 0x5678) {
00501             Debug(("detect auto increment bug, try again\n"));
00502             goto again;
00503         }
00504     }
00505 #endif
00506     return 0;
00507 }
00508 
00509 
00510 
00511 
00512 static int wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
00513 {
00514     int error, len;
00515     u_int16_t ltbuf[2];
00516 
00517     
00518 
00519 
00520     error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);
00521     if (error) {
00522         return error;
00523     }
00524 
00525     error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
00526     if (error) {
00527         return error;
00528     }
00529 
00530     if (le16toh(ltbuf[1]) != (u_int16_t) rid) {
00531         Debug(("record read mismatch, rid=%x, got=%x\n", rid, le16toh(ltbuf[1])));
00532         return EIO;
00533     }
00534     len = (le16toh(ltbuf[0]) - 1) * 2;  
00535     if (*buflenp < len) {
00536         Debug(("record buffer is too small, rid=%x, size=%d, len=%d\n", rid, *buflenp, len));
00537         return ENOSPC;
00538     }
00539     *buflenp = len;
00540     return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);
00541 }
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 static int wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
00551 {
00552     int error;
00553     u_int16_t ltbuf[2];
00554 
00555     ltbuf[0] = htole16((buflen + 1) / 2 + 1);   
00556     ltbuf[1] = htole16(rid);
00557 
00558     error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));
00559     if (error) {
00560         return error;
00561     }
00562     error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);
00563     if (error) {
00564         return error;
00565     }
00566 
00567     return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);
00568 }
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 
00577 
00578 static int wi_write_val(struct wi_softc *sc, int rid, u_int16_t val)
00579 {
00580     val = htole16(val);
00581     return wi_write_rid(sc, rid, &val, sizeof(val));
00582 }
00583 
00584 
00585 
00586 
00587 static int wi_write_txrate(struct wi_softc *sc)
00588 {
00589     struct ieee80211com *ic = &sc->sc_ic;
00590     int i;
00591     u_int16_t rate;
00592 
00593     if (ic->ic_fixed_rate < 0) {
00594         rate = 0;               
00595     } else {
00596         rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL) / 2;
00597     }
00598 
00599     
00600 
00601 
00602 
00603     switch (sc->sc_firmware_type) {
00604     case WI_LUCENT:
00605         switch (rate) {
00606         case 0:                
00607             rate = 3;
00608             break;
00609             
00610 
00611 
00612         case 5:                
00613             rate = 4;
00614             break;
00615         case 11:               
00616             rate = 5;
00617             break;
00618         default:
00619             break;
00620         }
00621         break;
00622     default:
00623         
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 
00633         for (i = 8; i > 0; i >>= 1) {
00634             if ((int) rate >= i) {
00635                 break;
00636             }
00637         }
00638         if (i == 0) {
00639             rate = 0xf;         
00640         } else {
00641             rate = i;
00642         }
00643         break;
00644     }
00645     return wi_write_val(sc, WI_RID_TX_RATE, rate);
00646 }
00647 
00648 
00649 
00650 
00651 static int wi_reset(struct wi_softc *sc)
00652 {
00653     
00654     int i;
00655     int error = 0;
00656     int tries;
00657 
00658     
00659 
00660 
00661     if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset) {
00662         return (0);
00663     }
00664     if (sc->sc_firmware_type == WI_SYMBOL) {
00665         tries = 1;
00666     } else {
00667         tries = 3;
00668     }
00669 
00670     for (i = 0; i < tries; i++) {
00671         if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0) {
00672             break;
00673         }
00674         DELAY(WI_DELAY * 1000);
00675     }
00676     sc->sc_reset = 1;
00677 
00678     if (i == tries) {
00679         Debug(("init failed\n"));
00680         return (error);
00681     }
00682 
00683     CSR_WRITE_2(sc, WI_INT_EN, 0);
00684     CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
00685 
00686     
00687 
00688 
00689     wi_write_val(sc, WI_RID_TICK_TIME, 8);
00690 
00691     return (0);
00692 }
00693 
00694 
00695 
00696 
00697 static void WLANInterrupt(void *p)
00698 {
00699     NUTDEVICE *dev = (NUTDEVICE *) p;
00700     struct wi_softc *sc = (struct wi_softc *) dev->dev_dcb;
00701 
00702     if ((sc->wi_gone == 1) || (sc->sc_enabled == 0)) {
00703         CSR_WRITE_2(sc, WI_INT_EN, 0);
00704         CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
00705         return;
00706     }
00707 
00708     
00709 
00710 
00711 
00712     CSR_WRITE_2(sc, WI_INT_EN, 0);
00713 
00714     sc->EventStatus = CSR_READ_2(sc, WI_EVENT_STAT);
00715 
00716     NutEventPostFromIrq(&sc->InterruptEvent);
00717 }
00718 
00719 
00720 
00721 
00722 static void wi_tx_intr(struct wi_softc *sc)
00723 {
00724     
00725     int fid, cur;
00726 
00727     if (sc->wi_gone) {
00728         return;
00729     }
00730 
00731     fid = CSR_READ_2(sc, WI_ALLOC_FID);
00732     CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
00733 
00734     cur = sc->sc_txcur;
00735     if (sc->sc_txd[cur].d_fid != fid) {
00736 #if (WLAN_ENABLE_TX_FRAME_DUMP >= 1)
00737         Debug(("bad alloc %x != %x, cur %d nxt %d\n", fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext));
00738 #endif
00739         return;
00740     }
00741     sc->sc_tx_timer = 0;
00742     sc->sc_txd[cur].d_len = 0;
00743     sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
00744     if (sc->sc_txd[cur].d_len == 0) {
00745         
00746     } else {
00747         if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid, 0, 0)) {
00748             Debug(("xmit failed\n"));
00749             sc->sc_txd[cur].d_len = 0;
00750         } else {
00751             sc->sc_tx_timer = 5;
00752             
00753         }
00754     }
00755 }
00756 
00757 
00758 
00759 
00760 static void wi_info_intr(struct wi_softc *sc)
00761 {
00762     struct ieee80211com *ic = &sc->sc_ic;
00763     
00764     
00765     int fid;
00766     u_int16_t ltbuf[2];
00767     u_int16_t stat;
00768     
00769 
00770     fid = CSR_READ_2(sc, WI_INFO_FID);
00771     wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));
00772 
00773     switch (le16toh(ltbuf[1])) {
00774 
00775     case WI_INFO_LINK_STAT:
00776         wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));
00777 #if (WLAN_ENABLE_LINK_STATUS >= 1)
00778         Debug(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));
00779 #endif                          
00780 
00781         switch (le16toh(stat)) {
00782         case WI_INFO_LINK_STAT_CONNECTED:
00783             sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
00784             if (ic->ic_state == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS) {
00785                 break;
00786             }
00787             
00788 
00789 
00790         case WI_INFO_LINK_STAT_AP_CHG:
00791             ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
00792             break;
00793         case WI_INFO_LINK_STAT_AP_INR:
00794             sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
00795             break;
00796         case WI_INFO_LINK_STAT_AP_OOR:
00797             if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_scan_timer > 0) {
00798                 if (wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS, 0, 0)
00799                     != 0) {
00800                     sc->sc_scan_timer = 0;
00801                 }
00802                 break;
00803             }
00804             if (ic->ic_opmode == IEEE80211_M_STA) {
00805                 sc->sc_flags |= WI_FLAGS_OUTRANGE;
00806             }
00807             break;
00808         case WI_INFO_LINK_STAT_DISCONNECTED:
00809         case WI_INFO_LINK_STAT_ASSOC_FAILED:
00810             if (ic->ic_opmode == IEEE80211_M_STA) {
00811                 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
00812             }
00813             break;
00814         }
00815         break;
00816 
00817     case WI_INFO_COUNTERS:
00818 #if 0                           //@@MF later
00819         
00820 
00821 
00822 
00823 
00824         
00825 
00826 
00827         len = min(le16toh(ltbuf[0]) - 1, sizeof(sc->sc_stats) / 4);
00828         ptr = (u_int32_t *) & sc->sc_stats;
00829         off = sizeof(ltbuf);
00830         for (i = 0; i < len; i++, off += 2, ptr++) {
00831             wi_read_bap(sc, fid, off, &stat, sizeof(stat));
00832 #ifdef WI_HERMES_STATS_WAR
00833             if (stat & 0xf000) {
00834                 stat = ~stat;
00835             }
00836 #endif
00837             *ptr += stat;
00838         }
00839         ifp->if_collisions = sc->sc_stats.wi_tx_single_retries + sc->sc_stats.wi_tx_multi_retries + sc->sc_stats.wi_tx_retry_limit;
00840 #endif                          
00841         break;
00842 
00843 #if 0                           //@@MF later
00844     case WI_INFO_SCAN_RESULTS:
00845     case WI_INFO_HOST_SCAN_RESULTS:
00846         wi_scan_result(sc, fid, le16toh(ltbuf[0]));
00847         break;
00848 #endif                          
00849 
00850     default:
00851         Debug(("wi_info_intr: got fid %x type %x len %d\n", fid, le16toh(ltbuf[1]), le16toh(ltbuf[0])));
00852         break;
00853     }
00854     CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
00855 }
00856 
00857 
00858 
00859 
00860 static NETBUF *wi_rx_intr(struct wi_softc *sc)
00861 {
00862     
00863     struct wi_frame frmhdr;
00864     int fid, len, off;
00865     u_int16_t status;
00866     int error;
00867 
00868     NETBUF *nb = 0;
00869     LLCS_SNAP_HEADER *pLLCSSNAPHeader;
00870     ETHERHDR LABBuffer;
00871     ETHERHDR MAC802_3;
00872     u_int8_t *pFrameBuffer = 0; 
00873     u_int8_t *pBytePointer;
00874     int copy_size = 0;          
00875     int size;
00876     int IPFrame = 0;
00877 
00878     if (sc->wi_gone) {
00879         Debug(("wi_rx_intr gone\r\n"));
00880         return (0);
00881     }
00882 
00883     fid = CSR_READ_2(sc, WI_RX_FID);
00884 
00885     
00886 
00887 
00888     if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
00889         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
00890         Debug(("wi_rx_intr: read fid %x failed\n", fid));
00891         return 0;
00892     }
00893 
00894     
00895 
00896 
00897     status = le16toh(frmhdr.wi_status);
00898     if (status & WI_STAT_ERRSTAT) {
00899         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
00900         Debug(("wi_rx_intr: fid %x error status %x\n", fid, status));
00901         return 0;
00902     }
00903 
00904     
00905 
00906 
00907     memcpy(MAC802_3.ether_dhost, frmhdr.wi_ehdr.ether_dhost, IEEE80211_ADDR_LEN);
00908     memcpy(MAC802_3.ether_shost, frmhdr.wi_ehdr.ether_shost, IEEE80211_ADDR_LEN);
00909     
00910 
00911 
00912 
00913     
00914 
00915 
00916 
00917 
00918     len = le16toh(frmhdr.wi_dat_len);
00919     off = sizeof(frmhdr);
00920 
00921     
00922 
00923 
00924 
00925     if (len > WLAN_MAX_ETHERNET_FRAME_LEN) {
00926         CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
00927         Debug(("wi_rx_intr: oversized packet\n"));
00928         return (0);
00929     }
00930 
00931     
00932 
00933 
00934     error = wi_read_bap(sc, fid, off, &LABBuffer, sizeof(LABBuffer));
00935     off += sizeof(LABBuffer);
00936 
00937     if (error == 0) {
00938         
00939 
00940 
00941         pLLCSSNAPHeader = (LLCS_SNAP_HEADER *) & LABBuffer;
00942         if ((pLLCSSNAPHeader->DSAPSSAP == 0xAAAA) && (pLLCSSNAPHeader->Control == 0x0003) && (pLLCSSNAPHeader->MustZero == 0x0000)) {
00943 
00944             if ((pLLCSSNAPHeader->Type == 0x0608) || (pLLCSSNAPHeader->Type == 0x0008)) {
00945 
00946 #if (WLAN_ENABLE_RX_FRAME_DUMP >= 1)
00947                 Debug(("RFC1024 IP-Frame\n"));
00948 #endif
00949 
00950                 IPFrame = 1;
00951                 MAC802_3.ether_type = pLLCSSNAPHeader->Type;
00952 
00953                 
00954 
00955 
00956 
00957 
00958 
00959                 len -= 6;
00960 
00961                 
00962 
00963 
00964 
00965                 len += 12;
00966 
00967                 
00968 
00969 
00970 
00971                 len += 1;
00972                 len &= ~1;
00973 
00974                 
00975 
00976 
00977                 nb = NutNetBufAlloc(0, NBAF_DATALINK, len);
00978                 if (nb != 0) {
00979                     pFrameBuffer = nb->nb_dl.vp;
00980 
00981                     
00982 
00983 
00984                     copy_size = len;
00985 
00986                     
00987 
00988 
00989                     memcpy(pFrameBuffer, &MAC802_3, sizeof(MAC802_3));
00990                     pFrameBuffer += sizeof(MAC802_3);
00991                     copy_size -= sizeof(MAC802_3);      
00992 
00993                     
00994 
00995 
00996                     pBytePointer = (BYTE *) & LABBuffer;
00997                     
00998 
00999 
01000                     pBytePointer += sizeof(LLCS_SNAP_HEADER);
01001                     
01002 
01003 
01004                     size = sizeof(LABBuffer) - sizeof(LLCS_SNAP_HEADER);
01005                     memcpy(pFrameBuffer, pBytePointer, size);
01006                     
01007 
01008 
01009                     pFrameBuffer += size;
01010                     copy_size -= size;  
01011                 } else {
01012                     IPFrame = 0;
01013                 }
01014             }                   
01015         } else {
01016             
01017 
01018 
01019             if ((LABBuffer.ether_type == 0x0608) || (LABBuffer.ether_type == 0x0008)) {
01020 
01021 #if (WLAN_ENABLE_RX_FRAME_DUMP >= 1)
01022                 Debug(("RFC894 IP-Frame\n"));
01023 #endif
01024 
01025                 IPFrame = 1;
01026 
01027                 
01028 
01029 
01030 
01031                 len += 1;
01032                 len &= ~1;
01033 
01034                 
01035 
01036 
01037 
01038                 nb = NutNetBufAlloc(0, NBAF_DATALINK, len);
01039                 if (nb != 0) {
01040                     pFrameBuffer = nb->nb_dl.vp;
01041 
01042                     
01043 
01044 
01045                     copy_size = len;
01046 
01047                     
01048 
01049 
01050                     memcpy(pFrameBuffer, &LABBuffer, sizeof(LABBuffer));
01051                     pFrameBuffer += sizeof(LABBuffer);
01052                     copy_size -= sizeof(LABBuffer);     
01053                 } else {
01054                     IPFrame = 0;
01055                 }               
01056             }                   
01057         }                       
01058 
01059         
01060 
01061 
01062         if (IPFrame == 1) {
01063             error = wi_read_bap(sc, fid, off, pFrameBuffer, copy_size);
01064             if (error != 0) {
01065                 NutNetBufFree(nb);
01066                 nb = NULL;
01067             } else {
01068 #if (WLAN_ENABLE_RX_FRAME_DUMP >= 1)
01069                 Debug(("RxFrame: %d\n", len));
01070                 DumpWlanData(nb->nb_dl.vp, nb->nb_dl.sz);
01071 #endif
01072             }
01073         }
01074     }
01075 
01076     
01077 
01078 
01079     CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
01080 
01081     return (nb);
01082 }
01083 
01084 
01085 
01086 
01087 THREAD(RxThread, arg)
01088 {
01089     NUTDEVICE *dev;
01090     IFNET *ifn;
01091     NETBUF *nb;
01092     struct wi_softc *sc;
01093     u_int16_t EventStatus;
01094 
01095     dev = arg;
01096     ifn = (IFNET *) dev->dev_icb;
01097     sc = (struct wi_softc *) dev->dev_dcb;
01098 
01099     for (;;) {
01100         
01101 
01102 
01103 
01104         NutEventWait(&sc->InterruptEvent, 2000);
01105         EventStatus = sc->EventStatus;
01106 
01107         
01108 
01109 
01110 
01111 
01112         sc->EventStatus = 0;
01113 
01114         if (EventStatus != 0) {
01115             if (EventStatus & WI_EV_RX) {
01116                 WI_LOCK(sc);
01117                 nb = wi_rx_intr(sc);
01118                 WI_UNLOCK(sc);
01119 
01120                 if (nb != 0) {
01121                     (*ifn->if_recv) (dev, nb);
01122                 }
01123             }
01124 
01125             if (EventStatus & WI_EV_ALLOC) {
01126                 WI_LOCK(sc);
01127                 wi_tx_intr(sc);
01128                 WI_UNLOCK(sc);
01129             }
01130 
01131             if (EventStatus & WI_EV_INFO) {
01132                 WI_LOCK(sc);
01133                 wi_info_intr(sc);
01134                 WI_UNLOCK(sc);
01135             }
01136 
01137             if (EventStatus & WI_EV_TX_EXC) {
01138                 Debug(("WI_EV_TX_EXC\n"));
01139             }
01140 
01141 
01142             CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
01143         } else {
01144             
01145 
01146 
01147             if ((sc->sc_enabled == 1) && (sc->wi_gone == 1)) {
01148                 
01149 
01150 
01151                 Debug(("Houston, we have a problem...\n"));
01152                 sc->wi_gone = 0;
01153                 wlandrv_Init(dev);
01154             }
01155         }                       
01156     }                           
01157 }
01158 
01159 
01160 
01161 
01162 static int wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
01163 {
01164     unsigned long i;                     
01165                                                                          
01166 
01167     if (wi_cmd(sc, WI_CMD_ALLOC_MEM, len, 0, 0)) {
01168         Debug(("failed to allocate %d bytes on NIC\n", len));
01169         return ENOMEM;
01170     }
01171 
01172     for (i = 0; i < WI_TIMEOUT; i++) {
01173         if (CSR_READ_2(sc, WI_EVENT_STAT) & WI_EV_ALLOC) {
01174             break;
01175         }
01176         if (i == WI_TIMEOUT) {
01177             Debug(("timeout in alloc\n"));
01178             return ETIMEDOUT;
01179         }
01180         DELAY(1);
01181     }
01182     *idp = CSR_READ_2(sc, WI_ALLOC_FID);
01183     CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);
01184     return 0;
01185 }
01186 
01187 
01188 
01189 
01190 static int wi_write_ssid(struct wi_softc *sc, int rid, u_int8_t * buf, int buflen)
01191 {
01192     struct wi_ssid ssid;
01193 
01194     if (buflen > IEEE80211_NWID_LEN) {
01195         return ENOBUFS;
01196     }
01197     memset(&ssid, 0, sizeof(ssid));
01198     ssid.wi_len = htole16(buflen);
01199     memcpy(ssid.wi_ssid, buf, buflen);
01200     return wi_write_rid(sc, rid, &ssid, sizeof(ssid));
01201 }
01202 
01203 
01204 
01205 
01206 static void wi_read_nicid(struct wi_softc *sc)
01207 {
01208     struct wi_card_ident *id;
01209     char *p;
01210     int len;
01211     u_int16_t ver[4];
01212 
01213     
01214 
01215 
01216     memset(ver, 0, sizeof(ver));
01217     len = sizeof(ver);
01218     wi_read_rid(sc, WI_RID_CARD_ID, ver, &len);
01219     Debug(("using "));
01220 
01221     sc->sc_firmware_type = WI_NOTYPE;
01222     for (id = wi_card_ident; id->card_name != NULL; id++) {
01223         if (le16toh(ver[0]) == id->card_id) {
01224             Debug(("%s", id->card_name));
01225             sc->sc_firmware_type = id->firm_type;
01226             break;
01227         }
01228     }
01229     if (sc->sc_firmware_type == WI_NOTYPE) {
01230         if (le16toh(ver[0]) & 0x8000) {
01231             Debug(("Unknown PRISM2 chip"));
01232             sc->sc_firmware_type = WI_INTERSIL;
01233         } else {
01234             Debug(("Unknown Lucent chip"));
01235             sc->sc_firmware_type = WI_LUCENT;
01236         }
01237     }
01238 
01239     
01240 
01241 
01242     if (sc->sc_firmware_type != WI_LUCENT) {
01243         memset(ver, 0, sizeof(ver));
01244         len = sizeof(ver);
01245         wi_read_rid(sc, WI_RID_PRI_IDENTITY, ver, &len);
01246         sc->sc_pri_firmware_ver = le16toh(ver[2]) * 10000 + le16toh(ver[3]) * 100 + le16toh(ver[1]);
01247     }
01248 
01249     
01250 
01251 
01252     memset(ver, 0, sizeof(ver));
01253     len = sizeof(ver);
01254     wi_read_rid(sc, WI_RID_STA_IDENTITY, ver, &len);
01255     sc->sc_sta_firmware_ver = le16toh(ver[2]) * 10000 + le16toh(ver[3]) * 100 + le16toh(ver[1]);
01256     if (sc->sc_firmware_type == WI_INTERSIL && (sc->sc_sta_firmware_ver == 10102 || sc->sc_sta_firmware_ver == 20102)) {
01257         char ident[12];
01258         memset(ident, 0, sizeof(ident));
01259         len = sizeof(ident);
01260         
01261 
01262 
01263         if (wi_read_rid(sc, WI_RID_SYMBOL_IDENTITY, ident, &len) == 0 &&
01264             *(p = (char *) ident) >= 'A' && p[2] == '.' && p[5] == '-' && p[8] == '\0') {
01265             sc->sc_firmware_type = WI_SYMBOL;
01266             sc->sc_sta_firmware_ver = (p[1] - '0') * 10000 +
01267                 (p[3] - '0') * 1000 + (p[4] - '0') * 100 + (p[6] - '0') * 10 + (p[7] - '0');
01268         }
01269     }
01270     Debug(("\n"));
01271     Debug(("%s Firmware: ",
01272            sc->sc_firmware_type == WI_LUCENT ? "Lucent" : (sc->sc_firmware_type == WI_SYMBOL ? "Symbol" : "Intersil")));
01273     if (sc->sc_firmware_type != WI_LUCENT) {    
01274         Debug(("Primary (%ld.%ld.%ld), ",
01275                sc->sc_pri_firmware_ver / 10000, (sc->sc_pri_firmware_ver % 10000) / 100, sc->sc_pri_firmware_ver % 100));
01276     }
01277     Debug(("Station (%ld.%ld.%ld)\n",
01278            sc->sc_sta_firmware_ver / 10000, (sc->sc_sta_firmware_ver % 10000) / 100, sc->sc_sta_firmware_ver % 100));
01279 }
01280 
01281 
01282 
01283 
01284 static int wi_write_wep(struct wi_softc *sc)
01285 {
01286     struct ieee80211com *ic = &sc->sc_ic;
01287     int error = 0;
01288     int i, keylen;
01289     u_int16_t val;
01290     struct wi_key wkey[IEEE80211_WEP_NKID];
01291 
01292     switch (sc->sc_firmware_type) {
01293 #if (WLAN_SUPPORT_LUCENT >= 1)
01294     case WI_LUCENT:
01295         val = (ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0;
01296         error = wi_write_val(sc, WI_RID_ENCRYPTION, val);
01297         if (error)
01298             break;
01299         error = wi_write_val(sc, WI_RID_TX_CRYPT_KEY, ic->ic_wep_txkey);
01300         if (error)
01301             break;
01302         memset(wkey, 0, sizeof(wkey));
01303         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
01304             keylen = ic->ic_nw_keys[i].wk_len;
01305             wkey[i].wi_keylen = htole16(keylen);
01306             memcpy(wkey[i].wi_keydat, ic->ic_nw_keys[i].wk_key, keylen);
01307         }
01308         error = wi_write_rid(sc, WI_RID_DEFLT_CRYPT_KEYS, wkey, sizeof(wkey));
01309         break;
01310 #endif                          
01311 
01312 #if ((WLAN_SUPPORT_INTERSIL >= 1) || (WLAN_SUPPORT_SYMBOL >= 1))
01313     case WI_INTERSIL:
01314     case WI_SYMBOL:
01315         if (ic->ic_flags & IEEE80211_F_WEPON) {
01316             
01317 
01318 
01319 
01320 
01321 
01322 
01323 
01324 
01325             if (sc->sc_firmware_type == WI_INTERSIL && sc->sc_sta_firmware_ver < 802) {
01326                 
01327 
01328 
01329                 wi_write_val(sc, WI_RID_PROMISC, 1);
01330             }
01331             wi_write_val(sc, WI_RID_CNFAUTHMODE, sc->sc_cnfauthmode);
01332             val = PRIVACY_INVOKED | EXCLUDE_UNENCRYPTED;
01333             
01334 
01335 
01336             if (sc->sc_firmware_type == WI_INTERSIL && ic->ic_opmode == IEEE80211_M_HOSTAP) {
01337                 val |= HOST_ENCRYPT;
01338             }
01339         } else {
01340             wi_write_val(sc, WI_RID_CNFAUTHMODE, IEEE80211_AUTH_OPEN);
01341             val = HOST_ENCRYPT | HOST_DECRYPT;
01342         }
01343         error = wi_write_val(sc, WI_RID_P2_ENCRYPTION, val);
01344         if (error) {
01345             break;
01346         }
01347         error = wi_write_val(sc, WI_RID_P2_TX_CRYPT_KEY, ic->ic_wep_txkey);
01348         if (error) {
01349             break;
01350         }
01351         
01352 
01353 
01354 
01355 
01356 
01357         keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
01358         if (keylen > IEEE80211_WEP_KEYLEN) {
01359             keylen = 13;        
01360         } else {
01361             keylen = IEEE80211_WEP_KEYLEN;
01362         }
01363         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
01364             error = wi_write_rid(sc, WI_RID_P2_CRYPT_KEY0 + i, ic->ic_nw_keys[i].wk_key, keylen);
01365             if (error) {
01366                 break;
01367             }
01368         }
01369         break;
01370 #endif                          
01371     }
01372     return error;
01373 }
01374 
01375 
01376 
01377 
01378 
01379 
01380 
01381 
01382 
01383 
01384 
01385 int wlandrv_ProbeDevice(void)
01386 {
01387     int error = -1;
01388     u_int16_t Value;
01389 
01390     
01391 
01392 
01393     RESET_EN_PORT |= RESET_BIT;
01394     RESET_PORT |= RESET_BIT;
01395 
01396     NutSleep(100);
01397 
01398     
01399 
01400 
01401     RESET_PORT &= ~RESET_BIT;
01402 
01403     NutSleep(500);
01404 
01405     
01406 
01407 
01408     pcmcia_WriteMem(WI_COR_OFFSET, WI_COR_VALUE);
01409     NutSleep(100);
01410 
01411     
01412 
01413 
01414     pcmcia_WriteReg(WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC);
01415     Value = pcmcia_ReadReg(WI_HFA384X_SWSUPPORT0_OFF);
01416     if (Value == WI_PRISM2STA_MAGIC) {
01417         
01418 
01419 
01420         error = 0;
01421     }
01422 
01423     return (error);
01424 }
01425 
01426 
01427 
01428 
01429 
01430 
01431 
01432 
01433 
01434 int wlandrv_Attach(device_t dev)
01435 {
01436     struct wi_softc *sc = device_get_softc(dev);
01437     struct ieee80211com *ic = &sc->sc_ic;
01438     struct ieee80211_rateset *rs;
01439     int i, nrates, buflen;
01440     u_int16_t val;
01441     u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
01442     
01443     
01444     
01445     int error;
01446 
01447     bDebugState = 2;
01448 
01449     sc->wi_cmd_count = 500;
01450     ic->ic_fixed_rate = -1;     
01451 
01452 
01453     
01454 
01455 
01456     if (wi_reset(sc) != 0) {
01457         return ENXIO;           
01458     }
01459 
01460     
01461 
01462 
01463 
01464 
01465 
01466     buflen = IEEE80211_ADDR_LEN;
01467     error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
01468     if (error != 0) {
01469         buflen = IEEE80211_ADDR_LEN;
01470         error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
01471     }
01472     if (error != 0) {
01473         Debug(("mac read failed %d\n", error));
01474         return (error);
01475     }
01476     Debug(("802.11 address: %02X-%02X-%02X-%02X-%02X-%02X\n",
01477            ic->ic_myaddr[0], ic->ic_myaddr[1], ic->ic_myaddr[2], ic->ic_myaddr[3], ic->ic_myaddr[4], ic->ic_myaddr[5]));
01478 
01479     
01480 
01481 
01482     wi_read_nicid(sc);
01483 
01484     ic->ic_opmode = IEEE80211_M_STA;
01485     ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_AHDEMO;
01486     ic->ic_state = IEEE80211_S_INIT;
01487 
01488     
01489 
01490 
01491     buflen = sizeof(val);
01492     if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) {
01493         val = htole16(0x1fff);  
01494     }
01495     if (val == 0) {
01496         Debug(("wi_attach: no available channels listed!"));
01497     }
01498     ic->ChannelList = (val << 1);
01499 
01500     
01501 
01502 
01503 
01504 
01505 
01506 
01507 
01508     buflen = sizeof(val);
01509     if (wi_read_rid(sc, WI_RID_OWN_CHNL, &val, &buflen) == 0) {
01510         val = le16toh(val);
01511         i = (1 << val);
01512 
01513         if ((val > 16) || ((ic->ChannelList & i) == 0)) {
01514             Debug(("wi_attach: invalid own channel %d!", val));
01515         }
01516         ic->ic_ibss_chan = val;
01517     } else {
01518         Debug(("WI_RID_OWN_CHNL failed, using first channel!\n"));
01519         ic->ic_ibss_chan = 1;
01520     }
01521 
01522     
01523 
01524 
01525     switch (sc->sc_firmware_type) {
01526 #if (WLAN_SUPPORT_LUCENT >= 1)
01527     case WI_LUCENT:
01528         sc->sc_ntxbuf = 1;
01529         sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
01530 
01531 #ifdef WI_HERMES_AUTOINC_WAR
01532         
01533 
01534 
01535         if (sc->sc_sta_firmware_ver < 40000) {
01536             sc->sc_flags |= WI_FLAGS_BUG_AUTOINC;
01537         }
01538 #endif
01539         if (sc->sc_sta_firmware_ver >= 60000) {
01540             sc->sc_flags |= WI_FLAGS_HAS_MOR;
01541         }
01542         if (sc->sc_sta_firmware_ver >= 60006) {
01543             ic->ic_caps |= IEEE80211_C_IBSS;
01544             ic->ic_caps |= IEEE80211_C_MONITOR;
01545         }
01546         sc->sc_ibss_port = htole16(1);
01547 
01548         sc->sc_min_rssi = WI_LUCENT_MIN_RSSI;
01549         sc->sc_max_rssi = WI_LUCENT_MAX_RSSI;
01550         sc->sc_dbm_offset = WI_LUCENT_DBM_OFFSET;
01551         break;
01552 #endif                          
01553 
01554 #if (WLAN_SUPPORT_INTERSIL >= 1)
01555     case WI_INTERSIL:
01556         sc->sc_ntxbuf = WI_NTXBUF;
01557         sc->sc_flags |= WI_FLAGS_HAS_FRAGTHR;
01558         sc->sc_flags |= WI_FLAGS_HAS_ROAMING;
01559         sc->sc_flags |= WI_FLAGS_HAS_SYSSCALE;
01560         
01561 
01562 
01563         if (sc->sc_sta_firmware_ver < 10000) {
01564             sc->wi_cmd_count = 5000;
01565         }
01566         if (sc->sc_sta_firmware_ver > 10101) {
01567             sc->sc_flags |= WI_FLAGS_HAS_DBMADJUST;
01568         }
01569         if (sc->sc_sta_firmware_ver >= 800) {
01570             ic->ic_caps |= IEEE80211_C_IBSS;
01571             ic->ic_caps |= IEEE80211_C_MONITOR;
01572         }
01573         
01574 
01575 
01576 
01577 
01578         if (sc->sc_sta_firmware_ver >= 803) {
01579             ic->ic_caps |= IEEE80211_C_HOSTAP;
01580         }
01581         sc->sc_ibss_port = htole16(0);
01582 
01583         sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
01584         sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
01585         sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
01586         break;
01587 #endif                          
01588 
01589 #if (WLAN_SUPPORT_SYMBOL >= 1)
01590     case WI_SYMBOL:
01591         sc->sc_ntxbuf = 1;
01592         sc->sc_flags |= WI_FLAGS_HAS_DIVERSITY;
01593         if (sc->sc_sta_firmware_ver >= 25000) {
01594             ic->ic_caps |= IEEE80211_C_IBSS;
01595         }
01596         sc->sc_ibss_port = htole16(4);
01597 
01598         sc->sc_min_rssi = WI_PRISM_MIN_RSSI;
01599         sc->sc_max_rssi = WI_PRISM_MAX_RSSI;
01600         sc->sc_dbm_offset = WI_PRISM_DBM_OFFSET;
01601         break;
01602 #endif                          
01603     }
01604 
01605     
01606 
01607 
01608     buflen = sizeof(val);
01609     if (wi_read_rid(sc, WI_RID_WEP_AVAIL, &val, &buflen) == 0 && val != htole16(0)) {
01610         ic->ic_caps |= IEEE80211_C_WEP;
01611     }
01612 
01613     
01614 
01615 
01616     buflen = sizeof(ratebuf);
01617     rs = &ic->ic_sup_rates[IEEE80211_MODE_11B];
01618     if (wi_read_rid(sc, WI_RID_DATA_RATES, ratebuf, &buflen) == 0) {
01619         nrates = le16toh(*(u_int16_t *) ratebuf);
01620         if (nrates > IEEE80211_RATE_MAXSIZE) {
01621             nrates = IEEE80211_RATE_MAXSIZE;
01622         }
01623         rs->rs_nrates = 0;
01624         for (i = 0; i < nrates; i++) {
01625             if (ratebuf[2 + i]) {
01626                 rs->rs_rates[rs->rs_nrates++] = ratebuf[2 + i];
01627             }
01628         }
01629     } else {
01630         
01631 
01632 
01633         rs->rs_nrates = 0;
01634     }
01635 
01636     buflen = sizeof(val);
01637     if ((sc->sc_flags & WI_FLAGS_HAS_DBMADJUST) && wi_read_rid(sc, WI_RID_DBM_ADJUST, &val, &buflen) == 0) {
01638         sc->sc_dbm_offset = le16toh(val);
01639     }
01640 
01641     sc->sc_max_datalen = 2304;
01642     sc->sc_system_scale = 1;
01643     sc->sc_cnfauthmode = IEEE80211_AUTH_OPEN;
01644     sc->sc_roaming_mode = WI_DEFAULT_ROAMING;
01645 
01646     sc->sc_portnum = WI_DEFAULT_PORT;
01647     sc->sc_authtype = WI_DEFAULT_AUTHTYPE;
01648 
01649     
01650 
01651 
01652     NutEventPost(&hDeviceSemaphore);
01653 
01654     return (0);
01655 }
01656 
01657 
01658 
01659 
01660 void wlandrv_Init(device_t dev)
01661 {
01662     struct wi_softc *sc = device_get_softc(dev);
01663     struct ieee80211com *ic = &sc->sc_ic;
01664     int i;
01665     int error = 0, wasenabled;
01666 
01667     WI_LOCK(sc);
01668 
01669     if (sc->wi_gone) {
01670         WI_UNLOCK(sc);
01671         return;
01672     }
01673 
01674     if ((wasenabled = sc->sc_enabled)) {
01675         wi_stop(sc, 1);
01676     }
01677     wi_reset(sc);
01678 
01679     
01680 
01681 
01682     ic->ic_flags &= ~IEEE80211_F_IBSSON;
01683     sc->sc_flags &= ~WI_FLAGS_OUTRANGE;
01684     switch (ic->ic_opmode) {
01685     case IEEE80211_M_STA:
01686         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_BSS);
01687         break;
01688     case IEEE80211_M_IBSS:
01689         wi_write_val(sc, WI_RID_PORTTYPE, sc->sc_ibss_port);
01690         ic->ic_flags |= IEEE80211_F_IBSSON;
01691         break;
01692     case IEEE80211_M_AHDEMO:
01693         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
01694         break;
01695     case IEEE80211_M_HOSTAP:
01696         
01697 
01698 
01699 
01700         if (sc->sc_firmware_type == WI_INTERSIL && ic->ic_des_esslen == 0) {
01701             ic->ic_des_essid[0] = ' ';
01702             ic->ic_des_esslen = 1;
01703         }
01704         wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_HOSTAP);
01705         break;
01706     case IEEE80211_M_MONITOR:
01707         
01708 #if 0                           // @@MF this mode is not working with my card
01709         if (sc->sc_firmware_type == WI_LUCENT) {
01710             wi_write_val(sc, WI_RID_PORTTYPE, WI_PORTTYPE_ADHOC);
01711         }
01712         error = wi_cmd(sc, WI_CMD_DEBUG | (WI_TEST_MONITOR << 8), 0, 0, 0);
01713 #endif
01714         break;
01715     }
01716 
01717     
01718 
01719 
01720     if (sc->sc_firmware_type == WI_LUCENT && (ic->ic_flags & IEEE80211_F_IBSSON) && ic->ic_des_esslen > 0) {
01721         wi_write_val(sc, WI_RID_CREATE_IBSS, 1);
01722     } else {
01723         wi_write_val(sc, WI_RID_CREATE_IBSS, 0);
01724     }
01725 
01726 #if 0                           //@@MF later
01727     wi_write_val(sc, WI_RID_MAX_SLEEP, ic->ic_lintval);
01728 #endif                          
01729 
01730     wi_write_ssid(sc, WI_RID_DESIRED_SSID, ic->ic_des_essid, ic->ic_des_esslen);
01731     wi_write_val(sc, WI_RID_OWN_CHNL, ic->ic_ibss_chan);
01732     wi_write_ssid(sc, WI_RID_OWN_SSID, ic->ic_des_essid, ic->ic_des_esslen);
01733 
01734     wi_write_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, IEEE80211_ADDR_LEN);
01735 
01736     wi_write_val(sc, WI_RID_PM_ENABLED, (ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0);
01737 
01738     
01739 
01740 
01741     wi_write_val(sc, WI_RID_MAX_DATALEN, sc->sc_max_datalen);
01742 
01743 #if 0                           //@@MF later
01744     wi_write_val(sc, WI_RID_RTS_THRESH, ic->ic_rtsthreshold);
01745     if (sc->sc_flags & WI_FLAGS_HAS_FRAGTHR) {
01746         wi_write_val(sc, WI_RID_FRAG_THRESH, ic->ic_fragthreshold);
01747     }
01748 #endif                          
01749 
01750     
01751 
01752 
01753     if (sc->sc_flags & WI_FLAGS_HAS_SYSSCALE) {
01754         wi_write_val(sc, WI_RID_SYSTEM_SCALE, sc->sc_system_scale);
01755     }
01756     if (sc->sc_flags & WI_FLAGS_HAS_ROAMING) {
01757         wi_write_val(sc, WI_RID_ROAMING_MODE, sc->sc_roaming_mode);
01758     }
01759     if (sc->sc_flags & WI_FLAGS_HAS_MOR) {
01760         wi_write_val(sc, WI_RID_MICROWAVE_OVEN, sc->sc_microwave_oven);
01761     }
01762     wi_write_txrate(sc);
01763 
01764 #if 0                           //@@MF later
01765     
01766 
01767 
01768     wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
01769 #endif                          
01770 
01771 #if 0                           //@@MF later
01772     
01773 
01774 
01775     if (ic->ic_opmode == IEEE80211_M_HOSTAP && sc->sc_firmware_type == WI_INTERSIL) {
01776         wi_write_val(sc, WI_RID_OWN_BEACON_INT, ic->ic_lintval);
01777         wi_write_val(sc, WI_RID_BASIC_RATE, 0x03);      
01778         wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f);    
01779         wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
01780     }
01781 #endif                          
01782 
01783     
01784 
01785 
01786 
01787 
01788 
01789 
01790 
01791     if ((ic->ic_opmode != IEEE80211_M_HOSTAP) && (sc->PromiscuousMode != 0)) {
01792         wi_write_val(sc, WI_RID_PROMISC, 1);
01793     } else {
01794         wi_write_val(sc, WI_RID_PROMISC, 0);
01795     }
01796 
01797     
01798 
01799 
01800     if (ic->ic_caps & IEEE80211_C_WEP) {
01801         wi_write_wep(sc);
01802     }
01803 #if 0                           //@@MF later
01804     
01805 
01806 
01807     wi_write_multi(sc);
01808 #endif                          
01809 
01810     
01811 
01812 
01813     if (sc->sc_firmware_type != WI_SYMBOL || !wasenabled) {
01814         sc->sc_buflen = IEEE80211_MAX_LEN + sizeof(struct wi_frame);
01815         if (sc->sc_firmware_type == WI_SYMBOL) {
01816             sc->sc_buflen = 1585;       
01817         }
01818         for (i = 0; i < sc->sc_ntxbuf; i++) {
01819             error = wi_alloc_fid(sc, sc->sc_buflen, &sc->sc_txd[i].d_fid);
01820             if (error) {
01821                 Debug(("tx buffer allocation failed (error %u)\n", error));
01822                 goto out;
01823             }
01824             sc->sc_txd[i].d_len = 0;
01825         }
01826     }
01827     sc->sc_txcur = sc->sc_txnext = 0;
01828 
01829     
01830 
01831 
01832     wi_cmd(sc, WI_CMD_ENABLE | sc->sc_portnum, 0, 0, 0);
01833 
01834     sc->sc_enabled = 1;
01835     if (ic->ic_opmode == IEEE80211_M_AHDEMO || ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_opmode == IEEE80211_M_HOSTAP) {
01836         ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
01837     }
01838 
01839   
01840     
01841   
01842     if (sc->InterruptInitDone == 0) {
01843         sc->InterruptInitDone = 1;
01844         
01845 
01846 
01847         PORTE |= 0x80;          
01848         error = NutRegisterIrqHandler(&sig_INTERRUPT7, WLANInterrupt, dev);
01849         if (error == FALSE) {
01850             EICR |= 0x80;       
01851             sbi(EIMSK, INT7);
01852 
01853             
01854 
01855 
01856             NutThreadCreate("rxi7", RxThread, dev, 640);
01857         }
01858     }
01859   
01860 
01861 
01862     
01863 
01864 
01865     CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
01866 
01867     if (!wasenabled && ic->ic_opmode == IEEE80211_M_HOSTAP && sc->sc_firmware_type == WI_INTERSIL) {
01868         
01869 
01870 
01871         wi_cmd(sc, WI_CMD_DISABLE | WI_PORT0, 0, 0, 0);
01872         wi_cmd(sc, WI_CMD_ENABLE | WI_PORT0, 0, 0, 0);
01873     }
01874 #if 0                           //@@MF later
01875     
01876 
01877 
01878     if (ic->ic_opmode == IEEE80211_M_STA && ((ic->ic_flags & IEEE80211_F_DESBSSID) || ic->ic_des_chan != IEEE80211_CHAN_ANYC)) {
01879         memset(&join, 0, sizeof(join));
01880         if (ic->ic_flags & IEEE80211_F_DESBSSID)
01881             IEEE80211_ADDR_COPY(&join.wi_bssid, ic->ic_des_bssid);
01882         if (ic->ic_des_chan != IEEE80211_CHAN_ANYC)
01883             join.wi_chan = htole16(ieee80211_chan2ieee(ic, ic->ic_des_chan));
01884         
01885 
01886 
01887         if (sc->sc_firmware_type != WI_LUCENT)
01888             wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
01889     }
01890 #endif                          
01891 
01892     WI_UNLOCK(sc);
01893     return;
01894   out:
01895     if (error) {
01896         Debug(("interface not running\n"));
01897         wi_stop(sc, 1);
01898     }
01899     WI_UNLOCK(sc);
01900     Debug(("wi_init: return %d\n", error));
01901     return;
01902 }
01903 
01904 
01905 
01906 
01907 int wlandrv_PutPacket(NUTDEVICE * dev, NETBUF * nb)
01908 {
01909     int error = -1;
01910     struct wi_softc *sc = (struct wi_softc *) dev->dev_dcb;
01911     struct wi_frame frmhdr;
01912     LLCS_SNAP_HEADER LLCSSNAPHeader;
01913     ETHERHDR *pMAC8023Header;
01914     int cur, fid, off, len;
01915 
01916     if (sc->wi_gone) {
01917         Debug(("wlandrv_PutPacket gone\r\n"));
01918         return (-1);
01919     }
01920 
01921     
01922 
01923 
01924 
01925     len = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;
01926     if (len > 1518) {
01927         return (-1);
01928     } else {
01929         WI_LOCK(sc);
01930 
01931         
01932 
01933 
01934 #if (WLAN_ENABLE_TX_FRAME_DUMP >= 1)
01935         Debug(("TxFrame: %d\n", len));
01936         DumpWlanData(nb->nb_dl.vp, len);
01937 #endif
01938 
01939         
01940 
01941 
01942 
01943         len = len - sizeof(ETHERHDR);
01944 
01945         
01946 
01947 
01948         len += sizeof(LLCS_SNAP_HEADER);
01949 
01950         
01951 
01952 
01953 
01954         memset(&frmhdr, 0, sizeof(frmhdr));
01955 
01956         
01957 
01958 
01959         pMAC8023Header = (ETHERHDR *) nb->nb_dl.vp;
01960         frmhdr.wi_dat_len = len;
01961         memcpy(frmhdr.wi_ehdr.ether_dhost, pMAC8023Header->ether_dhost, IEEE80211_ADDR_LEN);
01962         memcpy(frmhdr.wi_ehdr.ether_shost, pMAC8023Header->ether_shost, IEEE80211_ADDR_LEN);
01963         frmhdr.wi_ehdr.ether_type = SWAP(len);
01964 
01965         
01966 
01967 
01968         LLCSSNAPHeader.DSAPSSAP = 0xAAAA;
01969         LLCSSNAPHeader.Control = 0x0003;
01970         LLCSSNAPHeader.MustZero = 0x0000;
01971         LLCSSNAPHeader.Type = pMAC8023Header->ether_type;
01972 
01973         
01974 
01975 
01976         cur = sc->sc_txcur;
01977         fid = sc->sc_txd[cur].d_fid;
01978 
01979         
01980 
01981 
01982         error = wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr));
01983         if (error == 0) {
01984             off = sizeof(frmhdr);
01985 
01986             
01987 
01988 
01989             error = wi_write_bap(sc, fid, off, &LLCSSNAPHeader, sizeof(LLCSSNAPHeader));
01990             if (error == 0) {
01991                 off += sizeof(LLCSSNAPHeader);
01992 
01993                 
01994 
01995 
01996                 if ((error == 0) && (nb->nb_nw.sz != 0)) {
01997                     error = wi_write_bap(sc, fid, off, nb->nb_nw.vp, nb->nb_nw.sz);
01998                     off += nb->nb_nw.sz;
01999                 }
02000                 if ((error == 0) && (nb->nb_tp.sz != 0)) {
02001                     error = wi_write_bap(sc, fid, off, nb->nb_tp.vp, nb->nb_tp.sz);
02002                     off += nb->nb_tp.sz;
02003                 }
02004                 if ((error == 0) && (nb->nb_ap.sz != 0)) {
02005                     error = wi_write_bap(sc, fid, off, nb->nb_ap.vp, nb->nb_ap.sz);
02006                 }
02007                 if (error == 0) {
02008 
02009                     
02010 
02011                     error = wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0);
02012                     if (error != 0) {
02013                         Debug(("xmit failed\n"));
02014                         sc->sc_txd[cur].d_len = 0;
02015                     }
02016 
02017                     sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
02018                 }
02019             }
02020         }
02021 
02022         WI_UNLOCK(sc);
02023     }
02024 
02025     return (error);
02026 }
02027 
02028 
02029 
02030 
02031 int wlandrv_IOCTL(NUTDEVICE * dev, int req, void *conf)
02032 {
02033     int error = 0;
02034     int len;
02035     int i;
02036     u_int16_t DataBuffer[6];
02037     struct wi_softc *sc = (struct wi_softc *) dev->dev_dcb;
02038     struct ieee80211com *ic = &sc->sc_ic;
02039     WLAN_CONFIG *pWLANConfig;
02040     WLAN_STATUS *pWLANStatus;
02041     u_int8_t BSSIDAddress[6];
02042 
02043     if ((sc->wi_gone) || (conf == 0)) {
02044         error = -1;
02045     } else {
02046 
02047         switch (req) {
02048       
02049             
02050       
02051         case WLAN_IOCTL_GET_MAC_ADDRESS:{
02052                 memcpy(conf, ic->ic_myaddr, IEEE80211_ADDR_LEN);
02053                 break;
02054             }                   
02055 
02056       
02057             
02058       
02059         case WLAN_IOCTL_SET_CONFIG:{
02060                 pWLANConfig = (WLAN_CONFIG *) conf;
02061 
02062                 if ((pWLANConfig != NULL) && (pWLANConfig->Size == sizeof(WLAN_CONFIG))) {
02063                     WI_LOCK(sc);
02064 
02065                     
02066                     wi_stop(sc, 1);
02067 
02068                     
02069                     switch (pWLANConfig->Mode) {
02070                     case WLAN_MODE_STOP:{
02071                             WI_UNLOCK(sc);
02072                             return (0);
02073                             break;
02074                         }
02075                     case WLAN_MODE_STATION:{
02076                             ic->ic_opmode = IEEE80211_M_STA;
02077                             break;
02078                         }
02079                     case WLAN_MODE_ADHOC:{
02080                             ic->ic_opmode = IEEE80211_M_IBSS;
02081                             break;
02082                         }
02083                     default:{
02084                             error = -1;
02085                             break;
02086                         }
02087                     }
02088 
02089                     if (error == 0) {
02090                         
02091                         len = strlen(pWLANConfig->Networkname);
02092                         memcpy(ic->ic_des_essid, pWLANConfig->Networkname, len);
02093                         ic->ic_des_esslen = len;
02094 
02095                         
02096                         switch (pWLANConfig->UseWEP) {
02097                         case WLAN_USE_NO_WEP:{
02098                                 ic->ic_flags &= ~IEEE80211_F_WEPON;
02099                                 break;
02100                             }
02101                         case WLAN_USE_64BIT_WEP:
02102                         case WLAN_USE_128BIT_WEP:{
02103                                 ic->ic_flags |= IEEE80211_F_WEPON;
02104                                 break;
02105                             }
02106                         default:{
02107                                 error = -1;
02108                                 break;
02109                             }
02110                         }
02111 
02112                         
02113                         ic->ic_wep_txkey = pWLANConfig->UseWEPTxKey;
02114 
02115                         
02116                         for (i = 0; i < WLAN_WEP_MAX_KEY_COUNT; i++) {
02117                             ic->ic_nw_keys[i].wk_len = pWLANConfig->WEPKey[i].KeyLen;
02118                             memcpy(ic->ic_nw_keys[i].wk_key, pWLANConfig->WEPKey[i].Key, WLAN_WEP_MAX_KEY_SIZE);
02119                         }
02120                     }
02121 
02122                     WI_UNLOCK(sc);
02123 
02124                     if (error == 0) {
02125                         wlandrv_Init(dev);
02126                     }
02127                 } else {
02128                     error = -1;
02129                 }
02130                 break;
02131             }                   
02132 
02133       
02134             
02135       
02136         case WLAN_IOCTL_GET_STATUS:{
02137                 pWLANStatus = (WLAN_STATUS *) conf;
02138 
02139                 if ((pWLANStatus != NULL) && (pWLANStatus->Size == sizeof(WLAN_STATUS))) {
02140                     WI_LOCK(sc);
02141 
02142                     memset(pWLANStatus, 0x00, sizeof(WLAN_STATUS));
02143                     pWLANStatus->Size = sizeof(WLAN_STATUS);
02144 
02145                     
02146 
02147 
02148                     memset(DataBuffer, 0, sizeof(DataBuffer));
02149                     len = sizeof(DataBuffer);
02150                     error = wi_read_rid(sc, WI_RID_PORT_STAT, DataBuffer, &len);
02151                     if (error == 0) {
02152                         pWLANStatus->PortStatus = (u_int8_t) DataBuffer[0];
02153                     }
02154 
02155                     
02156 
02157 
02158                     memset(BSSIDAddress, 0, sizeof(BSSIDAddress));
02159                     len = sizeof(BSSIDAddress);
02160                     error = wi_read_rid(sc, WI_RID_CURRENT_BSSID, BSSIDAddress, &len);
02161                     if (error == 0) {
02162                         memcpy(pWLANStatus->BSSIDAddress, BSSIDAddress, IEEE80211_ADDR_LEN);
02163                     }
02164 
02165                     
02166 
02167 
02168                     memset(DataBuffer, 0, sizeof(DataBuffer));
02169                     len = sizeof(DataBuffer);
02170                     error = wi_read_rid(sc, WI_RID_CURRENT_CHAN, DataBuffer, &len);
02171                     if (error == 0) {
02172                         pWLANStatus->Channel = (u_int8_t) DataBuffer[0];
02173                     }
02174 
02175                     
02176 
02177 
02178                     memset(DataBuffer, 0, sizeof(DataBuffer));
02179                     len = sizeof(DataBuffer);
02180                     error = wi_read_rid(sc, WI_RID_CUR_TX_RATE, DataBuffer, &len);
02181                     if (error == 0) {
02182                         pWLANStatus->TxRate = (u_int8_t) DataBuffer[0];
02183                     }
02184 
02185                     
02186 
02187 
02188                     memset(DataBuffer, 0, sizeof(DataBuffer));
02189                     len = sizeof(DataBuffer);
02190                     error = wi_read_rid(sc, WI_RID_DBM_COMMS_QUAL, DataBuffer, &len);
02191                     if (error == 0) {
02192                         pWLANStatus->Quality = DataBuffer[0];
02193                         pWLANStatus->Signal = DataBuffer[1];
02194                         pWLANStatus->Noise = DataBuffer[2];
02195                     }
02196 
02197                     WI_UNLOCK(sc);
02198                 } else {
02199                     error = -1;
02200                 }
02201 
02202                 break;
02203             }                   
02204 
02205 
02206         default:{
02207                 error = -1;
02208                 break;
02209             }
02210         }                       
02211     }                           
02212 
02213 
02214     return (error);
02215 }