diff options
Diffstat (limited to 'package/broadcom-wl/src')
29 files changed, 7990 insertions, 2577 deletions
diff --git a/package/broadcom-wl/src/driver/Makefile b/package/broadcom-wl/src/driver/Makefile index 0a16bdcec0..c75795a554 100644 --- a/package/broadcom-wl/src/driver/Makefile +++ b/package/broadcom-wl/src/driver/Makefile @@ -23,9 +23,6 @@ obj-m := $(O_TARGET) wl_mod$(MOD_NAME).o: wl_apsta$(MOD_NAME).o perl -ne 's,eth%d,wl%d\x00,g,print' < $< > $@ -wl$(MOD_NAME).o.patch: wl$(MOD_NAME).o - $(OBJDUMP) -d $< | perl patchtable.pl > $@ - -modules: wl$(MOD_NAME).o.patch +modules: wl$(MOD_NAME).o include $(TOPDIR)/Rules.make diff --git a/package/broadcom-wl/src/driver/bcmutils.c b/package/broadcom-wl/src/driver/bcmutils.c index 7592f230ad..88337d60c7 100644 --- a/package/broadcom-wl/src/driver/bcmutils.c +++ b/package/broadcom-wl/src/driver/bcmutils.c @@ -1,730 +1,1590 @@ /* - * Misc useful OS-independent routines. + * Driver O/S-independent utility routines * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, 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 $ + * $Id$ */ #include <typedefs.h> #include <bcmdefs.h> #include <stdarg.h> +#include "bcmutils.h" #include <osl.h> -#include "linux_osl.h" -#include "pktq.h" -#include <bcmutils.h> #include <sbutils.h> #include <bcmnvram.h> #include <bcmendian.h> #include <bcmdevs.h> -#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; -}; +#include "proto/ethernet.h" +#include "proto/vlan.h" +#include "proto/bcmip.h" +#include "proto/bcmtcp.h" +#include "proto/802.1d.h" + +#ifdef BCMPERFSTATS +#include <bcmperf.h> +#endif + +#if 0 +/* nvram vars cache */ +static char *nvram_vars = NULL; +static int vars_len = -1; +#endif /* copy a pkt buffer chain into a buffer */ uint -pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) +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; + 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) +pkttotlen (osl_t * osh, void *p) { - uint total; + uint total; - total = 0; - for (; p; p = PKTNEXT(osh, p)) - total += PKTLEN(osh, p); - return (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) +pktlast (osl_t * osh, void *p) { - for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) - ; + for (; PKTNEXT (osh, p); p = PKTNEXT (osh, p)) + ; - return (p); + return (p); } /* * osl multiple-precedence packet queue - * hi_prec is always >= the number of the highest non-empty queue + * hi_prec is always >= the number of the highest non-empty precedence */ void * -pktq_penq(struct pktq *pq, int prec, void *p) +pktq_penq (struct pktq *pq, int prec, void *p) { - struct pktq_prec *q; + struct pktq_prec *q; - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + ASSERT (prec >= 0 && prec < pq->num_prec); + ASSERT (PKTLINK (p) == NULL); /* queueing chains not allowed */ - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT (!pktq_full (pq)); + ASSERT (!pktq_pfull (pq, prec)); - q = &pq->q[prec]; + q = &pq->q[prec]; - if (q->head) - PKTSETLINK(q->tail, p); - else - q->head = p; + if (q->head) + PKTSETLINK (q->tail, p); + else + q->head = p; - q->tail = p; - q->len++; + q->tail = p; + q->len++; - pq->len++; + pq->len++; - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; + if (pq->hi_prec < prec) + pq->hi_prec = (uint8) prec; - return p; + return p; } void * -pktq_penq_head(struct pktq *pq, int prec, void *p) +pktq_penq_head (struct pktq *pq, int prec, void *p) { - struct pktq_prec *q; + struct pktq_prec *q; - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ + ASSERT (prec >= 0 && prec < pq->num_prec); + ASSERT (PKTLINK (p) == NULL); /* queueing chains not allowed */ - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT (!pktq_full (pq)); + ASSERT (!pktq_pfull (pq, prec)); - q = &pq->q[prec]; + q = &pq->q[prec]; - if (q->head == NULL) - q->tail = p; + if (q->head == NULL) + q->tail = p; - PKTSETLINK(p, q->head); - q->head = p; - q->len++; + PKTSETLINK (p, q->head); + q->head = p; + q->len++; - pq->len++; + pq->len++; - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; + if (pq->hi_prec < prec) + pq->hi_prec = (uint8) prec; - return p; + return p; } void * -pktq_pdeq(struct pktq *pq, int prec) +pktq_pdeq (struct pktq *pq, int prec) { - struct pktq_prec *q; - void *p; + struct pktq_prec *q; + void *p; - ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT (prec >= 0 && prec < pq->num_prec); - q = &pq->q[prec]; + q = &pq->q[prec]; - if ((p = q->head) == NULL) - return NULL; + if ((p = q->head) == NULL) + return NULL; - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; + if ((q->head = PKTLINK (p)) == NULL) + q->tail = NULL; - q->len--; + q->len--; - pq->len--; + pq->len--; - PKTSETLINK(p, NULL); + PKTSETLINK (p, NULL); - return p; + return p; } void * -pktq_pdeq_tail(struct pktq *pq, int prec) +pktq_pdeq_tail (struct pktq *pq, int prec) { - struct pktq_prec *q; - void *p, *prev; + struct pktq_prec *q; + void *p, *prev; - ASSERT(prec >= 0 && prec < pq->num_prec); + ASSERT (prec >= 0 && prec < pq->num_prec); - q = &pq->q[prec]; + q = &pq->q[prec]; - if ((p = q->head) == NULL) - return NULL; + if ((p = q->head) == NULL) + return NULL; - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; + for (prev = NULL; p != q->tail; p = PKTLINK (p)) + prev = p; - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; + if (prev) + PKTSETLINK (prev, NULL); + else + q->head = NULL; - q->tail = prev; - q->len--; + q->tail = prev; + q->len--; - pq->len--; + pq->len--; - return p; + 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; +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; } +#if 0 bool -pktq_pdel(struct pktq *pq, void *pktbuf, int prec) +pktq_pdel (struct pktq *pq, void *pktbuf, int prec) { - struct pktq_prec *q; - void *p; - - ASSERT(prec >= 0 && prec < pq->num_prec); + struct pktq_prec *q; + void *p; - if (!pktbuf) - return FALSE; + ASSERT (prec >= 0 && prec < pq->num_prec); - q = &pq->q[prec]; + if (!pktbuf) + return FALSE; - 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; + q = &pq->q[prec]; - PKTSETLINK(p, PKTLINK(pktbuf)); - if (q->tail == pktbuf) - q->tail = p; - } + 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; + q->len--; + pq->len--; + PKTSETLINK (pktbuf, NULL); + return TRUE; } +#endif void -pktq_init(struct pktq *pq, int num_prec, int max_len) +pktq_init (struct pktq *pq, int num_prec, int max_len) { - int prec; + int prec; - ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); + ASSERT (num_prec > 0 && num_prec <= PKTQ_MAX_PREC); - bzero(pq, sizeof(*pq)); + /* pq is variable size; only zero out what's requested */ + bzero (pq, + OFFSETOF (struct pktq, q) + (sizeof (struct pktq_prec) * num_prec)); - pq->num_prec = (uint16)num_prec; + pq->num_prec = (uint16) num_prec; - pq->max = (uint16)max_len; + pq->max = (uint16) max_len; - for (prec = 0; prec < num_prec; prec++) - pq->q[prec].max = pq->max; + for (prec = 0; prec < num_prec; prec++) + pq->q[prec].max = pq->max; +} + +int +pktq_setmax (struct pktq *pq, int max_len) +{ + int prec; + + if (!max_len) + return pq->max; + + pq->max = (uint16) max_len; + for (prec = 0; prec < pq->num_prec; prec++) + pq->q[prec].max = pq->max; + + return pq->max; } void * -pktq_deq(struct pktq *pq, int *prec_out) +pktq_deq (struct pktq *pq, int *prec_out) { - struct pktq_prec *q; - void *p; - int prec; + struct pktq_prec *q; + void *p; + int prec; - if (pq->len == 0) - return NULL; + if (pq->len == 0) + return NULL; - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; + while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) + pq->hi_prec--; - q = &pq->q[prec]; + q = &pq->q[prec]; - if ((p = q->head) == NULL) - return NULL; + if ((p = q->head) == NULL) + return NULL; - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; + if ((q->head = PKTLINK (p)) == NULL) + q->tail = NULL; - q->len--; + q->len--; - pq->len--; + pq->len--; - if (prec_out) - *prec_out = prec; + if (prec_out) + *prec_out = prec; - PKTSETLINK(p, NULL); + PKTSETLINK (p, NULL); - return p; + return p; } void * -pktq_deq_tail(struct pktq *pq, int *prec_out) +pktq_deq_tail (struct pktq *pq, int *prec_out) { - struct pktq_prec *q; - void *p, *prev; - int prec; + struct pktq_prec *q; + void *p, *prev; + int prec; - if (pq->len == 0) - return NULL; + if (pq->len == 0) + return NULL; - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; - q = &pq->q[prec]; + q = &pq->q[prec]; - if ((p = q->head) == NULL) - return NULL; + if ((p = q->head) == NULL) + return NULL; - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; + for (prev = NULL; p != q->tail; p = PKTLINK (p)) + prev = p; - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; + if (prev) + PKTSETLINK (prev, NULL); + else + q->head = NULL; - q->tail = prev; - q->len--; + q->tail = prev; + q->len--; - pq->len--; + pq->len--; - if (prec_out) - *prec_out = prec; + if (prec_out) + *prec_out = prec; - PKTSETLINK(p, NULL); + PKTSETLINK (p, NULL); - return p; + return p; } +#if 0 void * -pktq_peek(struct pktq *pq, int *prec_out) +pktq_peek (struct pktq *pq, int *prec_out) { - int prec; + int prec; - if (pq->len == 0) - return NULL; + if (pq->len == 0) + return NULL; - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; + while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) + pq->hi_prec--; - if (prec_out) - *prec_out = prec; + if (prec_out) + *prec_out = prec; - return (pq->q[prec].head); + return (pq->q[prec].head); } +#endif void * -pktq_peek_tail(struct pktq *pq, int *prec_out) +pktq_peek_tail (struct pktq *pq, int *prec_out) { - int prec; + int prec; - if (pq->len == 0) - return NULL; + if (pq->len == 0) + return NULL; - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; - if (prec_out) - *prec_out = prec; + if (prec_out) + *prec_out = prec; - return (pq->q[prec].tail); + return (pq->q[prec].tail); } void -pktq_flush(osl_t *osh, struct pktq *pq, bool dir) +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); + 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) +pktq_mlen (struct pktq *pq, uint prec_bmp) { - int prec, len; + int prec, len; - len = 0; + len = 0; - for (prec = 0; prec <= pq->hi_prec; prec++) - if (prec_bmp & (1 << prec)) - len += pq->q[prec].len; + for (prec = 0; prec <= pq->hi_prec; prec++) + if (prec_bmp & (1 << prec)) + len += pq->q[prec].len; - return len; + return len; } /* Priority dequeue from a specific set of precedences */ void * -pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) +pktq_mdeq (struct pktq *pq, uint prec_bmp, int *prec_out) { - struct pktq_prec *q; - void *p; - int prec; + struct pktq_prec *q; + void *p; + int prec; - if (pq->len == 0) - return NULL; + if (pq->len == 0) + return NULL; - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; + 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; + while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) + if (prec-- == 0) + return NULL; - q = &pq->q[prec]; + q = &pq->q[prec]; - if ((p = q->head) == NULL) - return NULL; + if ((p = q->head) == NULL) + return NULL; - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; + if ((q->head = PKTLINK (p)) == NULL) + q->tail = NULL; - q->len--; + q->len--; - if (prec_out) - *prec_out = prec; + if (prec_out) + *prec_out = prec; - pq->len--; + pq->len--; - PKTSETLINK(p, NULL); + PKTSETLINK (p, NULL); - return p; + return p; } -char* -bcmstrcat(char *dest, const char *src) +const unsigned char bcm_ctype[] = { + _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, /* 0-7 */ + _BCM_C, _BCM_C | _BCM_S, _BCM_C | _BCM_S, _BCM_C | _BCM_S, _BCM_C | _BCM_S, + _BCM_C | _BCM_S, _BCM_C, + _BCM_C, /* 8-15 */ + _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, /* 16-23 */ + _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, _BCM_C, /* 24-31 */ + _BCM_S | _BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 32-39 */ + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 40-47 */ + _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, _BCM_D, /* 48-55 */ + _BCM_D, _BCM_D, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 56-63 */ + _BCM_P, _BCM_U | _BCM_X, _BCM_U | _BCM_X, _BCM_U | _BCM_X, _BCM_U | _BCM_X, + _BCM_U | _BCM_X, + _BCM_U | _BCM_X, _BCM_U, /* 64-71 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 72-79 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 80-87 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 88-95 */ + _BCM_P, _BCM_L | _BCM_X, _BCM_L | _BCM_X, _BCM_L | _BCM_X, _BCM_L | _BCM_X, + _BCM_L | _BCM_X, + _BCM_L | _BCM_X, _BCM_L, /* 96-103 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 104-111 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 112-119 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_C, /* 120-127 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ + _BCM_S | _BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, + _BCM_P, _BCM_P, + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, + _BCM_P, _BCM_P, + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, + _BCM_U, _BCM_U, + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, + _BCM_U, _BCM_U, + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, + _BCM_L, _BCM_L, + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, + _BCM_L, _BCM_L, + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ +}; + +ulong BCMROMFN (bcm_strtoul) (char *cp, char **endp, uint base) { - strcpy(&dest[strlen(dest)], src); - return (dest); + ulong result, value; + bool minus; + + minus = FALSE; + + while (bcm_isspace (*cp)) + cp++; + + if (cp[0] == '+') + cp++; + else if (cp[0] == '-') + { + minus = TRUE; + cp++; + } + + if (base == 0) + { + if (cp[0] == '0') + { + if ((cp[1] == 'x') || (cp[1] == 'X')) + { + base = 16; + cp = &cp[2]; + } + else + { + base = 8; + cp = &cp[1]; + } + } + else + base = 10; + } + else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) + { + cp = &cp[2]; + } + + result = 0; + + while (bcm_isxdigit (*cp) && + (value = + bcm_isdigit (*cp) ? *cp - '0' : bcm_toupper (*cp) - 'A' + 10) < + base) + { + result = result * base + value; + cp++; + } + + if (minus) + result = (ulong) (result * -1); + + if (endp) + *endp = (char *) cp; + + return (result); } -char* -bcm_ether_ntoa(struct ether_addr *ea, char *buf) +#if 0 +int BCMROMFN (bcm_atoi) (char *s) { - 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); + return (int) bcm_strtoul (s, NULL, 10); } +/* return pointer to location of substring 'needle' in 'haystack' */ +char *BCMROMFN (bcmstrstr) (char *haystack, char *needle) +{ + int len, nlen; + int i; + + if ((haystack == NULL) || (needle == NULL)) + return (haystack); + + nlen = strlen (needle); + len = strlen (haystack) - nlen + 1; + + for (i = 0; i < len; i++) + if (memcmp (needle, &haystack[i], nlen) == 0) + return (&haystack[i]); + return (NULL); +} + +char *BCMROMFN (bcmstrcat) (char *dest, const char *src) +{ + strcpy (&dest[strlen (dest)], src); + return (dest); +} + +char *BCMROMFN (bcmstrncat) (char *dest, const char *src, uint size) +{ + char *endp; + char *p; + + p = dest + strlen (dest); + endp = p + size; + + while (p != endp && (*p++ = *src++) != '\0') + ; + + return (dest); +} +#endif + /* parse a xx:xx:xx:xx:xx:xx format ethernet address */ +int BCMROMFN (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); +} + +#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) +/* registry routine buffer preparation utility functions: + * parameter order is like strncpy, but returns count + * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) + */ +ulong +wchar2ascii (char *abuf, ushort * wbuf, ushort wbuflen, ulong abuflen) +{ + ulong copyct = 1; + ushort i; + + if (abuflen == 0) + return 0; + + /* wbuflen is in bytes */ + wbuflen /= sizeof (ushort); + + for (i = 0; i < wbuflen; ++i) + { + if (--abuflen == 0) + break; + *abuf++ = (char) *wbuf++; + ++copyct; + } + *abuf = '\0'; + + return copyct; +} +#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ + +#if 0 +char * +bcm_ether_ntoa (struct ether_addr *ea, char *buf) +{ + snprintf (buf, 18, "%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); +} + +char * +bcm_ip_ntoa (struct ipv4_addr *ia, char *buf) +{ + snprintf (buf, 16, "%d.%d.%d.%d", + ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); + return (buf); +} +void +bcm_mdelay (uint ms) +{ + uint i; + + for (i = 0; i < ms; i++) + { + OSL_DELAY (1000); + } +} +#endif + +#if 0 + +/* + * Search the name=value vars for a specific one and return its value. + * Returns NULL if not found. + */ +char * +getvar (char *vars, const char *name) +{ +#ifdef _MINOSL_ + return NULL; +#else + char *s; + int len; + + if (!name) + return NULL; + + len = strlen (name); + if (len == 0) + return NULL; + + /* first look in vars[] */ + for (s = vars; s && *s;) + { + /* CSTYLED */ + if ((bcmp (s, name, len) == 0) && (s[len] == '=')) + return (&s[len + 1]); + + while (*s++) + ; + } + + /* then query nvram */ + return (nvram_get (name)); +#endif /* _MINOSL_ */ +} + +/* + * Search the vars for a specific one and return its value as + * an integer. Returns 0 if not found. + */ int -bcm_ether_atoe(char *p, struct ether_addr *ea) +getintvar (char *vars, const char *name) +{ +#ifdef _MINOSL_ + return 0; +#else + char *val; + + if ((val = getvar (vars, name)) == NULL) + return (0); + + return (bcm_strtoul (val, NULL, 0)); +#endif /* _MINOSL_ */ +} + + +/* Search for token in comma separated token-string */ +static int +findmatch (char *string, char *name) { - int i = 0; + uint len; + char *c; + + len = strlen (name); + /* CSTYLED */ + while ((c = strchr (string, ',')) != NULL) + { + if (len == (uint) (c - string) && !strncmp (string, name, len)) + return 1; + string = c + 1; + } + + return (!strcmp (string, name)); +} - for (;;) { - ea->octet[i++] = (char) bcm_strtoul(p, &p, 16); - if (!*p++ || i == 6) - break; +/* Return gpio pin number assigned to the named pin + * + * Variable should be in format: + * + * gpio<N>=pin_name,pin_name + * + * This format allows multiple features to share the gpio with mutual + * understanding. + * + * 'def_pin' is returned if a specific gpio is not defined for the requested functionality + * and if def_pin is not used by others. + */ +uint +getgpiopin (char *vars, char *pin_name, uint def_pin) +{ + char name[] = "gpioXXXX"; + char *val; + uint pin; + + /* Go thru all possibilities till a match in pin name */ + for (pin = 0; pin < GPIO_NUMPINS; pin++) + { + snprintf (name, sizeof (name), "gpio%d", pin); + val = getvar (vars, name); + if (val && findmatch (val, pin_name)) + return pin; + } + + if (def_pin != GPIO_PIN_NOTDEFINED) + { + /* make sure the default pin is not used by someone else */ + snprintf (name, sizeof (name), "gpio%d", def_pin); + if (getvar (vars, name)) + { + def_pin = GPIO_PIN_NOTDEFINED; } + } + + return def_pin; +} +#endif + +#ifdef BCMPERFSTATS - return (i == 6); +#define LOGSIZE 256 /* should be power of 2 to avoid div below */ +static struct +{ + uint cycles; + char *fmt; + uint a1; + uint a2; +} logtab[LOGSIZE]; + +/* last entry logged */ +static uint logi = 0; +/* next entry to read */ +static uint readi = 0; + +void +bcm_perf_enable () +{ + BCMPERF_ENABLE_INSTRCOUNT (); + BCMPERF_ENABLE_ICACHE_MISS (); + BCMPERF_ENABLE_ICACHE_HIT (); } -/* Takes an Ethernet frame and sets out-of-bound PKTPRIO - * Also updates the inplace vlan tag if requested +void +bcmlog (char *fmt, uint a1, uint a2) +{ + static uint last = 0; + uint cycles, i; + OSL_GETCYCLES (cycles); + + i = logi; + + logtab[i].cycles = cycles - last; + logtab[i].fmt = fmt; + logtab[i].a1 = a1; + logtab[i].a2 = a2; + + logi = (i + 1) % LOGSIZE; + last = cycles; +} + + +void +bcmstats (char *fmt) +{ + static uint last = 0; + static uint32 ic_miss = 0; + static uint32 instr_count = 0; + uint32 ic_miss_cur; + uint32 instr_count_cur; + uint cycles, i; + + OSL_GETCYCLES (cycles); + BCMPERF_GETICACHE_MISS (ic_miss_cur); + BCMPERF_GETINSTRCOUNT (instr_count_cur); + + i = logi; + + logtab[i].cycles = cycles - last; + logtab[i].a1 = ic_miss_cur - ic_miss; + logtab[i].a2 = instr_count_cur - instr_count; + logtab[i].fmt = fmt; + + logi = (i + 1) % LOGSIZE; + + last = cycles; + instr_count = instr_count_cur; + ic_miss = ic_miss_cur; +} + + +void +bcmdumplog (char *buf, int size) +{ + char *limit, *line; + int j = 0; + int num; + + limit = buf + size - 80; + *buf = '\0'; + + num = logi - readi; + + if (num < 0) + num += LOGSIZE; + + /* print in chronological order */ + + for (j = 0; j < num && (buf < limit); readi = (readi + 1) % LOGSIZE, j++) + { + if (logtab[readi].fmt == NULL) + continue; + line = buf; + buf += sprintf (buf, "%d\t", logtab[readi].cycles); + buf += + sprintf (buf, logtab[readi].fmt, logtab[readi].a1, logtab[readi].a2); + buf += sprintf (buf, "\n"); + } + +} + + +/* + * Dump one log entry at a time. + * Return index of next entry or -1 when no more . */ +int +bcmdumplogent (char *buf, uint i) +{ + bool hit; + + /* + * If buf is NULL, return the starting index, + * interpreting i as the indicator of last 'i' entries to dump. + */ + if (buf == NULL) + { + i = ((i > 0) && (i < (LOGSIZE - 1))) ? i : (LOGSIZE - 1); + return ((logi - i) % LOGSIZE); + } + + *buf = '\0'; + + ASSERT (i < LOGSIZE); + + if (i == logi) + return (-1); + + hit = FALSE; + for (; (i != logi) && !hit; i = (i + 1) % LOGSIZE) + { + if (logtab[i].fmt == NULL) + continue; + buf += sprintf (buf, "%d: %d\t", i, logtab[i].cycles); + buf += sprintf (buf, logtab[i].fmt, logtab[i].a1, logtab[i].a2); + buf += sprintf (buf, "\n"); + hit = TRUE; + } + + return (i); +} + +#endif /* BCMPERFSTATS */ + +#ifdef BCMDBG +/* pretty hex print a pkt buffer chain */ void -pktsetprio(void *pkt, bool update_vtag) +prpkt (const char *msg, osl_t * osh, void *p0) { - struct ether_header *eh; - struct ethervlan_header *evh; - uint8 *pktdata; - int priority = 0; + void *p; - pktdata = (uint8 *) PKTDATA(NULL, pkt); - ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); + if (msg && (msg[0] != '\0')) + printf ("%s:\n", msg); - eh = (struct ether_header *) pktdata; + for (p = p0; p; p = PKTNEXT (osh, p)) + prhex (NULL, PKTDATA (osh, p), PKTLEN (osh, p)); +} +#endif /* BCMDBG */ - if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { - uint16 vlan_tag; - int vlan_prio, dscp_prio = 0; +/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. + * Also updates the inplace vlan tag if requested. + * For debugging, it returns an indication of what it did. + */ +uint +pktsetprio (void *pkt, bool update_vtag) +{ + struct ether_header *eh; + struct ethervlan_header *evh; + uint8 *pktdata; + int priority = 0; + int rc = 0; - evh = (struct ethervlan_header *)eh; + pktdata = (uint8 *) PKTDATA (NULL, pkt); + ASSERT (ISALIGNED ((uintptr) pktdata, sizeof (uint16))); - vlan_tag = ntoh16(evh->vlan_tag); - vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; + eh = (struct ether_header *) pktdata; - 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); - } + if (ntoh16 (eh->ether_type) == ETHER_TYPE_8021Q) + { + uint16 vlan_tag; + int vlan_prio, dscp_prio = 0; + + evh = (struct ethervlan_header *) eh; - /* 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); + 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); + if ((IP_VER (ip_body) == IP_VER_4) + && (IPV4_PROT (ip_body) == IP_PROT_TCP)) + { + int ip_len; + int src_port; + bool src_port_exc; + uint8 *tcp_hdr; + + ip_len = IPV4_PAYLOAD_LEN (ip_body); + tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD (ip_body); + src_port = TCP_SRC_PORT (tcp_hdr); + src_port_exc = (src_port == 10110) || (src_port == 10120) || + (src_port == 10130) || (src_port == 10140); + + if ((ip_len == 40) && src_port_exc && TCP_IS_ACK (tcp_hdr)) + { + dscp_prio = 7; } - } 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); + /* DSCP priority gets precedence over 802.1P (vlan tag) */ + if (dscp_prio != 0) + { + priority = dscp_prio; + rc |= PKTPRIO_VDSCP; + } + else + { + priority = vlan_prio; + rc |= PKTPRIO_VLAN; + } + /* + * 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); + rc |= PKTPRIO_UPD; + } + } + 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); + rc |= PKTPRIO_DSCP; + if ((IP_VER (ip_body) == IP_VER_4) + && (IPV4_PROT (ip_body) == IP_PROT_TCP)) + { + int ip_len; + int src_port; + bool src_port_exc; + uint8 *tcp_hdr; + + ip_len = IPV4_PAYLOAD_LEN (ip_body); + tcp_hdr = IPV4_NO_OPTIONS_PAYLOAD (ip_body); + src_port = TCP_SRC_PORT (tcp_hdr); + src_port_exc = (src_port == 10110) || (src_port == 10120) || + (src_port == 10130) || (src_port == 10140); + + if ((ip_len == 40) && src_port_exc && TCP_IS_ACK (tcp_hdr)) + { + priority = 7; + } + } + } + + ASSERT (priority >= 0 && priority <= MAXPRIO); + PKTSETPRIO (pkt, priority); + return (rc | priority); } static char bcm_undeferrstr[BCME_STRLEN]; static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; -/* Convert the Error codes into related Error strings */ +/* Convert the error codes into related error strings */ const char * -bcmerrorstr(int bcmerror) +bcmerrorstr (int bcmerror) +{ + /* check if someone added a bcmerror code but forgot to add errorstring */ + ASSERT (ABS (BCME_LAST) == (ARRAYSIZE (bcmerrorstrtable) - 1)); + + if (bcmerror > 0 || bcmerror < BCME_LAST) + { + snprintf (bcm_undeferrstr, BCME_STRLEN, "Undefined error %d", bcmerror); + return bcm_undeferrstr; + } + + ASSERT (strlen (bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); + + return bcmerrorstrtable[-bcmerror]; +} + +#if 0 +static void BCMINITFN (bcm_nvram_refresh) (char *flash) { - int abs_bcmerror; + int i; + int ret = 0; + + ASSERT (flash); + + /* default "empty" vars cache */ + bzero (flash, 2); + + if ((ret = nvram_getall (flash, NVRAM_SPACE))) + return; + + /* determine nvram length */ + for (i = 0; i < NVRAM_SPACE; i++) + { + if (flash[i] == '\0' && flash[i + 1] == '\0') + break; + } - abs_bcmerror = ABS(bcmerror); + if (i > 1) + vars_len = i + 2; + else + vars_len = 0; +} +#endif + +#ifdef BCMDBG_PKT /* pkt logging for debugging */ +/* Add a packet to the pktlist */ +void +pktlist_add (pktlist_info_t * pktlist, void *pkt) +{ + uint i; + ASSERT (pktlist->count < PKTLIST_SIZE); + + /* Verify the packet is not already part of the list */ + for (i = 0; i < pktlist->count; i++) + { + if (pktlist->list[i] == pkt) + ASSERT (0); + } + pktlist->list[pktlist->count] = pkt; + pktlist->count++; + return; +} - /* 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; +/* Remove a packet from the pktlist */ +void +pktlist_remove (pktlist_info_t * pktlist, void *pkt) +{ + uint i; + uint num = pktlist->count; + + /* find the index where pkt exists */ + for (i = 0; i < num; i++) + { + /* check for the existence of pkt in the list */ + if (pktlist->list[i] == pkt) + { + /* replace with the last element */ + pktlist->list[i] = pktlist->list[num - 1]; + pktlist->count--; + return; } + } + ASSERT (0); +} + +/* Dump the pktlist (and the contents of each packet if 'data' + * is set). 'buf' should be large enough + */ + +char * +pktlist_dump (pktlist_info_t * pktlist, char *buf) +{ + char *obuf; + uint i; + + obuf = buf; + + buf += sprintf (buf, "Packet list dump:\n"); - ASSERT((strlen((char*)bcmerrorstrtable[abs_bcmerror])) < BCME_STRLEN); + for (i = 0; i < (pktlist->count); i++) + { + buf += sprintf (buf, "0x%p\t", pktlist->list[i]); - return bcmerrorstrtable[abs_bcmerror]; +#ifdef NOTDEF /* Remove this ifdef to print pkttag and pktdata */ + if (PKTTAG (pktlist->list[i])) + { + /* Print pkttag */ + buf += sprintf (buf, "Pkttag(in hex): "); + buf += + bcm_format_hex (buf, PKTTAG (pktlist->list[i]), OSL_PKTTAG_SZ); + } + buf += sprintf (buf, "Pktdata(in hex): "); + buf += bcm_format_hex (buf, PKTDATA (NULL, pktlist->list[i]), + PKTLEN (NULL, pktlist->list[i])); +#endif /* NOTDEF */ + + buf += sprintf (buf, "\n"); + } + return obuf; } +#endif /* BCMDBG_PKT */ +#if 0 +/* iovar table lookup */ +const bcm_iovar_t * +bcm_iovar_lookup (const bcm_iovar_t * table, const char *name) +{ + const bcm_iovar_t *vi; + const char *lookup_name; + + /* skip any ':' delimited option prefixes */ + lookup_name = strrchr (name, ':'); + if (lookup_name != NULL) + lookup_name++; + else + lookup_name = name; + + ASSERT (table); + + for (vi = table; vi->name; vi++) + { + if (!strcmp (vi->name, lookup_name)) + return vi; + } + /* ran to end of table */ + + return NULL; /* var name not found */ +} +#endif 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; +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; + case IOVT_BUFFER: + /* buffer must meet minimum length requirement */ + if (len < vi->minlen) + { + bcmerror = BCME_BUFTOOSHORT; + } + break; - default: - /* unknown type for length check in iovar info */ - ASSERT(0); - bcmerror = BCME_UNSUPPORTED; + 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; + 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 + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] + +#if 0 +/******************************************************************************* + * crc8 + * + * Computes a crc8 over the input data using the polynomial: + * + * x^8 + x^7 +x^6 + x^4 + x^2 + 1 + * + * The caller provides the initial value (either CRC8_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC8_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ + +static const uint8 crc8_table[256] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F }; -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 BCMROMFN (hndcrc8) (uint8 * pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint8 crc /* either CRC8_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]); - } + /* hard code the crc loop instead of using CRC_INNER_LOOP macro + * to avoid the undefined and unnecessary (uint8 >> 8) operation. + */ + while (nbytes-- > 0) + crc = crc8_table[(crc ^ *pdata++) & 0xff]; + + return crc; +} - /* 1-3 bytes at end of buffer */ - pend = pdata + (nbytes & 0x03); - while (pdata < pend) - CRC_INNER_LOOP(32, crc, *pdata++); +/******************************************************************************* + * crc16 + * + * Computes a crc16 over the input data using the polynomial: + * + * x^16 + x^12 +x^5 + 1 + * + * The caller provides the initial value (either CRC16_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC16_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ +static const uint16 crc16_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; + +uint16 BCMROMFN (hndcrc16) (uint8 * pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint16 crc /* either CRC16_INIT_VALUE or previous return value */ + ) +{ + while (nbytes-- > 0) + CRC_INNER_LOOP (16, crc, *pdata++); + return crc; +} +#endif + +static const 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 BCMROMFN (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++); + pend = pdata + nbytes; + while (pdata < pend) + CRC_INNER_LOOP (32, crc, *pdata++); #endif /* __mips__ */ - return crc; + return crc; } +#ifdef notdef +#define CLEN 1499 /* CRC Length */ +#define CBUFSIZ (CLEN+4) +#define CNBUFS 5 /* # of bufs */ + +void +testcrc32 (void) +{ + uint j, k, l; + uint8 *buf; + uint len[CNBUFS]; + uint32 crcr; + uint32 crc32tv[CNBUFS] = + { 0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110 }; + + ASSERT ((buf = MALLOC (CBUFSIZ * CNBUFS)) != NULL); + + /* step through all possible alignments */ + for (l = 0; l <= 4; l++) + { + for (j = 0; j < CNBUFS; j++) + { + len[j] = CLEN; + for (k = 0; k < len[j]; k++) + *(buf + j * CBUFSIZ + (k + l)) = (j + k) & 0xff; + } + + for (j = 0; j < CNBUFS; j++) + { + crcr = crc32 (buf + j * CBUFSIZ + l, len[j], CRC32_INIT_VALUE); + ASSERT (crcr == crc32tv[j]); + } + } + + MFREE (buf, CBUFSIZ * CNBUFS); + return; +} +#endif /* notdef */ /* * Advance from the current 1-byte tag/1-byte length/variable-length value @@ -732,27 +1592,26 @@ hndcrc32( * 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. + * by the TLV parameter's length if it is valid. */ -bcm_tlv_t * -bcm_next_tlv(bcm_tlv_t *elt, int *buflen) +bcm_tlv_t *BCMROMFN (bcm_next_tlv) (bcm_tlv_t * elt, int *buflen) { - int len; + int len; - /* validate current elt */ - if (!bcm_valid_tlv(elt, *buflen)) - return NULL; + /* 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); + /* 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; + /* validate next elt */ + if (!bcm_valid_tlv (elt, *buflen)) + return NULL; - return elt; + return elt; } /* @@ -760,114 +1619,417 @@ bcm_next_tlv(bcm_tlv_t *elt, int *buflen) * 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 *BCMROMFN (bcm_parse_tlvs) (void *buf, int buflen, uint key) { - bcm_tlv_t *elt; - int totlen; + bcm_tlv_t *elt; + int totlen; - elt = (bcm_tlv_t*)buf; - totlen = buflen; + elt = (bcm_tlv_t *) buf; + totlen = buflen; - /* find tagged parameter */ - while (totlen >= 2) { - int len = elt->len; + /* find tagged parameter */ + while (totlen >= 2) + { + int len = elt->len; - /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (len + 2))) - return (elt); + /* validate remaining totlen */ + if ((elt->id == key) && (totlen >= (len + 2))) + return (elt); - elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); - totlen -= (len + 2); - } + elt = (bcm_tlv_t *) ((uint8 *) elt + (len + 2)); + totlen -= (len + 2); + } - return NULL; + return NULL; } +#if 0 /* * 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 *BCMROMFN (bcm_parse_ordered_tlvs) (void *buf, int buflen, uint key) { - bcm_tlv_t *elt; - int totlen; + 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; +} - elt = (bcm_tlv_t*)buf; - totlen = buflen; +#ifdef BCMDBG +int +bcm_format_flags (const bcm_bit_desc_t * bd, uint32 flags, char *buf, int len) +{ + int i; + char *p = buf; + char hexstr[16]; + int slen = 0; + uint32 bit; + const char *name; + + if (len < 2 || !buf) + return 0; + + buf[0] = '\0'; + len -= 1; + + for (i = 0; flags != 0; i++) + { + bit = bd[i].bit; + name = bd[i].name; + if (bit == 0 && flags) + { + /* print any unnamed bits */ + sprintf (hexstr, "0x%X", flags); + name = hexstr; + flags = 0; /* exit loop */ + } + else if ((flags & bit) == 0) + continue; + slen += strlen (name); + if (len < slen) + break; + if (p != buf) + p += sprintf (p, " "); /* btwn flag space */ + strcat (p, name); + p += strlen (name); + flags &= ~bit; + len -= slen; + slen = 1; /* account for btwn flag space */ + } + + /* indicate the str was too short */ + if (flags != 0) + { + if (len == 0) + p--; /* overwrite last char */ + p += sprintf (p, ">"); + } + + return (int) (p - buf); +} - /* find tagged parameter */ - while (totlen >= 2) { - uint id = elt->id; - int len = elt->len; +void +deadbeef (void *p, uint len) +{ + static uint8 meat[] = { 0xde, 0xad, 0xbe, 0xef }; - /* Punt if we start seeing IDs > than target key */ - if (id > key) - return (NULL); + while (len-- > 0) + { + *(uint8 *) p = meat[((uintptr) p) & 3]; + p = (uint8 *) p + 1; + } +} - /* validate remaining totlen */ - if ((id == key) && (totlen >= (len + 2))) - return (elt); +/* pretty hex print a contiguous buffer */ +void +prhex (const char *msg, uchar * buf, uint nbytes) +{ + char line[128], *p; + uint i; - elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); - totlen -= (len + 2); + if (msg && (msg[0] != '\0')) + printf ("%s:\n", msg); + + p = line; + for (i = 0; i < nbytes; i++) + { + if (i % 16 == 0) + { + p += sprintf (p, " %04d: ", i); /* line prefix */ } - return NULL; + p += sprintf (p, "%02x ", buf[i]); + if (i % 16 == 15) + { + printf ("%s\n", line); /* flush line */ + p = line; + } + } + + /* flush last partial line */ + if (p != line) + printf ("%s\n", line); +} + +/* print bytes formatted as hex to a string. return the resulting string length */ +int +bcm_format_hex (char *str, const void *bytes, int len) +{ + int i; + char *p = str; + const uint8 *src = (const uint8 *) bytes; + + for (i = 0; i < len; i++) + { + p += sprintf (p, "%02X", *src); + src++; + } + return (int) (p - str); } +#endif /* BCMDBG */ -/* Initialization of bcmstrbuf structure */ +/* Produce a human-readable string for boardrev */ +char * +bcm_brev_str (uint16 brev, char *buf) +{ + if (brev < 0x100) + snprintf (buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); + else + snprintf (buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', + brev & 0xfff); + + return (buf); +} + +#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ + +/* dump large strings to console */ void -bcm_binit(struct bcmstrbuf *b, char *buf, uint size) +printfbig (char *buf) { - b->origsize = b->size = size; - b->origbuf = b->buf = buf; + uint len, max_len; + char c; + + len = strlen (buf); + + max_len = BUFSIZE_TODUMP_ATONCE; + + while (len > max_len) + { + c = buf[max_len]; + buf[max_len] = '\0'; + printf ("%s", buf); + buf[max_len] = c; + + buf += max_len; + len -= max_len; + } + /* print the remaining string */ + printf ("%s\n", buf); + return; } -/* Buffer sprintf wrapper to guard against buffer overflow */ -int -bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) +/* routine to dump fields in a fileddesc structure */ +uint +bcmdumpfields (readreg_rtn read_rtn, void *arg0, void *arg1, + struct fielddesc * fielddesc_array, char *buf, uint32 bufsize) +{ + uint filled_len; + int len; + struct fielddesc *cur_ptr; + + filled_len = 0; + cur_ptr = fielddesc_array; + + while (bufsize > 1) + { + if (cur_ptr->nameandfmt == NULL) + break; + len = snprintf (buf, bufsize, cur_ptr->nameandfmt, + read_rtn (arg0, arg1, cur_ptr->offset)); + /* check for snprintf overflow or error */ + if (len < 0 || (uint32) len >= bufsize) + len = bufsize - 1; + buf += len; + bufsize -= len; + filled_len += len; + cur_ptr++; + } + return filled_len; +} +#endif + +uint +bcm_mkiovar (char *name, char *data, uint datalen, char *buf, uint buflen) { - va_list ap; - int r; + uint len; - va_start(ap, fmt); - r = vsnprintf(b->buf, b->size, fmt, ap); + len = strlen (name) + 1; - /* 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 + if ((len + datalen) > buflen) + return 0; + + strncpy (buf, name, buflen); + + /* append data onto the end of the name string */ + memcpy (&buf[len], data, datalen); + len += datalen; + + return len; +} + +/* Quarter dBm units to mW + * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 + * Table is offset so the last entry is largest mW value that fits in + * a uint16. + */ + +#define QDBM_OFFSET 153 /* Offset for first entry */ +#define QDBM_TABLE_LEN 40 /* Table size */ + +/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. + * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 + */ +#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ + +/* Largest mW value that will round down to the last table entry, + * QDBM_OFFSET + QDBM_TABLE_LEN-1. + * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. + */ +#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ + +static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { +/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ +/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, +/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, +/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, +/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, +/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 +}; + +uint16 BCMROMFN (bcm_qdbm_to_mw) (uint8 qdbm) +{ + uint factor = 1; + int idx = qdbm - QDBM_OFFSET; + + if (idx > QDBM_TABLE_LEN) + { + /* clamp to max uint16 mW value */ + return 0xFFFF; + } + + /* scale the qdBm index up to the range of the table 0-40 + * where an offset of 40 qdBm equals a factor of 10 mW. + */ + while (idx < 0) + { + idx += 40; + factor *= 10; + } + + /* return the mW value scaled down to the correct factor of 10, + * adding in factor/2 to get proper rounding. + */ + return ((nqdBm_to_mW_map[idx] + factor / 2) / factor); +} + +uint8 BCMROMFN (bcm_mw_to_qdbm) (uint16 mw) +{ + uint8 qdbm; + int offset; + uint mw_uint = mw; + uint boundary; + + /* handle boundary case */ + if (mw_uint <= 1) + return 0; + + offset = QDBM_OFFSET; + + /* move mw into the range of the table */ + while (mw_uint < QDBM_TABLE_LOW_BOUND) + { + mw_uint *= 10; + offset -= 40; + } + + for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) + { + boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] - + nqdBm_to_mW_map[qdbm]) / 2; + if (mw_uint < boundary) + break; + } + + qdbm += (uint8) offset; + + return (qdbm); +} + + +uint BCMROMFN (bcm_bitcount) (uint8 * bitmap, uint length) +{ + uint bitcount = 0, i; + uint8 tmp; + for (i = 0; i < length; i++) + { + tmp = bitmap[i]; + while (tmp) { - b->size -= r; - b->buf += r; + bitcount++; + tmp &= (tmp - 1); } + } + return bitcount; +} - va_end(ap); - return r; +/* Initialization of bcmstrbuf structure */ +void +bcm_binit (struct bcmstrbuf *b, char *buf, uint size) +{ + b->origsize = b->size = size; + b->origbuf = b->buf = buf; } -uint -bcm_bitcount(uint8 *bitmap, uint length) -{ - uint bitcount = 0, i; - uint8 tmp; - for (i = 0; i < length; i++) { - tmp = bitmap[i]; - while (tmp) { - bitcount++; - tmp &= (tmp - 1); - } - } - return bitcount; +/* 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; +} + +char * +bcm_ether_ntoa (struct ether_addr *ea, char *buf) +{ + snprintf (buf, 18, "%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); } diff --git a/package/broadcom-wl/src/driver/bcmutils.h b/package/broadcom-wl/src/driver/bcmutils.h new file mode 100644 index 0000000000..9dcf08b726 --- /dev/null +++ b/package/broadcom-wl/src/driver/bcmutils.h @@ -0,0 +1,582 @@ +/* + * Misc useful os-independent macros and functions. + * + * Copyright 2007, 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$ + */ + +#ifndef _bcmutils_h_ +#define _bcmutils_h_ +#include "linux_osl.h" + +/* ctype replacement */ +#define _BCM_U 0x01 /* upper */ +#define _BCM_L 0x02 /* lower */ +#define _BCM_D 0x04 /* digit */ +#define _BCM_C 0x08 /* cntrl */ +#define _BCM_P 0x10 /* punct */ +#define _BCM_S 0x20 /* white space (space/lf/tab) */ +#define _BCM_X 0x40 /* hex digit */ +#define _BCM_SP 0x80 /* hard space (0x20) */ + +extern const unsigned char bcm_ctype[]; +#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) + +#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) +#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) +#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) +#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) +#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) +#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) +#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) +#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) +#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) +#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) +#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) +#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) +#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) + +/* Buffer structure for collecting string-formatted data +* using bcm_bprintf() API. +* Use bcm_binit() to initialize before use +*/ + +struct bcmstrbuf { + char *buf; /* pointer to current position in origbuf */ + unsigned int size; /* current (residual) size in bytes */ + char *origbuf; /* unmodified pointer to orignal buffer */ + unsigned int origsize; /* unmodified orignal buffer size in bytes */ +}; + +/* ** driver-only section ** */ +#include <osl.h> + +#define GPIO_PIN_NOTDEFINED 0x20 /* Pin not defined */ + + +/* osl multi-precedence packet queue */ +#ifndef PKTQ_LEN_DEFAULT +#define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ +#endif +#ifndef PKTQ_MAX_PREC +#define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ +#endif + +typedef 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 */ +} pktq_prec_t; + + +/* multi-priority pkt queue */ +struct pktq { + 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 */ + /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ + struct pktq_prec q[PKTQ_MAX_PREC]; +}; + +/* simple, non-priority pkt queue */ +struct spktq { + uint16 num_prec; /* number of precedences in use (always 1) */ + uint16 hi_prec; /* rapid dequeue hint (>= highest non-empty prec) */ + uint16 max; /* total max packets */ + uint16 len; /* total number of packets */ + /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ + struct pktq_prec q[1]; +}; + +#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(((struct pktq *)pq), 0, (p)) +#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)pq), 0, (p)) +#define pktdeq(pq) pktq_pdeq(((struct pktq *)pq), 0) +#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)pq), 0) +#define pktqinit(pq, len) pktq_init(((struct pktq *)pq), 1, len) + +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 */ +extern int pktq_setmax(struct pktq *pq, int max_len); + +/* 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); + +/* Get priority from a packet and pass it back in scb (or equiv) */ +extern uint pktsetprio(void *pkt, bool update_vtag); +#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */ +#define PKTPRIO_VLAN 0x200 /* VLAN prio found */ +#define PKTPRIO_UPD 0x400 /* DSCP used to update VLAN prio */ +#define PKTPRIO_DSCP 0x800 /* DSCP prio found */ + +/* string */ +extern int BCMROMFN(bcm_atoi)(char *s); +extern ulong BCMROMFN(bcm_strtoul)(char *cp, char **endp, uint base); +extern char *BCMROMFN(bcmstrstr)(char *haystack, char *needle); +extern char *BCMROMFN(bcmstrcat)(char *dest, const char *src); +extern char *BCMROMFN(bcmstrncat)(char *dest, const char *src, uint size); +extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); +/* ethernet address */ +extern char *bcm_ether_ntoa(struct ether_addr *ea, char *buf); +extern int BCMROMFN(bcm_ether_atoe)(char *p, struct ether_addr *ea); + +/* ip address */ +struct ipv4_addr; +extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); + +/* delay */ +extern void bcm_mdelay(uint ms); +/* variable access */ +extern char *getvar(char *vars, const char *name); +extern int getintvar(char *vars, const char *name); +extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); +#ifdef BCMDBG +extern void prpkt(const char *msg, osl_t *osh, void *p0); +#endif /* BCMDBG */ +#ifdef BCMPERFSTATS +extern void bcm_perf_enable(void); +extern void bcmstats(char *fmt); +extern void bcmlog(char *fmt, uint a1, uint a2); +extern void bcmdumplog(char *buf, int size); +extern int bcmdumplogent(char *buf, uint idx); +#else +#define bcm_perf_enable() +#define bcmstats(fmt) +#define bcmlog(fmt, a1, a2) +#define bcmdumplog(buf, size) *buf = '\0' +#define bcmdumplogent(buf, idx) -1 +#endif /* BCMPERFSTATS */ +extern char *bcm_nvram_vars(uint *length); +extern int bcm_nvram_cache(void *sbh); + +/* Support for sharing code across in-driver iovar implementations. + * The intent is that a driver use this structure to map iovar names + * to its (private) iovar identifiers, and the lookup function to + * find the entry. Macros are provided to map ids and get/set actions + * into a single number space for a switch statement. + */ + +/* iovar structure */ +typedef struct bcm_iovar { + const char *name; /* name for lookup and display */ + uint16 varid; /* id for switch */ + uint16 flags; /* driver-specific flag bits */ + uint16 type; /* base type of argument */ + uint16 minlen; /* min length for buffer vars */ +} bcm_iovar_t; + +/* varid definitions are per-driver, may use these get/set bits */ + +/* IOVar action bits for id mapping */ +#define IOV_GET 0 /* Get an iovar */ +#define IOV_SET 1 /* Set an iovar */ + +/* Varid to actionid mapping */ +#define IOV_GVAL(id) ((id)*2) +#define IOV_SVAL(id) (((id)*2)+IOV_SET) +#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) + +/* flags are per-driver based on driver attributes */ + +extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); +extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); + +/* Base type definitions */ +#define IOVT_VOID 0 /* no value (implictly set only) */ +#define IOVT_BOOL 1 /* any value ok (zero/nonzero) */ +#define IOVT_INT8 2 /* integer values are range-checked */ +#define IOVT_UINT8 3 /* unsigned int 8 bits */ +#define IOVT_INT16 4 /* int 16 bits */ +#define IOVT_UINT16 5 /* unsigned int 16 bits */ +#define IOVT_INT32 6 /* int 32 bits */ +#define IOVT_UINT32 7 /* unsigned int 32 bits */ +#define IOVT_BUFFER 8 /* buffer is size-checked as per minlen */ +#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) + +/* Initializer for IOV type strings */ +#define BCM_IOV_TYPE_INIT { \ + "void", \ + "bool", \ + "int8", \ + "uint8", \ + "int16", \ + "uint16", \ + "int32", \ + "uint32", \ + "buffer", \ + "" } + +#define BCM_IOVT_IS_INT(type) (\ + (type == IOVT_BOOL) || \ + (type == IOVT_INT8) || \ + (type == IOVT_UINT8) || \ + (type == IOVT_INT16) || \ + (type == IOVT_UINT16) || \ + (type == IOVT_INT32) || \ + (type == IOVT_UINT32)) + +/* ** 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_VERSION -37 /* Incorrect version */ +#define BCME_LAST BCME_VERSION + +/* 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", \ + "Incorrect version" \ +} + +#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)) +#ifndef OFFSETOF +#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) +#endif /* OFFSETOF */ +#ifndef ARRAYSIZE +#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) +#endif + +/* 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) (((const uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a, i) ((((const 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; + const 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 /* IL_BIGENDIAN */ + +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 */ + +/* externs */ +/* crc */ +extern uint8 BCMROMFN(hndcrc8)(uint8 *p, uint nbytes, uint8 crc); +extern uint16 BCMROMFN(hndcrc16)(uint8 *p, uint nbytes, uint16 crc); +extern uint32 BCMROMFN(hndcrc32)(uint8 *p, uint nbytes, uint32 crc); +/* format/print */ +#ifdef BCMDBG +extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); +extern int bcm_format_hex(char *str, const void *bytes, int len); +extern void deadbeef(void *p, uint len); +extern void prhex(const char *msg, uchar *buf, uint len); +#endif /* BCMDBG */ +extern char *bcm_brev_str(uint16 brev, char *buf); +extern void printfbig(char *buf); + +/* IE parsing */ +extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); +extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); +extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); + +/* bcmerror */ +extern const char *bcmerrorstr(int bcmerror); + +/* multi-bool data type: set of bools, mbool is true if any is set */ +typedef uint32 mbool; +#define mboolset(mb, bit) ((mb) |= (bit)) /* set one bool */ +#define mboolclr(mb, bit) ((mb) &= ~(bit)) /* clear one bool */ +#define mboolisset(mb, bit) (((mb) & (bit)) != 0) /* TRUE if one bool is set */ +#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) + +/* power conversion */ +extern uint16 BCMROMFN(bcm_qdbm_to_mw)(uint8 qdbm); +extern uint8 BCMROMFN(bcm_mw_to_qdbm)(uint16 mw); + +/* generic datastruct to help dump routines */ +struct fielddesc { + const char *nameandfmt; + uint32 offset; + uint32 len; +}; + +extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); +extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); + +typedef uint32 (*readreg_rtn)(void *arg0, void *arg1, uint32 offset); +extern uint bcmdumpfields(readreg_rtn func_ptr, void *arg0, void *arg1, struct fielddesc *str, + char *buf, uint32 bufsize); + +extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); +extern uint BCMROMFN(bcm_bitcount)(uint8 *bitmap, uint bytelength); + +#ifdef BCMDBG_PKT /* pkt logging for debugging */ +#define PKTLIST_SIZE 1000 +typedef struct { + void *list[PKTLIST_SIZE]; /* List of pointers to packets */ + uint count; /* Total count of the packets */ +} pktlist_info_t; + +extern void pktlist_add(pktlist_info_t *pktlist, void *p); +extern void pktlist_remove(pktlist_info_t *pktlist, void *p); +extern char* pktlist_dump(pktlist_info_t *pktlist, char *buf); +#endif /* BCMDBG_PKT */ + +#endif /* _bcmutils_h_ */ diff --git a/package/broadcom-wl/src/driver/hnddma.c b/package/broadcom-wl/src/driver/hnddma.c index 1b79dff4c2..c6f6a13ed7 100644 --- a/package/broadcom-wl/src/driver/hnddma.c +++ b/package/broadcom-wl/src/driver/hnddma.c @@ -2,7 +2,7 @@ * Generic Broadcom Home Networking Division (HND) DMA module. * This supports the following chips: BCM42xx, 44xx, 47xx . * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -10,7 +10,7 @@ * 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 $ + * $Id$ */ #include <typedefs.h> @@ -19,7 +19,7 @@ #include "linux_osl.h" #include <bcmendian.h> #include <sbconfig.h> -#include <bcmutils.h> +#include "bcmutils.h" #include <bcmdevs.h> #include <sbutils.h> @@ -27,71 +27,77 @@ #include "hnddma.h" /* debug/trace */ +#ifdef BCMDBG +#define DMA_ERROR(args) if (!(*di->msg_level & 1)); else printf args +#define DMA_TRACE(args) if (!(*di->msg_level & 2)); else printf args +#else #define DMA_ERROR(args) #define DMA_TRACE(args) +#endif /* default dma message level (if input msg_level pointer is null in dma_attach()) */ -static uint dma_msg_level = - 0; +static uint dma_msg_level = 0; -#define MAXNAMEL 8 /* 8 char names */ +#define MAXNAMEL 8 /* 8 char names */ #define DI_INFO(dmah) (dma_info_t *)dmah +typedef struct osl_dmainfo osldma_t; /* 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 */ +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; #ifdef BCMDMA64 @@ -117,1053 +123,1394 @@ typedef struct dma_info { #define I2B(index, type) ((index) * sizeof(type)) #define PCI32ADDR_HIGH 0xc0000000 /* address[31:30] */ -#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ +#define PCI32ADDR_HIGH_SHIFT 30 /* address[31:30] */ /* common prototypes */ -static bool _dma_isaddrext(dma_info_t *di); -static bool _dma_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, const char *name); -static void _dma_counterreset(dma_info_t *di); -static void _dma_fifoloopbackenable(dma_info_t *di); +static bool _dma_isaddrext (dma_info_t * di); +static bool _dma_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, const 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 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); /* ** 64 bit DMA prototypes and stubs */ #ifdef BCMDMA64 -static bool dma64_alloc(dma_info_t *di, uint direction); -static bool dma64_txreset(dma_info_t *di); -static bool dma64_rxreset(dma_info_t *di); -static bool dma64_txsuspendedidle(dma_info_t *di); -static int dma64_txfast(dma_info_t *di, void *p0, bool commit); -static void *dma64_getnexttxp(dma_info_t *di, bool forceall); -static void *dma64_getnextrxp(dma_info_t *di, bool forceall); -static void dma64_txrotate(dma_info_t *di); - -static bool dma64_rxidle(dma_info_t *di); -static void dma64_txinit(dma_info_t *di); -static bool dma64_txenabled(dma_info_t *di); -static void dma64_txsuspend(dma_info_t *di); -static void dma64_txresume(dma_info_t *di); -static bool dma64_txsuspended(dma_info_t *di); -static void dma64_txreclaim(dma_info_t *di, bool forceall); -static bool dma64_txstopped(dma_info_t *di); -static bool dma64_rxstopped(dma_info_t *di); -static bool dma64_rxenabled(dma_info_t *di); -static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs); +static bool dma64_alloc (dma_info_t * di, uint direction); +static bool dma64_txreset (dma_info_t * di); +static bool dma64_rxreset (dma_info_t * di); +static bool dma64_txsuspendedidle (dma_info_t * di); +static int dma64_txfast (dma_info_t * di, void *p0, bool commit); +static void *dma64_getnexttxp (dma_info_t * di, bool forceall); +static void *dma64_getnextrxp (dma_info_t * di, bool forceall); +static void dma64_txrotate (dma_info_t * di); + +static bool dma64_rxidle (dma_info_t * di); +static void dma64_txinit (dma_info_t * di); +static bool dma64_txenabled (dma_info_t * di); +static void dma64_txsuspend (dma_info_t * di); +static void dma64_txresume (dma_info_t * di); +static bool dma64_txsuspended (dma_info_t * di); +static void dma64_txreclaim (dma_info_t * di, bool forceall); +static bool dma64_txstopped (dma_info_t * di); +static bool dma64_rxstopped (dma_info_t * di); +static bool dma64_rxenabled (dma_info_t * di); +static bool _dma64_addrext (osl_t * osh, dma64regs_t * dma64regs); #else -static bool dma64_alloc(dma_info_t *di, uint direction) { return FALSE; } -static bool dma64_txreset(dma_info_t *di) { return FALSE; } -static bool dma64_rxreset(dma_info_t *di) { return FALSE; } -static bool dma64_txsuspendedidle(dma_info_t *di) { return FALSE;} -static int dma64_txfast(dma_info_t *di, void *p0, bool commit) { return 0; } -static void *dma64_getnexttxp(dma_info_t *di, bool forceall) { return NULL; } -static void *dma64_getnextrxp(dma_info_t *di, bool forceall) { return NULL; } -static void dma64_txrotate(dma_info_t *di) { return; } - -static bool dma64_rxidle(dma_info_t *di) { return FALSE; } -static void dma64_txinit(dma_info_t *di) { return; } -static bool dma64_txenabled(dma_info_t *di) { return FALSE; } -static void dma64_txsuspend(dma_info_t *di) { return; } -static void dma64_txresume(dma_info_t *di) { return; } -static bool dma64_txsuspended(dma_info_t *di) {return FALSE; } -static void dma64_txreclaim(dma_info_t *di, bool forceall) { return; } -static bool dma64_txstopped(dma_info_t *di) { return FALSE; } -static bool dma64_rxstopped(dma_info_t *di) { return FALSE; } -static bool dma64_rxenabled(dma_info_t *di) { return FALSE; } -static bool _dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) { return FALSE; } - -#endif /* BCMDMA64 */ +static bool +dma64_alloc (dma_info_t * di, uint direction) +{ + return FALSE; +} +static bool +dma64_txreset (dma_info_t * di) +{ + return FALSE; +} +static bool +dma64_rxreset (dma_info_t * di) +{ + return FALSE; +} +static bool +dma64_txsuspendedidle (dma_info_t * di) +{ + return FALSE; +} +static int +dma64_txfast (dma_info_t * di, void *p0, bool commit) +{ + return 0; +} +static void * +dma64_getnexttxp (dma_info_t * di, bool forceall) +{ + return NULL; +} +static void * +dma64_getnextrxp (dma_info_t * di, bool forceall) +{ + return NULL; +} +static void +dma64_txrotate (dma_info_t * di) +{ + return; +} +static bool +dma64_rxidle (dma_info_t * di) +{ + return FALSE; +} +static void +dma64_txinit (dma_info_t * di) +{ + return; +} +static bool +dma64_txenabled (dma_info_t * di) +{ + return FALSE; +} +static void +dma64_txsuspend (dma_info_t * di) +{ + return; +} +static void +dma64_txresume (dma_info_t * di) +{ + return; +} +static bool +dma64_txsuspended (dma_info_t * di) +{ + return FALSE; +} +static void +dma64_txreclaim (dma_info_t * di, bool forceall) +{ + return; +} +static bool +dma64_txstopped (dma_info_t * di) +{ + return FALSE; +} +static bool +dma64_rxstopped (dma_info_t * di) +{ + return FALSE; +} +static bool +dma64_rxenabled (dma_info_t * di) +{ + return FALSE; +} +static bool +_dma64_addrext (osl_t * osh, dma64regs_t * dma64regs) +{ + return FALSE; +} + +#endif /* BCMDMA64 */ + +#ifdef BCMDBG +static void dma32_dumpring (dma_info_t * di, struct bcmstrbuf *b, + dma32dd_t * ring, uint start, uint end, + uint max_num); +static void dma32_dump (dma_info_t * di, struct bcmstrbuf *b, bool dumpring); +static void dma32_dumptx (dma_info_t * di, struct bcmstrbuf *b, + bool dumpring); +static void dma32_dumprx (dma_info_t * di, struct bcmstrbuf *b, + bool dumpring); + +static void dma64_dumpring (dma_info_t * di, struct bcmstrbuf *b, + dma64dd_t * ring, uint start, uint end, + uint max_num); +static void dma64_dump (dma_info_t * di, struct bcmstrbuf *b, bool dumpring); +static void dma64_dumptx (dma_info_t * di, struct bcmstrbuf *b, + bool dumpring); +static void dma64_dumprx (dma_info_t * di, struct bcmstrbuf *b, + bool dumpring); +#endif static di_fcn_t dma64proc = { - (di_detach_t)_dma_detach, - (di_txinit_t)dma64_txinit, - (di_txreset_t)dma64_txreset, - (di_txenabled_t)dma64_txenabled, - (di_txsuspend_t)dma64_txsuspend, - (di_txresume_t)dma64_txresume, - (di_txsuspended_t)dma64_txsuspended, - (di_txsuspendedidle_t)dma64_txsuspendedidle, - (di_txfast_t)dma64_txfast, - (di_txstopped_t)dma64_txstopped, - (di_txreclaim_t)dma64_txreclaim, - (di_getnexttxp_t)dma64_getnexttxp, - (di_peeknexttxp_t)_dma_peeknexttxp, - (di_txblock_t)_dma_txblock, - (di_txunblock_t)_dma_txunblock, - (di_txactive_t)_dma_txactive, - (di_txrotate_t)dma64_txrotate, - - (di_rxinit_t)_dma_rxinit, - (di_rxreset_t)dma64_rxreset, - (di_rxidle_t)dma64_rxidle, - (di_rxstopped_t)dma64_rxstopped, - (di_rxenable_t)_dma_rxenable, - (di_rxenabled_t)dma64_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 + (di_detach_t) _dma_detach, + (di_txinit_t) dma64_txinit, + (di_txreset_t) dma64_txreset, + (di_txenabled_t) dma64_txenabled, + (di_txsuspend_t) dma64_txsuspend, + (di_txresume_t) dma64_txresume, + (di_txsuspended_t) dma64_txsuspended, + (di_txsuspendedidle_t) dma64_txsuspendedidle, + (di_txfast_t) dma64_txfast, + (di_txstopped_t) dma64_txstopped, + (di_txreclaim_t) dma64_txreclaim, + (di_getnexttxp_t) dma64_getnexttxp, + (di_peeknexttxp_t) _dma_peeknexttxp, + (di_txblock_t) _dma_txblock, + (di_txunblock_t) _dma_txunblock, + (di_txactive_t) _dma_txactive, + (di_txrotate_t) dma64_txrotate, + + (di_rxinit_t) _dma_rxinit, + (di_rxreset_t) dma64_rxreset, + (di_rxidle_t) dma64_rxidle, + (di_rxstopped_t) dma64_rxstopped, + (di_rxenable_t) _dma_rxenable, + (di_rxenabled_t) dma64_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, + +#ifdef BCMDBG + (di_dump_t) dma64_dump, + (di_dumptx_t) dma64_dumptx, + (di_dumprx_t) dma64_dumprx, +#else + NULL, + NULL, + NULL, +#endif + 34 }; 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 + (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, + +#ifdef BCMDBG + (di_dump_t) dma32_dump, + (di_dumptx_t) dma32_dumptx, + (di_dumprx_t) dma32_dumprx, +#else + NULL, + NULL, + NULL, +#endif + 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_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; + dma_info_t *di; + uint size; + + /* allocate private info structure */ + if ((di = MALLOC (osh, sizeof (dma_info_t))) == NULL) + { +#ifdef BCMDBG + printf ("dma_attach: out of memory, malloced %d bytes\n", + MALLOCED (osh)); +#endif + return (NULL); + } + bzero ((char *) di, sizeof (dma_info_t)); - /* 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; - di->msg_level = msg_level ? msg_level : &dma_msg_level; + /* old chips w/o sb is no longer supported */ + ASSERT (sbh != NULL); - /* old chips w/o sb is no longer supported */ - ASSERT(sbh != NULL); - - di->dma64 = ((sb_coreflagshi(sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64); + di->dma64 = ((sb_coreflagshi (sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64); #ifndef BCMDMA64 - if (di->dma64) { - DMA_ERROR(("dma_attach: driver doesn't have the capability to support " - "64 bits DMA\n")); - goto fail; - } + if (di->dma64) + { + DMA_ERROR (("dma_attach: driver doesn't have the capability to support " + "64 bits DMA\n")); + goto fail; + } #endif - /* check arguments */ - ASSERT(ISPOWEROF2(ntxd)); - ASSERT(ISPOWEROF2(nrxd)); - if (nrxd == 0) - ASSERT(dmaregsrx == NULL); - if (ntxd == 0) - ASSERT(dmaregstx == NULL); - - - /* init dma reg pointer */ - if (di->dma64) { - ASSERT(ntxd <= D64MAXDD); - ASSERT(nrxd <= D64MAXDD); - di->d64txregs = (dma64regs_t *)dmaregstx; - di->d64rxregs = (dma64regs_t *)dmaregsrx; - - di->dma64align = D64RINGALIGN; - if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) { - /* for smaller dd table, HW relax the alignment requirement */ - di->dma64align = D64RINGALIGN / 2; - } - } else { - ASSERT(ntxd <= D32MAXDD); - ASSERT(nrxd <= D32MAXDD); - di->d32txregs = (dma32regs_t *)dmaregstx; - di->d32rxregs = (dma32regs_t *)dmaregsrx; + /* check arguments */ + ASSERT (ISPOWEROF2 (ntxd)); + ASSERT (ISPOWEROF2 (nrxd)); + if (nrxd == 0) + ASSERT (dmaregsrx == NULL); + if (ntxd == 0) + ASSERT (dmaregstx == NULL); + + + /* init dma reg pointer */ + if (di->dma64) + { + ASSERT (ntxd <= D64MAXDD); + ASSERT (nrxd <= D64MAXDD); + di->d64txregs = (dma64regs_t *) dmaregstx; + di->d64rxregs = (dma64regs_t *) dmaregsrx; + + di->dma64align = D64RINGALIGN; + if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) + { + /* for smaller dd table, HW relax the alignment requirement */ + di->dma64align = D64RINGALIGN / 2; } - - DMA_TRACE(("%s: dma_attach: %s osh %p ntxd %d nrxd %d rxbufsize %d nrxpost %d " - "rxoffset %d dmaregstx %p dmaregsrx %p\n", - name, (di->dma64 ? "DMA64" : "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) { - if ((sbh->buscoretype == SB_PCIE) && di->dma64) { - /* pcie with DMA64 */ - di->ddoffsetlow = 0; - di->ddoffsethigh = SB_PCIE_DMA_H32; - } else { - /* pci(DMA32/DMA64) or pcie with DMA32 */ - di->ddoffsetlow = SB_PCI_DMA; - di->ddoffsethigh = 0; - } - di->dataoffsetlow = di->ddoffsetlow; - di->dataoffsethigh = di->ddoffsethigh; + } + else + { + 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, (di->dma64 ? "DMA64" : "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) + { + if ((sbh->buscoretype == SB_PCIE) && di->dma64) + { + /* pcie with DMA64 */ + di->ddoffsetlow = 0; + di->ddoffsethigh = SB_PCIE_DMA_H32; } + else + { + /* pci(DMA32/DMA64) or pcie with DMA32 */ + 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; + 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); + 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; } - - /* 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); + 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; } - - /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ - if (ntxd) { - if (!_dma_alloc(di, DMA_TX)) - goto fail; - } - - /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ - if (nrxd) { - if (!_dma_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 = DMA64_ENAB(di) ? dma64proc : dma32proc; - - return ((hnddma_t *)di); + bzero ((char *) di->rxp, size); + } + + /* allocate transmit descriptor ring, only need ntxd descriptors but it must be aligned */ + if (ntxd) + { + if (!_dma_alloc (di, DMA_TX)) + goto fail; + } + + /* allocate receive descriptor ring, only need nrxd descriptors but it must be aligned */ + if (nrxd) + { + if (!_dma_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 = DMA64_ENAB (di) ? dma64proc : dma32proc; + + return ((hnddma_t *) di); fail: - _dma_detach(di); - return (NULL); + _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)); - } +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 INLINE void -dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, ulong pa, uint outidx, uint32 *flags, - uint32 bufcount) -{ - uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; - - /* PCI bus with big(>1G) physical address, use address extension */ - if ((di->dataoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { - W_SM(&ddring[outidx].addrlow, BUS_SWAP32(pa + di->dataoffsetlow)); - W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); - W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); - W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); - } else { - /* address extension */ - uint32 ae; - ASSERT(di->addrext); - - ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; - pa &= ~PCI32ADDR_HIGH; - - ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; - W_SM(&ddring[outidx].addrlow, BUS_SWAP32(pa + di->dataoffsetlow)); - W_SM(&ddring[outidx].addrhigh, BUS_SWAP32(0 + di->dataoffsethigh)); - W_SM(&ddring[outidx].ctrl1, BUS_SWAP32(*flags)); - W_SM(&ddring[outidx].ctrl2, BUS_SWAP32(ctrl2)); - } +dma64_dd_upd (dma_info_t * di, dma64dd_t * ddring, ulong pa, uint outidx, + uint32 * flags, uint32 bufcount) +{ + uint32 ctrl2 = bufcount & D64_CTRL2_BC_MASK; + + /* PCI bus with big(>1G) physical address, use address extension */ + if ((di->dataoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) + { + W_SM (&ddring[outidx].addrlow, BUS_SWAP32 (pa + di->dataoffsetlow)); + W_SM (&ddring[outidx].addrhigh, BUS_SWAP32 (0 + di->dataoffsethigh)); + W_SM (&ddring[outidx].ctrl1, BUS_SWAP32 (*flags)); + W_SM (&ddring[outidx].ctrl2, BUS_SWAP32 (ctrl2)); + } + else + { + /* address extension */ + uint32 ae; + ASSERT (di->addrext); + + ae = (pa & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT; + pa &= ~PCI32ADDR_HIGH; + + ctrl2 |= (ae << D64_CTRL2_AE_SHIFT) & D64_CTRL2_AE; + W_SM (&ddring[outidx].addrlow, BUS_SWAP32 (pa + di->dataoffsetlow)); + W_SM (&ddring[outidx].addrhigh, BUS_SWAP32 (0 + di->dataoffsethigh)); + W_SM (&ddring[outidx].ctrl1, BUS_SWAP32 (*flags)); + W_SM (&ddring[outidx].ctrl2, BUS_SWAP32 (ctrl2)); + } } static bool -_dma32_addrext(osl_t *osh, dma32regs_t *dma32regs) +_dma32_addrext (osl_t * osh, dma32regs_t * dma32regs) { - uint32 w; + 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); + 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); } static bool -_dma_alloc(dma_info_t *di, uint direction) +_dma_alloc (dma_info_t * di, uint direction) { - if (DMA64_ENAB(di)) { - return dma64_alloc(di, direction); - } else { - return dma32_alloc(di, direction); - } + if (DMA64_ENAB (di)) + { + return dma64_alloc (di, direction); + } + else + { + return dma32_alloc (di, direction); + } } /* !! 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 (DMA64_ENAB(di)) { - if (di->txd64) - DMA_FREE_CONSISTENT(di->osh, ((int8*)(uintptr)di->txd64 - di->txdalign), - di->txdalloc, (di->txdpa - di->txdalign), &di->tx_dmah); - if (di->rxd64) - DMA_FREE_CONSISTENT(di->osh, ((int8*)(uintptr)di->rxd64 - di->rxdalign), - di->rxdalloc, (di->rxdpa - di->rxdalign), &di->rx_dmah); - } else { - if (di->txd32) - DMA_FREE_CONSISTENT(di->osh, ((int8*)(uintptr)di->txd32 - di->txdalign), - di->txdalloc, (di->txdpa - di->txdalign), &di->tx_dmah); - if (di->rxd32) - DMA_FREE_CONSISTENT(di->osh, ((int8*)(uintptr)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)); +_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 (DMA64_ENAB (di)) + { + if (di->txd64) + DMA_FREE_CONSISTENT (di->osh, + ((int8 *) (uintptr) di->txd64 - di->txdalign), + di->txdalloc, (di->txdpa - di->txdalign), + &di->tx_dmah); + if (di->rxd64) + DMA_FREE_CONSISTENT (di->osh, + ((int8 *) (uintptr) di->rxd64 - di->rxdalign), + di->rxdalloc, (di->rxdpa - di->rxdalign), + &di->rx_dmah); + } + else + { + if (di->txd32) + DMA_FREE_CONSISTENT (di->osh, + ((int8 *) (uintptr) di->txd32 - di->txdalign), + di->txdalloc, (di->txdpa - di->txdalign), + &di->tx_dmah); + if (di->rxd32) + DMA_FREE_CONSISTENT (di->osh, + ((int8 *) (uintptr) 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 (DMA64_ENAB(di)) { - /* DMA64 supports full 32 bits or 64 bits. AE is always valid */ - - /* not all tx or rx channel are available */ - if (di->d64txregs != NULL) { - if (!_dma64_addrext(di->osh, di->d64txregs)) { - DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", - di->name)); - ASSERT(0); - } - return TRUE; - } else if (di->d64rxregs != NULL) { - if (!_dma64_addrext(di->osh, di->d64rxregs)) { - DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", - di->name)); - ASSERT(0); - } - return TRUE; - } - return FALSE; - } else if (di->d32txregs) - return (_dma32_addrext(di->osh, di->d32txregs)); - else if (di->d32rxregs) - return (_dma32_addrext(di->osh, di->d32rxregs)); - return FALSE; +_dma_isaddrext (dma_info_t * di) +{ + if (DMA64_ENAB (di)) + { + /* DMA64 supports full 32 bits or 64 bits. AE is always valid */ + + /* not all tx or rx channel are available */ + if (di->d64txregs != NULL) + { + if (!_dma64_addrext (di->osh, di->d64txregs)) + { + DMA_ERROR (("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", di->name)); + ASSERT (0); + } + return TRUE; + } + else if (di->d64rxregs != NULL) + { + if (!_dma64_addrext (di->osh, di->d64rxregs)) + { + DMA_ERROR (("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", di->name)); + ASSERT (0); + } + return TRUE; + } + return FALSE; + } + else 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 (DMA64_ENAB(di)) { - - if ((di->ddoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) { - if (direction == DMA_TX) { - W_REG(di->osh, &di->d64txregs->addrlow, (pa + di->ddoffsetlow)); - W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); - } else { - W_REG(di->osh, &di->d64rxregs->addrlow, (pa + di->ddoffsetlow)); - W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); - } - } else { - /* DMA64 32bits 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->d64txregs->addrlow, (pa + di->ddoffsetlow)); - W_REG(di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); - SET_REG(di->osh, &di->d64txregs->control, D64_XC_AE, - (ae << D64_XC_AE_SHIFT)); - } else { - W_REG(di->osh, &di->d64rxregs->addrlow, (pa + di->ddoffsetlow)); - W_REG(di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); - SET_REG(di->osh, &di->d64rxregs->control, D64_RC_AE, - (ae << D64_RC_AE_SHIFT)); - } - } - - } else { - 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 <<XC_AE_SHIFT); - } else { - W_REG(di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); - SET_REG(di->osh, &di->d32rxregs->control, RC_AE, ae <<RC_AE_SHIFT); - } - } +_dma_ddtable_init (dma_info_t * di, uint direction, ulong pa) +{ + if (DMA64_ENAB (di)) + { + + if ((di->ddoffsetlow != SB_PCI_DMA) || !(pa & PCI32ADDR_HIGH)) + { + if (direction == DMA_TX) + { + W_REG (di->osh, &di->d64txregs->addrlow, + (pa + di->ddoffsetlow)); + W_REG (di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); + } + else + { + W_REG (di->osh, &di->d64rxregs->addrlow, + (pa + di->ddoffsetlow)); + W_REG (di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); + } + } + else + { + /* DMA64 32bits 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->d64txregs->addrlow, + (pa + di->ddoffsetlow)); + W_REG (di->osh, &di->d64txregs->addrhigh, di->ddoffsethigh); + SET_REG (di->osh, &di->d64txregs->control, D64_XC_AE, + (ae << D64_XC_AE_SHIFT)); + } + else + { + W_REG (di->osh, &di->d64rxregs->addrlow, + (pa + di->ddoffsetlow)); + W_REG (di->osh, &di->d64rxregs->addrhigh, di->ddoffsethigh); + SET_REG (di->osh, &di->d64rxregs->control, D64_RC_AE, + (ae << D64_RC_AE_SHIFT)); + } + } + + } + else + { + 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 << XC_AE_SHIFT); + } + else + { + W_REG (di->osh, &di->d32rxregs->addr, (pa + di->ddoffsetlow)); + SET_REG (di->osh, &di->d32rxregs->control, RC_AE, + ae << RC_AE_SHIFT); + } + } + } } static void -_dma_fifoloopbackenable(dma_info_t *di) +_dma_fifoloopbackenable (dma_info_t * di) { - DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name)); - if (DMA64_ENAB(di)) - OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE); - else - OR_REG(di->osh, &di->d32txregs->control, XC_LE); + DMA_TRACE (("%s: dma_fifoloopbackenable\n", di->name)); + if (DMA64_ENAB (di)) + OR_REG (di->osh, &di->d64txregs->control, D64_XC_LE); + else + OR_REG (di->osh, &di->d32txregs->control, XC_LE); } static void -_dma_rxinit(dma_info_t *di) +_dma_rxinit (dma_info_t * di) { - DMA_TRACE(("%s: dma_rxinit\n", di->name)); + DMA_TRACE (("%s: dma_rxinit\n", di->name)); - if (di->nrxd == 0) - return; + if (di->nrxd == 0) + return; - di->rxin = di->rxout = 0; + di->rxin = di->rxout = 0; - /* clear rx descriptor ring */ - if (DMA64_ENAB(di)) { - BZERO_SM((void *)(uintptr)di->rxd64, (di->nrxd * sizeof(dma64dd_t))); - _dma_rxenable(di); - _dma_ddtable_init(di, DMA_RX, di->rxdpa); - } else { - BZERO_SM((void *)(uintptr)di->rxd32, (di->nrxd * sizeof(dma32dd_t))); - _dma_rxenable(di); - _dma_ddtable_init(di, DMA_RX, di->rxdpa); - } + /* clear rx descriptor ring */ + if (DMA64_ENAB (di)) + BZERO_SM ((void *) (uintptr) di->rxd64, (di->nrxd * sizeof (dma64dd_t))); + else + BZERO_SM ((void *) (uintptr) 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_rxenable (dma_info_t * di) { - DMA_TRACE(("%s: dma_rxenable\n", di->name)); - - if (DMA64_ENAB(di)) - W_REG(di->osh, &di->d64rxregs->control, - ((di->rxoffset << D64_RC_RO_SHIFT) | D64_RC_RE)); - else - W_REG(di->osh, &di->d32rxregs->control, ((di->rxoffset << RC_RO_SHIFT) | RC_RE)); + DMA_TRACE (("%s: dma_rxenable\n", di->name)); + + if (DMA64_ENAB (di)) + W_REG (di->osh, &di->d64rxregs->control, + ((di->rxoffset << D64_RC_RO_SHIFT) | D64_RC_RE)); + else + 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; +_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; } - return (p); + /* 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 (DMA64_ENAB(di)) { - if (rxout == (di->nrxd - 1)) - flags = D64_CTRL1_EOT; - - dma64_dd_upd(di, di->rxd64, pa, rxout, &flags, di->rxbufsize); - } else { - if (rxout == (di->nrxd - 1)) - flags = CTRL_EOT; - - dma32_dd_upd(di, di->rxd32, pa, rxout, &flags, di->rxbufsize); - } - rxout = NEXTRXD(rxout); +_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); - di->rxout = rxout; + /* Do a cached write instead of uncached write since DMA_MAP + * will flush the cache. + */ + *(uint32 *) (PKTDATA (di->osh, p)) = 0; - /* update the chip lastdscr pointer */ - if (DMA64_ENAB(di)) { - W_REG(di->osh, &di->d64rxregs->ptr, I2B(rxout, dma64dd_t)); - } else { - W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t)); - } -} + pa = (uint32) DMA_MAP (di->osh, PKTDATA (di->osh, p), + di->rxbufsize, DMA_RX, p, &di->rxp_dmah[rxout]); -/* like getnexttxp but no reclaim */ -static void * -_dma_peeknexttxp(dma_info_t *di) -{ - uint end, i; + ASSERT (ISALIGNED (pa, 4)); + + /* save the free packet pointer */ + ASSERT (di->rxp[rxout] == NULL); + di->rxp[rxout] = p; - if (di->ntxd == 0) - return (NULL); + /* reset flags for each descriptor */ + flags = 0; + if (DMA64_ENAB (di)) + { + if (rxout == (di->nrxd - 1)) + flags = D64_CTRL1_EOT; - if (DMA64_ENAB(di)) { - end = B2I(R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); - } else { - end = B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK, dma32dd_t); + dma64_dd_upd (di, di->rxd64, pa, rxout, &flags, di->rxbufsize); } + else + { + if (rxout == (di->nrxd - 1)) + flags = CTRL_EOT; - for (i = di->txin; i != end; i = NEXTTXD(i)) - if (di->txp[i]) - return (di->txp[i]); + dma32_dd_upd (di, di->rxd32, pa, rxout, &flags, di->rxbufsize); + } + rxout = NEXTRXD (rxout); + } + + di->rxout = rxout; + + /* update the chip lastdscr pointer */ + if (DMA64_ENAB (di)) + { + W_REG (di->osh, &di->d64rxregs->ptr, I2B (rxout, dma64dd_t)); + } + else + { + W_REG (di->osh, &di->d32rxregs->ptr, I2B (rxout, dma32dd_t)); + } +} - return (NULL); +/* like getnexttxp but no reclaim */ +static void * +_dma_peeknexttxp (dma_info_t * di) +{ + uint end, i; + + if (di->ntxd == 0) + return (NULL); + + if (DMA64_ENAB (di)) + { + end = + B2I (R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK, + dma64dd_t); + } + else + { + 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) +_dma_rxreclaim (dma_info_t * di) { - void *p; + void *p; - /* "unused local" warning suppression for OSLs that - * define PKTFREE() without using the di->osh arg - */ - di = di; + /* "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)); + DMA_TRACE (("%s: dma_rxreclaim\n", di->name)); - while ((p = _dma_getnextrxp(di, TRUE))) - PKTFREE(di->osh, p, FALSE); + while ((p = _dma_getnextrxp (di, TRUE))) + PKTFREE (di->osh, p, FALSE); } static void * -_dma_getnextrxp(dma_info_t *di, bool forceall) +_dma_getnextrxp (dma_info_t * di, bool forceall) { - if (di->nrxd == 0) - return (NULL); - - if (DMA64_ENAB(di)) { - return dma64_getnextrxp(di, forceall); - } else { - return dma32_getnextrxp(di, forceall); - } + if (di->nrxd == 0) + return (NULL); + + if (DMA64_ENAB (di)) + { + return dma64_getnextrxp (di, forceall); + } + else + { + return dma32_getnextrxp (di, forceall); + } } static void -_dma_txblock(dma_info_t *di) +_dma_txblock (dma_info_t * di) { - di->hnddma.txavail = 0; + di->hnddma.txavail = 0; } static void -_dma_txunblock(dma_info_t *di) +_dma_txunblock (dma_info_t * di) { - di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + di->hnddma.txavail = di->ntxd - NTXDACTIVE (di->txin, di->txout) - 1; } static uint -_dma_txactive(dma_info_t *di) +_dma_txactive (dma_info_t * di) { - return (NTXDACTIVE(di->txin, di->txout)); + return (NTXDACTIVE (di->txin, di->txout)); } static void -_dma_counterreset(dma_info_t *di) +_dma_counterreset (dma_info_t * di) { - /* reset all software counter */ - di->hnddma.rxgiants = 0; - di->hnddma.rxnobuf = 0; - di->hnddma.txnobuf = 0; + /* 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, const char *name) +_dma_getvar (dma_info_t * di, const char *name) { - if (!strcmp(name, "&txavail")) - return ((uintptr) &(di->hnddma.txavail)); - else { - ASSERT(0); - } - return (0); + if (!strcmp (name, "&txavail")) + return ((uintptr) & (di->hnddma.txavail)); + else + { + ASSERT (0); + } + return (0); } void -dma_txpioloopback(osl_t *osh, dma32regs_t *regs) +dma_txpioloopback (osl_t * osh, dma32regs_t * regs) { - OR_REG(osh, ®s->control, XC_LE); + OR_REG (osh, ®s->control, XC_LE); } +#ifdef BCMDBG +static void +dma32_dumpring (dma_info_t * di, struct bcmstrbuf *b, dma32dd_t * ring, + uint start, uint end, uint max_num) +{ + uint i; + + for (i = start; i != end; i = XXD ((i + 1), max_num)) + { + /* in the format of high->low 8 bytes */ + bcm_bprintf (b, "ring index %d: 0x%x %x\n", i, ring[i].addr, + ring[i].ctrl); + } +} + +static void +dma32_dumptx (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + if (di->ntxd == 0) + return; + + bcm_bprintf (b, "DMA32: txd32 %p txdpa 0x%lx txp %p txin %d txout %d " + "txavail %d\n", di->txd32, di->txdpa, di->txp, di->txin, + di->txout, di->hnddma.txavail); + + bcm_bprintf (b, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%x\n", + R_REG (di->osh, &di->d32txregs->control), + R_REG (di->osh, &di->d32txregs->addr), + R_REG (di->osh, &di->d32txregs->ptr), + R_REG (di->osh, &di->d32txregs->status)); + + if (dumpring && di->txd32) + dma32_dumpring (di, b, di->txd32, di->txin, di->txout, di->ntxd); +} + +static void +dma32_dumprx (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + if (di->nrxd == 0) + return; + + bcm_bprintf (b, "DMA32: rxd32 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", + di->rxd32, di->rxdpa, di->rxp, di->rxin, di->rxout); + + bcm_bprintf (b, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%x\n", + R_REG (di->osh, &di->d32rxregs->control), + R_REG (di->osh, &di->d32rxregs->addr), + R_REG (di->osh, &di->d32rxregs->ptr), + R_REG (di->osh, &di->d32rxregs->status)); + if (di->rxd32 && dumpring) + dma32_dumpring (di, b, di->rxd32, di->rxin, di->rxout, di->nrxd); +} + +static void +dma32_dump (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + dma32_dumptx (di, b, dumpring); + dma32_dumprx (di, b, dumpring); +} + +static void +dma64_dumpring (dma_info_t * di, struct bcmstrbuf *b, dma64dd_t * ring, + uint start, uint end, uint max_num) +{ + uint i; + + for (i = start; i != end; i = XXD ((i + 1), max_num)) + { + /* in the format of high->low 16 bytes */ + bcm_bprintf (b, "ring index %d: 0x%x %x %x %x\n", + i, ring[i].addrhigh, ring[i].addrlow, ring[i].ctrl2, + ring[i].ctrl1); + } +} + +static void +dma64_dumptx (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + if (di->ntxd == 0) + return; + + bcm_bprintf (b, "DMA64: txd64 %p txdpa 0x%lx txp %p txin %d txout %d " + "txavail %d\n", di->txd64, di->txdpa, di->txp, di->txin, + di->txout, di->hnddma.txavail); + + bcm_bprintf (b, "xmtcontrol 0x%x xmtaddrlow 0x%x xmtaddrhigh 0x%x " + "xmtptr 0x%x xmtstatus0 0x%x xmtstatus1 0x%x\n", + R_REG (di->osh, &di->d64txregs->control), + R_REG (di->osh, &di->d64txregs->addrlow), + R_REG (di->osh, &di->d64txregs->addrhigh), + R_REG (di->osh, &di->d64txregs->ptr), + R_REG (di->osh, &di->d64txregs->status0), + R_REG (di->osh, &di->d64txregs->status1)); + + if (dumpring && di->txd64) + { + dma64_dumpring (di, b, di->txd64, di->txin, di->txout, di->ntxd); + } +} + +static void +dma64_dumprx (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + if (di->nrxd == 0) + return; + + bcm_bprintf (b, "DMA64: rxd64 %p rxdpa 0x%lx rxp %p rxin %d rxout %d\n", + di->rxd64, di->rxdpa, di->rxp, di->rxin, di->rxout); + + bcm_bprintf (b, "rcvcontrol 0x%x rcvaddrlow 0x%x rcvaddrhigh 0x%x rcvptr " + "0x%x rcvstatus0 0x%x rcvstatus1 0x%x\n", + R_REG (di->osh, &di->d64rxregs->control), + R_REG (di->osh, &di->d64rxregs->addrlow), + R_REG (di->osh, &di->d64rxregs->addrhigh), + R_REG (di->osh, &di->d64rxregs->ptr), + R_REG (di->osh, &di->d64rxregs->status0), + R_REG (di->osh, &di->d64rxregs->status1)); + if (di->rxd64 && dumpring) + { + dma64_dumpring (di, b, di->rxd64, di->rxin, di->rxout, di->nrxd); + } +} + +static void +dma64_dump (dma_info_t * di, struct bcmstrbuf *b, bool dumpring) +{ + dma64_dumptx (di, b, dumpring); + dma64_dumprx (di, b, dumpring); +} + +#endif /* BCMDBG */ /* 32 bits DMA functions */ static void -dma32_txinit(dma_info_t *di) +dma32_txinit (dma_info_t * di) { - DMA_TRACE(("%s: dma_txinit\n", di->name)); + DMA_TRACE (("%s: dma_txinit\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - di->txin = di->txout = 0; - di->hnddma.txavail = di->ntxd - 1; + di->txin = di->txout = 0; + di->hnddma.txavail = di->ntxd - 1; - /* clear tx descriptor ring */ - BZERO_SM((void *)(uintptr)di->txd32, (di->ntxd * sizeof(dma32dd_t))); - W_REG(di->osh, &di->d32txregs->control, XC_XE); - _dma_ddtable_init(di, DMA_TX, di->txdpa); + /* clear tx descriptor ring */ + BZERO_SM ((void *) (uintptr) 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) +dma32_txenabled (dma_info_t * di) { - uint32 xc; + 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)); + /* 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) +dma32_txsuspend (dma_info_t * di) { - DMA_TRACE(("%s: dma_txsuspend\n", di->name)); + DMA_TRACE (("%s: dma_txsuspend\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - OR_REG(di->osh, &di->d32txregs->control, XC_SE); + OR_REG (di->osh, &di->d32txregs->control, XC_SE); } static void -dma32_txresume(dma_info_t *di) +dma32_txresume (dma_info_t * di) { - DMA_TRACE(("%s: dma_txresume\n", di->name)); + DMA_TRACE (("%s: dma_txresume\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - AND_REG(di->osh, &di->d32txregs->control, ~XC_SE); + AND_REG (di->osh, &di->d32txregs->control, ~XC_SE); } static bool -dma32_txsuspended(dma_info_t *di) +dma32_txsuspended (dma_info_t * di) { - return (di->ntxd == 0) || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE); + 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) +dma32_txreclaim (dma_info_t * di, bool forceall) { - void *p; + void *p; - DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + DMA_TRACE (("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); - while ((p = dma32_getnexttxp(di, forceall))) - PKTFREE(di->osh, p, TRUE); + while ((p = dma32_getnexttxp (di, forceall))) + PKTFREE (di->osh, p, TRUE); } static bool -dma32_txstopped(dma_info_t *di) +dma32_txstopped (dma_info_t * di) { - return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) == XS_XS_STOPPED); + return ((R_REG (di->osh, &di->d32txregs->status) & XS_XS_MASK) == + XS_XS_STOPPED); } static bool -dma32_rxstopped(dma_info_t *di) +dma32_rxstopped (dma_info_t * di) { - return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) == RS_RS_STOPPED); + 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*)(uintptr)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*)(uintptr)di->rxd32 - (int8*)va); - di->rxdpa += di->rxdalign; - di->rxdalloc = size; - ASSERT(ISALIGNED((uintptr)di->rxd32, D32RINGALIGN)); +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; } - return TRUE; + di->txd32 = (dma32dd_t *) ROUNDUP ((uintptr) va, D32RINGALIGN); + di->txdalign = (uint) ((int8 *) (uintptr) 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 *) (uintptr) 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) +dma32_txreset (dma_info_t * di) { - uint32 status; + uint32 status; - if (di->ntxd == 0) - return TRUE; + 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)); + /* 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); + 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); + /* wait for the last transaction to complete */ + OSL_DELAY (300); - return (status == XS_XS_DISABLED); + return (status == XS_XS_DISABLED); } static bool -dma32_rxidle(dma_info_t *di) +dma32_rxidle (dma_info_t * di) { - DMA_TRACE(("%s: dma_rxidle\n", di->name)); + DMA_TRACE (("%s: dma_rxidle\n", di->name)); - if (di->nrxd == 0) - return TRUE; + if (di->nrxd == 0) + return TRUE; - return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) == - R_REG(di->osh, &di->d32rxregs->ptr)); + 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) +dma32_rxreset (dma_info_t * di) { - uint32 status; + uint32 status; - if (di->nrxd == 0) - return TRUE; + 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); + 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); + return (status == RS_RS_DISABLED); } static bool -dma32_rxenabled(dma_info_t *di) +dma32_rxenabled (dma_info_t * di) { - uint32 rc; + uint32 rc; - rc = R_REG(di->osh, &di->d32rxregs->control); - return ((rc != 0xffffffff) && (rc & RC_RE)); + rc = R_REG (di->osh, &di->d32rxregs->control); + return ((rc != 0xffffffff) && (rc & RC_RE)); } static bool -dma32_txsuspendedidle(dma_info_t *di) +dma32_txsuspendedidle (dma_info_t * di) { - if (di->ntxd == 0) - return TRUE; + 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->control) & XC_SE)) + return 0; - if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE) - 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); + OSL_DELAY (2); + return ((R_REG (di->osh, &di->d32txregs->status) & XS_XS_MASK) == + XS_XS_IDLE); } /* !! tx entry routine @@ -1171,77 +1518,81 @@ dma32_txsuspendedidle(dma_info_t *di) * 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); - } +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, + &di->txp_dmah[txout]); + + flags = 0; + if (p == p0) + flags |= CTRL_SOF; + if (next == NULL) + flags |= (CTRL_IOC | CTRL_EOF); + if (txout == (di->ntxd - 1)) + flags |= CTRL_EOT; - /* 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)); + dma32_dd_upd (di, di->txd32, pa, txout, &flags, len); + ASSERT (di->txp[txout] == NULL); - /* save the packet */ - di->txp[PREVTXD(txout)] = p0; + txout = NEXTTXD (txout); + } - /* bump the tx descriptor index */ - di->txout = 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)); - /* kick the chip */ - if (commit) - W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t)); + /* save the packet */ + di->txp[PREVTXD (txout)] = p0; - /* tx flow control */ - di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + /* bump the tx descriptor index */ + di->txout = txout; - return (0); + /* 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); + 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); } /* @@ -1251,431 +1602,456 @@ outoftxd: * regardless of the value of the hardware "curr" pointer. */ static void * -dma32_getnexttxp(dma_info_t *di, bool forceall) +dma32_getnexttxp (dma_info_t * di, bool forceall) { - uint start, end, i; - void *txp; + uint start, end, i; + void *txp; - DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + DMA_TRACE (("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); - if (di->ntxd == 0) - return (NULL); + if (di->ntxd == 0) + return (NULL); - txp = 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); + 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; + 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]); + 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], &di->txp_dmah[i]); - W_SM(&di->txd32[i].addr, 0xdeadbeef); - txp = di->txp[i]; - di->txp[i] = NULL; - } + W_SM (&di->txd32[i].addr, 0xdeadbeef); + txp = di->txp[i]; + di->txp[i] = NULL; + } - di->txin = i; + di->txin = i; - /* tx flow control */ - di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + /* tx flow control */ + di->hnddma.txavail = di->ntxd - NTXDACTIVE (di->txin, di->txout) - 1; - return (txp); + 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); + return (NULL); } static void * -dma32_getnextrxp(dma_info_t *di, bool forceall) +dma32_getnextrxp (dma_info_t * di, bool forceall) { - uint i; - void *rxp; + uint i; + void *rxp; - /* if forcing, dma engine must be disabled */ - ASSERT(!forceall || !dma32_rxenabled(di)); + /* if forcing, dma engine must be disabled */ + ASSERT (!forceall || !dma32_rxenabled (di)); - i = di->rxin; + i = di->rxin; - /* return if no packets posted */ - if (i == di->rxout) - return (NULL); + /* 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); + /* 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; + /* 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); + /* 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, &di->rxp_dmah[i]); - W_SM(&di->rxd32[i].addr, 0xdeadbeef); + W_SM (&di->rxd32[i].addr, 0xdeadbeef); - di->rxin = NEXTRXD(i); + di->rxin = NEXTRXD (i); - return (rxp); + return (rxp); } /* * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). */ static void -dma32_txrotate(dma_info_t *di) +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 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)); } /* 64 bits DMA functions */ #ifdef BCMDMA64 static void -dma64_txinit(dma_info_t *di) +dma64_txinit (dma_info_t * di) { - DMA_TRACE(("%s: dma_txinit\n", di->name)); + DMA_TRACE (("%s: dma_txinit\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - di->txin = di->txout = 0; - di->hnddma.txavail = di->ntxd - 1; + di->txin = di->txout = 0; + di->hnddma.txavail = di->ntxd - 1; - /* clear tx descriptor ring */ - BZERO_SM((void *)(uintptr)di->txd64, (di->ntxd * sizeof(dma64dd_t))); - W_REG(di->osh, &di->d64txregs->control, D64_XC_XE); - _dma_ddtable_init(di, DMA_TX, di->txdpa); + /* clear tx descriptor ring */ + BZERO_SM ((void *) (uintptr) di->txd64, (di->ntxd * sizeof (dma64dd_t))); + W_REG (di->osh, &di->d64txregs->control, D64_XC_XE); + _dma_ddtable_init (di, DMA_TX, di->txdpa); } static bool -dma64_txenabled(dma_info_t *di) +dma64_txenabled (dma_info_t * di) { - uint32 xc; + uint32 xc; - /* If the chip is dead, it is not enabled :-) */ - xc = R_REG(di->osh, &di->d64txregs->control); - return ((xc != 0xffffffff) && (xc & D64_XC_XE)); + /* If the chip is dead, it is not enabled :-) */ + xc = R_REG (di->osh, &di->d64txregs->control); + return ((xc != 0xffffffff) && (xc & D64_XC_XE)); } static void -dma64_txsuspend(dma_info_t *di) +dma64_txsuspend (dma_info_t * di) { - DMA_TRACE(("%s: dma_txsuspend\n", di->name)); + DMA_TRACE (("%s: dma_txsuspend\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE); + OR_REG (di->osh, &di->d64txregs->control, D64_XC_SE); } static void -dma64_txresume(dma_info_t *di) +dma64_txresume (dma_info_t * di) { - DMA_TRACE(("%s: dma_txresume\n", di->name)); + DMA_TRACE (("%s: dma_txresume\n", di->name)); - if (di->ntxd == 0) - return; + if (di->ntxd == 0) + return; - AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE); + AND_REG (di->osh, &di->d64txregs->control, ~D64_XC_SE); } static bool -dma64_txsuspended(dma_info_t *di) +dma64_txsuspended (dma_info_t * di) { - return (di->ntxd == 0) || ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) - == D64_XC_SE); + return (di->ntxd == 0) + || ((R_REG (di->osh, &di->d64txregs->control) & D64_XC_SE) == D64_XC_SE); } static void -dma64_txreclaim(dma_info_t *di, bool forceall) +dma64_txreclaim (dma_info_t * di, bool forceall) { - void *p; + void *p; - DMA_TRACE(("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); + DMA_TRACE (("%s: dma_txreclaim %s\n", di->name, forceall ? "all" : "")); - while ((p = dma64_getnexttxp(di, forceall))) - PKTFREE(di->osh, p, TRUE); + while ((p = dma64_getnexttxp (di, forceall))) + PKTFREE (di->osh, p, TRUE); } static bool -dma64_txstopped(dma_info_t *di) +dma64_txstopped (dma_info_t * di) { - return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_STOPPED); + return ((R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == + D64_XS0_XS_STOPPED); } static bool -dma64_rxstopped(dma_info_t *di) +dma64_rxstopped (dma_info_t * di) { - return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == D64_RS0_RS_STOPPED); + return ((R_REG (di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) == + D64_RS0_RS_STOPPED); } static bool -dma64_alloc(dma_info_t *di, uint direction) -{ - uint size; - uint ddlen; - uint32 alignbytes; - void *va; - - ddlen = sizeof(dma64dd_t); - - size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); - - alignbytes = di->dma64align; - - if (!ISALIGNED(DMA_CONSISTENT_ALIGN, alignbytes)) - size += alignbytes; - - 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->txd64 = (dma64dd_t *) ROUNDUP((uintptr)va, alignbytes); - di->txdalign = (uint)((int8*)(uintptr)di->txd64 - (int8*)va); - di->txdpa += di->txdalign; - di->txdalloc = size; - ASSERT(ISALIGNED((uintptr)di->txd64, alignbytes)); - } 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->rxd64 = (dma64dd_t *) ROUNDUP((uintptr)va, alignbytes); - di->rxdalign = (uint)((int8*)(uintptr)di->rxd64 - (int8*)va); - di->rxdpa += di->rxdalign; - di->rxdalloc = size; - ASSERT(ISALIGNED((uintptr)di->rxd64, alignbytes)); +dma64_alloc (dma_info_t * di, uint direction) +{ + uint size; + uint ddlen; + uint32 alignbytes; + void *va; + + ddlen = sizeof (dma64dd_t); + + size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen); + + alignbytes = di->dma64align; + + if (!ISALIGNED (DMA_CONSISTENT_ALIGN, alignbytes)) + size += alignbytes; + + 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; } - return TRUE; + di->txd64 = (dma64dd_t *) ROUNDUP ((uintptr) va, alignbytes); + di->txdalign = (uint) ((int8 *) (uintptr) di->txd64 - (int8 *) va); + di->txdpa += di->txdalign; + di->txdalloc = size; + ASSERT (ISALIGNED ((uintptr) di->txd64, alignbytes)); + } + 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->rxd64 = (dma64dd_t *) ROUNDUP ((uintptr) va, alignbytes); + di->rxdalign = (uint) ((int8 *) (uintptr) di->rxd64 - (int8 *) va); + di->rxdpa += di->rxdalign; + di->rxdalloc = size; + ASSERT (ISALIGNED ((uintptr) di->rxd64, alignbytes)); + } + + return TRUE; } static bool -dma64_txreset(dma_info_t *di) +dma64_txreset (dma_info_t * di) { - uint32 status; + uint32 status; - if (di->ntxd == 0) - return TRUE; + if (di->ntxd == 0) + return TRUE; - /* suspend tx DMA first */ - W_REG(di->osh, &di->d64txregs->control, D64_XC_SE); - SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != - D64_XS0_XS_DISABLED) && - (status != D64_XS0_XS_IDLE) && - (status != D64_XS0_XS_STOPPED), - 10000); + /* suspend tx DMA first */ + W_REG (di->osh, &di->d64txregs->control, D64_XC_SE); + SPINWAIT (((status = + (R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != + D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE) + && (status != D64_XS0_XS_STOPPED), 10000); - W_REG(di->osh, &di->d64txregs->control, 0); - SPINWAIT(((status = (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != - D64_XS0_XS_DISABLED), - 10000); + W_REG (di->osh, &di->d64txregs->control, 0); + SPINWAIT (((status = + (R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK)) != + D64_XS0_XS_DISABLED), 10000); - /* wait for the last transaction to complete */ - OSL_DELAY(300); + /* wait for the last transaction to complete */ + OSL_DELAY (300); - return (status == D64_XS0_XS_DISABLED); + return (status == D64_XS0_XS_DISABLED); } static bool -dma64_rxidle(dma_info_t *di) +dma64_rxidle (dma_info_t * di) { - DMA_TRACE(("%s: dma_rxidle\n", di->name)); + DMA_TRACE (("%s: dma_rxidle\n", di->name)); - if (di->nrxd == 0) - return TRUE; + if (di->nrxd == 0) + return TRUE; - return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == - R_REG(di->osh, &di->d64rxregs->ptr)); + return ((R_REG (di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) == + R_REG (di->osh, &di->d64rxregs->ptr)); } static bool -dma64_rxreset(dma_info_t *di) +dma64_rxreset (dma_info_t * di) { - uint32 status; + uint32 status; - if (di->nrxd == 0) - return TRUE; + if (di->nrxd == 0) + return TRUE; - W_REG(di->osh, &di->d64rxregs->control, 0); - SPINWAIT(((status = (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != - D64_RS0_RS_DISABLED), - 10000); + W_REG (di->osh, &di->d64rxregs->control, 0); + SPINWAIT (((status = + (R_REG (di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK)) != + D64_RS0_RS_DISABLED), 10000); - return (status == D64_RS0_RS_DISABLED); + return (status == D64_RS0_RS_DISABLED); } static bool -dma64_rxenabled(dma_info_t *di) +dma64_rxenabled (dma_info_t * di) { - uint32 rc; + uint32 rc; - rc = R_REG(di->osh, &di->d64rxregs->control); - return ((rc != 0xffffffff) && (rc & D64_RC_RE)); + rc = R_REG (di->osh, &di->d64rxregs->control); + return ((rc != 0xffffffff) && (rc & D64_RC_RE)); } static bool -dma64_txsuspendedidle(dma_info_t *di) +dma64_txsuspendedidle (dma_info_t * di) { - if (di->ntxd == 0) - return TRUE; + if (di->ntxd == 0) + return TRUE; - if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE)) - return 0; + if (!(R_REG (di->osh, &di->d64txregs->control) & D64_XC_SE)) + return 0; - if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == D64_XS0_XS_IDLE) - return 1; + if ((R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) == + D64_XS0_XS_IDLE) + return 1; - return 0; + return 0; } /* !! tx entry routine */ static int -dma64_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 |= D64_CTRL1_SOF; - if (next == NULL) - flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); - if (txout == (di->ntxd - 1)) - flags |= D64_CTRL1_EOT; - - dma64_dd_upd(di, di->txd64, pa, txout, &flags, len); - ASSERT(di->txp[txout] == NULL); - - txout = NEXTTXD(txout); - } +dma64_txfast (dma_info_t * di, void *p0, bool commit) +{ + void *p, *next; + uchar *data; + uint len; + uint txout; + uint32 flags = 0; + uint32 pa; - /* if last txd eof not set, fix it */ - if (!(flags & D64_CTRL1_EOF)) - W_SM(&di->txd64[PREVTXD(txout)].ctrl1, - BUS_SWAP32(flags | D64_CTRL1_IOC | D64_CTRL1_EOF)); + DMA_TRACE (("%s: dma_txfast\n", di->name)); - /* save the packet */ - di->txp[PREVTXD(txout)] = p0; + txout = di->txout; - /* bump the tx descriptor index */ - di->txout = 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); - /* kick the chip */ - if (commit) - W_REG(di->osh, &di->d64txregs->ptr, I2B(txout, dma64dd_t)); + /* return nonzero if out of tx descriptors */ + if (NEXTTXD (txout) == di->txin) + goto outoftxd; - /* tx flow control */ - di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + if (len == 0) + continue; - return (0); + /* get physical address of buffer start */ + pa = + (uint32) DMA_MAP (di->osh, data, len, DMA_TX, p, + &di->txp_dmah[txout]); + + flags = 0; + if (p == p0) + flags |= D64_CTRL1_SOF; + if (next == NULL) + flags |= (D64_CTRL1_IOC | D64_CTRL1_EOF); + if (txout == (di->ntxd - 1)) + flags |= D64_CTRL1_EOT; + + dma64_dd_upd (di, di->txd64, pa, txout, &flags, len); + ASSERT (di->txp[txout] == NULL); + + txout = NEXTTXD (txout); + } + + /* if last txd eof not set, fix it */ + if (!(flags & D64_CTRL1_EOF)) + W_SM (&di->txd64[PREVTXD (txout)].ctrl1, + BUS_SWAP32 (flags | D64_CTRL1_IOC | D64_CTRL1_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->d64txregs->ptr, I2B (txout, dma64dd_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); + 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); } /* @@ -1685,209 +2061,221 @@ outoftxd: * regardless of the value of the hardware "curr" pointer. */ static void * -dma64_getnexttxp(dma_info_t *di, bool forceall) +dma64_getnexttxp (dma_info_t * di, bool forceall) { - uint start, end, i; - void *txp; + uint start, end, i; + void *txp; - DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); + DMA_TRACE (("%s: dma_getnexttxp %s\n", di->name, forceall ? "all" : "")); - if (di->ntxd == 0) - return (NULL); + if (di->ntxd == 0) + return (NULL); - txp = NULL; + txp = NULL; - start = di->txin; - if (forceall) - end = di->txout; - else - end = B2I(R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK, dma64dd_t); + start = di->txin; + if (forceall) + end = di->txout; + else + end = + B2I (R_REG (di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK, + dma64dd_t); - if ((start == 0) && (end > di->txout)) - goto bogus; + 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->txd64[i].addrlow)) - di->dataoffsetlow), - (BUS_SWAP32(R_SM(&di->txd64[i].ctrl2)) & D64_CTRL2_BC_MASK), - DMA_TX, di->txp[i]); + for (i = start; i != end && !txp; i = NEXTTXD (i)) + { + DMA_UNMAP (di->osh, + (BUS_SWAP32 (R_SM (&di->txd64[i].addrlow)) - + di->dataoffsetlow), + (BUS_SWAP32 (R_SM (&di->txd64[i].ctrl2)) & + D64_CTRL2_BC_MASK), DMA_TX, di->txp[i], &di->txp_dmah[i]); - W_SM(&di->txd64[i].addrlow, 0xdeadbeef); - W_SM(&di->txd64[i].addrhigh, 0xdeadbeef); + W_SM (&di->txd64[i].addrlow, 0xdeadbeef); + W_SM (&di->txd64[i].addrhigh, 0xdeadbeef); - txp = di->txp[i]; - di->txp[i] = NULL; - } + txp = di->txp[i]; + di->txp[i] = NULL; + } - di->txin = i; + di->txin = i; - /* tx flow control */ - di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; + /* tx flow control */ + di->hnddma.txavail = di->ntxd - NTXDACTIVE (di->txin, di->txout) - 1; - return (txp); + 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); + return (NULL); } static void * -dma64_getnextrxp(dma_info_t *di, bool forceall) +dma64_getnextrxp (dma_info_t * di, bool forceall) { - uint i; - void *rxp; + uint i; + void *rxp; - /* if forcing, dma engine must be disabled */ - ASSERT(!forceall || !dma64_rxenabled(di)); + /* if forcing, dma engine must be disabled */ + ASSERT (!forceall || !dma64_rxenabled (di)); - i = di->rxin; + i = di->rxin; - /* return if no packets posted */ - if (i == di->rxout) - return (NULL); + /* return if no packets posted */ + if (i == di->rxout) + return (NULL); - /* ignore curr if forceall */ - if (!forceall && - (i == B2I(R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK, dma64dd_t))) - return (NULL); + /* ignore curr if forceall */ + if (!forceall && + (i == + B2I (R_REG (di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK, + dma64dd_t))) + return (NULL); - /* get the packet pointer that corresponds to the rx descriptor */ - rxp = di->rxp[i]; - ASSERT(rxp); - di->rxp[i] = 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->rxd64[i].addrlow)) - di->dataoffsetlow), - di->rxbufsize, DMA_RX, rxp); + /* clear this packet from the descriptor ring */ + DMA_UNMAP (di->osh, + (BUS_SWAP32 (R_SM (&di->rxd64[i].addrlow)) - di->dataoffsetlow), + di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]); - W_SM(&di->rxd64[i].addrlow, 0xdeadbeef); - W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef); + W_SM (&di->rxd64[i].addrlow, 0xdeadbeef); + W_SM (&di->rxd64[i].addrhigh, 0xdeadbeef); - di->rxin = NEXTRXD(i); + di->rxin = NEXTRXD (i); - return (rxp); + return (rxp); } static bool -_dma64_addrext(osl_t *osh, dma64regs_t *dma64regs) +_dma64_addrext (osl_t * osh, dma64regs_t * dma64regs) { - uint32 w; - OR_REG(osh, &dma64regs->control, D64_XC_AE); - w = R_REG(osh, &dma64regs->control); - AND_REG(osh, &dma64regs->control, ~D64_XC_AE); - return ((w & D64_XC_AE) == D64_XC_AE); + uint32 w; + OR_REG (osh, &dma64regs->control, D64_XC_AE); + w = R_REG (osh, &dma64regs->control); + AND_REG (osh, &dma64regs->control, ~D64_XC_AE); + return ((w & D64_XC_AE) == D64_XC_AE); } /* * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin). */ static void -dma64_txrotate(dma_info_t *di) +dma64_txrotate (dma_info_t * di) { - uint ad; - uint nactive; - uint rot; - uint old, new; - uint32 w; - uint first, last; - - ASSERT(dma64_txsuspendedidle(di)); - - nactive = _dma_txactive(di); - ad = B2I((R_REG(di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK), dma64dd_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->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; - if (new == (di->ntxd - 1)) - w |= D64_CTRL1_EOT; - W_SM(&di->txd64[new].ctrl1, BUS_SWAP32(w)); - - w = BUS_SWAP32(R_SM(&di->txd64[old].ctrl2)); - W_SM(&di->txd64[new].ctrl2, BUS_SWAP32(w)); - - W_SM(&di->txd64[new].addrlow, R_SM(&di->txd64[old].addrlow)); - W_SM(&di->txd64[new].addrhigh, R_SM(&di->txd64[old].addrhigh)); - - /* zap the old tx dma descriptor address field */ - W_SM(&di->txd64[old].addrlow, BUS_SWAP32(0xdeadbeef)); - W_SM(&di->txd64[old].addrhigh, 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->d64txregs->ptr, I2B(di->txout, dma64dd_t)); + uint ad; + uint nactive; + uint rot; + uint old, new; + uint32 w; + uint first, last; + + ASSERT (dma64_txsuspendedidle (di)); + + nactive = _dma_txactive (di); + ad = + B2I ((R_REG (di->osh, &di->d64txregs->status1) & D64_XS1_AD_MASK), + dma64dd_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->txd64[old].ctrl1)) & ~D64_CTRL1_EOT; + if (new == (di->ntxd - 1)) + w |= D64_CTRL1_EOT; + W_SM (&di->txd64[new].ctrl1, BUS_SWAP32 (w)); + + w = BUS_SWAP32 (R_SM (&di->txd64[old].ctrl2)); + W_SM (&di->txd64[new].ctrl2, BUS_SWAP32 (w)); + + W_SM (&di->txd64[new].addrlow, R_SM (&di->txd64[old].addrlow)); + W_SM (&di->txd64[new].addrhigh, R_SM (&di->txd64[old].addrhigh)); + + /* zap the old tx dma descriptor address field */ + W_SM (&di->txd64[old].addrlow, BUS_SWAP32 (0xdeadbeef)); + W_SM (&di->txd64[old].addrhigh, 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->d64txregs->ptr, I2B (di->txout, dma64dd_t)); } -#endif /* BCMDMA64 */ +#endif /* BCMDMA64 */ uint -dma_addrwidth(sb_t *sbh, void *dmaregs) -{ - dma32regs_t *dma32regs; - osl_t *osh; - - osh = sb_osh(sbh); - - if (DMA64_CAP) { - /* DMA engine is 64-bit capable */ - if (((sb_coreflagshi(sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64)) { - /* backplane are 64 bits capable */ -#if 0 - if (sb_backplane64(sbh)) - /* If bus is System Backplane or PCIE then we can access 64-bits */ - if ((BUSTYPE(sbh->bustype) == SB_BUS) || - ((BUSTYPE(sbh->bustype) == PCI_BUS) && - sbh->buscoretype == SB_PCIE)) - return (DMADDRWIDTH_64); -#endif - - /* DMA64 is always 32 bits capable, AE is always TRUE */ +dma_addrwidth (sb_t * sbh, void *dmaregs) +{ + dma32regs_t *dma32regs; + osl_t *osh; + + osh = sb_osh (sbh); + + if (DMA64_CAP) + { + /* DMA engine is 64-bit capable */ + if (((sb_coreflagshi (sbh, 0, 0) & SBTMH_DMA64) == SBTMH_DMA64)) + { + /* backplane are 64 bits capable */ + if (sb_backplane64 (sbh)) + /* If bus is System Backplane or PCIE then we can access 64-bits */ + if ((BUSTYPE (sbh->bustype) == SB_BUS) || + ((BUSTYPE (sbh->bustype) == PCI_BUS) && + sbh->buscoretype == SB_PCIE)) + return (DMADDRWIDTH_64); + + /* DMA64 is always 32 bits capable, AE is always TRUE */ #ifdef BCMDMA64 - ASSERT(_dma64_addrext(osh, (dma64regs_t *)dmaregs)); + ASSERT (_dma64_addrext (osh, (dma64regs_t *) dmaregs)); #endif - return (DMADDRWIDTH_32); - } + return (DMADDRWIDTH_32); } + } - /* Start checking for 32-bit / 30-bit addressing */ - dma32regs = (dma32regs_t *)dmaregs; + /* 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); + /* 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); + /* Fallthru */ + return (DMADDRWIDTH_30); } diff --git a/package/broadcom-wl/src/driver/hnddma.h b/package/broadcom-wl/src/driver/hnddma.h index de74c067b2..8d1b5acb6b 100644 --- a/package/broadcom-wl/src/driver/hnddma.h +++ b/package/broadcom-wl/src/driver/hnddma.h @@ -2,14 +2,14 @@ * Generic Broadcom Home Networking Division (HND) DMA engine SW interface * This supports the following chips: BCM42xx, 44xx, 47xx . * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, 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 $ + * $Id$ */ #ifndef _hnddma_h_ @@ -39,7 +39,7 @@ 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 uintptr (*di_getvar_t)(hnddma_t *dmah, const 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); @@ -141,8 +141,12 @@ extern hnddma_t * dma_attach(osl_t *osh, char *name, sb_t *sbh, void *dmaregstx, #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)) +#ifdef BCMDBG +#define dma_dump(di, buf, dumpring) ((di)->di_fn.dump(di, buf, dumpring)) +#define dma_dumptx(di, buf, dumpring) ((di)->di_fn.dumptx(di, buf, dumpring)) +#define dma_dumprx(di, buf, dumpring) ((di)->di_fn.dumprx(di, buf, dumpring)) +#endif -#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 diff --git a/package/broadcom-wl/src/driver/linux_osl.c b/package/broadcom-wl/src/driver/linux_osl.c index 24fd77daea..cc55eb68e9 100644 --- a/package/broadcom-wl/src/driver/linux_osl.c +++ b/package/broadcom-wl/src/driver/linux_osl.c @@ -1,7 +1,7 @@ /* * Linux OS Independent Layer * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,266 +9,882 @@ * 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 $ + * $Id$ */ #define LINUX_OSL #include <typedefs.h> #include <bcmendian.h> -#include <linux/module.h> #include <linuxver.h> #include <bcmdefs.h> #include <osl.h> #include "linux_osl.h" -#include <bcmutils.h> +#include "bcmutils.h" #include <linux/delay.h> #ifdef mips #include <asm/paccess.h> #endif /* mips */ #include <pcicfg.h> -#define PCI_CFG_RETRY 10 +#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]; +#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 */ +#if 0 +struct osl_info +{ + osl_pubinfo_t pub; + uint magic; + void *pdev; + uint malloced; + uint failed; + uint bustype; + bcm_mem_link_t *dbgmem_list; +#ifdef BCMDBG_PKT /* pkt logging for debugging */ + pktlist_info_t pktlist; +#endif /* BCMDBG_PKT */ +}; +#endif + +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 */ + -EINVAL /* BCME_VERSION */ +/* When an new error code is added to bcmutils.h, add os + * spcecific error translation here as well + */ +/* check if BCME_LAST changed since the last time this function was updated */ +#if BCME_LAST != -37 +#error "You need to add a OS error translation in the linuxbcmerrormap \ + for new error code defined in bcmuitls.h" +#endif /* BCME_LAST != -37 */ }; /* translate bcmerrors into linux errors */ int -osl_error(int bcmerror) +osl_error (int bcmerror) { - int abs_bcmerror; - int array_size = ARRAYSIZE(linuxbcmerrormap); + if (bcmerror > 0) + bcmerror = 0; + else if (bcmerror < BCME_LAST) + bcmerror = BCME_ERROR; - abs_bcmerror = ABS(bcmerror); + /* Array bounds covered by ASSERT in osl_attach */ + return linuxbcmerrormap[-bcmerror]; +} - if (bcmerror > 0) - abs_bcmerror = 0; +osl_t * +osl_attach (void *pdev, uint bustype, bool pkttag) +{ + osl_t *osh; + + osh = kmalloc (sizeof (osl_t), GFP_ATOMIC); + ASSERT (osh); + + bzero (osh, sizeof (osl_t)); + + /* Check that error map has the right number of entries in it */ + 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; + osh->bustype = bustype; + + switch (bustype) + { + case PCI_BUS: + case SB_BUS: + case PCMCIA_BUS: + osh->pub.mmbus = TRUE; + break; + case JTAG_BUS: + case SDIO_BUS: + break; + default: + ASSERT (FALSE); + break; + } + +#ifdef BCMDBG + if (pkttag) + { + struct sk_buff *skb; + ASSERT (OSL_PKTTAG_SZ <= sizeof (skb->cb)); + } +#endif + return osh; +} - else if (abs_bcmerror >= array_size) - abs_bcmerror = BCME_ERROR; +void +osl_detach (osl_t * osh) +{ + if (osh == NULL) + return; - return linuxbcmerrormap[abs_bcmerror]; + ASSERT (osh->magic == OS_HANDLE_MAGIC); + kfree (osh); } -osl_t * -osl_attach(void *pdev, bool pkttag) +/* Return a new packet. zero out pkttag */ +void * +osl_pktget (osl_t * osh, uint len) +{ + 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, bool send) +{ + struct sk_buff *skb, *nskb; + + skb = (struct sk_buff *) p; + + if (send && osh->pub.tx_fn) + osh->pub.tx_fn (osh->pub.tx_ctx, p, 0); + + /* 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; + } +} + +uint32 +osl_pci_read_config (osl_t * osh, uint offset, uint size) { - osl_t *osh; + uint val; + uint retry = PCI_CFG_RETRY; - osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); - ASSERT(osh); + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); - bzero(osh, sizeof(osl_t)); + /* only 4byte access supported */ + ASSERT (size == 4); - /* - * 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)); + do + { + pci_read_config_dword (osh->pdev, offset, &val); + if (val != 0xffffffff) + break; + } + while (retry--); - osh->magic = OS_HANDLE_MAGIC; - osh->malloced = 0; - osh->failed = 0; - osh->dbgmem_list = NULL; - osh->pdev = pdev; - osh->pub.pkttag = pkttag; +#ifdef BCMDBG + if (retry < PCI_CFG_RETRY) + printk ("PCI CONFIG READ access to %d required %d retries\n", offset, + (PCI_CFG_RETRY - retry)); +#endif /* BCMDBG */ - return osh; + return (val); } void -osl_detach(osl_t *osh) +osl_pci_write_config (osl_t * osh, uint offset, uint size, uint val) { - if (osh == NULL) - return; + uint retry = PCI_CFG_RETRY; + + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + + /* only 4byte access supported */ + ASSERT (size == 4); + + do + { + pci_write_config_dword (osh->pdev, offset, val); + if (offset != PCI_BAR0_WIN) + break; + if (osl_pci_read_config (osh, offset, size) == val) + break; + } + while (retry--); + +#ifdef BCMDBG + if (retry < PCI_CFG_RETRY) + printk ("PCI CONFIG WRITE access to %d required %d retries\n", offset, + (PCI_CFG_RETRY - retry)); +#endif /* BCMDBG */ +} - ASSERT(osh->magic == OS_HANDLE_MAGIC); - kfree(osh); +/* return bus # for the pci device pointed by osh->pdev */ +uint +osl_pci_bus (osl_t * osh) +{ + ASSERT (osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); + + return ((struct pci_dev *) osh->pdev)->bus->number; } -/* Return a new packet. zero out pkttag */ -void* -osl_pktget(osl_t *osh, uint len, bool send) +/* return slot # for the pci device pointed by osh->pdev */ +uint +osl_pci_slot (osl_t * osh) { - struct sk_buff *skb; + ASSERT (osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); - if ((skb = dev_alloc_skb(len))) { - skb_put(skb, len); - skb->priority = 0; + return PCI_SLOT (((struct pci_dev *) osh->pdev)->devfn); +} -#ifdef BCMDBG_PKT - pktlist_add(&(osh->pktlist), (void *) skb); -#endif /* BCMDBG_PKT */ +static void +osl_pcmcia_attr (osl_t * osh, uint offset, char *buf, int size, bool write) +{ +} - osh->pub.pktalloced++; - } +void +osl_pcmcia_read_attr (osl_t * osh, uint offset, void *buf, int size) +{ + osl_pcmcia_attr (osh, offset, (char *) buf, size, FALSE); +} + +void +osl_pcmcia_write_attr (osl_t * osh, uint offset, void *buf, int size) +{ + osl_pcmcia_attr (osh, offset, (char *) buf, size, TRUE); +} + + +#ifdef BCMDBG_MEM + +void * +osl_debug_malloc (osl_t * osh, uint size, int line, char *file) +{ + bcm_mem_link_t *p; + char *basename; + + ASSERT (size); - return ((void*) skb); + if ((p = + (bcm_mem_link_t *) osl_malloc (osh, + sizeof (bcm_mem_link_t) + size)) == + NULL) + return (NULL); + + p->size = size; + p->line = line; + + basename = strrchr (file, '/'); + /* skip the '/' */ + if (basename) + basename++; + + if (!basename) + basename = file; + + strncpy (p->file, basename, BCM_MEM_FILENAME_LEN); + p->file[BCM_MEM_FILENAME_LEN - 1] = '\0'; + + /* link this block */ + p->prev = NULL; + p->next = osh->dbgmem_list; + if (p->next) + p->next->prev = p; + osh->dbgmem_list = p; + + return p + 1; } -typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, uint16 status); -/* Free the driver packet. Free the tag if present */ void -osl_pktfree(osl_t *osh, void *p, bool send) +osl_debug_mfree (osl_t * osh, void *addr, uint size, int line, char *file) { - struct sk_buff *skb, *nskb; - pktfree_cb_fn_t tx_fn = osh->pub.tx_fn; + bcm_mem_link_t *p = + (bcm_mem_link_t *) ((int8 *) addr - sizeof (bcm_mem_link_t)); + + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + + if (p->size == 0) + { + printk + ("osl_debug_mfree: double free on addr %p size %d at line %d file %s\n", + addr, size, line, file); + ASSERT (p->size); + return; + } + + if (p->size != size) + { + printk + ("osl_debug_mfree: dealloc size %d does not match alloc size %d on addr %p" + " at line %d file %s\n", size, p->size, addr, line, file); + ASSERT (p->size == size); + return; + } + + /* unlink this block */ + if (p->prev) + p->prev->next = p->next; + if (p->next) + p->next->prev = p->prev; + if (osh->dbgmem_list == p) + osh->dbgmem_list = p->next; + p->next = p->prev = NULL; + + osl_mfree (osh, p, size + sizeof (bcm_mem_link_t)); +} - skb = (struct sk_buff*) p; - - if (send && tx_fn) - tx_fn(osh->pub.tx_ctx, p, 0); +int +osl_debug_memdump (osl_t * osh, struct bcmstrbuf *b) +{ + bcm_mem_link_t *p; - /* perversion: we use skb->next to chain multi-skb packets */ - while (skb) { - nskb = skb->next; - skb->next = NULL; + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); -#ifdef BCMDBG_PKT - pktlist_remove(&(osh->pktlist), (void *) skb); -#endif /* BCMDBG_PKT */ + bcm_bprintf (b, " Address\tSize\tFile:line\n"); + for (p = osh->dbgmem_list; p; p = p->next) + bcm_bprintf (b, "0x%08x\t%5d\t%s:%d\n", + (uintptr) p + sizeof (bcm_mem_link_t), p->size, p->file, + p->line); - 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); - } + return 0; +} - osh->pub.pktalloced--; +#endif /* BCMDBG_MEM */ - 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_malloc(osl_t *osh, uint size) +void +osl_mfree (osl_t * osh, void *addr, uint size) { - void *addr; + if (osh) + { + ASSERT (osh->magic == OS_HANDLE_MAGIC); + osh->malloced -= size; + } + kfree (addr); +} - /* only ASSERT if osh is defined */ - if (osh) - ASSERT(osh->magic == OS_HANDLE_MAGIC); +uint +osl_malloced (osl_t * osh) +{ + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + return (osh->malloced); +} - if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { - if (osh) - osh->failed++; - return (NULL); - } - if (osh) - osh->malloced += size; +uint +osl_malloc_failed (osl_t * osh) +{ + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + return (osh->failed); +} + +void * +osl_dma_alloc_consistent (osl_t * osh, uint size, ulong * pap) +{ + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); - return (addr); + return (pci_alloc_consistent (osh->pdev, size, (dma_addr_t *) pap)); } void -osl_mfree(osl_t *osh, void *addr, uint size) +osl_dma_free_consistent (osl_t * osh, void *va, uint size, ulong pa) { - if (osh) { - ASSERT(osh->magic == OS_HANDLE_MAGIC); - osh->malloced -= size; - } - kfree(addr); + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + + pci_free_consistent (osh->pdev, size, va, (dma_addr_t) pa); } uint -osl_malloced(osl_t *osh) +osl_dma_map (osl_t * osh, void *va, uint size, int direction) { - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - return (osh->malloced); + int dir; + + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + dir = (direction == DMA_TX) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE; + return (pci_map_single (osh->pdev, va, size, dir)); } -uint osl_malloc_failed(osl_t *osh) +void +osl_dma_unmap (osl_t * osh, uint pa, uint size, int direction) { - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - return (osh->failed); + int dir; + + ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC))); + dir = (direction == DMA_TX) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE; + pci_unmap_single (osh->pdev, (uint32) pa, size, dir); } -#undef osl_delay +#if defined(BINOSL) || defined(BCMDBG_ASSERT) void -osl_delay(uint usec) +osl_assert (char *exp, char *file, int line) { - OSL_DELAY(usec); + char tempbuf[255]; + + sprintf (tempbuf, "assertion \"%s\" failed: file \"%s\", line %d\n", exp, + file, line); + panic (tempbuf); +} +#endif /* BCMDBG_ASSERT || BINOSL */ + +void +osl_delay (uint usec) +{ + uint d; + + while (usec > 0) + { + d = MIN (usec, 1000); + udelay (d); + usec -= d; + } } /* Clone a packet. * The pkttag contents are NOT cloned. */ void * -osl_pktdup(osl_t *osh, void *skb) +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++; +#ifdef BCMDBG_PKT + pktlist_add (&(osh->pktlist), (void *) p); +#endif /* BCMDBG_PKT */ + return (p); +} + +uint +osl_pktalloced (osl_t * osh) +{ + return (osh->pub.pktalloced); +} + +#ifdef BCMDBG_PKT +char * +osl_pktlist_dump (osl_t * osh, char *buf) +{ + pktlist_dump (&(osh->pktlist), buf); + return buf; +} + +void +osl_pktlist_add (osl_t * osh, void *p) +{ + pktlist_add (&(osh->pktlist), p); +} + +void +osl_pktlist_remove (osl_t * osh, void *p) +{ + pktlist_remove (&(osh->pktlist), p); +} +#endif /* BCMDBG_PKT */ + +/* + * BINOSL selects the slightly slower function-call-based binary compatible osl. + */ +#ifdef BINOSL + +int +osl_printf (const char *format, ...) +{ + va_list args; + char buf[1024]; + int len; + + /* sprintf into a local buffer because there *is* no "vprintk()".. */ + va_start (args, format); + len = vsnprintf (buf, 1024, format, args); + va_end (args); + + if (len > sizeof (buf)) + { + printk ("osl_printf: buffer overrun\n"); + return (0); + } + + return (printk (buf)); +} + +int +osl_sprintf (char *buf, const char *format, ...) +{ + va_list args; + int rc; + + va_start (args, format); + rc = vsprintf (buf, format, args); + va_end (args); + return (rc); +} + +int +osl_strcmp (const char *s1, const char *s2) +{ + return (strcmp (s1, s2)); +} + +int +osl_strncmp (const char *s1, const char *s2, uint n) +{ + return (strncmp (s1, s2, n)); +} + +int +osl_strlen (const char *s) +{ + return (strlen (s)); +} + +char * +osl_strcpy (char *d, const char *s) +{ + return (strcpy (d, s)); +} + +char * +osl_strncpy (char *d, const char *s, uint n) +{ + return (strncpy (d, s, n)); +} + +void +bcopy (const void *src, void *dst, int len) +{ + memcpy (dst, src, len); +} + +int +bcmp (const void *b1, const void *b2, int len) +{ + return (memcmp (b1, b2, len)); +} + +void +bzero (void *b, int len) +{ + memset (b, '\0', len); +} + +uint32 +osl_readl (volatile uint32 * r) +{ + return (readl (r)); +} + +uint16 +osl_readw (volatile uint16 * r) +{ + return (readw (r)); +} + +uint8 +osl_readb (volatile uint8 * r) +{ + return (readb (r)); +} + +void +osl_writel (uint32 v, volatile uint32 * r) +{ + writel (v, r); +} + +void +osl_writew (uint16 v, volatile uint16 * r) +{ + writew (v, r); +} + +void +osl_writeb (uint8 v, volatile uint8 * r) +{ + writeb (v, r); +} + +void * +osl_uncached (void *va) +{ +#ifdef mips + return ((void *) KSEG1ADDR (va)); +#else + return ((void *) va); +#endif /* mips */ +} + +uint +osl_getcycles (void) { - void * p; + uint cycles; + +#if defined(mips) + cycles = read_c0_count () * 2; +#elif defined(__i386__) + rdtscl (cycles); +#else + cycles = 0; +#endif /* defined(mips) */ + return cycles; +} - if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) - return NULL; +void * +osl_reg_map (uint32 pa, uint size) +{ + return (ioremap_nocache ((unsigned long) pa, (unsigned long) size)); +} - /* skb_clone copies skb->cb.. we don't want that */ - if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); +void +osl_reg_unmap (void *va) +{ + iounmap (va); +} - /* Increment the packet counter */ - osh->pub.pktalloced++; - return (p); +int +osl_busprobe (uint32 * val, uint32 addr) +{ +#ifdef mips + return get_dbe (*val, (uint32 *) addr); +#else + *val = readl ((uint32 *) (uintptr) addr); + return 0; +#endif /* mips */ +} + +bool +osl_pktshared (void *skb) +{ + return (((struct sk_buff *) skb)->cloned); +} + +uchar * +osl_pktdata (osl_t * osh, void *skb) +{ + return (((struct sk_buff *) skb)->data); } uint -osl_pktalloced(osl_t *osh) +osl_pktlen (osl_t * osh, void *skb) +{ + return (((struct sk_buff *) skb)->len); +} + +uint +osl_pktheadroom (osl_t * osh, void *skb) +{ + return (uint) skb_headroom ((struct sk_buff *) skb); +} + +uint +osl_pkttailroom (osl_t * osh, void *skb) +{ + return (uint) skb_tailroom ((struct sk_buff *) skb); +} + +void * +osl_pktnext (osl_t * osh, void *skb) +{ + return (((struct sk_buff *) skb)->next); +} + +void +osl_pktsetnext (void *skb, void *x) +{ + ((struct sk_buff *) skb)->next = (struct sk_buff *) x; +} + +void +osl_pktsetlen (osl_t * osh, void *skb, uint len) +{ + __skb_trim ((struct sk_buff *) skb, len); +} + +uchar * +osl_pktpush (osl_t * osh, void *skb, int bytes) +{ + return (skb_push ((struct sk_buff *) skb, bytes)); +} + +uchar * +osl_pktpull (osl_t * osh, void *skb, int bytes) +{ + return (skb_pull ((struct sk_buff *) skb, bytes)); +} + +void * +osl_pkttag (void *skb) { - return (osh->pub.pktalloced); + return ((void *) (((struct sk_buff *) skb)->cb)); +} + +void * +osl_pktlink (void *skb) +{ + return (((struct sk_buff *) skb)->prev); +} + +void +osl_pktsetlink (void *skb, void *x) +{ + ((struct sk_buff *) skb)->prev = (struct sk_buff *) x; +} + +uint +osl_pktprio (void *skb) +{ + return (((struct sk_buff *) skb)->priority); +} + +void +osl_pktsetprio (void *skb, uint x) +{ + ((struct sk_buff *) skb)->priority = x; +} + +/* 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 + */ +struct sk_buff * +osl_pkt_tonative (osl_t * osh, void *pkt) +{ + struct sk_buff *nskb; + + if (osh->pub.pkttag) + bzero ((void *) ((struct sk_buff *) pkt)->cb, OSL_PKTTAG_SZ); + + /* Decrement the packet counter */ + for (nskb = (struct sk_buff *) pkt; nskb; nskb = nskb->next) + { +#ifdef BCMDBG_PKT + pktlist_remove (&(osh->pktlist), (void *) nskb); +#endif /* BCMDBG_PKT */ + osh->pub.pktalloced--; + } + + return (struct sk_buff *) pkt; +} + +/* 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 + */ +void * +osl_pkt_frmnative (osl_t * osh, struct sk_buff *skb) +{ + struct sk_buff *nskb; + + if (osh->pub.pkttag) + bzero ((void *) skb->cb, OSL_PKTTAG_SZ); + + /* Increment the packet counter */ + for (nskb = skb; nskb; nskb = nskb->next) + { +#ifdef BCMDBG_PKT + pktlist_add (&(osh->pktlist), (void *) nskb); +#endif /* BCMDBG_PKT */ + osh->pub.pktalloced++; + } + + return (void *) skb; } +#endif /* BINOSL */ diff --git a/package/broadcom-wl/src/driver/linux_osl.h b/package/broadcom-wl/src/driver/linux_osl.h index d9c5533b85..f65c85966b 100644 --- a/package/broadcom-wl/src/driver/linux_osl.h +++ b/package/broadcom-wl/src/driver/linux_osl.h @@ -1,7 +1,7 @@ /* * Linux OS Independent Layer * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -9,7 +9,7 @@ * 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 $ + * $Id$ */ #ifndef _linux_osl_h_ @@ -19,17 +19,25 @@ #include <linuxver.h> #include <osl.h> -#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ +#define OSL_PKTTAG_SZ 32 /* Size of PktTag */ -/* osl handle type forward declaration */ -typedef struct osl_dmainfo osldma_t; +/* microsecond delay */ +extern void osl_delay(uint usec); /* OSL initialization */ -extern osl_t *osl_attach(void *pdev, bool pkttag); +extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); extern void osl_detach(osl_t *osh); +#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ + do { \ + ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ + ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ + } while (0) + /* 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); @@ -37,61 +45,110 @@ 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) +/* allocate/free shared (dma-able) consistent memory */ #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)); -} +extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap); +extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); -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); -} +/* map/unmap direction */ +#define DMA_TX 1 /* TX direction for DMA */ +#define DMA_RX 2 /* RX direction for DMA */ + +/* map/unmap shared (dma-able) memory */ +#define DMA_MAP(osh, va, size, direction, p, dmah) \ + osl_dma_map((osh), (va), (size), (direction)) +#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ + osl_dma_unmap((osh), (pa), (size), (direction)) +extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); +extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); +/* API for DMA addressing capability */ +#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) /* register access macros */ #if defined(BCMJTAG) #include <bcmjtag.h> -#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) */ +#define OSL_WRITE_REG(osh, r, v) (bcmjtag_write(NULL, (uintptr)(r), (v), sizeof(*(r)))) +#define OSL_READ_REG(osh, r) (bcmjtag_read(NULL, (uintptr)(r), sizeof(*(r)))) +#endif + +#if defined(BCMJTAG) +#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \ + mmap_op else bus_op +#define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \ + mmap_op : bus_op +#else +#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op +#define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op +#endif + +/* + * BINOSL selects the slightly slower function-call-based binary compatible osl. + * Macros expand to calls to functions defined in linux_osl.c . + */ +#ifndef BINOSL + +/* string library, kernel mode */ +#ifndef printf +#define printf(fmt, args...) printk(fmt, ## args) +#endif /* printf */ +#include <linux/kernel.h> +#include <linux/string.h> + +/* register access macros */ +#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) +#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) + +/* bcopy, bcmp, and bzero */ +#define bcopy(src, dst, len) memcpy((dst), (src), (len)) +#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) +#define bzero(b, len) memset((b), '\0', (len)) + +/* uncached virtual address */ +#ifdef mips +#define OSL_UNCACHED(va) KSEG1ADDR((va)) +#include <asm/addrspace.h> +#else +#define OSL_UNCACHED(va) (va) +#endif /* mips */ + +/* get processor cycle count */ +#if defined(mips) +#define OSL_GETCYCLES(x) ((x) = read_c0_count() * 2) +#elif defined(__i386__) +#define OSL_GETCYCLES(x) rdtscl((x)) +#else +#define OSL_GETCYCLES(x) ((x) = 0) +#endif /* defined(mips) */ + +/* dereference an address that may cause a bus exception */ +#ifdef mips +#if defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) +#define BUSPROBE(val, addr) panic("get_dbe() will not fixup a bus exception when compiled into"\ + " a module") +#else +#define BUSPROBE(val, addr) get_dbe((val), (addr)) +#include <asm/paccess.h> +#endif /* defined(MODULE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 17)) */ +#else +#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) +#endif /* mips */ + +/* map/unmap physical to virtual I/O */ +#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) +#define REG_UNMAP(va) iounmap((void *)(va)) + +/* shared (dma-able) memory access macros */ +#define R_SM(r) *(r) +#define W_SM(r, v) (*(r) = (v)) +#define BZERO_SM(r, len) memset((r), '\0', (len)) /* packet primitives */ -#define PKTGET(osh, len, send) osl_pktget((osh), (len), (send)) +#define PKTGET(osh, len, send) osl_pktget((osh), (len)) #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) #define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) @@ -104,15 +161,25 @@ osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) #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 PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced +#ifdef BCMDBG_PKT /* pkt logging for debugging */ +#define PKTLIST_DUMP(osh, buf) osl_pktlist_dump(osh, buf) +#else /* BCMDBG_PKT */ #define PKTLIST_DUMP(osh, buf) +#endif /* BCMDBG_PKT */ + +#ifdef BCMDBG_PKT /* pkt logging for debugging */ +extern void osl_pktlist_add(osl_t *osh, void *p); +extern void osl_pktlist_remove(osl_t *osh, void *p); +extern char *osl_pktlist_dump(osl_t *osh, char *buf); +#endif /* BCMDBG_PKT */ /* 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(osl_pubinfo_t*osh, struct sk_buff *skb) +osl_pkt_frmnative(osl_pubinfo_t *osh, struct sk_buff *skb) { struct sk_buff *nskb; @@ -121,13 +188,15 @@ osl_pkt_frmnative(osl_pubinfo_t*osh, struct sk_buff *skb) /* Increment the packet counter */ for (nskb = skb; nskb; nskb = nskb->next) { +#ifdef BCMDBG_PKT + osl_pktlist_add((osl_t *)osh, (void *) nskb); +#endif /* BCMDBG_PKT */ osh->pktalloced++; } return (void *)skb; } -#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_pubinfo_t*)osh), \ - (struct sk_buff*)(skb)) +#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_pubinfo_t *)osh), (struct sk_buff*)(skb)) /* Convert a driver packet to native(OS) packet * In the process, packettag is zeroed out before sending up @@ -135,7 +204,7 @@ osl_pkt_frmnative(osl_pubinfo_t*osh, struct sk_buff *skb) * In our case, that means it should be 0 */ static INLINE struct sk_buff * -osl_pkt_tonative(osl_pubinfo_t*osh, void *pkt) +osl_pkt_tonative(osl_pubinfo_t *osh, void *pkt) { struct sk_buff *nskb; @@ -144,24 +213,167 @@ osl_pkt_tonative(osl_pubinfo_t*osh, void *pkt) /* Decrement the packet counter */ for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { +#ifdef BCMDBG_PKT + osl_pktlist_remove((osl_t *)osh, (void *) nskb); +#endif /* BCMDBG_PKT */ osh->pktalloced--; } return (struct sk_buff *)pkt; } -#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_pubinfo_t*)(osh), (pkt)) +#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_pubinfo_t *)(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 PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) +#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ + ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) +/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ #define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) -extern void *osl_pktget(osl_t *osh, uint len, bool send); +extern void *osl_pktget(osl_t *osh, uint len); +extern void osl_pktfree(osl_t *osh, void *skb, bool send); +extern void *osl_pktdup(osl_t *osh, void *skb); +#else /* BINOSL */ + +/* string library */ +#ifndef LINUX_OSL +#undef printf +#define printf(fmt, args...) osl_printf((fmt), ## args) +#undef sprintf +#define sprintf(buf, fmt, args...) osl_sprintf((buf), (fmt), ## args) +#undef strcmp +#define strcmp(s1, s2) osl_strcmp((s1), (s2)) +#undef strncmp +#define strncmp(s1, s2, n) osl_strncmp((s1), (s2), (n)) +#undef strlen +#define strlen(s) osl_strlen((s)) +#undef strcpy +#define strcpy(d, s) osl_strcpy((d), (s)) +#undef strncpy +#define strncpy(d, s, n) osl_strncpy((d), (s), (n)) +#endif /* LINUX_OSL */ +extern int osl_printf(const char *format, ...); +extern int osl_sprintf(char *buf, const char *format, ...); +extern int osl_strcmp(const char *s1, const char *s2); +extern int osl_strncmp(const char *s1, const char *s2, uint n); +extern int osl_strlen(const char *s); +extern char* osl_strcpy(char *d, const char *s); +extern char* osl_strncpy(char *d, const char *s, uint n); + +/* register access macros */ +#if !defined(BCMJTAG) +#define R_REG(osh, r) (\ + sizeof(*(r)) == sizeof(uint8) ? osl_readb((volatile uint8*)(r)) : \ + sizeof(*(r)) == sizeof(uint16) ? osl_readw((volatile uint16*)(r)) : \ + osl_readl((volatile uint32*)(r)) \ +) +#define W_REG(osh, r, v) do { \ + switch (sizeof(*(r))) { \ + case sizeof(uint8): osl_writeb((uint8)(v), (volatile uint8*)(r)); break; \ + case sizeof(uint16): osl_writew((uint16)(v), (volatile uint16*)(r)); break; \ + case sizeof(uint32): osl_writel((uint32)(v), (volatile uint32*)(r)); break; \ + } \ +} while (0) +#endif + +#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) +#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) +extern uint8 osl_readb(volatile uint8 *r); +extern uint16 osl_readw(volatile uint16 *r); +extern uint32 osl_readl(volatile uint32 *r); +extern void osl_writeb(uint8 v, volatile uint8 *r); +extern void osl_writew(uint16 v, volatile uint16 *r); +extern void osl_writel(uint32 v, volatile uint32 *r); + +/* bcopy, bcmp, and bzero */ +extern void bcopy(const void *src, void *dst, int len); +extern int bcmp(const void *b1, const void *b2, int len); +extern void bzero(void *b, int len); + +/* uncached virtual address */ +#define OSL_UNCACHED(va) osl_uncached((va)) +extern void *osl_uncached(void *va); + +/* get processor cycle count */ +#define OSL_GETCYCLES(x) ((x) = osl_getcycles()) +extern uint osl_getcycles(void); + +/* dereference an address that may target abort */ +#define BUSPROBE(val, addr) osl_busprobe(&(val), (addr)) +extern int osl_busprobe(uint32 *val, uint32 addr); + +/* map/unmap physical to virtual */ +#define REG_MAP(pa, size) osl_reg_map((pa), (size)) +#define REG_UNMAP(va) osl_reg_unmap((va)) +extern void *osl_reg_map(uint32 pa, uint size); +extern void osl_reg_unmap(void *va); + +/* shared (dma-able) memory access macros */ +#define R_SM(r) *(r) +#define W_SM(r, v) (*(r) = (v)) +#define BZERO_SM(r, len) bzero((r), (len)) + +/* packet primitives */ +#define PKTGET(osh, len, send) osl_pktget((osh), (len)) +#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) +#define PKTDATA(osh, skb) osl_pktdata((osh), (skb)) +#define PKTLEN(osh, skb) osl_pktlen((osh), (skb)) +#define PKTHEADROOM(osh, skb) osl_pktheadroom((osh), (skb)) +#define PKTTAILROOM(osh, skb) osl_pkttailroom((osh), (skb)) +#define PKTNEXT(osh, skb) osl_pktnext((osh), (skb)) +#define PKTSETNEXT(osh, skb, x) osl_pktsetnext((skb), (x)) +#define PKTSETLEN(osh, skb, len) osl_pktsetlen((osh), (skb), (len)) +#define PKTPUSH(osh, skb, bytes) osl_pktpush((osh), (skb), (bytes)) +#define PKTPULL(osh, skb, bytes) osl_pktpull((osh), (skb), (bytes)) +#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) +#define PKTTAG(skb) osl_pkttag((skb)) +#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative((osh), (struct sk_buff*)(skb)) +#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osh), (pkt)) +#define PKTLINK(skb) osl_pktlink((skb)) +#define PKTSETLINK(skb, x) osl_pktsetlink((skb), (x)) +#define PKTPRIO(skb) osl_pktprio((skb)) +#define PKTSETPRIO(skb, x) osl_pktsetprio((skb), (x)) +#define PKTSHARED(skb) osl_pktshared((skb)) +#define PKTALLOCED(osh) osl_pktalloced((osh)) +#ifdef BCMDBG_PKT +#define PKTLIST_DUMP(osh, buf) osl_pktlist_dump(osh, buf) +#else /* BCMDBG_PKT */ +#define PKTLIST_DUMP(osh, buf) +#endif /* BCMDBG_PKT */ + +extern void *osl_pktget(osl_t *osh, uint len); extern void osl_pktfree(osl_t *osh, void *skb, bool send); +extern uchar *osl_pktdata(osl_t *osh, void *skb); +extern uint osl_pktlen(osl_t *osh, void *skb); +extern uint osl_pktheadroom(osl_t *osh, void *skb); +extern uint osl_pkttailroom(osl_t *osh, void *skb); +extern void *osl_pktnext(osl_t *osh, void *skb); +extern void osl_pktsetnext(void *skb, void *x); +extern void osl_pktsetlen(osl_t *osh, void *skb, uint len); +extern uchar *osl_pktpush(osl_t *osh, void *skb, int bytes); +extern uchar *osl_pktpull(osl_t *osh, void *skb, int bytes); extern void *osl_pktdup(osl_t *osh, void *skb); +extern void *osl_pkttag(void *skb); +extern void *osl_pktlink(void *skb); +extern void osl_pktsetlink(void *skb, void *x); +extern uint osl_pktprio(void *skb); +extern void osl_pktsetprio(void *skb, uint x); +extern void *osl_pkt_frmnative(osl_t *osh, struct sk_buff *skb); +extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); +extern bool osl_pktshared(void *skb); extern uint osl_pktalloced(osl_t *osh); +#ifdef BCMDBG_PKT /* pkt logging for debugging */ +extern char *osl_pktlist_dump(osl_t *osh, char *buf); +extern void osl_pktlist_add(osl_t *osh, void *p); +extern void osl_pktlist_remove(osl_t *osh, void *p); +#endif /* BCMDBG_PKT */ + +#endif /* BINOSL */ + #define OSL_ERROR(bcmerror) osl_error(bcmerror) extern int osl_error(int bcmerror); diff --git a/package/broadcom-wl/src/driver/patchtable.pl b/package/broadcom-wl/src/driver/patchtable.pl deleted file mode 100644 index 6999735125..0000000000 --- a/package/broadcom-wl/src/driver/patchtable.pl +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (C) 2006 OpenWrt.org -# Copyright (C) 2006 Felix Fietkau -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -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/driver/pktq.h b/package/broadcom-wl/src/driver/pktq.h deleted file mode 100644 index 7fe21815e8..0000000000 --- a/package/broadcom-wl/src/driver/pktq.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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.h> - -/* 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/driver/proto/802.11.h b/package/broadcom-wl/src/driver/proto/802.11.h new file mode 100644 index 0000000000..83f4612e57 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/802.11.h @@ -0,0 +1,1387 @@ +/* + * Copyright 2007, 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$ + */ + +#ifndef _802_11_H_ +#define _802_11_H_ + +#ifndef _TYPEDEFS_H_ +#include <typedefs.h> +#endif + +#ifndef _NET_ETHERNET_H_ +#include <proto/ethernet.h> +#endif + +#include <proto/wpa.h> + +/* 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 */ + +/* control frame header (BA/BAR) */ +struct dot11_ctl_header { + uint16 fc; /* frame control */ + uint16 durid; /* duration/ID */ + struct ether_addr ra; /* receiver address */ + struct ether_addr ta; /* transmitter address */ +} PACKED; +#define DOT11_CTL_HDR_LEN 16 /* control frame hdr len */ + +/* BAR frame payload */ +struct dot11_bar { + uint16 bar_control; /* BAR Control */ + uint16 seqnum; /* Starting Sequence control */ +} PACKED; +#define DOT11_BAR_LEN 4 /* BAR frame payload length */ + +#define DOT11_BA_BITMAP_LEN 128 /* bitmap length */ +#define DOT11_BA_CMP_BITMAP_LEN 8 /* compressed bitmap length */ +/* BA frame payload */ +struct dot11_ba { + uint16 ba_control; /* BA Control */ + uint16 seqnum; /* Starting Sequence control */ + uint8 bitmap[DOT11_BA_BITMAP_LEN]; /* Block Ack Bitmap */ +} PACKED; +#define DOT11_BA_LEN 4 /* BA frame payload len (wo 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 /* 802.11 beacon/probe frame fixed 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_ht_ch_width { + uint8 category; + uint8 action; + uint8 ch_width; +} PACKED; + +struct dot11_action_ht_mimops { + uint8 category; + uint8 action; + uint8 control; +} PACKED; + +#define SM_PWRSAVE_ENABLE 1 +#define SM_PWRSAVE_MODE 2 + +struct dot11_action_ht_info_xchg { + uint8 category; + uint8 action; + uint8 info; +} PACKED; + +#define DOT11_HT_INFO_XCHG_INFO_REQ 0x01 +#define DOT11_HT_INFO_XCHG_40MHZ_INTOLERANT 0x02 +#define DOT11_HT_INFO_XCHG_STA_CHAN_WIDTH 0x04 + + +/* ************* 802.11h related definitions. ************* */ +struct dot11_power_cnst { + uint8 id; + uint8 len; + uint8 power; +} PACKED; +typedef struct dot11_power_cnst dot11_power_cnst_t; + +struct dot11_power_cap { + uint8 min; + uint8 max; +} PACKED; +typedef struct dot11_power_cap dot11_power_cap_t; + +struct dot11_tpc_rep { + uint8 id; + uint8 len; + uint8 tx_pwr; + uint8 margin; +} PACKED; +typedef struct dot11_tpc_rep dot11_tpc_rep_t; +#define DOT11_MNG_IE_TPC_REPORT_LEN 2 /* length of IE data, not including 2 byte header */ + +struct dot11_supp_channels { + uint8 id; + uint8 len; + uint8 first_channel; + uint8 num_channels; +} PACKED; +typedef struct dot11_supp_channels dot11_supp_channels_t; + +/* Extension Channel Offset IE: 802.11n-D1.0 spec. added sideband + * offset for 40MHz operation. The possible 3 values are: + * 1 = above control channel + * 3 = below control channel + * 0 = no extension channel + */ +struct dot11_extch { + uint8 id; /* IE ID, 62, DOT11_MNG_EXT_CHANNEL_OFFSET */ + uint8 len; /* IE length */ + uint8 extch; +} PACKED; +typedef struct dot11_extch dot11_extch_ie_t; + +struct dot11_brcm_extch { + uint8 id; /* IE ID, 221, DOT11_MNG_PROPR_ID */ + uint8 len; /* IE length */ + uint8 oui[3]; /* Proprietary OUI, BRCM_OUI */ + uint8 type; /* type inidicates what follows */ + uint8 extch; +} PACKED; +typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; + +#define BRCM_EXTCH_IE_LEN 5 +#define BRCM_EXTCH_IE_TYPE 53 /* 802.11n ID not yet assigned */ +#define DOT11_EXTCH_IE_LEN 1 +#define DOT11_EXT_CH_MASK 0x03 /* extension channel mask */ +#define DOT11_EXT_CH_UPPER 0x01 /* ext. ch. on upper sb */ +#define DOT11_EXT_CH_LOWER 0x03 /* ext. ch. on lower sb */ +#define DOT11_EXT_CH_NONE 0x00 /* no extension ch. */ + +struct dot11_action_frmhdr { + uint8 category; + uint8 action; + uint8 data[1]; +} PACKED; + +/* CSA IE data structure */ +struct dot11_channel_switch { + uint8 id; /* id DOT11_MNG_CHANNEL_SWITCH_ID */ + uint8 len; /* length of IE */ + uint8 mode; /* mode 0 or 1 */ + uint8 channel; /* channel switch to */ + uint8 count; /* number of beacons before switching */ +} PACKED; +typedef struct dot11_channel_switch dot11_chan_switch_ie_t; + +#define DOT11_SWITCH_IE_LEN 3 /* length of IE data, not including 2 byte header */ +/* CSA mode - 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. */ + +struct dot11_action_switch_channel { + uint8 category; + uint8 action; + dot11_chan_switch_ie_t chan_switch_ie; /* for switch IE */ + dot11_brcm_extch_ie_t extch_ie; /* extension channel offset */ +} PACKED; + +/* 11n Extended Channel Switch IE data structure */ +struct dot11_ext_csa { + uint8 id; /* id DOT11_MNG_EXT_CHANNEL_SWITCH_ID */ + uint8 len; /* length of IE */ + uint8 mode; /* mode 0 or 1 */ + uint8 reg; /* regulatory class */ + uint8 channel; /* channel switch to */ + uint8 count; /* number of beacons before switching */ +} PACKED; +typedef struct dot11_ext_csa dot11_ext_csa_ie_t; +#define DOT11_EXT_CSA_IE_LEN 4 /* length of extended channel switch IE body */ + +struct dot11_action_ext_csa { + uint8 category; + uint8 action; + dot11_ext_csa_ie_t chan_switch_ie; /* for switch IE */ +} PACKED; + +/* 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 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 */ + +struct dot11_meas_req { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint8 channel; + uint8 start_time[8]; + uint16 duration; +} PACKED; +typedef struct dot11_meas_req 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; + +struct chan_map_tuple { + uint8 channel; + uint8 map; +} PACKED; +typedef struct chan_map_tuple chan_map_tuple_t; + +struct dot11_ibss_dfs { + uint8 id; + uint8 len; + uint8 eaddr[ETHER_ADDR_LEN]; + uint8 interval; + chan_map_tuple_t map[1]; +} PACKED; +typedef struct dot11_ibss_dfs 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 + * body and return the char* pointer to the SSID info element + */ +#define BCN_PRB_SSID(body) ((char*)(body) + 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 challenge 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 */ +#define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ + +/* Control Subtypes */ +#define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ +#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_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ + +#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ +#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_BAD_PC 10 /* Unacceptable power capability element */ +#define DOT11_RC_BAD_CHANNELS 11 /* Unacceptable supported channels element */ +/* 12 is unused */ + +/* 32-39 are QSTA specific reasons added in 11e */ +#define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ +#define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ +#define DOT11_RC_EXCESSIVE_FRAMES 34 /* excessive number of frames need ack */ +#define DOT11_RC_TX_OUTSIDE_TXOP 35 /* transmitting outside the limits of txop */ +#define DOT11_RC_LEAVING_QBSS 36 /* QSTA is leaving the QBSS (or restting) */ +#define DOT11_RC_BAD_MECHANISM 37 /* does not want to use the mechanism */ +#define DOT11_RC_SETUP_NEEDED 38 /* mechanism needs a setup */ +#define DOT11_RC_TIMEOUT 39 /* timeout */ + +#define DOT11_RC_MAX 23 /* Reason codes > 23 are reserved */ + +/* Status Codes */ +#define DOT11_SC_SUCCESS 0 /* Successful */ +#define DOT11_SC_FAILURE 1 /* Unspecified failure */ +#define DOT11_SC_CAP_MISMATCH 10 /* Cannot support all requested + * capabilities in the Capability + * Information field + */ +#define DOT11_SC_REASSOC_FAIL 11 /* Reassociation denied due to inability + * to confirm that association exists + */ +#define DOT11_SC_ASSOC_FAIL 12 /* Association denied due to reason + * outside the scope of this standard + */ +#define DOT11_SC_AUTH_MISMATCH 13 /* Responding station does not support + * the specified authentication + * algorithm + */ +#define DOT11_SC_AUTH_SEQ 14 /* Received an Authentication frame + * with authentication transaction + * sequence number out of expected + * sequence + */ +#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 /* Authentication rejected because of + * challenge failure + */ +#define DOT11_SC_AUTH_TIMEOUT 16 /* Authentication rejected due to timeout + * waiting for next frame in sequence + */ +#define DOT11_SC_ASSOC_BUSY_FAIL 17 /* Association denied because AP is + * unable to handle additional + * associated stations + */ +#define DOT11_SC_ASSOC_RATE_MISMATCH 18 /* Association denied due to requesting + * station not supporting all of the + * data rates in the BSSBasicRateSet + * parameter + */ +#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 /* Association denied due to requesting + * station not supporting the Short + * Preamble option + */ +#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 /* Association denied due to requesting + * station not supporting the PBCC + * Modulation option + */ +#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 /* Association denied due to requesting + * station not supporting the Channel + * Agility option + */ +#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 /* Association denied because Spectrum + * Management capability is required. + */ +#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 /* Association denied because the info + * in the Power Cap element is + * unacceptable. + */ +#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 /* Association denied because the info + * in the Supported Channel element is + * unacceptable + */ +#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 /* Association denied due to requesting + * station not supporting the Short Slot + * Time option + */ +#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 /* Association denied due to requesting + * station not supporting the ER-PBCC + * Modulation option + */ +#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 /* Association denied due to requesting + * station not supporting the DSS-OFDM + * option + */ + +#define DOT11_SC_DECLINED 37 /* request declined */ +#define DOT11_SC_INVALID_PARAMS 38 /* One or more params have invalid values */ + +/* 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_HT_CAP 45 /* d11 mgmt HT cap 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_EXT_CSA_ID 60 /* d11 Extended CSA */ +#define DOT11_MNG_HT_ADD 61 /* d11 mgmt additional HT info */ +#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 /* d11 mgmt ext channel offset */ +#define DOT11_MNG_EXT_CAP 127 /* d11 mgmt ext capability */ +#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 */ + +/* Extended Capability Information Field */ +#define DOT11_EXT_CAP_HT_IE_SUPPORT 0x01 /* support for info xchg action frame */ + +/* Action Frame Constants */ +#define DOT11_ACTION_HDR_LEN 2 /* action frame header length */ +#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_CAT_HT 0x07 /* d11 action category for HT */ +#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 */ +#define DOT11_ACTION_ID_EXT_CSA 5 /* d11 extened CSA for 11n */ + +/* HT action ids */ +#define DOT11_ACTION_ID_HT_CH_WIDTH 0 /* notify channel width action id */ +#define DOT11_ACTION_ID_HT_MIMO_PS 1 /* mimo ps action id */ +#define DOT11_ACTION_ID_HT_INFO_XCHG 8 /* HT Information Exchange action 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_AMSDU_SUP 0x0001 /* AMSDU supported under BA */ +#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 8 /* extra mixed mode preamble time */ +#define PREN_PREAMBLE_EXT 4 /* extra preamble (multiply by unique_streams-1) */ + +/* 802.11 N PHY constants */ +#define NPHY_RIFS_TIME 2 /* NPHY RIFS time */ + +/* 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 BRF1_DPT 0x2 /* DPT 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 */ +#define MAX_MCS_NUM (128) /* max mcs number = 128 */ + +struct ewc_cap_ie { + uint16 cap; + uint8 params; + uint8 supp_mcs[MCSSET_LEN]; + uint16 ext_htcap; + uint32 txbf_cap; + uint8 as_cap; +} PACKED; +typedef struct ewc_cap_ie ewc_cap_ie_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_prop_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_ie_t cap_ie; +} PACKED; +typedef struct ewc_prop_cap_ie ewc_prop_cap_ie_t; +#define EWC_PROP_IE_OVERHEAD 4 /* overhead bytes for prop oui ie */ +#define EWC_CAP_IE_LEN 26 +#define EWC_CAP_IE_TYPE 51 + +#define EWC_CAP_LDPC_CODING 0x0001 /* Support for rx of LDPC coded pkts */ +#define EWC_CAP_40MHZ 0x0002 /* FALSE:20Mhz, TRUE:20/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_40MHZ_INTOLERANT 0x4000 /* 40MHz Intolerant */ +#define EWC_CAP_LSIG_TXOP 0x8000 /* L-SIG TXOP protection support */ + +#define EWC_CAP_RX_STBC_NO 0x0 /* no rx STBC support */ +#define EWC_CAP_RX_STBC_ONE_STREAM 0x1 /* rx STBC support of 1 spatial stream */ +#define EWC_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ +#define EWC_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ + +#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_ie { + 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_ie ewc_add_ie_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_prop_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_ie_t add_ie; +} PACKED; +typedef struct ewc_prop_add_ie ewc_prop_add_ie_t; + +#define EWC_ADD_IE_LEN 22 +#define EWC_ADD_IE_TYPE 52 + +/* byte1 defn's */ +#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_SHIFT 0 /* protection mode shift */ +#define EWC_OPMODE_PURE 0x0000 /* protection mode PURE */ +#define EWC_OPMODE_OPTIONAL 0x0001 /* protection mode optional */ +#define EWC_OPMODE_HT20IN40 0x0002 /* protection mode 20MHz HT in 40MHz BSS */ +#define EWC_OPMODE_MIXED 0x0003 /* protection mode Mixed Mode */ +#define EWC_OPMODE_NONGF 0x0004 /* protection mode non-GF */ +#define DOT11N_TXBURST 0x0008 /* Tx burst limit */ +#define DOT11N_OBSS_NONHT 0x0010 /* OBSS Non-HT STA present */ + +/* 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 */ + +/* Tx Burst Limits */ +#define DOT11N_2G_TXBURST_LIMIT 6160 /* 2G band Tx burst limit per 802.11n Draft 1.10 (usec) */ +#define DOT11N_5G_TXBURST_LIMIT 3080 /* 5G band Tx burst limit per 802.11n Draft 1.10 (usec) */ + +/* Macros for opmode */ +#define GET_EWC_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \ + >> EWC_OPMODE_SHIFT) +#define EWC_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \ + == EWC_OPMODE_MIXED) /* mixed mode present */ +#define EWC_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \ + == EWC_OPMODE_HT20IN40) /* 20MHz HT present */ +#define EWC_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_MASK) \ + == EWC_OPMODE_OPTIONAL) /* Optional protection present */ +#define EWC_USE_PROTECTION(add_ie) (EWC_HT20_PRESENT((add_ie)) || \ + EWC_MIXEDMODE_PRESENT((add_ie))) /* use protection */ +#define EWC_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & EWC_OPMODE_NONGF) \ + == EWC_OPMODE_NONGF) /* non-GF present */ +#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ + == DOT11N_TXBURST) /* Tx Burst present */ +#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ + == DOT11N_OBSS_NONHT) /* OBSS Non-HT present */ + +/* 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/driver/proto/802.11e.h b/package/broadcom-wl/src/driver/proto/802.11e.h new file mode 100644 index 0000000000..e1aa5069e8 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/802.11e.h @@ -0,0 +1,123 @@ +/* + * 802.11e protocol header file + * + * Copyright 2007, 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$ + */ + +#ifndef _802_11e_H_ +#define _802_11e_H_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#ifdef BCMDBG +extern const char *aci_names[]; +#endif /* BCMDBG */ + +/* WME Traffic Specification (TSPEC) element */ +#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ +#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ + +#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ +#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ +#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ +#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ + +struct tsinfo { + uint8 octets[3]; +} PACKED; + +typedef struct tsinfo tsinfo_t; + +/* 802.11e TSPEC IE */ +typedef struct tspec { + uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ + uint8 type; /* WME_TYPE */ + uint8 subtype; /* WME_SUBTYPE_TSPEC */ + uint8 version; /* WME_VERSION */ + tsinfo_t tsinfo; /* TS Info bit field */ + uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ + uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ + uint32 min_srv_interval; /* Minimum Service Interval (us) */ + uint32 max_srv_interval; /* Maximum Service Interval (us) */ + uint32 inactivity_interval; /* Inactivity Interval (us) */ + uint32 suspension_interval; /* Suspension Interval (us) */ + uint32 srv_start_time; /* Service Start Time (us) */ + uint32 min_data_rate; /* Minimum Data Rate (bps) */ + uint32 mean_data_rate; /* Mean Data Rate (bps) */ + uint32 peak_data_rate; /* Peak Data Rate (bps) */ + uint32 max_burst_size; /* Maximum Burst Size (bytes) */ + uint32 delay_bound; /* Delay Bound (us) */ + uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ + uint16 surplus_bw; /* Surplus Bandwidth Allowance Factor */ + uint16 medium_time; /* Medium Time (32 us/s periods) */ +} PACKED tspec_t; + +#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ + +/* ts_info */ +/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ +#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ +#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ +#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ +#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ +#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ +#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ +#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ +#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ +#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ +#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ +#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ +#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ +/* TS info. user priority mask */ +#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) + +/* Macro to get/set bit(s) field in TSINFO */ +#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) +#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ + TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) +#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & WLC_CAC_PSB_MASK) >> WLC_CAC_PSB_SHIFT) +#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ + TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) + +#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ + ((id) << TS_INFO_TID_SHIFT)) +#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ + ((prio) << TS_INFO_USER_PRIO_SHIFT)) + +/* 802.11e QBSS Load IE */ +#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ +#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ + +#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */ + +/* 802.11e ADDTS status code */ +#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ +#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ +#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ + +/* 802.11e DELTS status code */ +#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ +#define DOT11E_STATUS_END_TS 37 /* END TS */ +#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ +#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _802_11e_CAC_H_ */ diff --git a/package/broadcom-wl/src/driver/proto/802.1d.h b/package/broadcom-wl/src/driver/proto/802.1d.h new file mode 100644 index 0000000000..421b963202 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/802.1d.h @@ -0,0 +1,38 @@ +/* + * Copyright 2007, 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.1D + * + * $Id$ + */ + +#ifndef _802_1_D_ +#define _802_1_D_ + +/* 802.1D priority defines */ +#define PRIO_8021D_NONE 2 /* None = - */ +#define PRIO_8021D_BK 1 /* BK - Background */ +#define PRIO_8021D_BE 0 /* BE - Best-effort */ +#define PRIO_8021D_EE 3 /* EE - Excellent-effort */ +#define PRIO_8021D_CL 4 /* CL - Controlled Load */ +#define PRIO_8021D_VI 5 /* Vi - Video */ +#define PRIO_8021D_VO 6 /* Vo - Voice */ +#define PRIO_8021D_NC 7 /* NC - Network Control */ +#define MAXPRIO 7 /* 0-7 */ +#define NUMPRIO (MAXPRIO + 1) + +#define ALLPRIO -1 /* All prioirty */ + +/* Converts prio to precedence since the numerical value of + * PRIO_8021D_BE and PRIO_8021D_NONE are swapped. + */ +#define PRIO2PREC(prio) \ + (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) + +#endif /* _802_1_D__ */ diff --git a/package/broadcom-wl/src/driver/proto/802.3.h b/package/broadcom-wl/src/driver/proto/802.3.h new file mode 100644 index 0000000000..54a17c24ed --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/802.3.h @@ -0,0 +1,20 @@ +/* + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * Fundamental constants relating to 802.3 + * + * $Id$ + */ + +#ifndef _802_3_h_ +#define _802_3_h_ + +#define SNAP_HDR_LEN 6 /* 802.3 LLC/SNAP header length */ + +#endif /* #ifndef _802_3_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/bcmarp.h b/package/broadcom-wl/src/driver/proto/bcmarp.h new file mode 100644 index 0000000000..f5058b6aa7 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmarp.h @@ -0,0 +1,60 @@ +/* + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * Fundamental constants relating to ARP Protocol + * + * $Id$ + */ + +#ifndef _bcmarp_h_ +#define _bcmarp_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#define ARP_OPC_OFFSET 6 /* option code offset */ +#define ARP_SRC_ETH_OFFSET 8 /* src h/w address offset */ +#define ARP_SRC_IP_OFFSET 14 /* src IP address offset */ +#define ARP_TGT_ETH_OFFSET 18 /* target h/w address offset */ +#define ARP_TGT_IP_OFFSET 24 /* target IP address offset */ + +#define ARP_OPC_REQUEST 1 /* ARP request */ +#define ARP_OPC_REPLY 2 /* ARP reply */ + +#define ARP_DATA_LEN 28 /* ARP data length */ + +struct bcmarp { + uint16 htype; /* Header type (1 = ethernet) */ + uint16 ptype; /* Protocol type (0x800 = IP) */ + uint8 hlen; /* Hardware address length (Eth = 6) */ + uint8 plen; /* Protocol address length (IP = 4) */ + uint16 oper; /* ARP_OPC_... */ + uint8 src_eth[ETHER_ADDR_LEN]; /* Source hardware address */ + uint8 src_ip[IPV4_ADDR_LEN]; /* Source protocol address (not aligned) */ + uint8 dst_eth[ETHER_ADDR_LEN]; /* Destination hardware address */ + uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination protocol address */ +} PACKED; + +/* Ethernet header + Arp message */ +struct bcmetharp { + struct ether_header eh; + struct bcmarp arp; +} PACKED; + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* !defined(_bcmarp_h_) */ diff --git a/package/broadcom-wl/src/driver/proto/bcmdhcp.h b/package/broadcom-wl/src/driver/proto/bcmdhcp.h new file mode 100644 index 0000000000..a2cdc58fbd --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmdhcp.h @@ -0,0 +1,36 @@ +/* + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * Fundamental constants relating to DHCP Protocol + * + * $Id$ + */ + +#ifndef _bcmdhcp_h_ +#define _bcmdhcp_h_ + +/* DHCP params */ +#define DHCP_TYPE_OFFSET 0 /* DHCP type (request|reply) offset */ +#define DHCP_FLAGS_OFFSET 10 /* DHCP flags offset */ +#define DHCP_CIADDR_OFFSET 12 /* DHCP client IP address offset */ +#define DHCP_YIADDR_OFFSET 16 /* DHCP your IP address offset */ +#define DHCP_GIADDR_OFFSET 24 /* DHCP relay agent IP address offset */ +#define DHCP_CHADDR_OFFSET 28 /* DHCP client h/w address offset */ + +#define DHCP_TYPE_REQUEST 1 /* DHCP request (discover|request) */ +#define DHCP_TYPE_REPLY 2 /* DHCP reply (offset|ack) */ + +#define DHCP_PORT_SERVER 67 /* DHCP server UDP port */ +#define DHCP_PORT_CLIENT 68 /* DHCP client UDP port */ + +#define DHCP_FLAG_BCAST 0x8000 /* DHCP broadcast flag */ + +#define DHCP_FLAGS_LEN 2 /* DHCP flags field length */ + +#endif /* #ifndef _bcmdhcp_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/bcmeth.h b/package/broadcom-wl/src/driver/proto/bcmeth.h new file mode 100644 index 0000000000..23aa41159d --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmeth.h @@ -0,0 +1,101 @@ +/* + * Broadcom Ethernettype protocol definitions + * + * Copyright 2007, 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$ + */ + +/* + * 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/driver/proto/bcmevent.h b/package/broadcom-wl/src/driver/proto/bcmevent.h new file mode 100644 index 0000000000..785ef22bb2 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmevent.h @@ -0,0 +1,166 @@ +/* + * Broadcom Event protocol definitions + * + * Copyright 2007, 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$ + * + */ + +/* + * 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 */ + +/* these 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_BCNLOST_MSG 31 /* indicate to host loss of beacon */ +#define WLC_E_ROAM_PREP 32 /* before attempting to roam */ +#define WLC_E_PFN_NET_FOUND 33 /* PFN network found event */ +#define WLC_E_PFN_NET_LOST 34 /* PFN network lost event */ + +#ifdef EXT_STA +#define WLC_E_RESET_COMPLETE 35 +#define WLC_E_JOIN_START 36 +#define WLC_E_ROAM_START 37 +#define WLC_E_ASSOC_START 38 +#define WLC_E_IBSS_ASSOC 39 +#define WLC_E_RADIO 40 +#define WLC_E_LAST 41 /* highest val + 1 for range checking */ +#else /* EXT_STA */ +#define WLC_E_LAST 35 /* highest val + 1 for range checking */ +#endif /* EXT_STA */ + +/* 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 */ +#define WLC_E_STATUS_PARTIAL 8 /* scan results are incomplete */ +#define WLC_E_STATUS_NEWSCAN 9 /* scan aborted by another scan */ +#define WLC_E_STATUS_NEWASSOC 10 /* scan aborted due to assoc in progress */ +#define WLC_E_STATUS_11HQUIET 11 /* 802.11h quiet period started */ +#define WLC_E_STATUS_SUPPRESS 12 /* user disabled scanning (WLC_SET_SCANSUPPRESS) */ +#define WLC_E_STATUS_NOCHANS 13 /* no allowable channels to scan */ +#define WLC_E_STATUS_CCXFASTRM 14 /* scan aborted due to CCX fast roam */ + +/* 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 /* encryption 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_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_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 */ + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif /* PACKED */ + +#endif /* _BCMEVENT_H_ */ diff --git a/package/broadcom-wl/src/driver/proto/bcmip.h b/package/broadcom-wl/src/driver/proto/bcmip.h new file mode 100644 index 0000000000..4169060da3 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmip.h @@ -0,0 +1,152 @@ +/* + * Copyright 2007, 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$ + */ + +#ifndef _bcmip_h_ +#define _bcmip_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + + +/* 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_PKTLEN_OFFSET 2 /* packet length offset */ +#define IPV4_PKTFLAG_OFFSET 6 /* more-frag,dont-frag flag 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 */ +#define IPV4_OPTIONS_OFFSET 20 /* IP options 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_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ + ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) + +#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_FRAG_RESV 0x8000 /* Reserved */ +#define IPV4_FRAG_DONT 0x4000 /* Don't fragment */ +#define IPV4_FRAG_MORE 0x2000 /* More fragments */ +#define IPV4_FRAG_OFFSET_MASK 0x1fff /* Fragment offset */ + +#define IPV4_ADDR_STR_LEN 16 /* Max IP address length in string format */ + +/* IPv4, no options only. */ +#define IPV4_NO_OPTIONS_HDR_LEN 20 +#define IPV4_NO_OPTIONS_PAYLOAD(ip_hdr) (&(((uint8 *)(ip_hdr))[IPV4_NO_OPTIONS_HDR_LEN])) + +#define IPV4_PAYLOAD_LEN(ip_body) \ + (((int)(((uint8 *)(ip_body))[IPV4_PKTLEN_OFFSET + 0]) << 8) | \ + ((uint8 *)(ip_body))[IPV4_PKTLEN_OFFSET + 1]) + +/* IPV4 packet formats */ +struct ipv4_addr { + uint8 addr[IPV4_ADDR_LEN]; +} PACKED; + +struct ipv4_hdr { + uint8 version_ihl; /* Version and Internet Header Length */ + uint8 tos; /* Type Of Service */ + uint16 tot_len; /* Number of bytes in packet (max 65535) */ + uint16 id; + uint16 frag; /* 3 flag bits and fragment offset */ + uint8 ttl; /* Time To Live */ + uint8 prot; /* Protocol */ + uint16 hdr_chksum; /* IP header checksum */ + uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */ + uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */ +} PACKED; + +/* 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) + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _bcmip_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/bcmtcp.h b/package/broadcom-wl/src/driver/proto/bcmtcp.h new file mode 100644 index 0000000000..832fd434c0 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmtcp.h @@ -0,0 +1,68 @@ +/* + * Copyright 2007, 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 TCP Protocol + * + * $Id$ + */ + +#ifndef _bcmtcp_h_ +#define _bcmtcp_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#define TCP_SRC_PORT_OFFSET 0 /* TCP source port offset */ +#define TCP_DEST_PORT_OFFSET 2 /* TCP dest port offset */ +#define TCP_CHKSUM_OFFSET 16 /* TCP body checksum offset */ + +/* These fields are stored in network order */ +struct bcmtcp_hdr +{ + uint16 src_port; /* Source Port Address */ + uint16 dst_port; /* Destination Port Address */ + uint32 seq_num; /* TCP Sequence Number */ + uint32 ack_num; /* TCP Sequence Number */ + uint16 hdrlen_rsvd_flags; /* Header length, reserved bits and flags */ + uint16 tcpwin; /* TCP window */ + uint16 chksum; /* Segment checksum with pseudoheader */ + uint16 urg_ptr; /* Points to seq-num of byte following urg data */ +} PACKED; + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +/* Byte offset of flags in TCP header */ +#define TCP_FLAGS_OFFSET 13 + +#define TCP_FLAGS_FIN 0x01 +#define TCP_FLAGS_SYN 0x02 +#define TCP_FLAGS_RST 0x03 +#define TCP_FLAGS_PSH 0x04 +#define TCP_FLAGS_ACK 0x10 +#define TCP_FLAGS_URG 0x20 +#define TCP_FLAGS_ECN 0x40 +#define TCP_FLAGS_CWR 0x80 + +#define TCP_FLAGS(tcp_hdr) (((uint8 *)(tcp_hdr))[TCP_FLAGS_OFFSET]) +#define TCP_IS_ACK(tcp_hdr) (TCP_FLAGS(tcp_hdr) & TCP_FLAGS_ACK) + +#define TCP_SRC_PORT(tcp_hdr) (ntoh16(((struct bcmtcp_hdr*)(tcp_hdr))->src_port)) +#define TCP_DST_PORT(tcp_hdr) (ntoh16(((struct bcmtcp_hdr*)(tcp_hdr))->dst_port)) +#define TCP_SEQ_NUM(tcp_hdr) (ntoh32(((struct bcmtcp_hdr*)(tcp_hdr))->seq_num)) +#define TCP_ACK_NUM(tcp_hdr) (ntoh32(((struct bcmtcp_hdr*)(tcp_hdr))->ack_num)) + +#endif /* #ifndef _bcmtcp_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/bcmudp.h b/package/broadcom-wl/src/driver/proto/bcmudp.h new file mode 100644 index 0000000000..5464284cf7 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/bcmudp.h @@ -0,0 +1,48 @@ +/* + * Copyright 2007, Broadcom Corporation + * All Rights Reserved. + * + * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; + * the contents of this file may not be disclosed to third parties, copied + * or duplicated in any form, in whole or in part, without the prior + * written permission of Broadcom Corporation. + * + * Fundamental constants relating to UDP Protocol + * + * $Id$ + */ + +#ifndef _bcmudp_h_ +#define _bcmudp_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +/* UDP header */ +#define UDP_DEST_PORT_OFFSET 2 /* UDP dest port offset */ +#define UDP_LEN_OFFSET 4 /* UDP length offset */ +#define UDP_CHKSUM_OFFSET 6 /* UDP body checksum offset */ + +#define UDP_HDR_LEN 8 /* UDP header length */ +#define UDP_PORT_LEN 2 /* UDP port length */ + +/* These fields are stored in network order */ +struct bcmudp_hdr +{ + uint16 src_port; /* Source Port Address */ + uint16 dst_port; /* Destination Port Address */ + uint16 len; /* Number of bytes in datagram including header */ + uint16 chksum; /* entire datagram checksum with pseudoheader */ +} PACKED; + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* #ifndef _bcmudp_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/eap.h b/package/broadcom-wl/src/driver/proto/eap.h new file mode 100644 index 0000000000..5548e2fb54 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/eap.h @@ -0,0 +1,45 @@ +/* + * Extensible Authentication Protocol (EAP) definitions + * + * See + * RFC 2284: PPP Extensible Authentication Protocol (EAP) + * + * Copyright (C) 2002 Broadcom Corporation + * + * $Id$ + */ + +#ifndef _eap_h_ +#define _eap_h_ + +/* EAP packet format */ +typedef struct { + unsigned char code; /* EAP code */ + unsigned char id; /* Current request ID */ + unsigned short length; /* Length including header */ + unsigned char type; /* EAP type (optional) */ + unsigned char data[1]; /* Type data (optional) */ +} eap_header_t; + +#define EAP_HEADER_LEN 4 + +/* EAP codes */ +#define EAP_REQUEST 1 +#define EAP_RESPONSE 2 +#define EAP_SUCCESS 3 +#define EAP_FAILURE 4 + +/* EAP types */ +#define EAP_IDENTITY 1 +#define EAP_NOTIFICATION 2 +#define EAP_NAK 3 +#define EAP_MD5 4 +#define EAP_OTP 5 +#define EAP_GTC 6 +#define EAP_TLS 13 +#define EAP_EXPANDED 254 +#define BCM_EAP_SES 10 +#define BCM_EAP_EXP_LEN 12 /* EAP_LEN 5 + 3 bytes for SMI ID + 4 bytes for ven type */ +#define BCM_SMI_ID 0x113d + +#endif /* _eap_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/eapol.h b/package/broadcom-wl/src/driver/proto/eapol.h new file mode 100644 index 0000000000..9a1a58da83 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/eapol.h @@ -0,0 +1,179 @@ +/* + * 802.1x EAPOL definitions + * + * See + * IEEE Std 802.1X-2001 + * IEEE 802.1X RADIUS Usage Guidelines + * + * Copyright (C) 2002 Broadcom Corporation + * + * $Id$ + */ + +#ifndef _eapol_h_ +#define _eapol_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#include <bcmcrypto/aeskeywrap.h> + +/* EAPOL for 802.3/Ethernet */ +typedef struct { + struct ether_header eth; /* 802.3/Ethernet header */ + unsigned char version; /* EAPOL protocol version */ + unsigned char type; /* EAPOL type */ + unsigned short length; /* Length of body */ + unsigned char body[1]; /* Body (optional) */ +} eapol_header_t; + +#define EAPOL_HEADER_LEN 18 + +/* EAPOL version */ +#define WPA2_EAPOL_VERSION 2 +#define WPA_EAPOL_VERSION 1 +#define LEAP_EAPOL_VERSION 1 +#define SES_EAPOL_VERSION 1 + +/* EAPOL types */ +#define EAP_PACKET 0 +#define EAPOL_START 1 +#define EAPOL_LOGOFF 2 +#define EAPOL_KEY 3 +#define EAPOL_ASF 4 + +/* EAPOL-Key types */ +#define EAPOL_RC4_KEY 1 +#ifdef BCMWPA2 +#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */ +#endif +#define EAPOL_WPA_KEY 254 /* WPA */ + +/* RC4 EAPOL-Key header field sizes */ +#define EAPOL_KEY_REPLAY_LEN 8 +#define EAPOL_KEY_IV_LEN 16 +#define EAPOL_KEY_SIG_LEN 16 + +/* RC4 EAPOL-Key */ +typedef struct { + unsigned char type; /* Key Descriptor Type */ + unsigned short length; /* Key Length (unaligned) */ + unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */ + unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */ + unsigned char index; /* Key Flags & Index */ + unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */ + unsigned char key[1]; /* Key (optional) */ +} PACKED eapol_key_header_t; + +#define EAPOL_KEY_HEADER_LEN 44 + +/* RC4 EAPOL-Key flags */ +#define EAPOL_KEY_FLAGS_MASK 0x80 +#define EAPOL_KEY_BROADCAST 0 +#define EAPOL_KEY_UNICAST 0x80 + +/* RC4 EAPOL-Key index */ +#define EAPOL_KEY_INDEX_MASK 0x7f + +/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */ +#define EAPOL_WPA_KEY_REPLAY_LEN 8 +#define EAPOL_WPA_KEY_NONCE_LEN 32 +#define EAPOL_WPA_KEY_IV_LEN 16 +#define EAPOL_WPA_KEY_RSC_LEN 8 +#define EAPOL_WPA_KEY_ID_LEN 8 +#define EAPOL_WPA_KEY_MIC_LEN 16 +#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN) +#define EAPOL_WPA_MAX_KEY_SIZE 32 + +/* WPA EAPOL-Key */ +typedef struct { + unsigned char type; /* Key Descriptor Type */ + unsigned short key_info; /* Key Information (unaligned) */ + unsigned short key_len; /* Key Length (unaligned) */ + unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ + unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ + unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ + unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ + unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ + unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ + unsigned short data_len; /* Key Data Length */ + unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */ +} PACKED eapol_wpa_key_header_t; + +#define EAPOL_WPA_KEY_LEN 95 + +/* WPA/802.11i/WPA2 KEY KEY_INFO bits */ +#define WPA_KEY_DESC_V1 0x01 +#define WPA_KEY_DESC_V2 0x02 +#define WPA_KEY_PAIRWISE 0x08 +#define WPA_KEY_INSTALL 0x40 +#define WPA_KEY_ACK 0x80 +#define WPA_KEY_MIC 0x100 +#define WPA_KEY_SECURE 0x200 +#define WPA_KEY_ERROR 0x400 +#define WPA_KEY_REQ 0x800 + +/* WPA-only KEY KEY_INFO bits */ +#define WPA_KEY_INDEX_0 0x00 +#define WPA_KEY_INDEX_1 0x10 +#define WPA_KEY_INDEX_2 0x20 +#define WPA_KEY_INDEX_3 0x30 +#define WPA_KEY_INDEX_MASK 0x30 +#define WPA_KEY_INDEX_SHIFT 0x04 + +#ifdef BCMWPA2 +/* 802.11i/WPA2-only KEY KEY_INFO bits */ +#define WPA_KEY_ENCRYPTED_DATA 0x1000 + +/* Key Data encapsulation */ +typedef struct { + uint8 type; + uint8 length; + uint8 oui[3]; + uint8 subtype; + uint8 data[1]; +} PACKED eapol_wpa2_encap_data_t; + +#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6 + +#define WPA2_KEY_DATA_SUBTYPE_GTK 1 +#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2 +#define WPA2_KEY_DATA_SUBTYPE_MAC 3 +#define WPA2_KEY_DATA_SUBTYPE_PMKID 4 + +/* GTK encapsulation */ +typedef struct { + uint8 flags; + uint8 reserved; + uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE]; +} PACKED eapol_wpa2_key_gtk_encap_t; + +#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2 + +#define WPA2_GTK_INDEX_MASK 0x03 +#define WPA2_GTK_INDEX_SHIFT 0x00 + +#define WPA2_GTK_TRANSMIT 0x04 + +/* STAKey encapsulation */ +typedef struct { + uint8 reserved[2]; + uint8 mac[ETHER_ADDR_LEN]; + uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE]; +} PACKED eapol_wpa2_key_stakey_encap_t; + +#define WPA2_KEY_DATA_PAD 0xdd + +#endif /* BCMWPA2 */ + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _eapol_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/ethernet.h b/package/broadcom-wl/src/driver/proto/ethernet.h new file mode 100644 index 0000000000..b674e0ce36 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/ethernet.h @@ -0,0 +1,175 @@ +/* + * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. + * + * Copyright 2007, 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$ + */ + +#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_MIN 0x0600 /* Anything less than MIN is a length */ +#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 * ETHER_ADDR_LEN) /* dest address offset */ +#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) /* src address offset */ +#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) /* 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. + */ +#ifndef NOETHREQ /* Quick and ugly hack for VxWorks */ +struct ether_addr { + uint8 octet[ETHER_ADDR_LEN]; +} PACKED; +#endif +#endif /* !__INCif_etherh Quick and ugly hack for VxWorks */ + +/* + * Takes a pointer, set, test, clear, toggle locally admininistered + * address bit in the 48-bit Ethernet address. + */ +#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) +#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) +#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xd)) +#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) + +/* Takes a pointer, marks unicast address bit in the MAC address */ +#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) + +/* + * Takes a pointer, returns true if a 48-bit multicast address + * (including broadcast, since it is all ones) + */ +#define ETHER_ISMULTI(ea) (((const 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}}; +static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; + +/* + * 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/driver/proto/vlan.h b/package/broadcom-wl/src/driver/proto/vlan.h new file mode 100644 index 0000000000..2854b72c6f --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/vlan.h @@ -0,0 +1,52 @@ +/* + * 802.1Q VLAN protocol definitions + * + * Copyright 2007, 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$ + */ + +#ifndef _vlan_h_ +#define _vlan_h_ + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +#define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ +#define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ +#define VLAN_PRI_SHIFT 13 /* user priority */ + +#define VLAN_PRI_MASK 7 /* 3 bits of priority */ + +#define VLAN_TAG_LEN 4 +#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) /* offset in Ethernet II packet only */ + +#define VLAN_TPID 0x8100 /* VLAN ethertype/Tag Protocol ID */ + +struct ethervlan_header { + uint8 ether_dhost[ETHER_ADDR_LEN]; + uint8 ether_shost[ETHER_ADDR_LEN]; + uint16 vlan_type; /* 0x8100 */ + uint16 vlan_tag; /* priority, cfi and vid */ + uint16 ether_type; +}; + +#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _vlan_h_ */ diff --git a/package/broadcom-wl/src/driver/proto/wpa.h b/package/broadcom-wl/src/driver/proto/wpa.h new file mode 100644 index 0000000000..c4b6dd1db1 --- /dev/null +++ b/package/broadcom-wl/src/driver/proto/wpa.h @@ -0,0 +1,158 @@ +/* + * Fundamental types and constants relating to WPA + * + * Copyright 2007, 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$ + */ + +#ifndef _proto_wpa_h_ +#define _proto_wpa_h_ + +#include <typedefs.h> +#include <proto/ethernet.h> + +/* enable structure packing */ +#if defined(__GNUC__) +#define PACKED __attribute__((packed)) +#else +#pragma pack(1) +#define PACKED +#endif + +/* Reason Codes */ + +/* 13 through 23 taken from IEEE Std 802.11i-2004 */ +#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) */ + +/* RSN IE defines */ +#define RSN_CAP_LEN 2 /* Length of RSN capabilities field (2 octets) */ + +/* RSN Capabilities defined in 802.11i */ +#define RSN_CAP_PREAUTH 0x0001 +#define RSN_CAP_NOPAIRWISE 0x0002 +#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C +#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 +#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 +#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 +#define RSN_CAP_1_REPLAY_CNTR 0 +#define RSN_CAP_2_REPLAY_CNTRS 1 +#define RSN_CAP_4_REPLAY_CNTRS 2 +#define RSN_CAP_16_REPLAY_CNTRS 3 + +/* WPA capabilities defined in 802.11i */ +#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS +#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS +#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT +#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK + +/* WPA Specific defines */ +#define WPA_CAP_LEN RSN_CAP_LEN /* Length of RSN capabilities in RSN IE (2 octets) */ + +#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH + + +#undef PACKED +#if !defined(__GNUC__) +#pragma pack() +#endif + +#endif /* _proto_wpa_h_ */ diff --git a/package/broadcom-wl/src/driver/sbhnddma.h b/package/broadcom-wl/src/driver/sbhnddma.h index a26db7395e..b83baeb614 100644 --- a/package/broadcom-wl/src/driver/sbhnddma.h +++ b/package/broadcom-wl/src/driver/sbhnddma.h @@ -2,7 +2,7 @@ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface * This supports the following chips: BCM42xx, 44xx, 47xx . * - * Copyright 2006, Broadcom Corporation + * Copyright 2007, Broadcom Corporation * All Rights Reserved. * * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY @@ -10,7 +10,7 @@ * 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 $ + * $Id$ */ #ifndef _sbhnddma_h_ diff --git a/package/broadcom-wl/src/wlc/wlc.c b/package/broadcom-wl/src/wlc/wlc.c index f5db9a7638..aa9a559f73 100644 --- a/package/broadcom-wl/src/wlc/wlc.c +++ b/package/broadcom-wl/src/wlc/wlc.c @@ -56,7 +56,6 @@ 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; @@ -98,205 +97,6 @@ static inline int my_ether_ntoa(unsigned char *ea, char *buf) ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); } -/* - * 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.patch", 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 (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); @@ -957,6 +757,13 @@ static const struct wlc_call wlc_calls[] = { .desc = "RTS threshold" }, { + .name = "slottime", + .param = INT, + .handler = wlc_iovar, + .data.str = "acktiming", + .desc = "Slot time" + }, + { .name = "rxant", .param = INT, .handler = wlc_ioctl, @@ -1052,24 +859,6 @@ static const struct wlc_call wlc_calls[] = { .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)) diff --git a/package/broadcom-wl/src/wlcompat/Makefile b/package/broadcom-wl/src/wlcompat/Makefile index 6f3224df14..31e54244e8 100644 --- a/package/broadcom-wl/src/wlcompat/Makefile +++ b/package/broadcom-wl/src/wlcompat/Makefile @@ -15,6 +15,9 @@ ifneq ($(DEBUG),) EXTRA_CFLAGS += -DDEBUG=1 _D=-debug endif +ifneq ($(WL_WEXT),) + EXTRA_CFLAGS += -DWL_WEXT=1 +endif obj-m := wlcompat$(_D).o modules: wlcompat$(_D).o diff --git a/package/broadcom-wl/src/wlcompat/wlcompat.c b/package/broadcom-wl/src/wlcompat/wlcompat.c index 2694a851c0..5d2e74d412 100644 --- a/package/broadcom-wl/src/wlcompat/wlcompat.c +++ b/package/broadcom-wl/src/wlcompat/wlcompat.c @@ -30,6 +30,7 @@ #include <linux/wireless.h> #include <linux/timer.h> #include <linux/delay.h> +#include <linux/random.h> #include <net/iw_handler.h> #include <asm/uaccess.h> @@ -37,14 +38,15 @@ #include <bcmutils.h> #include <wlioctl.h> +char buf[WLC_IOCTL_MAXLEN]; static struct net_device *dev; -static struct iw_statistics wstats; #ifndef DEBUG static int random = 1; #endif +#ifndef WL_WEXT +static struct iw_statistics wstats; static int last_mode = -1; static int scan_cur = 0; -char buf[WLC_IOCTL_MAXLEN]; /* The frequency of each channel in MHz */ const long channel_frequency[] = { @@ -52,6 +54,7 @@ const long channel_frequency[] = { 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; #define NUM_CHANNELS ( sizeof(channel_frequency) / sizeof(channel_frequency[0]) ) +#endif #define SCAN_RETRY_MAX 5 #define RNG_POLL_FREQ 1 @@ -88,6 +91,7 @@ static int wl_ioctl(struct net_device *dev, int cmd, void *buf, int len) return ret; } +#if !defined(DEBUG) || !defined(WL_WEXT) static int wl_iovar_getbuf(struct net_device *dev, char *iovar, void *param, int paramlen, void *bufptr, int buflen) { @@ -268,6 +272,9 @@ wl_bssiovar_get(struct net_device *dev, char *iovar, int bssidx, void *outbuf, i return err; } #endif +#endif + +#ifndef WL_WEXT int get_primary_key(struct net_device *dev) { @@ -903,6 +910,7 @@ static const struct iw_handler_def wlcompat_handler_def = .num_standard = sizeof(wlcompat_handler)/sizeof(iw_handler), }; +#endif #ifdef DEBUG void print_buffer(int len, unsigned char *buf) { @@ -923,8 +931,6 @@ void print_buffer(int len, unsigned char *buf) { static int (*old_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); static int new_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int ret = 0; - struct iwreq *iwr = (struct iwreq *) ifr; - struct iw_request_info info; #ifdef DEBUG printk("dev: %s ioctl: 0x%04x\n",dev->name,cmd); @@ -975,23 +981,25 @@ static int __init wlcompat_init() { int found = 0, i; char devname[4] = "wl0"; - + while (!found && (dev = dev_get_by_name(devname))) { - if ((dev->wireless_handlers == NULL) && ((wl_ioctl(dev, WLC_GET_MAGIC, &i, sizeof(i)) == 0) && i == WLC_IOCTL_MAGIC)) + if ((wl_ioctl(dev, WLC_GET_MAGIC, &i, sizeof(i)) == 0) && (i == WLC_IOCTL_MAGIC)) found = 1; devname[2]++; } - + + if (!found) { printk("No Broadcom devices found.\n"); return -ENODEV; } - old_ioctl = dev->do_ioctl; dev->do_ioctl = new_ioctl; +#ifndef WL_WEXT dev->wireless_handlers = (struct iw_handler_def *)&wlcompat_handler_def; dev->get_wireless_stats = wlcompat_get_wireless_stats; +#endif #ifndef DEBUG if (random) { @@ -1014,8 +1022,10 @@ static void __exit wlcompat_exit() if (random) del_timer(&rng_timer); #endif +#ifndef WL_WEXT dev->get_wireless_stats = NULL; dev->wireless_handlers = NULL; +#endif dev->do_ioctl = old_ioctl; return; } |