c7628965c0e5cf93ddcd702e654d0a4b33917f36
2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <bcmendian.h>
23 #include <linux/delay.h>
25 #include <asm/paccess.h>
31 #define PCI_CFG_RETRY 10
33 #define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognise osh */
34 #define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */
36 typedef struct bcm_mem_link
{
37 struct bcm_mem_link
*prev
;
38 struct bcm_mem_link
*next
;
41 char file
[BCM_MEM_FILENAME_LEN
];
51 bcm_mem_link_t
*dbgmem_list
;
54 /* Global ASSERT type flag */
57 static int16 linuxbcmerrormap
[] = { 0, /* 0 */
58 -EINVAL
, /* BCME_ERROR */
59 -EINVAL
, /* BCME_BADARG */
60 -EINVAL
, /* BCME_BADOPTION */
61 -EINVAL
, /* BCME_NOTUP */
62 -EINVAL
, /* BCME_NOTDOWN */
63 -EINVAL
, /* BCME_NOTAP */
64 -EINVAL
, /* BCME_NOTSTA */
65 -EINVAL
, /* BCME_BADKEYIDX */
66 -EINVAL
, /* BCME_RADIOOFF */
67 -EINVAL
, /* BCME_NOTBANDLOCKED */
68 -EINVAL
, /* BCME_NOCLK */
69 -EINVAL
, /* BCME_BADRATESET */
70 -EINVAL
, /* BCME_BADBAND */
71 -E2BIG
, /* BCME_BUFTOOSHORT */
72 -E2BIG
, /* BCME_BUFTOOLONG */
73 -EBUSY
, /* BCME_BUSY */
74 -EINVAL
, /* BCME_NOTASSOCIATED */
75 -EINVAL
, /* BCME_BADSSIDLEN */
76 -EINVAL
, /* BCME_OUTOFRANGECHAN */
77 -EINVAL
, /* BCME_BADCHAN */
78 -EFAULT
, /* BCME_BADADDR */
79 -ENOMEM
, /* BCME_NORESOURCE */
80 -EOPNOTSUPP
, /* BCME_UNSUPPORTED */
81 -EMSGSIZE
, /* BCME_BADLENGTH */
82 -EINVAL
, /* BCME_NOTREADY */
83 -EPERM
, /* BCME_NOTPERMITTED */
84 -ENOMEM
, /* BCME_NOMEM */
85 -EINVAL
, /* BCME_ASSOCIATED */
86 -ERANGE
, /* BCME_RANGE */
87 -EINVAL
, /* BCME_NOTFOUND */
88 -EINVAL
, /* BCME_WME_NOT_ENABLED */
89 -EINVAL
, /* BCME_TSPEC_NOTFOUND */
90 -EINVAL
, /* BCME_ACM_NOTSUPPORTED */
91 -EINVAL
, /* BCME_NOT_WME_ASSOCIATION */
92 -EIO
, /* BCME_SDIO_ERROR */
93 -ENODEV
, /* BCME_DONGLE_DOWN */
94 -EINVAL
, /* BCME_VERSION */
95 -EIO
, /* BCME_TXFAIL */
96 -EIO
, /* BCME_RXFAIL */
97 -EINVAL
, /* BCME_NODEVICE */
98 -EINVAL
, /* BCME_NMODE_DISABLED */
99 -ENODATA
, /* BCME_NONRESIDENT */
101 /* When an new error code is added to bcmutils.h, add os
102 * spcecific error translation here as well
104 /* check if BCME_LAST changed since the last time this function was updated */
106 #error "You need to add a OS error translation in the linuxbcmerrormap \
107 for new error code defined in bcmutils.h"
111 /* translate bcmerrors into linux errors */
112 int osl_error(int bcmerror
)
116 else if (bcmerror
< BCME_LAST
)
117 bcmerror
= BCME_ERROR
;
119 /* Array bounds covered by ASSERT in osl_attach */
120 return linuxbcmerrormap
[-bcmerror
];
123 osl_t
*osl_attach(void *pdev
, uint bustype
, bool pkttag
)
127 osh
= kmalloc(sizeof(osl_t
), GFP_ATOMIC
);
130 bzero(osh
, sizeof(osl_t
));
132 /* Check that error map has the right number of entries in it */
133 ASSERT(ABS(BCME_LAST
) == (ARRAYSIZE(linuxbcmerrormap
) - 1));
135 osh
->magic
= OS_HANDLE_MAGIC
;
138 osh
->dbgmem_list
= NULL
;
140 osh
->pub
.pkttag
= pkttag
;
141 osh
->bustype
= bustype
;
146 osh
->pub
.mmbus
= TRUE
;
153 osh
->pub
.mmbus
= FALSE
;
163 ASSERT(OSL_PKTTAG_SZ
<= sizeof(skb
->cb
));
169 void osl_detach(osl_t
*osh
)
174 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
178 /* Return a new packet. zero out pkttag */
179 void *BCMFASTPATH
osl_pktget(osl_t
*osh
, uint len
)
183 skb
= dev_alloc_skb(len
);
188 osh
->pub
.pktalloced
++;
194 /* Free the driver packet. Free the tag if present */
195 void BCMFASTPATH
osl_pktfree(osl_t
*osh
, void *p
, bool send
)
197 struct sk_buff
*skb
, *nskb
;
200 skb
= (struct sk_buff
*)p
;
203 if (send
&& osh
->pub
.tx_fn
)
204 osh
->pub
.tx_fn(osh
->pub
.tx_ctx
, p
, 0);
206 /* perversion: we use skb->next to chain multi-skb packets */
212 /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
215 dev_kfree_skb_any(skb
);
217 /* can free immediately (even in_irq()) if destructor
222 osh
->pub
.pktalloced
--;
228 uint32
osl_pci_read_config(osl_t
*osh
, uint offset
, uint size
)
231 uint retry
= PCI_CFG_RETRY
;
233 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
235 /* only 4byte access supported */
239 pci_read_config_dword(osh
->pdev
, offset
, &val
);
240 if (val
!= 0xffffffff)
245 if (retry
< PCI_CFG_RETRY
)
246 printk("PCI CONFIG READ access to %d required %d retries\n",
247 offset
, (PCI_CFG_RETRY
- retry
));
253 void osl_pci_write_config(osl_t
*osh
, uint offset
, uint size
, uint val
)
255 uint retry
= PCI_CFG_RETRY
;
257 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
259 /* only 4byte access supported */
263 pci_write_config_dword(osh
->pdev
, offset
, val
);
264 if (offset
!= PCI_BAR0_WIN
)
266 if (osl_pci_read_config(osh
, offset
, size
) == val
)
271 if (retry
< PCI_CFG_RETRY
)
272 printk("PCI CONFIG WRITE access to %d required %d retries\n",
273 offset
, (PCI_CFG_RETRY
- retry
));
277 /* return bus # for the pci device pointed by osh->pdev */
278 uint
osl_pci_bus(osl_t
*osh
)
280 ASSERT(osh
&& (osh
->magic
== OS_HANDLE_MAGIC
) && osh
->pdev
);
282 return ((struct pci_dev
*)osh
->pdev
)->bus
->number
;
285 /* return slot # for the pci device pointed by osh->pdev */
286 uint
osl_pci_slot(osl_t
*osh
)
288 ASSERT(osh
&& (osh
->magic
== OS_HANDLE_MAGIC
) && osh
->pdev
);
290 return PCI_SLOT(((struct pci_dev
*)osh
->pdev
)->devfn
);
294 osl_pcmcia_attr(osl_t
*osh
, uint offset
, char *buf
, int size
, bool write
)
298 void osl_pcmcia_read_attr(osl_t
*osh
, uint offset
, void *buf
, int size
)
300 osl_pcmcia_attr(osh
, offset
, (char *)buf
, size
, FALSE
);
303 void osl_pcmcia_write_attr(osl_t
*osh
, uint offset
, void *buf
, int size
)
305 osl_pcmcia_attr(osh
, offset
, (char *)buf
, size
, TRUE
);
308 void *osl_malloc(osl_t
*osh
, uint size
)
312 /* only ASSERT if osh is defined */
314 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
316 addr
= kmalloc(size
, GFP_ATOMIC
);
323 osh
->malloced
+= size
;
328 void osl_mfree(osl_t
*osh
, void *addr
, uint size
)
331 ASSERT(osh
->magic
== OS_HANDLE_MAGIC
);
332 osh
->malloced
-= size
;
337 uint
osl_malloced(osl_t
*osh
)
339 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
340 return osh
->malloced
;
343 uint
osl_malloc_failed(osl_t
*osh
)
345 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
349 uint
osl_dma_consistent_align(void)
354 void *osl_dma_alloc_consistent(osl_t
*osh
, uint size
, uint16 align_bits
,
355 uint
*alloced
, unsigned long *pap
)
357 uint16 align
= (1 << align_bits
);
358 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
360 if (!ISALIGNED(DMA_CONSISTENT_ALIGN
, align
))
364 return pci_alloc_consistent(osh
->pdev
, size
, (dma_addr_t
*) pap
);
367 void osl_dma_free_consistent(osl_t
*osh
, void *va
, uint size
, unsigned long pa
)
369 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
371 pci_free_consistent(osh
->pdev
, size
, va
, (dma_addr_t
) pa
);
374 uint BCMFASTPATH
osl_dma_map(osl_t
*osh
, void *va
, uint size
, int direction
)
378 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
379 dir
= (direction
== DMA_TX
) ? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE
;
380 return pci_map_single(osh
->pdev
, va
, size
, dir
);
383 void BCMFASTPATH
osl_dma_unmap(osl_t
*osh
, uint pa
, uint size
, int direction
)
387 ASSERT((osh
&& (osh
->magic
== OS_HANDLE_MAGIC
)));
388 dir
= (direction
== DMA_TX
) ? PCI_DMA_TODEVICE
: PCI_DMA_FROMDEVICE
;
389 pci_unmap_single(osh
->pdev
, (uint32
) pa
, size
, dir
);
392 #if defined(BCMDBG_ASSERT)
393 void osl_assert(char *exp
, char *file
, int line
)
398 basename
= strrchr(file
, '/');
407 snprintf(tempbuf
, 256,
408 "assertion \"%s\" failed: file \"%s\", line %d\n", exp
,
411 /* Print assert message and give it time to be written to /var/log/messages */
412 if (!in_interrupt()) {
414 printk("%s", tempbuf
);
415 printk("panic in %d seconds\n", delay
);
416 set_current_state(TASK_INTERRUPTIBLE
);
417 schedule_timeout(delay
* HZ
);
420 switch (g_assert_type
) {
422 panic("%s", tempbuf
);
425 printk("%s", tempbuf
);
429 printk("%s", tempbuf
);
434 #endif /* BCMDBG_ASSERT */
437 #endif /* defined(BCMDBG_ASSERT) */
439 void osl_delay(uint usec
)
451 * The pkttag contents are NOT cloned.
453 void *osl_pktdup(osl_t
*osh
, void *skb
)
457 p
= skb_clone((struct sk_buff
*)skb
, GFP_ATOMIC
);
461 /* skb_clone copies skb->cb.. we don't want that */
463 bzero((void *)((struct sk_buff
*)p
)->cb
, OSL_PKTTAG_SZ
);
465 /* Increment the packet counter */
466 osh
->pub
.pktalloced
++;
471 u8
osl_readb(osl_t
*osh
, volatile u8
*r
)
473 osl_rreg_fn_t rreg
= ((osl_pubinfo_t
*) osh
)->rreg_fn
;
474 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
476 return (u8
) ((rreg
) (ctx
, (void *)r
, sizeof(u8
)));
479 uint16
osl_readw(osl_t
*osh
, volatile uint16
*r
)
481 osl_rreg_fn_t rreg
= ((osl_pubinfo_t
*) osh
)->rreg_fn
;
482 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
484 return (uint16
) ((rreg
) (ctx
, (void *)r
, sizeof(uint16
)));
487 uint32
osl_readl(osl_t
*osh
, volatile uint32
*r
)
489 osl_rreg_fn_t rreg
= ((osl_pubinfo_t
*) osh
)->rreg_fn
;
490 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
492 return (uint32
) ((rreg
) (ctx
, (void *)r
, sizeof(uint32
)));
495 void osl_writeb(osl_t
*osh
, volatile u8
*r
, u8 v
)
497 osl_wreg_fn_t wreg
= ((osl_pubinfo_t
*) osh
)->wreg_fn
;
498 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
500 ((wreg
) (ctx
, (void *)r
, v
, sizeof(u8
)));
503 void osl_writew(osl_t
*osh
, volatile uint16
*r
, uint16 v
)
505 osl_wreg_fn_t wreg
= ((osl_pubinfo_t
*) osh
)->wreg_fn
;
506 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
508 ((wreg
) (ctx
, (void *)r
, v
, sizeof(uint16
)));
511 void osl_writel(osl_t
*osh
, volatile uint32
*r
, uint32 v
)
513 osl_wreg_fn_t wreg
= ((osl_pubinfo_t
*) osh
)->wreg_fn
;
514 void *ctx
= ((osl_pubinfo_t
*) osh
)->reg_ctx
;
516 ((wreg
) (ctx
, (void *)r
, v
, sizeof(uint32
)));
519 /* Linux Kernel: File Operations: end */
This page took 0.052546 seconds and 4 git commands to generate.