⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wlandrv.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    CSR_WRITE_2(sc, WI_SEL0, id);    CSR_WRITE_2(sc, WI_OFF0, off);    for (i = 0;; i++) {        status = CSR_READ_2(sc, WI_OFF0);        if ((status & WI_OFF_BUSY) == 0) {            break;        }        if (i == WI_TIMEOUT) {            Debug(("timeout in wi_seek to %x/%x\n", id, off));            sc->sc_bap_off = WI_OFF_ERR;        /* invalidate */            if (status == 0xffff) {                sc->wi_gone = 1;            }            return ETIMEDOUT;        }        DELAY(1);    }    if (status & WI_OFF_ERR) {        Debug(("failed in wi_seek to %x/%x\n", id, off));        sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */        return EIO;    }    sc->sc_bap_id = id;    sc->sc_bap_off = off;    return 0;}/************************************************************//*  wi_read_bap                                             *//************************************************************/static int wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen){    u_int16_t *ptr;    int i, error, cnt;    if (buflen == 0) {        return 0;    }    if (id != sc->sc_bap_id || off != sc->sc_bap_off) {        if ((error = wi_seek_bap(sc, id, off)) != 0) {            return error;        }    }    cnt = (buflen + 1) / 2;    ptr = (u_int16_t *) buf;    for (i = 0; i < cnt; i++) {        *ptr++ = CSR_READ_2(sc, WI_DATA0);    }    sc->sc_bap_off += cnt * 2;    return 0;}/************************************************************//*  wi_write_bap                                            *//************************************************************/static int wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen){    u_int16_t *ptr;    int i, error, cnt;    if (buflen == 0) {        return 0;    }#ifdef WI_HERMES_AUTOINC_WAR  again:#endif    if (id != sc->sc_bap_id || off != sc->sc_bap_off) {        if ((error = wi_seek_bap(sc, id, off)) != 0) {            return error;        }    }    cnt = (buflen + 1) / 2;    ptr = (u_int16_t *) buf;    for (i = 0; i < cnt; i++) {        CSR_WRITE_2(sc, WI_DATA0, ptr[i]);    }    sc->sc_bap_off += cnt * 2;#ifdef WI_HERMES_AUTOINC_WAR    /*     * According to the comments in the HCF Light code, there is a bug     * in the Hermes (or possibly in certain Hermes firmware revisions)     * where the chip's internal autoincrement counter gets thrown off     * during data writes:  the autoincrement is missed, causing one     * data word to be overwritten and subsequent words to be written to     * the wrong memory locations. The end result is that we could end     * up transmitting bogus frames without realizing it. The workaround     * for this is to write a couple of extra guard words after the end     * of the transfer, then attempt to read then back. If we fail to     * locate the guard words where we expect them, we preform the     * transfer over again.     */    if ((sc->sc_flags & WI_FLAGS_BUG_AUTOINC) && (id & 0xf000) == 0) {        CSR_WRITE_2(sc, WI_DATA0, 0x1234);        CSR_WRITE_2(sc, WI_DATA0, 0x5678);        wi_seek_bap(sc, id, sc->sc_bap_off);        sc->sc_bap_off = WI_OFF_ERR;    /* invalidate */        if (CSR_READ_2(sc, WI_DATA0) != 0x1234 || CSR_READ_2(sc, WI_DATA0) != 0x5678) {            Debug(("detect auto increment bug, try again\n"));            goto again;        }    }#endif    return 0;}/************************************************************//*  wi_read_rid                                             *//************************************************************/static int wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp){    int error, len;    u_int16_t ltbuf[2];    /*     * Tell the NIC to enter record read mode.     */    error = wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_READ, rid, 0, 0);    if (error) {        return error;    }    error = wi_read_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));    if (error) {        return error;    }    if (le16toh(ltbuf[1]) != (u_int16_t) rid) {        Debug(("record read mismatch, rid=%x, got=%x\n", rid, le16toh(ltbuf[1])));        return EIO;    }    len = (le16toh(ltbuf[0]) - 1) * 2;  /* already got rid */    if (*buflenp < len) {        Debug(("record buffer is too small, rid=%x, size=%d, len=%d\n", rid, *buflenp, len));        return ENOSPC;    }    *buflenp = len;    return wi_read_bap(sc, rid, sizeof(ltbuf), buf, len);}/************************************************************//*  wi_write_rid                                            *//*                                                          *//*  Write a block of data to the Resource Identifier.       *//*                                                          *//*  Return: OK or Error cause.                              *//************************************************************/static int wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen){    int error;    u_int16_t ltbuf[2];    ltbuf[0] = htole16((buflen + 1) / 2 + 1);   /* includes rid */    ltbuf[1] = htole16(rid);    error = wi_write_bap(sc, rid, 0, ltbuf, sizeof(ltbuf));    if (error) {        return error;    }    error = wi_write_bap(sc, rid, sizeof(ltbuf), buf, buflen);    if (error) {        return error;    }    return wi_cmd(sc, WI_CMD_ACCESS | WI_ACCESS_WRITE, rid, 0, 0);}/************************************************************//*  wi_write_val                                            *//*                                                          *//*  Write the value to the Resource Identifier.             *//*  The function will write only a WORD                     *//*                                                          *//*  Return: OK or Error cause.                              *//************************************************************/static int wi_write_val(struct wi_softc *sc, int rid, u_int16_t val){    val = htole16(val);    return wi_write_rid(sc, rid, &val, sizeof(val));}/************************************************************//*  wi_write_txrate                                         *//************************************************************/static int wi_write_txrate(struct wi_softc *sc){    struct ieee80211com *ic = &sc->sc_ic;    int i;    u_int16_t rate;    if (ic->ic_fixed_rate < 0) {        rate = 0;               /* auto */    } else {        rate = (ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL) / 2;    }    /*     * rate: 0, 1, 2, 5, 11     */    switch (sc->sc_firmware_type) {    case WI_LUCENT:        switch (rate) {        case 0:                /* auto == 11mbps auto */            rate = 3;            break;            /*             * case 1, 2 map to 1, 2             */        case 5:                /* 5.5Mbps -> 4 */            rate = 4;            break;        case 11:               /* 11mbps -> 5 */            rate = 5;            break;        default:            break;        }        break;    default:        /*         * Choose a bit according to this table.         * *         * * bit | data rate         * * ----+-------------------         * * 0   | 1Mbps         * * 1   | 2Mbps         * * 2   | 5.5Mbps         * * 3   | 11Mbps         */        for (i = 8; i > 0; i >>= 1) {            if ((int) rate >= i) {                break;            }        }        if (i == 0) {            rate = 0xf;         /* auto */        } else {            rate = i;        }        break;    }    return wi_write_val(sc, WI_RID_TX_RATE, rate);}/************************************************************//*  wi_reset                                                *//************************************************************/static int wi_reset(struct wi_softc *sc){    //struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used */    int i;    int error = 0;    int tries;    /*     * Symbol firmware cannot be initialized more than once     */    if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_reset) {        return (0);    }    if (sc->sc_firmware_type == WI_SYMBOL) {        tries = 1;    } else {        tries = 3;    }    for (i = 0; i < tries; i++) {        if ((error = wi_cmd(sc, WI_CMD_INI, 0, 0, 0)) == 0) {            break;        }        DELAY(WI_DELAY * 1000);    }    sc->sc_reset = 1;    if (i == tries) {        Debug(("init failed\n"));        return (error);    }    CSR_WRITE_2(sc, WI_INT_EN, 0);    CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);    /*     * Calibrate timer     */    wi_write_val(sc, WI_RID_TICK_TIME, 8);    return (0);}/************************************************************//*  WLANInterrupt                                           *//************************************************************/static void WLANInterrupt(void *p){    NUTDEVICE *dev = (NUTDEVICE *) p;    struct wi_softc *sc = (struct wi_softc *) dev->dev_dcb;    if ((sc->wi_gone == 1) || (sc->sc_enabled == 0)) {        CSR_WRITE_2(sc, WI_INT_EN, 0);        CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);        return;    }    /*     * Disable interrupts. We will enable the interrupt     * later in the RxThread.     */    CSR_WRITE_2(sc, WI_INT_EN, 0);    sc->EventStatus = CSR_READ_2(sc, WI_EVENT_STAT);    NutEventPostFromIrq(&sc->InterruptEvent);}/************************************************************//*  wi_tx_intr                                              *//************************************************************/static void wi_tx_intr(struct wi_softc *sc){    // struct ieee80211com *ic = &sc->sc_ic; /* Harald: Not used. */    int fid, cur;    if (sc->wi_gone) {        return;    }    fid = CSR_READ_2(sc, WI_ALLOC_FID);    CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_ALLOC);    cur = sc->sc_txcur;    if (sc->sc_txd[cur].d_fid != fid) {#if (WLAN_ENABLE_TX_FRAME_DUMP >= 1)        Debug(("bad alloc %x != %x, cur %d nxt %d\n", fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext));#endif        return;    }    sc->sc_tx_timer = 0;    sc->sc_txd[cur].d_len = 0;    sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;    if (sc->sc_txd[cur].d_len == 0) {        //ifp->if_flags &= ~IFF_OACTIVE;    } else {        if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid, 0, 0)) {            Debug(("xmit failed\n"));            sc->sc_txd[cur].d_len = 0;        } else {            sc->sc_tx_timer = 5;            //ifp->if_timer = 1;        }    }}/************************************************************//*  wi_info_intr                                            *//************************************************************/static void wi_info_intr(struct wi_softc *sc){    struct ieee80211com *ic = &sc->sc_ic;    //struct ifnet *ifp = &ic->ic_if;    //int i, len, off; /* Harald: Not used */    int fid;    u_int16_t ltbuf[2];    u_int16_t stat;    //u_int32_t *ptr; /* Harald: Not used. */    fid = CSR_READ_2(sc, WI_INFO_FID);    wi_read_bap(sc, fid, 0, ltbuf, sizeof(ltbuf));    switch (le16toh(ltbuf[1])) {    case WI_INFO_LINK_STAT:        wi_read_bap(sc, fid, sizeof(ltbuf), &stat, sizeof(stat));#if (WLAN_ENABLE_LINK_STATUS >= 1)        Debug(("wi_info_intr: LINK_STAT 0x%x\n", le16toh(stat)));#endif                          /* (WLAN_ENABLE_LINK_STATUS >= 1) */        switch (le16toh(stat)) {        case WI_INFO_LINK_STAT_CONNECTED:            sc->sc_flags &= ~WI_FLAGS_OUTRANGE;            if (ic->ic_state == IEEE80211_S_RUN && ic->ic_opmode != IEEE80211_M_IBSS) {                break;            }            /*             * FALLTHROUGH             */        case WI_INFO_LINK_STAT_AP_CHG:            ieee80211_new_state(ic, IEEE80211_S_RUN, -1);            break;        case WI_INFO_LINK_STAT_AP_INR:            sc->sc_flags &= ~WI_FLAGS_OUTRANGE;            break;        case WI_INFO_LINK_STAT_AP_OOR:            if (sc->sc_firmware_type == WI_SYMBOL && sc->sc_scan_timer > 0) {                if (wi_cmd(sc, WI_CMD_INQUIRE, WI_INFO_HOST_SCAN_RESULTS, 0, 0)                    != 0) {                    sc->sc_scan_timer = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -