📄 if_wlp_wavelan.c
字号:
/* * Copyright (c) 1997 Carnegie Mellon University. All Rights Reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted (including for commercial or for-profit * use), provided that both the copyright notice and this permission notice * appear in all copies of the software, derivative works, or modified * versions, and any portions thereof, and that both notices appear in * supporting documentation, and that credit is given to Carnegie Mellon * University in all publications reporting on direct or indirect use of this * code or its derivatives. * * THIS IMPLEMENTATION IS EXPERIMENTAL AND MAY HAVE BUGS, SOME OF WHICH MAY HAVE * SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS SOFTWARE IN ITS "AS * IS" CONDITION, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON * UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Carnegie Mellon encourages (but does not require) users of this software to * return any improvements or extensions that they make, and to grant * Carnegie Mellon the rights to redistribute these changes without * encumbrance. * * */#include "card.h"#if NCARD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/time.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#include <machine/clock.h>#include <i386/isa/isa_device.h>#include <i386/isa/ic/i82593.h>#include <i386/isa/if_wlp_wavelan.h>#include <i386/isa/if_wlp.h>#ifdef WAVELAN_ROAMING#include <i386/isa/if_wlp_wavelan_roam.h>#endifextern struct wlp_softc wlp_softc[];/* * From /sys/pccard/pccard.c */int pccard_map_attr_mem(struct slot *slt, struct mem_desc *oldmp, u_int32_t *window, caddr_t *start);int pccard_unmap_attr_mem(struct slot *slt, struct mem_desc *oldmp, u_int32_t window);/* ====================================================================== Global Variables ====================================================================== */u_char ether_wavelan_snaphdr[8] = {0xAA, 0xAA, 0x03, 0x08, 0x00, 0x0E, 0x20, 0x03};u_char ether_bridge_multiaddr[ETHER_ADDR_LEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x10};u_char ether_beacon_multiaddr[ETHER_ADDR_LEN] = {0x09, 0x00, 0x0E, 0x20, 0x03, 0x00};char *I82593_IRQ[16] = { "", "IA-SETUP DONE", "CONFIGURE DONE", "MC-SETUP DONE", "TRANSMIT DONE", "TDR DONE", "DUMP DONE", "DIAGNOSE PASSED", "END OF FRAME", "TRANSMIT NO CRC DONE", "RCV ABORT", "STOP HIT REG", "RETRANSMIT DONE", "EXECUTION ABORT", "", "DIAGNOSE FAILED" };char *RoamModeString[4] = {"INVALID", "Fast Cell Search", "Regular Cell Search", "Stop Cell Search"};/* * ====================================================================== * Intel 82593 Specific Routines * ====================================================================== */static voidi82593_wavelan_config(struct ifnet *ifp, struct i82593_conf *cfg);static voidi82593_wavelan_config(struct ifnet *ifp, struct i82593_conf *cfg){ cfg->byte_count_low = sizeof(cfg->data.cfgblock); cfg->byte_count_high = 0; cfg->data.bytes[0] = 0x25; cfg->data.bytes[1] = 0x80; cfg->data.bytes[2] = 0x0E; cfg->data.bytes[3] = 0xD0; cfg->data.bytes[4] = 0x20; cfg->data.bytes[5] = 0x20; cfg->data.bytes[6] = 0xF0; cfg->data.bytes[7] = 0x08; if (ifp->if_flags & IFF_PROMISC) cfg->data.bytes[7] |= 0x01; cfg->data.bytes[8] = 0x00; cfg->data.bytes[9] = 0x40; cfg->data.bytes[10] = 0xBE; cfg->data.bytes[11] = 0x00; cfg->data.bytes[12] = 0x3F; cfg->data.bytes[13] = 0x07; cfg->data.bytes[14] = 0xF1; cfg->data.bytes[15] = 0x04;#ifdef notdef cfg->data.cfgblock.lin_prio = 0x01;#endif}/* ====================================================================== Low-level Modem Routines ====================================================================== */static void wait_for_modem(struct wlp_softc*);static void wait_for_eeprom(struct wlp_softc*);static u_int8_t read_modem_byte(struct wlp_softc*, u_int8_t);static void write_modem_byte(struct wlp_softc*, u_int8_t, u_int8_t);/* * Give the modem upto 10 ms */static voidwait_for_modem(sc) struct wlp_softc *sc;{ u_int16_t i; for(i = 0; i < 100; i++) { if((IORead1(0x01) & P1_MMI_BUSY) == 0) return; DELAY(100); } printf("wlp%d: MMI Busy...\n", sc->sc_ac.ac_if.if_unit);}static voidwait_for_eeprom(sc) struct wlp_softc *sc;{ u_int16_t i; u_int8_t val; DELAY(10000); for(i = 0; i < 100; i++) { val = read_modem_byte(sc, RF_EECTRL); if((val & (RF_EECTRL_EEBUSY | RF_EECTRL_DWLD)) == 0) return; DELAY(100); } printf("wlp%d: EEPROM Busy...\n", sc->sc_ac.ac_if.if_unit);}static u_int8_tread_modem_byte(sc, reg) struct wlp_softc *sc; u_int8_t reg;{ wait_for_modem(sc); IOWrite1(0x06, (reg << 1) & ~P6_MMI_WR); IOWrite1(0x07, 0x00); /* start the read cycle */ wait_for_modem(sc); return IORead1(0x07);}static voidwrite_modem_byte(sc, reg, val) struct wlp_softc *sc; u_int8_t reg; u_int8_t val;{ wait_for_modem(sc); IOWrite1(0x06, (reg << 1) | P6_MMI_WR); IOWrite1(0x07, val); wait_for_modem(sc);}/* ====================================================================== WaveLAN (wlp) Specific Routines ====================================================================== */static void wlp_set_wavelan_conf(struct wlp_softc*, caddr_t);static voidwlp_set_wavelan_conf(sc, attrmem) struct wlp_softc *sc; caddr_t attrmem;{#ifdef WLP_DEBUG printf("ENTRY wlp_set_wavelan_conf()\n");#endif sc->sc_conf.umac_address[0] = READ_PSA(attrmem, PSA_UMAC_ADDRESS); sc->sc_conf.umac_address[1] = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 1); sc->sc_conf.umac_address[2] = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 2); sc->sc_conf.umac_address[3] = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 3); sc->sc_conf.umac_address[4] = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 4); sc->sc_conf.umac_address[5] = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 5);#ifdef WLP_DEBUG printf("\tMAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", sc->sc_conf.umac_address[0], sc->sc_conf.umac_address[1], sc->sc_conf.umac_address[2], sc->sc_conf.umac_address[3], sc->sc_conf.umac_address[4], sc->sc_conf.umac_address[5]);#endif sc->sc_conf.compat_number = READ_PSA(attrmem, PSA_COMPAT_NUMBER); sc->sc_conf.threshold_preset = READ_PSA(attrmem, PSA_THRESHOLD_PRESET); sc->sc_conf.subband_number = READ_PSA(attrmem, PSA_SUBBAND_NUMBER); sc->sc_conf.quality_threshold = READ_PSA(attrmem, PSA_QUALITY_THRESHOLD); sc->sc_conf.nwid[0] = READ_PSA(attrmem, PSA_NWID); sc->sc_conf.nwid[1] = READ_PSA(attrmem, PSA_NWID + 1);#ifdef WLP_DEBUG printf("\tNWID: %02x:%02x\n", sc->sc_conf.nwid[0], sc->sc_conf.nwid[1]);#endif sc->sc_conf.nwid_select = READ_PSA(attrmem, PSA_UMAC_ADDRESS + 1); sc->sc_conf.config_status = READ_PSA(attrmem, PSA_CONFIG_STATUS);#ifdef WLP_DEBUG printf("wlp_set_wavelan_conf() EXIT ()\n");#endif}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#define DELAYCONST 1000intwlpprobe(is, dp) struct isa_device *is; struct pccard_devinfo *dp;{ struct wlp_softc *sc = &wlp_softc[is->id_unit];#ifdef WLP_DEBUG printf("wlp%d: ENTRY wlpprobe()\n", is->id_unit);#endif /* * Reset the Intel 82593 */ IOWrite1(0x00, P0_RESET); DELAY(DELAYCONST);#ifdef WLP_DEBUG printf("wlpprobe() calling ProbeIntel82593()\n");#endif if (ProbeIntel82593(is, IFTYPE_WAVELAN)) { printf("wlp%d: unable to probe I82593\n", sc->sc_unit); goto bad; } /* * Get the Modem configuration from the PSA */ { struct mem_desc oldmp; u_int32_t window; caddr_t attrmem;#ifdef WLP_DEBUG printf("wlpprobe() calling pccard_map_attr_mem()\n");#endif if(pccard_map_attr_mem(dp->slt, &oldmp, &window, &attrmem)) return ENOMEM;#ifdef WLP_DEBUG printf("wlpprobe() calling wlp_set_wavelan_conf()\n");#endif wlp_set_wavelan_conf(sc, attrmem);#ifdef WLP_DEBUG printf("wlpprobe() calling pccard_unmap_attr_mem()\n");#endif if(pccard_unmap_attr_mem(dp->slt, &oldmp, window)) return EINVAL;#ifdef WLP_DEBUG printf("wlpprobe() done with PSA\n");#endif } bcopy(sc->sc_conf.umac_address, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN); sc->sc_nwid[0] = sc->sc_conf.nwid[0]; sc->sc_nwid[1] = sc->sc_conf.nwid[1]; sc->sc_sigthresh = 0x03; /* Default Value */ if ((sc->sc_conf.config_status & 0x01) == 0) { printf("wlp%d: config status not set\n", sc->sc_unit);#if 0 /* some wavelan cards that are properly configured don't have the config_status bit set */ goto bad;#endif }#ifdef WLP_DEBUG printf("wlpprobe() resetting DMA...\n");#endif /* * (1) Reset RX_DMA, TX_DMA and PWR STAT * (2) Check to see that the modem is present by reading the NO_CLK bit. */ IOWrite1(0x01, P1_RX_DMA_RESET | P1_TX_DMA_RESET | P1_PWR_STAT); DELAY(DELAYCONST); IOWrite1(0x01, P1_PWR_STAT); DELAY(DELAYCONST); if (IORead1(0x01) & P1_PWR_STAT) { printf("wlp%d: modem not connected\n", sc->sc_unit); goto bad; }#ifdef WLP_STATS i82593_reset_stats(sc);#endif#ifdef WLP_DEBUG printf("wlp%d: EXIT wlpprobe() successful...\n", is->id_unit);#endif return WLP_IOSIZE;bad:#ifdef WLP_DEBUG printf("wlp%d: EXIT wlpprobe() error...\n", is->id_unit);#endif return 0; /* Error */}intwlpconfig(sc) struct wlp_softc *sc;{ struct ifnet *ifp = &sc->sc_ac.ac_if; u_int8_t val; u_int8_t status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -