Nut/OS  4.10.3
API Reference
wlandrv.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 *  This file is part of the WLAN-Ethernut device driver.
00003 *
00004 *  Copyright (c) 2004 by Michael Fischer. All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *  1. Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *  2. Redistributions in binary form must reproduce the above copyright
00013 *     notice, this list of conditions and the following disclaimer in the
00014 *     documentation and/or other materials provided with the distribution.
00015 *  3. Neither the name of the author nor the names of its contributors may
00016 *     be used to endorse or promote products derived from this software
00017 *     without specific prior written permission.
00018 *
00019 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00023 *  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027 *  AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029 *  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030 *  SUCH DAMAGE.
00031 *
00032 ****************************************************************************
00033 *  Portions Copyright:
00034 *
00035 *  Copyright (c) 2002
00036 *        M Warner Losh <imp@freebsd.org>.  All rights reserved.
00037 *  Copyright (c) 1997, 1998, 1999
00038 *        Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
00039 *
00040 *  Redistribution and use in source and binary forms, with or without
00041 *  modification, are permitted provided that the following conditions
00042 *  are met:
00043 *  1. Redistributions of source code must retain the above copyright
00044 *     notice, this list of conditions and the following disclaimer.
00045 *  2. Redistributions in binary form must reproduce the above copyright
00046 *     notice, this list of conditions and the following disclaimer in the
00047 *     documentation and/or other materials provided with the distribution.
00048 *  3. Neither the name of the author nor the names of any co-contributors
00049 *     may be used to endorse or promote products derived from this software
00050 *     without specific prior written permission.
00051 *
00052 *  THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
00053 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00054 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00055 *  ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
00056 *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00057 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00058 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00059 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00060 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00061 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00062 *  THE POSSIBILITY OF SUCH DAMAGE.
00063 *
00064 ****************************************************************************
00065 *  History:
00066 *
00067 *  28.02.04  mifi   First Version
00068 *                   If you like to see the original source. Take a look
00069 *                   in if_wi.c from FreeBSD.
00070 *  01.03.04  mifi   Now we use a timeout in our Thread, and check if we lost
00071 *                   the card. In this case we try to Init it again.
00072 *  02.03.04  mifi   Remove QuickHack for Networkname and WEP.
00073 *  03.03.04  mifi   Use struct to config WLAN (WLAN_IOCTL_SET_CONFIG)
00074 *  04.03.04  mifi   Add function to get WLAN_STATUS (WLAN_IOCTL_GET_STATUS)
00075 *  06.03.04  mifi   Remove all @@MF later for monitor mode.
00076 *                   It does not work with my card, and I think we need a
00077 *                   special firmware for it.
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 /*  DEFINE: All Structures and Common Constants             */
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  * Length information
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  * Interrupt define
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  * transmit/receive frame structure
00153 */
00154 struct wi_frame {
00155     u_int16_t wi_status;        /* 0x00 */
00156     u_int16_t wi_rx_tstamp1;    /* 0x02 */
00157     u_int16_t wi_rx_tstamp0;    /* 0x04 */
00158     u_int8_t wi_rx_silence;     /* 0x06 */
00159     u_int8_t wi_rx_signal;      /* 0x07 */
00160     u_int8_t wi_rx_rate;        /* 0x08 */
00161     u_int8_t wi_rx_flow;        /* 0x09 */
00162     u_int8_t wi_tx_rtry;        /* 0x0a *//* Prism2 AP Only */
00163     u_int8_t wi_tx_rate;        /* 0x0b *//* Prism2 AP Only */
00164     u_int16_t wi_tx_ctl;        /* 0x0c */
00165     struct ieee80211_frame_addr4 wi_whdr;       /* 0x0e */
00166     u_int16_t wi_dat_len;       /* 0x2c */
00167     struct ether_header wi_ehdr;        /* 0x2e */
00168 };
00169 
00170 /*
00171  * Station set identification (SSID). (0xFC02, 0xFC04)
00172 */
00173 struct wi_ssid {
00174     u_int16_t wi_len;
00175     u_int8_t wi_ssid[32];
00176 };
00177 
00178 /*
00179  * Ethernet LLCS + SNAP header
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 /*  DEFINE: Prototypes                                      */
00190 /*==========================================================*/
00191 
00192 /*==========================================================*/
00193 /*  DEFINE: Definition of all local Data                    */
00194 /*==========================================================*/
00195 static HANDLE hDeviceSemaphore;
00196 static BYTE bDebugState = 0;
00197 
00198 struct wi_card_ident wi_card_ident[] = {
00199     /*
00200      * CARD_ID          CARD_NAME      FIRM_TYPE
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                          /* (WLAN_SUPPORT_LUCENT >= 1) */
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                          /* (WLAN_SUPPORT_INTERSIL >= 1) */
00239     {0, NULL, 0},
00240 };
00241 
00242 /*==========================================================*/
00243 /*  DEFINE: Definition of all local Procedures              */
00244 /*==========================================================*/
00245 /************************************************************/
00246 /*  DELAY                                                   */
00247 /*                                                          */
00248 /*  Delay in us.                                            */
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 /*  DumpData                                                */
00259 /*                                                          */
00260 /*  Dump the Buffer to the Terminal                         */
00261 /************************************************************/
00262 /* Harald: Not always used, but not sure how. Changed
00263 fron static to global and changed name to avoid conflicts */
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 /*  wi_cmd                                                  */
00291 /************************************************************/
00292 static int wi_cmd(struct wi_softc *sc, int cmd, int val0, int val1, int val2)
00293 {
00294     unsigned long i;            /* Harald: Changed from int to long. */
00295     unsigned int s = 0;                 /* Oliver: Changed from signed to unsigned. */
00296     static volatile int count = 0;
00297 
00298     if (sc->wi_gone) {
00299         return (ENODEV);
00300     }
00301 
00302     /* Harald: Removed this, it makes no sense */
00303     //if (count > 0) {
00304     //  panic("Hey partner, hold on there!");
00305     //}
00306     count++;
00307 
00308     /*
00309      * wait for the busy bit to clear
00310      */
00311     for (i = sc->wi_cmd_count; i > 0; i--) {    /* 500ms */
00312         if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
00313             break;
00314         }
00315         DELAY(1 * 1000);        /* 1ms */
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          * XXX: should sleep here.
00332          */
00333         /* Harald: Added UL specifiers, no idea how Michael's ICC accepted this */
00334         DELAY(250UL * 1000UL);  /* 250ms delay for init */
00335     }
00336     for (i = 0; i < WI_TIMEOUT; i++) {
00337         /*
00338          * Wait for 'command complete' bit to be
00339          * set in the event status register.
00340          */
00341         s = CSR_READ_2(sc, WI_EVENT_STAT);
00342         if (s & WI_EV_CMD) {
00343             /*
00344              * Ack the event and read result code.
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 /*  wi_stop                                                 */
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) {   /* gone --> not enabled */
00386             sc->sc_enabled = 0;
00387         }
00388     }
00389 
00390     sc->sc_tx_timer = 0;
00391     sc->sc_scan_timer = 0;
00392 }
00393 
00394 /************************************************************/
00395 /*  wi_seek_bap                                             */
00396 /************************************************************/
00397 static int wi_seek_bap(struct wi_softc *sc, int id, int off)
00398 {
00399     long i;                     /* Harald: from int to long  */
00400     unsigned int status;                /* Oliver: from signed to unsigned */
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;        /* invalidate */
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;    /* invalidate */
00423         return EIO;
00424     }
00425     sc->sc_bap_id = id;
00426     sc->sc_bap_off = off;
00427     return 0;
00428 }
00429 
00430 /************************************************************/
00431 /*  wi_read_bap                                             */
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 /*  wi_write_bap                                            */
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      * According to the comments in the HCF Light code, there is a bug
00484      * in the Hermes (or possibly in certain Hermes firmware revisions)
00485      * where the chip's internal autoincrement counter gets thrown off
00486      * during data writes:  the autoincrement is missed, causing one
00487      * data word to be overwritten and subsequent words to be written to
00488      * the wrong memory locations. The end result is that we could end
00489      * up transmitting bogus frames without realizing it. The workaround
00490      * for this is to write a couple of extra guard words after the end
00491      * of the transfer, then attempt to read then back. If we fail to
00492      * locate the guard words where we expect them, we preform the
00493      * transfer over again.
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;    /* invalidate */
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 /*  wi_read_rid                                             */
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      * Tell the NIC to enter record read mode.
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;  /* already got rid */
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 /*  wi_write_rid                                            */
00545 /*                                                          */
00546 /*  Write a block of data to the Resource Identifier.       */
00547 /*                                                          */
00548 /*  Return: OK or Error cause.                              */
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);   /* includes rid */
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 /*  wi_write_val                                            */
00572 /*                                                          */
00573 /*  Write the value to the Resource Identifier.             */
00574 /*  The function will write only a WORD                     */
00575 /*                                                          */
00576 /*  Return: OK or Error cause.                              */
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 /*  wi_write_txrate                                         */
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;               /* auto */
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      * rate: 0, 1, 2, 5, 11
00601      */
00602 
00603     switch (sc->sc_firmware_type) {
00604     case WI_LUCENT:
00605         switch (rate) {
00606         case 0:                /* auto == 11mbps auto */
00607             rate = 3;
00608             break;
00609             /*
00610              * case 1, 2 map to 1, 2
00611              */
00612         case 5:                /* 5.5Mbps -> 4 */
00613             rate = 4;
00614             break;
00615         case 11:               /* 11mbps -> 5 */
00616             rate = 5;
00617             break;
00618         default:
00619             break;
00620         }
00621         break;
00622     default:
00623         /*
00624          * Choose a bit according to this table.
00625          * *
00626          * * bit | data rate
00627          * * ----+-------------------
00628          * * 0   | 1Mbps
00629          * * 1   | 2Mbps
00630          * * 2   | 5.5Mbps
00631          * * 3   | 11Mbps
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;         /* auto */
00640         } else {
00641             rate = i;
00642         }
00643         break;
00644     }
00645     return wi_write_val(sc, WI_RID_TX_RATE, rate);
00646 }
00647 
00648 /************************************************************/
00649 /*  wi_reset                                                */
00650 /************************************************************/
00651 static int wi_reset(struct wi_softc *sc)
00652 {
00653     //struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used */
00654     int i;
00655     int error = 0;
00656     int tries;
00657 
00658     /*
00659      * Symbol firmware cannot be initialized more than once
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      * Calibrate timer
00688      */
00689     wi_write_val(sc, WI_RID_TICK_TIME, 8);
00690 
00691     return (0);
00692 }
00693 
00694 /************************************************************/
00695 /*  WLANInterrupt                                           */
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      * Disable interrupts. We will enable the interrupt
00710      * later in the RxThread.
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 /*  wi_tx_intr                                              */
00721 /************************************************************/
00722 static void wi_tx_intr(struct wi_softc *sc)
00723 {
00724     // struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used. */
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         //ifp->if_flags &= ~IFF_OACTIVE;
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             //ifp->if_timer = 1;
00753         }
00754     }
00755 }
00756 
00757 /************************************************************/
00758 /*  wi_info_intr                                            */
00759 /************************************************************/
00760 static void wi_info_intr(struct wi_softc *sc)
00761 {
00762     struct ieee80211com *ic = &sc->sc_ic;
00763     //struct ifnet *ifp = &ic->ic_if;
00764     //int i, len, off; /* Harald: Not used */
00765     int fid;
00766     u_int16_t ltbuf[2];
00767     u_int16_t stat;
00768     //u_int32_t *ptr; /* Harald: Not used. */
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                          /* (WLAN_ENABLE_LINK_STATUS >= 1) */
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              * FALLTHROUGH
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          * I think we does not need the counter,
00821          * therefore it can be take longer to implement it.
00822          */
00823 
00824         /*
00825          * some card versions have a larger stats structure
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                          /* later */
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                          /* later */
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 /*  wi_rx_intr                                              */
00859 /************************************************************/
00860 static NETBUF *wi_rx_intr(struct wi_softc *sc)
00861 {
00862     // struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used */
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; /* Harald: Missing init */
00873     u_int8_t *pBytePointer;
00874     int copy_size = 0;          /* Harald: Missing init */
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      * First read in the frame header
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      * Drop undecryptable or packets with receive errors here
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      * Catch the MAC 802.3 header
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      * The ether_type comes later
00911      */
00912 
00913     /*
00914      * Get the frame length, at this point I don't know
00915      * if it is a RFC1024 or RFC894 frame. But Ethernut need
00916      * an RFC894 frame! So we will alloc the NetBuffer later.
00917      */
00918     len = le16toh(frmhdr.wi_dat_len);
00919     off = sizeof(frmhdr);
00920 
00921     /*
00922      * Sometimes the PRISM2.x returns bogusly large frames. Except
00923      * in monitor mode, just throw them away.
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      * First read the LookAheadBuffer
00933      */
00934     error = wi_read_bap(sc, fid, off, &LABBuffer, sizeof(LABBuffer));
00935     off += sizeof(LABBuffer);
00936 
00937     if (error == 0) {
00938         /*
00939          * Check if this is a 802.2 LLC 802.2 SNAP IP-Header RFC1024
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                  * Now we can calculate the wFrameLength.
00955                  * It is a RFC1042 Frame, and we must discard the:
00956                  * DSAP, SSAP, cntl, and the org. code
00957                  *  1  +  1  +  1        +  3  = 6
00958                  */
00959                 len -= 6;
00960 
00961                 /*
00962                  * The Ethernut need the dest and source address,
00963                  * therefore add 12 again.
00964                  */
00965                 len += 12;
00966 
00967                 /*
00968                  * The MAC can not handle odd counts, test it.
00969                  *
00970                  */
00971                 len += 1;
00972                 len &= ~1;
00973 
00974                 /*
00975                  * Now alloc the NetBuffer for Ethernut.
00976                  */
00977                 nb = NutNetBufAlloc(0, NBAF_DATALINK, len);
00978                 if (nb != 0) {
00979                     pFrameBuffer = nb->nb_dl.vp;
00980 
00981                     /*
00982                      * We must copy wFrameLength out of the MAC
00983                      */
00984                     copy_size = len;
00985 
00986                     /*
00987                      * Copy the MAC 802.3 Header
00988                      */
00989                     memcpy(pFrameBuffer, &MAC802_3, sizeof(MAC802_3));
00990                     pFrameBuffer += sizeof(MAC802_3);
00991                     copy_size -= sizeof(MAC802_3);      /* This was already in the WLANHeader */
00992 
00993                     /*
00994                      * Now we have some data in our LABBuffer which we need
00995                      */
00996                     pBytePointer = (BYTE *) & LABBuffer;
00997                     /*
00998                      * jump over the header
00999                      */
01000                     pBytePointer += sizeof(LLCS_SNAP_HEADER);
01001                     /*
01002                      * and copy the rest
01003                      */
01004                     size = sizeof(LABBuffer) - sizeof(LLCS_SNAP_HEADER);
01005                     memcpy(pFrameBuffer, pBytePointer, size);
01006                     /*
01007                      * Change the pointer for the "global copy"
01008                      */
01009                     pFrameBuffer += size;
01010                     copy_size -= size;  /* This was already in the LookAheadBuffer */
01011                 } else {
01012                     IPFrame = 0;
01013                 }
01014             }                   /* only ARP and IP */
01015         } else {
01016             /*
01017              * Check if this is a RFX894 Frame
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                  * The MAC can not handle odd counts, test it.
01029                  *
01030                  */
01031                 len += 1;
01032                 len &= ~1;
01033 
01034                 /*
01035                  * The FrameLength is now the correct length for an RFC894 Frame,
01036                  * Now alloc the NetBuffer for Ethernut.
01037                  */
01038                 nb = NutNetBufAlloc(0, NBAF_DATALINK, len);
01039                 if (nb != 0) {
01040                     pFrameBuffer = nb->nb_dl.vp;
01041 
01042                     /*
01043                      * We must copy wFrameLength out of the MAC
01044                      */
01045                     copy_size = len;
01046 
01047                     /*
01048                      * The LookAheadBuffer is the MAC-Header
01049                      */
01050                     memcpy(pFrameBuffer, &LABBuffer, sizeof(LABBuffer));
01051                     pFrameBuffer += sizeof(LABBuffer);
01052                     copy_size -= sizeof(LABBuffer);     /* This was our LookAheadBuffer */
01053                 } else {
01054                     IPFrame = 0;
01055                 }               /* NutNetBufAlloc */
01056             }                   /* RFC894 Frame */
01057         }                       /* Error read LookAheadBuffer */
01058 
01059         /*
01060          * Do the rest here, "global copy"
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      * At least, send a ack for the event
01078      */
01079     CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
01080 
01081     return (nb);
01082 }
01083 
01084 /************************************************************/
01085 /*  RxThread                                                */
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          * Wait for the arrival of new packets or check
01102          * the receiver every two second.
01103          */
01104         NutEventWait(&sc->InterruptEvent, 2000);
01105         EventStatus = sc->EventStatus;
01106 
01107         /*
01108          * Clear the sc-EventStatus. If the next time the
01109          * EventStatus is 0, it was the timeout and not
01110          * an interrupt.
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              * It was the timeout, check if the card is alive
01146              */
01147             if ((sc->sc_enabled == 1) && (sc->wi_gone == 1)) {
01148                 /*
01149                  * The card was enabled but we has lost the card, reinit...
01150                  */
01151                 Debug(("Houston, we have a problem...\n"));
01152                 sc->wi_gone = 0;
01153                 wlandrv_Init(dev);
01154             }
01155         }                       /* (EventStatus != 0) */
01156     }                           /* for */
01157 }
01158 
01159 /************************************************************/
01160 /*  wi_alloc_fid                                            */
01161 /************************************************************/
01162 static int wi_alloc_fid(struct wi_softc *sc, int len, int *idp)
01163 {
01164     unsigned long i;                     /* Harald: Changed from int to long */
01165                                                                          /* Oliver: Changed from signed to unsigned */
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 /*  wi_write_ssid                                           */
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 /*  wi_read_nicid                                           */
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      * getting chip identity
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      * get primary firmware version (Only Prism chips)
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      * get station firmware version
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          * value should be the format like "V2.00-11"
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) {    /* XXX */
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 /*  wi_write_wep                                            */
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                          /* (WLAN_SUPPORT_LUCENT >= 1) */
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              * ONLY HWB3163 EVAL-CARD Firmware version
01318              * less than 0.8 variant2
01319              *
01320              *   If promiscuous mode disable, Prism2 chip
01321              *  does not work with WEP .
01322              * It is under investigation for details.
01323              * (ichiro@netbsd.org)
01324              */
01325             if (sc->sc_firmware_type == WI_INTERSIL && sc->sc_sta_firmware_ver < 802) {
01326                 /*
01327                  * firm ver < 0.8 variant 2
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              * Encryption firmware has a bug for HostAP mode.
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          * It seems that the firmware accept 104bit key only if
01353          * all the keys have 104bit length.  We get the length of
01354          * the transmit key and use it for all other keys.
01355          * Perhaps we should use software WEP for such situation.
01356          */
01357         keylen = ic->ic_nw_keys[ic->ic_wep_txkey].wk_len;
01358         if (keylen > IEEE80211_WEP_KEYLEN) {
01359             keylen = 13;        /* 104bit keys */
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                          /* ((WLAN_SUPPORT_INTERSIL >= 1) || (WLAN_SUPPORT_SYMBOL >= 1)) */
01371     }
01372     return error;
01373 }
01374 
01375 /*==========================================================*/
01376 /*  DEFINE: All code exported                               */
01377 /*==========================================================*/
01378 /************************************************************/
01379 /*  wlandrv_ProbeDevice                                     */
01380 /*                                                          */
01381 /*  Make a HW-Reset and test if a card is available.        */
01382 /*                                                          */
01383 /*  Return: ERROR, OK                                       */
01384 /************************************************************/
01385 int wlandrv_ProbeDevice(void)
01386 {
01387     int error = -1;
01388     u_int16_t Value;
01389 
01390     /*
01391      * Set RESET
01392      */
01393     RESET_EN_PORT |= RESET_BIT;
01394     RESET_PORT |= RESET_BIT;
01395 
01396     NutSleep(100);
01397 
01398     /*
01399      * Remove RESET
01400      */
01401     RESET_PORT &= ~RESET_BIT;
01402 
01403     NutSleep(500);
01404 
01405     /*
01406      * Set the MAC into I/O mode
01407      */
01408     pcmcia_WriteMem(WI_COR_OFFSET, WI_COR_VALUE);
01409     NutSleep(100);
01410 
01411     /*
01412      * Test if we can found a card
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          * We found a card :-)
01419          */
01420         error = 0;
01421     }
01422 
01423     return (error);
01424 }
01425 
01426 /************************************************************/
01427 /*  wlandrv_Attach                                          */
01428 /*                                                          */
01429 /*  Catch all information about the card which              */
01430 /*  could be found. And set some default parameter          */
01431 /*                                                          */
01432 /*  Return: ERROR, OK                                       */
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     //u_int8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
01443     //  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
01444     //}; /* Harald: This is unused */
01445     int error;
01446 
01447     bDebugState = 2;
01448 
01449     sc->wi_cmd_count = 500;
01450     ic->ic_fixed_rate = -1;     /* auto */
01451 
01452 
01453     /*
01454      * Reset the NIC.
01455      */
01456     if (wi_reset(sc) != 0) {
01457         return ENXIO;           /* XXX */
01458     }
01459 
01460     /*
01461      * Read the station address.
01462      * And do it twice. I've seen PRISM-based cards that return
01463      * an error when trying to read it the first time, which causes
01464      * the probe to fail.
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      * Read NIC identification
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      * Query the card for available channels.
01490      */
01491     buflen = sizeof(val);
01492     if (wi_read_rid(sc, WI_RID_CHANNEL_LIST, &val, &buflen) != 0) {
01493         val = htole16(0x1fff);  /* assume 1-13 */
01494     }
01495     if (val == 0) {
01496         Debug(("wi_attach: no available channels listed!"));
01497     }
01498     ic->ChannelList = (val << 1);
01499 
01500     /*
01501      * Read the default channel from the NIC. This may vary
01502      * depending on the country where the NIC was purchased, so
01503      * we can't hard-code a default and expect it to work for
01504      * everyone.
01505      *
01506      * If no channel is specified, let the 802.11 code select.
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      * Set flags based on firmware version.
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          * XXX: not confirmed, but never seen for recent firmware
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                          /* (WLAN_SUPPORT_LUCENT >= 1) */
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          * Old firmware are slow, so give peace a chance.
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          * version 0.8.3 and newer are the only ones that are known
01575          * to currently work.  Earlier versions can be made to work,
01576          * at least according to the Linux driver.
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                          /* (WLAN_SUPPORT_INTERSIL >= 1) */
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                          /* (WLAN_SUPPORT_SYMBOL >= 1) */
01603     }
01604 
01605     /*
01606      * Find out if we support WEP on this card.
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      * Find supported rates.
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          * XXX fallback on error?
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      * Init DeviceSemaphore
01651      */
01652     NutEventPost(&hDeviceSemaphore);
01653 
01654     return (0);
01655 }
01656 
01657 /************************************************************/
01658 /*  wlandrv_Init                                            */
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      * common 802.11 configuration
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          * For PRISM cards, override the empty SSID, because in
01698          * HostAP mode the controller will lock up otherwise.
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         /* Harald: Should be handled. */
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      * Intersil interprets this RID as joining ESS even in IBSS mode
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                          /* later */
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      * not yet common 802.11 configuration
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                          /* later */
01749 
01750     /*
01751      * driver specific 802.11 configuration
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      * What is a nodename ??? :-(
01767      */
01768     wi_write_ssid(sc, WI_RID_NODENAME, sc->sc_nodename, sc->sc_nodelen);
01769 #endif                          /* later */
01770 
01771 #if 0                           //@@MF later
01772     /*
01773      * Does we realy need HOSTAP on Ethernut??
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);      /* 1, 2 */
01778         wi_write_val(sc, WI_RID_SUPPORT_RATE, 0x0f);    /* 1, 2, 5.5, 11 */
01779         wi_write_val(sc, WI_RID_DTIM_PERIOD, 1);
01780     }
01781 #endif                          /* later */
01782 
01783     /*
01784      *  Initialize promisc mode.
01785      *  Being in the Host-AP mode causes a great
01786      *  deal of pain if primisc mode is set.
01787      *  Therefore we avoid confusing the firmware
01788      *  and always reset promisc mode in Host-AP
01789      *  mode.  Host-AP sees all the packets anyway.
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      * Configure WEP.
01799      */
01800     if (ic->ic_caps & IEEE80211_C_WEP) {
01801         wi_write_wep(sc);
01802     }
01803 #if 0                           //@@MF later
01804     /*
01805      * Set multicast filter.
01806      */
01807     wi_write_multi(sc);
01808 #endif                          /* later */
01809 
01810     /*
01811      * Allocate fids for the card
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;       /* XXX */
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      * Enable desired port
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     /*                  Set interrupt and start RxThread                     */
01841   /*************************************************************************/
01842     if (sc->InterruptInitDone == 0) {
01843         sc->InterruptInitDone = 1;
01844         /*
01845          * Install WLAN interrupt
01846          */
01847         PORTE |= 0x80;          /* Enable PullUp */
01848         error = NutRegisterIrqHandler(&sig_INTERRUPT7, WLANInterrupt, dev);
01849         if (error == FALSE) {
01850             EICR |= 0x80;       // falling edge
01851             sbi(EIMSK, INT7);
01852 
01853             /*
01854              * Start the receiver thread.
01855              */
01856             NutThreadCreate("rxi7", RxThread, dev, 640);
01857         }
01858     }
01859   /*************************************************************************/
01860 
01861 
01862     /*
01863      * Enable interrupts
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          * XXX: some card need to be re-enabled for hostap
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      * This is only for IEEE80211_M_STA
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          * Lucent firmware does not support the JOIN RID.
01886          */
01887         if (sc->sc_firmware_type != WI_LUCENT)
01888             wi_write_rid(sc, WI_RID_JOIN_REQ, &join, sizeof(join));
01889     }
01890 #endif                          /* later */
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 /*  wlandrv_PutPacket                                       */
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      * Calculate the number of bytes to be send. Do not
01923      * send packets larger than 1518 bytes.
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          * This is a RFC894 Frame from Ethernut
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          * But we must send a RFC1024 Frame.
01941          * ETHERHDR is not part of an RFC1024 Frame
01942          */
01943         len = len - sizeof(ETHERHDR);
01944 
01945         /*
01946          * Add RFC1024 Header
01947          */
01948         len += sizeof(LLCS_SNAP_HEADER);
01949 
01950         /*
01951          * I do not know what I do here, therefore clear the header
01952          * and to hope for, the card will do the rest?
01953          */
01954         memset(&frmhdr, 0, sizeof(frmhdr));
01955 
01956         /*
01957          * Copy the Ethernut MAC 802.3 Dest/Source Address into the WLANHeader
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          * Prepare the RFC1024 Header
01967          */
01968         LLCSSNAPHeader.DSAPSSAP = 0xAAAA;
01969         LLCSSNAPHeader.Control = 0x0003;
01970         LLCSSNAPHeader.MustZero = 0x0000;
01971         LLCSSNAPHeader.Type = pMAC8023Header->ether_type;
01972 
01973         /*
01974          * Get the TX-BUffer-ID
01975          */
01976         cur = sc->sc_txcur;
01977         fid = sc->sc_txd[cur].d_fid;
01978 
01979         /*
01980          * And Copy the WLANHeader
01981          */
01982         error = wi_write_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr));
01983         if (error == 0) {
01984             off = sizeof(frmhdr);
01985 
01986             /*
01987              * Now copy the RFC1024 Header
01988              */
01989             error = wi_write_bap(sc, fid, off, &LLCSSNAPHeader, sizeof(LLCSSNAPHeader));
01990             if (error == 0) {
01991                 off += sizeof(LLCSSNAPHeader);
01992 
01993                 /*
01994                  * Copy the rest of the Ethernut Data
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                     //@@MF sc->sc_txd[cur].d_len = off;
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 /*  wlandrv_IOCTL                                           */
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             /*             WLAN_IOCTL_GET_MAC_ADDRESS            */
02050       /*****************************************************/
02051         case WLAN_IOCTL_GET_MAC_ADDRESS:{
02052                 memcpy(conf, ic->ic_myaddr, IEEE80211_ADDR_LEN);
02053                 break;
02054             }                   /* WLAN_IOCTL_GET_MAC_ADDRESS */
02055 
02056       /*****************************************************/
02057             /*                WLAN_IOCTL_SET_CONFIG              */
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                     /* Stop WLAN controller */
02066                     wi_stop(sc, 1);
02067 
02068                     /* Set mode */
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                         /* Set SSID */
02091                         len = strlen(pWLANConfig->Networkname);
02092                         memcpy(ic->ic_des_essid, pWLANConfig->Networkname, len);
02093                         ic->ic_des_esslen = len;
02094 
02095                         /* Enable WEP */
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                         /* Set WEP tx key */
02113                         ic->ic_wep_txkey = pWLANConfig->UseWEPTxKey;
02114 
02115                         /* Set WEP keys */
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             }                   /* WLAN_IOCTL_SET_CONFIG */
02132 
02133       /*****************************************************/
02134             /*                WLAN_IOCTL_GET_STATUS              */
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                      * PortStatus
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                      * Current BSSID
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                      * Current Channel
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                      * Current TxRate
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                      * Getting Quality
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             }                   /* WLAN_IOCTL_GET_STATUS */
02204 
02205 
02206         default:{
02207                 error = -1;
02208                 break;
02209             }
02210         }                       /* switch */
02211     }                           /* sc->wi_gone */
02212 
02213 
02214     return (error);
02215 }