1171095Ssam/*- 2171095Ssam * Copyright (c) 2002-2007 Neterion, Inc. 3171095Ssam * All rights reserved. 4171095Ssam * 5171095Ssam * Redistribution and use in source and binary forms, with or without 6171095Ssam * modification, are permitted provided that the following conditions 7171095Ssam * are met: 8171095Ssam * 1. Redistributions of source code must retain the above copyright 9171095Ssam * notice, this list of conditions and the following disclaimer. 10171095Ssam * 2. Redistributions in binary form must reproduce the above copyright 11171095Ssam * notice, this list of conditions and the following disclaimer in the 12171095Ssam * documentation and/or other materials provided with the distribution. 13171095Ssam * 14171095Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15171095Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16171095Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17171095Ssam * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18171095Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19171095Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20171095Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21171095Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22171095Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23171095Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24171095Ssam * SUCH DAMAGE. 25171095Ssam * 26171095Ssam * $FreeBSD$ 27171095Ssam */ 28171095Ssam 29171095Ssam#ifndef XGE_OSDEP_H 30171095Ssam#define XGE_OSDEP_H 31171095Ssam 32173139Srwatson/** 33171095Ssam * Includes and defines 34173139Srwatson */ 35171095Ssam#include <sys/param.h> 36171095Ssam#include <sys/systm.h> 37171095Ssam#include <sys/mbuf.h> 38171095Ssam#include <sys/protosw.h> 39171095Ssam#include <sys/socket.h> 40171095Ssam#include <sys/malloc.h> 41171095Ssam#include <sys/kernel.h> 42171095Ssam#include <sys/module.h> 43171095Ssam#include <sys/bus.h> 44171095Ssam#include <sys/lock.h> 45171095Ssam#include <sys/mutex.h> 46171095Ssam#include <sys/rman.h> 47171095Ssam#include <sys/stddef.h> 48171095Ssam#include <sys/types.h> 49171095Ssam#include <sys/sockio.h> 50171095Ssam#include <sys/proc.h> 51171095Ssam#include <sys/mutex.h> 52171095Ssam#include <sys/types.h> 53171095Ssam#include <sys/endian.h> 54173139Srwatson#include <sys/sysctl.h> 55173139Srwatson#include <sys/endian.h> 56173139Srwatson#include <sys/socket.h> 57171095Ssam#include <machine/bus.h> 58171095Ssam#include <machine/resource.h> 59171095Ssam#include <machine/clock.h> 60171095Ssam#include <vm/vm.h> 61171095Ssam#include <vm/pmap.h> 62171095Ssam#include <dev/pci/pcivar.h> 63171095Ssam#include <dev/pci/pcireg.h> 64171095Ssam#include <dev/pci/pci_private.h> 65171095Ssam#include <net/if.h> 66171095Ssam#include <net/if_arp.h> 67171095Ssam#include <net/ethernet.h> 68171095Ssam#include <net/if_dl.h> 69171095Ssam#include <net/if_media.h> 70171095Ssam#include <net/if_var.h> 71171095Ssam#include <net/bpf.h> 72171095Ssam#include <net/if_types.h> 73173139Srwatson#include <netinet/in_systm.h> 74173139Srwatson#include <netinet/in.h> 75173139Srwatson#include <netinet/ip.h> 76173139Srwatson#include <netinet/tcp.h> 77171095Ssam 78171095Ssam#define XGE_OS_PLATFORM_64BIT 79171095Ssam 80171095Ssam#if BYTE_ORDER == BIG_ENDIAN 81173139Srwatson#define XGE_OS_HOST_BIG_ENDIAN 82171095Ssam#elif BYTE_ORDER == LITTLE_ENDIAN 83173139Srwatson#define XGE_OS_HOST_LITTLE_ENDIAN 84171095Ssam#endif 85171095Ssam 86173139Srwatson#define XGE_HAL_USE_5B_MODE 87173139Srwatson 88173139Srwatson#ifdef XGE_TRACE_ASSERT 89173139Srwatson#undef XGE_TRACE_ASSERT 90173139Srwatson#endif 91173139Srwatson 92171095Ssam#define OS_NETSTACK_BUF struct mbuf * 93171095Ssam#define XGE_LL_IP_FAST_CSUM(hdr, len) 0 94171095Ssam 95173139Srwatson#ifndef __DECONST 96173139Srwatson#define __DECONST(type, var) ((type)(uintrptr_t)(const void *)(var)) 97173139Srwatson#endif 98173139Srwatson 99171095Ssam#define xge_os_ntohs ntohs 100171095Ssam#define xge_os_ntohl ntohl 101171095Ssam#define xge_os_htons htons 102171095Ssam#define xge_os_htonl htonl 103171095Ssam 104173139Srwatsontypedef struct xge_bus_resource_t { 105173139Srwatson bus_space_tag_t bus_tag; /* DMA Tag */ 106173139Srwatson bus_space_handle_t bus_handle; /* Bus handle */ 107173139Srwatson struct resource *bar_start_addr;/* BAR start address */ 108173139Srwatson} xge_bus_resource_t; 109171095Ssam 110173139Srwatsontypedef struct xge_dma_alloc_t { 111173139Srwatson bus_addr_t dma_phyaddr; /* Physical Address */ 112173139Srwatson caddr_t dma_viraddr; /* Virtual Address */ 113173139Srwatson bus_dma_tag_t dma_tag; /* DMA Tag */ 114173139Srwatson bus_dmamap_t dma_map; /* DMA Map */ 115173139Srwatson bus_dma_segment_t dma_segment; /* DMA Segment */ 116173139Srwatson bus_size_t dma_size; /* Size */ 117173139Srwatson int dma_nseg; /* Maximum scatter-gather segs. */ 118173139Srwatson} xge_dma_alloc_t; 119171095Ssam 120173139Srwatsontypedef struct xge_dma_mbuf_t { 121173139Srwatson bus_addr_t dma_phyaddr; /* Physical Address */ 122173139Srwatson bus_dmamap_t dma_map; /* DMA Map */ 123173139Srwatson}xge_dma_mbuf_t; 124171095Ssam 125173139Srwatsontypedef struct xge_pci_info { 126173139Srwatson device_t device; /* Device */ 127173139Srwatson struct resource *regmap0; /* Resource for BAR0 */ 128173139Srwatson struct resource *regmap1; /* Resource for BAR1 */ 129173139Srwatson void *bar0resource; /* BAR0 tag and handle */ 130173139Srwatson void *bar1resource; /* BAR1 tag and handle */ 131173139Srwatson} xge_pci_info_t; 132171095Ssam 133171095Ssam 134173139Srwatson/** 135171095Ssam * Fixed size primitive types 136173139Srwatson */ 137171095Ssam#define u8 uint8_t 138171095Ssam#define u16 uint16_t 139171095Ssam#define u32 uint32_t 140171095Ssam#define u64 uint64_t 141171095Ssam#define ulong_t unsigned long 142171095Ssam#define uint unsigned int 143171095Ssam#define ptrdiff_t ptrdiff_t 144171095Ssamtypedef bus_addr_t dma_addr_t; 145171095Ssamtypedef struct mtx spinlock_t; 146173139Srwatsontypedef xge_pci_info_t *pci_dev_h; 147173139Srwatsontypedef xge_bus_resource_t *pci_reg_h; 148173139Srwatsontypedef xge_dma_alloc_t pci_dma_h; 149173139Srwatsontypedef xge_dma_alloc_t pci_dma_acc_h; 150171095Ssamtypedef struct resource *pci_irq_h; 151173139Srwatsontypedef xge_pci_info_t *pci_cfg_h; 152171095Ssam 153173139Srwatson/** 154171095Ssam * "libc" functionality 155173139Srwatson */ 156171095Ssam#define xge_os_memzero(addr, size) bzero(addr, size) 157171095Ssam#define xge_os_memcpy(dst, src, size) bcopy(src, dst, size) 158171095Ssam#define xge_os_memcmp memcmp 159171095Ssam#define xge_os_strcpy strcpy 160171095Ssam#define xge_os_strlen strlen 161171095Ssam#define xge_os_snprintf snprintf 162171095Ssam#define xge_os_sprintf sprintf 163173139Srwatson#define xge_os_printf(fmt...) { \ 164173139Srwatson printf(fmt); \ 165173139Srwatson printf("\n"); \ 166171095Ssam} 167171095Ssam 168173139Srwatson#define xge_os_vaprintf(fmt) { \ 169173139Srwatson sprintf(fmt, fmt, "\n"); \ 170173139Srwatson va_list va; \ 171173139Srwatson va_start(va, fmt); \ 172173139Srwatson vprintf(fmt, va); \ 173173139Srwatson va_end(va); \ 174171095Ssam} 175171095Ssam 176173139Srwatson#define xge_os_vasprintf(buf, fmt) { \ 177173139Srwatson va_list va; \ 178173139Srwatson va_start(va, fmt); \ 179173139Srwatson (void) vaprintf(buf, fmt, va); \ 180173139Srwatson va_end(va); \ 181171095Ssam} 182171095Ssam 183173139Srwatson#define xge_os_timestamp(buf) { \ 184173139Srwatson struct timeval current_time; \ 185173139Srwatson gettimeofday(¤t_time, 0); \ 186173139Srwatson sprintf(buf, "%08li.%08li: ", current_time.tv_sec, \ 187173139Srwatson current_time.tv_usec); \ 188171095Ssam} 189171095Ssam 190171095Ssam#define xge_os_println xge_os_printf 191171095Ssam 192173139Srwatson/** 193171095Ssam * Synchronization Primitives 194173139Srwatson */ 195171095Ssam/* Initialize the spin lock */ 196173139Srwatson#define xge_os_spin_lock_init(lockp, ctxh) { \ 197173139Srwatson if(mtx_initialized(lockp) == 0) { \ 198173139Srwatson mtx_init((lockp), "xge", NULL, MTX_DEF); \ 199173139Srwatson } \ 200173139Srwatson} 201171095Ssam 202171095Ssam/* Initialize the spin lock (IRQ version) */ 203173139Srwatson#define xge_os_spin_lock_init_irq(lockp, ctxh) { \ 204173139Srwatson if(mtx_initialized(lockp) == 0) { \ 205173139Srwatson mtx_init((lockp), "xge", NULL, MTX_DEF); \ 206173139Srwatson } \ 207173139Srwatson} 208171095Ssam 209171095Ssam/* Destroy the lock */ 210173139Srwatson#define xge_os_spin_lock_destroy(lockp, ctxh) { \ 211173139Srwatson if(mtx_initialized(lockp) != 0) { \ 212173139Srwatson mtx_destroy(lockp); \ 213173139Srwatson } \ 214173139Srwatson} 215171095Ssam 216171095Ssam/* Destroy the lock (IRQ version) */ 217173139Srwatson#define xge_os_spin_lock_destroy_irq(lockp, ctxh) { \ 218173139Srwatson if(mtx_initialized(lockp) != 0) { \ 219173139Srwatson mtx_destroy(lockp); \ 220173139Srwatson } \ 221173139Srwatson} 222171095Ssam 223171095Ssam/* Acquire the lock */ 224173139Srwatson#define xge_os_spin_lock(lockp) { \ 225173139Srwatson if(mtx_owned(lockp) == 0) mtx_lock(lockp); \ 226173139Srwatson} 227171095Ssam 228171095Ssam/* Release the lock */ 229173139Srwatson#define xge_os_spin_unlock(lockp) { \ 230173139Srwatson mtx_unlock(lockp); \ 231173139Srwatson} 232171095Ssam 233171095Ssam/* Acquire the lock (IRQ version) */ 234173139Srwatson#define xge_os_spin_lock_irq(lockp, flags) { \ 235173139Srwatson flags = MTX_QUIET; \ 236173139Srwatson if(mtx_owned(lockp) == 0) mtx_lock_flags(lockp, flags); \ 237171095Ssam} 238171095Ssam 239171095Ssam/* Release the lock (IRQ version) */ 240173139Srwatson#define xge_os_spin_unlock_irq(lockp, flags) { \ 241173139Srwatson flags = MTX_QUIET; \ 242173139Srwatson mtx_unlock_flags(lockp, flags); \ 243171095Ssam} 244171095Ssam 245185162Skmacy#if __FreeBSD_version > 800053 246171095Ssam/* Write memory barrier */ 247185162Skmacy#define xge_os_wmb() wmb() 248185162Skmacy#else 249171095Ssam#define xge_os_wmb() 250185162Skmacy#endif 251171095Ssam 252171095Ssam/* Delay (in micro seconds) */ 253171095Ssam#define xge_os_udelay(us) DELAY(us) 254171095Ssam 255171095Ssam/* Delay (in milli seconds) */ 256171095Ssam#define xge_os_mdelay(ms) DELAY(ms * 1000) 257171095Ssam 258171095Ssam/* Compare and exchange */ 259173139Srwatson//#define xge_os_cmpxchg(targetp, cmd, newval) 260171095Ssam 261173139Srwatson/** 262171095Ssam * Misc primitives 263173139Srwatson */ 264171095Ssam#define xge_os_unlikely(x) (x) 265173139Srwatson#define xge_os_prefetch(x) (x=x) 266173139Srwatson#define xge_os_prefetchw(x) (x=x) 267173139Srwatson#define xge_os_bug(fmt...) printf(fmt) 268171095Ssam#define xge_os_htohs ntohs 269171095Ssam#define xge_os_ntohl ntohl 270171095Ssam#define xge_os_htons htons 271171095Ssam#define xge_os_htonl htonl 272171095Ssam 273173139Srwatson/** 274171095Ssam * Compiler Stuffs 275173139Srwatson */ 276173139Srwatson#define __xge_os_attr_cacheline_aligned 277171095Ssam#define __xge_os_cacheline_size 32 278171095Ssam 279173139Srwatson/** 280171095Ssam * Memory Primitives 281173139Srwatson */ 282171095Ssam#define XGE_OS_INVALID_DMA_ADDR ((dma_addr_t)0) 283171095Ssam 284173139Srwatson/** 285173139Srwatson * xge_os_malloc 286173139Srwatson * Allocate non DMA-able memory. 287171095Ssam * @pdev: Device context. 288171095Ssam * @size: Size to allocate. 289171095Ssam * 290173139Srwatson * Allocate @size bytes of memory. This allocation can sleep, and therefore, 291173139Srwatson * and therefore it requires process context. In other words, xge_os_malloc() 292173139Srwatson * cannot be called from the interrupt context. Use xge_os_free() to free the 293173139Srwatson * allocated block. 294171095Ssam * 295171095Ssam * Returns: Pointer to allocated memory, NULL - on failure. 296171095Ssam * 297171095Ssam * See also: xge_os_free(). 298173139Srwatson */ 299171095Ssamstatic inline void * 300171095Ssamxge_os_malloc(pci_dev_h pdev, unsigned long size) { 301173139Srwatson void *vaddr = malloc((size), M_DEVBUF, M_NOWAIT | M_ZERO); 302173139Srwatson if(vaddr != NULL) { 303173139Srwatson XGE_OS_MEMORY_CHECK_MALLOC(vaddr, size, __FILE__, __LINE__); 304173139Srwatson xge_os_memzero(vaddr, size); 305173139Srwatson } 306173139Srwatson return (vaddr); 307171095Ssam} 308171095Ssam 309173139Srwatson/** 310173139Srwatson * xge_os_free 311173139Srwatson * Free non DMA-able memory. 312171095Ssam * @pdev: Device context. 313171095Ssam * @vaddr: Address of the allocated memory block. 314171095Ssam * @size: Some OS's require to provide size on free 315171095Ssam * 316173139Srwatson * Free the memory area obtained via xge_os_malloc(). This call may also sleep, 317173139Srwatson * and therefore it cannot be used inside interrupt. 318171095Ssam * 319171095Ssam * See also: xge_os_malloc(). 320173139Srwatson */ 321171095Ssamstatic inline void 322171095Ssamxge_os_free(pci_dev_h pdev, const void *vaddr, unsigned long size) { 323171095Ssam XGE_OS_MEMORY_CHECK_FREE(vaddr, size); 324171095Ssam free(__DECONST(void *, vaddr), M_DEVBUF); 325171095Ssam} 326171095Ssam 327171095Ssamstatic void 328171095Ssamxge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { 329171095Ssam if(error) return; 330171095Ssam *(bus_addr_t *) arg = segs->ds_addr; 331171095Ssam return; 332171095Ssam} 333171095Ssam 334173139Srwatson/** 335173139Srwatson * xge_os_dma_malloc 336173139Srwatson * Allocate DMA-able memory. 337171095Ssam * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. 338171095Ssam * @size: Size (in bytes) to allocate. 339173139Srwatson * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, XGE_OS_DMA_STREAMING, 340173139Srwatson * XGE_OS_DMA_CONSISTENT (Note that the last two flags are mutually exclusive.) 341171095Ssam * @p_dmah: Handle used to map the memory onto the corresponding device memory 342173139Srwatson * space. See xge_os_dma_map(). The handle is an out-parameter returned by the 343173139Srwatson * function. 344173139Srwatson * @p_dma_acch: One more DMA handle used subsequently to free the DMA object 345173139Srwatson * (via xge_os_dma_free()). 346171095Ssam * 347173139Srwatson * Allocate DMA-able contiguous memory block of the specified @size. This memory 348173139Srwatson * can be subsequently freed using xge_os_dma_free(). 349171095Ssam * Note: can be used inside interrupt context. 350171095Ssam * 351171095Ssam * Returns: Pointer to allocated memory(DMA-able), NULL on failure. 352173139Srwatson */ 353171095Ssamstatic inline void * 354171095Ssamxge_os_dma_malloc(pci_dev_h pdev, unsigned long size, int dma_flags, 355171095Ssam pci_dma_h *p_dmah, pci_dma_acc_h *p_dma_acch) { 356171095Ssam int retValue = bus_dma_tag_create( 357173139Srwatson bus_get_dma_tag(pdev->device), /* Parent */ 358171095Ssam PAGE_SIZE, /* Alignment no specific alignment */ 359173139Srwatson 0, /* Bounds */ 360173139Srwatson BUS_SPACE_MAXADDR, /* Low Address */ 361173139Srwatson BUS_SPACE_MAXADDR, /* High Address */ 362173139Srwatson NULL, /* Filter */ 363173139Srwatson NULL, /* Filter arg */ 364173139Srwatson size, /* Max Size */ 365173139Srwatson 1, /* n segments */ 366173139Srwatson size, /* max segment size */ 367173139Srwatson BUS_DMA_ALLOCNOW, /* Flags */ 368173139Srwatson NULL, /* lockfunction */ 369173139Srwatson NULL, /* lock arg */ 370173139Srwatson &p_dmah->dma_tag); /* DMA tag */ 371171095Ssam if(retValue != 0) { 372173139Srwatson xge_os_printf("bus_dma_tag_create failed\n") 373171095Ssam goto fail_1; 374171095Ssam } 375171095Ssam p_dmah->dma_size = size; 376171095Ssam retValue = bus_dmamem_alloc(p_dmah->dma_tag, 377171095Ssam (void **)&p_dmah->dma_viraddr, BUS_DMA_NOWAIT, &p_dmah->dma_map); 378171095Ssam if(retValue != 0) { 379173139Srwatson xge_os_printf("bus_dmamem_alloc failed\n") 380171095Ssam goto fail_2; 381171095Ssam } 382173139Srwatson XGE_OS_MEMORY_CHECK_MALLOC(p_dmah->dma_viraddr, p_dmah->dma_size, 383173139Srwatson __FILE__, __LINE__); 384171095Ssam return(p_dmah->dma_viraddr); 385171095Ssam 386171095Ssamfail_2: bus_dma_tag_destroy(p_dmah->dma_tag); 387171095Ssamfail_1: return(NULL); 388171095Ssam} 389171095Ssam 390173139Srwatson/** 391173139Srwatson * xge_os_dma_free 392173139Srwatson * Free previously allocated DMA-able memory. 393171095Ssam * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. 394171095Ssam * @vaddr: Virtual address of the DMA-able memory. 395171095Ssam * @p_dma_acch: DMA handle used to free the resource. 396171095Ssam * @p_dmah: DMA handle used for mapping. See xge_os_dma_malloc(). 397171095Ssam * 398171095Ssam * Free DMA-able memory originally allocated by xge_os_dma_malloc(). 399171095Ssam * Note: can be used inside interrupt. 400171095Ssam * See also: xge_os_dma_malloc(). 401173139Srwatson */ 402171095Ssamstatic inline void 403171095Ssamxge_os_dma_free(pci_dev_h pdev, const void *vaddr, int size, 404173139Srwatson pci_dma_acc_h *p_dma_acch, pci_dma_h *p_dmah) 405173139Srwatson{ 406171095Ssam XGE_OS_MEMORY_CHECK_FREE(p_dmah->dma_viraddr, size); 407171095Ssam bus_dmamem_free(p_dmah->dma_tag, p_dmah->dma_viraddr, p_dmah->dma_map); 408171095Ssam bus_dma_tag_destroy(p_dmah->dma_tag); 409171095Ssam p_dmah->dma_map = NULL; 410171095Ssam p_dmah->dma_tag = NULL; 411171095Ssam p_dmah->dma_viraddr = NULL; 412171095Ssam return; 413171095Ssam} 414171095Ssam 415173139Srwatson/** 416171095Ssam * IO/PCI/DMA Primitives 417173139Srwatson */ 418171095Ssam#define XGE_OS_DMA_DIR_TODEVICE 0 419171095Ssam#define XGE_OS_DMA_DIR_FROMDEVICE 1 420171095Ssam#define XGE_OS_DMA_DIR_BIDIRECTIONAL 2 421171095Ssam 422173139Srwatson/** 423173139Srwatson * xge_os_pci_read8 424173139Srwatson * Read one byte from device PCI configuration. 425173139Srwatson * @pdev: Device context. Some OSs require device context to perform PIO and/or 426173139Srwatson * config space IO. 427171095Ssam * @cfgh: PCI configuration space handle. 428171095Ssam * @where: Offset in the PCI configuration space. 429171095Ssam * @val: Address of the result. 430171095Ssam * 431171095Ssam * Read byte value from the specified @regh PCI configuration space at the 432171095Ssam * specified offset = @where. 433171095Ssam * Returns: 0 - success, non-zero - failure. 434173139Srwatson */ 435173139Srwatson#define xge_os_pci_read8(pdev, cfgh, where, val) \ 436171095Ssam (*(val) = pci_read_config(pdev->device, where, 1)) 437171095Ssam 438173139Srwatson/** 439173139Srwatson * xge_os_pci_write8 440173139Srwatson * Write one byte into device PCI configuration. 441173139Srwatson * @pdev: Device context. Some OSs require device context to perform PIO and/or 442173139Srwatson * config space IO. 443171095Ssam * @cfgh: PCI configuration space handle. 444171095Ssam * @where: Offset in the PCI configuration space. 445171095Ssam * @val: Value to write. 446171095Ssam * 447171095Ssam * Write byte value into the specified PCI configuration space 448171095Ssam * Returns: 0 - success, non-zero - failure. 449173139Srwatson */ 450173139Srwatson#define xge_os_pci_write8(pdev, cfgh, where, val) \ 451171095Ssam pci_write_config(pdev->device, where, val, 1) 452171095Ssam 453173139Srwatson/** 454173139Srwatson * xge_os_pci_read16 455173139Srwatson * Read 16bit word from device PCI configuration. 456171095Ssam * @pdev: Device context. 457171095Ssam * @cfgh: PCI configuration space handle. 458171095Ssam * @where: Offset in the PCI configuration space. 459171095Ssam * @val: Address of the 16bit result. 460171095Ssam * 461171095Ssam * Read 16bit value from the specified PCI configuration space at the 462171095Ssam * specified offset. 463171095Ssam * Returns: 0 - success, non-zero - failure. 464173139Srwatson */ 465173139Srwatson#define xge_os_pci_read16(pdev, cfgh, where, val) \ 466171095Ssam (*(val) = pci_read_config(pdev->device, where, 2)) 467171095Ssam 468173139Srwatson/** 469173139Srwatson * xge_os_pci_write16 470173139Srwatson * Write 16bit word into device PCI configuration. 471171095Ssam * @pdev: Device context. 472171095Ssam * @cfgh: PCI configuration space handle. 473171095Ssam * @where: Offset in the PCI configuration space. 474171095Ssam * @val: Value to write. 475171095Ssam * 476173139Srwatson * Write 16bit value into the specified @offset in PCI configuration space. 477171095Ssam * Returns: 0 - success, non-zero - failure. 478173139Srwatson */ 479173139Srwatson#define xge_os_pci_write16(pdev, cfgh, where, val) \ 480171095Ssam pci_write_config(pdev->device, where, val, 2) 481171095Ssam 482173139Srwatson/** 483173139Srwatson * xge_os_pci_read32 484173139Srwatson * Read 32bit word from device PCI configuration. 485171095Ssam * @pdev: Device context. 486171095Ssam * @cfgh: PCI configuration space handle. 487171095Ssam * @where: Offset in the PCI configuration space. 488171095Ssam * @val: Address of 32bit result. 489171095Ssam * 490171095Ssam * Read 32bit value from the specified PCI configuration space at the 491171095Ssam * specified offset. 492171095Ssam * Returns: 0 - success, non-zero - failure. 493173139Srwatson */ 494173139Srwatson#define xge_os_pci_read32(pdev, cfgh, where, val) \ 495171095Ssam (*(val) = pci_read_config(pdev->device, where, 4)) 496171095Ssam 497173139Srwatson/** 498173139Srwatson * xge_os_pci_write32 499173139Srwatson * Write 32bit word into device PCI configuration. 500171095Ssam * @pdev: Device context. 501171095Ssam * @cfgh: PCI configuration space handle. 502171095Ssam * @where: Offset in the PCI configuration space. 503171095Ssam * @val: Value to write. 504171095Ssam * 505173139Srwatson * Write 32bit value into the specified @offset in PCI configuration space. 506171095Ssam * Returns: 0 - success, non-zero - failure. 507173139Srwatson */ 508173139Srwatson#define xge_os_pci_write32(pdev, cfgh, where, val) \ 509171095Ssam pci_write_config(pdev->device, where, val, 4) 510171095Ssam 511173139Srwatson/** 512173139Srwatson * xge_os_pio_mem_read8 513173139Srwatson * Read 1 byte from device memory mapped space. 514171095Ssam * @pdev: Device context. 515171095Ssam * @regh: PCI configuration space handle. 516171095Ssam * @addr: Address in device memory space. 517171095Ssam * 518171095Ssam * Returns: 1 byte value read from the specified (mapped) memory space address. 519173139Srwatson */ 520171095Ssamstatic inline u8 521171095Ssamxge_os_pio_mem_read8(pci_dev_h pdev, pci_reg_h regh, void *addr) 522171095Ssam{ 523171095Ssam bus_space_tag_t tag = 524173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 525171095Ssam bus_space_handle_t handle = 526173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 527173139Srwatson caddr_t addrss = (caddr_t) 528173139Srwatson (((xge_bus_resource_t *)(regh))->bar_start_addr); 529171095Ssam 530171095Ssam return bus_space_read_1(tag, handle, (caddr_t)(addr) - addrss); 531171095Ssam} 532171095Ssam 533173139Srwatson/** 534173139Srwatson * xge_os_pio_mem_write8 535173139Srwatson * Write 1 byte into device memory mapped space. 536171095Ssam * @pdev: Device context. 537171095Ssam * @regh: PCI configuration space handle. 538171095Ssam * @val: Value to write. 539171095Ssam * @addr: Address in device memory space. 540171095Ssam * 541171095Ssam * Write byte value into the specified (mapped) device memory space. 542173139Srwatson */ 543171095Ssamstatic inline void 544171095Ssamxge_os_pio_mem_write8(pci_dev_h pdev, pci_reg_h regh, u8 val, void *addr) 545171095Ssam{ 546171095Ssam bus_space_tag_t tag = 547173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 548171095Ssam bus_space_handle_t handle = 549173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 550173139Srwatson caddr_t addrss = (caddr_t) 551173139Srwatson (((xge_bus_resource_t *)(regh))->bar_start_addr); 552171095Ssam 553171095Ssam bus_space_write_1(tag, handle, (caddr_t)(addr) - addrss, val); 554171095Ssam} 555171095Ssam 556173139Srwatson/** 557173139Srwatson * xge_os_pio_mem_read16 558173139Srwatson * Read 16bit from device memory mapped space. 559171095Ssam * @pdev: Device context. 560171095Ssam * @regh: PCI configuration space handle. 561171095Ssam * @addr: Address in device memory space. 562171095Ssam * 563171095Ssam * Returns: 16bit value read from the specified (mapped) memory space address. 564173139Srwatson */ 565171095Ssamstatic inline u16 566171095Ssamxge_os_pio_mem_read16(pci_dev_h pdev, pci_reg_h regh, void *addr) 567171095Ssam{ 568171095Ssam bus_space_tag_t tag = 569173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 570171095Ssam bus_space_handle_t handle = 571173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 572173139Srwatson caddr_t addrss = (caddr_t) 573173139Srwatson (((xge_bus_resource_t *)(regh))->bar_start_addr); 574171095Ssam 575171095Ssam return bus_space_read_2(tag, handle, (caddr_t)(addr) - addrss); 576171095Ssam} 577171095Ssam 578173139Srwatson/** 579173139Srwatson * xge_os_pio_mem_write16 580173139Srwatson * Write 16bit into device memory mapped space. 581171095Ssam * @pdev: Device context. 582171095Ssam * @regh: PCI configuration space handle. 583171095Ssam * @val: Value to write. 584171095Ssam * @addr: Address in device memory space. 585171095Ssam * 586171095Ssam * Write 16bit value into the specified (mapped) device memory space. 587173139Srwatson */ 588171095Ssamstatic inline void 589171095Ssamxge_os_pio_mem_write16(pci_dev_h pdev, pci_reg_h regh, u16 val, void *addr) 590171095Ssam{ 591171095Ssam bus_space_tag_t tag = 592173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 593171095Ssam bus_space_handle_t handle = 594173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 595173139Srwatson caddr_t addrss = (caddr_t)(((xge_bus_resource_t *)(regh))->bar_start_addr); 596171095Ssam 597171095Ssam bus_space_write_2(tag, handle, (caddr_t)(addr) - addrss, val); 598171095Ssam} 599171095Ssam 600173139Srwatson/** 601173139Srwatson * xge_os_pio_mem_read32 602173139Srwatson * Read 32bit from device memory mapped space. 603171095Ssam * @pdev: Device context. 604171095Ssam * @regh: PCI configuration space handle. 605171095Ssam * @addr: Address in device memory space. 606171095Ssam * 607171095Ssam * Returns: 32bit value read from the specified (mapped) memory space address. 608173139Srwatson */ 609171095Ssamstatic inline u32 610171095Ssamxge_os_pio_mem_read32(pci_dev_h pdev, pci_reg_h regh, void *addr) 611171095Ssam{ 612171095Ssam bus_space_tag_t tag = 613173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 614171095Ssam bus_space_handle_t handle = 615173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 616173139Srwatson caddr_t addrss = (caddr_t) 617173139Srwatson (((xge_bus_resource_t *)(regh))->bar_start_addr); 618171095Ssam 619171095Ssam return bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss); 620171095Ssam} 621171095Ssam 622173139Srwatson/** 623173139Srwatson * xge_os_pio_mem_write32 624173139Srwatson * Write 32bit into device memory space. 625171095Ssam * @pdev: Device context. 626171095Ssam * @regh: PCI configuration space handle. 627171095Ssam * @val: Value to write. 628171095Ssam * @addr: Address in device memory space. 629171095Ssam * 630171095Ssam * Write 32bit value into the specified (mapped) device memory space. 631173139Srwatson */ 632171095Ssamstatic inline void 633171095Ssamxge_os_pio_mem_write32(pci_dev_h pdev, pci_reg_h regh, u32 val, void *addr) 634171095Ssam{ 635171095Ssam bus_space_tag_t tag = 636173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 637171095Ssam bus_space_handle_t handle = 638173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 639173139Srwatson caddr_t addrss = (caddr_t)(((xge_bus_resource_t *)(regh))->bar_start_addr); 640171095Ssam bus_space_write_4(tag, handle, (caddr_t)(addr) - addrss, val); 641171095Ssam} 642171095Ssam 643173139Srwatson/** 644173139Srwatson * xge_os_pio_mem_read64 645173139Srwatson * Read 64bit from device memory mapped space. 646171095Ssam * @pdev: Device context. 647171095Ssam * @regh: PCI configuration space handle. 648171095Ssam * @addr: Address in device memory space. 649171095Ssam * 650171095Ssam * Returns: 64bit value read from the specified (mapped) memory space address. 651173139Srwatson */ 652171095Ssamstatic inline u64 653171095Ssamxge_os_pio_mem_read64(pci_dev_h pdev, pci_reg_h regh, void *addr) 654171095Ssam{ 655171095Ssam u64 value1, value2; 656171095Ssam 657171095Ssam bus_space_tag_t tag = 658173139Srwatson (bus_space_tag_t)(((xge_bus_resource_t *)regh)->bus_tag); 659171095Ssam bus_space_handle_t handle = 660173139Srwatson (bus_space_handle_t)(((xge_bus_resource_t *)regh)->bus_handle); 661173139Srwatson caddr_t addrss = (caddr_t) 662173139Srwatson (((xge_bus_resource_t *)(regh))->bar_start_addr); 663171095Ssam 664171095Ssam value1 = bus_space_read_4(tag, handle, (caddr_t)(addr) + 4 - addrss); 665171095Ssam value1 <<= 32; 666171095Ssam value2 = bus_space_read_4(tag, handle, (caddr_t)(addr) - addrss); 667171095Ssam value1 |= value2; 668171095Ssam return value1; 669171095Ssam} 670171095Ssam 671173139Srwatson/** 672173139Srwatson * xge_os_pio_mem_write64 673173139Srwatson * Write 32bit into device memory space. 674171095Ssam * @pdev: Device context. 675171095Ssam * @regh: PCI configuration space handle. 676171095Ssam * @val: Value to write. 677171095Ssam * @addr: Address in device memory space. 678171095Ssam * 679171095Ssam * Write 64bit value into the specified (mapped) device memory space. 680173139Srwatson */ 681171095Ssamstatic inline void 682171095Ssamxge_os_pio_mem_write64(pci_dev_h pdev, pci_reg_h regh, u64 val, void *addr) 683171095Ssam{ 684171095Ssam u32 vall = val & 0xffffffff; 685171095Ssam xge_os_pio_mem_write32(pdev, regh, vall, addr); 686171095Ssam xge_os_pio_mem_write32(pdev, regh, val >> 32, ((caddr_t)(addr) + 4)); 687171095Ssam} 688171095Ssam 689173139Srwatson/** 690171095Ssam * FIXME: document 691173139Srwatson */ 692171095Ssam#define xge_os_flush_bridge xge_os_pio_mem_read64 693171095Ssam 694173139Srwatson/** 695173139Srwatson * xge_os_dma_map 696173139Srwatson * Map DMA-able memory block to, or from, or to-and-from device. 697171095Ssam * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. 698171095Ssam * @dmah: DMA handle used to map the memory block. Obtained via 699171095Ssam * xge_os_dma_malloc(). 700171095Ssam * @vaddr: Virtual address of the DMA-able memory. 701171095Ssam * @size: Size (in bytes) to be mapped. 702171095Ssam * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) 703173139Srwatson * @dma_flags: XGE_OS_DMA_CACHELINE_ALIGNED, XGE_OS_DMA_STREAMING, 704173139Srwatson * XGE_OS_DMA_CONSISTENT (Note that the last two flags are mutually exclusive). 705171095Ssam * 706171095Ssam * Map a single memory block. 707171095Ssam * 708173139Srwatson * Returns: DMA address of the memory block, XGE_OS_INVALID_DMA_ADDR on failure. 709171095Ssam * 710173139Srwatson * See also: xge_os_dma_malloc(), xge_os_dma_unmap(), xge_os_dma_sync(). 711173139Srwatson */ 712171095Ssamstatic inline dma_addr_t 713171095Ssamxge_os_dma_map(pci_dev_h pdev, pci_dma_h dmah, void *vaddr, size_t size, 714171095Ssam int dir, int dma_flags) 715171095Ssam{ 716171095Ssam int retValue = 717171095Ssam bus_dmamap_load(dmah.dma_tag, dmah.dma_map, dmah.dma_viraddr, 718171095Ssam dmah.dma_size, xge_dmamap_cb, &dmah.dma_phyaddr, BUS_DMA_NOWAIT); 719171095Ssam if(retValue != 0) { 720173139Srwatson xge_os_printf("bus_dmamap_load_ failed\n") 721171095Ssam return XGE_OS_INVALID_DMA_ADDR; 722171095Ssam } 723171095Ssam dmah.dma_size = size; 724171095Ssam return dmah.dma_phyaddr; 725171095Ssam} 726171095Ssam 727173139Srwatson/** 728171095Ssam * xge_os_dma_unmap - Unmap DMA-able memory. 729171095Ssam * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. 730171095Ssam * @dmah: DMA handle used to map the memory block. Obtained via 731171095Ssam * xge_os_dma_malloc(). 732171095Ssam * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). 733171095Ssam * @size: Size (in bytes) to be unmapped. 734171095Ssam * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) 735171095Ssam * 736173139Srwatson * Unmap a single DMA-able memory block that was previously mapped using 737173139Srwatson * xge_os_dma_map(). 738171095Ssam * See also: xge_os_dma_malloc(), xge_os_dma_map(). 739173139Srwatson */ 740171095Ssamstatic inline void 741171095Ssamxge_os_dma_unmap(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr, 742171095Ssam size_t size, int dir) 743171095Ssam{ 744171095Ssam bus_dmamap_unload(dmah.dma_tag, dmah.dma_map); 745171095Ssam return; 746171095Ssam} 747171095Ssam 748173139Srwatson/** 749171095Ssam * xge_os_dma_sync - Synchronize mapped memory. 750171095Ssam * @pdev: Device context. Used to allocate/pin/map/unmap DMA-able memory. 751171095Ssam * @dmah: DMA handle used to map the memory block. Obtained via 752171095Ssam * xge_os_dma_malloc(). 753171095Ssam * @dma_addr: DMA address of the block. Obtained via xge_os_dma_map(). 754171095Ssam * @dma_offset: Offset from start of the blocke. Used by Solaris only. 755171095Ssam * @length: Size of the block. 756171095Ssam * @dir: Direction of this operation (XGE_OS_DMA_DIR_TODEVICE, etc.) 757171095Ssam * 758173139Srwatson * Make physical and CPU memory consistent for a single streaming mode DMA 759173139Srwatson * translation. This API compiles to NOP on cache-coherent platforms. On 760173139Srwatson * non cache-coherent platforms, depending on the direction of the "sync" 761173139Srwatson * operation, this API will effectively either invalidate CPU cache (that might 762173139Srwatson * contain old data), or flush CPU cache to update physical memory. 763171095Ssam * See also: xge_os_dma_malloc(), xge_os_dma_map(), 764171095Ssam * xge_os_dma_unmap(). 765173139Srwatson */ 766171095Ssamstatic inline void 767171095Ssamxge_os_dma_sync(pci_dev_h pdev, pci_dma_h dmah, dma_addr_t dma_addr, 768171095Ssam u64 dma_offset, size_t length, int dir) 769171095Ssam{ 770171095Ssam bus_dmasync_op_t syncop; 771171095Ssam switch(dir) { 772171095Ssam case XGE_OS_DMA_DIR_TODEVICE: 773171095Ssam syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_POSTWRITE; 774171095Ssam break; 775171095Ssam 776171095Ssam case XGE_OS_DMA_DIR_FROMDEVICE: 777171095Ssam syncop = BUS_DMASYNC_PREREAD | BUS_DMASYNC_POSTREAD; 778171095Ssam break; 779171095Ssam 780173139Srwatson default: 781171095Ssam syncop = BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREWRITE; 782171095Ssam break; 783171095Ssam } 784171095Ssam bus_dmamap_sync(dmah.dma_tag, dmah.dma_map, syncop); 785171095Ssam return; 786171095Ssam} 787171095Ssam 788171095Ssam#endif /* XGE_OSDEP_H */ 789173139Srwatson 790