📄 linux_osl.c
字号:
/* * Linux OS Independent Layer * * Copyright 2005-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$ */#define LINUX_OSL#include <typedefs.h>#include <bcmendian.h>#include <linux/module.h>#include <linuxver.h>#include <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;struct osl_info { uint magic; void *pdev; uint malloced; uint failed; bool pkttag; /* require pkttag structure */ bcm_mem_link_t *dbgmem_list;};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 */};/* translate bcmerrors into linux errors */intosl_error(int bcmerror){ int abs_bcmerror; int array_size = ARRAYSIZE(linuxbcmerrormap); abs_bcmerror = ABS(bcmerror); if (bcmerror > 0) abs_bcmerror = 0; else if (abs_bcmerror >= array_size) abs_bcmerror = BCME_ERROR; return linuxbcmerrormap[abs_bcmerror];}osl_t *osl_attach(void *pdev, bool pkttag){ osl_t *osh; osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); ASSERT(osh); bzero(osh, sizeof(osl_t)); /* * check the cases where * 1.Error code Added to bcmerror table, but forgot to add it to the OS * dependent error code * 2. Error code is added to the bcmerror table, but forgot to add the * corresponding errorstring(dummy call to bcmerrorstr) */ bcmerrorstr(0); ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); osh->magic = OS_HANDLE_MAGIC; osh->malloced = 0; osh->failed = 0; osh->dbgmem_list = NULL; osh->pdev = pdev; osh->pkttag = pkttag; return osh;}voidosl_detach(osl_t *osh){ if (osh == NULL) return; ASSERT(osh->magic == OS_HANDLE_MAGIC); kfree(osh);}/* Return a new packet. zero out pkttag */void*osl_pktget(osl_t *osh, uint len, bool send){ struct sk_buff *skb; if ((skb = dev_alloc_skb(len))) { skb_put(skb, len); skb->priority = 0; } return ((void*) skb);}/* Free the driver packet. Free the tag if present */voidosl_pktfree(osl_t *osh, void *p){ struct sk_buff *skb, *nskb; skb = (struct sk_buff*) p; /* perversion: we use skb->next to chain multi-skb packets */ while (skb) { nskb = skb->next; skb->next = NULL; 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); } skb = nskb; }}uint32osl_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--); return (val);}voidosl_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--);}/* return bus # for the pci device pointed by osh->pdev */uintosl_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 */uintosl_pci_slot(osl_t *osh){ ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);}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);}voidosl_mfree(osl_t *osh, void *addr, uint size){ if (osh) { ASSERT(osh->magic == OS_HANDLE_MAGIC); osh->malloced -= size; } kfree(addr);}uintosl_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));}voidosl_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);}uintosl_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));}voidosl_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)voidosl_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 || BINOSL */voidosl_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) { if (osh->pkttag) bzero((void*)((struct sk_buff *)skb)->cb, OSL_PKTTAG_SZ); return NULL; } return (p);}/* * BINOSL selects the slightly slower function-call-based binary compatible osl. */#ifdef BINOSLintosl_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));}intosl_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);}intosl_strcmp(const char *s1, const char *s2){ return (strcmp(s1, s2));}intosl_strncmp(const char *s1, const char *s2, uint n){ return (strncmp(s1, s2, n));}intosl_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));}voidbcopy(const void *src, void *dst, int len){ memcpy(dst, src, len);}intbcmp(const void *b1, const void *b2, int len){ return (memcmp(b1, b2, len));}voidbzero(void *b, int len){ memset(b, '\0', len);}uint32osl_readl(volatile uint32 *r){ return (readl(r));}uint16osl_readw(volatile uint16 *r){ return (readw(r));}uint8osl_readb(volatile uint8 *r){ return (readb(r));}voidosl_writel(uint32 v, volatile uint32 *r){ writel(v, r);}voidosl_writew(uint16 v, volatile uint16 *r){ writew(v, r);}voidosl_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 */}uintosl_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));}voidosl_reg_unmap(void *va){ iounmap(va);}intosl_busprobe(uint32 *val, uint32 addr){#ifdef mips return get_dbe(*val, (uint32*)addr);#else *val = readl(addr); return 0;#endif /* mips */}boolosl_pktshared(void *skb){ return (((struct sk_buff*)skb)->cloned);}uchar*osl_pktdata(osl_t *osh, void *skb){ return (((struct sk_buff*)skb)->data);}uintosl_pktlen(osl_t *osh, void *skb){ return (((struct sk_buff*)skb)->len);}uintosl_pktheadroom(osl_t *osh, void *skb){ return (uint) skb_headroom((struct sk_buff *) skb);}uintosl_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);}voidosl_pktsetnext(void *skb, void *x){ ((struct sk_buff*)skb)->next = (struct sk_buff*)x;}voidosl_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);}voidosl_pktsetlink(void *skb, void *x){ ((struct sk_buff*)skb)->prev = (struct sk_buff*)x;}uintosl_pktprio(void *skb){ return (((struct sk_buff*)skb)->priority);}voidosl_pktsetprio(void *skb, uint x){ ((struct sk_buff*)skb)->priority = x;}#endif /* BINOSL *//* 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){ if (osh->pkttag) bzero((void*)skb->cb, OSL_PKTTAG_SZ); return (void *)skb;}/* Convert a driver packet to native(OS) packet * In the process, packettag is zeroed out before sending up */struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt){ return (struct sk_buff *)pkt;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -