1*d39a76e7Sxw /* 2*d39a76e7Sxw * CDDL HEADER START 3*d39a76e7Sxw * 4*d39a76e7Sxw * The contents of this file are subject to the terms of the 5*d39a76e7Sxw * Common Development and Distribution License (the "License"). 6*d39a76e7Sxw * You may not use this file except in compliance with the License. 7*d39a76e7Sxw * 8*d39a76e7Sxw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d39a76e7Sxw * or http://www.opensolaris.org/os/licensing. 10*d39a76e7Sxw * See the License for the specific language governing permissions 11*d39a76e7Sxw * and limitations under the License. 12*d39a76e7Sxw * 13*d39a76e7Sxw * When distributing Covered Code, include this CDDL HEADER in each 14*d39a76e7Sxw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d39a76e7Sxw * If applicable, add the following below this CDDL HEADER, with the 16*d39a76e7Sxw * fields enclosed by brackets "[]" replaced with your own identifying 17*d39a76e7Sxw * information: Portions Copyright [yyyy] [name of copyright owner] 18*d39a76e7Sxw * 19*d39a76e7Sxw * CDDL HEADER END 20*d39a76e7Sxw */ 21*d39a76e7Sxw 22*d39a76e7Sxw /* 23*d39a76e7Sxw * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*d39a76e7Sxw * Use is subject to license terms. 25*d39a76e7Sxw */ 26*d39a76e7Sxw 27*d39a76e7Sxw /* 28*d39a76e7Sxw * This file is part of the Chelsio T1 Ethernet driver. 29*d39a76e7Sxw * 30*d39a76e7Sxw * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 31*d39a76e7Sxw */ 32*d39a76e7Sxw 33*d39a76e7Sxw /* 34*d39a76e7Sxw * Solaris support routines for common code part of 35*d39a76e7Sxw * Chelsio PCI Ethernet Driver. 36*d39a76e7Sxw */ 37*d39a76e7Sxw 38*d39a76e7Sxw #pragma ident "%Z%%M% %I% %E% SMI" 39*d39a76e7Sxw 40*d39a76e7Sxw #include <sys/types.h> 41*d39a76e7Sxw #include <sys/conf.h> 42*d39a76e7Sxw #include <sys/stropts.h> 43*d39a76e7Sxw #include <sys/stream.h> 44*d39a76e7Sxw #include <sys/strlog.h> 45*d39a76e7Sxw #include <sys/kmem.h> 46*d39a76e7Sxw #include <sys/stat.h> 47*d39a76e7Sxw #include <sys/kstat.h> 48*d39a76e7Sxw #include <sys/modctl.h> 49*d39a76e7Sxw #include <sys/errno.h> 50*d39a76e7Sxw #include <sys/varargs.h> 51*d39a76e7Sxw #include <sys/ddi.h> 52*d39a76e7Sxw #include <sys/sunddi.h> 53*d39a76e7Sxw #include <sys/dlpi.h> 54*d39a76e7Sxw #include <sys/ethernet.h> 55*d39a76e7Sxw #include <sys/strsun.h> 56*d39a76e7Sxw #include "ostypes.h" 57*d39a76e7Sxw #undef OFFSET 58*d39a76e7Sxw #include "common.h" 59*d39a76e7Sxw #include <sys/gld.h> 60*d39a76e7Sxw #include "oschtoe.h" 61*d39a76e7Sxw #include "ch.h" /* Chelsio Driver specific parameters */ 62*d39a76e7Sxw #include "sge.h" 63*d39a76e7Sxw #include "regs.h" 64*d39a76e7Sxw 65*d39a76e7Sxw /* 66*d39a76e7Sxw * Device specific. 67*d39a76e7Sxw */ 68*d39a76e7Sxw struct pe_reg { 69*d39a76e7Sxw uint32_t cmd; 70*d39a76e7Sxw uint32_t addr; 71*d39a76e7Sxw union { 72*d39a76e7Sxw uint32_t v32; 73*d39a76e7Sxw uint64_t v64; 74*d39a76e7Sxw }vv; 75*d39a76e7Sxw union { 76*d39a76e7Sxw uint32_t m32; 77*d39a76e7Sxw uint64_t m64; 78*d39a76e7Sxw }mm; 79*d39a76e7Sxw }; 80*d39a76e7Sxw #define pe_reg_val vv.v32 81*d39a76e7Sxw #define pe_opt_val vv.v64 82*d39a76e7Sxw #define pe_mask32 mm.m32 83*d39a76e7Sxw #define pe_mask64 mm.m64 84*d39a76e7Sxw 85*d39a76e7Sxw struct toetool_reg { 86*d39a76e7Sxw uint32_t cmd; 87*d39a76e7Sxw uint32_t addr; 88*d39a76e7Sxw uint32_t val; 89*d39a76e7Sxw }; 90*d39a76e7Sxw 91*d39a76e7Sxw uint32_t 92*d39a76e7Sxw t1_read_reg_4(ch_t *obj, uint32_t reg_val) 93*d39a76e7Sxw { 94*d39a76e7Sxw return (ddi_get32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0 + reg_val))); 95*d39a76e7Sxw } 96*d39a76e7Sxw 97*d39a76e7Sxw void 98*d39a76e7Sxw t1_write_reg_4(ch_t *obj, uint32_t reg_val, uint32_t write_val) 99*d39a76e7Sxw { 100*d39a76e7Sxw ddi_put32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0+reg_val), write_val); 101*d39a76e7Sxw } 102*d39a76e7Sxw 103*d39a76e7Sxw uint32_t 104*d39a76e7Sxw t1_os_pci_read_config_2(ch_t *obj, uint32_t reg, uint16_t *val) 105*d39a76e7Sxw { 106*d39a76e7Sxw *val = pci_config_get16(obj->ch_hpci, reg); 107*d39a76e7Sxw return (0); 108*d39a76e7Sxw } 109*d39a76e7Sxw 110*d39a76e7Sxw int 111*d39a76e7Sxw t1_os_pci_write_config_2(ch_t *obj, uint32_t reg, uint16_t val) 112*d39a76e7Sxw { 113*d39a76e7Sxw pci_config_put16(obj->ch_hpci, reg, val); 114*d39a76e7Sxw return (0); 115*d39a76e7Sxw } 116*d39a76e7Sxw 117*d39a76e7Sxw uint32_t 118*d39a76e7Sxw t1_os_pci_read_config_4(ch_t *obj, uint32_t reg, uint32_t *val) 119*d39a76e7Sxw { 120*d39a76e7Sxw *val = pci_config_get32(obj->ch_hpci, reg); 121*d39a76e7Sxw return (0); 122*d39a76e7Sxw } 123*d39a76e7Sxw 124*d39a76e7Sxw int 125*d39a76e7Sxw t1_os_pci_write_config_4(ch_t *obj, uint32_t reg, uint32_t val) 126*d39a76e7Sxw { 127*d39a76e7Sxw pci_config_put32(obj->ch_hpci, reg, val); 128*d39a76e7Sxw return (0); 129*d39a76e7Sxw } 130*d39a76e7Sxw 131*d39a76e7Sxw void * 132*d39a76e7Sxw t1_os_malloc_wait_zero(size_t len) 133*d39a76e7Sxw { 134*d39a76e7Sxw return (kmem_zalloc(len, KM_SLEEP)); 135*d39a76e7Sxw } 136*d39a76e7Sxw 137*d39a76e7Sxw void 138*d39a76e7Sxw t1_os_free(void *adr, size_t len) 139*d39a76e7Sxw { 140*d39a76e7Sxw kmem_free(adr, len); 141*d39a76e7Sxw } 142*d39a76e7Sxw 143*d39a76e7Sxw int 144*d39a76e7Sxw t1_num_of_ports(ch_t *obj) 145*d39a76e7Sxw { 146*d39a76e7Sxw return (obj->config_data.num_of_ports); 147*d39a76e7Sxw } 148*d39a76e7Sxw 149*d39a76e7Sxw /* ARGSUSED */ 150*d39a76e7Sxw int 151*d39a76e7Sxw pe_os_mem_copy(ch_t *obj, void *dst, void *src, size_t len) 152*d39a76e7Sxw { 153*d39a76e7Sxw bcopy(src, dst, len); 154*d39a76e7Sxw return (0); 155*d39a76e7Sxw } 156*d39a76e7Sxw 157*d39a76e7Sxw int 158*d39a76e7Sxw pe_is_ring_buffer_enabled(ch_t *obj) 159*d39a76e7Sxw { 160*d39a76e7Sxw return (obj->config & CFGMD_RINGB); 161*d39a76e7Sxw } 162*d39a76e7Sxw 163*d39a76e7Sxw #define PE_READ_REG _IOR('i', 0xAB, 0x18) 164*d39a76e7Sxw #define PE_WRITE_REG _IOW('i', 0xAB, 0x18) 165*d39a76e7Sxw #define PE_READ_PCI _IOR('i', 0xAC, 0x18) 166*d39a76e7Sxw #define PE_WRITE_PCI _IOW('i', 0xAC, 0x18) 167*d39a76e7Sxw #define PE_READ_INTR _IOR('i', 0xAD, 0x20) 168*d39a76e7Sxw #define TOETOOL_GETTPI _IOR('i', 0xAE, 0xc) 169*d39a76e7Sxw #define TOETOOL_SETTPI _IOW('i', 0xAE, 0xc) 170*d39a76e7Sxw 171*d39a76e7Sxw void 172*d39a76e7Sxw pe_ioctl(ch_t *chp, queue_t *q, mblk_t *mp) 173*d39a76e7Sxw { 174*d39a76e7Sxw struct iocblk *iocp; 175*d39a76e7Sxw mblk_t *dmp; 176*d39a76e7Sxw struct pe_reg *pe; 177*d39a76e7Sxw struct toetool_reg *te; 178*d39a76e7Sxw uint32_t reg; 179*d39a76e7Sxw struct sge_intr_counts *se, *sep; 180*d39a76e7Sxw 181*d39a76e7Sxw iocp = (struct iocblk *)mp->b_rptr; 182*d39a76e7Sxw 183*d39a76e7Sxw /* don't support TRASPARENT ioctls */ 184*d39a76e7Sxw if (iocp->ioc_count == TRANSPARENT) { 185*d39a76e7Sxw iocp->ioc_error = ENOTTY; 186*d39a76e7Sxw goto bad; 187*d39a76e7Sxw } 188*d39a76e7Sxw 189*d39a76e7Sxw /* 190*d39a76e7Sxw * sanity checks. There should be a M_DATA mblk following 191*d39a76e7Sxw * the initial M_IOCTL mblk 192*d39a76e7Sxw */ 193*d39a76e7Sxw if ((dmp = mp->b_cont) == NULL) { 194*d39a76e7Sxw iocp->ioc_error = ENOTTY; 195*d39a76e7Sxw goto bad; 196*d39a76e7Sxw } 197*d39a76e7Sxw 198*d39a76e7Sxw if (dmp->b_datap->db_type != M_DATA) { 199*d39a76e7Sxw iocp->ioc_error = ENOTTY; 200*d39a76e7Sxw goto bad; 201*d39a76e7Sxw } 202*d39a76e7Sxw 203*d39a76e7Sxw pe = (struct pe_reg *)dmp->b_rptr; 204*d39a76e7Sxw se = (struct sge_intr_counts *)dmp->b_rptr; 205*d39a76e7Sxw te = (struct toetool_reg *)dmp->b_rptr; 206*d39a76e7Sxw 207*d39a76e7Sxw /* now process the ioctl */ 208*d39a76e7Sxw switch (iocp->ioc_cmd) { 209*d39a76e7Sxw case PE_READ_REG: 210*d39a76e7Sxw 211*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) { 212*d39a76e7Sxw iocp->ioc_error = ENOTTY; 213*d39a76e7Sxw goto bad; 214*d39a76e7Sxw } 215*d39a76e7Sxw 216*d39a76e7Sxw /* protect against bad addr values */ 217*d39a76e7Sxw pe->addr &= (uint32_t)~3; 218*d39a76e7Sxw 219*d39a76e7Sxw pe->pe_mask32 = 0xFFFFFFFF; 220*d39a76e7Sxw 221*d39a76e7Sxw if (pe->addr == 0x950) 222*d39a76e7Sxw pe->pe_reg_val = reg = t1_sge_get_ptimeout(chp); 223*d39a76e7Sxw else 224*d39a76e7Sxw pe->pe_reg_val = reg = t1_read_reg_4(chp, pe->addr); 225*d39a76e7Sxw 226*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 227*d39a76e7Sxw iocp->ioc_count = sizeof (*pe); 228*d39a76e7Sxw 229*d39a76e7Sxw break; 230*d39a76e7Sxw 231*d39a76e7Sxw case PE_WRITE_REG: 232*d39a76e7Sxw 233*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) { 234*d39a76e7Sxw iocp->ioc_error = ENOTTY; 235*d39a76e7Sxw goto bad; 236*d39a76e7Sxw } 237*d39a76e7Sxw 238*d39a76e7Sxw if (pe->addr == 0x950) 239*d39a76e7Sxw t1_sge_set_ptimeout(chp, pe->pe_reg_val); 240*d39a76e7Sxw else { 241*d39a76e7Sxw if (pe->pe_mask32 != 0xffffffff) { 242*d39a76e7Sxw reg = t1_read_reg_4(chp, pe->addr); 243*d39a76e7Sxw pe->pe_reg_val |= (reg & ~pe->pe_mask32); 244*d39a76e7Sxw } 245*d39a76e7Sxw 246*d39a76e7Sxw t1_write_reg_4(chp, pe->addr, pe->pe_reg_val); 247*d39a76e7Sxw } 248*d39a76e7Sxw 249*d39a76e7Sxw if (mp->b_cont) 250*d39a76e7Sxw freemsg(mp->b_cont); 251*d39a76e7Sxw mp->b_cont = NULL; 252*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 253*d39a76e7Sxw break; 254*d39a76e7Sxw 255*d39a76e7Sxw case PE_READ_PCI: 256*d39a76e7Sxw 257*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) { 258*d39a76e7Sxw iocp->ioc_error = ENOTTY; 259*d39a76e7Sxw goto bad; 260*d39a76e7Sxw } 261*d39a76e7Sxw 262*d39a76e7Sxw /* protect against bad addr values */ 263*d39a76e7Sxw pe->addr &= (uint32_t)~3; 264*d39a76e7Sxw 265*d39a76e7Sxw pe->pe_mask32 = 0xFFFFFFFF; 266*d39a76e7Sxw pe->pe_reg_val = reg = pci_config_get32(chp->ch_hpci, pe->addr); 267*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 268*d39a76e7Sxw iocp->ioc_count = sizeof (*pe); 269*d39a76e7Sxw 270*d39a76e7Sxw break; 271*d39a76e7Sxw 272*d39a76e7Sxw case PE_WRITE_PCI: 273*d39a76e7Sxw 274*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) { 275*d39a76e7Sxw iocp->ioc_error = ENOTTY; 276*d39a76e7Sxw goto bad; 277*d39a76e7Sxw } 278*d39a76e7Sxw 279*d39a76e7Sxw if (pe->pe_mask32 != 0xffffffff) { 280*d39a76e7Sxw reg = pci_config_get32(chp->ch_hpci, pe->addr); 281*d39a76e7Sxw pe->pe_reg_val |= (reg & ~pe->pe_mask32); 282*d39a76e7Sxw } 283*d39a76e7Sxw 284*d39a76e7Sxw pci_config_put32(chp->ch_hpci, pe->addr, pe->pe_reg_val); 285*d39a76e7Sxw 286*d39a76e7Sxw if (mp->b_cont) 287*d39a76e7Sxw freemsg(mp->b_cont); 288*d39a76e7Sxw mp->b_cont = NULL; 289*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 290*d39a76e7Sxw break; 291*d39a76e7Sxw 292*d39a76e7Sxw case PE_READ_INTR: 293*d39a76e7Sxw 294*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*se)) { 295*d39a76e7Sxw iocp->ioc_error = ENOTTY; 296*d39a76e7Sxw goto bad; 297*d39a76e7Sxw } 298*d39a76e7Sxw 299*d39a76e7Sxw sep = sge_get_stat(chp->sge); 300*d39a76e7Sxw bcopy(sep, se, sizeof (*se)); 301*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 302*d39a76e7Sxw iocp->ioc_count = sizeof (*se); 303*d39a76e7Sxw break; 304*d39a76e7Sxw 305*d39a76e7Sxw case TOETOOL_GETTPI: 306*d39a76e7Sxw 307*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) { 308*d39a76e7Sxw iocp->ioc_error = ENOTTY; 309*d39a76e7Sxw goto bad; 310*d39a76e7Sxw } 311*d39a76e7Sxw 312*d39a76e7Sxw /* protect against bad addr values */ 313*d39a76e7Sxw if ((te->addr & 3) != 0) { 314*d39a76e7Sxw iocp->ioc_error = ENOTTY; 315*d39a76e7Sxw goto bad; 316*d39a76e7Sxw } 317*d39a76e7Sxw 318*d39a76e7Sxw (void) t1_tpi_read(chp, te->addr, &te->val); 319*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 320*d39a76e7Sxw iocp->ioc_count = sizeof (*te); 321*d39a76e7Sxw 322*d39a76e7Sxw break; 323*d39a76e7Sxw 324*d39a76e7Sxw case TOETOOL_SETTPI: 325*d39a76e7Sxw 326*d39a76e7Sxw if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) { 327*d39a76e7Sxw iocp->ioc_error = ENOTTY; 328*d39a76e7Sxw goto bad; 329*d39a76e7Sxw } 330*d39a76e7Sxw 331*d39a76e7Sxw /* protect against bad addr values */ 332*d39a76e7Sxw if ((te->addr & 3) != 0) { 333*d39a76e7Sxw iocp->ioc_error = ENOTTY; 334*d39a76e7Sxw goto bad; 335*d39a76e7Sxw } 336*d39a76e7Sxw 337*d39a76e7Sxw (void) t1_tpi_write(chp, te->addr, te->val); 338*d39a76e7Sxw 339*d39a76e7Sxw mp->b_datap->db_type = M_IOCACK; 340*d39a76e7Sxw iocp->ioc_count = sizeof (*te); 341*d39a76e7Sxw 342*d39a76e7Sxw break; 343*d39a76e7Sxw 344*d39a76e7Sxw default: 345*d39a76e7Sxw iocp->ioc_error = ENOTTY; 346*d39a76e7Sxw goto bad; 347*d39a76e7Sxw } 348*d39a76e7Sxw 349*d39a76e7Sxw qreply(q, mp); 350*d39a76e7Sxw 351*d39a76e7Sxw return; 352*d39a76e7Sxw 353*d39a76e7Sxw bad: 354*d39a76e7Sxw if (mp->b_cont) 355*d39a76e7Sxw freemsg(mp->b_cont); 356*d39a76e7Sxw mp->b_cont = NULL; 357*d39a76e7Sxw mp->b_datap->db_type = M_IOCNAK; 358*d39a76e7Sxw 359*d39a76e7Sxw qreply(q, mp); 360*d39a76e7Sxw } 361*d39a76e7Sxw 362*d39a76e7Sxw /* 363*d39a76e7Sxw * Can't wait for memory here, since we have to use the Solaris dma 364*d39a76e7Sxw * mechanisms to determine the physical address. 365*d39a76e7Sxw * flg is either 0 (read) or DMA_OUT (write). 366*d39a76e7Sxw */ 367*d39a76e7Sxw void * 368*d39a76e7Sxw pe_os_malloc_contig_wait_zero(ch_t *chp, size_t len, uint64_t *dma_addr, 369*d39a76e7Sxw ulong_t *dh, ulong_t *ah, uint32_t flg) 370*d39a76e7Sxw { 371*d39a76e7Sxw void *mem = NULL; 372*d39a76e7Sxw uint64_t pa; 373*d39a76e7Sxw 374*d39a76e7Sxw /* 375*d39a76e7Sxw * byte swap, consistant mapping & 4k aligned 376*d39a76e7Sxw */ 377*d39a76e7Sxw mem = ch_alloc_dma_mem(chp, 1, DMA_4KALN|flg, len, &pa, dh, ah); 378*d39a76e7Sxw if (mem == NULL) { 379*d39a76e7Sxw return (0); 380*d39a76e7Sxw } 381*d39a76e7Sxw 382*d39a76e7Sxw if (dma_addr) 383*d39a76e7Sxw *dma_addr = pa; 384*d39a76e7Sxw 385*d39a76e7Sxw bzero(mem, len); 386*d39a76e7Sxw 387*d39a76e7Sxw return ((void *)mem); 388*d39a76e7Sxw } 389*d39a76e7Sxw 390*d39a76e7Sxw /* ARGSUSED */ 391*d39a76e7Sxw void 392*d39a76e7Sxw pe_os_free_contig(ch_t *obj, size_t len, void *addr, uint64_t dma_addr, 393*d39a76e7Sxw ulong_t dh, ulong_t ah) 394*d39a76e7Sxw { 395*d39a76e7Sxw ch_free_dma_mem(dh, ah); 396*d39a76e7Sxw } 397*d39a76e7Sxw 398*d39a76e7Sxw void 399*d39a76e7Sxw t1_fatal_err(ch_t *adapter) 400*d39a76e7Sxw { 401*d39a76e7Sxw if (adapter->ch_flags & PEINITDONE) { 402*d39a76e7Sxw (void) sge_stop(adapter->sge); 403*d39a76e7Sxw t1_interrupts_disable(adapter); 404*d39a76e7Sxw } 405*d39a76e7Sxw CH_ALERT("%s: encountered fatal error, operation suspended\n", 406*d39a76e7Sxw adapter_name(adapter)); 407*d39a76e7Sxw } 408*d39a76e7Sxw 409*d39a76e7Sxw void 410*d39a76e7Sxw CH_ALERT(const char *fmt, ...) 411*d39a76e7Sxw { 412*d39a76e7Sxw va_list ap; 413*d39a76e7Sxw char buf[128]; 414*d39a76e7Sxw 415*d39a76e7Sxw /* format buf using fmt and arguments contained in ap */ 416*d39a76e7Sxw 417*d39a76e7Sxw va_start(ap, fmt); 418*d39a76e7Sxw (void) vsprintf(buf, fmt, ap); 419*d39a76e7Sxw va_end(ap); 420*d39a76e7Sxw 421*d39a76e7Sxw /* pass formatted string to cmn_err(9F) */ 422*d39a76e7Sxw cmn_err(CE_WARN, "%s", buf); 423*d39a76e7Sxw } 424*d39a76e7Sxw 425*d39a76e7Sxw void 426*d39a76e7Sxw CH_WARN(const char *fmt, ...) 427*d39a76e7Sxw { 428*d39a76e7Sxw va_list ap; 429*d39a76e7Sxw char buf[128]; 430*d39a76e7Sxw 431*d39a76e7Sxw /* format buf using fmt and arguments contained in ap */ 432*d39a76e7Sxw 433*d39a76e7Sxw va_start(ap, fmt); 434*d39a76e7Sxw (void) vsprintf(buf, fmt, ap); 435*d39a76e7Sxw va_end(ap); 436*d39a76e7Sxw 437*d39a76e7Sxw /* pass formatted string to cmn_err(9F) */ 438*d39a76e7Sxw cmn_err(CE_WARN, "%s", buf); 439*d39a76e7Sxw } 440*d39a76e7Sxw 441*d39a76e7Sxw void 442*d39a76e7Sxw CH_ERR(const char *fmt, ...) 443*d39a76e7Sxw { 444*d39a76e7Sxw va_list ap; 445*d39a76e7Sxw char buf[128]; 446*d39a76e7Sxw 447*d39a76e7Sxw /* format buf using fmt and arguments contained in ap */ 448*d39a76e7Sxw 449*d39a76e7Sxw va_start(ap, fmt); 450*d39a76e7Sxw (void) vsprintf(buf, fmt, ap); 451*d39a76e7Sxw va_end(ap); 452*d39a76e7Sxw 453*d39a76e7Sxw /* pass formatted string to cmn_err(9F) */ 454*d39a76e7Sxw cmn_err(CE_WARN, "%s", buf); 455*d39a76e7Sxw } 456*d39a76e7Sxw 457*d39a76e7Sxw u32 458*d39a76e7Sxw le32_to_cpu(u32 data) 459*d39a76e7Sxw { 460*d39a76e7Sxw #if BYTE_ORDER == BIG_ENDIAN 461*d39a76e7Sxw uint8_t *in, t; 462*d39a76e7Sxw in = (uint8_t *)&data; 463*d39a76e7Sxw t = in[0]; 464*d39a76e7Sxw in[0] = in[3]; 465*d39a76e7Sxw in[3] = t; 466*d39a76e7Sxw t = in[1]; 467*d39a76e7Sxw in[1] = in[2]; 468*d39a76e7Sxw in[2] = t; 469*d39a76e7Sxw #endif 470*d39a76e7Sxw return (data); 471*d39a76e7Sxw } 472*d39a76e7Sxw 473*d39a76e7Sxw /* 474*d39a76e7Sxw * This function initializes a polling routine, Poll_func 475*d39a76e7Sxw * which will be polled ever N Microsecond, where N is 476*d39a76e7Sxw * provided in the cyclic start routine. 477*d39a76e7Sxw */ 478*d39a76e7Sxw /* ARGSUSED */ 479*d39a76e7Sxw void 480*d39a76e7Sxw ch_init_cyclic(void *adapter, p_ch_cyclic_t cyclic, 481*d39a76e7Sxw void (*poll_func)(void *), void *arg) 482*d39a76e7Sxw { 483*d39a76e7Sxw cyclic->func = poll_func; 484*d39a76e7Sxw cyclic->arg = arg; 485*d39a76e7Sxw cyclic->timer = 0; 486*d39a76e7Sxw } 487*d39a76e7Sxw 488*d39a76e7Sxw /* 489*d39a76e7Sxw * Cyclic function which provides a periodic polling 490*d39a76e7Sxw * capability to Solaris. The poll function provided by 491*d39a76e7Sxw * the 'ch_init_cyclic' function is called from this 492*d39a76e7Sxw * here, and this routine launches a new one-shot 493*d39a76e7Sxw * timer to bring it back in some period later. 494*d39a76e7Sxw */ 495*d39a76e7Sxw void 496*d39a76e7Sxw ch_cyclic(p_ch_cyclic_t cyclic) 497*d39a76e7Sxw { 498*d39a76e7Sxw if (cyclic->timer != 0) { 499*d39a76e7Sxw cyclic->func(cyclic->arg); 500*d39a76e7Sxw cyclic->timer = timeout((void(*)(void *))ch_cyclic, 501*d39a76e7Sxw (void *)cyclic, cyclic->period); 502*d39a76e7Sxw } 503*d39a76e7Sxw } 504*d39a76e7Sxw 505*d39a76e7Sxw /* 506*d39a76e7Sxw * The 'ch_start_cyclic' starts the polling. 507*d39a76e7Sxw */ 508*d39a76e7Sxw void 509*d39a76e7Sxw ch_start_cyclic(p_ch_cyclic_t cyclic, unsigned long period) 510*d39a76e7Sxw { 511*d39a76e7Sxw cyclic->period = drv_usectohz(period * 1000); 512*d39a76e7Sxw if (cyclic->timer == 0) { 513*d39a76e7Sxw cyclic->timer = timeout((void(*)(void *))ch_cyclic, 514*d39a76e7Sxw (void *)cyclic, cyclic->period); 515*d39a76e7Sxw } 516*d39a76e7Sxw } 517*d39a76e7Sxw 518*d39a76e7Sxw /* 519*d39a76e7Sxw * The 'ch_stop_cyclic' stops the polling. 520*d39a76e7Sxw */ 521*d39a76e7Sxw void 522*d39a76e7Sxw ch_stop_cyclic(p_ch_cyclic_t cyclic) 523*d39a76e7Sxw { 524*d39a76e7Sxw timeout_id_t timer; 525*d39a76e7Sxw clock_t value; 526*d39a76e7Sxw 527*d39a76e7Sxw do { 528*d39a76e7Sxw timer = cyclic->timer; 529*d39a76e7Sxw cyclic->timer = 0; 530*d39a76e7Sxw value = untimeout(timer); 531*d39a76e7Sxw if (value == 0) 532*d39a76e7Sxw delay(2 * cyclic->period); 533*d39a76e7Sxw } while ((timer != 0) && (value == 0)); 534*d39a76e7Sxw } 535