1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*
  28  *  Copyright (c) 2002-2005 Neterion, Inc.
  29  *  All right Reserved.
  30  *
  31  *  FileName :    xge_osdep.h
  32  *
  33  *  Description:  OSPAL - Solaris
  34  *
  35  */
  36 
  37 #ifndef _SYS_XGE_OSDEP_H
  38 #define _SYS_XGE_OSDEP_H
  39 
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/varargs.h>
  43 #include <sys/atomic.h>
  44 #include <sys/policy.h>
  45 #include <sys/int_fmtio.h>
  46 #include <sys/thread.h>
  47 #include <sys/cpuvar.h>
  48 
  49 #include <inet/common.h>
  50 #include <inet/ip.h>
  51 #include <inet/mi.h>
  52 #include <inet/nd.h>
  53 
  54 #ifdef __cplusplus
  55 extern "C" {
  56 #endif
  57 
  58 /* ------------------------- includes and defines ------------------------- */
  59 
  60 #define XGE_HAL_TX_MULTI_POST_IRQ       1
  61 #define XGE_HAL_TX_MULTI_RESERVE_IRQ    1
  62 #define XGE_HAL_TX_MULTI_FREE_IRQ       1
  63 #define XGE_HAL_DMA_DTR_CONSISTENT      1
  64 #define XGE_HAL_DMA_STATS_STREAMING     1
  65 
  66 #if defined(__sparc)
  67 #define XGE_OS_DMA_REQUIRES_SYNC        1
  68 #endif
  69 
  70 #define XGE_HAL_ALIGN_XMIT              1
  71 
  72 #ifdef _BIG_ENDIAN
  73 #define XGE_OS_HOST_BIG_ENDIAN          1
  74 #else
  75 #define XGE_OS_HOST_LITTLE_ENDIAN       1
  76 #endif
  77 
  78 #if defined(__sparc)
  79 #define XGE_OS_HOST_PAGE_SIZE           8192
  80 #else
  81 #define XGE_OS_HOST_PAGE_SIZE           4096
  82 #endif
  83 
  84 #if defined(_LP64)
  85 #define XGE_OS_PLATFORM_64BIT           1
  86 #else
  87 #define XGE_OS_PLATFORM_32BIT           1
  88 #endif
  89 
  90 #define XGE_OS_HAS_SNPRINTF             1
  91 
  92 /* LRO defines */
  93 #define XGE_LL_IP_FAST_CSUM(hdr, len)   0 /* ip_ocsum(hdr, len>>1, 0); */
  94 
  95 /* ---------------------- fixed size primitive types ----------------------- */
  96 
  97 #define u8                      uint8_t
  98 #define u16                     uint16_t
  99 #define u32                     uint32_t
 100 #define u64                     uint64_t
 101 typedef u64                     dma_addr_t;
 102 #define ulong_t                 ulong_t
 103 #define ptrdiff_t               ptrdiff_t
 104 typedef kmutex_t                spinlock_t;
 105 typedef dev_info_t              *pci_dev_h;
 106 typedef ddi_acc_handle_t        pci_reg_h;
 107 typedef ddi_acc_handle_t        pci_cfg_h;
 108 typedef uint_t                  pci_irq_h;
 109 typedef ddi_dma_handle_t        pci_dma_h;
 110 typedef ddi_acc_handle_t        pci_dma_acc_h;
 111 
 112 /* LRO types */
 113 #define OS_NETSTACK_BUF         mblk_t *
 114 #define OS_LL_HEADER            uint8_t *
 115 #define OS_IP_HEADER            uint8_t *
 116 #define OS_TL_HEADER            uint8_t *
 117 
 118 /* -------------------------- "libc" functionality ------------------------- */
 119 
 120 #define xge_os_strlcpy                  (void) strlcpy
 121 #define xge_os_strlen                   strlen
 122 #define xge_os_snprintf                 snprintf
 123 #define xge_os_memzero(addr, size)      bzero(addr, size)
 124 #define xge_os_memcpy(dst, src, size)   bcopy(src, dst, size)
 125 #define xge_os_memcmp(src1, src2, size) bcmp(src1, src2, size)
 126 #define xge_os_ntohl                    ntohl
 127 #define xge_os_htons                    htons
 128 #define xge_os_ntohs                    ntohs
 129 
 130 #ifdef __GNUC__
 131 #define xge_os_printf(fmt...)           cmn_err(CE_CONT, fmt)
 132 #define xge_os_sprintf(buf, fmt...)     strlen(sprintf(buf, fmt))
 133 #else
 134 #define xge_os_vaprintf(fmt) { \
 135         va_list va; \
 136         va_start(va, fmt); \
 137         vcmn_err(CE_CONT, fmt, va); \
 138         va_end(va); \
 139 }
 140 
 141 static inline void xge_os_printf(char *fmt, ...) {
 142         xge_os_vaprintf(fmt);
 143 }
 144 
 145 #define xge_os_vasprintf(buf, fmt) { \
 146         va_list va; \
 147         va_start(va, fmt); \
 148         (void) vsprintf(buf, fmt, va); \
 149         va_end(va); \
 150 }
 151 
 152 static inline int xge_os_sprintf(char *buf, char *fmt, ...) {
 153         xge_os_vasprintf(buf, fmt);
 154         return (strlen(buf));
 155 }
 156 #endif
 157 
 158 #define xge_os_timestamp(buf) { \
 159         todinfo_t todinfo = utc_to_tod(ddi_get_time()); \
 160         (void) xge_os_sprintf(buf, "%02d/%02d/%02d.%02d:%02d:%02d: ", \
 161             todinfo.tod_day, todinfo.tod_month, \
 162             (1970 + todinfo.tod_year - 70), \
 163             todinfo.tod_hour, todinfo.tod_min, todinfo.tod_sec); \
 164 }
 165 
 166 #define xge_os_println                  xge_os_printf
 167 
 168 /* -------------------- synchronization primitives ------------------------- */
 169 
 170 #define xge_os_spin_lock_init(lockp, ctxh) \
 171         mutex_init(lockp, NULL, MUTEX_DRIVER, NULL)
 172 #define xge_os_spin_lock_init_irq(lockp, irqh) \
 173         mutex_init(lockp, NULL, MUTEX_DRIVER, DDI_INTR_PRI(irqh))
 174 #define xge_os_spin_lock_destroy(lockp, cthx) \
 175         (cthx = cthx, mutex_destroy(lockp))
 176 #define xge_os_spin_lock_destroy_irq(lockp, cthx) \
 177         (cthx = cthx, mutex_destroy(lockp))
 178 #define xge_os_spin_lock(lockp)                 mutex_enter(lockp)
 179 #define xge_os_spin_unlock(lockp)               mutex_exit(lockp)
 180 #define xge_os_spin_lock_irq(lockp, flags) (flags = flags, mutex_enter(lockp))
 181 #define xge_os_spin_unlock_irq(lockp, flags)    mutex_exit(lockp)
 182 
 183 /* x86 arch will never re-order writes, Sparc can */
 184 #define xge_os_wmb()                            membar_producer()
 185 
 186 #define xge_os_udelay(us)                       drv_usecwait(us)
 187 #define xge_os_mdelay(ms)                       drv_usecwait(ms * 1000)
 188 
 189 #define xge_os_cmpxchg(targetp, cmp, newval)            \
 190         sizeof (*(targetp)) == 4 ?                      \
 191         atomic_cas_32((uint32_t *)targetp, cmp, newval) :       \
 192         atomic_cas_64((uint64_t *)targetp, cmp, newval)
 193 
 194 /* ------------------------- misc primitives ------------------------------- */
 195 
 196 #define xge_os_unlikely(x)              (x)
 197 #define xge_os_prefetch(a)              (a = a)
 198 #define xge_os_prefetchw
 199 #ifdef __GNUC__
 200 #define xge_os_bug(fmt...)              cmn_err(CE_PANIC, fmt)
 201 #else
 202 static inline void xge_os_bug(char *fmt, ...) {
 203         va_list ap;
 204 
 205         va_start(ap, fmt);
 206         vcmn_err(CE_PANIC, fmt, ap);
 207         va_end(ap);
 208 }
 209 #endif
 210 
 211 /* -------------------------- compiler stuffs ------------------------------ */
 212 
 213 #if defined(__i386)
 214 #define __xge_os_cacheline_size         64 /* L1-cache line size: x86_64 */
 215 #else
 216 #define __xge_os_cacheline_size         64 /* L1-cache line size: sparcv9 */
 217 #endif
 218 
 219 #ifdef __GNUC__
 220 #define __xge_os_attr_cacheline_aligned \
 221         __attribute__((__aligned__(__xge_os_cacheline_size)))
 222 #else
 223 #define __xge_os_attr_cacheline_aligned
 224 #endif
 225 
 226 /* ---------------------- memory primitives -------------------------------- */
 227 
 228 static inline void *__xge_os_malloc(pci_dev_h pdev, unsigned long size,
 229     char *file, int line)
 230 {
 231         void *vaddr = kmem_alloc(size, KM_SLEEP);
 232 
 233         XGE_OS_MEMORY_CHECK_MALLOC(vaddr, size, file, line);
 234         return (vaddr);
 235 }
 236 
 237 static inline void xge_os_free(pci_dev_h pdev, const void *vaddr,
 238     unsigned long size)
 239 {
 240         XGE_OS_MEMORY_CHECK_FREE(vaddr, size);
 241         kmem_free((void*)vaddr, size);
 242 }
 243 
 244 #define xge_os_malloc(pdev, size) \
 245         __xge_os_malloc(pdev, size, __FILE__, __LINE__)
 246 
 247 static inline void *__xge_os_dma_malloc(pci_dev_h pdev, unsigned long size,
 248     int dma_flags, pci_dma_h *p_dmah, pci_dma_acc_h *p_dma_acch, char *file,
 249     int line)
 250 {
 251         void *vaddr;
 252         int ret;
 253         size_t real_size;
 254         extern ddi_device_acc_attr_t *p_xge_dev_attr;
 255         extern struct ddi_dma_attr *p_hal_dma_attr;
 256 
 257         ret = ddi_dma_alloc_handle(pdev, p_hal_dma_attr,
 258             DDI_DMA_DONTWAIT, 0, p_dmah);
 259         if (ret != DDI_SUCCESS) {
 260                 return (NULL);
 261         }
 262 
 263         ret = ddi_dma_mem_alloc(*p_dmah, size, p_xge_dev_attr,
 264             (dma_flags & XGE_OS_DMA_CONSISTENT ?
 265             DDI_DMA_CONSISTENT : DDI_DMA_STREAMING), DDI_DMA_DONTWAIT, 0,
 266             (caddr_t *)&vaddr, &real_size, p_dma_acch);
 267         if (ret != DDI_SUCCESS) {
 268                 ddi_dma_free_handle(p_dmah);
 269                 return (NULL);
 270         }
 271 
 272         if (size > real_size) {
 273                 ddi_dma_mem_free(p_dma_acch);
 274                 ddi_dma_free_handle(p_dmah);
 275                 return (NULL);
 276         }
 277 
 278         XGE_OS_MEMORY_CHECK_MALLOC(vaddr, size, file, line);
 279 
 280         return (vaddr);
 281 }
 282 
 283 #define xge_os_dma_malloc(pdev, size, dma_flags, p_dmah, p_dma_acch) \
 284         __xge_os_dma_malloc(pdev, size, dma_flags, p_dmah, p_dma_acch, \
 285             __FILE__, __LINE__)
 286 
 287 static inline void xge_os_dma_free(pci_dev_h pdev, const void *vaddr, int size,
 288     pci_dma_acc_h *p_dma_acch, pci_dma_h *p_dmah)
 289 {
 290         XGE_OS_MEMORY_CHECK_FREE(vaddr, 0);
 291         ddi_dma_mem_free(p_dma_acch);
 292         ddi_dma_free_handle(p_dmah);
 293 }
 294 
 295 
 296 /* --------------------------- pci primitives ------------------------------ */
 297 
 298 #define xge_os_pci_read8(pdev, cfgh, where, val)        \
 299         (*(val) = pci_config_get8(cfgh, where))
 300 
 301 #define xge_os_pci_write8(pdev, cfgh, where, val)       \
 302         pci_config_put8(cfgh, where, val)
 303 
 304 #define xge_os_pci_read16(pdev, cfgh, where, val)       \
 305         (*(val) = pci_config_get16(cfgh, where))
 306 
 307 #define xge_os_pci_write16(pdev, cfgh, where, val)      \
 308         pci_config_put16(cfgh, where, val)
 309 
 310 #define xge_os_pci_read32(pdev, cfgh, where, val)       \
 311         (*(val) = pci_config_get32(cfgh, where))
 312 
 313 #define xge_os_pci_write32(pdev, cfgh, where, val)      \
 314         pci_config_put32(cfgh, where, val)
 315 
 316 /* --------------------------- io primitives ------------------------------- */
 317 
 318 #define xge_os_pio_mem_read8(pdev, regh, addr)          \
 319         (ddi_get8(regh, (uint8_t *)(addr)))
 320 
 321 #define xge_os_pio_mem_write8(pdev, regh, val, addr)    \
 322         (ddi_put8(regh, (uint8_t *)(addr), val))
 323 
 324 #define xge_os_pio_mem_read16(pdev, regh, addr)         \
 325         (ddi_get16(regh, (uint16_t *)(addr)))
 326 
 327 #define xge_os_pio_mem_write16(pdev, regh, val, addr)   \
 328         (ddi_put16(regh, (uint16_t *)(addr), val))
 329 
 330 #define xge_os_pio_mem_read32(pdev, regh, addr)         \
 331         (ddi_get32(regh, (uint32_t *)(addr)))
 332 
 333 #define xge_os_pio_mem_write32(pdev, regh, val, addr)   \
 334         (ddi_put32(regh, (uint32_t *)(addr), val))
 335 
 336 #define xge_os_pio_mem_read64(pdev, regh, addr)         \
 337         (ddi_get64(regh, (uint64_t *)(addr)))
 338 
 339 #define xge_os_pio_mem_write64(pdev, regh, val, addr)   \
 340         (ddi_put64(regh, (uint64_t *)(addr), val))
 341 
 342 #define xge_os_flush_bridge xge_os_pio_mem_read64
 343 
 344 /* --------------------------- dma primitives ----------------------------- */
 345 
 346 #define XGE_OS_DMA_DIR_TODEVICE         DDI_DMA_SYNC_FORDEV
 347 #define XGE_OS_DMA_DIR_FROMDEVICE       DDI_DMA_SYNC_FORKERNEL
 348 #define XGE_OS_DMA_DIR_BIDIRECTIONAL    -1
 349 #if defined(__x86)
 350 #define XGE_OS_DMA_USES_IOMMU           0
 351 #else
 352 #define XGE_OS_DMA_USES_IOMMU           1
 353 #endif
 354 
 355 #define XGE_OS_INVALID_DMA_ADDR         ((dma_addr_t)0)
 356 
 357 static inline dma_addr_t xge_os_dma_map(pci_dev_h pdev, pci_dma_h dmah,
 358     void *vaddr, size_t size, int dir, int dma_flags) {
 359         int ret;
 360         uint_t flags;
 361         uint_t ncookies;
 362         ddi_dma_cookie_t dma_cookie;
 363 
 364         switch (dir) {
 365         case XGE_OS_DMA_DIR_TODEVICE:
 366                 flags = DDI_DMA_WRITE;
 367                 break;
 368         case XGE_OS_DMA_DIR_FROMDEVICE:
 369                 flags = DDI_DMA_READ;
 370                 break;
 371         case XGE_OS_DMA_DIR_BIDIRECTIONAL:
 372                 flags = DDI_DMA_RDWR;
 373                 break;
 374         default:
 375                 return (0);
 376         }
 377 
 378         flags |= (dma_flags & XGE_OS_DMA_CONSISTENT) ?
 379             DDI_DMA_CONSISTENT : DDI_DMA_STREAMING;
 380 
 381         ret = ddi_dma_addr_bind_handle(dmah, NULL, vaddr, size, flags,
 382             DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies);
 383         if (ret != DDI_SUCCESS) {
 384                 return (0);
 385         }
 386 
 387         if (ncookies != 1 || dma_cookie.dmac_size < size) {
 388                 (void) ddi_dma_unbind_handle(dmah);
 389                 return (0);
 390         }
 391 
 392         return (dma_cookie.dmac_laddress);
 393 }
 394 
 395 static inline void xge_os_dma_unmap(pci_dev_h pdev, pci_dma_h dmah,
 396     dma_addr_t dma_addr, size_t size, int dir)
 397 {
 398         (void) ddi_dma_unbind_handle(dmah);
 399 }
 400 
 401 static inline void xge_os_dma_sync(pci_dev_h pdev, pci_dma_h dmah,
 402     dma_addr_t dma_addr, u64 dma_offset, size_t length, int dir)
 403 {
 404         (void) ddi_dma_sync(dmah, dma_offset, length, dir);
 405 }
 406 
 407 #ifdef __cplusplus
 408 }
 409 #endif
 410 
 411 #endif /* _SYS_XGE_OSDEP_H */