Tomato-ND 1.21
[tomato.git] / release / src / shared / linux_osl.c
blob287c428734388ce134bfec5699cb1d38b4c8d8e4
1 /*
2 * Linux OS Independent Layer
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
12 * $Id: linux_osl.c,v 1.1.1.10 2005/03/07 07:31:12 kanki Exp $
15 #define LINUX_OSL
17 #include <typedefs.h>
18 #include <bcmendian.h>
19 #include <linux/module.h>
20 #include <linuxver.h>
21 #include <linux_osl.h>
22 #include <bcmutils.h>
23 #include <linux/delay.h>
24 #ifdef mips
25 #include <asm/paccess.h>
26 #endif
27 #include <pcicfg.h>
29 #define PCI_CFG_RETRY 10
31 #define OS_HANDLE_MAGIC 0x1234abcd
32 #define BCM_MEM_FILENAME_LEN 24
34 typedef struct bcm_mem_link {
35 struct bcm_mem_link *prev;
36 struct bcm_mem_link *next;
37 uint size;
38 int line;
39 char file[BCM_MEM_FILENAME_LEN];
40 } bcm_mem_link_t;
42 typedef struct os_handle {
43 uint magic;
44 void *pdev;
45 uint malloced;
46 uint failed;
47 bcm_mem_link_t *dbgmem_list;
48 } os_handle_t;
50 void *
51 osl_attach(void *pdev)
53 os_handle_t *osh;
55 osh = kmalloc(sizeof(os_handle_t), GFP_ATOMIC);
56 ASSERT(osh);
58 osh->magic = OS_HANDLE_MAGIC;
59 osh->malloced = 0;
60 osh->failed = 0;
61 osh->dbgmem_list = NULL;
62 osh->pdev = pdev;
64 return osh;
67 void
68 osl_detach(void *osh)
70 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
71 kfree(osh);
74 void*
75 osl_pktget(void *drv, uint len, bool send)
77 struct sk_buff *skb;
79 if ((skb = dev_alloc_skb(len)) == NULL)
80 return (NULL);
82 skb_put(skb, len);
84 /* ensure the cookie field is cleared */
85 PKTSETCOOKIE(skb, NULL);
87 return ((void*) skb);
90 void
91 osl_pktfree(void *p)
93 struct sk_buff *skb, *nskb;
95 skb = (struct sk_buff*) p;
97 /* perversion: we use skb->next to chain multi-skb packets */
98 while (skb) {
99 nskb = skb->next;
100 skb->next = NULL;
101 if (skb->destructor) {
102 /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if destructor exists */
103 dev_kfree_skb_any(skb);
104 } else {
105 /* can free immediately (even in_irq()) if destructor does not exist */
106 dev_kfree_skb(skb);
108 skb = nskb;
112 uint32
113 osl_pci_read_config(void *osh, uint offset, uint size)
115 struct pci_dev *pdev;
116 uint val;
117 uint retry=PCI_CFG_RETRY;
119 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
121 /* only 4byte access supported */
122 ASSERT(size == 4);
124 pdev = ((os_handle_t *)osh)->pdev;
125 do {
126 pci_read_config_dword(pdev, offset, &val);
127 if (val != 0xffffffff)
128 break;
129 } while (retry--);
132 return (val);
135 void
136 osl_pci_write_config(void *osh, uint offset, uint size, uint val)
138 struct pci_dev *pdev;
139 uint retry=PCI_CFG_RETRY;
141 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
143 /* only 4byte access supported */
144 ASSERT(size == 4);
146 pdev = ((os_handle_t *)osh)->pdev;
148 do {
149 pci_write_config_dword(pdev, offset, val);
150 if (offset!=PCI_BAR0_WIN)
151 break;
152 if (osl_pci_read_config(osh,offset,size) == val)
153 break;
154 } while (retry--);
158 static void
159 osl_pcmcia_attr(void *osh, uint offset, char *buf, int size, bool write)
163 void
164 osl_pcmcia_read_attr(void *osh, uint offset, void *buf, int size)
166 osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE);
169 void
170 osl_pcmcia_write_attr(void *osh, uint offset, void *buf, int size)
172 osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE);
176 #ifdef BCMDBG_MEM
178 void*
179 osl_debug_malloc(void *osh, uint size, int line, char* file)
181 bcm_mem_link_t *p;
182 char* basename;
183 os_handle_t *h = (os_handle_t *)osh;
185 if (size == 0) {
186 return NULL;
189 p = (bcm_mem_link_t*)osl_malloc(osh, sizeof(bcm_mem_link_t) + size);
190 if (p == NULL)
191 return p;
193 p->size = size;
194 p->line = line;
196 basename = strrchr(file, '/');
197 /* skip the '/' */
198 if (basename)
199 basename++;
201 if (!basename)
202 basename = file;
204 strncpy(p->file, basename, BCM_MEM_FILENAME_LEN);
205 p->file[BCM_MEM_FILENAME_LEN - 1] = '\0';
207 /* link this block */
208 p->prev = NULL;
209 p->next = h->dbgmem_list;
210 if (p->next)
211 p->next->prev = p;
212 h->dbgmem_list = p;
214 return p + 1;
217 void
218 osl_debug_mfree(void *osh, void *addr, uint size, int line, char* file)
220 bcm_mem_link_t *p = (bcm_mem_link_t *)((int8*)addr - sizeof(bcm_mem_link_t));
221 os_handle_t *h = (os_handle_t *)osh;
223 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
225 if (p->size == 0) {
226 printk("osl_debug_mfree: double free on addr 0x%x size %d at line %d file %s\n",
227 (uint)addr, size, line, file);
228 return;
231 if (p->size != size) {
232 printk("osl_debug_mfree: dealloc size %d does not match alloc size %d on addr 0x%x at line %d file %s\n",
233 size, p->size, (uint)addr, line, file);
234 return;
237 /* unlink this block */
238 if (p->prev)
239 p->prev->next = p->next;
240 if (p->next)
241 p->next->prev = p->prev;
242 if (h->dbgmem_list == p)
243 h->dbgmem_list = p->next;
244 p->next = p->prev = NULL;
246 osl_mfree(osh, p, size + sizeof(bcm_mem_link_t));
249 char*
250 osl_debug_memdump(void *osh, char *buf, uint sz)
252 bcm_mem_link_t *p;
253 char *obuf;
254 os_handle_t *h = (os_handle_t *)osh;
256 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
257 obuf = buf;
259 buf += sprintf(buf, " Address\tSize\tFile:line\n");
260 for (p = h->dbgmem_list; p && ((buf - obuf) < (sz - 128)); p = p->next)
261 buf += sprintf(buf, "0x%08x\t%5d\t%s:%d\n",
262 (int)p + sizeof(bcm_mem_link_t), p->size, p->file, p->line);
264 return (obuf);
267 #endif /* BCMDBG_MEM */
269 void*
270 osl_malloc(void *osh, uint size)
272 os_handle_t *h = (os_handle_t *)osh;
273 void *addr;
275 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
276 h->malloced += size;
277 addr = kmalloc(size, GFP_ATOMIC);
278 if (!addr)
279 h->failed++;
280 return (addr);
283 void
284 osl_mfree(void *osh, void *addr, uint size)
286 os_handle_t *h = (os_handle_t *)osh;
288 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
289 h->malloced -= size;
290 kfree(addr);
293 uint
294 osl_malloced(void *osh)
296 os_handle_t *h = (os_handle_t *)osh;
298 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
299 return (h->malloced);
302 uint osl_malloc_failed(void *osh)
304 os_handle_t *h = (os_handle_t *)osh;
306 ASSERT((h && (h->magic == OS_HANDLE_MAGIC)));
307 return (h->failed);
310 void*
311 osl_dma_alloc_consistent(void *osh, uint size, ulong *pap)
313 struct pci_dev *dev;
315 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
317 dev = ((os_handle_t *)osh)->pdev;
318 return (pci_alloc_consistent(dev, size, (dma_addr_t*)pap));
321 void
322 osl_dma_free_consistent(void *osh, void *va, uint size, ulong pa)
324 struct pci_dev *dev;
326 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
328 dev = ((os_handle_t *)osh)->pdev;
329 pci_free_consistent(dev, size, va, (dma_addr_t)pa);
332 uint
333 osl_dma_map(void *osh, void *va, uint size, int direction)
335 int dir;
336 struct pci_dev *dev;
338 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
340 dev = ((os_handle_t *)osh)->pdev;
341 dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
342 return (pci_map_single(dev, va, size, dir));
345 void
346 osl_dma_unmap(void *osh, uint pa, uint size, int direction)
348 int dir;
349 struct pci_dev *dev;
351 ASSERT((osh && (((os_handle_t *)osh)->magic == OS_HANDLE_MAGIC)));
353 dev = ((os_handle_t *)osh)->pdev;
354 dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE;
355 pci_unmap_single(dev, (uint32)pa, size, dir);
358 #if defined(BINOSL)
359 void
360 osl_assert(char *exp, char *file, int line)
362 char tempbuf[255];
364 sprintf(tempbuf, "assertion \"%s\" failed: file \"%s\", line %d\n", exp, file, line);
365 panic(tempbuf);
367 #endif /* BCMDBG || BINOSL */
370 * BINOSL selects the slightly slower function-call-based binary compatible osl.
372 #ifdef BINOSL
375 osl_printf(const char *format, ...)
377 va_list args;
378 char buf[1024];
379 int len;
381 /* sprintf into a local buffer because there *is* no "vprintk()".. */
382 va_start(args, format);
383 len = vsprintf(buf, format, args);
384 va_end(args);
386 if (len > sizeof (buf)) {
387 printk("osl_printf: buffer overrun\n");
388 return (0);
391 return (printk(buf));
395 osl_sprintf(char *buf, const char *format, ...)
397 va_list args;
398 int rc;
400 va_start(args, format);
401 rc = vsprintf(buf, format, args);
402 va_end(args);
403 return (rc);
407 osl_strcmp(const char *s1, const char *s2)
409 return (strcmp(s1, s2));
413 osl_strncmp(const char *s1, const char *s2, uint n)
415 return (strncmp(s1, s2, n));
419 osl_strlen(char *s)
421 return (strlen(s));
424 char*
425 osl_strcpy(char *d, const char *s)
427 return (strcpy(d, s));
430 char*
431 osl_strncpy(char *d, const char *s, uint n)
433 return (strncpy(d, s, n));
436 void
437 bcopy(const void *src, void *dst, int len)
439 memcpy(dst, src, len);
443 bcmp(const void *b1, const void *b2, int len)
445 return (memcmp(b1, b2, len));
448 void
449 bzero(void *b, int len)
451 memset(b, '\0', len);
454 uint32
455 osl_readl(volatile uint32 *r)
457 return (readl(r));
460 uint16
461 osl_readw(volatile uint16 *r)
463 return (readw(r));
466 uint8
467 osl_readb(volatile uint8 *r)
469 return (readb(r));
472 void
473 osl_writel(uint32 v, volatile uint32 *r)
475 writel(v, r);
478 void
479 osl_writew(uint16 v, volatile uint16 *r)
481 writew(v, r);
484 void
485 osl_writeb(uint8 v, volatile uint8 *r)
487 writeb(v, r);
490 void *
491 osl_uncached(void *va)
493 #ifdef mips
494 return ((void*)KSEG1ADDR(va));
495 #else
496 return ((void*)va);
497 #endif
500 uint
501 osl_getcycles(void)
503 uint cycles;
505 #if defined(mips)
506 cycles = read_c0_count() * 2;
507 #elif defined(__i386__)
508 rdtscl(cycles);
509 #else
510 cycles = 0;
511 #endif
512 return cycles;
515 void *
516 osl_reg_map(uint32 pa, uint size)
518 return (ioremap_nocache((unsigned long)pa, (unsigned long)size));
521 void
522 osl_reg_unmap(void *va)
524 iounmap(va);
528 osl_busprobe(uint32 *val, uint32 addr)
530 #ifdef mips
531 return get_dbe(*val, (uint32*)addr);
532 #else
533 *val = readl(addr);
534 return 0;
535 #endif
538 void
539 osl_delay(uint usec)
541 udelay(usec);
544 uchar*
545 osl_pktdata(void *drv, void *skb)
547 return (((struct sk_buff*)skb)->data);
550 uint
551 osl_pktlen(void *drv, void *skb)
553 return (((struct sk_buff*)skb)->len);
556 uint
557 osl_pktheadroom(void *drv, void *skb)
559 return (uint) skb_headroom((struct sk_buff *) skb);
562 uint
563 osl_pkttailroom(void *drv, void *skb)
565 return (uint) skb_tailroom((struct sk_buff *) skb);
568 void*
569 osl_pktnext(void *drv, void *skb)
571 return (((struct sk_buff*)skb)->next);
574 void
575 osl_pktsetnext(void *skb, void *x)
577 ((struct sk_buff*)skb)->next = (struct sk_buff*)x;
580 void
581 osl_pktsetlen(void *drv, void *skb, uint len)
583 __skb_trim((struct sk_buff*)skb, len);
586 uchar*
587 osl_pktpush(void *drv, void *skb, int bytes)
589 return (skb_push((struct sk_buff*)skb, bytes));
592 uchar*
593 osl_pktpull(void *drv, void *skb, int bytes)
595 return (skb_pull((struct sk_buff*)skb, bytes));
598 void*
599 osl_pktdup(void *drv, void *skb)
601 return (skb_clone((struct sk_buff*)skb, GFP_ATOMIC));
604 void*
605 osl_pktcookie(void *skb)
607 return ((void*)((struct sk_buff*)skb)->csum);
610 void
611 osl_pktsetcookie(void *skb, void *x)
613 ((struct sk_buff*)skb)->csum = (uint)x;
616 void*
617 osl_pktlink(void *skb)
619 return (((struct sk_buff*)skb)->prev);
622 void
623 osl_pktsetlink(void *skb, void *x)
625 ((struct sk_buff*)skb)->prev = (struct sk_buff*)x;
628 uint
629 osl_pktprio(void *skb)
631 return (((struct sk_buff*)skb)->priority);
634 void
635 osl_pktsetprio(void *skb, uint x)
637 ((struct sk_buff*)skb)->priority = x;
640 #endif /* BINOSL */