From aeccadaee28c4278c731494f4d6c2452472ab331 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Jun 2006 19:59:53 +0000 Subject: remove the wl.o build from the kernel patch and move the driver along with wl, nas and wlc into packages/broadcom-wl git-svn-id: svn://svn.openwrt.org/openwrt/branches/buildroot-ng/openwrt@4009 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- package/broadcom-wl/src/kmod/Makefile | 32 + package/broadcom-wl/src/kmod/bcmip.h | 101 ++ package/broadcom-wl/src/kmod/bcmutils.c | 857 ++++++++++++ package/broadcom-wl/src/kmod/hnddma.c | 1157 ++++++++++++++++ package/broadcom-wl/src/kmod/hnddma.h | 156 +++ package/broadcom-wl/src/kmod/linux_osl.c | 269 ++++ package/broadcom-wl/src/kmod/linux_osl.h | 171 +++ package/broadcom-wl/src/kmod/patchtable.pl | 54 + package/broadcom-wl/src/kmod/pktq.h | 97 ++ package/broadcom-wl/src/kmod/sbhnddma.h | 284 ++++ package/broadcom-wl/src/wlc/Makefile | 9 + package/broadcom-wl/src/wlc/include/bcmdefs.h | 106 ++ package/broadcom-wl/src/wlc/include/bcmutils.h | 258 ++++ package/broadcom-wl/src/wlc/include/proto/802.11.h | 1258 ++++++++++++++++++ package/broadcom-wl/src/wlc/include/proto/bcmeth.h | 101 ++ .../broadcom-wl/src/wlc/include/proto/bcmevent.h | 152 +++ .../broadcom-wl/src/wlc/include/proto/ethernet.h | 165 +++ package/broadcom-wl/src/wlc/include/proto/wpa.h | 148 +++ package/broadcom-wl/src/wlc/include/typedefs.h | 230 ++++ package/broadcom-wl/src/wlc/include/wlioctl.h | 1384 ++++++++++++++++++++ package/broadcom-wl/src/wlc/include/wlutils.h | 102 ++ package/broadcom-wl/src/wlc/ioctl.c | 298 +++++ package/broadcom-wl/src/wlc/wlc.c | 1138 ++++++++++++++++ 23 files changed, 8527 insertions(+) create mode 100644 package/broadcom-wl/src/kmod/Makefile create mode 100644 package/broadcom-wl/src/kmod/bcmip.h create mode 100644 package/broadcom-wl/src/kmod/bcmutils.c create mode 100644 package/broadcom-wl/src/kmod/hnddma.c create mode 100644 package/broadcom-wl/src/kmod/hnddma.h create mode 100644 package/broadcom-wl/src/kmod/linux_osl.c create mode 100644 package/broadcom-wl/src/kmod/linux_osl.h create mode 100644 package/broadcom-wl/src/kmod/patchtable.pl create mode 100644 package/broadcom-wl/src/kmod/pktq.h create mode 100644 package/broadcom-wl/src/kmod/sbhnddma.h create mode 100644 package/broadcom-wl/src/wlc/Makefile create mode 100644 package/broadcom-wl/src/wlc/include/bcmdefs.h create mode 100644 package/broadcom-wl/src/wlc/include/bcmutils.h create mode 100644 package/broadcom-wl/src/wlc/include/proto/802.11.h create mode 100644 package/broadcom-wl/src/wlc/include/proto/bcmeth.h create mode 100644 package/broadcom-wl/src/wlc/include/proto/bcmevent.h create mode 100644 package/broadcom-wl/src/wlc/include/proto/ethernet.h create mode 100644 package/broadcom-wl/src/wlc/include/proto/wpa.h create mode 100644 package/broadcom-wl/src/wlc/include/typedefs.h create mode 100644 package/broadcom-wl/src/wlc/include/wlioctl.h create mode 100644 package/broadcom-wl/src/wlc/include/wlutils.h create mode 100644 package/broadcom-wl/src/wlc/ioctl.c create mode 100644 package/broadcom-wl/src/wlc/wlc.c (limited to 'package/broadcom-wl/src') diff --git a/package/broadcom-wl/src/kmod/Makefile b/package/broadcom-wl/src/kmod/Makefile new file mode 100644 index 0000000000..672384035f --- /dev/null +++ b/package/broadcom-wl/src/kmod/Makefile @@ -0,0 +1,32 @@ +# +# Makefile for the Broadcom wl driver +# +# Copyright 2004, Broadcom Corporation +# All Rights Reserved. +# +# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY +# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM +# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS +# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. +# +# $Id: Makefile,v 1.2 2005/03/29 03:32:18 mbm Exp $ + +EXTRA_CFLAGS += -I$(TOPDIR)/arch/mips/bcm947xx/include -DBCMDRIVER + +O_TARGET := wl_link.o + +obj-y := wl_mod.o +obj-y += bcmutils.o hnddma.o linux_osl.o + +obj-m := $(O_TARGET) + +wl_mod.o: wl_apsta.o + sed -e 's,eth%d,wl%d\x00,g' < $< > $@ + +wl.o: wl_link.o + $(OBJDUMP) -d $< | perl patchtable.pl > patchtable.bin + cat wl_link.o patchtable.bin > $@ + +modules: wl.o + +include $(TOPDIR)/Rules.make diff --git a/package/broadcom-wl/src/kmod/bcmip.h b/package/broadcom-wl/src/kmod/bcmip.h new file mode 100644 index 0000000000..423a0e5c5c --- /dev/null +++ b/package/broadcom-wl/src/kmod/bcmip.h @@ -0,0 +1,101 @@ +/* + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * Fundamental constants relating to IP Protocol + * + * $Id: bcmip.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $ + */ + +#ifndef _bcmip_h_ +#define _bcmip_h_ + +/* IPV4 and IPV6 common */ +#define IP_VER_OFFSET 0x0 /* offset to version field */ +#define IP_VER_MASK 0xf0 /* version mask */ +#define IP_VER_SHIFT 4 /* version shift */ +#define IP_VER_4 4 /* version number for IPV4 */ +#define IP_VER_6 6 /* version number for IPV6 */ + +#define IP_VER(ip_body) \ + ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) + +#define IP_PROT_ICMP 0x1 /* ICMP protocol */ +#define IP_PROT_TCP 0x6 /* TCP protocol */ +#define IP_PROT_UDP 0x11 /* UDP protocol type */ + +/* IPV4 field offsets */ +#define IPV4_VER_HL_OFFSET 0 /* version and ihl byte offset */ +#define IPV4_TOS_OFFSET 1 /* type of service offset */ +#define IPV4_PROT_OFFSET 9 /* protocol type offset */ +#define IPV4_CHKSUM_OFFSET 10 /* IP header checksum offset */ +#define IPV4_SRC_IP_OFFSET 12 /* src IP addr offset */ +#define IPV4_DEST_IP_OFFSET 16 /* dest IP addr offset */ + +/* IPV4 field decodes */ +#define IPV4_VER_MASK 0xf0 /* IPV4 version mask */ +#define IPV4_VER_SHIFT 4 /* IPV4 version shift */ + +#define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ +#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) + +#define IPV4_ADDR_LEN 4 /* IPV4 address length */ + +#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ + ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) + +#define IPV4_TOS_DSCP_MASK 0xfc /* DiffServ codepoint mask */ +#define IPV4_TOS_DSCP_SHIFT 2 /* DiffServ codepoint shift */ + +#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) + +#define IPV4_TOS_PREC_MASK 0xe0 /* Historical precedence mask */ +#define IPV4_TOS_PREC_SHIFT 5 /* Historical precedence shift */ + +#define IPV4_TOS_LOWDELAY 0x10 /* Lowest delay requested */ +#define IPV4_TOS_THROUGHPUT 0x8 /* Best throughput requested */ +#define IPV4_TOS_RELIABILITY 0x4 /* Most reliable delivery requested */ + +#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) + +#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ + +/* IPV6 field offsets */ +#define IPV6_PAYLOAD_LEN_OFFSET 4 /* payload length offset */ +#define IPV6_NEXT_HDR_OFFSET 6 /* next header/protocol offset */ +#define IPV6_HOP_LIMIT_OFFSET 7 /* hop limit offset */ +#define IPV6_SRC_IP_OFFSET 8 /* src IP addr offset */ +#define IPV6_DEST_IP_OFFSET 24 /* dst IP addr offset */ + +/* IPV6 field decodes */ +#define IPV6_TRAFFIC_CLASS(ipv6_body) \ + (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ + ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) + +#define IPV6_FLOW_LABEL(ipv6_body) \ + (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ + (((uint8 *)(ipv6_body))[2] << 8) | \ + (((uint8 *)(ipv6_body))[3])) + +#define IPV6_PAYLOAD_LEN(ipv6_body) \ + ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ + ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) + +#define IPV6_NEXT_HDR(ipv6_body) \ + (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) + +#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) + +#define IPV6_ADDR_LEN 16 /* IPV6 address length */ + +/* IPV4 TOS or IPV6 Traffic Classifier or 0 */ +#define IP_TOS(ip_body) \ + (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ + IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) + +#endif /* _bcmip_h_ */ diff --git a/package/broadcom-wl/src/kmod/bcmutils.c b/package/broadcom-wl/src/kmod/bcmutils.c new file mode 100644 index 0000000000..c264ea500b --- /dev/null +++ b/package/broadcom-wl/src/kmod/bcmutils.c @@ -0,0 +1,857 @@ +/* + * Misc useful OS-independent routines. + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: bcmutils.c,v 1.1.1.12 2006/02/27 03:43:16 honor Exp $ + */ + +#include +#include +#include +#include +#include "linux_osl.h" +#include "pktq.h" +#include +#include +#include +#include +#include +#include "bcmip.h" + +#define ETHER_TYPE_8021Q 0x8100 +#define ETHER_TYPE_IP 0x0800 +#define VLAN_PRI_SHIFT 13 +#define VLAN_PRI_MASK 7 + + +struct ether_header { + uint8 ether_dhost[6]; + uint8 ether_shost[6]; + uint16 ether_type; +} __attribute__((packed)); + + +struct ethervlan_header { + uint8 ether_dhost[6]; + uint8 ether_shost[6]; + uint16 vlan_type; /* 0x8100 */ + uint16 vlan_tag; /* priority, cfi and vid */ + uint16 ether_type; +}; + +/* copy a pkt buffer chain into a buffer */ +uint +pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) +{ + uint n, ret = 0; + + if (len < 0) + len = 4096; /* "infinite" */ + + /* skip 'offset' bytes */ + for (; p && offset; p = PKTNEXT(osh, p)) { + if (offset < (uint)PKTLEN(osh, p)) + break; + offset -= PKTLEN(osh, p); + } + + if (!p) + return 0; + + /* copy the data */ + for (; p && len; p = PKTNEXT(osh, p)) { + n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); + bcopy(PKTDATA(osh, p) + offset, buf, n); + buf += n; + len -= n; + ret += n; + offset = 0; + } + + return ret; +} + +/* return total length of buffer chain */ +uint +pkttotlen(osl_t *osh, void *p) +{ + uint total; + + total = 0; + for (; p; p = PKTNEXT(osh, p)) + total += PKTLEN(osh, p); + return (total); +} + +/* return the last buffer of chained pkt */ +void * +pktlast(osl_t *osh, void *p) +{ + for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) + ; + + return (p); +} + + +/* + * osl multiple-precedence packet queue + * hi_prec is always >= the number of the highest non-empty queue + */ +void * +pktq_penq(struct pktq *pq, int prec, void *p) +{ + struct pktq_prec *q; + + ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + + ASSERT(!pktq_full(pq)); + ASSERT(!pktq_pfull(pq, prec)); + + q = &pq->q[prec]; + + if (q->head) + PKTSETLINK(q->tail, p); + else + q->head = p; + + q->tail = p; + q->len++; + + pq->len++; + + if (pq->hi_prec < prec) + pq->hi_prec = (uint8)prec; + + return p; +} + +void * +pktq_penq_head(struct pktq *pq, int prec, void *p) +{ + struct pktq_prec *q; + + ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + + ASSERT(!pktq_full(pq)); + ASSERT(!pktq_pfull(pq, prec)); + + q = &pq->q[prec]; + + if (q->head == NULL) + q->tail = p; + + PKTSETLINK(p, q->head); + q->head = p; + q->len++; + + pq->len++; + + if (pq->hi_prec < prec) + pq->hi_prec = (uint8)prec; + + return p; +} + +void * +pktq_pdeq(struct pktq *pq, int prec) +{ + struct pktq_prec *q; + void *p; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + return NULL; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->len--; + + pq->len--; + + PKTSETLINK(p, NULL); + + return p; +} + +void * +pktq_pdeq_tail(struct pktq *pq, int prec) +{ + struct pktq_prec *q; + void *p, *prev; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + return NULL; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->len--; + + pq->len--; + + return p; +} + +void +pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir) +{ + struct pktq_prec *q; + void *p; + + q = &pq->q[prec]; + p = q->head; + while (p) { + q->head = PKTLINK(p); + PKTSETLINK(p, NULL); + PKTFREE(osh, p, dir); + q->len--; + pq->len--; + p = q->head; + } + ASSERT(q->len == 0); + q->tail = NULL; +} + +bool +pktq_pdel(struct pktq *pq, void *pktbuf, int prec) +{ + struct pktq_prec *q; + void *p; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + if (!pktbuf) + return FALSE; + + q = &pq->q[prec]; + + if (q->head == pktbuf) { + if ((q->head = PKTLINK(pktbuf)) == NULL) + q->tail = NULL; + } else { + for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) + ; + if (p == NULL) + return FALSE; + + PKTSETLINK(p, PKTLINK(pktbuf)); + if (q->tail == pktbuf) + q->tail = p; + } + + q->len--; + pq->len--; + PKTSETLINK(pktbuf, NULL); + return TRUE; +} + +void +pktq_init(struct pktq *pq, int num_prec, int max_len) +{ + int prec; + + ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); + + bzero(pq, sizeof(*pq)); + + pq->num_prec = (uint16)num_prec; + + pq->max = (uint16)max_len; + + for (prec = 0; prec < num_prec; prec++) + pq->q[prec].max = pq->max; +} + +void * +pktq_deq(struct pktq *pq, int *prec_out) +{ + struct pktq_prec *q; + void *p; + int prec; + + if (pq->len == 0) + return NULL; + + while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) + pq->hi_prec--; + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + return NULL; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->len--; + + pq->len--; + + if (prec_out) + *prec_out = prec; + + PKTSETLINK(p, NULL); + + return p; +} + +void * +pktq_deq_tail(struct pktq *pq, int *prec_out) +{ + struct pktq_prec *q; + void *p, *prev; + int prec; + + if (pq->len == 0) + return NULL; + + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + return NULL; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->len--; + + pq->len--; + + if (prec_out) + *prec_out = prec; + + PKTSETLINK(p, NULL); + + return p; +} + +void * +pktq_peek(struct pktq *pq, int *prec_out) +{ + int prec; + + if (pq->len == 0) + return NULL; + + while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) + pq->hi_prec--; + + if (prec_out) + *prec_out = prec; + + return (pq->q[prec].head); +} + +void * +pktq_peek_tail(struct pktq *pq, int *prec_out) +{ + int prec; + + if (pq->len == 0) + return NULL; + + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; + + if (prec_out) + *prec_out = prec; + + return (pq->q[prec].tail); +} + +void +pktq_flush(osl_t *osh, struct pktq *pq, bool dir) +{ + int prec; + for (prec = 0; prec < pq->num_prec; prec++) + pktq_pflush(osh, pq, prec, dir); + ASSERT(pq->len == 0); +} + +/* Return sum of lengths of a specific set of precedences */ +int +pktq_mlen(struct pktq *pq, uint prec_bmp) +{ + int prec, len; + + len = 0; + + for (prec = 0; prec <= pq->hi_prec; prec++) + if (prec_bmp & (1 << prec)) + len += pq->q[prec].len; + + return len; +} + +/* Priority dequeue from a specific set of precedences */ +void * +pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) +{ + struct pktq_prec *q; + void *p; + int prec; + + if (pq->len == 0) + return NULL; + + while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) + pq->hi_prec--; + + while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) + if (prec-- == 0) + return NULL; + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + return NULL; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->len--; + + if (prec_out) + *prec_out = prec; + + pq->len--; + + PKTSETLINK(p, NULL); + + return p; +} + +char* +bcmstrcat(char *dest, const char *src) +{ + strcpy(&dest[strlen(dest)], src); + return (dest); +} + +char* +bcm_ether_ntoa(struct ether_addr *ea, char *buf) +{ + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff, + ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff); + return (buf); +} + +/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ +int +bcm_ether_atoe(char *p, struct ether_addr *ea) +{ + int i = 0; + + for (;;) { + ea->octet[i++] = (char) bcm_strtoul(p, &p, 16); + if (!*p++ || i == 6) + break; + } + + return (i == 6); +} + +/* Takes an Ethernet frame and sets out-of-bound PKTPRIO + * Also updates the inplace vlan tag if requested + */ +void +pktsetprio(void *pkt, bool update_vtag) +{ + struct ether_header *eh; + struct ethervlan_header *evh; + uint8 *pktdata; + int priority = 0; + + pktdata = (uint8 *) PKTDATA(NULL, pkt); + ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); + + eh = (struct ether_header *) pktdata; + + if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { + uint16 vlan_tag; + int vlan_prio, dscp_prio = 0; + + evh = (struct ethervlan_header *)eh; + + vlan_tag = ntoh16(evh->vlan_tag); + vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; + + if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { + uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); + uint8 tos_tc = IP_TOS(ip_body); + dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); + } + + /* DSCP priority gets precedence over 802.1P (vlan tag) */ + priority = (dscp_prio != 0) ? dscp_prio : vlan_prio; + + /* + * If the DSCP priority is not the same as the VLAN priority, + * then overwrite the priority field in the vlan tag, with the + * DSCP priority value. This is required for Linux APs because + * the VLAN driver on Linux, overwrites the skb->priority field + * with the priority value in the vlan tag + */ + if (update_vtag && (priority != vlan_prio)) { + vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); + vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; + evh->vlan_tag = hton16(vlan_tag); + } + } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { + uint8 *ip_body = pktdata + sizeof(struct ether_header); + uint8 tos_tc = IP_TOS(ip_body); + priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); + } + + ASSERT(priority >= 0 && priority <= MAXPRIO); + PKTSETPRIO(pkt, priority); +} + +static char bcm_undeferrstr[BCME_STRLEN]; + +static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; + +/* Convert the Error codes into related Error strings */ +const char * +bcmerrorstr(int bcmerror) +{ + int abs_bcmerror; + + abs_bcmerror = ABS(bcmerror); + + /* check if someone added a bcmerror code but forgot to add errorstring */ + ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); + if ((bcmerror > 0) || (abs_bcmerror > ABS(BCME_LAST))) { + sprintf(bcm_undeferrstr, "undefined Error %d", bcmerror); + return bcm_undeferrstr; + } + + ASSERT((strlen((char*)bcmerrorstrtable[abs_bcmerror])) < BCME_STRLEN); + + return bcmerrorstrtable[abs_bcmerror]; +} + + +int +bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) +{ + int bcmerror = 0; + + /* length check on io buf */ + switch (vi->type) { + case IOVT_BOOL: + case IOVT_INT8: + case IOVT_INT16: + case IOVT_INT32: + case IOVT_UINT8: + case IOVT_UINT16: + case IOVT_UINT32: + /* all integers are int32 sized args at the ioctl interface */ + if (len < (int)sizeof(int)) { + bcmerror = BCME_BUFTOOSHORT; + } + break; + + case IOVT_BUFFER: + /* buffer must meet minimum length requirement */ + if (len < vi->minlen) { + bcmerror = BCME_BUFTOOSHORT; + } + break; + + case IOVT_VOID: + if (!set) { + /* Cannot return nil... */ + bcmerror = BCME_UNSUPPORTED; + } else if (len) { + /* Set is an action w/o parameters */ + bcmerror = BCME_BUFTOOLONG; + } + break; + + default: + /* unknown type for length check in iovar info */ + ASSERT(0); + bcmerror = BCME_UNSUPPORTED; + } + + return bcmerror; +} + +#define CRC_INNER_LOOP(n, c, x) \ + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] + +static uint32 crc32_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + +uint32 +hndcrc32( + uint8 *pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint32 crc /* either CRC32_INIT_VALUE or previous return value */ +) +{ + uint8 *pend; +#ifdef __mips__ + uint8 tmp[4]; + ulong *tptr = (ulong *)tmp; + + /* in case the beginning of the buffer isn't aligned */ + pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc); + nbytes -= (pend - pdata); + while (pdata < pend) + CRC_INNER_LOOP(32, crc, *pdata++); + + /* handle bulk of data as 32-bit words */ + pend = pdata + (nbytes & 0xfffffffc); + while (pdata < pend) { + *tptr = *(ulong *)pdata; + pdata += sizeof(ulong *); + CRC_INNER_LOOP(32, crc, tmp[0]); + CRC_INNER_LOOP(32, crc, tmp[1]); + CRC_INNER_LOOP(32, crc, tmp[2]); + CRC_INNER_LOOP(32, crc, tmp[3]); + } + + /* 1-3 bytes at end of buffer */ + pend = pdata + (nbytes & 0x03); + while (pdata < pend) + CRC_INNER_LOOP(32, crc, *pdata++); +#else + pend = pdata + nbytes; + while (pdata < pend) + CRC_INNER_LOOP(32, crc, *pdata++); +#endif /* __mips__ */ + + return crc; +} + + +/* + * Advance from the current 1-byte tag/1-byte length/variable-length value + * triple, to the next, returning a pointer to the next. + * If the current or next TLV is invalid (does not fit in given buffer length), + * NULL is returned. + * *buflen is not modified if the TLV elt parameter is invalid, or is decremented + * by the TLV paramter's length if it is valid. + */ +bcm_tlv_t * +bcm_next_tlv(bcm_tlv_t *elt, int *buflen) +{ + int len; + + /* validate current elt */ + if (!bcm_valid_tlv(elt, *buflen)) + return NULL; + + /* advance to next elt */ + len = elt->len; + elt = (bcm_tlv_t*)(elt->data + len); + *buflen -= (2 + len); + + /* validate next elt */ + if (!bcm_valid_tlv(elt, *buflen)) + return NULL; + + return elt; +} + +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + */ +bcm_tlv_t * +bcm_parse_tlvs(void *buf, int buflen, uint key) +{ + bcm_tlv_t *elt; + int totlen; + + elt = (bcm_tlv_t*)buf; + totlen = buflen; + + /* find tagged parameter */ + while (totlen >= 2) { + int len = elt->len; + + /* validate remaining totlen */ + if ((elt->id == key) && (totlen >= (len + 2))) + return (elt); + + elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); + totlen -= (len + 2); + } + + return NULL; +} + +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag. Stop parsing when we see an element whose ID is greater + * than the target key. + */ +bcm_tlv_t * +bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) +{ + bcm_tlv_t *elt; + int totlen; + + elt = (bcm_tlv_t*)buf; + totlen = buflen; + + /* find tagged parameter */ + while (totlen >= 2) { + uint id = elt->id; + int len = elt->len; + + /* Punt if we start seeing IDs > than target key */ + if (id > key) + return (NULL); + + /* validate remaining totlen */ + if ((id == key) && (totlen >= (len + 2))) + return (elt); + + elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); + totlen -= (len + 2); + } + return NULL; +} + + +/* Initialization of bcmstrbuf structure */ +void +bcm_binit(struct bcmstrbuf *b, char *buf, uint size) +{ + b->origsize = b->size = size; + b->origbuf = b->buf = buf; +} + +/* Buffer sprintf wrapper to guard against buffer overflow */ +int +bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) +{ + va_list ap; + int r; + + va_start(ap, fmt); + r = vsnprintf(b->buf, b->size, fmt, ap); + + /* Non Ansi C99 compliant returns -1, + * Ansi compliant return r >= b->size, + * bcmstdlib returns 0, handle all + */ + if ((r == -1) || (r >= (int)b->size) || (r == 0)) + { + b->size = 0; + } + else + { + b->size -= r; + b->buf += r; + } + + va_end(ap); + + return r; +} diff --git a/package/broadcom-wl/src/kmod/hnddma.c b/package/broadcom-wl/src/kmod/hnddma.c new file mode 100644 index 0000000000..4336560888 --- /dev/null +++ b/package/broadcom-wl/src/kmod/hnddma.c @@ -0,0 +1,1157 @@ +/* + * Generic Broadcom Home Networking Division (HND) DMA module. + * This supports the following chips: BCM42xx, 44xx, 47xx . + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: hnddma.c,v 1.11 2006/04/08 07:12:42 honor Exp $ + */ + +#include +#include +#include +#include "linux_osl.h" +#include +#include +#include +#include +#include + +#include "sbhnddma.h" +#include "hnddma.h" + +/* debug/trace */ +#define DMA_ERROR(args) +#define DMA_TRACE(args) + +/* default dma message level (if input msg_level pointer is null in dma_attach()) */ +static uint dma_msg_level = + 0; + +#define MAXNAMEL 8 /* 8 char names */ + +#define DI_INFO(dmah) (dma_info_t *)dmah + +/* dma engine software state */ +typedef struct dma_info { + struct hnddma_pub hnddma; /* exported structure, don't use hnddma_t, + * which could be const + */ + uint *msg_level; /* message level pointer */ + char name[MAXNAMEL]; /* callers name for diag msgs */ + + void *osh; /* os handle */ + sb_t *sbh; /* sb handle */ + + bool dma64; /* dma64 enabled */ + bool addrext; /* this dma engine supports DmaExtendedAddrChanges */ + + dma32regs_t *d32txregs; /* 32 bits dma tx engine registers */ + dma32regs_t *d32rxregs; /* 32 bits dma rx engine registers */ + dma64regs_t *d64txregs; /* 64 bits dma tx engine registers */ + dma64regs_t *d64rxregs; /* 64 bits dma rx engine registers */ + + uint32 dma64align; /* either 8k or 4k depends on number of dd */ + dma32dd_t *txd32; /* pointer to dma32 tx descriptor ring */ + dma64dd_t *txd64; /* pointer to dma64 tx descriptor ring */ + uint ntxd; /* # tx descriptors tunable */ + uint txin; /* index of next descriptor to reclaim */ + uint txout; /* index of next descriptor to post */ + void **txp; /* pointer to parallel array of pointers to packets */ + osldma_t *tx_dmah; /* DMA TX descriptor ring handle */ + osldma_t **txp_dmah; /* DMA TX packet data handle */ + ulong txdpa; /* physical address of descriptor ring */ + uint txdalign; /* #bytes added to alloc'd mem to align txd */ + uint txdalloc; /* #bytes allocated for the ring */ + + dma32dd_t *rxd32; /* pointer to dma32 rx descriptor ring */ + dma64dd_t *rxd64; /* pointer to dma64 rx descriptor ring */ + uint nrxd; /* # rx descriptors tunable */ + uint rxin; /* index of next descriptor to reclaim */ + uint rxout; /* index of next descriptor to post */ + void **rxp; /* pointer to parallel array of pointers to packets */ + osldma_t *rx_dmah; /* DMA RX descriptor ring handle */ + osldma_t **rxp_dmah; /* DMA RX packet data handle */ + ulong rxdpa; /* physical address of descriptor ring */ + uint rxdalign; /* #bytes added to alloc'd mem to align rxd */ + uint rxdalloc; /* #bytes allocated for the ring */ + + /* tunables */ + uint rxbufsize; /* rx buffer size in bytes, + not including the extra headroom + */ + uint nrxpost; /* # rx buffers to keep posted */ + uint rxoffset; /* rxcontrol offset */ + uint ddoffsetlow; /* add to get dma address of descriptor ring, low 32 bits */ + uint ddoffsethigh; /* high 32 bits */ + uint dataoffsetlow; /* add to get dma address of data buffer, low 32 bits */ + uint dataoffsethigh; /* high 32 bits */ +} dma_info_t; + +/* descriptor bumping macros */ +#define XXD(x, n) ((x) & ((n) - 1)) /* faster than %, but n must be power of 2 */ +#define TXD(x) XXD((x), di->ntxd) +#define RXD(x) XXD((x), di->nrxd) +#define NEXTTXD(i) TXD(i + 1) +#define PREVTXD(i) TXD(i - 1) +#define NEXTRXD(i) RXD(i + 1) +#define NTXDACTIVE(h, t) TXD(t - h) +#define NRXDACTIVE(h, t) RXD(t - h) + +/* macros to convert between byte offsets and indexes */ +#define B2I(bytes, type) ((bytes) / sizeof(type)) +#define I2B(index, type) ((index) * sizeof(type)) + +#define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ +#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ + + +/* common prototypes */ +static bool _dma_isaddrext(dma_info_t *di); +static bool dma32_alloc(dma_info_t *di, uint direction); +static void _dma_detach(dma_info_t *di); +static void _dma_ddtable_init(dma_info_t *di, uint direction, ulong pa); +static void _dma_rxinit(dma_info_t *di); +static void *_dma_rx(dma_info_t *di); +static void _dma_rxfill(dma_info_t *di); +static void _dma_rxreclaim(dma_info_t *di); +static void _dma_rxenable(dma_info_t *di); +static void * _dma_getnextrxp(dma_info_t *di, bool forceall); + +static void _dma_txblock(dma_info_t *di); +static void _dma_txunblock(dma_info_t *di); +static uint _dma_txactive(dma_info_t *di); + +static void* _dma_peeknexttxp(dma_info_t *di); +static uintptr _dma_getvar(dma_info_t *di, char *name); +static void _dma_counterreset(dma_info_t *di); +static void _dma_fifoloopbackenable(dma_info_t *di); + +/* ** 32 bit DMA prototypes */ +static bool dma32_alloc(dma_info_t *di, uint direction); +static bool dma32_txreset(dma_info_t *di); +static bool dma32_rxreset(dma_info_t *di); +static bool dma32_txsuspendedidle(dma_info_t *di); +static int dma32_txfast(dma_info_t *di, void *p0, bool commit); +static void *dma32_getnexttxp(dma_info_t *di, bool forceall); +static void *dma32_getnextrxp(dma_info_t *di, bool forceall); +static void dma32_txrotate(dma_info_t *di); +static bool dma32_rxidle(dma_info_t *di); +static void dma32_txinit(dma_info_t *di); +static bool dma32_txenabled(dma_info_t *di); +static void dma32_txsuspend(dma_info_t *di); +static void dma32_txresume(dma_info_t *di); +static bool dma32_txsuspended(dma_info_t *di); +static void dma32_txreclaim(dma_info_t *di, bool forceall); +static bool dma32_txstopped(dma_info_t *di); +static bool dma32_rxstopped(dma_info_t *di); +static bool dma32_rxenabled(dma_info_t *di); +static bool _dma32_addrext(osl_t *osh, dma32regs_t *dma32regs); + + +static di_fcn_t dma32proc = { + (di_detach_t)_dma_detach, + (di_txinit_t)dma32_txinit, + (di_txreset_t)dma32_txreset, + (di_txenabled_t)dma32_txenabled, + (di_txsuspend_t)dma32_txsuspend, + (di_txresume_t)dma32_txresume, + (di_txsuspended_t)dma32_txsuspended, + (di_txsuspendedidle_t)dma32_txsuspendedidle, + (di_txfast_t)dma32_txfast, + (di_txstopped_t)dma32_txstopped, + (di_txreclaim_t)dma32_txreclaim, + (di_getnexttxp_t)dma32_getnexttxp, + (di_peeknexttxp_t)_dma_peeknexttxp, + (di_txblock_t)_dma_txblock, + (di_txunblock_t)_dma_txunblock, + (di_txactive_t)_dma_txactive, + (di_txrotate_t)dma32_txrotate, + + (di_rxinit_t)_dma_rxinit, + (di_rxreset_t)dma32_rxreset, + (di_rxidle_t)dma32_rxidle, + (di_rxstopped_t)dma32_rxstopped, + (di_rxenable_t)_dma_rxenable, + (di_rxenabled_t)dma32_rxenabled, + (di_rx_t)_dma_rx, + (di_rxfill_t)_dma_rxfill, + (di_rxreclaim_t)_dma_rxreclaim, + (di_getnextrxp_t)_dma_getnextrxp, + + (di_fifoloopbackenable_t)_dma_fifoloopbackenable, + (di_getvar_t)_dma_getvar, + (di_counterreset_t)_dma_counterreset, + + NULL, + NULL, + NULL, + 34 +}; + +hnddma_t * +dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx, + uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, uint *msg_level) +{ + dma_info_t *di; + uint size; + + /* allocate private info structure */ + if ((di = MALLOC(osh, sizeof (dma_info_t))) == NULL) { + return (NULL); + } + bzero((char *)di, sizeof(dma_info_t)); + + di->msg_level = msg_level ? msg_level : &dma_msg_level; + + /* old chips w/o sb is no longer supported */ + ASSERT(sbh != NULL); + + /* check arguments */ + ASSERT(ISPOWEROF2(ntxd)); + ASSERT(ISPOWEROF2(nrxd)); + if (nrxd == 0) + ASSERT(dmaregsrx == NULL); + if (ntxd == 0) + ASSERT(dmaregstx == NULL); + + + /* init dma reg pointer */ + ASSERT(ntxd <= D32MAXDD); + ASSERT(nrxd <= D32MAXDD); + di->d32txregs = (dma32regs_t *)dmaregstx; + di->d32rxregs = (dma32regs_t *)dmaregsrx; + + DMA_TRACE(("%s: dma_attach: %s osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d " + "rxoffset %d dmaregstx %p dmaregsrx %p\n", + name, "DMA32", osh, ntxd, nrxd, rxbufsize, + nrxpost, rxoffset, dmaregstx, dmaregsrx)); + + /* make a private copy of our callers name */ + strncpy(di->name, name, MAXNAMEL); + di->name[MAXNAMEL-1] = '\0'; + + di->osh = osh; + di->sbh = sbh; + + /* save tunables */ + di->ntxd = ntxd; + di->nrxd = nrxd; + + /* the actual dma size doesn't include the extra headroom */ + if (rxbufsize > BCMEXTRAHDROOM) + di->rxbufsize = rxbufsize - BCMEXTRAHDROOM; + else + di->rxbufsize = rxbufsize; + + di->nrxpost = nrxpost; + di->rxoffset = rxoffset; + + /* + * figure out the DMA physical address offset for dd and data + * for old chips w/o sb, use zero + * for new chips w sb, + * PCI/PCIE: they map silicon backplace address to zero based memory, need offset + * Other bus: use zero + * SB_BUS BIGENDIAN kludge: use sdram swapped region for data buffer, not descriptor + */ + di->ddoffsetlow = 0; + di->dataoffsetlow = 0; + /* for pci bus, add offset */ + if (sbh->bustype == PCI_BUS) { + di->ddoffsetlow = SB_PCI_DMA; + di->ddoffsethigh = 0; + di->dataoffsetlow = di->ddoffsetlow; + di->dataoffsethigh = di->ddoffsethigh; + } + +#if defined(__mips__) && defined(IL_BIGENDIAN) + di->dataoffsetlow = di->dataoffsetlow + SB_SDRAM_SWAPPED; +#endif + + di->addrext = _dma_isaddrext(di); + + /* allocate tx packet pointer vector */ + if (ntxd) { + size = ntxd * sizeof(void *); + if ((di->txp = MALLOC(osh, size)) == NULL) { + DMA_ERROR(("%s: dma_attach: out of tx memory, malloced %d bytes\n", + di->name, MALLOCED(osh))); + goto fail; + } + bzero((char *)di->txp, size); + } + + /* allocate rx packet pointer vector */ + if (nrxd) { + size = nrxd * sizeof(void *); + if ((di->rxp = MALLOC(osh, size)) == NULL) { + DMA_ERROR(("%s: dma_attach: out of rx memory, malloced %d bytes\n", + di->name, MALLOCED(osh))); + goto fail; + } + bzero((char *)di->rxp, size); + } + + /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ + if (ntxd) { + if (!dma32_alloc(di, DMA_TX)) + goto fail; + } + + /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ + if (nrxd) { + if (!dma32_alloc(di, DMA_RX)) + goto fail; + } + + if ((di->ddoffsetlow == SB_PCI_DMA) && (di->txdpa > SB_PCI_DMA_SZ) && !di->addrext) { + DMA_ERROR(("%s: dma_attach: txdpa 0x%lx: addrext not supported\n", + di->name, di->txdpa)); + goto fail; + } + if ((di->ddoffsetlow == SB_PCI_DMA) && (di->rxdpa > SB_PCI_DMA_SZ) && !di->addrext) { + DMA_ERROR(("%s: dma_attach: rxdpa 0x%lx: addrext not supported\n", + di->name, di->rxdpa)); + goto fail; + } + + DMA_TRACE(("ddoffsetlow 0x%x ddoffsethigh 0x%x dataoffsetlow 0x%x dataoffsethigh " + "0x%x addrext %d\n", di->ddoffsetlow, di->ddoffsethigh, di->dataoffsetlow, + di->dataoffsethigh, di->addrext)); + + /* allocate tx packet pointer vector and DMA mapping vectors */ + if (ntxd) { + + size = ntxd * sizeof(osldma_t **); + if ((di->txp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL) + goto fail; + bzero((char*)di->txp_dmah, size); + }else + di->txp_dmah = NULL; + + /* allocate rx packet pointer vector and DMA mapping vectors */ + if (nrxd) { + + size = nrxd * sizeof(osldma_t **); + if ((di->rxp_dmah = (osldma_t **)MALLOC(osh, size)) == NULL) + goto fail; + bzero((char*)di->rxp_dmah, size); + + } else + di->rxp_dmah = NULL; + + /* initialize opsvec of function pointers */ + di->hnddma.di_fn = dma32proc; + + return ((hnddma_t *)di); + +fail: + _dma_detach(di); + return (NULL); +} + +/* init the tx or rx descriptor */ +static INLINE void +dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, ulong pa, uint outidx, uint32 *flags, + uint32 bufcount) +{ + /* dma32 uses 32 bits control to fit both flags and bufcounter */ + *flags = *flags | (bufcount & CTRL_BC_MASK); + + if ((di->dataoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { + W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow)); + W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); + } else { + /* address extension */ + uint32 ae; + ASSERT(di->addrext); + ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; + pa &= ~PCI32ADDR_HIGH; + + *flags |= (ae << CTRL_AE_SHIFT); + W_SM(&ddring[outidx].addr, BUS_SWAP32(pa + di->dataoffsetlow)); + W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags)); + } +} + +static bool +_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) +{ + uint32 w; + + OR_REG(osh, &dma32regs->control, XC_AE); + w = R_REG(osh, &dma32regs->control); + AND_REG(osh, &dma32regs->control, ~XC_AE); + return ((w & XC_AE) == XC_AE); +} + +/* !! may be called with core in reset */ +static void +_dma_detach(dma_info_t *di) +{ + if (di == NULL) + return; + + DMA_TRACE(("%s: dma_detach\n", di->name)); + + /* shouldn't be here if descriptors are unreclaimed */ + ASSERT(di->txin == di->txout); + ASSERT(di->rxin == di->rxout); + + /* free dma descriptor rings */ + if (di->txd32) + DMA_FREE_CONSISTENT(di->osh, ((int8*)di->txd32 - di->txdalign), + di->txdalloc, (di->txdpa - di->txdalign), &di->tx_dmah); + if (di->rxd32) + DMA_FREE_CONSISTENT(di->osh, ((int8*)di->rxd32 - di->rxdalign), + di->rxdalloc, (di->rxdpa - di->rxdalign), &di->rx_dmah); + + /* free packet pointer vectors */ + if (di->txp) + MFREE(di->osh, (void *)di->txp, (di->ntxd * sizeof(void *))); + if (di->rxp) + MFREE(di->osh, (void *)di->rxp, (di->nrxd * sizeof(void *))); + + /* free tx packet DMA handles */ + if (di->txp_dmah) + MFREE(di->osh, (void *)di->txp_dmah, di->ntxd * sizeof(osldma_t **)); + + /* free rx packet DMA handles */ + if (di->rxp_dmah) + MFREE(di->osh, (void *)di->rxp_dmah, di->nrxd * sizeof(osldma_t **)); + + /* free our private info structure */ + MFREE(di->osh, (void *)di, sizeof(dma_info_t)); + +} + +/* return TRUE if this dma engine supports DmaExtendedAddrChanges, otherwise FALSE */ +static bool +_dma_isaddrext(dma_info_t *di) +{ + if (di->d32txregs) + return (_dma32_addrext(di->osh, di->d32txregs)); + else if (di->d32rxregs) + return (_dma32_addrext(di->osh, di->d32rxregs)); + return FALSE; +} + +/* initialize descriptor table base address */ +static void +_dma_ddtable_init(dma_info_t *di, uint direction, ulong pa) +{ + if ((di->ddoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { + if (direction == DMA_TX) + W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow)); + else + W_REG(di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); + } else { + /* dma32 address extension */ + uint32 ae; + ASSERT(di->addrext); + + /* shift the high bit(s) from pa to ae */ + ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; + pa &= ~PCI32ADDR_HIGH; + + if (direction == DMA_TX) { + W_REG(di->osh, &di->d32txregs->addr, (pa + di->ddoffsetlow)); + SET_REG(di->osh, &di->d32txregs->control, XC_AE, ae <osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); + SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <name)); + OR_REG(di->osh, &di->d32txregs->control, XC_LE); +} + +static void +_dma_rxinit(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_rxinit\n", di->name)); + + if (di->nrxd == 0) + return; + + di->rxin = di->rxout = 0; + + /* clear rx descriptor ring */ + BZERO_SM((void *)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); + _dma_rxenable(di); + _dma_ddtable_init(di, DMA_RX, di->rxdpa); +} + +static void +_dma_rxenable(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_rxenable\n", di->name)); + + W_REG(di->osh, &di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE)); +} + +/* !! rx entry routine, returns a pointer to the next frame received, + * or NULL if there are no more + */ +static void * +_dma_rx(dma_info_t *di) +{ + void *p; + uint len; + int skiplen = 0; + + while ((p = _dma_getnextrxp(di, FALSE))) { + /* skip giant packets which span multiple rx descriptors */ + if (skiplen > 0) { + skiplen -= di->rxbufsize; + if (skiplen < 0) + skiplen = 0; + PKTFREE(di->osh, p, FALSE); + continue; + } + + len = ltoh16(*(uint16*)(PKTDATA(di->osh, p))); + DMA_TRACE(("%s: dma_rx len %d\n", di->name, len)); + + /* bad frame length check */ + if (len > (di->rxbufsize - di->rxoffset)) { + DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n", di->name, len)); + if (len > 0) + skiplen = len - (di->rxbufsize - di->rxoffset); + PKTFREE(di->osh, p, FALSE); + di->hnddma.rxgiants++; + continue; + } + + /* set actual length */ + PKTSETLEN(di->osh, p, (di->rxoffset + len)); + + break; + } + + return (p); +} + +/* post receive buffers */ +static void +_dma_rxfill(dma_info_t *di) +{ + void *p; + uint rxin, rxout; + uint32 flags = 0; + uint n; + uint i; + uint32 pa; + uint extra_offset = 0; + + /* + * Determine how many receive buffers we're lacking + * from the full complement, allocate, initialize, + * and post them, then update the chip rx lastdscr. + */ + + rxin = di->rxin; + rxout = di->rxout; + + n = di->nrxpost - NRXDACTIVE(rxin, rxout); + + DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); + + if (di->rxbufsize > BCMEXTRAHDROOM) + extra_offset = BCMEXTRAHDROOM; + + for (i = 0; i < n; i++) { + /* the di->rxbufsize doesn't include the extra headroom, we need to add it to the + size to be allocated + */ + if ((p = PKTGET(di->osh, di->rxbufsize + extra_offset, + FALSE)) == NULL) { + DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name)); + di->hnddma.rxnobuf++; + break; + } + /* reserve an extra headroom, if applicable */ + if (extra_offset) + PKTPULL(di->osh, p, extra_offset); + + /* Do a cached write instead of uncached write since DMA_MAP + * will flush the cache. + */ + *(uint32*)(PKTDATA(di->osh, p)) = 0; + + pa = (uint32) DMA_MAP(di->osh, PKTDATA(di->osh, p), + di->rxbufsize, DMA_RX, p); + + ASSERT(ISALIGNED(pa, 4)); + + /* save the free packet pointer */ + ASSERT(di->rxp[rxout] == NULL); + di->rxp[rxout] = p; + + /* reset flags for each descriptor */ + flags = 0; + if (rxout == (di->nrxd - 1)) + flags = CTRL_EOT; + dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); + rxout = NEXTRXD(rxout); + } + + di->rxout = rxout; + + /* update the chip lastdscr pointer */ + W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); +} + +/* like getnexttxp but no reclaim */ +static void * +_dma_peeknexttxp(dma_info_t *di) +{ + uint end, i; + + if (di->ntxd == 0) + return (NULL); + + end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); + + for (i = di->txin; i != end; i = NEXTTXD(i)) + if (di->txp[i]) + return (di->txp[i]); + + return (NULL); +} + +static void +_dma_rxreclaim(dma_info_t *di) +{ + void *p; + + /* "unused local" warning suppression for OSLs that + * define PKTFREE() without using the di->osh arg + */ + di = di; + + DMA_TRACE(("%s: dma_rxreclaim\n", di->name)); + + while ((p = _dma_getnextrxp(di, TRUE))) + PKTFREE(di->osh, p, FALSE); +} + +static void * +_dma_getnextrxp(dma_info_t *di, bool forceall) +{ + if (di->nrxd == 0) + return (NULL); + + return dma32_getnextrxp(di, forceall); +} + +static void +_dma_txblock(dma_info_t *di) +{ + di->hnddma.txavail = 0; +} + +static void +_dma_txunblock(dma_info_t *di) +{ + di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; +} + +static uint +_dma_txactive(dma_info_t *di) +{ + return (NTXDACTIVE(di->txin, di->txout)); +} + +static void +_dma_counterreset(dma_info_t *di) +{ + /* reset all software counter */ + di->hnddma.rxgiants = 0; + di->hnddma.rxnobuf = 0; + di->hnddma.txnobuf = 0; +} + +/* get the address of the var in order to change later */ +static uintptr +_dma_getvar(dma_info_t *di, char *name) +{ + if (!strcmp(name, "&txavail")) + return ((uintptr) &(di->hnddma.txavail)); + else { + ASSERT(0); + } + return (0); +} + +void +dma_txpioloopback(osl_t *osh, dma32regs_t *regs) +{ + OR_REG(osh, ®s->control, XC_LE); +} + + + +/* 32 bits DMA functions */ +static void +dma32_txinit(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_txinit\n", di->name)); + + if (di->ntxd == 0) + return; + + di->txin = di->txout = 0; + di->hnddma.txavail = di->ntxd - 1; + + /* clear tx descriptor ring */ + BZERO_SM((void *)di->txd32, (di->ntxd * sizeof(dma32dd_t))); + W_REG(di->osh, &di->d32txregs->control, XC_XE); + _dma_ddtable_init(di, DMA_TX, di->txdpa); +} + +static bool +dma32_txenabled(dma_info_t *di) +{ + uint32 xc; + + /* If the chip is dead, it is not enabled :-) */ + xc = R_REG(di->osh, &di->d32txregs->control); + return ((xc != 0xffffffff) && (xc & XC_XE)); +} + +static void +dma32_txsuspend(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_txsuspend\n", di->name)); + + if (di->ntxd == 0) + return; + + OR_REG(di->osh, &di->d32txregs->control, XC_SE); +} + +static void +dma32_txresume(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_txresume\n", di->name)); + + if (di->ntxd == 0) + return; + + AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); +} + +static bool +dma32_txsuspended(dma_info_t *di) +{ + return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); +} + +static void +dma32_txreclaim(dma_info_t *di, bool forceall) +{ + void *p; + + DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + + while ((p = dma32_getnexttxp(di, forceall))) + PKTFREE(di->osh, p, TRUE); +} + +static bool +dma32_txstopped(dma_info_t *di) +{ + return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); +} + +static bool +dma32_rxstopped(dma_info_t *di) +{ + return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); +} + +static bool +dma32_alloc(dma_info_t *di, uint direction) +{ + uint size; + uint ddlen; + void *va; + + ddlen = sizeof(dma32dd_t); + + size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + + if (!ISALIGNED(DMA_CONSISTENT_ALIGN, D32RINGALIGN)) + size += D32RINGALIGN; + + + if (direction == DMA_TX) { + if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->txdpa, &di->tx_dmah)) == NULL) { + DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(ntxd) failed\n", + di->name)); + return FALSE; + } + + di->txd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN); + di->txdalign = (uint)((int8*)di->txd32 - (int8*)va); + di->txdpa += di->txdalign; + di->txdalloc = size; + ASSERT(ISALIGNED((uintptr)di->txd32, D32RINGALIGN)); + } else { + if ((va = DMA_ALLOC_CONSISTENT(di->osh, size, &di->rxdpa, &di->rx_dmah)) == NULL) { + DMA_ERROR(("%s: dma_attach: DMA_ALLOC_CONSISTENT(nrxd) failed\n", + di->name)); + return FALSE; + } + di->rxd32 = (dma32dd_t *) ROUNDUP((uintptr)va, D32RINGALIGN); + di->rxdalign = (uint)((int8*)di->rxd32 - (int8*)va); + di->rxdpa += di->rxdalign; + di->rxdalloc = size; + ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN)); + } + + return TRUE; +} + +static bool +dma32_txreset(dma_info_t *di) +{ + uint32 status; + + if (di->ntxd == 0) + return TRUE; + + /* suspend tx DMA first */ + W_REG(di->osh, &di->d32txregs->control, XC_SE); + SPINWAIT(((status = (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK)) + != XS_XS_DISABLED) && + (status != XS_XS_IDLE) && + (status != XS_XS_STOPPED), + (10000)); + + W_REG(di->osh, &di->d32txregs->control, 0); + SPINWAIT(((status = (R_REG(di->osh, + &di->d32txregs->status) & XS_XS_MASK)) != XS_XS_DISABLED), + 10000); + + /* wait for the last transaction to complete */ + OSL_DELAY(300); + + return (status == XS_XS_DISABLED); +} + +static bool +dma32_rxidle(dma_info_t *di) +{ + DMA_TRACE(("%s: dma_rxidle\n", di->name)); + + if (di->nrxd == 0) + return TRUE; + + return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == + R_REG(di->osh, &di->d32rxregs->ptr)); +} + +static bool +dma32_rxreset(dma_info_t *di) +{ + uint32 status; + + if (di->nrxd == 0) + return TRUE; + + W_REG(di->osh, &di->d32rxregs->control, 0); + SPINWAIT(((status = (R_REG(di->osh, + &di->d32rxregs->status) & RS_RS_MASK)) != RS_RS_DISABLED), + 10000); + + return (status == RS_RS_DISABLED); +} + +static bool +dma32_rxenabled(dma_info_t *di) +{ + uint32 rc; + + rc = R_REG(di->osh, &di->d32rxregs->control); + return ((rc != 0xffffffff) && (rc & RC_RE)); +} + +static bool +dma32_txsuspendedidle(dma_info_t *di) +{ + if (di->ntxd == 0) + return TRUE; + + if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE)) + return 0; + + if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) + return 0; + + OSL_DELAY(2); + return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_IDLE); +} + +/* !! tx entry routine + * supports full 32bit dma engine buffer addressing so + * dma buffers can cross 4 Kbyte page boundaries. + */ +static int +dma32_txfast(dma_info_t *di, void *p0, bool commit) +{ + void *p, *next; + uchar *data; + uint len; + uint txout; + uint32 flags = 0; + uint32 pa; + + DMA_TRACE(("%s: dma_txfast\n", di->name)); + + txout = di->txout; + + /* + * Walk the chain of packet buffers + * allocating and initializing transmit descriptor entries. + */ + for (p = p0; p; p = next) { + data = PKTDATA(di->osh, p); + len = PKTLEN(di->osh, p); + next = PKTNEXT(di->osh, p); + + /* return nonzero if out of tx descriptors */ + if (NEXTTXD(txout) == di->txin) + goto outoftxd; + + if (len == 0) + continue; + + /* get physical address of buffer start */ + pa = (uint32) DMA_MAP(di->osh, data, len, DMA_TX, p); + + flags = 0; + if (p == p0) + flags |= CTRL_SOF; + if (next == NULL) + flags |= (CTRL_IOC | CTRL_EOF); + if (txout == (di->ntxd - 1)) + flags |= CTRL_EOT; + + dma32_dd_upd(di, di->txd32, pa, txout, &flags, len); + ASSERT(di->txp[txout] == NULL); + + txout = NEXTTXD(txout); + } + + /* if last txd eof not set, fix it */ + if (!(flags & CTRL_EOF)) + W_SM(&di->txd32[PREVTXD(txout)].ctrl, BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF)); + + /* save the packet */ + di->txp[PREVTXD(txout)] = p0; + + /* bump the tx descriptor index */ + di->txout = txout; + + /* kick the chip */ + if (commit) + W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); + + /* tx flow control */ + di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + + return (0); + +outoftxd: + DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name)); + PKTFREE(di->osh, p0, TRUE); + di->hnddma.txavail = 0; + di->hnddma.txnobuf++; + return (-1); +} + +/* + * Reclaim next completed txd (txds if using chained buffers) and + * return associated packet. + * If 'force' is true, reclaim txd(s) and return associated packet + * regardless of the value of the hardware "curr" pointer. + */ +static void * +dma32_getnexttxp(dma_info_t *di, bool forceall) +{ + uint start, end, i; + void *txp; + + DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + + if (di->ntxd == 0) + return (NULL); + + txp = NULL; + + start = di->txin; + if (forceall) + end = di->txout; + else + end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); + + if ((start == 0) && (end > di->txout)) + goto bogus; + + for (i = start; i != end && !txp; i = NEXTTXD(i)) { + DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->txd32[i].addr)) - di->dataoffsetlow), + (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) & CTRL_BC_MASK), + DMA_TX, di->txp[i]); + + W_SM(&di->txd32[i].addr, 0xdeadbeef); + txp = di->txp[i]; + di->txp[i] = NULL; + } + + di->txin = i; + + /* tx flow control */ + di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + + return (txp); + +bogus: +/* + DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", + start, end, di->txout, forceall)); +*/ + return (NULL); +} + +static void * +dma32_getnextrxp(dma_info_t *di, bool forceall) +{ + uint i; + void *rxp; + + /* if forcing, dma engine must be disabled */ + ASSERT(!forceall || !dma32_rxenabled(di)); + + i = di->rxin; + + /* return if no packets posted */ + if (i == di->rxout) + return (NULL); + + /* ignore curr if forceall */ + if (!forceall && (i == B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t))) + return (NULL); + + /* get the packet pointer that corresponds to the rx descriptor */ + rxp = di->rxp[i]; + ASSERT(rxp); + di->rxp[i] = NULL; + + /* clear this packet from the descriptor ring */ + DMA_UNMAP(di->osh, (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) - di->dataoffsetlow), + di->rxbufsize, DMA_RX, rxp); + + W_SM(&di->rxd32[i].addr, 0xdeadbeef); + + di->rxin = NEXTRXD(i); + + return (rxp); +} + +/* + * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). + */ +static void +dma32_txrotate(dma_info_t *di) +{ + uint ad; + uint nactive; + uint rot; + uint old, new; + uint32 w; + uint first, last; + + ASSERT(dma32_txsuspendedidle(di)); + + nactive = _dma_txactive(di); + ad = B2I(((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK) >> XS_AD_SHIFT), dma32dd_t); + rot = TXD(ad - di->txin); + + ASSERT(rot < di->ntxd); + + /* full-ring case is a lot harder - don't worry about this */ + if (rot >= (di->ntxd - nactive)) { + DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name)); + return; + } + + first = di->txin; + last = PREVTXD(di->txout); + + /* move entries starting at last and moving backwards to first */ + for (old = last; old != PREVTXD(first); old = PREVTXD(old)) { + new = TXD(old + rot); + + /* + * Move the tx dma descriptor. + * EOT is set only in the last entry in the ring. + */ + w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT; + if (new == (di->ntxd - 1)) + w |= CTRL_EOT; + W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w)); + W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr)); + + /* zap the old tx dma descriptor address field */ + W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef)); + + /* move the corresponding txp[] entry */ + ASSERT(di->txp[new] == NULL); + di->txp[new] = di->txp[old]; + di->txp[old] = NULL; + } + + /* update txin and txout */ + di->txin = ad; + di->txout = TXD(di->txout + rot); + di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + + /* kick the chip */ + W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t)); +} + + +uint +dma_addrwidth(sb_t *sbh, void *dmaregs) +{ + dma32regs_t *dma32regs; + osl_t *osh; + + osh = sb_osh(sbh); + + /* Start checking for 32-bit / 30-bit addressing */ + dma32regs = (dma32regs_t *)dmaregs; + + /* For System Backplane, PCIE bus or addrext feature, 32-bits ok */ + if ((BUSTYPE(sbh->bustype) == SB_BUS) || + ((BUSTYPE(sbh->bustype) == PCI_BUS) && sbh->buscoretype == SB_PCIE) || + (_dma32_addrext(osh, dma32regs))) + return (DMADDRWIDTH_32); + + /* Fallthru */ + return (DMADDRWIDTH_30); +} diff --git a/package/broadcom-wl/src/kmod/hnddma.h b/package/broadcom-wl/src/kmod/hnddma.h new file mode 100644 index 0000000000..de74c067b2 --- /dev/null +++ b/package/broadcom-wl/src/kmod/hnddma.h @@ -0,0 +1,156 @@ +/* + * Generic Broadcom Home Networking Division (HND) DMA engine SW interface + * This supports the following chips: BCM42xx, 44xx, 47xx . + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: hnddma.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $ + */ + +#ifndef _hnddma_h_ +#define _hnddma_h_ + +typedef const struct hnddma_pub hnddma_t; + +/* dma function type */ +typedef void (*di_detach_t)(hnddma_t *dmah); +typedef bool (*di_txreset_t)(hnddma_t *dmah); +typedef bool (*di_rxreset_t)(hnddma_t *dmah); +typedef bool (*di_rxidle_t)(hnddma_t *dmah); +typedef void (*di_txinit_t)(hnddma_t *dmah); +typedef bool (*di_txenabled_t)(hnddma_t *dmah); +typedef void (*di_rxinit_t)(hnddma_t *dmah); +typedef void (*di_txsuspend_t)(hnddma_t *dmah); +typedef void (*di_txresume_t)(hnddma_t *dmah); +typedef bool (*di_txsuspended_t)(hnddma_t *dmah); +typedef bool (*di_txsuspendedidle_t)(hnddma_t *dmah); +typedef int (*di_txfast_t)(hnddma_t *dmah, void *p, bool commit); +typedef void (*di_fifoloopbackenable_t)(hnddma_t *dmah); +typedef bool (*di_txstopped_t)(hnddma_t *dmah); +typedef bool (*di_rxstopped_t)(hnddma_t *dmah); +typedef bool (*di_rxenable_t)(hnddma_t *dmah); +typedef bool (*di_rxenabled_t)(hnddma_t *dmah); +typedef void* (*di_rx_t)(hnddma_t *dmah); +typedef void (*di_rxfill_t)(hnddma_t *dmah); +typedef void (*di_txreclaim_t)(hnddma_t *dmah, bool forceall); +typedef void (*di_rxreclaim_t)(hnddma_t *dmah); +typedef uintptr (*di_getvar_t)(hnddma_t *dmah, char *name); +typedef void* (*di_getnexttxp_t)(hnddma_t *dmah, bool forceall); +typedef void* (*di_getnextrxp_t)(hnddma_t *dmah, bool forceall); +typedef void* (*di_peeknexttxp_t)(hnddma_t *dmah); +typedef void (*di_txblock_t)(hnddma_t *dmah); +typedef void (*di_txunblock_t)(hnddma_t *dmah); +typedef uint (*di_txactive_t)(hnddma_t *dmah); +typedef void (*di_txrotate_t)(hnddma_t *dmah); +typedef void (*di_counterreset_t)(hnddma_t *dmah); +typedef char* (*di_dump_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); +typedef char* (*di_dumptx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); +typedef char* (*di_dumprx_t)(hnddma_t *dmah, struct bcmstrbuf *b, bool dumpring); + +/* dma opsvec */ +typedef struct di_fcn_s { + di_detach_t detach; + di_txinit_t txinit; + di_txreset_t txreset; + di_txenabled_t txenabled; + di_txsuspend_t txsuspend; + di_txresume_t txresume; + di_txsuspended_t txsuspended; + di_txsuspendedidle_t txsuspendedidle; + di_txfast_t txfast; + di_txstopped_t txstopped; + di_txreclaim_t txreclaim; + di_getnexttxp_t getnexttxp; + di_peeknexttxp_t peeknexttxp; + di_txblock_t txblock; + di_txunblock_t txunblock; + di_txactive_t txactive; + di_txrotate_t txrotate; + + di_rxinit_t rxinit; + di_rxreset_t rxreset; + di_rxidle_t rxidle; + di_rxstopped_t rxstopped; + di_rxenable_t rxenable; + di_rxenabled_t rxenabled; + di_rx_t rx; + di_rxfill_t rxfill; + di_rxreclaim_t rxreclaim; + di_getnextrxp_t getnextrxp; + + di_fifoloopbackenable_t fifoloopbackenable; + di_getvar_t d_getvar; + di_counterreset_t counterreset; + di_dump_t dump; + di_dumptx_t dumptx; + di_dumprx_t dumprx; + uint endnum; +} di_fcn_t; + +/* + * Exported data structure (read-only) + */ +/* export structure */ +struct hnddma_pub { + di_fcn_t di_fn; /* DMA function pointers */ + uint txavail; /* # free tx descriptors */ + + /* rx error counters */ + uint rxgiants; /* rx giant frames */ + uint rxnobuf; /* rx out of dma descriptors */ + /* tx error counters */ + uint txnobuf; /* tx out of dma descriptors */ +}; + + +extern hnddma_t * dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, void *dmaregsrx, + uint ntxd, uint nrxd, uint rxbufsize, uint nrxpost, uint rxoffset, + uint *msg_level); +#define dma_detach(di) ((di)->di_fn.detach(di)) +#define dma_txreset(di) ((di)->di_fn.txreset(di)) +#define dma_rxreset(di) ((di)->di_fn.rxreset(di)) +#define dma_rxidle(di) ((di)->di_fn.rxidle(di)) +#define dma_txinit(di) ((di)->di_fn.txinit(di)) +#define dma_txenabled(di) ((di)->di_fn.txenabled(di)) +#define dma_rxinit(di) ((di)->di_fn.rxinit(di)) +#define dma_txsuspend(di) ((di)->di_fn.txsuspend(di)) +#define dma_txresume(di) ((di)->di_fn.txresume(di)) +#define dma_txsuspended(di) ((di)->di_fn.txsuspended(di)) +#define dma_txsuspendedidle(di) ((di)->di_fn.txsuspendedidle(di)) +#define dma_txfast(di, p, commit) ((di)->di_fn.txfast(di, p, commit)) +#define dma_fifoloopbackenable(di) ((di)->di_fn.fifoloopbackenable(di)) +#define dma_txstopped(di) ((di)->di_fn.txstopped(di)) +#define dma_rxstopped(di) ((di)->di_fn.rxstopped(di)) +#define dma_rxenable(di) ((di)->di_fn.rxenable(di)) +#define dma_rxenabled(di) ((di)->di_fn.rxenabled(di)) +#define dma_rx(di) ((di)->di_fn.rx(di)) +#define dma_rxfill(di) ((di)->di_fn.rxfill(di)) +#define dma_txreclaim(di, forceall) ((di)->di_fn.txreclaim(di, forceall)) +#define dma_rxreclaim(di) ((di)->di_fn.rxreclaim(di)) +#define dma_getvar(di, name) ((di)->di_fn.d_getvar(di, name)) +#define dma_getnexttxp(di, forceall) ((di)->di_fn.getnexttxp(di, forceall)) +#define dma_getnextrxp(di, forceall) ((di)->di_fn.getnextrxp(di, forceall)) +#define dma_peeknexttxp(di) ((di)->di_fn.peeknexttxp(di)) +#define dma_txblock(di) ((di)->di_fn.txblock(di)) +#define dma_txunblock(di) ((di)->di_fn.txunblock(di)) +#define dma_txactive(di) ((di)->di_fn.txactive(di)) +#define dma_txrotate(di) ((di)->di_fn.txrotate(di)) +#define dma_counterreset(di) ((di)->di_fn.counterreset(di)) + +#define DMA_DUMP_SIZE 2048 +/* return addresswidth allowed + * This needs to be done after SB attach but before dma attach. + * SB attach provides ability to probe backplane and dma core capabilities + * This info is needed by DMA_ALLOC_CONSISTENT in dma attach + */ +extern uint dma_addrwidth(sb_t *sbh, void *dmaregs); + +/* pio helpers */ +void dma_txpioloopback(osl_t *osh, dma32regs_t *); + +#endif /* _hnddma_h_ */ diff --git a/package/broadcom-wl/src/kmod/linux_osl.c b/package/broadcom-wl/src/kmod/linux_osl.c new file mode 100644 index 0000000000..d702961032 --- /dev/null +++ b/package/broadcom-wl/src/kmod/linux_osl.c @@ -0,0 +1,269 @@ +/* + * Linux OS Independent Layer + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: linux_osl.c,v 1.1.1.14 2006/04/08 06:13:39 honor Exp $ + */ + +#define LINUX_OSL + +#include +#include +#include +#include +#include +#include +#include "linux_osl.h" +#include +#include +#ifdef mips +#include +#endif /* mips */ +#include + +#define PCI_CFG_RETRY 10 + +#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */ +#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ + +typedef struct bcm_mem_link { + struct bcm_mem_link *prev; + struct bcm_mem_link *next; + uint size; + int line; + char file[BCM_MEM_FILENAME_LEN]; +} bcm_mem_link_t; + +static int16 linuxbcmerrormap[] = \ +{ 0, /* 0 */ + -EINVAL, /* BCME_ERROR */ + -EINVAL, /* BCME_BADARG */ + -EINVAL, /* BCME_BADOPTION */ + -EINVAL, /* BCME_NOTUP */ + -EINVAL, /* BCME_NOTDOWN */ + -EINVAL, /* BCME_NOTAP */ + -EINVAL, /* BCME_NOTSTA */ + -EINVAL, /* BCME_BADKEYIDX */ + -EINVAL, /* BCME_RADIOOFF */ + -EINVAL, /* BCME_NOTBANDLOCKED */ + -EINVAL, /* BCME_NOCLK */ + -EINVAL, /* BCME_BADRATESET */ + -EINVAL, /* BCME_BADBAND */ + -E2BIG, /* BCME_BUFTOOSHORT */ + -E2BIG, /* BCME_BUFTOOLONG */ + -EBUSY, /* BCME_BUSY */ + -EINVAL, /* BCME_NOTASSOCIATED */ + -EINVAL, /* BCME_BADSSIDLEN */ + -EINVAL, /* BCME_OUTOFRANGECHAN */ + -EINVAL, /* BCME_BADCHAN */ + -EFAULT, /* BCME_BADADDR */ + -ENOMEM, /* BCME_NORESOURCE */ + -EOPNOTSUPP, /* BCME_UNSUPPORTED */ + -EMSGSIZE, /* BCME_BADLENGTH */ + -EINVAL, /* BCME_NOTREADY */ + -EPERM, /* BCME_NOTPERMITTED */ + -ENOMEM, /* BCME_NOMEM */ + -EINVAL, /* BCME_ASSOCIATED */ + -ERANGE, /* BCME_RANGE */ + -EINVAL, /* BCME_NOTFOUND */ + -EINVAL, /* BCME_WME_NOT_ENABLED */ + -EINVAL, /* BCME_TSPEC_NOTFOUND */ + -EINVAL, /* BCME_ACM_NOTSUPPORTED */ + -EINVAL, /* BCME_NOT_WME_ASSOCIATION */ + -EIO, /* BCME_SDIO_ERROR */ + -ENODEV /* BCME_DONGLE_DOWN */ +}; + +/* translate bcmerrors into linux errors */ +int +osl_error(int bcmerror) +{ + int abs_bcmerror; + int array_size = ARRAYSIZE(linuxbcmerrormap); + + abs_bcmerror = ABS(bcmerror); + + if (bcmerror > 0) + abs_bcmerror = 0; + + else if (abs_bcmerror >= array_size) + abs_bcmerror = BCME_ERROR; + + return linuxbcmerrormap[abs_bcmerror]; +} + +osl_t * +osl_attach(void *pdev, bool pkttag) +{ + osl_t *osh; + + osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); + ASSERT(osh); + + bzero(osh, sizeof(osl_t)); + + /* + * check the cases where + * 1.Error code Added to bcmerror table, but forgot to add it to the OS + * dependent error code + * 2. Error code is added to the bcmerror table, but forgot to add the + * corresponding errorstring(dummy call to bcmerrorstr) + */ + bcmerrorstr(0); + ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); + + osh->magic = OS_HANDLE_MAGIC; + osh->malloced = 0; + osh->failed = 0; + osh->dbgmem_list = NULL; + osh->pdev = pdev; + osh->pub.pkttag = pkttag; + + return osh; +} + +void +osl_detach(osl_t *osh) +{ + if (osh == NULL) + return; + + ASSERT(osh->magic == OS_HANDLE_MAGIC); + kfree(osh); +} + +/* Return a new packet. zero out pkttag */ +void* +osl_pktget(osl_t *osh, uint len, bool send) +{ + struct sk_buff *skb; + + if ((skb = dev_alloc_skb(len))) { + skb_put(skb, len); + skb->priority = 0; + +#ifdef BCMDBG_PKT + pktlist_add(&(osh->pktlist), (void *) skb); +#endif /* BCMDBG_PKT */ + + osh->pub.pktalloced++; + } + + return ((void*) skb); +} + +/* Free the driver packet. Free the tag if present */ +void +osl_pktfree(osl_t *osh, void *p) +{ + struct sk_buff *skb, *nskb; + + skb = (struct sk_buff*) p; + + /* perversion: we use skb->next to chain multi-skb packets */ + while (skb) { + nskb = skb->next; + skb->next = NULL; + +#ifdef BCMDBG_PKT + pktlist_remove(&(osh->pktlist), (void *) skb); +#endif /* BCMDBG_PKT */ + + if (skb->destructor) { + /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists + */ + dev_kfree_skb_any(skb); + } else { + /* can free immediately (even in_irq()) if destructor does not exist */ + dev_kfree_skb(skb); + } + + osh->pub.pktalloced--; + + skb = nskb; + } +} + +void* +osl_malloc(osl_t *osh, uint size) +{ + void *addr; + + /* only ASSERT if osh is defined */ + if (osh) + ASSERT(osh->magic == OS_HANDLE_MAGIC); + + if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { + if (osh) + osh->failed++; + return (NULL); + } + if (osh) + osh->malloced += size; + + return (addr); +} + +void +osl_mfree(osl_t *osh, void *addr, uint size) +{ + if (osh) { + ASSERT(osh->magic == OS_HANDLE_MAGIC); + osh->malloced -= size; + } + kfree(addr); +} + +uint +osl_malloced(osl_t *osh) +{ + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + return (osh->malloced); +} + +uint osl_malloc_failed(osl_t *osh) +{ + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + return (osh->failed); +} + +#undef osl_delay +void +osl_delay(uint usec) +{ + OSL_DELAY(usec); +} + +/* Clone a packet. + * The pkttag contents are NOT cloned. + */ +void * +osl_pktdup(osl_t *osh, void *skb) +{ + void * p; + + if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) + return NULL; + + /* skb_clone copies skb->cb.. we don't want that */ + if (osh->pub.pkttag) + bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); + + /* Increment the packet counter */ + osh->pub.pktalloced++; + return (p); +} + +uint +osl_pktalloced(osl_t *osh) +{ + return (osh->pub.pktalloced); +} + diff --git a/package/broadcom-wl/src/kmod/linux_osl.h b/package/broadcom-wl/src/kmod/linux_osl.h new file mode 100644 index 0000000000..f6af6124c6 --- /dev/null +++ b/package/broadcom-wl/src/kmod/linux_osl.h @@ -0,0 +1,171 @@ +/* + * Linux OS Independent Layer + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: linux_osl.h,v 1.1.1.13 2006/04/08 06:13:39 honor Exp $ + */ + +#ifndef _linux_osl_h_ +#define _linux_osl_h_ + +#include +#include +#include + +#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ + +/* osl handle type forward declaration */ +typedef struct osl_dmainfo osldma_t; + +/* OSL initialization */ +extern osl_t *osl_attach(void *pdev, bool pkttag); +extern void osl_detach(osl_t *osh); + +/* host/bus architecture-specific byte swap */ +#define BUS_SWAP32(v) (v) +#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) + +extern void *osl_malloc(osl_t *osh, uint size); +extern void osl_mfree(osl_t *osh, void *addr, uint size); +extern uint osl_malloced(osl_t *osh); +extern uint osl_malloc_failed(osl_t *osh); + +/* API for DMA addressing capability */ +#define DMA_MAP(osh, va, size, direction, p) \ + osl_dma_map((osh), (va), (size), (direction)) +#define DMA_UNMAP(osh, pa, size, direction, p) \ + osl_dma_unmap((osh), (pa), (size), (direction)) +static inline uint +osl_dma_map(void *osh, void *va, uint size, int direction) +{ + int dir; + struct pci_dev *dev; + + dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev); + dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; + return (pci_map_single(dev, va, size, dir)); +} + +static inline void +osl_dma_unmap(void *osh, uint pa, uint size, int direction) +{ + int dir; + struct pci_dev *dev; + + dev = (osh == NULL ? NULL : ((osl_t *)osh)->pdev); + dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; + pci_unmap_single(dev, (uint32)pa, size, dir); +} + +#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) +#define DMA_CONSISTENT_ALIGN PAGE_SIZE +#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah) \ + osl_dma_alloc_consistent((osh), (size), (pap)) +#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ + osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) +static inline void* +osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) +{ + return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); +} + +static inline void +osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) +{ + pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); +} + + +/* register access macros */ +#if defined(BCMJTAG) +#include +#define R_REG(osh, r) bcmjtag_read(NULL, (uint32)(r), sizeof(*(r))) +#define W_REG(osh, r, v) bcmjtag_write(NULL, (uint32)(r), (uint32)(v), sizeof(*(r))) +#endif /* defined(BCMSDIO) */ + +/* packet primitives */ +#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send)) +#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb)) +#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) +#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) +#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) +#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) +#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) +#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) +#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) +#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) +#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) +#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) +#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) +#define PKTALLOCED(osh) osl_pktalloced((osh)) +#define PKTLIST_DUMP(osh, buf) + +/* Convert a native(OS) packet to driver packet. + * In the process, native packet is destroyed, there is no copying + * Also, a packettag is zeroed out + */ +static INLINE void * +osl_pkt_frmnative(struct osl_pubinfo *osh, struct sk_buff *skb) +{ + struct sk_buff *nskb; + + if (osh->pkttag) + bzero((void*)skb->cb, OSL_PKTTAG_SZ); + + /* Increment the packet counter */ + for (nskb = skb; nskb; nskb = nskb->next) { + osh->pktalloced++; + } + + return (void *)skb; +} +#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((struct osl_pubinfo *)osh), \ + (struct sk_buff*)(skb)) + +/* Convert a driver packet to native(OS) packet + * In the process, packettag is zeroed out before sending up + * IP code depends on skb->cb to be setup correctly with various options + * In our case, that means it should be 0 + */ +static INLINE struct sk_buff * +osl_pkt_tonative(struct osl_pubinfo *osh, void *pkt) +{ + struct sk_buff *nskb; + + if (osh->pkttag) + bzero(((struct sk_buff*)pkt)->cb, OSL_PKTTAG_SZ); + + /* Decrement the packet counter */ + for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { + osh->pktalloced--; + } + + return (struct sk_buff *)pkt; +} +#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((struct osl_pubinfo *)(osh), (pkt)) + +#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) +#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) +#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) +#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) +#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) + +extern void *osl_pktget(osl_t *osh, uint len, bool send); +extern void osl_pktfree(osl_t *osh, void *skb); +extern void *osl_pktdup(osl_t *osh, void *skb); +extern uint osl_pktalloced(osl_t *osh); + +#define OSL_ERROR(bcmerror) osl_error(bcmerror) +extern int osl_error(int bcmerror); + +/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */ +#define PKTBUFSZ 2048 /* largest reasonable packet buffer, driver uses for ethernet MTU */ + +#endif /* _linux_osl_h_ */ diff --git a/package/broadcom-wl/src/kmod/patchtable.pl b/package/broadcom-wl/src/kmod/patchtable.pl new file mode 100644 index 0000000000..6144d8b925 --- /dev/null +++ b/package/broadcom-wl/src/kmod/patchtable.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +use strict; + +my $TABLE = pack("V", 0xbadc0ded); +my $TABLE_SIZE = 512; +my $SLT1 = "\x01\x00\x00\x00"; +my $SLT2 = "\x02\x00\x00\x00"; +my $ACKW = "\x03\x00\x00\x00"; +my $PTABLE_END = "\xff\xff\xff\xff"; + +my $addr = ""; +my $opcode = ""; +my $function = ""; + +sub add_entry { + my $key = shift; + my $value = shift; + my $default = shift; + + $TABLE .= $key; + $TABLE .= pack("V", $value); + $TABLE .= pack("V", $default); +} + +while (<>) { + $addr = $opcode = ""; + /^\w{8}\s*<(.*)>:$/ and $function = $1; + /^\s*(\w+):\s*(\w{8})\s*/ and do { + $addr = $1; + $opcode = $2; + }; + + ($function eq 'wlc_update_slot_timing') and do { + # li a2,9 -- short slot time + ($opcode eq '24060009') and add_entry($SLT1, hex($addr), hex($opcode)); + # li v0,519 -- 510 + short slot time + ($opcode eq '24020207') and add_entry($SLT2, hex($addr), hex($opcode)); + + # li a2,20 -- long slot time + ($opcode eq '24060014') and add_entry($SLT1, hex($addr), hex($opcode)); + # li v0,530 -- 510 + long slot time + ($opcode eq '24020212') and add_entry($SLT2, hex($addr), hex($opcode)); + }; + ($function eq 'wlc_d11hdrs') and do { + # ori s6,s6,0x1 -- ack flag (new) + ($opcode eq '36d60001') and add_entry($ACKW, hex($addr), hex($opcode)); + # ori s3,s3,0x1 -- ack flag (old) + ($opcode eq '36730001') and add_entry($ACKW, hex($addr), hex($opcode)); + } +} + +$TABLE .= $PTABLE_END; +$TABLE .= ("\x00" x ($TABLE_SIZE - length($TABLE))); +print $TABLE; diff --git a/package/broadcom-wl/src/kmod/pktq.h b/package/broadcom-wl/src/kmod/pktq.h new file mode 100644 index 0000000000..7fe21815e8 --- /dev/null +++ b/package/broadcom-wl/src/kmod/pktq.h @@ -0,0 +1,97 @@ +/* + * Misc useful os-independent macros and functions. + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $ + */ + +#ifndef _pktq_h_ +#define _pktq_h_ +#include + +/* osl multi-precedence packet queue */ + +#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ +#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ + +struct pktq { + struct pktq_prec { + void *head; /* first packet to dequeue */ + void *tail; /* last packet to dequeue */ + uint16 len; /* number of queued packets */ + uint16 max; /* maximum number of queued packets */ + } q[PKTQ_MAX_PREC]; + uint16 num_prec; /* number of precedences in use */ + uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ + uint16 max; /* total max packets */ + uint16 len; /* total number of packets */ +}; + +#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) + +/* forward definition of ether_addr structure used by some function prototypes */ + +struct ether_addr; + +/* operations on a specific precedence in packet queue */ + +#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) +#define pktq_plen(pq, prec) ((pq)->q[prec].len) +#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) +#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) +#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) + +#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) +#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) + +extern void *pktq_penq(struct pktq *pq, int prec, void *p); +extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); +extern void *pktq_pdeq(struct pktq *pq, int prec); +extern void *pktq_pdeq_tail(struct pktq *pq, int prec); +/* Empty the queue at particular precedence level */ +extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir); +/* Remove a specified packet from its queue */ +extern bool pktq_pdel(struct pktq *pq, void *p, int prec); + +/* operations on a set of precedences in packet queue */ + +extern int pktq_mlen(struct pktq *pq, uint prec_bmp); +extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); + +/* operations on packet queue as a whole */ + +#define pktq_len(pq) ((int)(pq)->len) +#define pktq_max(pq) ((int)(pq)->max) +#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) +#define pktq_full(pq) ((pq)->len >= (pq)->max) +#define pktq_empty(pq) ((pq)->len == 0) + +/* operations for single precedence queues */ +#define pktenq(pq, p) pktq_penq((pq), 0, (p)) +#define pktenq_head(pq, p) pktq_penq_head((pq), 0, (p)) +#define pktdeq(pq) pktq_pdeq((pq), 0) +#define pktdeq_tail(pq) pktq_pdeq_tail((pq), 0) + +extern void pktq_init(struct pktq *pq, int num_prec, int max_len); +/* prec_out may be NULL if caller is not interested in return value */ +extern void *pktq_deq(struct pktq *pq, int *prec_out); +extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); +extern void *pktq_peek(struct pktq *pq, int *prec_out); +extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); +extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir); /* Empty the entire queue */ + +/* externs */ +/* packet */ +extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); +extern uint pkttotlen(osl_t *osh, void *p); +extern void *pktlast(osl_t *osh, void *p); + +extern void pktsetprio(void *pkt, bool update_vtag); + +#endif /* _pktq_h_ */ diff --git a/package/broadcom-wl/src/kmod/sbhnddma.h b/package/broadcom-wl/src/kmod/sbhnddma.h new file mode 100644 index 0000000000..a26db7395e --- /dev/null +++ b/package/broadcom-wl/src/kmod/sbhnddma.h @@ -0,0 +1,284 @@ +/* + * Generic Broadcom Home Networking Division (HND) DMA engine HW interface + * This supports the following chips: BCM42xx, 44xx, 47xx . + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: sbhnddma.h,v 1.1.1.2 2006/02/27 03:43:16 honor Exp $ + */ + +#ifndef _sbhnddma_h_ +#define _sbhnddma_h_ + +/* DMA structure: + * support two DMA engines: 32 bits address or 64 bit addressing + * basic DMA register set is per channel(transmit or receive) + * a pair of channels is defined for convenience + */ + + +/* 32 bits addressing */ + +/* dma registers per channel(xmt or rcv) */ +typedef volatile struct { + uint32 control; /* enable, et al */ + uint32 addr; /* descriptor ring base address (4K aligned) */ + uint32 ptr; /* last descriptor posted to chip */ + uint32 status; /* current active descriptor, et al */ +} dma32regs_t; + +typedef volatile struct { + dma32regs_t xmt; /* dma tx channel */ + dma32regs_t rcv; /* dma rx channel */ +} dma32regp_t; + +typedef volatile struct { /* diag access */ + uint32 fifoaddr; /* diag address */ + uint32 fifodatalow; /* low 32bits of data */ + uint32 fifodatahigh; /* high 32bits of data */ + uint32 pad; /* reserved */ +} dma32diag_t; + +/* + * DMA Descriptor + * Descriptors are only read by the hardware, never written back. + */ +typedef volatile struct { + uint32 ctrl; /* misc control bits & bufcount */ + uint32 addr; /* data buffer address */ +} dma32dd_t; + +/* + * Each descriptor ring must be 4096byte aligned, and fit within a single 4096byte page. + */ +#define D32MAXRINGSZ 4096 +#define D32RINGALIGN 4096 +#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) + +/* transmit channel control */ +#define XC_XE ((uint32)1 << 0) /* transmit enable */ +#define XC_SE ((uint32)1 << 1) /* transmit suspend request */ +#define XC_LE ((uint32)1 << 2) /* loopback enable */ +#define XC_FL ((uint32)1 << 4) /* flush request */ +#define XC_AE ((uint32)3 << 16) /* address extension bits */ +#define XC_AE_SHIFT 16 + +/* transmit descriptor table pointer */ +#define XP_LD_MASK 0xfff /* last valid descriptor */ + +/* transmit channel status */ +#define XS_CD_MASK 0x0fff /* current descriptor pointer */ +#define XS_XS_MASK 0xf000 /* transmit state */ +#define XS_XS_SHIFT 12 +#define XS_XS_DISABLED 0x0000 /* disabled */ +#define XS_XS_ACTIVE 0x1000 /* active */ +#define XS_XS_IDLE 0x2000 /* idle wait */ +#define XS_XS_STOPPED 0x3000 /* stopped */ +#define XS_XS_SUSP 0x4000 /* suspend pending */ +#define XS_XE_MASK 0xf0000 /* transmit errors */ +#define XS_XE_SHIFT 16 +#define XS_XE_NOERR 0x00000 /* no error */ +#define XS_XE_DPE 0x10000 /* descriptor protocol error */ +#define XS_XE_DFU 0x20000 /* data fifo underrun */ +#define XS_XE_BEBR 0x30000 /* bus error on buffer read */ +#define XS_XE_BEDA 0x40000 /* bus error on descriptor access */ +#define XS_AD_MASK 0xfff00000 /* active descriptor */ +#define XS_AD_SHIFT 20 + +/* receive channel control */ +#define RC_RE ((uint32)1 << 0) /* receive enable */ +#define RC_RO_MASK 0xfe /* receive frame offset */ +#define RC_RO_SHIFT 1 +#define RC_FM ((uint32)1 << 8) /* direct fifo receive (pio) mode */ +#define RC_AE ((uint32)3 << 16) /* address extension bits */ +#define RC_AE_SHIFT 16 + +/* receive descriptor table pointer */ +#define RP_LD_MASK 0xfff /* last valid descriptor */ + +/* receive channel status */ +#define RS_CD_MASK 0x0fff /* current descriptor pointer */ +#define RS_RS_MASK 0xf000 /* receive state */ +#define RS_RS_SHIFT 12 +#define RS_RS_DISABLED 0x0000 /* disabled */ +#define RS_RS_ACTIVE 0x1000 /* active */ +#define RS_RS_IDLE 0x2000 /* idle wait */ +#define RS_RS_STOPPED 0x3000 /* reserved */ +#define RS_RE_MASK 0xf0000 /* receive errors */ +#define RS_RE_SHIFT 16 +#define RS_RE_NOERR 0x00000 /* no error */ +#define RS_RE_DPE 0x10000 /* descriptor protocol error */ +#define RS_RE_DFO 0x20000 /* data fifo overflow */ +#define RS_RE_BEBW 0x30000 /* bus error on buffer write */ +#define RS_RE_BEDA 0x40000 /* bus error on descriptor access */ +#define RS_AD_MASK 0xfff00000 /* active descriptor */ +#define RS_AD_SHIFT 20 + +/* fifoaddr */ +#define FA_OFF_MASK 0xffff /* offset */ +#define FA_SEL_MASK 0xf0000 /* select */ +#define FA_SEL_SHIFT 16 +#define FA_SEL_XDD 0x00000 /* transmit dma data */ +#define FA_SEL_XDP 0x10000 /* transmit dma pointers */ +#define FA_SEL_RDD 0x40000 /* receive dma data */ +#define FA_SEL_RDP 0x50000 /* receive dma pointers */ +#define FA_SEL_XFD 0x80000 /* transmit fifo data */ +#define FA_SEL_XFP 0x90000 /* transmit fifo pointers */ +#define FA_SEL_RFD 0xc0000 /* receive fifo data */ +#define FA_SEL_RFP 0xd0000 /* receive fifo pointers */ +#define FA_SEL_RSD 0xe0000 /* receive frame status data */ +#define FA_SEL_RSP 0xf0000 /* receive frame status pointers */ + +/* descriptor control flags */ +#define CTRL_BC_MASK 0x1fff /* buffer byte count */ +#define CTRL_AE ((uint32)3 << 16) /* address extension bits */ +#define CTRL_AE_SHIFT 16 +#define CTRL_EOT ((uint32)1 << 28) /* end of descriptor table */ +#define CTRL_IOC ((uint32)1 << 29) /* interrupt on completion */ +#define CTRL_EOF ((uint32)1 << 30) /* end of frame */ +#define CTRL_SOF ((uint32)1 << 31) /* start of frame */ + +/* control flags in the range [27:20] are core-specific and not defined here */ +#define CTRL_CORE_MASK 0x0ff00000 + +/* 64 bits addressing */ + +/* dma registers per channel(xmt or rcv) */ +typedef volatile struct { + uint32 control; /* enable, et al */ + uint32 ptr; /* last descriptor posted to chip */ + uint32 addrlow; /* descriptor ring base address low 32-bits (8K aligned) */ + uint32 addrhigh; /* descriptor ring base address bits 63:32 (8K aligned) */ + uint32 status0; /* current descriptor, xmt state */ + uint32 status1; /* active descriptor, xmt error */ +} dma64regs_t; + +typedef volatile struct { + dma64regs_t tx; /* dma64 tx channel */ + dma64regs_t rx; /* dma64 rx channel */ +} dma64regp_t; + +typedef volatile struct { /* diag access */ + uint32 fifoaddr; /* diag address */ + uint32 fifodatalow; /* low 32bits of data */ + uint32 fifodatahigh; /* high 32bits of data */ + uint32 pad; /* reserved */ +} dma64diag_t; + +/* + * DMA Descriptor + * Descriptors are only read by the hardware, never written back. + */ +typedef volatile struct { + uint32 ctrl1; /* misc control bits & bufcount */ + uint32 ctrl2; /* buffer count and address extension */ + uint32 addrlow; /* memory address of the date buffer, bits 31:0 */ + uint32 addrhigh; /* memory address of the date buffer, bits 63:32 */ +} dma64dd_t; + +/* + * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss. + */ +#define D64MAXRINGSZ 8192 +#define D64RINGALIGN 8192 +#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) + +/* transmit channel control */ +#define D64_XC_XE 0x00000001 /* transmit enable */ +#define D64_XC_SE 0x00000002 /* transmit suspend request */ +#define D64_XC_LE 0x00000004 /* loopback enable */ +#define D64_XC_FL 0x00000010 /* flush request */ +#define D64_XC_AE 0x00030000 /* address extension bits */ +#define D64_XC_AE_SHIFT 16 + +/* transmit descriptor table pointer */ +#define D64_XP_LD_MASK 0x00000fff /* last valid descriptor */ + +/* transmit channel status */ +#define D64_XS0_CD_MASK 0x00001fff /* current descriptor pointer */ +#define D64_XS0_XS_MASK 0xf0000000 /* transmit state */ +#define D64_XS0_XS_SHIFT 28 +#define D64_XS0_XS_DISABLED 0x00000000 /* disabled */ +#define D64_XS0_XS_ACTIVE 0x10000000 /* active */ +#define D64_XS0_XS_IDLE 0x20000000 /* idle wait */ +#define D64_XS0_XS_STOPPED 0x30000000 /* stopped */ +#define D64_XS0_XS_SUSP 0x40000000 /* suspend pending */ + +#define D64_XS1_AD_MASK 0x0001ffff /* active descriptor */ +#define D64_XS1_XE_MASK 0xf0000000 /* transmit errors */ +#define D64_XS1_XE_SHIFT 28 +#define D64_XS1_XE_NOERR 0x00000000 /* no error */ +#define D64_XS1_XE_DPE 0x10000000 /* descriptor protocol error */ +#define D64_XS1_XE_DFU 0x20000000 /* data fifo underrun */ +#define D64_XS1_XE_DTE 0x30000000 /* data transfer error */ +#define D64_XS1_XE_DESRE 0x40000000 /* descriptor read error */ +#define D64_XS1_XE_COREE 0x50000000 /* core error */ + +/* receive channel control */ +#define D64_RC_RE 0x00000001 /* receive enable */ +#define D64_RC_RO_MASK 0x000000fe /* receive frame offset */ +#define D64_RC_RO_SHIFT 1 +#define D64_RC_FM 0x00000100 /* direct fifo receive (pio) mode */ +#define D64_RC_AE 0x00030000 /* address extension bits */ +#define D64_RC_AE_SHIFT 16 + +/* receive descriptor table pointer */ +#define D64_RP_LD_MASK 0x00000fff /* last valid descriptor */ + +/* receive channel status */ +#define D64_RS0_CD_MASK 0x00001fff /* current descriptor pointer */ +#define D64_RS0_RS_MASK 0xf0000000 /* receive state */ +#define D64_RS0_RS_SHIFT 28 +#define D64_RS0_RS_DISABLED 0x00000000 /* disabled */ +#define D64_RS0_RS_ACTIVE 0x10000000 /* active */ +#define D64_RS0_RS_IDLE 0x20000000 /* idle wait */ +#define D64_RS0_RS_STOPPED 0x30000000 /* stopped */ +#define D64_RS0_RS_SUSP 0x40000000 /* suspend pending */ + +#define D64_RS1_AD_MASK 0x0001ffff /* active descriptor */ +#define D64_RS1_RE_MASK 0xf0000000 /* receive errors */ +#define D64_RS1_RE_SHIFT 28 +#define D64_RS1_RE_NOERR 0x00000000 /* no error */ +#define D64_RS1_RE_DPO 0x10000000 /* descriptor protocol error */ +#define D64_RS1_RE_DFU 0x20000000 /* data fifo overflow */ +#define D64_RS1_RE_DTE 0x30000000 /* data transfer error */ +#define D64_RS1_RE_DESRE 0x40000000 /* descriptor read error */ +#define D64_RS1_RE_COREE 0x50000000 /* core error */ + +/* fifoaddr */ +#define D64_FA_OFF_MASK 0xffff /* offset */ +#define D64_FA_SEL_MASK 0xf0000 /* select */ +#define D64_FA_SEL_SHIFT 16 +#define D64_FA_SEL_XDD 0x00000 /* transmit dma data */ +#define D64_FA_SEL_XDP 0x10000 /* transmit dma pointers */ +#define D64_FA_SEL_RDD 0x40000 /* receive dma data */ +#define D64_FA_SEL_RDP 0x50000 /* receive dma pointers */ +#define D64_FA_SEL_XFD 0x80000 /* transmit fifo data */ +#define D64_FA_SEL_XFP 0x90000 /* transmit fifo pointers */ +#define D64_FA_SEL_RFD 0xc0000 /* receive fifo data */ +#define D64_FA_SEL_RFP 0xd0000 /* receive fifo pointers */ +#define D64_FA_SEL_RSD 0xe0000 /* receive frame status data */ +#define D64_FA_SEL_RSP 0xf0000 /* receive frame status pointers */ + +/* descriptor control flags 1 */ +#define D64_CTRL1_EOT ((uint32)1 << 28) /* end of descriptor table */ +#define D64_CTRL1_IOC ((uint32)1 << 29) /* interrupt on completion */ +#define D64_CTRL1_EOF ((uint32)1 << 30) /* end of frame */ +#define D64_CTRL1_SOF ((uint32)1 << 31) /* start of frame */ + +/* descriptor control flags 2 */ +#define D64_CTRL2_BC_MASK 0x00007fff /* buffer byte count mask */ +#define D64_CTRL2_AE 0x00030000 /* address extension bits */ +#define D64_CTRL2_AE_SHIFT 16 + +/* control flags in the range [27:20] are core-specific and not defined here */ +#define D64_CTRL_CORE_MASK 0x0ff00000 + + +#endif /* _sbhnddma_h_ */ diff --git a/package/broadcom-wl/src/wlc/Makefile b/package/broadcom-wl/src/wlc/Makefile new file mode 100644 index 0000000000..ffe1649515 --- /dev/null +++ b/package/broadcom-wl/src/wlc/Makefile @@ -0,0 +1,9 @@ +all: wlc +clean: + rm -f *.o wlc + +wlc: wlc.o ioctl.o +%.o: %.c + $(CC) $(CFLAGS) -Wall -c -o $@ $< + +.PHONY: all clean diff --git a/package/broadcom-wl/src/wlc/include/bcmdefs.h b/package/broadcom-wl/src/wlc/include/bcmdefs.h new file mode 100644 index 0000000000..8b5abe5d26 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/bcmdefs.h @@ -0,0 +1,106 @@ +/* + * Misc system wide definitions + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: bcmdefs.h,v 1.1.1.3 2006/04/08 06:13:39 honor Exp $ + */ + +#ifndef _bcmdefs_h_ +#define _bcmdefs_h_ + +/* + * One doesn't need to include this file explicitly, gets included automatically if + * typedefs.h is included. + */ + +/* Reclaiming text and data : + * The following macros specify special linker sections that can be reclaimed + * after a system is considered 'up'. + */ +#if defined(__GNUC__) && defined(BCMRECLAIM) +extern bool bcmreclaimed; +#define BCMINITDATA(_data) __attribute__ ((__section__ (".dataini." #_data))) _data +#define BCMINITFN(_fn) __attribute__ ((__section__ (".textini." #_fn))) _fn +#else /* #if defined(__GNUC__) && defined(BCMRECLAIM) */ +#define BCMINITDATA(_data) _data +#define BCMINITFN(_fn) _fn +#define bcmreclaimed 0 +#endif /* #if defined(__GNUC__) && defined(BCMRECLAIM) */ + +/* Reclaim uninit functions if BCMNODOWN is defined */ +/* and if they are not already removed by -gc-sections */ +#ifdef BCMNODOWN +#define BCMUNINITFN(_fn) BCMINITFN(_fn) +#else +#define BCMUNINITFN(_fn) _fn +#endif + +#ifdef BCMRECLAIM +#define CONST +#else +#define CONST const +#endif /* BCMRECLAIM */ + +/* Compatibility with old-style BCMRECLAIM */ +#define BCMINIT(_id) _id + + +/* Put some library data/code into ROM to reduce RAM requirements */ +#if defined(__GNUC__) && defined(BCMROMOFFLOAD) +#define BCMROMDATA(_data) __attribute__ ((__section__ (".datarom." #_data))) _data +#define BCMROMFN(_fn) __attribute__ ((__section__ (".textrom." #_fn))) _fn +#else +#define BCMROMDATA(_data) _data +#define BCMROMFN(_fn) _fn +#endif + +/* Bus types */ +#define SB_BUS 0 /* Silicon Backplane */ +#define PCI_BUS 1 /* PCI target */ +#define PCMCIA_BUS 2 /* PCMCIA target */ +#define SDIO_BUS 3 /* SDIO target */ +#define JTAG_BUS 4 /* JTAG */ +#define NO_BUS 0xFF /* Bus that does not support R/W REG */ + +/* Allows optimization for single-bus support */ +#ifdef BCMBUSTYPE +#define BUSTYPE(bus) (BCMBUSTYPE) +#else +#define BUSTYPE(bus) (bus) +#endif + +/* Defines for DMA Address Width - Shared between OSL and HNDDMA */ +#define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ +#define DMADDR_MASK_30 0xc0000000 /* Address mask for 30-bits */ +#define DMADDR_MASK_0 0xffffffff /* Address mask for 0-bits (hi-part) */ + +#define DMADDRWIDTH_30 30 /* 30-bit addressing capability */ +#define DMADDRWIDTH_32 32 /* 32-bit addressing capability */ +#define DMADDRWIDTH_63 63 /* 64-bit addressing capability */ +#define DMADDRWIDTH_64 64 /* 64-bit addressing capability */ + +/* packet headroom necessary to accomodate the largest header in the system, (i.e TXOFF). + * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. + * There is a compile time check in wlc.c which ensure that this value is at least as big + * as TXOFF. This value is used in dma_rxfill (hnddma.c). + */ +#define BCMEXTRAHDROOM 160 + +/* Headroom required for dongle-to-host communication. Packets allocated + * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should + * leave this much room in front for low-level message headers which may + * be needed to get across the dongle bus to the host. (These messages + * don't go over the network, so room for the full WL header above would + * be a waste.) + */ +#define BCMDONGLEHDRSZ 8 + + + +#endif /* _bcmdefs_h_ */ diff --git a/package/broadcom-wl/src/wlc/include/bcmutils.h b/package/broadcom-wl/src/wlc/include/bcmutils.h new file mode 100644 index 0000000000..b6e7b0542b --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/bcmutils.h @@ -0,0 +1,258 @@ +/* + * Misc useful os-independent macros and functions. + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: bcmutils.h,v 1.1.1.16 2006/04/08 06:13:39 honor Exp $ + */ + +#ifndef _bcmutils_h_ +#define _bcmutils_h_ + +/* ** driver/apps-shared section ** */ + +#define BCME_STRLEN 64 /* Max string length for BCM errors */ +#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) + + +/* + * error codes could be added but the defined ones shouldn't be changed/deleted + * these error codes are exposed to the user code + * when ever a new error code is added to this list + * please update errorstring table with the related error string and + * update osl files with os specific errorcode map +*/ + +#define BCME_OK 0 /* Success */ +#define BCME_ERROR -1 /* Error generic */ +#define BCME_BADARG -2 /* Bad Argument */ +#define BCME_BADOPTION -3 /* Bad option */ +#define BCME_NOTUP -4 /* Not up */ +#define BCME_NOTDOWN -5 /* Not down */ +#define BCME_NOTAP -6 /* Not AP */ +#define BCME_NOTSTA -7 /* Not STA */ +#define BCME_BADKEYIDX -8 /* BAD Key Index */ +#define BCME_RADIOOFF -9 /* Radio Off */ +#define BCME_NOTBANDLOCKED -10 /* Not band locked */ +#define BCME_NOCLK -11 /* No Clock */ +#define BCME_BADRATESET -12 /* BAD Rate valueset */ +#define BCME_BADBAND -13 /* BAD Band */ +#define BCME_BUFTOOSHORT -14 /* Buffer too short */ +#define BCME_BUFTOOLONG -15 /* Buffer too long */ +#define BCME_BUSY -16 /* Busy */ +#define BCME_NOTASSOCIATED -17 /* Not Associated */ +#define BCME_BADSSIDLEN -18 /* Bad SSID len */ +#define BCME_OUTOFRANGECHAN -19 /* Out of Range Channel */ +#define BCME_BADCHAN -20 /* Bad Channel */ +#define BCME_BADADDR -21 /* Bad Address */ +#define BCME_NORESOURCE -22 /* Not Enough Resources */ +#define BCME_UNSUPPORTED -23 /* Unsupported */ +#define BCME_BADLEN -24 /* Bad length */ +#define BCME_NOTREADY -25 /* Not Ready */ +#define BCME_EPERM -26 /* Not Permitted */ +#define BCME_NOMEM -27 /* No Memory */ +#define BCME_ASSOCIATED -28 /* Associated */ +#define BCME_RANGE -29 /* Not In Range */ +#define BCME_NOTFOUND -30 /* Not Found */ +#define BCME_WME_NOT_ENABLED -31 /* WME Not Enabled */ +#define BCME_TSPEC_NOTFOUND -32 /* TSPEC Not Found */ +#define BCME_ACM_NOTSUPPORTED -33 /* ACM Not Supported */ +#define BCME_NOT_WME_ASSOCIATION -34 /* Not WME Association */ +#define BCME_SDIO_ERROR -35 /* SDIO Bus Error */ +#define BCME_DONGLE_DOWN -36 /* Dongle Not Accessible */ +#define BCME_LAST BCME_DONGLE_DOWN + +/* These are collection of BCME Error strings */ +#define BCMERRSTRINGTABLE { \ + "OK", \ + "Undefined error", \ + "Bad Argument", \ + "Bad Option", \ + "Not up", \ + "Not down", \ + "Not AP", \ + "Not STA", \ + "Bad Key Index", \ + "Radio Off", \ + "Not band locked", \ + "No clock", \ + "Bad Rate valueset", \ + "Bad Band", \ + "Buffer too short", \ + "Buffer too long", \ + "Busy", \ + "Not Associated", \ + "Bad SSID len", \ + "Out of Range Channel", \ + "Bad Channel", \ + "Bad Address", \ + "Not Enough Resources", \ + "Unsupported", \ + "Bad length", \ + "Not Ready", \ + "Not Permitted", \ + "No Memory", \ + "Associated", \ + "Not In Range", \ + "Not Found", \ + "WME Not Enabled", \ + "TSPEC Not Found", \ + "ACM Not Supported", \ + "Not WME Association", \ + "SDIO Bus Error", \ + "Dongle Not Accessible" \ +} + +#ifndef ABS +#define ABS(a) (((a) < 0)?-(a):(a)) +#endif /* ABS */ + +#ifndef MIN +#define MIN(a, b) (((a) < (b))?(a):(b)) +#endif /* MIN */ + +#ifndef MAX +#define MAX(a, b) (((a) > (b))?(a):(b)) +#endif /* MAX */ + +#define CEIL(x, y) (((x) + ((y)-1)) / (y)) +#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) +#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) +#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) +#define VALID_MASK(mask) !((mask) & ((mask) + 1)) +#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) + +/* bit map related macros */ +#ifndef setbit +#ifndef NBBY /* the BSD family defines NBBY */ +#define NBBY 8 /* 8 bits per byte */ +#endif /* #ifndef NBBY */ +#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a, i) (((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a, i) ((((uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) +#endif /* setbit */ + +#define NBITS(type) (sizeof(type) * 8) +#define NBITVAL(nbits) (1 << (nbits)) +#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) +#define NBITMASK(nbits) MAXBITVAL(nbits) +#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) + +/* basic mux operation - can be optimized on several architectures */ +#define MUX(pred, true, false) ((pred) ? (true) : (false)) + +/* modulo inc/dec - assumes x E [0, bound - 1] */ +#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) +#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) + +/* modulo inc/dec, bound = 2^k */ +#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) +#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) + +/* modulo add/sub - assumes x, y E [0, bound - 1] */ +#define MODADD(x, y, bound) \ + MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) +#define MODSUB(x, y, bound) \ + MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) + +/* module add/sub, bound = 2^k */ +#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) +#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) + +/* crc defines */ +#define CRC8_INIT_VALUE 0xff /* Initial CRC8 checksum value */ +#define CRC8_GOOD_VALUE 0x9f /* Good final CRC8 checksum value */ +#define CRC16_INIT_VALUE 0xffff /* Initial CRC16 checksum value */ +#define CRC16_GOOD_VALUE 0xf0b8 /* Good final CRC16 checksum value */ +#define CRC32_INIT_VALUE 0xffffffff /* Initial CRC32 checksum value */ +#define CRC32_GOOD_VALUE 0xdebb20e3 /* Good final CRC32 checksum value */ + +/* bcm_format_flags() bit description structure */ +typedef struct bcm_bit_desc { + uint32 bit; + char* name; +} bcm_bit_desc_t; + +/* tag_ID/length/value_buffer tuple */ +typedef struct bcm_tlv { + uint8 id; + uint8 len; + uint8 data[1]; +} bcm_tlv_t; + +/* Check that bcm_tlv_t fits into the given buflen */ +#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) + +/* buffer length for ethernet address from bcm_ether_ntoa() */ +#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */ + +/* unaligned load and store macros */ +#ifdef IL_BIGENDIAN +static INLINE uint32 +load32_ua(uint8 *a) +{ + return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]); +} + +static INLINE void +store32_ua(uint8 *a, uint32 v) +{ + a[0] = (v >> 24) & 0xff; + a[1] = (v >> 16) & 0xff; + a[2] = (v >> 8) & 0xff; + a[3] = v & 0xff; +} + +static INLINE uint16 +load16_ua(uint8 *a) +{ + return ((a[0] << 8) | a[1]); +} + +static INLINE void +store16_ua(uint8 *a, uint16 v) +{ + a[0] = (v >> 8) & 0xff; + a[1] = v & 0xff; +} + +#else + +static INLINE uint32 +load32_ua(uint8 *a) +{ + return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]); +} + +static INLINE void +store32_ua(uint8 *a, uint32 v) +{ + a[3] = (v >> 24) & 0xff; + a[2] = (v >> 16) & 0xff; + a[1] = (v >> 8) & 0xff; + a[0] = v & 0xff; +} + +static INLINE uint16 +load16_ua(uint8 *a) +{ + return ((a[1] << 8) | a[0]); +} + +static INLINE void +store16_ua(uint8 *a, uint16 v) +{ + a[1] = (v >> 8) & 0xff; + a[0] = v & 0xff; +} + +#endif /* IL_BIGENDIAN */ + +#endif /* _bcmutils_h_ */ diff --git a/package/broadcom-wl/src/wlc/include/proto/802.11.h b/package/broadcom-wl/src/wlc/include/proto/802.11.h new file mode 100644 index 0000000000..2b1c4ee111 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/proto/802.11.h @@ -0,0 +1,1258 @@ +/* + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * Fundamental types and constants relating to 802.11 + * + * $Id: 802.11.h,v 1.1.1.17 2006/04/15 01:29:08 michael Exp $ + */ + +#ifndef _802_11_H_ +#define _802_11_H_ + +#ifndef _TYPEDEFS_H_ +#include +#endif + +#ifndef _NET_ETHERNET_H_ +#include +#endif + +#include + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ + +/* Generic 802.11 frame constants */ +#define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ +#define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ +#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ +#define DOT11_FCS_LEN 4 /* d11 FCS length */ +#define DOT11_ICV_LEN 4 /* d11 ICV length */ +#define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ +#define DOT11_QOS_LEN 2 /* d11 QoS length */ +#define DOT11_HTC_LEN 4 /* d11 HT Control field length */ + +#define DOT11_KEY_INDEX_SHIFT 6 /* d11 key index shift */ +#define DOT11_IV_LEN 4 /* d11 IV length */ +#define DOT11_IV_TKIP_LEN 8 /* d11 IV TKIP length */ +#define DOT11_IV_AES_OCB_LEN 4 /* d11 IV/AES/OCB length */ +#define DOT11_IV_AES_CCM_LEN 8 /* d11 IV/AES/CCM length */ +#define DOT11_IV_MAX_LEN 8 /* maximum iv len for any encryption */ + +/* Includes MIC */ +#define DOT11_MAX_MPDU_BODY_LEN 2304 /* max MPDU body length */ +/* A4 header + QoS + CCMP + PDU + ICV + FCS = 2352 */ +#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ + DOT11_QOS_LEN + \ + DOT11_IV_AES_CCM_LEN + \ + DOT11_MAX_MPDU_BODY_LEN + \ + DOT11_ICV_LEN + \ + DOT11_FCS_LEN) /* d11 max MPDU length */ + +#define DOT11_MAX_SSID_LEN 32 /* d11 max ssid length */ + +/* dot11RTSThreshold */ +#define DOT11_DEFAULT_RTS_LEN 2347 /* d11 default RTS length */ +#define DOT11_MAX_RTS_LEN 2347 /* d11 max RTS length */ + +/* dot11FragmentationThreshold */ +#define DOT11_MIN_FRAG_LEN 256 /* d11 min fragmentation length */ +#define DOT11_MAX_FRAG_LEN 2346 /* Max frag is also limited by aMPDUMaxLength + * of the attached PHY + */ +#define DOT11_DEFAULT_FRAG_LEN 2346 /* d11 default fragmentation length */ + +/* dot11BeaconPeriod */ +#define DOT11_MIN_BEACON_PERIOD 1 /* d11 min beacon period */ +#define DOT11_MAX_BEACON_PERIOD 0xFFFF /* d11 max beacon period */ + +/* dot11DTIMPeriod */ +#define DOT11_MIN_DTIM_PERIOD 1 /* d11 min DTIM period */ +#define DOT11_MAX_DTIM_PERIOD 0xFF /* d11 max DTIM period */ + +/* 802.2 LLC/SNAP header used by 802.11 per 802.1H */ +#define DOT11_LLC_SNAP_HDR_LEN 8 /* d11 LLC/SNAP header length */ +#define DOT11_OUI_LEN 3 /* d11 OUI length */ +struct dot11_llc_snap_header { + uint8 dsap; /* always 0xAA */ + uint8 ssap; /* always 0xAA */ + uint8 ctl; /* always 0x03 */ + uint8 oui[DOT11_OUI_LEN]; /* RFC1042: 0x00 0x00 0x00 + * Bridge-Tunnel: 0x00 0x00 0xF8 + */ + uint16 type; /* ethertype */ +} PACKED; + +/* RFC1042 header used by 802.11 per 802.1H */ +#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) /* RCF1042 header length */ + +/* Generic 802.11 MAC header */ +/* + * N.B.: This struct reflects the full 4 address 802.11 MAC header. + * The fields are defined such that the shorter 1, 2, and 3 + * address headers just use the first k fields. + */ +struct dot11_header { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr a1; /* address 1 */ + struct ether_addr a2; /* address 2 */ + struct ether_addr a3; /* address 3 */ + uint16 seq; /* sequence control */ + struct ether_addr a4; /* address 4 */ +} PACKED; + +/* Control frames */ + +struct dot11_rts_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ + struct ether_addr ta; /* transmitter address */ +} PACKED; +#define DOT11_RTS_LEN 16 /* d11 RTS frame length */ + +struct dot11_cts_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ +} PACKED; +#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ + +struct dot11_ack_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ +} PACKED; +#define DOT11_ACK_LEN 10 /* d11 ACK frame length */ + +struct dot11_ps_poll_frame { + uint16 fc; /* frame control */ + uint16 durid; /* AID */ + struct ether_addr bssid; /* receiver address, STA in AP */ + struct ether_addr ta; /* transmitter address */ +} PACKED; +#define DOT11_PS_POLL_LEN 16 /* d11 PS poll frame length */ + +struct dot11_cf_end_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ + struct ether_addr bssid; /* transmitter address, STA in AP */ +} PACKED; +#define DOT11_CS_END_LEN 16 /* d11 CF-END frame length */ + +/* BA/BAR Control parameters */ +#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 /* normal ack */ +#define DOT11_BA_CTL_POLICY_NOACK 0x0001 /* no ack */ +#define DOT11_BA_CTL_POLICY_MASK 0x0001 /* ack policy mask */ + +#define DOT11_BA_CTL_MTID 0x0002 /* multi tid BA */ +#define DOT11_BA_CTL_COMPRESSED 0x0004 /* compressed bitmap */ + +#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 /* num msdu in bitmap mask */ +#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 /* num msdu in bitmap shift */ + +#define DOT11_BA_CTL_TID_MASK 0xF000 /* tid mask */ +#define DOT11_BA_CTL_TID_SHIFT 12 /* tid shift */ + +struct dot11_ba_req_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ + struct ether_addr ta; /* transmitter address */ + uint16 bar_control; /* BAR Control */ + uint16 seqnum; /* Starting Sequence control */ +} PACKED; +#define DOT11_BA_REQ_LEN 20 /* BAR frame length */ + +#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ +#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ +struct dot11_ba_frame { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ + struct ether_addr ta; /* transmitter address */ + uint16 ba_control; /* BA Control */ + uint16 seqnum; /* Starting Sequence control */ + uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ +} PACKED; +#define DOT11_BA_LEN 20 /* BA frame length (without bitmap) */ + +/* Management frame header */ +struct dot11_management_header { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr da; /* receiver address */ + struct ether_addr sa; /* transmitter address */ + struct ether_addr bssid; /* BSS ID */ + uint16 seq; /* sequence control */ +} PACKED; +#define DOT11_MGMT_HDR_LEN 24 /* d11 management header length */ + +/* Management frame payloads */ + +struct dot11_bcn_prb { + uint32 timestamp[2]; + uint16 beacon_interval; + uint16 capability; +} PACKED; +#define DOT11_BCN_PRB_LEN 12 /* d11 beacon probe frame length */ + +struct dot11_auth { + uint16 alg; /* algorithm */ + uint16 seq; /* sequence control */ + uint16 status; /* status code */ +} PACKED; +#define DOT11_AUTH_FIXED_LEN 6 /* length of auth frame without challenge info + * elt + */ + +struct dot11_assoc_req { + uint16 capability; /* capability information */ + uint16 listen; /* listen interval */ +} PACKED; +#define DOT11_ASSOC_REQ_FIXED_LEN 4 /* length of assoc frame without info elts */ + +struct dot11_reassoc_req { + uint16 capability; /* capability information */ + uint16 listen; /* listen interval */ + struct ether_addr ap; /* Current AP address */ +} PACKED; +#define DOT11_REASSOC_REQ_FIXED_LEN 10 /* length of assoc frame without info elts */ + +struct dot11_assoc_resp { + uint16 capability; /* capability information */ + uint16 status; /* status code */ + uint16 aid; /* association ID */ +} PACKED; + +struct dot11_action_measure { + uint8 category; + uint8 action; + uint8 token; + uint8 data[1]; +} PACKED; +#define DOT11_ACTION_MEASURE_LEN 3 /* d11 action measurement header length */ + +struct dot11_action_switch_channel { + uint8 category; + uint8 action; + uint8 data[5]; /* for switch IE */ +} PACKED; + +struct dot11_action_ht_ch_width { + uint8 category; + uint8 action; + uint8 ch_width; +} PACKED; + +struct dot11_action_ht_mimops { + uint8 category; + uint8 action; + uint8 enable; + uint8 psmode; +} PACKED; + +/* ************* 802.11h related definitions. ************* */ +typedef struct { + uint8 id; + uint8 len; + uint8 power; +} dot11_power_cnst_t; + +typedef struct { + uint8 min; + uint8 max; +} dot11_power_cap_t; + +typedef struct { + uint8 id; + uint8 len; + uint8 tx_pwr; + uint8 margin; +} dot11_tpc_rep_t; +#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ + +typedef struct { + uint8 id; + uint8 len; + uint8 first_channel; + uint8 num_channels; +} dot11_supp_channels_t; + +/* channel switch announcement (CSA) mode type - 802.11h-2003 $7.3.2.20 */ +#define DOT11_CSA_MODE_ADVISORY 0 /* no DOT11_CSA_MODE_NO_TX restriction imposed */ +#define DOT11_CSA_MODE_NO_TX 1 /* no transmission upon receiving CSA frame. */ + +/* CSA IE data structure */ +struct dot11_channel_switch { + uint8 id; + uint8 len; + uint8 mode; + uint8 channel; + uint8 count; +} PACKED; +typedef struct dot11_channel_switch dot11_channel_switch_t; + +#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ + +/* 802.11h Measurement Request/Report IEs */ +/* Measurement Type field */ +#define DOT11_MEASURE_TYPE_BASIC 0 /* d11 measurement basic type */ +#define DOT11_MEASURE_TYPE_CCA 1 /* d11 measurement CCA type */ +#define DOT11_MEASURE_TYPE_RPI 2 /* d11 measurement PRI type */ + +/* Measurement Mode field */ + +/* Measurement Request Modes */ +#define DOT11_MEASURE_MODE_ENABLE (1<<1) /* d11 measurement enable */ +#define DOT11_MEASURE_MODE_REQUEST (1<<2) /* d11 measurement request */ +#define DOT11_MEASURE_MODE_REPORT (1<<3) /* d11 measurement report */ +/* Measurement Report Modes */ +#define DOT11_MEASURE_MODE_LATE (1<<0) /* d11 measurement late */ +#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) /* d11 measurement incapable */ +#define DOT11_MEASURE_MODE_REFUSED (1<<2) /* d11 measurement refuse */ +/* Basic Measurement Map bits */ +#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) /* d11 measurement basic map BSS */ +#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) /* d11 measurement map OFDM */ +#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) /* d11 measurement map unknown */ +#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) /* d11 measurement map radar */ +#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) /* d11 measurement map unmeasuremnt */ + +typedef struct { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint8 channel; + uint8 start_time[8]; + uint16 duration; +} dot11_meas_req_t; +#define DOT11_MNG_IE_MREQ_LEN 14 /* d11 measurement request IE length */ +/* length of Measure Request IE data not including variable len */ +#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 /* d11 measurement request IE fixed length */ + +struct dot11_meas_rep { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + union + { + struct { + uint8 channel; + uint8 start_time[8]; + uint16 duration; + uint8 map; + } PACKED basic; + uint8 data[1]; + } PACKED rep; +} PACKED; +typedef struct dot11_meas_rep dot11_meas_rep_t; + +/* length of Measure Report IE data not including variable len */ +#define DOT11_MNG_IE_MREP_FIXED_LEN 3 /* d11 measurement response IE fixed length */ + +struct dot11_meas_rep_basic { + uint8 channel; + uint8 start_time[8]; + uint16 duration; + uint8 map; +} PACKED; +typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; +#define DOT11_MEASURE_BASIC_REP_LEN 12 /* d11 measurement basic report length */ + +struct dot11_quiet { + uint8 id; + uint8 len; + uint8 count; /* TBTTs until beacon interval in quiet starts */ + uint8 period; /* Beacon intervals between periodic quiet periods ? */ + uint16 duration; /* Length of quiet period, in TU's */ + uint16 offset; /* TU's offset from TBTT in Count field */ +} PACKED; +typedef struct dot11_quiet dot11_quiet_t; + +typedef struct { + uint8 channel; + uint8 map; +} chan_map_tuple_t; + +typedef struct { + uint8 id; + uint8 len; + uint8 eaddr[ETHER_ADDR_LEN]; + uint8 interval; + chan_map_tuple_t map[1]; +} dot11_ibss_dfs_t; + +/* WME Elements */ +#define WME_OUI "\x00\x50\xf2" /* WME OUI */ +#define WME_VER 1 /* WME version */ +#define WME_TYPE 2 /* WME type */ +#define WME_SUBTYPE_IE 0 /* Information Element */ +#define WME_SUBTYPE_PARAM_IE 1 /* Parameter Element */ +#define WME_SUBTYPE_TSPEC 2 /* Traffic Specification */ + +/* WME Access Category Indices (ACIs) */ +#define AC_BE 0 /* Best Effort */ +#define AC_BK 1 /* Background */ +#define AC_VI 2 /* Video */ +#define AC_VO 3 /* Voice */ +#define AC_COUNT 4 /* number of ACs */ + +typedef uint8 ac_bitmap_t; /* AC bitmap of (1 << AC_xx) */ + +#define AC_BITMAP_NONE 0x0 /* No ACs */ +#define AC_BITMAP_ALL 0xf /* All ACs */ +#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) + +/* WME Information Element (IE) */ +struct wme_ie { + uint8 oui[3]; + uint8 type; + uint8 subtype; + uint8 version; + uint8 qosinfo; +} PACKED; +typedef struct wme_ie wme_ie_t; +#define WME_IE_LEN 7 /* WME IE length */ + +struct edcf_acparam { + uint8 ACI; + uint8 ECW; + uint16 TXOP; /* stored in network order (ls octet first) */ +} PACKED; +typedef struct edcf_acparam edcf_acparam_t; + +/* WME Parameter Element (PE) */ +struct wme_param_ie { + uint8 oui[3]; + uint8 type; + uint8 subtype; + uint8 version; + uint8 qosinfo; + uint8 rsvd; + edcf_acparam_t acparam[AC_COUNT]; +} PACKED; +typedef struct wme_param_ie wme_param_ie_t; +#define WME_PARAM_IE_LEN 24 /* WME Parameter IE length */ + +/* QoS Info field for IE as sent from AP */ +#define WME_QI_AP_APSD_MASK 0x80 /* U-APSD Supported mask */ +#define WME_QI_AP_APSD_SHIFT 7 /* U-APSD Supported shift */ +#define WME_QI_AP_COUNT_MASK 0x0f /* Parameter set count mask */ +#define WME_QI_AP_COUNT_SHIFT 0 /* Parameter set count shift */ + +/* QoS Info field for IE as sent from STA */ +#define WME_QI_STA_MAXSPLEN_MASK 0x60 /* Max Service Period Length mask */ +#define WME_QI_STA_MAXSPLEN_SHIFT 5 /* Max Service Period Length shift */ +#define WME_QI_STA_APSD_ALL_MASK 0xf /* APSD all AC bits mask */ +#define WME_QI_STA_APSD_ALL_SHIFT 0 /* APSD all AC bits shift */ +#define WME_QI_STA_APSD_BE_MASK 0x8 /* APSD AC_BE mask */ +#define WME_QI_STA_APSD_BE_SHIFT 3 /* APSD AC_BE shift */ +#define WME_QI_STA_APSD_BK_MASK 0x4 /* APSD AC_BK mask */ +#define WME_QI_STA_APSD_BK_SHIFT 2 /* APSD AC_BK shift */ +#define WME_QI_STA_APSD_VI_MASK 0x2 /* APSD AC_VI mask */ +#define WME_QI_STA_APSD_VI_SHIFT 1 /* APSD AC_VI shift */ +#define WME_QI_STA_APSD_VO_MASK 0x1 /* APSD AC_VO mask */ +#define WME_QI_STA_APSD_VO_SHIFT 0 /* APSD AC_VO shift */ + +/* ACI */ +#define EDCF_AIFSN_MIN 1 /* AIFSN minimum value */ +#define EDCF_AIFSN_MAX 15 /* AIFSN maximum value */ +#define EDCF_AIFSN_MASK 0x0f /* AIFSN mask */ +#define EDCF_ACM_MASK 0x10 /* ACM mask */ +#define EDCF_ACI_MASK 0x60 /* ACI mask */ +#define EDCF_ACI_SHIFT 5 /* ACI shift */ + +/* ECW */ +#define EDCF_ECW_MIN 0 /* cwmin/cwmax exponent minimum value */ +#define EDCF_ECW_MAX 15 /* cwmin/cwmax exponent maximum value */ +#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) +#define EDCF_ECWMIN_MASK 0x0f /* cwmin exponent form mask */ +#define EDCF_ECWMAX_MASK 0xf0 /* cwmax exponent form mask */ +#define EDCF_ECWMAX_SHIFT 4 /* cwmax exponent form shift */ + +/* TXOP */ +#define EDCF_TXOP_MIN 0 /* TXOP minimum value */ +#define EDCF_TXOP_MAX 65535 /* TXOP maximum value */ +#define EDCF_TXOP2USEC(txop) ((txop) << 5) + +/* Default EDCF parameters that AP advertises for STA to use; WMM draft Table 12 */ +#define EDCF_AC_BE_ACI_STA 0x03 /* STA ACI value for best effort AC */ +#define EDCF_AC_BE_ECW_STA 0xA4 /* STA ECW value for best effort AC */ +#define EDCF_AC_BE_TXOP_STA 0x0000 /* STA TXOP value for best effort AC */ +#define EDCF_AC_BK_ACI_STA 0x27 /* STA ACI value for background AC */ +#define EDCF_AC_BK_ECW_STA 0xA4 /* STA ECW value for background AC */ +#define EDCF_AC_BK_TXOP_STA 0x0000 /* STA TXOP value for background AC */ +#define EDCF_AC_VI_ACI_STA 0x42 /* STA ACI value for video AC */ +#define EDCF_AC_VI_ECW_STA 0x43 /* STA ECW value for video AC */ +#define EDCF_AC_VI_TXOP_STA 0x005e /* STA TXOP value for video AC */ +#define EDCF_AC_VO_ACI_STA 0x62 /* STA ACI value for audio AC */ +#define EDCF_AC_VO_ECW_STA 0x32 /* STA ECW value for audio AC */ +#define EDCF_AC_VO_TXOP_STA 0x002f /* STA TXOP value for audio AC */ + +/* Default EDCF parameters that AP uses; WMM draft Table 14 */ +#define EDCF_AC_BE_ACI_AP 0x03 /* AP ACI value for best effort AC */ +#define EDCF_AC_BE_ECW_AP 0x64 /* AP ECW value for best effort AC */ +#define EDCF_AC_BE_TXOP_AP 0x0000 /* AP TXOP value for best effort AC */ +#define EDCF_AC_BK_ACI_AP 0x27 /* AP ACI value for background AC */ +#define EDCF_AC_BK_ECW_AP 0xA4 /* AP ECW value for background AC */ +#define EDCF_AC_BK_TXOP_AP 0x0000 /* AP TXOP value for background AC */ +#define EDCF_AC_VI_ACI_AP 0x41 /* AP ACI value for video AC */ +#define EDCF_AC_VI_ECW_AP 0x43 /* AP ECW value for video AC */ +#define EDCF_AC_VI_TXOP_AP 0x005e /* AP TXOP value for video AC */ +#define EDCF_AC_VO_ACI_AP 0x61 /* AP ACI value for audio AC */ +#define EDCF_AC_VO_ECW_AP 0x32 /* AP ECW value for audio AC */ +#define EDCF_AC_VO_TXOP_AP 0x002f /* AP TXOP value for audio AC */ + +struct dot11_qbss_load_ie { + uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ + uint8 length; + uint16 station_count; /* total number of STAs associated */ + uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ + uint16 aac; /* available admission capacity */ +} PACKED; +typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; + +/* nom_msdu_size */ +#define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ +#define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ + +/* surplus_bandwidth */ +/* Represented as 3 bits of integer, binary point, 13 bits fraction */ +#define INTEGER_SHIFT 13 /* integer shift */ +#define FRACTION_MASK 0x1FFF /* fraction mask */ + +/* Management Notification Frame */ +struct dot11_management_notification { + uint8 category; /* DOT11_ACTION_NOTIFICATION */ + uint8 action; + uint8 token; + uint8 status; + uint8 data[1]; /* Elements */ +} PACKED; +#define DOT11_MGMT_NOTIFICATION_LEN 4 /* Fixed length */ + +/* WME Action Codes */ +#define WME_ADDTS_REQUEST 0 /* WME ADDTS request */ +#define WME_ADDTS_RESPONSE 1 /* WME ADDTS response */ +#define WME_DELTS_REQUEST 2 /* WME DELTS request */ + +/* WME Setup Response Status Codes */ +#define WME_ADMISSION_ACCEPTED 0 /* WME admission accepted */ +#define WME_INVALID_PARAMETERS 1 /* WME invalide parameters */ +#define WME_ADMISSION_REFUSED 3 /* WME admission refused */ + +/* Macro to take a pointer to a beacon or probe response + * header and return the char* pointer to the SSID info element + */ +#define BCN_PRB_SSID(hdr) ((char*)(hdr) + DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_LEN) + +/* Authentication frame payload constants */ +#define DOT11_OPEN_SYSTEM 0 /* d11 open authentication */ +#define DOT11_SHARED_KEY 1 /* d11 shared authentication */ +#define DOT11_CHALLENGE_LEN 128 /* d11 chanllenge text length */ + +/* Frame control macros */ +#define FC_PVER_MASK 0x3 /* PVER mask */ +#define FC_PVER_SHIFT 0 /* PVER shift */ +#define FC_TYPE_MASK 0xC /* type mask */ +#define FC_TYPE_SHIFT 2 /* type shift */ +#define FC_SUBTYPE_MASK 0xF0 /* subtype mask */ +#define FC_SUBTYPE_SHIFT 4 /* subtype shift */ +#define FC_TODS 0x100 /* to DS */ +#define FC_TODS_SHIFT 8 /* to DS shift */ +#define FC_FROMDS 0x200 /* from DS */ +#define FC_FROMDS_SHIFT 9 /* from DS shift */ +#define FC_MOREFRAG 0x400 /* more frag. */ +#define FC_MOREFRAG_SHIFT 10 /* more frag. shift */ +#define FC_RETRY 0x800 /* retry */ +#define FC_RETRY_SHIFT 11 /* retry shift */ +#define FC_PM 0x1000 /* PM */ +#define FC_PM_SHIFT 12 /* PM shift */ +#define FC_MOREDATA 0x2000 /* more data */ +#define FC_MOREDATA_SHIFT 13 /* more data shift */ +#define FC_WEP 0x4000 /* WEP */ +#define FC_WEP_SHIFT 14 /* WEP shift */ +#define FC_ORDER 0x8000 /* order */ +#define FC_ORDER_SHIFT 15 /* order shift */ + +/* sequence control macros */ +#define SEQNUM_SHIFT 4 /* seq. number shift */ +#define SEQNUM_MAX 0x1000 /* max seqnum + 1 */ +#define FRAGNUM_MASK 0xF /* frag. number mask */ + +/* Frame Control type/subtype defs */ + +/* FC Types */ +#define FC_TYPE_MNG 0 /* management type */ +#define FC_TYPE_CTL 1 /* control type */ +#define FC_TYPE_DATA 2 /* data type */ + +/* Management Subtypes */ +#define FC_SUBTYPE_ASSOC_REQ 0 /* assoc. request */ +#define FC_SUBTYPE_ASSOC_RESP 1 /* assoc. response */ +#define FC_SUBTYPE_REASSOC_REQ 2 /* reassoc. request */ +#define FC_SUBTYPE_REASSOC_RESP 3 /* reassoc. response */ +#define FC_SUBTYPE_PROBE_REQ 4 /* probe request */ +#define FC_SUBTYPE_PROBE_RESP 5 /* probe response */ +#define FC_SUBTYPE_BEACON 8 /* beacon */ +#define FC_SUBTYPE_ATIM 9 /* ATIM */ +#define FC_SUBTYPE_DISASSOC 10 /* disassoc. */ +#define FC_SUBTYPE_AUTH 11 /* authentication */ +#define FC_SUBTYPE_DEAUTH 12 /* de-authentication */ +#define FC_SUBTYPE_ACTION 13 /* action */ + +/* Control Subtypes */ +#define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ +#define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ +#define FC_SUBTYPE_PS_POLL 10 /* PS poll */ +#define FC_SUBTYPE_RTS 11 /* RTS */ +#define FC_SUBTYPE_CTS 12 /* CTS */ +#define FC_SUBTYPE_ACK 13 /* ACK */ +#define FC_SUBTYPE_CF_END 14 /* CF-END */ +#define FC_SUBTYPE_CF_END_ACK 15 /* CF-END ACK */ + +/* Data Subtypes */ +#define FC_SUBTYPE_DATA 0 /* Data */ +#define FC_SUBTYPE_DATA_CF_ACK 1 /* Data + CF-ACK */ +#define FC_SUBTYPE_DATA_CF_POLL 2 /* Data + CF-Poll */ +#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 /* Data + CF-Ack + CF-Poll */ +#define FC_SUBTYPE_NULL 4 /* Null */ +#define FC_SUBTYPE_CF_ACK 5 /* CF-Ack */ +#define FC_SUBTYPE_CF_POLL 6 /* CF-Poll */ +#define FC_SUBTYPE_CF_ACK_POLL 7 /* CF-Ack + CF-Poll */ +#define FC_SUBTYPE_QOS_DATA 8 /* QoS Data */ +#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 /* QoS Data + CF-Ack */ +#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 /* QoS Data + CF-Poll */ +#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 /* QoS Data + CF-Ack + CF-Poll */ +#define FC_SUBTYPE_QOS_NULL 12 /* QoS Null */ +#define FC_SUBTYPE_QOS_CF_POLL 14 /* QoS CF-Poll */ +#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 /* QoS CF-Ack + CF-Poll */ + +/* Data Subtype Groups */ +#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) +#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) +#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) +#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) + +/* Type/Subtype Combos */ +#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) /* FC kind mask */ + +#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) /* FC kind */ + +#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) /* Subtype from FC */ +#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) /* Type from FC */ + +#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) /* assoc. request */ +#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) /* assoc. response */ +#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) /* reassoc. request */ +#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) /* reassoc. response */ +#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) /* probe request */ +#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) /* probe response */ +#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) /* beacon */ +#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) /* disassoc */ +#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) /* authentication */ +#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) /* deauthentication */ +#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ + +#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ +#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ +#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) /* PS poll */ +#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) /* RTS */ +#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) /* CTS */ +#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) /* ACK */ +#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) /* CF-END */ +#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) /* CF-END ACK */ + +#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) /* data */ +#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) /* null data */ +#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) /* data CF ACK */ +#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) /* QoS data */ +#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) /* QoS null */ + +/* QoS Control Field */ + +/* 802.1D Priority */ +#define QOS_PRIO_SHIFT 0 /* QoS priority shift */ +#define QOS_PRIO_MASK 0x0007 /* QoS priority mask */ +#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) /* QoS priority */ + +/* Traffic Identifier */ +#define QOS_TID_SHIFT 0 /* QoS TID shift */ +#define QOS_TID_MASK 0x000f /* QoS TID mask */ +#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) /* QoS TID */ + +/* End of Service Period (U-APSD) */ +#define QOS_EOSP_SHIFT 4 /* QoS End of Service Period shift */ +#define QOS_EOSP_MASK 0x0010 /* QoS End of Service Period mask */ +#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) /* Qos EOSP */ + +/* Ack Policy */ +#define QOS_ACK_NORMAL_ACK 0 /* Normal Ack */ +#define QOS_ACK_NO_ACK 1 /* No Ack (eg mcast) */ +#define QOS_ACK_NO_EXP_ACK 2 /* No Explicit Ack */ +#define QOS_ACK_BLOCK_ACK 3 /* Block Ack */ +#define QOS_ACK_SHIFT 5 /* QoS ACK shift */ +#define QOS_ACK_MASK 0x0060 /* QoS ACK mask */ +#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) /* QoS ACK */ + +/* A-MSDU flag */ +#define QOS_AMSDU_SHIFT 7 /* AMSDU shift */ +#define QOS_AMSDU_MASK 0x0080 /* AMSDU mask */ + +/* Management Frames */ + +/* Management Frame Constants */ + +/* Fixed fields */ +#define DOT11_MNG_AUTH_ALGO_LEN 2 /* d11 management auth. algo. length */ +#define DOT11_MNG_AUTH_SEQ_LEN 2 /* d11 management auth. seq. length */ +#define DOT11_MNG_BEACON_INT_LEN 2 /* d11 management beacon interval length */ +#define DOT11_MNG_CAP_LEN 2 /* d11 management cap. length */ +#define DOT11_MNG_AP_ADDR_LEN 6 /* d11 management AP address length */ +#define DOT11_MNG_LISTEN_INT_LEN 2 /* d11 management listen interval length */ +#define DOT11_MNG_REASON_LEN 2 /* d11 management reason length */ +#define DOT11_MNG_AID_LEN 2 /* d11 management AID length */ +#define DOT11_MNG_STATUS_LEN 2 /* d11 management status length */ +#define DOT11_MNG_TIMESTAMP_LEN 8 /* d11 management timestamp length */ + +/* DUR/ID field in assoc resp is 0xc000 | AID */ +#define DOT11_AID_MASK 0x3fff /* d11 AID mask */ + +/* Reason Codes */ +#define DOT11_RC_RESERVED 0 /* d11 RC reserved */ +#define DOT11_RC_UNSPECIFIED 1 /* Unspecified reason */ +#define DOT11_RC_AUTH_INVAL 2 /* Previous authentication no longer + * valid + */ +#define DOT11_RC_DEAUTH_LEAVING 3 /* Deauthenticated because sending station + * is leaving (or has left) IBSS or ESS + */ +#define DOT11_RC_INACTIVITY 4 /* Disassociated due to inactivity */ +#define DOT11_RC_BUSY 5 /* Disassociated because AP is unable + * to handle all currently associated + * stations + */ +#define DOT11_RC_INVAL_CLASS_2 6 /* Class 2 frame received from + * nonauthenticated station + */ +#define DOT11_RC_INVAL_CLASS_3 7 /* Class 3 frame received from + * nonassociated station + */ +#define DOT11_RC_DISASSOC_LEAVING 8 /* Disassociated because sending station is + * leaving (or has left) BSS + */ +#define DOT11_RC_NOT_AUTH 9 /* Station requesting (re)association is + * not authenticated with responding + * station + */ +#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ + +/* Status Codes */ +#define DOT11_STATUS_SUCCESS 0 /* Successful */ +#define DOT11_STATUS_FAILURE 1 /* Unspecified failure */ +#define DOT11_STATUS_CAP_MISMATCH 10 /* Cannot support all requested + * capabilities in the Capability + * Information field + */ +#define DOT11_STATUS_REASSOC_FAIL 11 /* Reassociation denied due to inability + * to confirm that association exists + */ +#define DOT11_STATUS_ASSOC_FAIL 12 /* Association denied due to reason + * outside the scope of this standard + */ +#define DOT11_STATUS_AUTH_MISMATCH 13 /* Responding station does not support + * the specified authentication + * algorithm + */ +#define DOT11_STATUS_AUTH_SEQ 14 /* Received an Authentication frame + * with authentication transaction + * sequence number out of expected + * sequence + */ +#define DOT11_STATUS_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of + * challenge failure + */ +#define DOT11_STATUS_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout + * waiting for next frame in sequence + */ +#define DOT11_STATUS_ASSOC_BUSY_FAIL 17 /* Association denied because AP is + * unable to handle additional + * associated stations + */ +#define DOT11_STATUS_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting + * station not supporting all of the + * data rates in the BSSBasicRateSet + * parameter + */ +#define DOT11_STATUS_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting + * station not supporting the Short + * Preamble option + */ +#define DOT11_STATUS_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting + * station not supporting the PBCC + * Modulation option + */ +#define DOT11_STATUS_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting + * station not supporting the Channel + * Agility option + */ +#define DOT11_STATUS_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum + * Management capability is required. + */ +#define DOT11_STATUS_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info + * in the Power Cap element is + * unacceptable. + */ +#define DOT11_STATUS_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info + * in the Supported Channel element is + * unacceptable + */ +#define DOT11_STATUS_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting + * station not supporting the Short Slot + * Time option + */ +#define DOT11_STATUS_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting + * station not supporting the ER-PBCC + * Modulation option + */ +#define DOT11_STATUS_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting + * station not supporting the DSS-OFDM + * option + */ + +/* Info Elts, length of INFORMATION portion of Info Elts */ +#define DOT11_MNG_DS_PARAM_LEN 1 /* d11 management DS parameter length */ +#define DOT11_MNG_IBSS_PARAM_LEN 2 /* d11 management IBSS parameter length */ + +/* TIM Info element has 3 bytes fixed info in INFORMATION field, + * followed by 1 to 251 bytes of Partial Virtual Bitmap + */ +#define DOT11_MNG_TIM_FIXED_LEN 3 /* d11 management TIM fixed length */ +#define DOT11_MNG_TIM_DTIM_COUNT 0 /* d11 management DTIM count */ +#define DOT11_MNG_TIM_DTIM_PERIOD 1 /* d11 management DTIM period */ +#define DOT11_MNG_TIM_BITMAP_CTL 2 /* d11 management TIM BITMAP control */ +#define DOT11_MNG_TIM_PVB 3 /* d11 management TIM PVB */ + +/* TLV defines */ +#define TLV_TAG_OFF 0 /* tag offset */ +#define TLV_LEN_OFF 1 /* length offset */ +#define TLV_HDR_LEN 2 /* header length */ +#define TLV_BODY_OFF 2 /* body offset */ + +/* Management Frame Information Element IDs */ +#define DOT11_MNG_SSID_ID 0 /* d11 management SSID id */ +#define DOT11_MNG_RATES_ID 1 /* d11 management rates id */ +#define DOT11_MNG_FH_PARMS_ID 2 /* d11 management FH parameter id */ +#define DOT11_MNG_DS_PARMS_ID 3 /* d11 management DS parameter id */ +#define DOT11_MNG_CF_PARMS_ID 4 /* d11 management CF parameter id */ +#define DOT11_MNG_TIM_ID 5 /* d11 management TIM id */ +#define DOT11_MNG_IBSS_PARMS_ID 6 /* d11 management IBSS parameter id */ +#define DOT11_MNG_COUNTRY_ID 7 /* d11 management country id */ +#define DOT11_MNG_HOPPING_PARMS_ID 8 /* d11 management hopping parameter id */ +#define DOT11_MNG_HOPPING_TABLE_ID 9 /* d11 management hopping table id */ +#define DOT11_MNG_REQUEST_ID 10 /* d11 management request id */ +#define DOT11_MNG_QBSS_LOAD_ID 11 /* d11 management QBSS Load id */ +#define DOT11_MNG_CHALLENGE_ID 16 /* d11 management chanllenge id */ +#define DOT11_MNG_PWR_CONSTRAINT_ID 32 /* 11H PowerConstraint */ +#define DOT11_MNG_PWR_CAP_ID 33 /* 11H PowerCapability */ +#define DOT11_MNG_TPC_REQUEST_ID 34 /* 11H TPC Request */ +#define DOT11_MNG_TPC_REPORT_ID 35 /* 11H TPC Report */ +#define DOT11_MNG_SUPP_CHANNELS_ID 36 /* 11H Supported Channels */ +#define DOT11_MNG_CHANNEL_SWITCH_ID 37 /* 11H ChannelSwitch Announcement */ +#define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */ +#define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementReport */ +#define DOT11_MNG_QUIET_ID 40 /* 11H Quiet */ +#define DOT11_MNG_IBSS_DFS_ID 41 /* 11H IBSS_DFS */ +#define DOT11_MNG_ERP_ID 42 /* d11 management ERP id */ +#define DOT11_MNG_TS_DELAY_ID 43 /* d11 management TS Delay id */ +#define DOT11_MNG_NONERP_ID 47 /* d11 management NON-ERP id */ +#define DOT11_MNG_RSN_ID 48 /* d11 management RSN id */ +#define DOT11_MNG_EXT_RATES_ID 50 /* d11 management ext. rates id */ +#define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ +#define DOT11_MNG_PROPR_ID 221 /* d11 management proprietary id */ + +/* Rate element Basic flag and rate mask */ +#define DOT11_RATE_BASIC 0x80 /* flag for a Basic Rate */ +#define DOT11_RATE_MASK 0x7F /* mask for numeric part of rate */ + +/* ERP info element bit values */ +#define DOT11_MNG_ERP_LEN 1 /* ERP is currently 1 byte long */ +#define DOT11_MNG_NONERP_PRESENT 0x01 /* NonERP (802.11b) STAs are present + *in the BSS + */ +#define DOT11_MNG_USE_PROTECTION 0x02 /* Use protection mechanisms for + *ERP-OFDM frames + */ +#define DOT11_MNG_BARKER_PREAMBLE 0x04 /* Short Preambles: 0 == allowed, + * 1 == not allowed + */ +/* TS Delay element offset & size */ +#define DOT11_MGN_TS_DELAY_LEN 4 /* length of TS DELAY IE */ +#define TS_DELAY_FIELD_SIZE 4 /* TS DELAY field size */ + +/* Capability Information Field */ +#define DOT11_CAP_ESS 0x0001 /* d11 cap. ESS */ +#define DOT11_CAP_IBSS 0x0002 /* d11 cap. IBSS */ +#define DOT11_CAP_POLLABLE 0x0004 /* d11 cap. pollable */ +#define DOT11_CAP_POLL_RQ 0x0008 /* d11 cap. poll request */ +#define DOT11_CAP_PRIVACY 0x0010 /* d11 cap. privacy */ +#define DOT11_CAP_SHORT 0x0020 /* d11 cap. short */ +#define DOT11_CAP_PBCC 0x0040 /* d11 cap. PBCC */ +#define DOT11_CAP_AGILITY 0x0080 /* d11 cap. agility */ +#define DOT11_CAP_SPECTRUM 0x0100 /* d11 cap. spectrum */ +#define DOT11_CAP_SHORTSLOT 0x0400 /* d11 cap. shortslot */ +#define DOT11_CAP_CCK_OFDM 0x2000 /* d11 cap. CCK/OFDM */ + +/* Action Frame Constants */ +#define DOT11_ACTION_CAT_ERR_MASK 0x80 /* d11 action category error mask */ +#define DOT11_ACTION_CAT_MASK 0x7F /* d11 action category mask */ +#define DOT11_ACTION_CAT_SPECT_MNG 0x00 /* d11 action category spectrum management */ +#define DOT11_ACTION_CAT_BLOCKACK 0x03 /* d11 action category block ack */ +#define DOT11_ACTION_NOTIFICATION 0x11 /* 17 */ + +#define DOT11_ACTION_ID_M_REQ 0 /* d11 action measurement request */ +#define DOT11_ACTION_ID_M_REP 1 /* d11 action measurement response */ +#define DOT11_ACTION_ID_TPC_REQ 2 /* d11 action TPC request */ +#define DOT11_ACTION_ID_TPC_REP 3 /* d11 action TPC response */ +#define DOT11_ACTION_ID_CHANNEL_SWITCH 4 /* d11 action channel switch */ + +/* HT (EWC) action ids */ +#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* mimo ps action frame id */ +#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action frame id */ + +/* Block Ack action types */ +#define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ +#define DOT11_BA_ACTION_ADDBA_RESP 1 /* ADDBA Resp action frame type */ +#define DOT11_BA_ACTION_DELBA 2 /* DELBA action frame type */ + +/* ADDBA action parameters */ +#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 /* policy mask(ack vs delayed) */ +#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 /* policy shift */ +#define DOT11_ADDBA_PARAM_TID_MASK 0x003c /* tid mask */ +#define DOT11_ADDBA_PARAM_TID_SHIFT 2 /* tid shift */ +#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 /* buffer size mask */ +#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 /* buffer size shift */ + +#define DOT11_ADDBA_POLICY_DELAYED 0 /* delayed BA policy */ +#define DOT11_ADDBA_POLICY_IMMEDIATE 1 /* immediate BA policy */ + +struct dot11_addba_req { + uint8 category; /* category of action frame (3) */ + uint8 action; /* action: addba req */ + uint8 token; /* identifier */ + uint16 addba_param_set; /* parameter set */ + uint16 timeout; /* timeout in seconds */ + uint16 start_seqnum; /* starting sequence number */ +}PACKED; +typedef struct dot11_addba_req dot11_addba_req_t; +#define DOT11_ADDBA_REQ_LEN 9 /* length of addba req frame */ + +struct dot11_addba_resp { + uint8 category; /* category of action frame (3) */ + uint8 action; /* action: addba resp */ + uint8 token; /* identifier */ + uint16 status; /* status of add request */ + uint16 addba_param_set; /* negotiated parameter set */ + uint16 timeout; /* negotiated timeout in seconds */ +}PACKED; +typedef struct dot11_addba_resp dot11_addba_resp_t; +#define DOT11_ADDBA_RESP_LEN 9 /* length of addba resp frame */ + +/* DELBA action parameters */ +#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 /* initiator mask */ +#define DOT11_DELBA_PARAM_INIT_SHIFT 11 /* initiator shift */ +#define DOT11_DELBA_PARAM_TID_MASK 0xf000 /* tid mask */ +#define DOT11_DELBA_PARAM_TID_SHIFT 12 /* tid shift */ + +struct dot11_delba { + uint8 category; /* category of action frame (3) */ + uint8 action; /* action: addba req */ + uint16 delba_param_set; /* paarmeter set */ + uint16 reason; /* reason for dellba */ +}PACKED; +typedef struct dot11_delba dot11_delba_t; +#define DOT11_DELBA_LEN 6 /* length of delba frame */ + +/* MLME Enumerations */ +#define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ +#define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ +#define DOT11_BSSTYPE_ANY 2 /* d11 any BSS type */ +#define DOT11_SCANTYPE_ACTIVE 0 /* d11 scan active */ +#define DOT11_SCANTYPE_PASSIVE 1 /* d11 scan passive */ + +/* 802.11 BRCM "Compromise" Pre N constants */ +#define PREN_PREAMBLE 24 /* green field preamble time */ +#define PREN_MM_EXT 16 /* extra mixed mode preamble time */ +#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ + +/* 802.11 A PHY constants */ +#define APHY_SLOT_TIME 9 /* APHY slot time */ +#define APHY_SIFS_TIME 16 /* APHY SIFS time */ +#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) /* APHY DIFS time */ +#define APHY_PREAMBLE_TIME 16 /* APHY preamble time */ +#define APHY_SIGNAL_TIME 4 /* APHY signal time */ +#define APHY_SYMBOL_TIME 4 /* APHY symbol time */ +#define APHY_SERVICE_NBITS 16 /* APHY service nbits */ +#define APHY_TAIL_NBITS 6 /* APHY tail nbits */ +#define APHY_CWMIN 15 /* APHY cwmin */ + +/* 802.11 B PHY constants */ +#define BPHY_SLOT_TIME 20 /* BPHY slot time */ +#define BPHY_SIFS_TIME 10 /* BPHY SIFS time */ +#define BPHY_DIFS_TIME 50 /* BPHY DIFS time */ +#define BPHY_PLCP_TIME 192 /* BPHY PLCP time */ +#define BPHY_PLCP_SHORT_TIME 96 /* BPHY PLCP short time */ +#define BPHY_CWMIN 31 /* BPHY cwmin */ + +/* 802.11 G constants */ +#define DOT11_OFDM_SIGNAL_EXTENSION 6 /* d11 OFDM signal extension */ + +#define PHY_CWMAX 1023 /* PHY cwmax */ + +#define DOT11_MAXNUMFRAGS 16 /* max # fragments per MSDU */ + +/* dot11Counters Table - 802.11 spec., Annex D */ +typedef struct d11cnt { + uint32 txfrag; /* dot11TransmittedFragmentCount */ + uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32 txfail; /* dot11FailedCount */ + uint32 txretry; /* dot11RetryCount */ + uint32 txretrie; /* dot11MultipleRetryCount */ + uint32 rxdup; /* dot11FrameduplicateCount */ + uint32 txrts; /* dot11RTSSuccessCount */ + uint32 txnocts; /* dot11RTSFailureCount */ + uint32 txnoack; /* dot11ACKFailureCount */ + uint32 rxfrag; /* dot11ReceivedFragmentCount */ + uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32 rxcrc; /* dot11FCSErrorCount */ + uint32 txfrmsnt; /* dot11TransmittedFrameCount */ + uint32 rxundec; /* dot11WEPUndecryptableCount */ +} d11cnt_t; + +/* BRCM OUI */ +#define BRCM_OUI "\x00\x10\x18" /* Broadcom OUI */ + +/* OUI for BRCM proprietary IE */ +#define BRCM_PROP_OUI "\x00\x90\x4C" /* Broadcom proprietary OUI */ + +/* BRCM info element */ +struct brcm_ie { + uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ + uint8 len; /* IE length */ + uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ + uint8 ver; /* type/ver of this IE */ + uint8 assoc; /* # of assoc STAs */ + uint8 flags; /* misc flags */ + uint8 flags1; /* misc flags */ + uint16 amsdu_mtu_pref; /* preferred A-MSDU MTU */ +} PACKED; +typedef struct brcm_ie brcm_ie_t; +#define BRCM_IE_LEN 11 /* BRCM IE length */ +#define BRCM_IE_VER 2 /* BRCM IE version */ +#define BRCM_IE_LEGACY_AES_VER 1 /* BRCM IE legacy AES version */ + +/* brcm_ie flags */ +#define BRF_ABCAP 0x1 /* afterburner capable */ +#define BRF_ABRQRD 0x2 /* afterburner requested */ +#define BRF_LZWDS 0x4 /* lazy wds enabled */ +#define BRF_BLOCKACK 0x8 /* BlockACK capable */ +#define BRF_ABCOUNTER_MASK 0xf0 /* afterburner wds "state" counter */ +#define BRF_ABCOUNTER_SHIFT 4 /* offset of afterburner wds "state" counter */ + +/* brcm_ie flags1 */ +#define BRF1_AMSDU 0x1 /* A-MSDU capable */ + +#define AB_WDS_TIMEOUT_MAX 15 /* afterburner wds Max count indicating not + * locally capable + */ +#define AB_WDS_TIMEOUT_MIN 1 /* afterburner wds, use zero count as indicating + * "downrev" + */ + +/* EWC definitions */ +#define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ + +struct ewc_cap { + uint16 cap; + uint8 params; + uint8 supp_mcs[MCSSET_LEN]; + uint16 ext_htcap; + uint32 txbf_cap; + uint8 as_cap; +} PACKED; +typedef struct ewc_cap ewc_cap_t; + +/* CAP IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ +/* the capability IE is primarily used to convey this nodes abilities */ +struct ewc_cap_ie { + uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ + uint8 len; /* IE length */ + uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ + uint8 type; /* type inidicates what follows */ + ewc_cap_t cap; +} PACKED; +typedef struct ewc_cap_ie ewc_cap_ie_t; + +#define EWC_CAP_IE_LEN (26+4) +#define EWC_CAP_IE_TYPE 51 + +#define EWC_CAP_ADC_CODING 0x0001 /* Advance coding support */ +#define EWC_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE: 20 and 40MHZ supported */ +#define EWC_CAP_MIMO_PS_MASK 0x000C /* Mimo PS mask */ +#define EWC_CAP_MIMO_PS_SHIFT 0x0002 /* Mimo PS shift */ +#define EWC_CAP_MIMO_PS_OFF 0x0003 /* Mimo PS, no restriction */ +#define EWC_CAP_MIMO_PS_RTS 0x0001 /* Mimo PS, send RTS/CTS around MIMO frames */ +#define EWC_CAP_MIMO_PS_ON 0x0000 /* Mimo PS, MIMO disallowed */ +#define EWC_CAP_GF 0x0010 /* Greenfield preamble support */ +#define EWC_CAP_SHORT_GI_20 0x0020 /* 20MHZ short guard interval support */ +#define EWC_CAP_SHORT_GI_40 0x0040 /* 40Mhz short guard interval support */ +#define EWC_CAP_TX_STBC 0x0080 /* Tx STBC support */ +#define EWC_CAP_RX_STBC_MASK 0x0300 /* Rx STBC mask */ +#define EWC_CAP_RX_STBC_SHIFT 8 /* Rx STBC shift */ +#define EWC_CAP_DELAYED_BA 0x0400 /* delayed BA support */ +#define EWC_CAP_MAX_AMSDU 0x0800 /* Max AMSDU size in bytes , 0=3839, 1=7935 */ +#define EWC_CAP_DSSS_CCK 0x1000 /* DSSS/CCK supported by the BSS */ +#define EWC_CAP_PSMP 0x2000 /* Power Save Multi Poll support */ +#define EWC_CAP_STBC_CTL 0x4000 /* STBC control frame support */ +#define EWC_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ + +#define EWC_MAX_AMSDU 7935 /* max amsdu size (bytes) per the EWC spec */ +#define EWC_MIN_AMSDU 3835 /* min amsdu size (bytes) per the EWC spec */ + +#define EWC_PARAMS_RX_FACTOR_MASK 0x03 /* ampdu rcv factor mask */ +#define EWC_PARAMS_DENSITY_MASK 0x1C /* ampdu density mask */ +#define EWC_PARAMS_DENSITY_SHIFT 2 /* ampdu density shift */ + +/* EWC/AMPDU specific define */ +#define AMPDU_MAX_MPDU_DENSITY 7 /* max mpdu density; in 1/8 usec units */ +#define AMPDU_MAX_RX_FACTOR 3 /* max rcv ampdu len (64kb) */ +#define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ +#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ + +struct ewc_add { + uint8 ctl_ch; /* control channel number */ + uint8 byte1; /* ext ch,rec. ch. width, RIFS support */ + uint16 opmode; /* operation mode */ + uint16 misc_bits; /* misc bits */ + uint8 basic_mcs[MCSSET_LEN]; /* required MCS set */ +} PACKED; +typedef struct ewc_add ewc_add_t; + +/* ADD IE: EWC 1.0 spec. simply stole a 802.11 IE, we use our prop. IE until this is resolved */ +/* the additional IE is primarily used to convey the current BSS configuration */ +struct ewc_add_ie { + uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ + uint8 len; /* IE length */ + uint8 oui[3]; /* Proprietary OUI, BRCM_PROP_OUI */ + uint8 type; /* indicates what follows */ + ewc_add_t add; +} PACKED; +typedef struct ewc_add_ie ewc_add_ie_t; + +#define EWC_ADD_IE_LEN (22+4) +#define EWC_ADD_IE_TYPE 52 + +/* byte1 defn's */ +#define EWC_EXT_CH_MASK 0x03 /* extension channel mask */ +#define EWC_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ +#define EWC_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ +#define EWC_EXT_CH_NONE 0x00 /* extension channel mask */ +#define EWC_BW_ANY 0x04 /* set, STA can use 20 or 40MHz */ +#define EWC_RIFS_PERMITTED 0x08 /* RIFS allowed */ + +/* opmode defn's */ +#define EWC_OPMODE_MASK 0x0003 /* protection mode mask */ +#define EWC_OPMODE_PURE 0x0000 /* protection mode PURE */ +#define EWC_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ +#define EWC_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ +#define EWC_NONGF_PRESENT 0x0004 /* protection mode non-GF */ + +/* misc_bites defn's */ +#define EWC_BASIC_STBC_MCS 0x007f /* basic STBC MCS */ +#define EWC_DUAL_STBC_PROT 0x0080 /* Dual STBC Protection */ +#define EWC_SECOND_BCN 0x0100 /* Secondary beacon support */ +#define EWC_LSIG_TXOP 0x0200 /* L-SIG TXOP Protection full support */ +#define EWC_PCO_ACTIVE 0x0400 /* PCO active */ +#define EWC_PCO_PHASE 0x0800 /* PCO phase */ + +/* Macros for opmode */ +#define EWC_MIXEDMODE_PRESENT(add) ((ltoh16_ua(&add.opmode) & EWC_OPMODE_MASK) \ + == EWC_OPMODE_MIXED) /* mixed mode present */ +#define EWC_HT20_PRESENT(add) ((ltoh16_ua(&add.opmode) & EWC_OPMODE_MASK) \ + == EWC_OPMODE_HT20IN40) /* 20MHz HT present */ +#define EWC_USE_PROTECTION(add) (EWC_HT20_PRESENT((add)) || \ + EWC_MIXEDMODE_PRESENT((add))) /* use protection */ + +/* Vendor IE structure */ +struct vndr_ie { + uchar id; + uchar len; + uchar oui [3]; + uchar data [1]; /* Variable size data */ +}PACKED; +typedef struct vndr_ie vndr_ie_t; + +#define VNDR_IE_HDR_LEN 2 /* id + len field */ +#define VNDR_IE_MIN_LEN 3 /* size of the oui field */ +#define VNDR_IE_MAX_LEN 256 /* verdor IE max length */ + +/* WPA definitions */ +#define WPA_VERSION 1 /* WPA version */ +#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ + +#define WPA2_VERSION 1 /* WPA2 version */ +#define WPA2_VERSION_LEN 2 /* WAP2 version length */ +#define WPA2_OUI "\x00\x0F\xAC" /* WPA2 OUI */ + +#define WPA_OUI_LEN 3 /* WPA OUI length */ + +/* RSN authenticated key managment suite */ +#define RSN_AKM_NONE 0 /* None (IBSS) */ +#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ +#define RSN_AKM_PSK 2 /* Pre-shared Key */ + +/* Key related defines */ +#define DOT11_MAX_DEFAULT_KEYS 4 /* number of default keys */ +#define DOT11_MAX_KEY_SIZE 32 /* max size of any key */ +#define DOT11_MAX_IV_SIZE 16 /* max size of any IV */ +#define DOT11_EXT_IV_FLAG (1<<5) /* flag to indicate IV is > 4 bytes */ + +#define WEP1_KEY_SIZE 5 /* max size of any WEP key */ +#define WEP1_KEY_HEX_SIZE 10 /* size of WEP key in hex. */ +#define WEP128_KEY_SIZE 13 /* max size of any WEP key */ +#define WEP128_KEY_HEX_SIZE 26 /* size of WEP key in hex. */ +#define TKIP_MIC_SIZE 8 /* size of TKIP MIC */ +#define TKIP_EOM_SIZE 7 /* max size of TKIP EOM */ +#define TKIP_EOM_FLAG 0x5a /* TKIP EOM flag byte */ +#define TKIP_KEY_SIZE 32 /* size of any TKIP key */ +#define TKIP_MIC_AUTH_TX 16 /* offset to Authenticator MIC TX key */ +#define TKIP_MIC_AUTH_RX 24 /* offset to Authenticator MIC RX key */ +#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX /* offset to Supplicant MIC RX key */ +#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX /* offset to Supplicant MIC TX key */ +#define AES_KEY_SIZE 16 /* size of AES key */ + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _802_11_H_ */ diff --git a/package/broadcom-wl/src/wlc/include/proto/bcmeth.h b/package/broadcom-wl/src/wlc/include/proto/bcmeth.h new file mode 100644 index 0000000000..7b3295389a --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/proto/bcmeth.h @@ -0,0 +1,101 @@ +/* + * Broadcom Ethernettype protocol definitions + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: bcmeth.h,v 1.1.1.4 2006/02/27 03:43:16 honor Exp $ + */ + +/* + * Broadcom Ethernet protocol defines + */ + +#ifndef _BCMETH_H_ +#define _BCMETH_H_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +/* ETHER_TYPE_BRCM is defined in ethernet.h */ + +/* + * Following the 2byte BRCM ether_type is a 16bit BRCM subtype field + * in one of two formats: (only subtypes 32768-65535 are in use now) + * + * subtypes 0-32767: + * 8 bit subtype (0-127) + * 8 bit length in bytes (0-255) + * + * subtypes 32768-65535: + * 16 bit big-endian subtype + * 16 bit big-endian length in bytes (0-65535) + * + * length is the number of additional bytes beyond the 4 or 6 byte header + * + * Reserved values: + * 0 reserved + * 5-15 reserved for iLine protocol assignments + * 17-126 reserved, assignable + * 127 reserved + * 32768 reserved + * 32769-65534 reserved, assignable + * 65535 reserved + */ + +/* + * While adding the subtypes and their specific processing code make sure + * bcmeth_bcm_hdr_t is the first data structure in the user specific data structure definition + */ + +#define BCMILCP_SUBTYPE_RATE 1 +#define BCMILCP_SUBTYPE_LINK 2 +#define BCMILCP_SUBTYPE_CSA 3 +#define BCMILCP_SUBTYPE_LARQ 4 +#define BCMILCP_SUBTYPE_VENDOR 5 +#define BCMILCP_SUBTYPE_FLH 17 + +#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 +#define BCMILCP_SUBTYPE_CERT 32770 +#define BCMILCP_SUBTYPE_SES 32771 + + +#define BCMILCP_BCM_SUBTYPE_RESERVED 0 +#define BCMILCP_BCM_SUBTYPE_EVENT 1 +#define BCMILCP_BCM_SUBTYPE_SES 2 +/* + * The EAPOL type is not used anymore. Instead EAPOL messages are now embedded + * within BCMILCP_BCM_SUBTYPE_EVENT type messages + */ +/* #define BCMILCP_BCM_SUBTYPE_EAPOL 3 */ + +#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 +#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 + +/* These fields are stored in network order */ +typedef struct bcmeth_hdr +{ + uint16 subtype; /* Vendor specific..32769 */ + uint16 length; + uint8 version; /* Version is 0 */ + uint8 oui[3]; /* Broadcom OUI */ + /* user specific Data */ + uint16 usr_subtype; +} PACKED bcmeth_hdr_t; + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _BCMETH_H_ */ diff --git a/package/broadcom-wl/src/wlc/include/proto/bcmevent.h b/package/broadcom-wl/src/wlc/include/proto/bcmevent.h new file mode 100644 index 0000000000..d922a5d215 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/proto/bcmevent.h @@ -0,0 +1,152 @@ +/* + * Broadcom Event protocol definitions + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * + * Dependencies: proto/bcmeth.h + * + * $Id: bcmevent.h,v 1.1.1.3 2006/02/27 03:43:16 honor Exp $ + * + */ + +/* + * Broadcom Ethernet Events protocol defines + * + */ + +#ifndef _BCMEVENT_H_ +#define _BCMEVENT_H_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif /* defined(__GNUC__) */ + +#define BCM_EVENT_MSG_VERSION 1 /* wl_event_msg_t struct version */ +#define BCM_MSG_IFNAME_MAX 16 /* max length of interface name */ + +/* flags */ +#define WLC_EVENT_MSG_LINK 0x01 /* link is up */ +#define WLC_EVENT_MSG_FLUSHTXQ 0x02 /* flush tx queue on MIC error */ +#define WLC_EVENT_MSG_GROUP 0x04 /* group MIC error */ + +/* theses fields are stored in network order */ +typedef struct +{ + uint16 version; + uint16 flags; /* see flags below */ + uint32 event_type; /* Message (see below) */ + uint32 status; /* Status code (see below) */ + uint32 reason; /* Reason code (if applicable) */ + uint32 auth_type; /* WLC_E_AUTH */ + uint32 datalen; /* data buf */ + struct ether_addr addr; /* Station address (if applicable) */ + char ifname[BCM_MSG_IFNAME_MAX]; /* name of the packet incoming interface */ +} PACKED wl_event_msg_t; + +/* used by driver msgs */ +typedef struct bcm_event { + struct ether_header eth; + bcmeth_hdr_t bcm_hdr; + wl_event_msg_t event; + /* data portion follows */ +} PACKED bcm_event_t; + +#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) + +/* Event messages */ +#define WLC_E_SET_SSID 0 /* indicates status of set SSID */ +#define WLC_E_JOIN 1 /* differentiates join IBSS from found (WLC_E_START) IBSS */ +#define WLC_E_START 2 /* STA founded an IBSS or AP started a BSS */ +#define WLC_E_AUTH 3 /* 802.11 AUTH request */ +#define WLC_E_AUTH_IND 4 /* 802.11 AUTH indication */ +#define WLC_E_DEAUTH 5 /* 802.11 DEAUTH request */ +#define WLC_E_DEAUTH_IND 6 /* 802.11 DEAUTH indication */ +#define WLC_E_ASSOC 7 /* 802.11 ASSOC request */ +#define WLC_E_ASSOC_IND 8 /* 802.11 ASSOC indication */ +#define WLC_E_REASSOC 9 /* 802.11 REASSOC request */ +#define WLC_E_REASSOC_IND 10 /* 802.11 REASSOC indication */ +#define WLC_E_DISASSOC 11 /* 802.11 DISASSOC request */ +#define WLC_E_DISASSOC_IND 12 /* 802.11 DISASSOC indication */ +#define WLC_E_QUIET_START 13 /* 802.11h Quiet period started */ +#define WLC_E_QUIET_END 14 /* 802.11h Quiet period ended */ +#define WLC_E_BEACON_RX 15 /* BEACONS received/lost indication */ +#define WLC_E_LINK 16 /* generic link indication */ +#define WLC_E_MIC_ERROR 17 /* TKIP MIC error occurred */ +#define WLC_E_NDIS_LINK 18 /* NDIS style link indication */ +#define WLC_E_ROAM 19 /* roam attempt occurred: indicate status & reason */ +#define WLC_E_TXFAIL 20 /* change in dot11FailedCount (txfail) */ +#define WLC_E_PMKID_CACHE 21 /* WPA2 pmkid cache indication */ +#define WLC_E_RETROGRADE_TSF 22 /* current AP's TSF value went backward */ +#define WLC_E_PRUNE 23 /* AP was pruned from join list for reason */ +#define WLC_E_AUTOAUTH 24 /* report AutoAuth table entry match for join attempt */ +#define WLC_E_EAPOL_MSG 25 /* Event encapsulating an EAPOL message */ +#define WLC_E_SCAN_COMPLETE 26 /* Scan results are ready or scan was aborted */ +#define WLC_E_ADDTS_IND 27 /* indicate to host addts fail/success */ +#define WLC_E_DELTS_IND 28 /* indicate to host delts fail/success */ +#define WLC_E_BCNSENT_IND 29 /* indicate to host of beacon transmit */ +#define WLC_E_BCNRX_MSG 30 /* Send the received beacon up to the host */ +#define WLC_E_LAST 31 /* highest val + 1 for range checking */ + +/* Event status codes */ +#define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ +#define WLC_E_STATUS_FAIL 1 /* operation failed */ +#define WLC_E_STATUS_TIMEOUT 2 /* operation timed out */ +#define WLC_E_STATUS_NO_NETWORKS 3 /* failed due to no matching network found */ +#define WLC_E_STATUS_ABORT 4 /* operation was aborted */ +#define WLC_E_STATUS_NO_ACK 5 /* protocol failure: packet not ack'd */ +#define WLC_E_STATUS_UNSOLICITED 6 /* AUTH or ASSOC packet was unsolicited */ +#define WLC_E_STATUS_ATTEMPT 7 /* attempt to assoc to an auto auth configuration */ + +/* roam reason codes */ +#define WLC_E_REASON_INITIAL_ASSOC 0 /* initial assoc */ +#define WLC_E_REASON_LOW_RSSI 1 /* roamed due to low RSSI */ +#define WLC_E_REASON_DEAUTH 2 /* roamed due to DEAUTH indication */ +#define WLC_E_REASON_DISASSOC 3 /* roamed due to DISASSOC indication */ +#define WLC_E_REASON_BCNS_LOST 4 /* roamed due to lost beacons */ +#define WLC_E_REASON_FAST_ROAM_FAILED 5 /* roamed due to fast roam failure */ +#define WLC_E_REASON_DIRECTED_ROAM 6 /* roamed due to request by AP */ +#define WLC_E_REASON_TSPEC_REJECTED 7 /* roamed due to TSPEC rejection */ +#define WLC_E_REASON_BETTER_AP 8 /* roamed due to finding better AP */ + +/* prune reason codes */ +#define WLC_E_PRUNE_ENCR_MISMATCH 1 /* ecryption mismatch */ +#define WLC_E_PRUNE_BCAST_BSSID 2 /* AP uses a broadcast BSSID */ +#define WLC_E_PRUNE_MAC_DENY 3 /* STA's MAC addr is in AP's MAC deny list */ +#define WLC_E_PRUNE_MAC_NA 4 /* STA's MAC addr is not in AP's MAC allow list */ +#define WLC_E_PRUNE_REG_PASSV 5 /* AP not allowed due to regulatory restriction */ +#define WLC_E_PRUNE_SPCT_MGMT 6 /* AP does not support STA locale spectrum mgmt */ +#define WLC_E_PRUNE_RADAR 7 /* AP is on a radar channel of STA locale */ +#define WLC_E_RSN_MISMATCH 8 /* STA does not support AP's RSN */ +#define WLC_E_PRUNE_NO_COMMON_RATES 9 /* No rates in common with AP */ +#define WLC_E_PRUNE_BASIC_RATES 10 /* STA does not support all basic rates of BSS */ +#define WLC_E_PRUNE_CCXFAST_PREVAP 11 /* CCX FAST ROAM: prune previous AP */ +#define WLC_E_PRUNE_CIPHER_NA 12 /* BSS's cipher not supported */ +#define WLC_E_PRUNE_KNOWN_STA 13 /* AP is already known to us as a STA */ +#define WLC_E_PRUNE_CCXFAST_DROAM 14 /* CCX FAST ROAM: prune unqulified AP */ +#define WLC_E_PRUNE_WDS_PEER 15 /* AP is already known to us as a WDS peer */ +#define WLC_E_PRUNE_QBSS_LOAD 16 /* QBSS LOAD - AAC is too low */ +#define WLC_E_PRUNE_HOME_AP 17 /* prune home AP */ + +/* WLC_SET_CALLBACK data type */ +typedef struct wlc_event_cb { + void (*fn)(void *, bcm_event_t *); /* Callback function */ + void *context; /* Passed to callback function */ +} wlc_event_cb_t; + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif /* PACKED */ + +#endif /* _BCMEVENT_H_ */ diff --git a/package/broadcom-wl/src/wlc/include/proto/ethernet.h b/package/broadcom-wl/src/wlc/include/proto/ethernet.h new file mode 100644 index 0000000000..03fd4f654c --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/proto/ethernet.h @@ -0,0 +1,165 @@ +/* + * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: ethernet.h,v 1.1.1.14 2006/02/27 03:43:16 honor Exp $ + */ + +#ifndef _NET_ETHERNET_H_ /* use native BSD ethernet.h when available */ +#define _NET_ETHERNET_H_ + +#ifndef _TYPEDEFS_H_ +#include "typedefs.h" +#endif + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +/* + * The number of bytes in an ethernet (MAC) address. + */ +#define ETHER_ADDR_LEN 6 + +/* + * The number of bytes in the type field. + */ +#define ETHER_TYPE_LEN 2 + +/* + * The number of bytes in the trailing CRC field. + */ +#define ETHER_CRC_LEN 4 + +/* + * The length of the combined header. + */ +#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN) + +/* + * The minimum packet length. + */ +#define ETHER_MIN_LEN 64 + +/* + * The minimum packet user data length. + */ +#define ETHER_MIN_DATA 46 + +/* + * The maximum packet length. + */ +#define ETHER_MAX_LEN 1518 + +/* + * The maximum packet user data length. + */ +#define ETHER_MAX_DATA 1500 + +/* ether types */ +#define ETHER_TYPE_IP 0x0800 /* IP */ +#define ETHER_TYPE_ARP 0x0806 /* ARP */ +#define ETHER_TYPE_8021Q 0x8100 /* 802.1Q */ +#define ETHER_TYPE_BRCM 0x886c /* Broadcom Corp. */ +#define ETHER_TYPE_802_1X 0x888e /* 802.1x */ +#ifdef BCMWPA2 +#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 /* 802.1x preauthentication */ +#endif + +/* Broadcom subtype follows ethertype; First 2 bytes are reserved; Next 2 are subtype; */ +#define ETHER_BRCM_SUBTYPE_LEN 4 /* Broadcom 4 byte subtype */ +#define ETHER_BRCM_CRAM 0x1 /* Broadcom subtype cram protocol */ + +/* ether header */ +#define ETHER_DEST_OFFSET 0 /* dest address offset */ +#define ETHER_SRC_OFFSET 6 /* src address offset */ +#define ETHER_TYPE_OFFSET 12 /* ether type offset */ + +/* + * A macro to validate a length with + */ +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + + +#ifndef __INCif_etherh /* Quick and ugly hack for VxWorks */ +/* + * Structure of a 10Mb/s Ethernet header. + */ +struct ether_header { + uint8 ether_dhost[ETHER_ADDR_LEN]; + uint8 ether_shost[ETHER_ADDR_LEN]; + uint16 ether_type; +} PACKED; + +/* + * Structure of a 48-bit Ethernet address. + */ +struct ether_addr { + uint8 octet[ETHER_ADDR_LEN]; +} PACKED; +#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ + +/* + * Takes a pointer, sets locally admininistered + * address bit in the 48-bit Ethernet address. + */ +#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) + +/* + * Takes a pointer, returns true if a 48-bit multicast address + * (including broadcast, since it is all ones) + */ +#define ETHER_ISMULTI(ea) (((uint8 *)(ea))[0] & 1) + + +/* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ +#define ether_cmp(a, b) (!(((short*)a)[0] == ((short*)b)[0]) | \ + !(((short*)a)[1] == ((short*)b)[1]) | \ + !(((short*)a)[2] == ((short*)b)[2])) + +/* copy an ethernet address - assumes the pointers can be referenced as shorts */ +#define ether_copy(s, d) { \ + ((short*)d)[0] = ((short*)s)[0]; \ + ((short*)d)[1] = ((short*)s)[1]; \ + ((short*)d)[2] = ((short*)s)[2]; } + +/* + * Takes a pointer, returns true if a 48-bit broadcast (all ones) + */ +#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ + ((uint8 *)(ea))[1] & \ + ((uint8 *)(ea))[2] & \ + ((uint8 *)(ea))[3] & \ + ((uint8 *)(ea))[4] & \ + ((uint8 *)(ea))[5]) == 0xff) + +static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; + +/* + * Takes a pointer, returns true if a 48-bit null address (all zeros) + */ +#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ + ((uint8 *)(ea))[1] | \ + ((uint8 *)(ea))[2] | \ + ((uint8 *)(ea))[3] | \ + ((uint8 *)(ea))[4] | \ + ((uint8 *)(ea))[5]) == 0) + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _NET_ETHERNET_H_ */ diff --git a/package/broadcom-wl/src/wlc/include/proto/wpa.h b/package/broadcom-wl/src/wlc/include/proto/wpa.h new file mode 100644 index 0000000000..dd35dbef02 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/proto/wpa.h @@ -0,0 +1,148 @@ +/* + * Fundamental types and constants relating to WPA + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: wpa.h,v 1.1.1.4 2006/02/27 03:43:16 honor Exp $ + */ + +#ifndef _proto_wpa_h_ +#define _proto_wpa_h_ + +#include +#include + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +/* Reason Codes */ + +/* 10 and 11 are from TGh. */ +#define DOT11_RC_BAD_PC 10 /* Unacceptable power capability element */ +#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ +/* 12 is unused */ +/* 13 through 23 taken from P802.11i/D3.0, November 2002 */ +#define DOT11_RC_INVALID_WPA_IE 13 /* Invalid info. element */ +#define DOT11_RC_MIC_FAILURE 14 /* Michael failure */ +#define DOT11_RC_4WH_TIMEOUT 15 /* 4-way handshake timeout */ +#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 /* Group key update timeout */ +#define DOT11_RC_WPA_IE_MISMATCH 17 /* WPA IE in 4-way handshake differs from + * (re-)assoc. request/probe response + */ +#define DOT11_RC_INVALID_MC_CIPHER 18 /* Invalid multicast cipher */ +#define DOT11_RC_INVALID_UC_CIPHER 19 /* Invalid unicast cipher */ +#define DOT11_RC_INVALID_AKMP 20 /* Invalid authenticated key management protocol */ +#define DOT11_RC_BAD_WPA_VERSION 21 /* Unsupported WPA version */ +#define DOT11_RC_INVALID_WPA_CAP 22 /* Invalid WPA IE capabilities */ +#define DOT11_RC_8021X_AUTH_FAIL 23 /* 802.1X authentication failure */ + +#define WPA2_PMKID_LEN 16 + +/* WPA IE fixed portion */ +typedef struct +{ + uint8 tag; /* TAG */ + uint8 length; /* TAG length */ + uint8 oui[3]; /* IE OUI */ + uint8 oui_type; /* OUI type */ + struct { + uint8 low; + uint8 high; + } PACKED version; /* IE version */ +} PACKED wpa_ie_fixed_t; +#define WPA_IE_OUITYPE_LEN 4 +#define WPA_IE_FIXED_LEN 8 +#define WPA_IE_TAG_FIXED_LEN 6 + +#ifdef BCMWPA2 +typedef struct { + uint8 tag; /* TAG */ + uint8 length; /* TAG length */ + struct { + uint8 low; + uint8 high; + } PACKED version; /* IE version */ +} PACKED wpa_rsn_ie_fixed_t; +#define WPA_RSN_IE_FIXED_LEN 4 +#define WPA_RSN_IE_TAG_FIXED_LEN 2 +typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; +#endif + +/* WPA suite/multicast suite */ +typedef struct +{ + uint8 oui[3]; + uint8 type; +} PACKED wpa_suite_t, wpa_suite_mcast_t; +#define WPA_SUITE_LEN 4 + +/* WPA unicast suite list/key management suite list */ +typedef struct +{ + struct { + uint8 low; + uint8 high; + } PACKED count; + wpa_suite_t list[1]; +} PACKED wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; +#define WPA_IE_SUITE_COUNT_LEN 2 +#ifdef BCMWPA2 +typedef struct +{ + struct { + uint8 low; + uint8 high; + } PACKED count; + wpa_pmkid_t list[1]; +} PACKED wpa_pmkid_list_t; +#endif + +/* WPA cipher suites */ +#define WPA_CIPHER_NONE 0 /* None */ +#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ +#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ +#define WPA_CIPHER_AES_OCB 3 /* AES (OCB) */ +#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ +#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ + +#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ + (cipher) == WPA_CIPHER_WEP_40 || \ + (cipher) == WPA_CIPHER_WEP_104 || \ + (cipher) == WPA_CIPHER_TKIP || \ + (cipher) == WPA_CIPHER_AES_OCB || \ + (cipher) == WPA_CIPHER_AES_CCM) + +/* WPA TKIP countermeasures parameters */ +#define WPA_TKIP_CM_DETECT 60 /* multiple MIC failure window (seconds) */ +#define WPA_TKIP_CM_BLOCK 60 /* countermeasures active window (seconds) */ + +/* WPA capabilities defined in 802.11i */ +#define WPA_CAP_4_REPLAY_CNTRS 2 +#define WPA_CAP_16_REPLAY_CNTRS 3 +#define WPA_CAP_REPLAY_CNTR_SHIFT 2 +#define WPA_CAP_REPLAY_CNTR_MASK 0x000c + +/* WPA Specific defines */ +#define WPA_CAP_LEN 2 /* Length of RSN capabilities in RSN IE (2 octets) */ + +#ifdef BCMWPA2 +#define WPA_CAP_WPA2_PREAUTH 1 +#endif /* BCMWPA2 */ + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _proto_wpa_h_ */ diff --git a/package/broadcom-wl/src/wlc/include/typedefs.h b/package/broadcom-wl/src/wlc/include/typedefs.h new file mode 100644 index 0000000000..6c498bbcb2 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/typedefs.h @@ -0,0 +1,230 @@ +/* + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * $Id: typedefs.h,v 1.1.1.12 2006/04/08 06:13:40 honor Exp $ + */ + +#ifndef _TYPEDEFS_H_ +#define _TYPEDEFS_H_ + +/* + * Inferred Typedefs + * + */ + +/* Infer the compile environment based on preprocessor symbols and pramas. + * Override type definitions as needed, and include configuration dependent + * header files to define types. + */ + +#ifdef __cplusplus + +#define TYPEDEF_BOOL +#ifndef FALSE +#define FALSE false +#endif +#ifndef TRUE +#define TRUE true +#endif + +#endif /* __cplusplus */ + +#if defined(_NEED_SIZE_T_) +typedef long unsigned int size_t; +#endif + +#define TYPEDEF_UINT +#define TYPEDEF_USHORT +#define TYPEDEF_ULONG + + +/* Do not support the (u)int64 types with strict ansi for GNU C */ +#if defined(__GNUC__) && defined(__STRICT_ANSI__) +#define TYPEDEF_INT64 +#define TYPEDEF_UINT64 +#endif + +/* pick up ushort & uint from standard types.h */ +#if defined(linux) && defined(__KERNEL__) +#include /* sys/types.h and linux/types.h are oil and water */ +#else +#include +#endif + +/* use the default typedefs in the next section of this file */ +#define USE_TYPEDEF_DEFAULTS + +/* + * Default Typedefs + * + */ + +#ifdef USE_TYPEDEF_DEFAULTS +#undef USE_TYPEDEF_DEFAULTS + +#ifndef TYPEDEF_BOOL +typedef /* @abstract@ */ unsigned char bool; +#endif + +/* define uchar, ushort, uint, ulong */ + +#ifndef TYPEDEF_UCHAR +typedef unsigned char uchar; +#endif + +#ifndef TYPEDEF_USHORT +typedef unsigned short ushort; +#endif + +#ifndef TYPEDEF_UINT +typedef unsigned int uint; +#endif + +#ifndef TYPEDEF_ULONG +typedef unsigned long ulong; +#endif + +/* define [u]int8/16/32/64, uintptr */ + +#ifndef TYPEDEF_UINT8 +typedef unsigned char uint8; +#endif + +#ifndef TYPEDEF_UINT16 +typedef unsigned short uint16; +#endif + +#ifndef TYPEDEF_UINT32 +typedef unsigned int uint32; +#endif + +#ifndef TYPEDEF_UINT64 +typedef unsigned long long uint64; +#endif + +#ifndef TYPEDEF_UINTPTR +typedef unsigned int uintptr; +#endif + +#ifndef TYPEDEF_INT8 +typedef signed char int8; +#endif + +#ifndef TYPEDEF_INT16 +typedef signed short int16; +#endif + +#ifndef TYPEDEF_INT32 +typedef signed int int32; +#endif + +#ifndef TYPEDEF_INT64 +typedef signed long long int64; +#endif + +/* define float32/64, float_t */ + +#ifndef TYPEDEF_FLOAT32 +typedef float float32; +#endif + +#ifndef TYPEDEF_FLOAT64 +typedef double float64; +#endif + +/* + * abstracted floating point type allows for compile time selection of + * single or double precision arithmetic. Compiling with -DFLOAT32 + * selects single precision; the default is double precision. + */ + +#ifndef TYPEDEF_FLOAT_T + +#if defined(FLOAT32) +typedef float32 float_t; +#else /* default to double precision floating point */ +typedef float64 float_t; +#endif + +#endif /* TYPEDEF_FLOAT_T */ + +/* define macro values */ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 /* TRUE */ +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef OFF +#define OFF 0 +#endif + +#ifndef ON +#define ON 1 /* ON = 1 */ +#endif + +#define AUTO (-1) /* Auto = -1 */ + +/* define PTRSZ, INLINE */ + +#ifndef PTRSZ +#define PTRSZ sizeof(char*) +#endif + +#ifndef INLINE + +#ifdef _MSC_VER + +#define INLINE __inline + +#elif __GNUC__ + +#define INLINE __inline__ + +#else + +#define INLINE + +#endif /* _MSC_VER */ + +#endif /* INLINE */ + +#undef TYPEDEF_BOOL +#undef TYPEDEF_UCHAR +#undef TYPEDEF_USHORT +#undef TYPEDEF_UINT +#undef TYPEDEF_ULONG +#undef TYPEDEF_UINT8 +#undef TYPEDEF_UINT16 +#undef TYPEDEF_UINT32 +#undef TYPEDEF_UINT64 +#undef TYPEDEF_UINTPTR +#undef TYPEDEF_INT8 +#undef TYPEDEF_INT16 +#undef TYPEDEF_INT32 +#undef TYPEDEF_INT64 +#undef TYPEDEF_FLOAT32 +#undef TYPEDEF_FLOAT64 +#undef TYPEDEF_FLOAT_T + +#endif /* USE_TYPEDEF_DEFAULTS */ + +/* + * Including the bcmdefs.h here, to make sure everyone including typedefs.h + * gets this automatically +*/ +#include + +#endif /* _TYPEDEFS_H_ */ diff --git a/package/broadcom-wl/src/wlc/include/wlioctl.h b/package/broadcom-wl/src/wlc/include/wlioctl.h new file mode 100644 index 0000000000..0558415d33 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/wlioctl.h @@ -0,0 +1,1384 @@ +/* + * Custom OID/ioctl definitions for + * Broadcom 802.11abg Networking Device Driver + * + * Definitions subject to change without notice. + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: wlioctl.h,v 1.1.1.22 2006/04/15 01:29:08 michael Exp $ + */ + +#ifndef _wlioctl_h_ +#define _wlioctl_h_ + +#include +#include +#include +#include +#include + +#ifdef __NetBSD__ +/* NetBSD 2.0 does not have SIOCDEVPRIVATE. This is NetBSD 2.0 specific */ +#define SIOCDEVPRIVATE _IOWR('i', 139, struct ifreq) +#endif + +/* require default structure packing */ +#if !defined(__GNUC__) +#pragma pack(push, 8) +#endif + +/* A chanspec holds the channel number, band, bandwidth and control sideband */ +typedef uint16 chanspec_t; +#define WL_CHANSPEC_CHAN_MASK 0x00ff + +#define WL_CHANSPEC_CTL_SB_MASK 0x0300 +#define WL_CHANSPEC_CTL_SB_SHIFT 8 +#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 +#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 +#define WL_CHANSPEC_CTL_SB_NONE 0x0300 + +#define WL_CHANSPEC_BW_MASK 0x0C00 +#define WL_CHANSPEC_BW_SHIFT 10 +#define WL_CHANSPEC_BW_10 0x0400 +#define WL_CHANSPEC_BW_20 0x0800 +#define WL_CHANSPEC_BW_40 0x0C00 + +#define WL_CHANSPEC_BAND_MASK 0xf000 +#define WL_CHANSPEC_BAND_SHIFT 12 +#define WL_CHANSPEC_BAND_5G 0x1000 +#define WL_CHANSPEC_BAND_2G 0x2000 +#define INVCHANSPEC 255 + +/* Legacy structure to help keep backward compatible wl tool and tray app */ + +#define LEGACY_WL_BSS_INFO_VERSION 107 /* older version of wl_bss_info struct */ + +typedef struct wl_bss_info_107 { + uint32 version; /* version field */ + uint32 length; /* byte length of data in this record, + * starting at version and including IEs + */ + struct ether_addr BSSID; + uint16 beacon_period; /* units are Kusec */ + uint16 capability; /* Capability information */ + uint8 SSID_len; + uint8 SSID[32]; + struct { + uint count; /* # rates in this set */ + uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ + } rateset; /* supported rates */ + uint8 channel; /* Channel no. */ + uint16 atim_window; /* units are Kusec */ + uint8 dtim_period; /* DTIM period */ + int16 RSSI; /* receive signal strength (in dBm) */ + int8 phy_noise; /* noise (in dBm) */ + uint32 ie_length; /* byte length of Information Elements */ + /* variable length Information Elements */ +} wl_bss_info_107_t; + +/* + * Per-bss information structure. + */ + +#define WL_BSS_INFO_VERSION 108 /* current version of wl_bss_info struct */ + +/* BSS info structure + * Applications MUST CHECK ie_offset field and length field to access IEs and + * next bss_info structure in a vector (in wl_scan_results_t) + */ +typedef struct wl_bss_info { + uint32 version; /* version field */ + uint32 length; /* byte length of data in this record, + * starting at version and including IEs + */ + struct ether_addr BSSID; + uint16 beacon_period; /* units are Kusec */ + uint16 capability; /* Capability information */ + uint8 SSID_len; + uint8 SSID[32]; + struct { + uint count; /* # rates in this set */ + uint8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ + } rateset; /* supported rates */ + chanspec_t chanspec; /* chanspec for bss */ + uint16 atim_window; /* units are Kusec */ + uint8 dtim_period; /* DTIM period */ + int16 RSSI; /* receive signal strength (in dBm) */ + int8 phy_noise; /* noise (in dBm) */ + + bool n_cap; /* BSS is 802.11N Capable */ + uint32 nbss_cap; /* 802.11N BSS Capabilities (based on EWC_CAP_*) */ + uint8 ctl_ch; /* 802.11N BSS control channel number */ + uint32 reserved[2]; /* Reserved for expansion of BSS properties */ + uint8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ + + uint16 ie_offset; /* offset at which IEs start, from beginning */ + uint32 ie_length; /* byte length of Information Elements */ + /* Add new fields here */ + /* variable length Information Elements */ +} wl_bss_info_t; + +typedef struct wlc_ssid { + uint32 SSID_len; + uchar SSID[32]; +} wlc_ssid_t; + +typedef struct wl_scan_params { + wlc_ssid_t ssid; /* default: {0, ""} */ + struct ether_addr bssid; /* default: bcast */ + int8 bss_type; /* default: any, + * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT + */ + int8 scan_type; /* -1 use default, DOT11_SCANTYPE_ACTIVE/PASSIVE */ + int32 nprobes; /* -1 use default, number of probes per channel */ + int32 active_time; /* -1 use default, dwell time per channel for + * active scanning + */ + int32 passive_time; /* -1 use default, dwell time per channel + * for passive scanning + */ + int32 home_time; /* -1 use default, dwell time for the home channel + * between channel scans + */ + int32 channel_num; /* 0 use default (all available channels), count of + * channels in channel_list + */ + uint16 channel_list[1]; /* list of chanspecs */ +} wl_scan_params_t; +/* size of wl_scan_params not including variable length array */ +#define WL_SCAN_PARAMS_FIXED_SIZE 64 + +typedef struct wl_scan_results { + uint32 buflen; + uint32 version; + uint32 count; + wl_bss_info_t bss_info[1]; +} wl_scan_results_t; +/* size of wl_scan_results not including variable length array */ +#define WL_SCAN_RESULTS_FIXED_SIZE 12 + + +#define WL_NUMRATES 255 /* max # of rates in a rateset */ +typedef struct wl_rateset { + uint32 count; /* # rates in this set */ + uint8 rates[WL_NUMRATES]; /* rates in 500kbps units w/hi bit set if basic */ +} wl_rateset_t; + +/* uint32 list */ +typedef struct wl_uint32_list { + /* in - # of elements, out - # of entries */ + uint32 count; + /* variable length uint32 list */ + uint32 element[1]; +} wl_uint32_list_t; + +#define WLC_CNTRY_BUF_SZ 4 /* Country string is 3 bytes + NULL */ + +/* defines used by the nrate iovar */ +#define NRATE_MCS_INUSE 0x00000080 /* MSC in use,indicates b0-6 holds an mcs */ +#define NRATE_RATE_MASK 0x0000007f /* rate/mcs value */ +#define NRATE_STF_MASK 0x0000ff00 /* stf mode mask: siso, cdd, stbc, sdm */ +#define NRATE_STF_SHIFT 8 /* stf mode shift */ + +#define ANTENNA_NUM_1 1 /* total number of antennas to be used */ +#define ANTENNA_NUM_2 2 +#define ANTENNA_NUM_3 3 +#define ANTENNA_NUM_4 4 + +typedef struct wl_channels_in_country { + uint32 buflen; + uint32 band; + char country_abbrev[WLC_CNTRY_BUF_SZ]; + uint32 count; + uint32 channel[1]; +} wl_channels_in_country_t; + +typedef struct wl_country_list { + uint32 buflen; + uint32 band_set; + uint32 band; + uint32 count; + char country_abbrev[1]; +} wl_country_list_t; + +#define WL_RM_TYPE_BASIC 1 +#define WL_RM_TYPE_CCA 2 +#define WL_RM_TYPE_RPI 3 + +#define WL_RM_FLAG_PARALLEL (1<<0) + +#define WL_RM_FLAG_LATE (1<<1) +#define WL_RM_FLAG_INCAPABLE (1<<2) +#define WL_RM_FLAG_REFUSED (1<<3) + +typedef struct wl_rm_req_elt { + int8 type; + int8 flags; + chanspec_t chanspec; + uint32 token; /* token for this measurement */ + uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ + uint32 tsf_l; /* TSF low 32-bits */ + uint32 dur; /* TUs */ +} wl_rm_req_elt_t; + +typedef struct wl_rm_req { + uint32 token; /* overall measurement set token */ + uint32 count; /* number of measurement requests */ + wl_rm_req_elt_t req[1]; /* variable length block of requests */ +} wl_rm_req_t; +#define WL_RM_REQ_FIXED_LEN 8 + +typedef struct wl_rm_rep_elt { + int8 type; + int8 flags; + chanspec_t chanspec; + uint32 token; /* token for this measurement */ + uint32 tsf_h; /* TSF high 32-bits of Measurement start time */ + uint32 tsf_l; /* TSF low 32-bits */ + uint32 dur; /* TUs */ + uint32 len; /* byte length of data block */ + uint8 data[1]; /* variable length data block */ +} wl_rm_rep_elt_t; +#define WL_RM_REP_ELT_FIXED_LEN 24 /* length excluding data block */ + +#define WL_RPI_REP_BIN_NUM 8 +typedef struct wl_rm_rpi_rep { + uint8 rpi[WL_RPI_REP_BIN_NUM]; + int8 rpi_max[WL_RPI_REP_BIN_NUM]; +} wl_rm_rpi_rep_t; + +typedef struct wl_rm_rep { + uint32 token; /* overall measurement set token */ + uint32 len; /* length of measurement report block */ + wl_rm_rep_elt_t rep[1]; /* variable length block of reports */ +} wl_rm_rep_t; +#define WL_RM_REP_FIXED_LEN 8 + + +#if defined(BCMSUP_PSK) +typedef enum sup_auth_status { + WLC_SUP_DISCONNECTED = 0, + WLC_SUP_CONNECTING, + WLC_SUP_IDREQUIRED, + WLC_SUP_AUTHENTICATING, + WLC_SUP_AUTHENTICATED, + WLC_SUP_KEYXCHANGE, + WLC_SUP_KEYED, + WLC_SUP_TIMEOUT +} sup_auth_status_t; +#endif /* BCMCCX | BCMSUP_PSK */ + +/* Enumerate crypto algorithms */ +#define CRYPTO_ALGO_OFF 0 +#define CRYPTO_ALGO_WEP1 1 +#define CRYPTO_ALGO_TKIP 2 +#define CRYPTO_ALGO_WEP128 3 +#define CRYPTO_ALGO_AES_CCM 4 +#define CRYPTO_ALGO_AES_OCB_MSDU 5 +#define CRYPTO_ALGO_AES_OCB_MPDU 6 +#define CRYPTO_ALGO_NALG 7 + +#define WSEC_GEN_MIC_ERROR 0x0001 +#define WSEC_GEN_REPLAY 0x0002 + +#define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ +#define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ +#define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ +#define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ + +typedef struct wl_wsec_key { + uint32 index; /* key index */ + uint32 len; /* key length */ + uint8 data[DOT11_MAX_KEY_SIZE]; /* key data */ + uint32 pad_1[18]; + uint32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ + uint32 flags; /* misc flags */ + uint32 pad_2[2]; + int pad_3; + int iv_initialized; /* has IV been initialized already? */ + int pad_4; + /* Rx IV */ + struct { + uint32 hi; /* upper 32 bits of IV */ + uint16 lo; /* lower 16 bits of IV */ + } rxiv; + uint32 pad_5[2]; + struct ether_addr ea; /* per station */ +} wl_wsec_key_t; + +#define WSEC_MIN_PSK_LEN 8 +#define WSEC_MAX_PSK_LEN 64 + +/* Flag for key material needing passhash'ing */ +#define WSEC_PASSPHRASE (1<<0) + +/* receptacle for WLC_SET_WSEC_PMK parameter */ +typedef struct { + ushort key_len; /* octets in key material */ + ushort flags; /* key handling qualification */ + uint8 key[WSEC_MAX_PSK_LEN]; /* PMK material */ +} wsec_pmk_t; + +/* wireless security bitvec */ +#define WEP_ENABLED 0x0001 +#define TKIP_ENABLED 0x0002 +#define AES_ENABLED 0x0004 +#define WSEC_SWFLAG 0x0008 +#define SES_OW_ENABLED 0x0040 /* to go into transition mode without setting wep */ +#define FIPS_ENABLED 0x0080 + +/* WPA authentication mode bitvec */ +#define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ +#define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ +#define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ +#define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ +/* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ +#ifdef BCMWPA2 +#define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ +#define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ +#endif /* BCMWPA2 */ + +#ifdef BCMWPA2 +/* pmkid */ +#define MAXPMKID 16 + +typedef struct _pmkid +{ + struct ether_addr BSSID; + uint8 PMKID[WPA2_PMKID_LEN]; +} pmkid_t; + +typedef struct _pmkid_list +{ + uint32 npmkid; + pmkid_t pmkid[1]; +} pmkid_list_t; + +typedef struct _pmkid_cand { + struct ether_addr BSSID; + uint8 preauth; +} pmkid_cand_t; + +typedef struct _pmkid_cand_list { + uint32 npmkid_cand; + pmkid_cand_t pmkid_cand[1]; +} pmkid_cand_list_t; +#endif /* BCMWPA2 */ + +typedef struct wl_led_info { + uint32 index; /* led index */ + uint32 behavior; + bool activehi; +} wl_led_info_t; + +typedef struct wlc_assoc_info { + uint32 req_len; + uint32 resp_len; + uint32 flags; + struct dot11_assoc_req req; + struct ether_addr reassoc_bssid; /* used in reassoc's */ + struct dot11_assoc_resp resp; +} wl_assoc_info_t; +/* flags */ +#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */ +/* srom read/write struct passed through ioctl */ +typedef struct { + uint byteoff; /* byte offset */ + uint nbytes; /* number of bytes */ + uint16 buf[1]; +} srom_rw_t; + +/* R_REG and W_REG struct passed through ioctl */ +typedef struct { + uint32 byteoff; /* byte offset of the field in d11regs_t */ + uint32 val; /* read/write value of the field */ + uint32 size; /* sizeof the field */ + uint band; /* band (optional) */ +} rw_reg_t; + +/* Structure used by GET/SET_ATTEN ioctls - it controls power in b/g-band */ +/* PCL - Power Control Loop */ +/* current gain setting is replaced by user input */ +#define WL_ATTEN_APP_INPUT_PCL_OFF 0 /* turn off PCL, apply supplied input */ +#define WL_ATTEN_PCL_ON 1 /* turn on PCL */ +/* current gain setting is maintained */ +#define WL_ATTEN_PCL_OFF 2 /* turn off PCL. */ +typedef struct { + uint16 auto_ctrl; /* WL_ATTEN_XX */ + uint16 bb; /* Baseband attenuation */ + uint16 radio; /* Radio attenuation */ + uint16 txctl1; /* Radio TX_CTL1 value */ +} atten_t; + +/* defines used by poweridx iovar - it controls power in a-band */ +/* current gain setting is maintained */ +#define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ +#define WL_PWRIDX_PCL_ON -1 /* turn on PCL */ +#define WL_PWRIDX_LOWER_LIMIT -2 /* lower limit */ +#define WL_PWRIDX_UPPER_LIMIT 63 /* upper limit */ +/* value >= 0 causes + * - input to be set to that value + * - PCL to be off + */ + +/* Used to get specific STA parameters */ +typedef struct { + uint32 val; + struct ether_addr ea; +} scb_val_t; + + +/* Event data type */ +typedef struct wlc_event { + wl_event_msg_t event; /* encapsulated event */ + struct ether_addr *addr; /* used to keep a trace of the potential present of + * an address in wlc_event_msg_t + */ + void *data; /* used to hang additional data on an event */ + struct wlc_event *next; /* enables ordered list of pending events */ +} wlc_event_t; + +#define BCM_MAC_STATUS_INDICATION (0x40010200L) + +/* Please update the following when modifying this structure: + * StaInfo Twiki page flags section - description of the sta_info_t struct + * src/wl/exe/wlu.c - print of sta_info_t + * Pay attention to version if structure changes. + */ +typedef struct { + uint16 ver; /* version of this struct */ + uint16 len; /* length in bytes of this structure */ + uint16 cap; /* sta's advertised capabilities */ + uint32 flags; /* flags defined below */ + uint32 idle; /* time since data pkt rx'd from sta */ + struct ether_addr ea; /* Station address */ + wl_rateset_t rateset; /* rateset in use */ + uint32 in; /* seconds elapsed since associated */ + uint32 listen_interval_inms; /* Min Listen interval in ms for this STA */ +} sta_info_t; + +#define WL_STA_VER 2 + +/* Flags for sta_info_t indicating properties of STA */ +#define WL_STA_BRCM 0x1 /* Running a Broadcom driver */ +#define WL_STA_WME 0x2 /* WMM association */ +#define WL_STA_ABCAP 0x4 /* Afterburner-capable */ +#define WL_STA_AUTHE 0x8 /* Authenticated */ +#define WL_STA_ASSOC 0x10 /* Associated */ +#define WL_STA_AUTHO 0x20 /* Authorized */ +#define WL_STA_WDS 0x40 /* Wireless Distribution System */ +#define WL_STA_WDS_LINKUP 0x80 /* WDS traffic/probes flowing properly */ +#define WL_STA_PS 0x100 /* STA is in power save mode from AP's viewpoint */ +#define WL_STA_APSD_BE 0x200 /* APSD delv/trigger for AC_BE is default enabled */ +#define WL_STA_APSD_BK 0x400 /* APSD delv/trigger for AC_BK is default enabled */ +#define WL_STA_APSD_VI 0x800 /* APSD delv/trigger for AC_VI is default enabled */ +#define WL_STA_APSD_VO 0x1000 /* APSD delv/trigger for AC_VO is default enabled */ +#define WL_STA_N_CAP 0x2000 /* STA 802.11n capable */ + +#define WL_WDS_LINKUP WL_STA_WDS_LINKUP /* deprecated */ + +/* + * Country locale determines which channels are available to us. + */ +typedef enum _wlc_locale { + WLC_WW = 0, /* Worldwide */ + WLC_THA, /* Thailand */ + WLC_ISR, /* Israel */ + WLC_JDN, /* Jordan */ + WLC_PRC, /* China */ + WLC_JPN, /* Japan */ + WLC_FCC, /* USA */ + WLC_EUR, /* Europe */ + WLC_USL, /* US Low Band only */ + WLC_JPH, /* Japan High Band only */ + WLC_ALL, /* All the channels in this band */ + WLC_11D, /* Represents locale received by 11d beacons */ + WLC_LAST_LOCALE, + WLC_UNDEFINED_LOCALE = 0xf +} wlc_locale_t; + +/* channel encoding */ +typedef struct channel_info { + int hw_channel; + int target_channel; + int scan_channel; +} channel_info_t; + +/* For ioctls that take a list of MAC addresses */ +struct maclist { + uint count; /* number of MAC addresses */ + struct ether_addr ea[1]; /* variable length array of MAC addresses */ +}; + +/* get pkt count struct passed through ioctl */ +typedef struct get_pktcnt { + uint rx_good_pkt; + uint rx_bad_pkt; + uint tx_good_pkt; + uint tx_bad_pkt; +} get_pktcnt_t; + +/* Linux network driver ioctl encoding */ +typedef struct wl_ioctl { + uint cmd; /* common ioctl definition */ + void *buf; /* pointer to user buffer */ + uint len; /* length of user buffer */ + bool set; /* get or set request (optional) */ + uint used; /* bytes read or written (optional) */ + uint needed; /* bytes needed (optional) */ +} wl_ioctl_t; + +/* + * Structure for passing hardware and software + * revision info up from the driver. + */ +typedef struct wlc_rev_info { + uint vendorid; /* PCI vendor id */ + uint deviceid; /* device id of chip */ + uint radiorev; /* radio revision */ + uint chiprev; /* chip revision */ + uint corerev; /* core revision */ + uint boardid; /* board identifier (usu. PCI sub-device id) */ + uint boardvendor; /* board vendor (usu. PCI sub-vendor id) */ + uint boardrev; /* board revision */ + uint driverrev; /* driver version */ + uint ucoderev; /* microcode version */ + uint bus; /* bus type */ + uint chipnum; /* chip number */ +} wlc_rev_info_t; + +#define WL_BRAND_MAX 10 +typedef struct wl_instance_info { + uint instance; + char brand[WL_BRAND_MAX]; +} wl_instance_info_t; + +/* check this magic number */ +#define WLC_IOCTL_MAGIC 0x14e46c77 + +/* bump this number if you change the ioctl interface */ +#define WLC_IOCTL_VERSION 1 + +#define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ +#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ + +/* common ioctl definitions */ +#define WLC_GET_MAGIC 0 +#define WLC_GET_VERSION 1 +#define WLC_UP 2 +#define WLC_DOWN 3 +#define WLC_DUMP 6 +#define WLC_GET_MSGLEVEL 7 +#define WLC_SET_MSGLEVEL 8 +#define WLC_GET_PROMISC 9 +#define WLC_SET_PROMISC 10 +#define WLC_GET_RATE 12 +/* #define WLC_SET_RATE 13 */ /* no longer supported */ +#define WLC_GET_INSTANCE 14 +/* #define WLC_GET_FRAG 15 */ /* no longer supported */ +/* #define WLC_SET_FRAG 16 */ /* no longer supported */ +/* #define WLC_GET_RTS 17 */ /* no longer supported */ +/* #define WLC_SET_RTS 18 */ /* no longer supported */ +#define WLC_GET_INFRA 19 +#define WLC_SET_INFRA 20 +#define WLC_GET_AUTH 21 +#define WLC_SET_AUTH 22 +#define WLC_GET_BSSID 23 +#define WLC_SET_BSSID 24 +#define WLC_GET_SSID 25 +#define WLC_SET_SSID 26 +#define WLC_RESTART 27 +#define WLC_GET_CHANNEL 29 +#define WLC_SET_CHANNEL 30 +#define WLC_GET_SRL 31 +#define WLC_SET_SRL 32 +#define WLC_GET_LRL 33 +#define WLC_SET_LRL 34 +#define WLC_GET_PLCPHDR 35 +#define WLC_SET_PLCPHDR 36 +#define WLC_GET_RADIO 37 +#define WLC_SET_RADIO 38 +#define WLC_GET_PHYTYPE 39 +/* #define WLC_GET_WEP 42 */ /* no longer supported */ +/* #define WLC_SET_WEP 43 */ /* no longer supported */ +#define WLC_GET_KEY 44 +#define WLC_SET_KEY 45 +#define WLC_GET_REGULATORY 46 +#define WLC_SET_REGULATORY 47 +#define WLC_GET_PASSIVE 48 +#define WLC_SET_PASSIVE 49 +#define WLC_SCAN 50 +#define WLC_SCAN_RESULTS 51 +#define WLC_DISASSOC 52 +#define WLC_REASSOC 53 +#define WLC_GET_ROAM_TRIGGER 54 +#define WLC_SET_ROAM_TRIGGER 55 +#define WLC_GET_TXANT 61 +#define WLC_SET_TXANT 62 +#define WLC_GET_ANTDIV 63 +#define WLC_SET_ANTDIV 64 +/* #define WLC_GET_TXPWR 65 */ /* no longer supported */ +/* #define WLC_SET_TXPWR 66 */ /* no longer supported */ +#define WLC_GET_CLOSED 67 +#define WLC_SET_CLOSED 68 +#define WLC_GET_MACLIST 69 +#define WLC_SET_MACLIST 70 +#define WLC_GET_RATESET 71 +#define WLC_SET_RATESET 72 +#define WLC_GET_LOCALE 73 +#define WLC_LONGTRAIN 74 +#define WLC_GET_BCNPRD 75 +#define WLC_SET_BCNPRD 76 +#define WLC_GET_DTIMPRD 77 +#define WLC_SET_DTIMPRD 78 +#define WLC_GET_SROM 79 +#define WLC_SET_SROM 80 +#define WLC_GET_WEP_RESTRICT 81 +#define WLC_SET_WEP_RESTRICT 82 +#define WLC_GET_COUNTRY 83 +#define WLC_SET_COUNTRY 84 +#define WLC_GET_PM 85 +#define WLC_SET_PM 86 +#define WLC_GET_WAKE 87 +#define WLC_SET_WAKE 88 +#define WLC_GET_D11CNTS 89 +#define WLC_GET_FORCELINK 90 /* ndis only */ +#define WLC_SET_FORCELINK 91 /* ndis only */ +#define WLC_FREQ_ACCURACY 92 +#define WLC_CARRIER_SUPPRESS 93 +#define WLC_GET_PHYREG 94 +#define WLC_SET_PHYREG 95 +#define WLC_GET_RADIOREG 96 +#define WLC_SET_RADIOREG 97 +#define WLC_GET_REVINFO 98 +#define WLC_GET_UCANTDIV 99 +#define WLC_SET_UCANTDIV 100 +#define WLC_R_REG 101 +#define WLC_W_REG 102 +#define WLC_DIAG_LOOPBACK 103 +#define WLC_RESET_D11CNTS 104 +#define WLC_GET_MACMODE 105 +#define WLC_SET_MACMODE 106 +#define WLC_GET_MONITOR 107 +#define WLC_SET_MONITOR 108 +#define WLC_GET_GMODE 109 +#define WLC_SET_GMODE 110 +#define WLC_GET_LEGACY_ERP 111 +#define WLC_SET_LEGACY_ERP 112 +#define WLC_GET_RX_ANT 113 +#define WLC_GET_CURR_RATESET 114 /* current rateset */ +#define WLC_GET_SCANSUPPRESS 115 +#define WLC_SET_SCANSUPPRESS 116 +#define WLC_GET_AP 117 +#define WLC_SET_AP 118 +#define WLC_GET_EAP_RESTRICT 119 +#define WLC_SET_EAP_RESTRICT 120 +#define WLC_SCB_AUTHORIZE 121 +#define WLC_SCB_DEAUTHORIZE 122 +#define WLC_GET_WDSLIST 123 +#define WLC_SET_WDSLIST 124 +#define WLC_GET_ATIM 125 +#define WLC_SET_ATIM 126 +#define WLC_GET_RSSI 127 +#define WLC_GET_PHYANTDIV 128 +#define WLC_SET_PHYANTDIV 129 +#define WLC_AP_RX_ONLY 130 +#define WLC_GET_TX_PATH_PWR 131 +#define WLC_SET_TX_PATH_PWR 132 +#define WLC_GET_WSEC 133 +#define WLC_SET_WSEC 134 +#define WLC_GET_PHY_NOISE 135 +#define WLC_GET_BSS_INFO 136 +#define WLC_GET_PKTCNTS 137 +#define WLC_GET_LAZYWDS 138 +#define WLC_SET_LAZYWDS 139 +#define WLC_GET_BANDLIST 140 +#define WLC_GET_BAND 141 +#define WLC_SET_BAND 142 +#define WLC_SCB_DEAUTHENTICATE 143 +#define WLC_GET_SHORTSLOT 144 +#define WLC_GET_SHORTSLOT_OVERRIDE 145 +#define WLC_SET_SHORTSLOT_OVERRIDE 146 +#define WLC_GET_SHORTSLOT_RESTRICT 147 +#define WLC_SET_SHORTSLOT_RESTRICT 148 +#define WLC_GET_GMODE_PROTECTION 149 +#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 +#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 +#define WLC_UPGRADE 152 +/* #define WLC_GET_MRATE 153 */ /* no longer supported */ +/* #define WLC_SET_MRATE 154 */ /* no longer supported */ +#define WLC_GET_ASSOCLIST 159 +#define WLC_GET_CLK 160 +#define WLC_SET_CLK 161 +#define WLC_GET_UP 162 +#define WLC_OUT 163 +#define WLC_GET_WPA_AUTH 164 +#define WLC_SET_WPA_AUTH 165 +#define WLC_GET_PROTECTION_CONTROL 178 +#define WLC_SET_PROTECTION_CONTROL 179 +#define WLC_GET_PHYLIST 180 +#define WLC_GET_KEY_SEQ 183 +/* #define WLC_GET_GMODE_PROTECTION_CTS 198 */ /* no longer supported */ +/* #define WLC_SET_GMODE_PROTECTION_CTS 199 */ /* no longer supported */ +#define WLC_GET_PIOMODE 203 +#define WLC_SET_PIOMODE 204 +#define WLC_SET_LED 209 +#define WLC_GET_LED 210 +#define WLC_GET_CHANNEL_SEL 215 +#define WLC_START_CHANNEL_SEL 216 +#define WLC_GET_VALID_CHANNELS 217 +#define WLC_GET_FAKEFRAG 218 +#define WLC_SET_FAKEFRAG 219 +#define WLC_GET_WET 230 +#define WLC_SET_WET 231 +#define WLC_GET_KEY_PRIMARY 235 +#define WLC_SET_KEY_PRIMARY 236 +#define WLC_GET_RADAR 242 +#define WLC_SET_RADAR 243 +#define WLC_SET_SPECT_MANAGMENT 244 +#define WLC_GET_SPECT_MANAGMENT 245 +#define WLC_WDS_GET_REMOTE_HWADDR 246 /* handled in wl_linux.c/wl_vx.c */ +#define WLC_SET_CS_SCAN_TIMER 248 +#define WLC_GET_CS_SCAN_TIMER 249 +#define WLC_SEND_PWR_CONSTRAINT 254 +#define WLC_CURRENT_PWR 256 +#define WLC_GET_CHANNELS_IN_COUNTRY 260 +#define WLC_GET_COUNTRY_LIST 261 +#define WLC_GET_VAR 262 /* get value of named variable */ +#define WLC_SET_VAR 263 /* set named variable to value */ +#define WLC_NVRAM_GET 264 /* deprecated */ +#define WLC_NVRAM_SET 265 +#define WLC_SET_WSEC_PMK 268 +#define WLC_GET_AUTH_MODE 269 +#define WLC_SET_AUTH_MODE 270 +#define WLC_NDCONFIG_ITEM 273 /* currently handled in wl_oid.c */ +#define WLC_NVOTPW 274 +#define WLC_OTPW 275 +#define WLC_SET_LOCALE 278 +#define WLC_LAST 279 /* do not change - use get_var/set_var */ + +/* + * Minor kludge alert: + * Duplicate a few definitions that irelay requires from epiioctl.h here + * so caller doesn't have to include this file and epiioctl.h . + * If this grows any more, it would be time to move these irelay-specific + * definitions out of the epiioctl.h and into a separate driver common file. + */ +#ifndef EPICTRL_COOKIE +#define EPICTRL_COOKIE 0xABADCEDE +#endif + +/* vx wlc ioctl's offset */ +#define CMN_IOCTL_OFF 0x180 + +/* + * custom OID support + * + * 0xFF - implementation specific OID + * 0xE4 - first byte of Broadcom PCI vendor ID + * 0x14 - second byte of Broadcom PCI vendor ID + * 0xXX - the custom OID number + */ + +/* begin 0x1f values beyond the start of the ET driver range. */ +#define WL_OID_BASE 0xFFE41420 + +/* NDIS overrides */ +#define OID_WL_GETINSTANCE (WL_OID_BASE + WLC_GET_INSTANCE) +#define OID_WL_NDCONFIG_ITEM (WL_OID_BASE + WLC_NDCONFIG_ITEM) + +#define WL_DECRYPT_STATUS_SUCCESS 1 +#define WL_DECRYPT_STATUS_FAILURE 2 +#define WL_DECRYPT_STATUS_UNKNOWN 3 + +/* allows user-mode app to poll the status of USB image upgrade */ +#define WLC_UPGRADE_SUCCESS 0 +#define WLC_UPGRADE_PENDING 1 + +#ifdef CONFIG_USBRNDIS_RETAIL +/* struct passed in for WLC_NDCONFIG_ITEM */ +typedef struct { + char *name; + void *param; +} ndconfig_item_t; +#endif + +/* Bit masks for radio disabled status - returned by WL_GET_RADIO */ +#define WL_RADIO_SW_DISABLE (1<<0) +#define WL_RADIO_HW_DISABLE (1<<1) +#define WL_RADIO_MPC_DISABLE (1<<2) +#define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ + +/* Override bit for WLC_SET_TXPWR. if set, ignore other level limits */ +#define WL_TXPWR_OVERRIDE (1<<31) + +/* "diag" iovar argument and error code */ +#define WL_DIAG_INTERRUPT 1 /* d11 loopback interrupt test */ +#define WL_DIAG_MEMORY 3 /* d11 memory test */ +#define WL_DIAG_LED 4 /* LED test */ +#define WL_DIAG_REG 5 /* d11/phy register test */ +#define WL_DIAG_SROM 6 /* srom read/crc test */ +#define WL_DIAG_DMA 7 /* DMA test */ + +#define WL_DIAGERR_SUCCESS 0 +#define WL_DIAGERR_FAIL_TO_RUN 1 /* unable to run requested diag */ +#define WL_DIAGERR_NOT_SUPPORTED 2 /* diag requested is not supported */ +#define WL_DIAGERR_INTERRUPT_FAIL 3 /* loopback interrupt test failed */ +#define WL_DIAGERR_LOOPBACK_FAIL 4 /* loopback data test failed */ +#define WL_DIAGERR_SROM_FAIL 5 /* srom read failed */ +#define WL_DIAGERR_SROM_BADCRC 6 /* srom crc failed */ +#define WL_DIAGERR_REG_FAIL 7 /* d11/phy register test failed */ +#define WL_DIAGERR_MEMORY_FAIL 8 /* d11 memory test failed */ +#define WL_DIAGERR_NOMEM 9 /* diag test failed due to no memory */ +#define WL_DIAGERR_DMA_FAIL 10 /* DMA test failed */ + +/* band types */ +#define WLC_BAND_AUTO 0 /* auto-select */ +#define WLC_BAND_5G 1 /* 5 Ghz */ +#define WLC_BAND_2G 2 /* 2.4 Ghz */ +#define WLC_BAND_ALL 3 /* all bands */ + +/* phy types (returned by WLC_GET_PHYTPE) */ +#define WLC_PHY_TYPE_A 0 +#define WLC_PHY_TYPE_B 1 +#define WLC_PHY_TYPE_G 2 +#define WLC_PHY_TYPE_N 4 +#define WLC_PHY_TYPE_NULL 0xf + +/* MAC list modes */ +#define WLC_MACMODE_DISABLED 0 /* MAC list disabled */ +#define WLC_MACMODE_DENY 1 /* Deny specified (i.e. allow unspecified) */ +#define WLC_MACMODE_ALLOW 2 /* Allow specified (i.e. deny unspecified) */ + +/* + * + */ +#define GMODE_LEGACY_B 0 +#define GMODE_AUTO 1 +#define GMODE_ONLY 2 +#define GMODE_B_DEFERRED 3 +#define GMODE_PERFORMANCE 4 +#define GMODE_LRS 5 +#define GMODE_MAX 6 + +/* values for PLCPHdr_override */ +#define WLC_PLCP_AUTO -1 +#define WLC_PLCP_SHORT 0 +#define WLC_PLCP_LONG 1 + +/* values for g_protection_override and n_protection_override */ +#define WLC_PROTECTION_AUTO -1 +#define WLC_PROTECTION_OFF 0 +#define WLC_PROTECTION_ON 1 + +/* values for g_protection_control and n_protection_control */ +#define WLC_PROTECTION_CTL_OFF 0 +#define WLC_PROTECTION_CTL_LOCAL 1 +#define WLC_PROTECTION_CTL_OVERLAP 2 + +/* deprecated const names for g_protection_override */ +#define WLC_G_PROTECTION_AUTO WLC_PROTECTION_AUTO +#define WLC_G_PROTECTION_OFF WLC_PROTECTION_OFF +#define WLC_G_PROTECTION_ON WLC_PROTECTION_ON + +/* deprecated const names for g_protection_control */ +#define WLC_G_PROTECTION_CTL_OFF WLC_PROTECTION_CTL_OFF +#define WLC_G_PROTECTION_CTL_LOCAL WLC_PROTECTION_CTL_LOCAL +#define WLC_G_PROTECTION_CTL_OVERLAP WLC_PROTECTION_CTL_OVERLAP + +/* deprecated const names for get/set g_protection_control */ +#define WLC_GET_GMODE_PROTECTION_CONTROL WLC_GET_PROTECTION_CONTROL +#define WLC_SET_GMODE_PROTECTION_CONTROL WLC_SET_PROTECTION_CONTROL + +/* values for n_protection */ +#define WLC_N_PROTECTION_OFF 0 +#define WLC_N_PROTECTION_MIXEDMODE 1 +#define WLC_N_PROTECTION_CTS 2 + +/* values for n_preamble_type */ +#define WLC_N_PREAMBLE_MIXEDMODE 0 +#define WLC_N_PREAMBLE_GF 1 + +/* Values for PM */ +#define PM_OFF 0 +#define PM_MAX 1 +#define PM_FAST 2 + + + +typedef struct { + int npulses; /* required number of pulses at n * t_int */ + int ncontig; /* required number of pulses at t_int */ + int min_pw; /* minimum pulse width (20 MHz clocks) */ + int max_pw; /* maximum pulse width (20 MHz clocks) */ + uint16 thresh0; /* Radar detection, thresh 0 */ + uint16 thresh1; /* Radar detection, thresh 1 */ + int npulses_lp; /* Radar detection, minimum long pulses */ + int min_pw_lp; /* Minimum pulsewidth for long pulses */ + int max_pw_lp; /* Maximum pulsewidth for long pulses */ + int min_fm_lp; /* Minimum fm for long pulses */ + int max_deltat_lp; /* Maximum deltat for long pulses */ + int min_deltat; /* Minimum spacing between pulses */ +} wl_radar_args_t; + +/* radar iovar SET defines */ +#define WL_RADAR_DETECTOR_OFF 0 /* radar detector off */ +#define WL_RADAR_DETECTOR_ON 1 /* radar detector on */ +#define WL_RADAR_SIMULATED 2 /* force radar detector to declare + * detection once + */ + +/* dfs_status iovar-related defines */ + +/* cac - channel availability check, + * ism - in-service monitoring + * csa - channel switching announcement + */ + +/* cac state values */ +#define WL_DFS_CACSTATE_IDLE 0 /* state for operating in non-radar channel */ +#define WL_DFS_CACSTATE_PREISM_CAC 1 /* CAC in progress */ +#define WL_DFS_CACSTATE_ISM 2 /* ISM in progress */ +#define WL_DFS_CACSTATE_CSA 3 /* csa */ +#define WL_DFS_CACSTATE_POSTISM_CAC 4 /* ISM CAC */ +#define WL_DFS_CACSTATE_PREISM_OOC 5 /* PREISM OOC */ +#define WL_DFS_CACSTATE_POSTISM_OOC 6 /* POSTISM OOC */ +#define WL_DFS_CACSTATES 7 /* this many states exist */ + +/* data structure used in 'dfs_status' wl interface, which is used to query dfs status */ +typedef struct { + uint state; /* noted by WL_DFS_CACSTATE_XX. */ + uint duration; /* time spent in ms in state. */ + /* as dfs enters ISM state, it removes the operational channel from quiet channel + * list and notes the channel in channel_cleared. set to 0 if no channel is cleared + */ + chanspec_t chanspec_cleared; + /* chanspec cleared used to be a uint, add another to uint16 to maintain size */ + uint16 pad; +} wl_dfs_status_t; + +#define NUM_PWRCTRL_RATES 12 + +typedef struct tx_inst_power { +} tx_inst_power_t; + + +/* regulatory enforcement levels */ +#define SPECT_MNGMT_OFF 0 /* both 11h and 11d disabled */ +#define SPECT_MNGMT_LOOSE_11H 1 /* allow non-11h APs in scan lists */ +#define SPECT_MNGMT_STRICT_11H 2 /* prune out non-11h APs from scan list */ +#define SPECT_MNGMT_STRICT_11D 3 /* switch to 802.11D mode */ +/* SPECT_MNGMT_LOOSE_11H_D - same as SPECT_MNGMT_LOOSE with the exception that Country IE + * adoption is done irregardless of capability-spectrum_management + */ +#define SPECT_MNGMT_LOOSE_11H_D 4 /* operation defined above */ + +#define WL_CHAN_VALID_HW (1 << 0) /* valid with current HW */ +#define WL_CHAN_VALID_SW (1 << 1) /* valid with current country setting */ +#define WL_CHAN_BAND_5G (1 << 2) /* 5GHz-band channel */ +#define WL_CHAN_RADAR (1 << 3) /* radar sensitive channel */ +#define WL_CHAN_INACTIVE (1 << 4) /* temporarily inactive due to radar */ +#define WL_CHAN_PASSIVE (1 << 5) /* channel is in passive mode */ +#define WL_CHAN_RESTRICTED (1 << 6) /* restricted use channel */ + +/* BTC mode used by "btc_mode" iovar */ +#define WL_BTC_DISABLE 0 /* disable BT coexistance */ +#define WL_BTC_ENABLE 1 /* enable BT coexistance */ +#define WL_BTC_PREMPT 2 /* enable BT coexistance and BT pre-emption */ + +#define WL_MPC_VAL 0x00400000 +#define WL_APSTA_VAL 0x00800000 +#define WL_DFS_VAL 0x01000000 +#define WL_BA_VAL 0x02000000 +#define WL_NITRO_VAL 0x04000000 +#define WL_CAC_VAL 0x08000000 +#define WL_AMSDU_VAL 0x10000000 +#define WL_AMPDU_VAL 0x20000000 + +/* max # of leds supported by GPIO (gpio pin# == led index#) */ +#define WL_LED_NUMGPIO 16 /* gpio 0-15 */ + +/* led per-pin behaviors */ +#define WL_LED_OFF 0 /* always off */ +#define WL_LED_ON 1 /* always on */ +#define WL_LED_ACTIVITY 2 /* activity */ +#define WL_LED_RADIO 3 /* radio enabled */ +#define WL_LED_ARADIO 4 /* 5 Ghz radio enabled */ +#define WL_LED_BRADIO 5 /* 2.4Ghz radio enabled */ +#define WL_LED_BGMODE 6 /* on if gmode, off if bmode */ +#define WL_LED_WI1 7 +#define WL_LED_WI2 8 +#define WL_LED_WI3 9 +#define WL_LED_ASSOC 10 /* associated state indicator */ +#define WL_LED_INACTIVE 11 /* null behavior (clears default behavior) */ +#define WL_LED_NUMBEHAVIOR 12 + +/* led behavior numeric value format */ +#define WL_LED_BEH_MASK 0x7f /* behavior mask */ +#define WL_LED_AL_MASK 0x80 /* activelow (polarity) bit */ + +/* max # of channels returnd by the get valid channels iovar */ +#define WL_NUMCHANSPECS 100 + +/* WDS link local endpoint WPA role */ +#define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ +#define WL_WDS_WPA_ROLE_SUP 1 /* supplicant */ +#define WL_WDS_WPA_ROLE_AUTO 255 /* auto, based on mac addr value */ + +/* number of bytes needed to define a 128-bit mask for MAC event reporting */ +#define WL_EVENTING_MASK_LEN 16 + +/* Structures and constants used for "vndr_ie" IOVar interface */ +#define VNDR_IE_CMD_LEN 4 /* length of the set command string: + * "add", "del" (+ NULL) + */ + +/* 802.11 Mgmt Packet flags */ +#define VNDR_IE_BEACON_FLAG 0x1 +#define VNDR_IE_PRBRSP_FLAG 0x2 +#define VNDR_IE_ASSOCRSP_FLAG 0x4 +#define VNDR_IE_AUTHRSP_FLAG 0x8 + +#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) + +typedef struct { + uint32 pktflag; /* bitmask indicating which packet(s) contain this IE */ + vndr_ie_t vndr_ie_data; /* vendor IE data */ +} vndr_ie_info_t; + +typedef struct { + int iecount; /* number of entries in the vndr_ie_list[] array */ + vndr_ie_info_t vndr_ie_list[1]; /* variable size list of vndr_ie_info_t structs */ +} vndr_ie_buf_t; + +typedef struct { + char cmd[VNDR_IE_CMD_LEN]; /* vndr_ie IOVar set command : "add", "del" + NULL */ + vndr_ie_buf_t vndr_ie_buffer; /* buffer containing Vendor IE list information */ +} vndr_ie_setbuf_t; + +/* join target preference types */ +#define WL_JOIN_PREF_RSSI 1 /* by RSSI, mandatory */ +#define WL_JOIN_PREF_WPA 2 /* by akm and ciphers, optional, RSN and WPA as values */ +#define WL_JOIN_PREF_BAND 3 /* by 802.11 band, optional, WLC_BAND_XXXX as values */ + +/* band preference */ +#define WLJP_BAND_ASSOC_PREF 255 /* use assoc preference settings */ + /* others use WLC_BAND_XXXX as values */ + +/* any multicast cipher suite */ +#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" + +struct tsinfo_arg { + uint8 octets[3]; +}; + +#if !defined(__GNUC__) +#pragma pack(pop) +#endif + +#define NFIFO 6 /* # tx/rx fifopairs */ + +#define WL_CNT_T_VERSION 1 /* current version of wl_cnt_t struct */ + +typedef struct { + uint16 version; /* see definition of WL_CNT_T_VERSION */ + uint16 length; /* length of entire structure */ + + /* transmit stat counters */ + uint32 txframe; /* tx data frames */ + uint32 txbyte; /* tx data bytes */ + uint32 txretrans; /* tx mac retransmits */ + uint32 txerror; /* tx data errors (derived: sum of others) */ + uint32 txctl; /* tx management frames */ + uint32 txprshort; /* tx short preamble frames */ + uint32 txserr; /* tx status errors */ + uint32 txnobuf; /* tx out of buffers errors */ + uint32 txnoassoc; /* tx discard because we're not associated */ + uint32 txrunt; /* tx runt frames */ + uint32 txchit; /* tx header cache hit (fastpath) */ + uint32 txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32 txuflo; /* tx fifo underflows */ + uint32 txphyerr; /* tx phy errors (indicated in tx status) */ + uint32 txphycrs; + + /* receive stat counters */ + uint32 rxframe; /* rx data frames */ + uint32 rxbyte; /* rx data bytes */ + uint32 rxerror; /* rx data errors (derived: sum of others) */ + uint32 rxctl; /* rx management frames */ + uint32 rxnobuf; /* rx out of buffers errors */ + uint32 rxnondata; /* rx non data frames in the data channel errors */ + uint32 rxbadds; /* rx bad DS errors */ + uint32 rxbadcm; /* rx bad control or management frames */ + uint32 rxfragerr; /* rx fragmentation errors */ + uint32 rxrunt; /* rx runt frames */ + uint32 rxgiant; /* rx giant frames */ + uint32 rxnoscb; /* rx no scb error */ + uint32 rxbadproto; /* rx invalid frames */ + uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32 rxbadda; /* rx frames tossed for invalid da */ + uint32 rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32 rxoflo; /* rx fifo overflow errors */ + uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32 dmade; /* tx/rx dma descriptor errors */ + uint32 dmada; /* tx/rx dma data errors */ + uint32 dmape; /* tx/rx dma descriptor protocol errors */ + uint32 reset; /* reset count */ + uint32 tbtt; /* cnts the TBTT int's */ + uint32 txdmawar; + uint32 pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32 txrtsfrm; /* number of RTS sent out by the MAC */ + uint32 txctsfrm; /* number of CTS sent out by the MAC */ + uint32 txackfrm; /* number of ACK frames sent out */ + uint32 txdnlfrm; /* Not used */ + uint32 txbcnfrm; /* beacons transmitted */ + uint32 txfunfl[8]; /* per-fifo tx underflows */ + uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32 rxbadplcp; /* parity check of the PLCP header failed */ + uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32 rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32 rxbeaconmbss; /* beacons received from member of BSS */ + uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32 rxbeaconobss; /* beacons received from other BSS */ + uint32 rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32 pmqovfl; /* Number of PMQ overflows */ + uint32 rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32 rxnack; /* Number of NACKS received (Afterburner) */ + uint32 frmscons; /* Number of frames completed without transmission because of an + * Afterburner re-queue + */ + uint32 txnack; /* Number of NACKs transmitted (Afterburner) */ + uint32 txglitch_nack; /* obsolete */ + uint32 txburst; /* obsolete */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32 txfrag; /* dot11TransmittedFragmentCount */ + uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32 txfail; /* dot11FailedCount */ + uint32 txretry; /* dot11RetryCount */ + uint32 txretrie; /* dot11MultipleRetryCount */ + uint32 rxdup; /* dot11FrameduplicateCount */ + uint32 txrts; /* dot11RTSSuccessCount */ + uint32 txnocts; /* dot11RTSFailureCount */ + uint32 txnoack; /* dot11ACKFailureCount */ + uint32 rxfrag; /* dot11ReceivedFragmentCount */ + uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32 rxcrc; /* dot11FCSErrorCount */ + uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32 rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32 tkipmicfaill; /* TKIPLocalMICFailures */ + uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32 tkipreplay; /* TKIPReplays */ + uint32 ccmpfmterr; /* CCMPFormatErrors */ + uint32 ccmpreplay; /* CCMPReplays */ + uint32 ccmpundec; /* CCMPDecryptErrors */ + uint32 fourwayfail; /* FourWayHandshakeFailures */ + uint32 wepundec; /* dot11WEPUndecryptableCount */ + uint32 wepicverr; /* dot11WEPICVErrorCount */ + uint32 decsuccess; /* DecryptSuccessCount */ + uint32 tkipicverr; /* TKIPICVErrorCount */ + uint32 wepexcluded; /* dot11WEPExcludedCount */ + + uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32 psmwds; /* Count PSM watchdogs */ + uint32 phywatchdog; /* Count Phy lockups */ +} wl_cnt_t; + +#define WL_WME_CNT_VERSION 1 /* current version of wl_wme_cnt_t */ + +typedef struct { + uint32 packets; + uint32 bytes; +} wl_traffic_stats_t; + +typedef struct { + uint16 version; /* see definition of WL_CNT_T_VERSION */ + uint16 length; /* length of entire structure */ + + wl_traffic_stats_t tx[AC_COUNT]; /* Packets transmitted */ + wl_traffic_stats_t tx_failed[AC_COUNT]; /* Packets dropped or failed to transmit */ + wl_traffic_stats_t rx[AC_COUNT]; /* Packets received */ + wl_traffic_stats_t rx_failed[AC_COUNT]; /* Packets failed to receive */ + + wl_traffic_stats_t forward[AC_COUNT]; /* Packets forwarded by AP */ + + wl_traffic_stats_t tx_expired[AC_COUNT]; /* packets dropped due to lifetime expiry */ + +} wl_wme_cnt_t; + +#ifdef WLBA + +#define WLC_BA_CNT_VERSION 1 /* current version of wlc_ba_cnt_t */ + +/* block ack related stats */ +typedef struct wlc_ba_cnt { + uint16 version; /* WLC_BA_CNT_VERSION */ + uint16 length; /* length of entire structure */ + + /* transmit stat counters */ + uint32 txpdu; /* pdus sent */ + uint32 txsdu; /* sdus sent */ + uint32 txfc; /* tx side flow controlled packets */ + uint32 txfci; /* tx side flow control initiated */ + uint32 txretrans; /* retransmitted pdus */ + uint32 txbatimer; /* ba resend due to timer */ + uint32 txdrop; /* dropped packets */ + uint32 txaddbareq; /* addba req sent */ + uint32 txaddbaresp; /* addba resp sent */ + uint32 txdelba; /* delba sent */ + uint32 txba; /* ba sent */ + uint32 txbar; /* bar sent */ + uint32 txpad[4]; /* future */ + + /* receive side counters */ + uint32 rxpdu; /* pdus recd */ + uint32 rxqed; /* pdus buffered before sending up */ + uint32 rxdup; /* duplicate pdus */ + uint32 rxnobuf; /* pdus discarded due to no buf */ + uint32 rxaddbareq; /* addba req recd */ + uint32 rxaddbaresp; /* addba resp recd */ + uint32 rxdelba; /* delba recd */ + uint32 rxba; /* ba recd */ + uint32 rxbar; /* bar recd */ + uint32 rxinvba; /* invalid ba recd */ + uint32 rxbaholes; /* ba recd with holes */ + uint32 rxunexp; /* unexpected packets */ + uint32 rxpad[4]; /* future */ +} wlc_ba_cnt_t; +#endif /* WLBA */ + +/* structure for per-tid ampdu control */ +struct ampdu_tid_control { + uint8 tid; /* tid */ + uint8 enable; /* enable/disable */ +}; + +/* structure for addts arguments */ +/* For ioctls that take a list of TSPEC */ +struct tslist { + int count; /* number of tspecs */ + struct tsinfo_arg tsinfo[1]; /* variable length array of tsinfo */ +}; + +/* structure for addts/delts arguments */ +typedef struct tspec_arg { + uint16 version; /* see definition of TSPEC_ARG_VERSION */ + uint16 length; /* length of entire structure */ + uint flag; /* bit field */ + /* TSPEC Arguments */ + struct tsinfo_arg tsinfo; /* TS Info bit field */ + uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ + uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ + uint min_srv_interval; /* Minimum Service Interval (us) */ + uint max_srv_interval; /* Maximum Service Interval (us) */ + uint inactivity_interval; /* Inactivity Interval (us) */ + uint suspension_interval; /* Suspension Interval (us) */ + uint srv_start_time; /* Service Start Time (us) */ + uint min_data_rate; /* Minimum Data Rate (bps) */ + uint mean_data_rate; /* Mean Data Rate (bps) */ + uint peak_data_rate; /* Peak Data Rate (bps) */ + uint max_burst_size; /* Maximum Burst Size (bytes) */ + uint delay_bound; /* Delay Bound (us) */ + uint min_phy_rate; /* Minimum PHY Rate (bps) */ + uint16 surplus_bw; /* Surplus Bandwidth Allowance Factor */ + uint16 medium_time; /* Medium Time (32 us/s periods) */ +} tspec_arg_t; + +/* current version of wl_tspec_arg_t struct */ +#define TSPEC_ARG_VERSION 1 /* current version of wl_tspec_arg_t struct */ +#define TSPEC_ARG_LENGTH 55 /* argment length from tsinfo to medium_time */ + +/* define for flag */ +#define TSPEC_PENDING 0 /* TSPEC pending */ +#define TSPEC_ACCEPTED 1 /* TSPEC accepted */ +#define TSPEC_REJECTED 2 /* TSPEC rejected */ +#define TSPEC_UNKNOWN 3 /* TSPEC unknown */ +#define TSPEC_STATUS_MASK 7 /* TSPEC status mask */ + + +/* Software feature flag defines used by wlfeatureflag */ +#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ +#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ + +#define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ + +/* Packet lifetime configuration per ac */ +typedef struct wl_lifetime { + uint32 ac; /* access class */ + uint32 lifetime; /* Packet lifetime value in ms */ +} wl_lifetime_t; + +#endif /* _wlioctl_h_ */ diff --git a/package/broadcom-wl/src/wlc/include/wlutils.h b/package/broadcom-wl/src/wlc/include/wlutils.h new file mode 100644 index 0000000000..a5aa1fd663 --- /dev/null +++ b/package/broadcom-wl/src/wlc/include/wlutils.h @@ -0,0 +1,102 @@ +/* + * Broadcom wireless network adapter utility functions + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: wlutils.h,v 1.1.1.12 2006/02/27 03:43:20 honor Exp $ + */ + +#ifndef _wlutils_h_ +#define _wlutils_h_ + +#include +#include + +/* + * Pass a wlioctl request to the specified interface. + * @param name interface name + * @param cmd WLC_GET_MAGIC <= cmd < WLC_LAST + * @param buf buffer for passing in and/or receiving data + * @param len length of buf + * @return >= 0 if successful or < 0 otherwise + */ +extern int wl_ioctl(char *name, int cmd, void *buf, int len); + +/* + * Probe the specified interface. + * @param name interface name + * @return >= 0 if a Broadcom wireless device or < 0 otherwise + */ +extern int wl_probe(char *name); + +extern int wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen); +extern int wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen); +/* + * Set/Get named variable. + * @param ifname interface name + * @param iovar variable name + * @param param input param value/buffer + * @param paramlen input param value/buffer length + * @param bufptr io buffer + * @param buflen io buffer length + * @param val val or val pointer for int routines + * @return success == 0, failure != 0 + */ +/* + * set named driver variable to int value + * calling example: wl_iovar_setint(ifname, "arate", rate) +*/ +static inline int +wl_iovar_setint(char *ifname, char *iovar, int val) +{ + return wl_iovar_set(ifname, iovar, &val, sizeof(val)); +} + +/* + * get named driver variable to int value and return error indication + * calling example: wl_iovar_getint(ifname, "arate", &rate) + */ +static inline int +wl_iovar_getint(char *ifname, char *iovar, int *val) +{ + return wl_iovar_get(ifname, iovar, val, sizeof(int)); +} + +/* + * Set/Get named variable indexed by BSS Configuration + * @param ifname interface name + * @param iovar variable name + * @param bssidx bsscfg index + * @param param input param value/buffer + * @param paramlen input param value/buffer length + * @param bufptr io buffer + * @param buflen io buffer length + * @param val val or val pointer for int routines + * @return success == 0, failure != 0 + */ +extern int wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len); +extern int wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen); +/* + * set named & bss indexed driver variable to int value + */ +static inline int +wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val) +{ + return wl_bssiovar_set(ifname, iovar, bssidx, &val, sizeof(int)); +} + +static inline int +wl_bssiovar_getint(char *ifname, char *iovar, int bssidx, int *val) +{ + return wl_bssiovar_get(ifname, iovar, bssidx, val, sizeof(int)); +} + +extern int wl_bssiovar_setint(char *ifname, char *iovar, int bssidx, int val); + +#endif /* _wlutils_h_ */ diff --git a/package/broadcom-wl/src/wlc/ioctl.c b/package/broadcom-wl/src/wlc/ioctl.c new file mode 100644 index 0000000000..6c676c7c9b --- /dev/null +++ b/package/broadcom-wl/src/wlc/ioctl.c @@ -0,0 +1,298 @@ +/* + * Wireless network adapter utilities + * + * Copyright 2006, Broadcom Corporation + * All Rights Reserved. + * + * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY + * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM + * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * + * $Id: wl.c,v 1.1.1.11 2006/02/27 03:43:20 honor Exp $ + */ +#include +#include +#include +#include +#include +#include +#include + +typedef u_int64_t u64; +typedef u_int32_t u32; +typedef u_int16_t u16; +typedef u_int8_t u8; +#include +#include + +#include +#include +#include +#include + +int +wl_ioctl(char *name, int cmd, void *buf, int len) +{ + struct ifreq ifr; + wl_ioctl_t ioc; + int ret = 0; + int s; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return errno; + } + + /* do it */ + ioc.cmd = cmd; + ioc.buf = buf; + ioc.len = len; + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_data = (caddr_t) &ioc; + if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) + + /* cleanup */ + close(s); + return ret; +} + +static inline int +wl_get_dev_type(char *name, void *buf, int len) +{ + int s; + int ret; + struct ifreq ifr; + struct ethtool_drvinfo info; + + /* open socket to kernel */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + return -1; + } + + /* get device type */ + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (caddr_t)&info; + strncpy(ifr.ifr_name, name, IFNAMSIZ); + if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) { + *(char *)buf = '\0'; + } else + strncpy(buf, info.driver, len); + + close(s); + return ret; +} + +int +wl_probe(char *name) +{ + int ret, val; + char buf[3]; + if ((ret = wl_get_dev_type(name, buf, 3)) < 0) + return ret; + /* Check interface */ + if (strncmp(buf, "wl", 2)) + return -1; + if ((ret = wl_ioctl(name, WLC_GET_VERSION, &val, sizeof(val)))) + return ret; + if (val > WLC_IOCTL_VERSION) + return -1; + + return ret; +} + +static int +wl_iovar_getbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen) +{ + int err; + uint namelen; + uint iolen; + + namelen = strlen(iovar) + 1; /* length of iovar name plus null */ + iolen = namelen + paramlen; + + /* check for overflow */ + if (iolen > buflen) + return (BCME_BUFTOOSHORT); + + memcpy(bufptr, iovar, namelen); /* copy iovar name including null */ + memcpy((int8*)bufptr + namelen, param, paramlen); + + err = wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen); + + return (err); +} + +static int +wl_iovar_setbuf(char *ifname, char *iovar, void *param, int paramlen, void *bufptr, int buflen) +{ + uint namelen; + uint iolen; + + namelen = strlen(iovar) + 1; /* length of iovar name plus null */ + iolen = namelen + paramlen; + + /* check for overflow */ + if (iolen > buflen) + return (BCME_BUFTOOSHORT); + + memcpy(bufptr, iovar, namelen); /* copy iovar name including null */ + memcpy((int8*)bufptr + namelen, param, paramlen); + + return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen); +} + +int +wl_iovar_set(char *ifname, char *iovar, void *param, int paramlen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + + return wl_iovar_setbuf(ifname, iovar, param, paramlen, smbuf, sizeof(smbuf)); +} + +int +wl_iovar_get(char *ifname, char *iovar, void *bufptr, int buflen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + int ret; + + /* use the return buffer if it is bigger than what we have on the stack */ + if (buflen > sizeof(smbuf)) { + ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, bufptr, buflen); + } else { + ret = wl_iovar_getbuf(ifname, iovar, NULL, 0, smbuf, sizeof(smbuf)); + if (ret == 0) + memcpy(bufptr, smbuf, buflen); + } + + return ret; +} + + +/* + * format a bsscfg indexed iovar buffer + */ +static int +wl_bssiovar_mkbuf(char *iovar, int bssidx, void *param, int paramlen, void *bufptr, int buflen, + int *plen) +{ + char *prefix = "bsscfg:"; + int8* p; + uint prefixlen; + uint namelen; + uint iolen; + + prefixlen = strlen(prefix); /* length of bsscfg prefix */ + namelen = strlen(iovar) + 1; /* length of iovar name + null */ + iolen = prefixlen + namelen + sizeof(int) + paramlen; + + /* check for overflow */ + if (buflen < 0 || iolen > (uint)buflen) { + *plen = 0; + return BCME_BUFTOOSHORT; + } + + p = (int8*)bufptr; + + /* copy prefix, no null */ + memcpy(p, prefix, prefixlen); + p += prefixlen; + + /* copy iovar name including null */ + memcpy(p, iovar, namelen); + p += namelen; + + /* bss config index as first param */ + memcpy(p, &bssidx, sizeof(int32)); + p += sizeof(int32); + + /* parameter buffer follows */ + if (paramlen) + memcpy(p, param, paramlen); + + *plen = iolen; + return 0; +} + +/* + * set named & bss indexed driver variable to buffer value + */ +static int +wl_bssiovar_setbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr, + int buflen) +{ + int err; + int iolen; + + err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen); + if (err) + return err; + + return wl_ioctl(ifname, WLC_SET_VAR, bufptr, iolen); +} + +/* + * get named & bss indexed driver variable buffer value + */ +static int +wl_bssiovar_getbuf(char *ifname, char *iovar, int bssidx, void *param, int paramlen, void *bufptr, + int buflen) +{ + int err; + int iolen; + + err = wl_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &iolen); + if (err) + return err; + + return wl_ioctl(ifname, WLC_GET_VAR, bufptr, buflen); +} + +/* + * set named & bss indexed driver variable to buffer value + */ +int +wl_bssiovar_set(char *ifname, char *iovar, int bssidx, void *param, int paramlen) +{ + char smbuf[WLC_IOCTL_SMLEN]; + + return wl_bssiovar_setbuf(ifname, iovar, bssidx, param, paramlen, smbuf, sizeof(smbuf)); +} + +/* + * get named & bss indexed driver variable buffer value + */ +int +wl_bssiovar_get(char *ifname, char *iovar, int bssidx, void *outbuf, int len) +{ + char smbuf[WLC_IOCTL_SMLEN]; + int err; + + /* use the return buffer if it is bigger than what we have on the stack */ + if (len > (int)sizeof(smbuf)) { + err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, outbuf, len); + } else { + memset(smbuf, 0, sizeof(smbuf)); + err = wl_bssiovar_getbuf(ifname, iovar, bssidx, NULL, 0, smbuf, sizeof(smbuf)); + if (err == 0) + memcpy(outbuf, smbuf, len); + } + + return err; +} + +void +wl_printlasterror(char *name) +{ + char err_buf[WLC_IOCTL_SMLEN]; + strcpy(err_buf, "bcmerrstr"); + + fprintf(stderr, "Error: "); + if ( wl_ioctl(name, WLC_GET_VAR, err_buf, sizeof (err_buf)) != 0) + fprintf(stderr, "Error getting the Errorstring from driver\n"); + else + fprintf(stderr, err_buf); +} diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c new file mode 100644 index 0000000000..99237c095a --- /dev/null +++ b/package/broadcom-wl/src/wlc/wlc.c @@ -0,0 +1,1138 @@ +/* + * wlc - Broadcom Wireless Driver Control Utility + * + * Copyright (C) 2006 Felix Fietkau + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define VERSION "0.1" +#define BUFSIZE 8192 +#define PTABLE_MAGIC 0xbadc0ded +#define PTABLE_SLT1 1 +#define PTABLE_SLT2 2 +#define PTABLE_ACKW 3 +#define PTABLE_ADHM 4 +#define PTABLE_END 0xffffffff + +/* + * Copy each token in wordlist delimited by space into word + * Taken from Broadcom shutils.h + */ +#define foreach(word, wordlist, next) \ + for (next = &wordlist[strspn(wordlist, " ")], \ + strncpy(word, next, sizeof(word)), \ + word[strcspn(word, " ")] = '\0', \ + word[sizeof(word) - 1] = '\0', \ + next = strchr(next, ' '); \ + strlen(word); \ + next = next ? &next[strspn(next, " ")] : "", \ + strncpy(word, next, sizeof(word)), \ + word[strcspn(word, " ")] = '\0', \ + word[sizeof(word) - 1] = '\0', \ + next = strchr(next, ' ')) + +static char wlbuf[8192]; +static char interface[16] = "wl0"; +static unsigned long ptable[128]; +static unsigned long kmem_offset = 0; +static int vif = 0, debug = 1, fromstdin = 0; + +typedef enum { + NONE = 0x00, + + /* types */ + PARAM_TYPE = 0x00f, + INT = 0x001, + STRING = 0x002, + + /* options */ + PARAM_OPTIONS = 0x0f0, + NOARG = 0x010, + + /* modes */ + PARAM_MODE = 0xf00, + GET = 0x100, + SET = 0x200, +} wlc_param; + +struct wlc_call { + const char *name; + wlc_param param; + int (*handler)(wlc_param param, void *data, void *value); + union { + int num; + char *str; + void *ptr; + } data; + const char *desc; +}; + +/* can't use the system include because of the stupid broadcom header files */ +extern struct ether_addr *ether_aton(const char *asc); +extern char *ether_ntoa(const struct ether_addr *addr); + +/* + * find the starting point of wl.o in memory + * by reading /proc/ksyms + */ +static inline void wlc_get_mem_offset(void) +{ + FILE *f; + char s[64]; + + /* yes, i'm lazy ;) */ + f = popen("grep '\\[wl]' /proc/ksyms | sort", "r"); + if (fgets(s, 64, f) == 0) + return; + + pclose(f); + + s[8] = 0; + kmem_offset = strtoul(s, NULL, 16); + + /* sanity check */ + if (kmem_offset < 0xc0000000) + kmem_offset = 0; +} + + +static int ptable_init(void) +{ + glob_t globbuf; + struct stat statbuf; + int fd; + + if (ptable[0] == PTABLE_MAGIC) + return 0; + + glob("/lib/modules/2.4.*/wl.o", 0, NULL, &globbuf); + + if (globbuf.gl_pathv[0] == NULL) + return -1; + + if ((fd = open(globbuf.gl_pathv[0], O_RDONLY)) < 0) + return -1; + + if (fstat(fd, &statbuf) < 0) + goto failed; + + if (statbuf.st_size <= 512) + goto failed; + + if (lseek(fd, statbuf.st_size - 512, SEEK_SET) < 0) { + perror("lseek"); + goto failed; + } + + if (read(fd, ptable, 512) < 512) + goto failed; + + if (ptable[0] != PTABLE_MAGIC) + goto failed; + + close(fd); + + wlc_get_mem_offset(); + if (kmem_offset == 0) + return -1; + + return 0; + +failed: + close(fd); + + return -1; +} + +static inline unsigned long wlc_kmem_read(unsigned long offset) +{ + int fd; + unsigned long ret; + + if ((fd = open("/dev/kmem", O_RDONLY )) < 0) + return -1; + + lseek(fd, 0x70000000, SEEK_SET); + lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR); + read(fd, &ret, 4); + close(fd); + + return ret; +} + +static inline void wlc_kmem_write(unsigned long offset, unsigned long value) +{ + int fd; + + if ((fd = open("/dev/kmem", O_WRONLY )) < 0) + return; + + lseek(fd, 0x70000000, SEEK_SET); + lseek(fd, (kmem_offset - 0x70000000) + offset, SEEK_CUR); + write(fd, &value, 4); + close(fd); +} + +static int wlc_patcher_getval(unsigned long key, unsigned long *val) +{ + unsigned long *pt = &ptable[1]; + unsigned long tmp; + + if (ptable_init() < 0) { + fprintf(stderr, "Could not load the ptable\n"); + return -1; + } + + while (*pt != PTABLE_END) { + if (*pt == key) { + tmp = wlc_kmem_read(pt[1]); + + if (tmp == pt[2]) + *val = 0xffffffff; + else + *val = tmp; + + return 0; + } + pt += 3; + } + + return -1; +} + +static int wlc_patcher_setval(unsigned long key, unsigned long val) +{ + unsigned long *pt = &ptable[1]; + + if (ptable_init() < 0) { + fprintf(stderr, "Could not load the ptable\n"); + return -1; + } + + if (val != 0xffffffff) + val = (pt[2] & ~(0xffff)) | (val & 0xffff); + + while (*pt != PTABLE_END) { + if (*pt == key) { + if (val == 0xffffffff) /* default */ + val = pt[2]; + + wlc_kmem_write(pt[1], val); + } + pt += 3; + } + + return 0; +} + +static int wlc_slottime(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int ret = 0; + + if ((param & PARAM_MODE) == SET) { + wlc_patcher_setval(PTABLE_SLT1, *val); + wlc_patcher_setval(PTABLE_SLT2, ((*val == -1) ? *val : *val + 510)); + } else if ((param & PARAM_MODE) == GET) { + ret = wlc_patcher_getval(PTABLE_SLT1, (unsigned long *) val); + if (*val != 0xffffffff) + *val &= 0xffff; + } + + return ret; +} + +static int wlc_noack(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int ret = 0; + + if ((param & PARAM_MODE) == SET) { + wlc_patcher_setval(PTABLE_ACKW, ((*val) ? 1 : 0)); + } else if ((param & PARAM_MODE) == GET) { + ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val); + *val &= 0xffff; + *val = (*val ? 1 : 0); + } + + return ret; +} + +static int wlc_ibss_merge(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int ret = 0; + + if ((param & PARAM_MODE) == SET) { + /* overwrite the instruction with 'lui v0,0x0' - fake a return + * status of 0 for wlc_bcn_tsf_later */ + wlc_patcher_setval(PTABLE_ACKW, ((*val) ? -1 : 0x3c020000)); + } else if ((param & PARAM_MODE) == GET) { + ret = wlc_patcher_getval(PTABLE_ACKW, (unsigned long *) val); + *val = ((*val == -1) ? 1 : 0); + } + + return ret; +} + +static int wlc_ioctl(wlc_param param, void *data, void *value) +{ + unsigned int *var = ((unsigned int *) data); + unsigned int ioc = *var; + + if (param & NOARG) { + return wl_ioctl(interface, ioc, NULL, 0); + } + switch(param & PARAM_TYPE) { + case INT: + return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, sizeof(int)); + case STRING: + return wl_ioctl(interface, ((param & SET) ? (ioc) : (ioc >> 16)) & 0xffff, value, BUFSIZE); + } + return 0; +} + +static int wlc_iovar(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + char *iov = *((char **) data); + int ret = 0; + + if (param & SET) { + switch(param & PARAM_TYPE) { + case INT: + ret = wl_iovar_setint(interface, iov, *val); + } + } + if (param & GET) { + switch(param & PARAM_TYPE) { + case INT: + ret = wl_iovar_getint(interface, iov, val); + } + } + + return ret; +} + +static int wlc_bssiovar(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + char *iov = *((char **) data); + int ret = 0; + + if (param & SET) { + switch(param & PARAM_TYPE) { + case INT: + ret = wl_bssiovar_setint(interface, iov, vif, *val); + } + } + if (param & GET) { + switch(param & PARAM_TYPE) { + case INT: + ret = wl_bssiovar_getint(interface, iov, vif, val); + } + } + + return ret; +} + +static int wlc_vif_enabled(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int buf[3]; + int ret = 0; + + sprintf((char *) buf, "bss"); + buf[1] = vif; + if (param & SET) { + buf[2] = (*val ? 1 : 0); + ret = wl_ioctl(interface, WLC_SET_VAR, buf, sizeof(buf)); + } else if (param & GET) { + ret = wl_ioctl(interface, WLC_GET_VAR, buf, sizeof(buf)); + *val = buf[0]; + } + + return ret; +} + +static int wlc_ssid(wlc_param param, void *data, void *value) +{ + int ret = -1, ret2 = -1; + char *dest = (char *) value; + wlc_ssid_t ssid; + + if ((param & PARAM_MODE) == GET) { + ret = wl_bssiovar_get(interface, "ssid", vif, &ssid, sizeof(ssid)); + + if (ret) + /* if we can't get the ssid through the bssiovar, try WLC_GET_SSID */ + ret = wl_ioctl(interface, WLC_GET_SSID, &ssid, sizeof(ssid)); + + if (!ret) { + memcpy(dest, ssid.SSID, ssid.SSID_len); + dest[ssid.SSID_len] = 0; + } + } else if ((param & PARAM_MODE) == SET) { + strncpy(ssid.SSID, value, 32); + ssid.SSID_len = strlen(value); + + if (ssid.SSID_len > 32) + ssid.SSID_len = 32; + + if (vif == 0) { + /* for the main interface, also try the WLC_SET_SSID call */ + ret2 = wl_ioctl(interface, WLC_SET_SSID, &ssid, sizeof(ssid)); + } + + ret = wl_bssiovar_set(interface, "ssid", vif, &ssid, sizeof(ssid)); + ret = (!ret2 ? 0 : ret); + } + + return ret; +} + +static int wlc_int(wlc_param param, void *data, void *value) +{ + int *var = *((int **) data); + int *val = (int *) value; + + if ((param & PARAM_MODE) == SET) { + *var = *val; + } else if ((param & PARAM_MODE) == GET) { + *val = *var; + } + + return 0; +} + +static int wlc_flag(wlc_param param, void *data, void *value) +{ + int *var = *((int **) data); + + *var = 1; + + return 0; +} + +static int wlc_string(wlc_param param, void *data, void *value) +{ + char *var = *((char **) data); + + if ((param & PARAM_MODE) == GET) { + strcpy(value, var); + } + + return 0; +} + +static int wlc_afterburner(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int ret = 0; + + if ((param & PARAM_MODE) == GET) { + ret = wl_iovar_getint(interface, "afterburner", val); + } else { + wl_iovar_setint(interface, "wlfeatureflag", (*val ? 3 : 0)); + ret = wl_iovar_setint(interface, "afterburner", (*val ? 1 : 0)); + wl_iovar_setint(interface, "afterburner_override", *val); + } + + return ret; +} + +static int wlc_maclist(wlc_param param, void *data, void *value) +{ + unsigned int *var = ((unsigned int *) data); + unsigned int ioc = *var; + int limit = (sizeof(wlbuf) - 4) / sizeof(struct ether_addr); + struct maclist *list = (struct maclist *) wlbuf; + char *str = (char *) value; + char astr[30], *p; + struct ether_addr *addr; + int isset = 0; + int ret; + + if ((param & PARAM_MODE) == GET) { + list->count = limit; + ret = wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)); + + if (!ret) + while (list->count) + str += sprintf(str, "%s%s", ((((char *) value) == str) ? "" : " "), ether_ntoa(&list->ea[list->count-- - 1])); + + return ret; + } else { + while (*str && isspace(*str)) + *str++; + + if (*str == '+') { + str++; + + list->count = limit; + if (wl_ioctl(interface, (ioc >> 16) & 0xffff, wlbuf, sizeof(wlbuf)) == 0) + isset = 1; + + while (*str && isspace(*str)) + str++; + } + + if (!isset) + memset(wlbuf, 0, sizeof(wlbuf)); + + foreach(astr, str, p) { + if (list->count >= limit) + break; + + if ((addr = ether_aton(astr)) != NULL) + memcpy(&list->ea[list->count++], addr, sizeof(struct ether_addr)); + } + + return wl_ioctl(interface, ioc & 0xffff, wlbuf, sizeof(wlbuf)); + } +} + +static int wlc_radio(wlc_param param, void *data, void *value) +{ + int *val = (int *) value; + int ret; + + if ((param & PARAM_MODE) == GET) { + ret = wl_ioctl(interface, WLC_GET_RADIO, val, sizeof(int)); + *val = ((*val & 1) ? 0 : 1); + } else { + *val = (1 << 16) | (*val ? 0 : 1); + ret = wl_ioctl(interface, WLC_SET_RADIO, val, sizeof(int)); + } + + return ret; +} + +static int wlc_wsec_key(wlc_param param, void *null, void *value) +{ + wl_wsec_key_t wsec_key; + unsigned char *index = value; + unsigned char *key; + unsigned char *data; + unsigned char hex[3]; + + if ((param & PARAM_MODE) != SET) + return 0; + + memset(&wsec_key, 0, sizeof(wsec_key)); + if (index[0] == '=') { + wsec_key.flags = WL_PRIMARY_KEY; + index++; + } + + if ((index[0] < '1') || (index[0] > '4') || (index[1] != ',')) + return -1; + + key = index + 2; + if (strncmp(key, "d:", 2) == 0) { /* delete key */ + } else if (strncmp(key, "s:", 2) == 0) { /* ascii key */ + key += 2; + wsec_key.len = strlen(key); + + if ((wsec_key.len != 5) && (wsec_key.len != 13)) + return -1; + + strcpy(wsec_key.data, key); + } else { /* hex key */ + wsec_key.len = strlen(key); + if ((wsec_key.len != 10) && (wsec_key.len != 26)) + return -1; + + wsec_key.len /= 2; + data = wsec_key.data; + hex[2] = 0; + do { + hex[0] = *(key++); + hex[1] = *(key++); + *(data++) = (unsigned char) strtoul(hex, NULL, 16); + } while (*key != 0); + } + + return wl_bssiovar_set(interface, "wsec_key", vif, &wsec_key, sizeof(wsec_key)); +} + +static inline int cw2ecw(int cw) +{ + int i; + for (cw++, i = 0; cw; i++) cw >>=1; + return i - 1; +} + +static int wlc_wme_ac(wlc_param param, void *data, void *value) +{ + char *type = *((char **) data); + char *settings = (char *) value; + char cmd[100], *p, *val; + edcf_acparam_t params[AC_COUNT]; + int ret; + int intval; + int cur = -1; + char *buf = wlbuf; + + if ((param & PARAM_MODE) != SET) + return -1; + + memset(params, 0, sizeof(params)); + ret = wl_iovar_get(interface, type, params, sizeof(params)); + memset(buf, 0, BUFSIZE); + strcpy(buf, type); + buf += strlen(buf) + 1; + + foreach(cmd, settings, p) { + val = strchr(cmd, '='); + if (val == NULL) { + if (strcmp(cmd, "be") == 0) + cur = AC_BE; + else if (strcmp(cmd, "bk") == 0) + cur = AC_BK; + else if (strcmp(cmd, "vi") == 0) + cur = AC_VI; + else if (strcmp(cmd, "vo") == 0) + cur = AC_VO; + else + return -1; + + /* just in case */ + params[cur].ACI = (params[cur].ACI & (0x3 << 5)) | (cur << 5); + } else { + *(val++) = 0; + + intval = strtoul(val, NULL, 10); + if (strcmp(cmd, "cwmin") == 0) + params[cur].ECW = (params[cur].ECW & ~(0xf)) | cw2ecw(intval); + else if (strcmp(cmd, "ecwmin") == 0) + params[cur].ECW = (params[cur].ECW & ~(0xf)) | (intval & 0xf); + else if (strcmp(cmd, "cwmax") == 0) + params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | (cw2ecw(intval) << 4); + else if (strcmp(cmd, "ecwmax") == 0) + params[cur].ECW = (params[cur].ECW & ~(0xf << 4)) | ((intval & 0xf) << 4); + else if (strcmp(cmd, "aifsn") == 0) + params[cur].ACI = (params[cur].ACI & ~(0xf)) | (intval & 0xf); + else if (strcmp(cmd, "txop") == 0) + params[cur].TXOP = intval >> 5; + else if (strcmp(cmd, "force") == 0) + params[cur].ACI = (params[cur].ACI & ~(1 << 4)) | ((intval) ? (1 << 4) : 0); + else return -1; + + memcpy(buf, ¶ms[cur], sizeof(edcf_acparam_t)); + wl_ioctl(interface, WLC_SET_VAR, wlbuf, BUFSIZE); + } + } + return ret; +} + +static const struct wlc_call wlc_calls[] = { + { + .name = "version", + .param = STRING|NOARG, + .handler = wlc_string, + .data.str = VERSION, + .desc = "Version of this program" + }, + { + .name = "debug", + .param = INT, + .handler = wlc_int, + .data.ptr = &debug, + .desc = "wlc debug level" + }, + { + .name = "stdin", + .param = NOARG, + .handler = wlc_flag, + .data.ptr = &fromstdin, + .desc = "Accept input from stdin" + }, + { + .name = "up", + .param = NOARG, + .handler = wlc_ioctl, + .data.num = WLC_UP, + .desc = "Bring the interface up" + }, + { + .name = "down", + .param = NOARG, + .handler = wlc_ioctl, + .data.num = WLC_DOWN, + .desc = "Bring the interface down" + }, + { + .name = "radio", + .param = INT, + .handler = wlc_radio, + .desc = "Radio enabled flag" + }, + { + .name = "ap", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_AP << 16) | WLC_SET_AP), + .desc = "Access Point mode" + }, + { + .name = "mssid", + .param = INT, + .handler = wlc_iovar, + .data.str = "mssid", + .desc = "Multi-ssid mode" + }, + { + .name = "apsta", + .param = INT, + .handler = wlc_iovar, + .data.str = "apsta", + .desc = "AP+STA mode" + }, + { + .name = "infra", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_INFRA << 16) | WLC_SET_INFRA), + .desc = "Infrastructure mode" + }, + { + .name = "wet", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_WET << 16) | WLC_SET_WET), + .desc = "Wireless repeater mode", + }, + { + .name = "statimeout", + .param = INT, + .handler = wlc_iovar, + .data.str = "sta_retry_time", + .desc = "STA connection timeout" + }, + { + .name = "country", + .param = STRING, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_COUNTRY << 16) | WLC_SET_COUNTRY), + .desc = "Country code" + }, + { + .name = "channel", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_CHANNEL << 16) | WLC_SET_CHANNEL), + .desc = "Channel", + }, + { + .name = "vif", + .param = INT, + .handler = wlc_int, + .data.ptr = &vif, + .desc = "Current vif index" + }, + { + .name = "enabled", + .param = INT, + .handler = wlc_vif_enabled, + .desc = "vif enabled flag" + }, + { + .name = "ssid", + .param = STRING, + .handler = wlc_ssid, + .desc = "Interface ESSID" + }, + { + .name = "closed", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "closednet", + .desc = "Hidden ESSID flag" + }, + { + .name = "wsec", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "wsec", + .desc = "Security mode flags" + }, + { + .name = "wepkey", + .param = STRING, + .handler = wlc_wsec_key, + .desc = "Set/Remove WEP keys" + }, + { + .name = "wsec_restrict", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "wsec_restrict", + .desc = "Drop unencrypted traffic" + }, + { + .name = "eap_restrict", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "eap_restrict", + .desc = "Only allow 802.1X traffic until 802.1X authorized" + }, + { + .name = "wpa_auth", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "wpa_auth", + .desc = "WPA authentication modes" + }, + { + .name = "ap_isolate", + .param = INT, + .handler = wlc_bssiovar, + .data.str = "ap_isolate", + .desc = "Isolate connected clients" + }, + { + .name = "supplicant", + .param = INT, + .handler = wlc_iovar, + .data.str = "sup_wpa", + .desc = "Built-in WPA supplicant" + }, + { + .name = "maxassoc", + .param = INT, + .handler = wlc_iovar, + .data.str = "maxassoc", + .desc = "Max. number of associated clients", + }, + { + .name = "wme", + .param = INT, + .handler = wlc_iovar, + .data.str = "wme", + .desc = "WME enabled" + }, + { + .name = "wme_ac_ap", + .param = STRING, + .handler = wlc_wme_ac, + .data.str = "wme_ac_ap", + .desc = "Set WME AC options for AP mode", + }, + { + .name = "wme_ac_sta", + .param = STRING, + .handler = wlc_wme_ac, + .data.str = "wme_ac_sta", + .desc = "Set WME AC options for STA mode", + }, + { + .name = "wme_noack", + .param = INT, + .handler = wlc_iovar, + .data.str = "wme_noack", + .desc = "WME ACK disable request", + }, + { + .name = "fragthresh", + .param = INT, + .handler = wlc_iovar, + .data.str = "fragthresh", + .desc = "Fragmentation threshold", + }, + { + .name = "rtsthresh", + .param = INT, + .handler = wlc_iovar, + .data.str = "rtsthresh", + .desc = "RTS threshold" + }, + { + .name = "rxant", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_ANTDIV << 16) | WLC_SET_ANTDIV), + .desc = "Rx antenna selection" + }, + { + .name = "txant", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_TXANT << 16) | WLC_SET_TXANT), + .desc = "Tx antenna selection" + }, + { + .name = "dtim", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_DTIMPRD << 16) | WLC_SET_DTIMPRD), + .desc = "DTIM period", + }, + { + .name = "bcn", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_BCNPRD << 16) | WLC_SET_BCNPRD), + .desc = "Beacon interval" + }, + { + .name = "frameburst", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_FAKEFRAG << 16) | WLC_SET_FAKEFRAG), + .desc = "Framebursting" + }, + { + .name = "monitor", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_MONITOR << 16) | WLC_SET_MONITOR), + .desc = "Monitor mode" + }, + { + .name = "passive", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_PASSIVE << 16) | WLC_SET_PASSIVE), + .desc = "Passive mode" + }, + { + .name = "macfilter", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_MACMODE << 16) | WLC_SET_MACMODE), + .desc = "MAC filter mode (0:disabled, 1:deny, 2:allow)" + }, + { + .name = "maclist", + .param = STRING, + .data.num = ((WLC_GET_MACLIST << 16) | WLC_SET_MACLIST), + .handler = wlc_maclist, + .desc = "MAC filter list" + }, + { + .name = "autowds", + .param = INT, + .handler = wlc_ioctl, + .data.num = ((WLC_GET_LAZYWDS << 16) | WLC_SET_LAZYWDS), + .desc = "Automatic WDS" + }, + { + .name = "wds", + .param = STRING, + .data.num = ((WLC_GET_WDSLIST << 16) | WLC_SET_WDSLIST), + .handler = wlc_maclist, + .desc = "WDS connection list" + }, + { + .name = "wdstimeout", + .param = INT, + .handler = wlc_iovar, + .data.str = "wdstimeout", + .desc = "WDS link detection timeout" + }, + { + .name = "afterburner", + .param = INT, + .handler = wlc_afterburner, + .desc = "Broadcom Afterburner" + }, + { + .name = "slottime", + .param = INT, + .handler = wlc_slottime, + .desc = "Slot time (-1 = auto)" + }, + { + .name = "txack", + .param = INT, + .handler = wlc_noack, + .desc = "Tx ACK enabled flag" + }, + { + .name = "ibss_merge", + .param = INT, + .handler = wlc_ibss_merge, + .desc = "Allow IBSS merge in Ad-Hoc mode" + } +}; +#define wlc_calls_size (sizeof(wlc_calls) / sizeof(struct wlc_call)) + +static void usage(char *cmd) +{ + int i; + fprintf(stderr, "Usage: %s [ ...]\n" + "\n" + "Available commands:\n", cmd); + for (i = 0; i < wlc_calls_size; i++) { + fprintf(stderr, "\t%-16s\t%s\n", wlc_calls[i].name ?: "", wlc_calls[i].desc ?: ""); + } + fprintf(stderr, "\n"); + exit(1); +} + +static int do_command(const struct wlc_call *cmd, char *arg) +{ + static char buf[BUFSIZE]; + int set; + int ret = 0; + char *format, *end; + int intval; + + if (debug >= 10) { + fprintf(stderr, "do_command %-16s\t'%s'\n", cmd->name, arg); + } + + if ((arg == NULL) && ((cmd->param & PARAM_TYPE) != NONE)) { + set = 0; + ret = cmd->handler(cmd->param | GET, (void *) &cmd->data, (void *) buf); + if (ret == 0) { + switch(cmd->param & PARAM_TYPE) { + case INT: + intval = *((int *) buf); + + if (intval > 65535) + format = "0x%08x\n"; + else if (intval > 255) + format = "0x%04x\n"; + else + format = "%d\n"; + + fprintf(stdout, format, intval); + break; + case STRING: + fprintf(stdout, "%s\n", buf); + } + } + } else { /* SET */ + set = 1; + switch(cmd->param & PARAM_TYPE) { + case INT: + intval = strtoul(arg, &end, 10); + if (end && !(*end)) { + memcpy(buf, &intval, sizeof(intval)); + } else { + fprintf(stderr, "%s: Invalid argument\n", cmd->name); + return -1; + } + break; + case STRING: + strncpy(buf, arg, BUFSIZE); + buf[BUFSIZE - 1] = 0; + } + + ret = cmd->handler(cmd->param | SET, (void *) &cmd->data, (void *) buf); + } + + if ((debug > 0) && (ret != 0)) + fprintf(stderr, "Command '%s %s' failed: %d\n", (set == 1 ? "set" : "get"), cmd->name, ret); + + return ret; +} + +static struct wlc_call *find_cmd(char *name) +{ + int found = 0, i = 0; + + while (!found && (i < wlc_calls_size)) { + if (strcmp(name, wlc_calls[i].name) == 0) + found = 1; + else + i++; + } + + return (struct wlc_call *) (found ? &wlc_calls[i] : NULL); +} + +int main(int argc, char **argv) +{ + static char buf[BUFSIZE]; + char *s, *s2; + char *cmd = argv[0]; + struct wlc_call *call; + int ret = 0; + + if (argc < 2) + usage(argv[0]); + + for(interface[2] = '0'; (interface[2] < '3') && (wl_probe(interface) != 0); interface[2]++); + if (interface[2] == '3') { + fprintf(stderr, "No Broadcom wl interface found!\n"); + return -1; + } + + argv++; + argc--; + while ((argc > 0) && (argv[0] != NULL)) { + if ((call = find_cmd(argv[0])) == NULL) { + fprintf(stderr, "Invalid command: %s\n\n", argv[0]); + usage(cmd); + } + if ((argc > 1) && (!(call->param & NOARG))) { + ret = do_command(call, argv[1]); + argv += 2; + argc -= 2; + } else { + ret = do_command(call, NULL); + argv++; + argc--; + } + } + + while (fromstdin && !feof(stdin)) { + *buf = 0; + fgets(buf, BUFSIZE - 1, stdin); + + if (*buf == 0) + continue; + + if ((s = strchr(buf, '\r')) != NULL) + *s = 0; + if ((s = strchr(buf, '\n')) != NULL) + *s = 0; + + s = buf; + while (isspace(*s)) + s++; + + if (!*s) + continue; + + if ((s2 = strchr(buf, ' ')) != NULL) + *(s2++) = 0; + + while (s2 && isspace(*s2)) + s2++; + + if ((call = find_cmd(buf)) == NULL) { + fprintf(stderr, "Invalid command: %s\n", buf); + ret = -1; + } else + ret = do_command(call, ((call->param & NOARG) ? NULL : s2)); + } + + return ret; +} -- cgit v1.2.3