| 1 | #ifndef __osl_h |
| 2 | #define __osl_h |
| 3 | |
| 4 | #include <linux/delay.h> |
| 5 | #include <typedefs.h> |
| 6 | #include <linuxver.h> |
| 7 | #include <pcicfg.h> |
| 8 | |
| 9 | #define ASSERT(n) |
| 10 | |
| 11 | #ifndef ABS |
| 12 | #define ABS(a) (((a) < 0)?-(a):(a)) |
| 13 | #endif /* ABS */ |
| 14 | |
| 15 | #ifndef MIN |
| 16 | #define MIN(a, b) (((a) < (b))?(a):(b)) |
| 17 | #endif /* MIN */ |
| 18 | |
| 19 | #ifndef MAX |
| 20 | #define MAX(a, b) (((a) > (b))?(a):(b)) |
| 21 | #endif /* MAX */ |
| 22 | |
| 23 | #define CEIL(x, y) (((x) + ((y)-1)) / (y)) |
| 24 | #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) |
| 25 | #define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) |
| 26 | #define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) |
| 27 | #define VALID_MASK(mask) !((mask) & ((mask) + 1)) |
| 28 | #ifndef OFFSETOF |
| 29 | #define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) |
| 30 | #endif /* OFFSETOF */ |
| 31 | #ifndef ARRAYSIZE |
| 32 | #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) |
| 33 | #endif |
| 34 | |
| 35 | /* |
| 36 | * Spin at most 'us' microseconds while 'exp' is true. |
| 37 | * Caller should explicitly test 'exp' when this completes |
| 38 | * and take appropriate error action if 'exp' is still true. |
| 39 | */ |
| 40 | #define SPINWAIT(exp, us) { \ |
| 41 | uint countdown = (us) + 9; \ |
| 42 | while ((exp) && (countdown >= 10)) {\ |
| 43 | OSL_DELAY(10); \ |
| 44 | countdown -= 10; \ |
| 45 | } \ |
| 46 | } |
| 47 | |
| 48 | |
| 49 | typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); |
| 50 | /* Pkttag flag should be part of public information */ |
| 51 | typedef struct { |
| 52 | bool pkttag; |
| 53 | uint pktalloced; /* Number of allocated packet buffers */ |
| 54 | bool mmbus; /* Bus supports memory-mapped register accesses */ |
| 55 | pktfree_cb_fn_t tx_fn; /* Callback function for PKTFREE */ |
| 56 | void *tx_ctx; /* Context to the callback function */ |
| 57 | } osl_pubinfo_t; |
| 58 | |
| 59 | struct osl_info { |
| 60 | osl_pubinfo_t pub; |
| 61 | uint magic; |
| 62 | void *pdev; |
| 63 | uint malloced; |
| 64 | uint failed; |
| 65 | uint bustype; |
| 66 | void *dbgmem_list; |
| 67 | }; |
| 68 | |
| 69 | typedef struct osl_info osl_t; |
| 70 | |
| 71 | #define PCI_CFG_RETRY 10 |
| 72 | |
| 73 | /* map/unmap direction */ |
| 74 | #define DMA_TX 1 /* TX direction for DMA */ |
| 75 | #define DMA_RX 2 /* RX direction for DMA */ |
| 76 | |
| 77 | #define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) |
| 78 | #define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) |
| 79 | #define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) |
| 80 | |
| 81 | /* bcopy, bcmp, and bzero */ |
| 82 | #define bcopy(src, dst, len) memcpy((dst), (src), (len)) |
| 83 | #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) |
| 84 | #define bzero(b, len) memset((b), '\0', (len)) |
| 85 | |
| 86 | /* uncached virtual address */ |
| 87 | #ifdef mips |
| 88 | #define OSL_UNCACHED(va) KSEG1ADDR((va)) |
| 89 | #include <asm/addrspace.h> |
| 90 | #else |
| 91 | #define OSL_UNCACHED(va) (va) |
| 92 | #endif /* mips */ |
| 93 | |
| 94 | |
| 95 | #ifndef IL_BIGENDIAN |
| 96 | #define R_REG(osh, r) (\ |
| 97 | sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \ |
| 98 | sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \ |
| 99 | readl((volatile uint32*)(r)) \ |
| 100 | ) |
| 101 | #define W_REG(osh, r, v) do { \ |
| 102 | switch (sizeof(*(r))) { \ |
| 103 | case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ |
| 104 | case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ |
| 105 | case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ |
| 106 | } \ |
| 107 | } while (0) |
| 108 | #else /* IL_BIGENDIAN */ |
| 109 | #define R_REG(osh, r) ({ \ |
| 110 | __typeof(*(r)) __osl_v; \ |
| 111 | switch (sizeof(*(r))) { \ |
| 112 | case sizeof(uint8): __osl_v = readb((volatile uint8*)((uint32)r^3)); break; \ |
| 113 | case sizeof(uint16): __osl_v = readw((volatile uint16*)((uint32)r^2)); break; \ |
| 114 | case sizeof(uint32): __osl_v = readl((volatile uint32*)(r)); break; \ |
| 115 | } \ |
| 116 | __osl_v; \ |
| 117 | }) |
| 118 | #define W_REG(osh, r, v) do { \ |
| 119 | switch (sizeof(*(r))) { \ |
| 120 | case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)((uint32)r^3)); break; \ |
| 121 | case sizeof(uint16): writew((uint16)(v), (volatile uint16*)((uint32)r^2)); break; \ |
| 122 | case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ |
| 123 | } \ |
| 124 | } while (0) |
| 125 | #endif /* IL_BIGENDIAN */ |
| 126 | |
| 127 | /* dereference an address that may cause a bus exception */ |
| 128 | #define BUSPROBE(val, addr) get_dbe((val), (addr)) |
| 129 | #include <asm/paccess.h> |
| 130 | |
| 131 | /* map/unmap physical to virtual I/O */ |
| 132 | #define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) |
| 133 | #define REG_UNMAP(va) iounmap((void *)(va)) |
| 134 | |
| 135 | /* shared (dma-able) memory access macros */ |
| 136 | #define R_SM(r) *(r) |
| 137 | #define W_SM(r, v) (*(r) = (v)) |
| 138 | #define BZERO_SM(r, len) memset((r), '\0', (len)) |
| 139 | |
| 140 | #define MALLOC(osh, size) kmalloc((size), GFP_ATOMIC) |
| 141 | #define MFREE(osh, addr, size) kfree((addr)) |
| 142 | #define MALLOCED(osh) (0) |
| 143 | |
| 144 | #define OSL_DELAY _osl_delay |
| 145 | static inline void _osl_delay(uint usec) |
| 146 | { |
| 147 | uint d; |
| 148 | |
| 149 | while (usec > 0) { |
| 150 | d = MIN(usec, 1000); |
| 151 | udelay(d); |
| 152 | usec -= d; |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | static inline void |
| 157 | bcm_mdelay(uint ms) |
| 158 | { |
| 159 | uint i; |
| 160 | |
| 161 | for (i = 0; i < ms; i++) { |
| 162 | OSL_DELAY(1000); |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | |
| 167 | #define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) |
| 168 | #define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) |
| 169 | |
| 170 | #define OSL_PCI_READ_CONFIG(osh, offset, size) \ |
| 171 | _osl_pci_read_config((osh), (offset), (size)) |
| 172 | |
| 173 | static inline uint32 |
| 174 | _osl_pci_read_config(osl_t *osh, uint offset, uint size) |
| 175 | { |
| 176 | uint val; |
| 177 | uint retry = PCI_CFG_RETRY; |
| 178 | |
| 179 | do { |
| 180 | pci_read_config_dword(osh->pdev, offset, &val); |
| 181 | if (val != 0xffffffff) |
| 182 | break; |
| 183 | } while (retry--); |
| 184 | |
| 185 | return (val); |
| 186 | } |
| 187 | |
| 188 | #define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ |
| 189 | _osl_pci_write_config((osh), (offset), (size), (val)) |
| 190 | static inline void |
| 191 | _osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) |
| 192 | { |
| 193 | uint retry = PCI_CFG_RETRY; |
| 194 | |
| 195 | do { |
| 196 | pci_write_config_dword(osh->pdev, offset, val); |
| 197 | if (offset != PCI_BAR0_WIN) |
| 198 | break; |
| 199 | if (_osl_pci_read_config(osh, offset, size) == val) |
| 200 | break; |
| 201 | } while (retry--); |
| 202 | } |
| 203 | |
| 204 | |
| 205 | /* return bus # for the pci device pointed by osh->pdev */ |
| 206 | #define OSL_PCI_BUS(osh) _osl_pci_bus(osh) |
| 207 | static inline uint |
| 208 | _osl_pci_bus(osl_t *osh) |
| 209 | { |
| 210 | return ((struct pci_dev *)osh->pdev)->bus->number; |
| 211 | } |
| 212 | |
| 213 | /* return slot # for the pci device pointed by osh->pdev */ |
| 214 | #define OSL_PCI_SLOT(osh) _osl_pci_slot(osh) |
| 215 | static inline uint |
| 216 | _osl_pci_slot(osl_t *osh) |
| 217 | { |
| 218 | return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); |
| 219 | } |
| 220 | |
| 221 | #endif |
| 222 | |