xge-osdep.h revision 171095
1/*-
2 * Copyright (c) 2002-2007 Neterion, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/nxge/xge-osdep.h 171095 2007-06-29 22:47:18Z sam $
27 */
28
29/*
30 *  xge-osdep.h
31 *
32 *  Platform-dependent "glue" code
33 */
34
35#ifndef XGE_OSDEP_H
36#define XGE_OSDEP_H
37
38/******************************************
39 * Includes and defines
40 ******************************************/
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/mbuf.h>
44#include <sys/protosw.h>
45#include <sys/socket.h>
46#include <sys/malloc.h>
47#include <sys/kernel.h>
48#include <sys/module.h>
49#include <sys/bus.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/rman.h>
53#include <sys/stddef.h>
54#include <sys/types.h>
55#include <sys/sockio.h>
56#include <sys/proc.h>
57#include <sys/mutex.h>
58#include <sys/types.h>
59#include <sys/endian.h>
60#include <machine/bus.h>
61#include <machine/resource.h>
62#include <machine/clock.h>
63#include <vm/vm.h>
64#include <vm/pmap.h>
65#include <dev/pci/pcivar.h>
66#include <dev/pci/pcireg.h>
67#include <dev/pci/pci_private.h>
68#include <net/if.h>
69#include <net/if_arp.h>
70#include <net/ethernet.h>
71#include <net/if_dl.h>
72#include <net/if_media.h>
73#include <net/if_var.h>
74#include <net/bpf.h>
75#include <net/if_types.h>
76
77
78#define XGE_OS_PLATFORM_64BIT
79
80#if BYTE_ORDER == BIG_ENDIAN
81#define XGE_OS_HOST_BIG_ENDIAN       1
82#elif BYTE_ORDER == LITTLE_ENDIAN
83#define XGE_OS_HOST_LITTLE_ENDIAN    1
84#endif
85
86#define XGE_HAL_USE_5B_MODE                1
87#define XGE_HAL_PROCESS_LINK_INT_IN_ISR    1
88#define OS_NETSTACK_BUF struct mbuf *
89#define XGE_LL_IP_FAST_CSUM(hdr, len)  0
90
91#define xge_os_ntohs                    ntohs
92#define xge_os_ntohl                    ntohl
93#define xge_os_htons                    htons
94#define xge_os_htonl                    htonl
95
96#ifndef __DECONST
97#define __DECONST(type, var)    ((type)(uintrptr_t)(const void *)(var))
98#endif
99
100typedef struct busresources {
101        bus_space_tag_t       bus_tag;        /* DMA Tag */
102        bus_space_handle_t    bus_handle;     /* Bus handle */
103        struct resource       *bar_start_addr;/* BAR start address */
104} busresource_t;
105
106typedef struct xge_dma_alloc {
107        bus_addr_t            dma_phyaddr;    /* Physical Address */
108        caddr_t               dma_viraddr;    /* Virtual Address */
109        bus_dma_tag_t         dma_tag;        /* DMA Tag */
110        bus_dmamap_t          dma_map;        /* DMA Map */
111        bus_dma_segment_t     dma_segment;    /* DMA Segment */
112        bus_size_t            dma_size;       /* Size */
113        int                   dma_nseg;       /* Maximum scatter-gather segs. */
114} xdma;
115
116struct xge_dma_mbuf {
117        bus_addr_t            dma_phyaddr;    /* Physical Address */
118        bus_dmamap_t          dma_map;        /* DMA Map */
119};
120
121typedef struct pci_info {
122        device_t              device;         /* Device */
123        struct resource       *regmap0;       /* Resource for BAR0 */
124        struct resource       *regmap1;       /* Resource for BAR1 */
125        void                  *bar0resource;  /* BAR0 tag and handle */
126        void                  *bar1resource;  /* BAR1 tag and handle */
127} pci_info_t;
128
129
130/******************************************
131 * Fixed size primitive types
132 ******************************************/
133#define u8                         uint8_t
134#define u16                        uint16_t
135#define u32                        uint32_t
136#define u64                        uint64_t
137#define ulong_t                    unsigned long
138#define uint                       unsigned int
139#define ptrdiff_t                  ptrdiff_t
140typedef bus_addr_t                 dma_addr_t;
141typedef struct mtx                 spinlock_t;
142typedef pci_info_t                 *pci_dev_h;
143typedef busresource_t              *pci_reg_h;
144typedef struct xge_dma_alloc       pci_dma_h;
145typedef struct resource            *pci_irq_h;
146typedef pci_info_t                 *pci_cfg_h;
147typedef struct xge_dma_alloc       pci_dma_acc_h;
148
149/******************************************
150 * "libc" functionality
151 ******************************************/
152#define xge_os_memzero(addr, size)    bzero(addr, size)
153#define xge_os_memcpy(dst, src, size) bcopy(src, dst, size)
154#define xge_os_memcmp                 memcmp
155#define xge_os_strcpy                 strcpy
156#define xge_os_strlen                 strlen
157#define xge_os_snprintf               snprintf
158#define xge_os_sprintf                sprintf
159#define xge_os_printf(fmt...) {                                               \
160	printf(fmt);                                                          \
161	printf("\n");                                                         \
162}
163
164#define xge_os_vaprintf(fmt) {                                                \
165	sprintf(fmt, fmt, "\n");                                              \
166	va_list va;                                                           \
167	va_start(va, fmt);                                                    \
168	vprintf(fmt, va);                                                     \
169	va_end(va);                                                           \
170}
171
172#define xge_os_vasprintf(buf, fmt) {                                          \
173	va_list va;                                                           \
174	va_start(va, fmt);                                                    \
175	(void) vaprintf(buf, fmt, va);                                        \
176	va_end(va);                                                           \
177}
178
179#define xge_os_timestamp(buf) {                                               \
180	struct timeval current_time;                                          \
181	gettimeofday(&current_time, 0);                                       \
182	sprintf(buf, "%08li.%08li: ", current_time.tv_sec,                    \
183	    current_time.tv_usec);                                            \
184}
185
186#define xge_os_println            xge_os_printf
187
188/******************************************
189 * Synchronization Primitives
190 ******************************************/
191/* Initialize the spin lock */
192#define xge_os_spin_lock_init(lockp, ctxh)                                    \
193	if(mtx_initialized(lockp) == 0) {                                     \
194	    mtx_init((lockp), "xge", MTX_NETWORK_LOCK, MTX_DEF);              \
195	}
196
197/* Initialize the spin lock (IRQ version) */
198#define xge_os_spin_lock_init_irq(lockp, ctxh)                                \
199	if(mtx_initialized(lockp) == 0) {                                     \
200	    mtx_init((lockp), "xge", MTX_NETWORK_LOCK, MTX_DEF);              \
201	}
202
203/* Destroy the lock */
204#define xge_os_spin_lock_destroy(lockp, ctxh)                                 \
205	if(mtx_initialized(lockp) != 0) {                                     \
206	    mtx_destroy(lockp);                                               \
207	}
208
209/* Destroy the lock (IRQ version) */
210#define xge_os_spin_lock_destroy_irq(lockp, ctxh)                             \
211	if(mtx_initialized(lockp) != 0) {                                     \
212	    mtx_destroy(lockp);                                               \
213	}
214
215/* Acquire the lock */
216#define xge_os_spin_lock(lockp)                                               \
217	if(mtx_owned(lockp) == 0) mtx_lock(lockp)
218
219/* Release the lock */
220#define xge_os_spin_unlock(lockp)             mtx_unlock(lockp)
221
222/* Acquire the lock (IRQ version) */
223#define xge_os_spin_lock_irq(lockp, flags) {                                  \
224	flags = MTX_QUIET;                                                    \
225	if(mtx_owned(lockp) == 0) mtx_lock_flags(lockp, flags);               \
226}
227
228/* Release the lock (IRQ version) */
229#define xge_os_spin_unlock_irq(lockp, flags) {                                \
230	flags = MTX_QUIET;                                                    \
231	mtx_unlock_flags(lockp, flags);                                       \
232}
233
234/* Write memory barrier */
235#define xge_os_wmb()
236
237/* Delay (in micro seconds) */
238#define xge_os_udelay(us)            DELAY(us)
239
240/* Delay (in milli seconds) */
241#define xge_os_mdelay(ms)            DELAY(ms * 1000)
242
243/* Compare and exchange */
244//#define xge_os_cmpxchg(targetp, cmd, newval)
245
246/******************************************
247 * Misc primitives
248 ******************************************/
249#define xge_os_unlikely(x)    (x)
250#define xge_os_prefetch(x)    (x=x)
251#define xge_os_prefetchw(x)   (x=x)
252#define xge_os_bug(fmt...)    printf(fmt...)
253#define xge_os_htohs          ntohs
254#define xge_os_ntohl          ntohl
255#define xge_os_htons          htons
256#define xge_os_htonl          htonl
257
258/******************************************
259 * Compiler Stuffs
260 ******************************************/
261#define __xge_os_attr_cacheline_aligned
262#define __xge_os_cacheline_size        32
263
264/******************************************
265 * Memory Primitives
266 ******************************************/
267#define XGE_OS_INVALID_DMA_ADDR ((dma_addr_t)0)
268
269/******************************************
270 * xge_os_malloc - Allocate non DMA-able memory.
271 * @pdev: Device context.
272 * @size: Size to allocate.
273 *
274 * Allocate @size bytes of memory. This allocation can sleep, and
275 * therefore, and therefore it requires process context. In other words,
276 * xge_os_malloc() cannot be called from the interrupt context.
277 * Use xge_os_free() to free the allocated block.
278 *
279 * Returns: Pointer to allocated memory, NULL - on failure.
280 *
281 * See also: xge_os_free().
282 ******************************************/
283static inline void *
284xge_os_malloc(pci_dev_h pdev, unsigned long size) {
285	void *vaddr = malloc((size), M_DEVBUF, M_NOWAIT);
286	xge_os_memzero(vaddr, size);
287	XGE_OS_MEMORY_CHECK_MALLOC(vaddr, size, file, line);
288	    return (vaddr);
289}
290
291/******************************************
292 * xge_os_free - Free non DMA-able memory.
293 * @pdev: Device context.
294 * @vaddr: Address of the allocated memory block.
295 * @size: Some OS's require to provide size on free
296 *
297 * Free the memory area obtained via xge_os_malloc().
298 * This call may also sleep, and therefore it cannot be used inside
299 * interrupt.
300 *
301 * See also: xge_os_malloc().
302 ******************************************/
303static inline void
304xge_os_free(pci_dev_h pdev, const void *vaddr, unsigned long size) {
305	XGE_OS_MEMORY_CHECK_FREE(vaddr, size);
306	free(__DECONST(void *, vaddr), M_DEVBUF);
307}
308
309static void
310xge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) {
311	if(error) return;
312	*(bus_addr_t *) arg = segs->ds_addr;
313	return;
314}
315
316/******************************************
317 * xge_os_dma_malloc  -  Allocate DMA-able memory.
318 * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory.
319 * @size: Size (in bytes) to allocate.
320 * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED,
321 *             XGE_OS_DMA_STREAMING,
322 *             XGE_OS_DMA_CONSISTENT
323 *     Note that the last two flags are mutually exclusive.
324 * @p_dmah: Handle used to map the memory onto the corresponding device memory
325 *          space. See xge_os_dma_map(). The handle is an out-parameter
326 *          returned by the function.
327 * @p_dma_acch: One more DMA handle used subsequently to free the
328 *              DMA object (via xge_os_dma_free()).
329 *
330 * Allocate DMA-able contiguous memory block of the specified @size.
331 * This memory can be subsequently freed using xge_os_dma_free().
332 * Note: can be used inside interrupt context.
333 *
334 * Returns: Pointer to allocated memory(DMA-able), NULL on failure.
335 *
336 ******************************************/
337static inline void *
338xge_os_dma_malloc(pci_dev_h pdev, unsigned long size, int dma_flags,
339	pci_dma_h *p_dmah, pci_dma_acc_h *p_dma_acch) {
340	int retValue = bus_dma_tag_create(
341	    bus_get_dma_tag(pdev->device), /* Parent */
342	    PAGE_SIZE,                     /* Alignment no specific alignment */
343	    0,                             /* Bounds */
344	    BUS_SPACE_MAXADDR,             /* Low Address */
345	    BUS_SPACE_MAXADDR,             /* High Address */
346	    NULL,                          /* Filter */
347	    NULL,                          /* Filter arg */
348	    size,                          /* Max Size */
349	    1,                             /* n segments */
350	    size,                          /* max segment size */
351	    BUS_DMA_ALLOCNOW,              /* Flags */
352	    NULL,                          /* lockfunction */
353	    NULL,                          /* lock arg */
354	    &p_dmah->dma_tag);             /* DMA tag */
355	if(retValue != 0) {
356	    xge_os_printf("bus_dma_tag_create failed\n");
357	    goto fail_1;
358	}
359	p_dmah->dma_size = size;
360	retValue = bus_dmamem_alloc(p_dmah->dma_tag,
361	    (void **)&p_dmah->dma_viraddr, BUS_DMA_NOWAIT, &p_dmah->dma_map);
362	if(retValue != 0) {
363	    xge_os_printf("bus_dmamem_alloc failed\n");
364	    goto fail_2;
365	}
366	return(p_dmah->dma_viraddr);
367
368fail_2: bus_dma_tag_destroy(p_dmah->dma_tag);
369fail_1: return(NULL);
370}
371
372/******************************************
373 * xge_os_dma_free - Free previously allocated DMA-able memory.
374 * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory.
375 * @vaddr: Virtual address of the DMA-able memory.
376 * @p_dma_acch: DMA handle used to free the resource.
377 * @p_dmah: DMA handle used for mapping. See xge_os_dma_malloc().
378 *
379 * Free DMA-able memory originally allocated by xge_os_dma_malloc().
380 * Note: can be used inside interrupt.
381 * See also: xge_os_dma_malloc().
382 ******************************************/
383static inline void
384xge_os_dma_free(pci_dev_h pdev, const void *vaddr, int size,
385	pci_dma_acc_h *p_dma_acch, pci_dma_h *p_dmah) {
386	XGE_OS_MEMORY_CHECK_FREE(p_dmah->dma_viraddr, size);
387	bus_dmamem_free(p_dmah->dma_tag, p_dmah->dma_viraddr, p_dmah->dma_map);
388	bus_dma_tag_destroy(p_dmah->dma_tag);
389	p_dmah->dma_map = NULL;
390	p_dmah->dma_tag = NULL;
391	p_dmah->dma_viraddr = NULL;
392	return;
393}
394
395/******************************************
396 * IO/PCI/DMA Primitives
397 ******************************************/
398#define XGE_OS_DMA_DIR_TODEVICE        0
399#define XGE_OS_DMA_DIR_FROMDEVICE      1
400#define XGE_OS_DMA_DIR_BIDIRECTIONAL   2
401
402/******************************************
403 * xge_os_pci_read8 - Read one byte from device PCI configuration.
404 * @pdev: Device context. Some OSs require device context to perform
405 *        PIO and/or config space IO.
406 * @cfgh: PCI configuration space handle.
407 * @where: Offset in the PCI configuration space.
408 * @val: Address of the result.
409 *
410 * Read byte value from the specified @regh PCI configuration space at the
411 * specified offset = @where.
412 * Returns: 0 - success, non-zero - failure.
413 ******************************************/
414#define xge_os_pci_read8(pdev, cfgh, where, val)                              \
415	(*(val) = pci_read_config(pdev->device, where, 1))
416
417/******************************************
418 * xge_os_pci_write8 - Write one byte into device PCI configuration.
419 * @pdev: Device context. Some OSs require device context to perform
420 *        PIO and/or config space IO.
421 * @cfgh: PCI configuration space handle.
422 * @where: Offset in the PCI configuration space.
423 * @val: Value to write.
424 *
425 * Write byte value into the specified PCI configuration space
426 * Returns: 0 - success, non-zero - failure.
427 ******************************************/
428#define xge_os_pci_write8(pdev, cfgh, where, val)                             \
429	pci_write_config(pdev->device, where, val, 1)
430
431/******************************************
432 * xge_os_pci_read16 - Read 16bit word from device PCI configuration.
433 * @pdev: Device context.
434 * @cfgh: PCI configuration space handle.
435 * @where: Offset in the PCI configuration space.
436 * @val: Address of the 16bit result.
437 *
438 * Read 16bit value from the specified PCI configuration space at the
439 * specified offset.
440 * Returns: 0 - success, non-zero - failure.
441 ******************************************/
442#define xge_os_pci_read16(pdev, cfgh, where, val)                             \
443	(*(val) = pci_read_config(pdev->device, where, 2))
444
445/******************************************
446 * xge_os_pci_write16 - Write 16bit word into device PCI configuration.
447 * @pdev: Device context.
448 * @cfgh: PCI configuration space handle.
449 * @where: Offset in the PCI configuration space.
450 * @val: Value to write.
451 *
452 * Write 16bit value into the specified @offset in PCI
453 * configuration space.
454 * Returns: 0 - success, non-zero - failure.
455 ******************************************/
456#define xge_os_pci_write16(pdev, cfgh, where, val)                            \
457	pci_write_config(pdev->device, where, val, 2)
458
459/******************************************
460 * xge_os_pci_read32 - Read 32bit word from device PCI configuration.
461 * @pdev: Device context.
462 * @cfgh: PCI configuration space handle.
463 * @where: Offset in the PCI configuration space.
464 * @val: Address of 32bit result.
465 *
466 * Read 32bit value from the specified PCI configuration space at the
467 * specified offset.
468 * Returns: 0 - success, non-zero - failure.
469 ******************************************/
470#define xge_os_pci_read32(pdev, cfgh, where, val)                             \
471	(*(val) = pci_read_config(pdev->device, where, 4))
472
473/******************************************
474 * xge_os_pci_write32 - Write 32bit word into device PCI configuration.
475 * @pdev: Device context.
476 * @cfgh: PCI configuration space handle.
477 * @where: Offset in the PCI configuration space.
478 * @val: Value to write.
479 *
480 * Write 32bit value into the specified @offset in PCI
481 * configuration space.
482 * Returns: 0 - success, non-zero - failure.
483 ******************************************/
484#define xge_os_pci_write32(pdev, cfgh, where, val)                            \
485	pci_write_config(pdev->device, where, val, 4)
486
487/******************************************
488 * xge_os_pio_mem_read8 - Read 1 byte from device memory mapped space.
489 * @pdev: Device context.
490 * @regh: PCI configuration space handle.
491 * @addr: Address in device memory space.
492 *
493 * Returns: 1 byte value read from the specified (mapped) memory space address.
494 ******************************************/
495static inline u8
496xge_os_pio_mem_read8(pci_dev_h pdev, pci_reg_h regh, void *addr)
497{
498	bus_space_tag_t tag =
499	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
500	bus_space_handle_t handle =
501	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
502	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
503
504	return bus_space_read_1(tag, handle, (caddr_t)(addr) - addrss);
505}
506
507/******************************************
508 * xge_os_pio_mem_write8 - Write 1 byte into device memory mapped
509 * space.
510 * @pdev: Device context.
511 * @regh: PCI configuration space handle.
512 * @val: Value to write.
513 * @addr: Address in device memory space.
514 *
515 * Write byte value into the specified (mapped) device memory space.
516 ******************************************/
517static inline void
518xge_os_pio_mem_write8(pci_dev_h pdev, pci_reg_h regh, u8 val, void *addr)
519{
520	bus_space_tag_t tag =
521	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
522	bus_space_handle_t handle =
523	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
524	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
525
526	bus_space_write_1(tag, handle, (caddr_t)(addr) - addrss, val);
527}
528
529/******************************************
530 * xge_os_pio_mem_read16 - Read 16bit from device memory mapped space.
531 * @pdev: Device context.
532 * @regh: PCI configuration space handle.
533 * @addr: Address in device memory space.
534 *
535 * Returns: 16bit value read from the specified (mapped) memory space address.
536 ******************************************/
537static inline u16
538xge_os_pio_mem_read16(pci_dev_h pdev, pci_reg_h regh, void *addr)
539{
540	bus_space_tag_t tag =
541	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
542	bus_space_handle_t handle =
543	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
544	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
545
546	return bus_space_read_2(tag, handle, (caddr_t)(addr) - addrss);
547}
548
549/******************************************
550 * xge_os_pio_mem_write16 - Write 16bit into device memory mapped space.
551 * @pdev: Device context.
552 * @regh: PCI configuration space handle.
553 * @val: Value to write.
554 * @addr: Address in device memory space.
555 *
556 * Write 16bit value into the specified (mapped) device memory space.
557 ******************************************/
558static inline void
559xge_os_pio_mem_write16(pci_dev_h pdev, pci_reg_h regh, u16 val, void *addr)
560{
561	bus_space_tag_t tag =
562	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
563	bus_space_handle_t handle =
564	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
565	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
566
567	bus_space_write_2(tag, handle, (caddr_t)(addr) - addrss, val);
568}
569
570/******************************************
571 * xge_os_pio_mem_read32 - Read 32bit from device memory mapped space.
572 * @pdev: Device context.
573 * @regh: PCI configuration space handle.
574 * @addr: Address in device memory space.
575 *
576 * Returns: 32bit value read from the specified (mapped) memory space address.
577 ******************************************/
578static inline u32
579xge_os_pio_mem_read32(pci_dev_h pdev, pci_reg_h regh, void *addr)
580{
581	bus_space_tag_t tag =
582	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
583	bus_space_handle_t handle =
584	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
585	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
586
587	return bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss);
588}
589
590/******************************************
591 * xge_os_pio_mem_write32 - Write 32bit into device memory space.
592 * @pdev: Device context.
593 * @regh: PCI configuration space handle.
594 * @val: Value to write.
595 * @addr: Address in device memory space.
596 *
597 * Write 32bit value into the specified (mapped) device memory space.
598 ******************************************/
599static inline void
600xge_os_pio_mem_write32(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr)
601{
602	bus_space_tag_t tag =
603	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
604	bus_space_handle_t handle =
605	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
606	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
607	bus_space_write_4(tag, handle, (caddr_t)(addr) - addrss, val);
608}
609
610/******************************************
611 * xge_os_pio_mem_read64 - Read 64bit from device memory mapped space.
612 * @pdev: Device context.
613 * @regh: PCI configuration space handle.
614 * @addr: Address in device memory space.
615 *
616 * Returns: 64bit value read from the specified (mapped) memory space address.
617 ******************************************/
618static inline u64
619xge_os_pio_mem_read64(pci_dev_h pdev, pci_reg_h regh, void *addr)
620{
621	u64 value1, value2;
622
623	bus_space_tag_t tag =
624	    (bus_space_tag_t)(((busresource_t *)regh)->bus_tag);
625	bus_space_handle_t handle =
626	    (bus_space_handle_t)(((busresource_t *)regh)->bus_handle);
627	caddr_t addrss = (caddr_t)(((busresource_t *)(regh))->bar_start_addr);
628
629	value1 = bus_space_read_4(tag, handle, (caddr_t)(addr) + 4 - addrss);
630	value1 <<= 32;
631	value2 = bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss);
632	value1 |= value2;
633	return value1;
634}
635
636/******************************************
637 * xge_os_pio_mem_write64 - Write 32bit into device memory space.
638 * @pdev: Device context.
639 * @regh: PCI configuration space handle.
640 * @val: Value to write.
641 * @addr: Address in device memory space.
642 *
643 * Write 64bit value into the specified (mapped) device memory space.
644 ******************************************/
645static inline void
646xge_os_pio_mem_write64(pci_dev_h pdev, pci_reg_h regh, u64 val, void *addr)
647{
648	u32 vall = val & 0xffffffff;
649	xge_os_pio_mem_write32(pdev, regh, vall, addr);
650	xge_os_pio_mem_write32(pdev, regh, val >> 32, ((caddr_t)(addr) + 4));
651}
652
653/******************************************
654 * FIXME: document
655 ******************************************/
656#define xge_os_flush_bridge    xge_os_pio_mem_read64
657
658/******************************************
659 * xge_os_dma_map - Map DMA-able memory block to, or from, or
660 * to-and-from device.
661 * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory.
662 * @dmah: DMA handle used to map the memory block. Obtained via
663 * xge_os_dma_malloc().
664 * @vaddr: Virtual address of the DMA-able memory.
665 * @size: Size (in bytes) to be mapped.
666 * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.)
667 * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED,
668 *             XGE_OS_DMA_STREAMING,
669 *             XGE_OS_DMA_CONSISTENT
670 *     Note that the last two flags are mutually exclusive.
671 *
672 * Map a single memory block.
673 *
674 * Returns: DMA address of the memory block,
675 * XGE_OS_INVALID_DMA_ADDR on failure.
676 *
677 * See also: xge_os_dma_malloc(), xge_os_dma_unmap(),
678 * xge_os_dma_sync().
679 ******************************************/
680static inline dma_addr_t
681xge_os_dma_map(pci_dev_h pdev, pci_dma_h dmah, void *vaddr, size_t size,
682	int dir, int dma_flags)
683{
684	int retValue =
685	    bus_dmamap_load(dmah.dma_tag, dmah.dma_map, dmah.dma_viraddr,
686	    dmah.dma_size, xge_dmamap_cb, &dmah.dma_phyaddr, BUS_DMA_NOWAIT);
687	if(retValue != 0) {
688	    xge_os_printf("bus_dmamap_load_ failed\n");
689	    return XGE_OS_INVALID_DMA_ADDR;
690	}
691	dmah.dma_size = size;
692	return dmah.dma_phyaddr;
693}
694
695/******************************************
696 * xge_os_dma_unmap - Unmap DMA-able memory.
697 * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory.
698 * @dmah: DMA handle used to map the memory block. Obtained via
699 * xge_os_dma_malloc().
700 * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map().
701 * @size: Size (in bytes) to be unmapped.
702 * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.)
703 *
704 * Unmap a single DMA-able memory block that was previously mapped
705 * using xge_os_dma_map().
706 * See also: xge_os_dma_malloc(), xge_os_dma_map().
707 ******************************************/
708static inline void
709xge_os_dma_unmap(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr,
710	size_t size, int dir)
711{
712	bus_dmamap_unload(dmah.dma_tag, dmah.dma_map);
713	return;
714}
715
716/******************************************
717 * xge_os_dma_sync - Synchronize mapped memory.
718 * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory.
719 * @dmah: DMA handle used to map the memory block. Obtained via
720 * xge_os_dma_malloc().
721 * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map().
722 * @dma_offset: Offset from start of the blocke. Used by Solaris only.
723 * @length: Size of the block.
724 * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.)
725 *
726 * Make physical and CPU memory consistent for a single
727 * streaming mode DMA translation.
728 * This API compiles to NOP on cache-coherent platforms.
729 * On non cache-coherent platforms, depending on the direction
730 * of the "sync" operation, this API will effectively
731 * either invalidate CPU cache (that might contain old data),
732 * or  flush CPU cache to update physical memory.
733 * See also: xge_os_dma_malloc(), xge_os_dma_map(),
734 * xge_os_dma_unmap().
735 ******************************************/
736static inline void
737xge_os_dma_sync(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr,
738	u64 dma_offset, size_t length, int dir)
739{
740	bus_dmasync_op_t syncop;
741	switch(dir) {
742	    case XGE_OS_DMA_DIR_TODEVICE:
743	        syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_POSTWRITE;
744	        break;
745
746	    case XGE_OS_DMA_DIR_FROMDEVICE:
747	        syncop = BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD;
748	        break;
749
750	    case XGE_OS_DMA_DIR_BIDIRECTIONAL:
751	        syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREWRITE;
752	        break;
753	}
754	bus_dmamap_sync(dmah.dma_tag, dmah.dma_map, syncop);
755	return;
756}
757
758#endif /* XGE_OSDEP_H */
759