diff options
Diffstat (limited to 'sys/dev/ic/an.c')
-rw-r--r-- | sys/dev/ic/an.c | 262 |
1 files changed, 160 insertions, 102 deletions
diff --git a/sys/dev/ic/an.c b/sys/dev/ic/an.c index 80b4820cf92..7a10311b013 100644 --- a/sys/dev/ic/an.c +++ b/sys/dev/ic/an.c @@ -1,4 +1,4 @@ -/* $OpenBSD: an.c,v 1.17 2001/06/23 23:36:02 mickey Exp $ */ +/* $OpenBSD: an.c,v 1.18 2001/06/25 21:11:16 mickey Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -163,6 +163,13 @@ void an_cache_store __P((struct an_softc *, struct ether_header *, struct mbuf *, unsigned short)); #endif +static __inline void +an_swap16(u_int16_t *p, int cnt) +{ + for (; cnt--; p++) + *p = swap16(*p); +} + int an_attach(sc) struct an_softc *sc; @@ -321,14 +328,13 @@ an_rxeof(sc) } /* Check for insane frame length */ - if (rx_frame_802_3.an_rx_802_3_payload_len > MCLBYTES) { + if (letoh16(rx_frame_802_3.an_rx_802_3_payload_len) > MCLBYTES) { ifp->if_ierrors++; return; } m->m_pkthdr.len = m->m_len = - rx_frame_802_3.an_rx_802_3_payload_len + 12; - + letoh16(rx_frame_802_3.an_rx_802_3_payload_len) + 12; bcopy((char *)&rx_frame_802_3.an_rx_dst_addr, (char *)&eh->ether_dhost, ETHER_ADDR_LEN); @@ -337,8 +343,7 @@ an_rxeof(sc) /* in mbuf header type is just before payload */ error = an_read_data(sc, id, 0x44, (caddr_t)&(eh->ether_type), - rx_frame_802_3.an_rx_802_3_payload_len); - + letoh16(rx_frame_802_3.an_rx_802_3_payload_len)); if (error) { m_freem(m); ifp->if_ierrors++; @@ -362,11 +367,11 @@ an_rxeof(sc) void an_txeof(sc, status) - struct an_softc *sc; - int status; + struct an_softc *sc; + int status; { - struct ifnet *ifp; - int id; + struct ifnet *ifp; + int id; ifp = &sc->arpcom.ac_if; @@ -375,9 +380,9 @@ an_txeof(sc, status) id = CSR_READ_2(sc, AN_TX_CMP_FID); - if (status & AN_EV_TX_EXC) { + if (status & AN_EV_TX_EXC) ifp->if_oerrors++; - } else + else ifp->if_opackets++; if (id != sc->an_rdata.an_tx_ring[sc->an_rdata.an_tx_cons]) @@ -576,8 +581,8 @@ an_read_record(sc, ltv) struct an_softc *sc; struct an_ltv_gen *ltv; { - u_int16_t *ptr; - int i, len; + u_int16_t *ptr, len; + int i; if (ltv->an_len == 0 || ltv->an_type == 0) return(EINVAL); @@ -612,10 +617,51 @@ an_read_record(sc, ltv) ltv->an_len = len; /* Now read the data. */ - ptr = <v->an_val; + ptr = ltv->an_val; for (i = 0; i < (ltv->an_len - 1) >> 1; i++) ptr[i] = CSR_READ_2(sc, AN_DATA1); +#if BYTE_ORDER == BIG_ENDIAN + switch (ltv->an_type) { + case AN_RID_GENCONFIG: + an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ + an_swap16(<v->an_val[63], 8); /* an_nodename */ + break; + case AN_RID_SSIDLIST: + an_swap16(<v->an_val[1], 16); /* an_ssid1 */ + an_swap16(<v->an_val[18], 16); /* an_ssid2 */ + an_swap16(<v->an_val[35], 16); /* an_ssid3 */ + break; + case AN_RID_APLIST: + an_swap16(ltv->an_val, 12); + break; + case AN_RID_DRVNAME: + an_swap16(ltv->an_val, 8); + break; + case AN_RID_CAPABILITIES: + an_swap16(ltv->an_val, 2); /* an_oui */ + an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ + an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ + break; + case AN_RID_STATUS: + an_swap16(<v->an_val[0], 3); /* an_macaddr */ + an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ + an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ + break; + case AN_RID_WEP_VOLATILE: + case AN_RID_WEP_PERMANENT: + an_swap16(<v->an_val[1], 3); /* an_mac_addr */ + an_swap16(<v->an_val[5], 6); + break; + case AN_RID_32BITS_CUM: + for (i = 0x60; i--; ) { + u_int16_t t = ltv->an_val[i * 2] ^ ltv->an_val[i * 2 + 1]; + ltv->an_val[i * 2] ^= t; + ltv->an_val[i * 2 + 1] ^= t; + } + break; + } +#endif return(0); } @@ -627,8 +673,8 @@ an_write_record(sc, ltv) struct an_softc *sc; struct an_ltv_gen *ltv; { - u_int16_t *ptr; - int i; + u_int16_t *ptr; + int i; if (an_cmd(sc, AN_CMD_ACCESS|AN_ACCESS_READ, ltv->an_type)) return(EIO); @@ -636,9 +682,44 @@ an_write_record(sc, ltv) if (an_seek(sc, ltv->an_type, 0, AN_BAP1)) return(EIO); +#if BYTE_ORDER == BIG_ENDIAN + switch (ltv->an_type) { + case AN_RID_GENCONFIG: + an_swap16(<v->an_val[4], 7); /* an_macaddr, an_rates */ + an_swap16(<v->an_val[63], 8); /* an_nodename */ + break; + case AN_RID_SSIDLIST: + an_swap16(<v->an_val[1], 16); /* an_ssid1 */ + an_swap16(<v->an_val[18], 16); /* an_ssid2 */ + an_swap16(<v->an_val[35], 16); /* an_ssid3 */ + break; + case AN_RID_APLIST: + an_swap16(ltv->an_val, 12); + break; + case AN_RID_DRVNAME: + an_swap16(ltv->an_val, 8); + break; + case AN_RID_CAPABILITIES: + an_swap16(ltv->an_val, 2); /* an_oui */ + an_swap16(<v->an_val[3], 34); /* an_manufname .. an_aironetaddr */ + an_swap16(<v->an_val[39], 8); /* an_callid .. an_tx_diversity */ + break; + case AN_RID_STATUS: + an_swap16(<v->an_val[0], 3); /* an_macaddr */ + an_swap16(<v->an_val[7], 36); /* an_ssid .. an_prev_bssid3 */ + an_swap16(<v->an_val[0x74/2], 2); /* an_ap_ip_addr */ + break; + case AN_RID_WEP_VOLATILE: + case AN_RID_WEP_PERMANENT: + an_swap16(<v->an_val[1], 3); /* an_mac_addr */ + an_swap16(<v->an_val[5], 6); + break; + } +#endif + CSR_WRITE_2(sc, AN_DATA1, ltv->an_len); - ptr = <v->an_val; + ptr = ltv->an_val; for (i = 0; i < (ltv->an_len - 1) >> 1; i++) CSR_WRITE_2(sc, AN_DATA1, ptr[i]); @@ -668,7 +749,7 @@ an_seek(sc, id, off, chan) default: printf("%s: invalid data path: %x\n", sc->sc_dev.dv_xname, chan); - return(EIO); + return (EIO); } CSR_WRITE_2(sc, selreg, id); @@ -682,7 +763,7 @@ an_seek(sc, id, off, chan) if (i <= 0) return(ETIMEDOUT); - return(0); + return (0); } int @@ -692,25 +773,15 @@ an_read_data(sc, id, off, buf, len) caddr_t buf; int len; { - int i; - u_int16_t *ptr; - u_int8_t *ptr2; - - if (off != -1) { - if (an_seek(sc, id, off, AN_BAP1)) - return(EIO); - } + if (off != -1 && an_seek(sc, id, off, AN_BAP1)) + return(EIO); - ptr = (u_int16_t *)buf; - for (i = 0; i < len / 2; i++) - ptr[i] = CSR_READ_2(sc, AN_DATA1); - i*=2; - if (i<len){ - ptr2 = (u_int8_t *)buf; - ptr2[i] = CSR_READ_1(sc, AN_DATA1); - } + bus_space_read_raw_multi_2(sc->an_btag, sc->an_bhandle, + AN_DATA1, buf, len & ~1); + if (len & 1) + ((u_int8_t *)buf)[len - 1] = CSR_READ_1(sc, AN_DATA1); - return(0); + return (0); } int @@ -720,25 +791,15 @@ an_write_data(sc, id, off, buf, len) caddr_t buf; int len; { - int i; - u_int16_t *ptr; - u_int8_t *ptr2; - - if (off != -1) { - if (an_seek(sc, id, off, AN_BAP0)) - return(EIO); - } + if (off != -1 && an_seek(sc, id, off, AN_BAP0)) + return(EIO); - ptr = (u_int16_t *)buf; - for (i = 0; i < (len / 2); i++) - CSR_WRITE_2(sc, AN_DATA0, ptr[i]); - i*=2; - if (i<len){ - ptr2 = (u_int8_t *)buf; - CSR_WRITE_1(sc, AN_DATA0, ptr2[i]); - } + bus_space_write_raw_multi_2(sc->an_btag, sc->an_bhandle, + AN_DATA0, buf, len & ~1); + if (len & 1) + CSR_WRITE_1(sc, AN_DATA0, ((u_int8_t *)buf)[len - 1]); - return(0); + return (0); } /* @@ -773,8 +834,9 @@ an_alloc_nicmem(sc, len, id) if (an_seek(sc, *id, 0, AN_BAP0)) return(EIO); - for (i = 0; i < len / 2; i++) - CSR_WRITE_2(sc, AN_DATA0, 0); + bus_space_set_multi_2(sc->an_btag, sc->an_bhandle, + AN_DATA0, 0, len / 2); + CSR_WRITE_1(sc, AN_DATA0, 0); return(0); } @@ -820,7 +882,7 @@ an_setdef(sc, areq) break; case AN_RID_TX_SPEED: sp = (struct an_ltv_gen *)areq; - sc->an_tx_rate = sp->an_val; + sc->an_tx_rate = sp->an_val[0]; break; case AN_RID_WEP_VOLATILE: /* Disable the MAC */ @@ -865,13 +927,14 @@ an_promisc(sc, promisc) struct an_softc *sc; int promisc; { + struct an_ltv_genconfig genconf; + /* Disable the MAC. */ an_cmd(sc, AN_CMD_DISABLE, 0); /* Set RX mode. */ if (promisc && - !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) - ) { + !(sc->an_config.an_rxmode & AN_RXMODE_LAN_MONITOR_CURBSS) ) { sc->an_rxmode = sc->an_config.an_rxmode; sc->an_config.an_rxmode |= AN_RXMODE_LAN_MONITOR_CURBSS; @@ -880,9 +943,10 @@ an_promisc(sc, promisc) } /* Transfer the configuration to the NIC */ - sc->an_config.an_len = sizeof(struct an_ltv_genconfig); - sc->an_config.an_type = AN_RID_GENCONFIG; - if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) { + genconf = sc->an_config; + genconf.an_len = sizeof(struct an_ltv_genconfig); + genconf.an_type = AN_RID_GENCONFIG; + if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { printf("%s: failed to set configuration\n", sc->sc_dev.dv_xname); return; @@ -1035,7 +1099,10 @@ an_init(sc) struct an_softc *sc; { struct ifnet *ifp = &sc->arpcom.ac_if; - int s; + struct an_ltv_ssidlist ssid; + struct an_ltv_aplist aplist; + struct an_ltv_genconfig genconf; + int s; if (sc->an_gone) return; @@ -1074,27 +1141,30 @@ an_init(sc) sc->an_rxmode = sc->an_config.an_rxmode; /* Set the ssid list */ - sc->an_ssidlist.an_type = AN_RID_SSIDLIST; - sc->an_ssidlist.an_len = sizeof(struct an_ltv_ssidlist); - if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_ssidlist)) { + ssid = sc->an_ssidlist; + ssid.an_type = AN_RID_SSIDLIST; + ssid.an_len = sizeof(struct an_ltv_ssidlist); + if (an_write_record(sc, (struct an_ltv_gen *)&ssid)) { printf("%s: failed to set ssid list\n", sc->sc_dev.dv_xname); splx(s); return; } /* Set the AP list */ - sc->an_aplist.an_type = AN_RID_APLIST; - sc->an_aplist.an_len = sizeof(struct an_ltv_aplist); - if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_aplist)) { + aplist = sc->an_aplist; + aplist.an_type = AN_RID_APLIST; + aplist.an_len = sizeof(struct an_ltv_aplist); + if (an_write_record(sc, (struct an_ltv_gen *)&aplist)) { printf("%s: failed to set AP list\n", sc->sc_dev.dv_xname); splx(s); return; } /* Set the configuration in the NIC */ - sc->an_config.an_len = sizeof(struct an_ltv_genconfig); - sc->an_config.an_type = AN_RID_GENCONFIG; - if (an_write_record(sc, (struct an_ltv_gen *)&sc->an_config)) { + genconf = sc->an_config; + genconf.an_len = sizeof(struct an_ltv_genconfig); + genconf.an_type = AN_RID_GENCONFIG; + if (an_write_record(sc, (struct an_ltv_gen *)&genconf)) { printf("%s: failed to set configuration\n", sc->sc_dev.dv_xname); splx(s); @@ -1127,6 +1197,7 @@ an_start(ifp) struct mbuf *m0 = NULL; struct an_txframe_802_3 tx_frame_802_3; struct ether_header *eh; + u_int16_t len; int id; int idx; unsigned char txcontrol; @@ -1158,11 +1229,10 @@ an_start(ifp) bcopy((char *)&eh->ether_shost, (char *)&tx_frame_802_3.an_tx_src_addr, ETHER_ADDR_LEN); - tx_frame_802_3.an_tx_802_3_payload_len = - m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ + len = m0->m_pkthdr.len - 12; /* minus src/dest mac & type */ + tx_frame_802_3.an_tx_802_3_payload_len = htole16(len); - m_copydata(m0, sizeof(struct ether_header) - 2 , - tx_frame_802_3.an_tx_802_3_payload_len, + m_copydata(m0, sizeof(struct ether_header) - 2, len, (caddr_t)&sc->an_txbuf); txcontrol=AN_TXCTL_8023; @@ -1175,8 +1245,7 @@ an_start(ifp) sizeof(struct an_txframe_802_3)); /* in mbuf header type is just before payload */ - an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, - tx_frame_802_3.an_tx_802_3_payload_len); + an_write_data(sc, id, 0x44, (caddr_t)&sc->an_txbuf, len); /* * If there's a BPF listner, bounce a copy of @@ -1339,59 +1408,50 @@ an_cache_store (sc, eh, m, rx_quality) * keep multicast only. */ - if ((ntohs(eh->ether_type) == 0x800)) { + if ((ntohs(eh->ether_type) == 0x800)) saanp = 1; - } /* filter for ip packets only */ - if (sc->an_cache_iponly && !saanp) { + if (sc->an_cache_iponly && !saanp) return; - } - /* filter for broadcast/multicast only - */ - if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) { + /* filter for broadcast/multicast only */ + if (sc->an_cache_mcastonly && ((eh->ether_dhost[0] & 1) == 0)) return; - } #ifdef SIGDEBUG printf("an: q value %x (MSB=0x%x, LSB=0x%x) \n", rx_quality & 0xffff, rx_quality >> 8, rx_quality & 0xff); #endif - /* find the ip header. we want to store the ip_src - * address. - */ - if (saanp) { + /* find the ip header. we want to store the ip_src address */ + if (saanp) ip = (struct ip *)(mtod(m, char *) + sizeof(struct ether_header)); - } /* do a linear search for a matching MAC address * in the cache table * . MAC address is 6 bytes, * . var w_nextitem holds total number of entries already cached */ - for(i = 0; i < sc->an_nextitem; i++) { - if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6)) { + for(i = 0; i < sc->an_nextitem; i++) + if (!bcmp(eh->ether_shost , sc->an_sigcache[i].macsrc, 6)) /* Match!, * so we already have this entry, update the data */ break; - } - } /* did we find a matching mac address? * if yes, then overwrite a previously existing cache entry */ - if (i < sc->an_nextitem ) { + if (i < sc->an_nextitem ) cache_slot = i; - } + /* else, have a new address entry,so * add this new entry, * if table full, then we need to replace LRU entry */ - else { + else { /* check for space in cache table * note: an_nextitem also holds number of entries @@ -1406,9 +1466,8 @@ an_cache_store (sc, eh, m, rx_quality) * and "zap" the next entry */ else { - if (wrapindex == MAXANCACHE) { + if (wrapindex == MAXANCACHE) wrapindex = 0; - } cache_slot = wrapindex++; } } @@ -1428,9 +1487,8 @@ an_cache_store (sc, eh, m, rx_quality) * .mac src * .signal, etc. */ - if (saanp) { + if (saanp) sc->an_sigcache[cache_slot].ipsrc = ip->ip_src.s_addr; - } bcopy( eh->ether_shost, sc->an_sigcache[cache_slot].macsrc, 6); sc->an_sigcache[cache_slot].signal = rx_quality; |