X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/ed261aac7dd5c71351f720ab16a12b5bd8c1073b..0bd45e87d91cc618487a629910a025767cfae4a1:/package/broadcom-wl/src/driver/linux_osl.c?ds=sidebyside diff --git a/package/broadcom-wl/src/driver/linux_osl.c b/package/broadcom-wl/src/driver/linux_osl.c index 24fd77dae..cc55eb68e 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 #include -#include #include #include #include #include "linux_osl.h" -#include +#include "bcmutils.h" #include #ifdef mips #include #endif /* mips */ #include -#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 */