mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2025-02-04 19:51:06 +02:00
90fba37c49
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10137 3c298f89-4303-0410-b956-a3cf2f4a3e73
891 lines
17 KiB
C
891 lines
17 KiB
C
/*
|
|
* Linux OS Independent Layer
|
|
*
|
|
* 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$
|
|
*/
|
|
|
|
#define LINUX_OSL
|
|
|
|
#include <typedefs.h>
|
|
#include <bcmendian.h>
|
|
#include <linuxver.h>
|
|
#include <bcmdefs.h>
|
|
#include <osl.h>
|
|
#include "linux_osl.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 OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */
|
|
#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
|
|
|
|
typedef struct bcm_mem_link
|
|
{
|
|
struct bcm_mem_link *prev;
|
|
struct bcm_mem_link *next;
|
|
uint size;
|
|
int line;
|
|
char file[BCM_MEM_FILENAME_LEN];
|
|
} bcm_mem_link_t;
|
|
|
|
#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)
|
|
{
|
|
if (bcmerror > 0)
|
|
bcmerror = 0;
|
|
else if (bcmerror < BCME_LAST)
|
|
bcmerror = BCME_ERROR;
|
|
|
|
/* Array bounds covered by ASSERT in osl_attach */
|
|
return linuxbcmerrormap[-bcmerror];
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void
|
|
osl_detach (osl_t * osh)
|
|
{
|
|
if (osh == NULL)
|
|
return;
|
|
|
|
ASSERT (osh->magic == OS_HANDLE_MAGIC);
|
|
kfree (osh);
|
|
}
|
|
|
|
/* Return a new packet. zero out pkttag */
|
|
void *
|
|
osl_pktget (osl_t * osh, uint len)
|
|
{
|
|
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)
|
|
{
|
|
uint val;
|
|
uint retry = PCI_CFG_RETRY;
|
|
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
|
|
/* only 4byte access supported */
|
|
ASSERT (size == 4);
|
|
|
|
do
|
|
{
|
|
pci_read_config_dword (osh->pdev, offset, &val);
|
|
if (val != 0xffffffff)
|
|
break;
|
|
}
|
|
while (retry--);
|
|
|
|
#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 (val);
|
|
}
|
|
|
|
void
|
|
osl_pci_write_config (osl_t * osh, uint offset, uint size, uint val)
|
|
{
|
|
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 */
|
|
}
|
|
|
|
/* 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 slot # for the pci device pointed by osh->pdev */
|
|
uint
|
|
osl_pci_slot (osl_t * osh)
|
|
{
|
|
ASSERT (osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
|
|
|
|
return PCI_SLOT (((struct pci_dev *) osh->pdev)->devfn);
|
|
}
|
|
|
|
static void
|
|
osl_pcmcia_attr (osl_t * osh, uint offset, char *buf, int size, bool write)
|
|
{
|
|
}
|
|
|
|
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);
|
|
|
|
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;
|
|
}
|
|
|
|
void
|
|
osl_debug_mfree (osl_t * osh, void *addr, uint size, int line, char *file)
|
|
{
|
|
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));
|
|
}
|
|
|
|
int
|
|
osl_debug_memdump (osl_t * osh, struct bcmstrbuf *b)
|
|
{
|
|
bcm_mem_link_t *p;
|
|
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
|
|
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);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* BCMDBG_MEM */
|
|
|
|
void *
|
|
osl_malloc (osl_t * osh, uint size)
|
|
{
|
|
void *addr;
|
|
|
|
/* only ASSERT if osh is defined */
|
|
if (osh)
|
|
ASSERT (osh->magic == OS_HANDLE_MAGIC);
|
|
|
|
if ((addr = kmalloc (size, GFP_ATOMIC)) == NULL)
|
|
{
|
|
if (osh)
|
|
osh->failed++;
|
|
return (NULL);
|
|
}
|
|
if (osh)
|
|
osh->malloced += size;
|
|
|
|
return (addr);
|
|
}
|
|
|
|
void
|
|
osl_mfree (osl_t * osh, void *addr, uint size)
|
|
{
|
|
if (osh)
|
|
{
|
|
ASSERT (osh->magic == OS_HANDLE_MAGIC);
|
|
osh->malloced -= size;
|
|
}
|
|
kfree (addr);
|
|
}
|
|
|
|
uint
|
|
osl_malloced (osl_t * osh)
|
|
{
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
return (osh->malloced);
|
|
}
|
|
|
|
uint
|
|
osl_malloc_failed (osl_t * osh)
|
|
{
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
return (osh->failed);
|
|
}
|
|
|
|
void *
|
|
osl_dma_alloc_consistent (osl_t * osh, uint size, ulong * pap)
|
|
{
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
|
|
return (pci_alloc_consistent (osh->pdev, size, (dma_addr_t *) pap));
|
|
}
|
|
|
|
void
|
|
osl_dma_free_consistent (osl_t * osh, void *va, uint size, ulong pa)
|
|
{
|
|
ASSERT ((osh && (osh->magic == OS_HANDLE_MAGIC)));
|
|
|
|
pci_free_consistent (osh->pdev, size, va, (dma_addr_t) pa);
|
|
}
|
|
|
|
uint
|
|
osl_dma_map (osl_t * osh, void *va, uint size, int direction)
|
|
{
|
|
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));
|
|
}
|
|
|
|
void
|
|
osl_dma_unmap (osl_t * osh, uint pa, uint size, int direction)
|
|
{
|
|
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);
|
|
}
|
|
|
|
#if defined(BINOSL) || defined(BCMDBG_ASSERT)
|
|
void
|
|
osl_assert (char *exp, char *file, int line)
|
|
{
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
uint cycles;
|
|
|
|
#if defined(mips)
|
|
cycles = read_c0_count () * 2;
|
|
#elif defined(__i386__)
|
|
rdtscl (cycles);
|
|
#else
|
|
cycles = 0;
|
|
#endif /* defined(mips) */
|
|
return cycles;
|
|
}
|
|
|
|
void *
|
|
osl_reg_map (uint32 pa, uint size)
|
|
{
|
|
return (ioremap_nocache ((unsigned long) pa, (unsigned long) size));
|
|
}
|
|
|
|
void
|
|
osl_reg_unmap (void *va)
|
|
{
|
|
iounmap (va);
|
|
}
|
|
|
|
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_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 ((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 */
|