xref: /onnv-gate/usr/src/uts/common/io/chxge/glue.c (revision 7656:2621e50fdf4a)
13833Sxw161283 /*
23833Sxw161283  * CDDL HEADER START
33833Sxw161283  *
43833Sxw161283  * The contents of this file are subject to the terms of the
53833Sxw161283  * Common Development and Distribution License (the "License").
63833Sxw161283  * You may not use this file except in compliance with the License.
73833Sxw161283  *
83833Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93833Sxw161283  * or http://www.opensolaris.org/os/licensing.
103833Sxw161283  * See the License for the specific language governing permissions
113833Sxw161283  * and limitations under the License.
123833Sxw161283  *
133833Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
143833Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153833Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
163833Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
173833Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
183833Sxw161283  *
193833Sxw161283  * CDDL HEADER END
203833Sxw161283  */
213833Sxw161283 
223833Sxw161283 /*
23*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
243833Sxw161283  * Use is subject to license terms.
253833Sxw161283  */
263833Sxw161283 
273833Sxw161283 /*
283833Sxw161283  * This file is part of the Chelsio T1 Ethernet driver.
293833Sxw161283  *
303833Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
313833Sxw161283  */
323833Sxw161283 
333833Sxw161283 /*
343833Sxw161283  * Solaris support routines for common code part of
353833Sxw161283  * Chelsio PCI Ethernet Driver.
363833Sxw161283  */
373833Sxw161283 
383833Sxw161283 #include <sys/types.h>
393833Sxw161283 #include <sys/conf.h>
403833Sxw161283 #include <sys/stropts.h>
413833Sxw161283 #include <sys/stream.h>
423833Sxw161283 #include <sys/strlog.h>
433833Sxw161283 #include <sys/kmem.h>
443833Sxw161283 #include <sys/stat.h>
453833Sxw161283 #include <sys/kstat.h>
463833Sxw161283 #include <sys/modctl.h>
473833Sxw161283 #include <sys/errno.h>
483833Sxw161283 #include <sys/varargs.h>
493833Sxw161283 #include <sys/ddi.h>
503833Sxw161283 #include <sys/sunddi.h>
513833Sxw161283 #include <sys/dlpi.h>
523833Sxw161283 #include <sys/ethernet.h>
533833Sxw161283 #include <sys/strsun.h>
543833Sxw161283 #include "ostypes.h"
553833Sxw161283 #undef OFFSET
563833Sxw161283 #include "common.h"
573833Sxw161283 #include <sys/gld.h>
583833Sxw161283 #include "oschtoe.h"
593833Sxw161283 #include "ch.h"			/* Chelsio Driver specific parameters */
603833Sxw161283 #include "sge.h"
613833Sxw161283 #include "regs.h"
623833Sxw161283 
633833Sxw161283 /*
643833Sxw161283  * Device specific.
653833Sxw161283  */
663833Sxw161283 struct pe_reg {
673833Sxw161283 	uint32_t cmd;
683833Sxw161283 	uint32_t addr;
693833Sxw161283 	union {
703833Sxw161283 		uint32_t v32;
713833Sxw161283 		uint64_t v64;
723833Sxw161283 	}vv;
733833Sxw161283 	union {
743833Sxw161283 		uint32_t m32;
753833Sxw161283 		uint64_t m64;
763833Sxw161283 	}mm;
773833Sxw161283 };
783833Sxw161283 #define	pe_reg_val vv.v32
793833Sxw161283 #define	pe_opt_val vv.v64
803833Sxw161283 #define	pe_mask32  mm.m32
813833Sxw161283 #define	pe_mask64  mm.m64
823833Sxw161283 
833833Sxw161283 struct toetool_reg {
843833Sxw161283 	uint32_t cmd;
853833Sxw161283 	uint32_t addr;
863833Sxw161283 	uint32_t val;
873833Sxw161283 };
883833Sxw161283 
893833Sxw161283 uint32_t
t1_read_reg_4(ch_t * obj,uint32_t reg_val)903833Sxw161283 t1_read_reg_4(ch_t *obj, uint32_t reg_val)
913833Sxw161283 {
923833Sxw161283 	return (ddi_get32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0 + reg_val)));
933833Sxw161283 }
943833Sxw161283 
953833Sxw161283 void
t1_write_reg_4(ch_t * obj,uint32_t reg_val,uint32_t write_val)963833Sxw161283 t1_write_reg_4(ch_t *obj, uint32_t reg_val, uint32_t write_val)
973833Sxw161283 {
983833Sxw161283 	ddi_put32(obj->ch_hbar0, (uint32_t *)(obj->ch_bar0+reg_val), write_val);
993833Sxw161283 }
1003833Sxw161283 
1013833Sxw161283 uint32_t
t1_os_pci_read_config_2(ch_t * obj,uint32_t reg,uint16_t * val)1023833Sxw161283 t1_os_pci_read_config_2(ch_t *obj, uint32_t reg, uint16_t *val)
1033833Sxw161283 {
1043833Sxw161283 	*val = pci_config_get16(obj->ch_hpci, reg);
1053833Sxw161283 	return (0);
1063833Sxw161283 }
1073833Sxw161283 
1083833Sxw161283 int
t1_os_pci_write_config_2(ch_t * obj,uint32_t reg,uint16_t val)1093833Sxw161283 t1_os_pci_write_config_2(ch_t *obj, uint32_t reg, uint16_t val)
1103833Sxw161283 {
1113833Sxw161283 	pci_config_put16(obj->ch_hpci, reg, val);
1123833Sxw161283 	return (0);
1133833Sxw161283 }
1143833Sxw161283 
1153833Sxw161283 uint32_t
t1_os_pci_read_config_4(ch_t * obj,uint32_t reg,uint32_t * val)1163833Sxw161283 t1_os_pci_read_config_4(ch_t *obj, uint32_t reg, uint32_t *val)
1173833Sxw161283 {
1183833Sxw161283 	*val = pci_config_get32(obj->ch_hpci, reg);
1193833Sxw161283 	return (0);
1203833Sxw161283 }
1213833Sxw161283 
1223833Sxw161283 int
t1_os_pci_write_config_4(ch_t * obj,uint32_t reg,uint32_t val)1233833Sxw161283 t1_os_pci_write_config_4(ch_t *obj, uint32_t reg, uint32_t val)
1243833Sxw161283 {
1253833Sxw161283 	pci_config_put32(obj->ch_hpci, reg, val);
1263833Sxw161283 	return (0);
1273833Sxw161283 }
1283833Sxw161283 
1293833Sxw161283 void *
t1_os_malloc_wait_zero(size_t len)1303833Sxw161283 t1_os_malloc_wait_zero(size_t len)
1313833Sxw161283 {
1323833Sxw161283 	return (kmem_zalloc(len, KM_SLEEP));
1333833Sxw161283 }
1343833Sxw161283 
1353833Sxw161283 void
t1_os_free(void * adr,size_t len)1363833Sxw161283 t1_os_free(void *adr, size_t len)
1373833Sxw161283 {
1383833Sxw161283 	kmem_free(adr, len);
1393833Sxw161283 }
1403833Sxw161283 
1413833Sxw161283 int
t1_num_of_ports(ch_t * obj)1423833Sxw161283 t1_num_of_ports(ch_t *obj)
1433833Sxw161283 {
1443833Sxw161283 	return (obj->config_data.num_of_ports);
1453833Sxw161283 }
1463833Sxw161283 
1473833Sxw161283 /* ARGSUSED */
1483833Sxw161283 int
pe_os_mem_copy(ch_t * obj,void * dst,void * src,size_t len)1493833Sxw161283 pe_os_mem_copy(ch_t *obj, void *dst, void *src, size_t len)
1503833Sxw161283 {
1513833Sxw161283 	bcopy(src, dst, len);
1523833Sxw161283 	return (0);
1533833Sxw161283 }
1543833Sxw161283 
1553833Sxw161283 int
pe_is_ring_buffer_enabled(ch_t * obj)1563833Sxw161283 pe_is_ring_buffer_enabled(ch_t *obj)
1573833Sxw161283 {
1583833Sxw161283 	return (obj->config & CFGMD_RINGB);
1593833Sxw161283 }
1603833Sxw161283 
1613833Sxw161283 #define	PE_READ_REG  _IOR('i', 0xAB, 0x18)
1623833Sxw161283 #define	PE_WRITE_REG _IOW('i', 0xAB, 0x18)
1633833Sxw161283 #define	PE_READ_PCI  _IOR('i', 0xAC, 0x18)
1643833Sxw161283 #define	PE_WRITE_PCI _IOW('i', 0xAC, 0x18)
1653833Sxw161283 #define	PE_READ_INTR _IOR('i', 0xAD, 0x20)
1663833Sxw161283 #define	TOETOOL_GETTPI _IOR('i', 0xAE, 0xc)
1673833Sxw161283 #define	TOETOOL_SETTPI _IOW('i', 0xAE, 0xc)
1683833Sxw161283 
1693833Sxw161283 void
pe_ioctl(ch_t * chp,queue_t * q,mblk_t * mp)1703833Sxw161283 pe_ioctl(ch_t *chp, queue_t *q, mblk_t *mp)
1713833Sxw161283 {
1723833Sxw161283 	struct iocblk *iocp;
1733833Sxw161283 	mblk_t *dmp;
1743833Sxw161283 	struct pe_reg *pe;
1753833Sxw161283 	struct toetool_reg *te;
1763833Sxw161283 	uint32_t reg;
1773833Sxw161283 	struct sge_intr_counts *se, *sep;
1783833Sxw161283 
1793833Sxw161283 	iocp = (struct iocblk *)mp->b_rptr;
1803833Sxw161283 
1813833Sxw161283 	/* don't support TRASPARENT ioctls */
1823833Sxw161283 	if (iocp->ioc_count == TRANSPARENT) {
1833833Sxw161283 		iocp->ioc_error = ENOTTY;
1843833Sxw161283 		goto bad;
1853833Sxw161283 	}
1863833Sxw161283 
1873833Sxw161283 	/*
1883833Sxw161283 	 * sanity checks. There should be a M_DATA mblk following
1893833Sxw161283 	 * the initial M_IOCTL mblk
1903833Sxw161283 	 */
1913833Sxw161283 	if ((dmp = mp->b_cont) == NULL) {
1923833Sxw161283 		iocp->ioc_error = ENOTTY;
1933833Sxw161283 		goto bad;
1943833Sxw161283 	}
1953833Sxw161283 
1963833Sxw161283 	if (dmp->b_datap->db_type != M_DATA) {
1973833Sxw161283 		iocp->ioc_error = ENOTTY;
1983833Sxw161283 		goto bad;
1993833Sxw161283 	}
2003833Sxw161283 
2013833Sxw161283 	pe = (struct pe_reg *)dmp->b_rptr;
2023833Sxw161283 	se = (struct sge_intr_counts *)dmp->b_rptr;
2033833Sxw161283 	te = (struct toetool_reg *)dmp->b_rptr;
2043833Sxw161283 
2053833Sxw161283 	/* now process the ioctl */
2063833Sxw161283 	switch (iocp->ioc_cmd) {
2073833Sxw161283 	case PE_READ_REG:
2083833Sxw161283 
2093833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
2103833Sxw161283 			iocp->ioc_error = ENOTTY;
2113833Sxw161283 			goto bad;
2123833Sxw161283 		}
2133833Sxw161283 
2143833Sxw161283 		/* protect against bad addr values */
2153833Sxw161283 		pe->addr &= (uint32_t)~3;
2163833Sxw161283 
2173833Sxw161283 		pe->pe_mask32 = 0xFFFFFFFF;
2183833Sxw161283 
2193833Sxw161283 		if (pe->addr == 0x950)
2203833Sxw161283 			pe->pe_reg_val = reg = t1_sge_get_ptimeout(chp);
2213833Sxw161283 		else
2223833Sxw161283 			pe->pe_reg_val = reg = t1_read_reg_4(chp, pe->addr);
2233833Sxw161283 
2243833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
2253833Sxw161283 		iocp->ioc_count = sizeof (*pe);
2263833Sxw161283 
2273833Sxw161283 		break;
2283833Sxw161283 
2293833Sxw161283 	case PE_WRITE_REG:
2303833Sxw161283 
2313833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
2323833Sxw161283 			iocp->ioc_error = ENOTTY;
2333833Sxw161283 			goto bad;
2343833Sxw161283 		}
2353833Sxw161283 
2363833Sxw161283 		if (pe->addr == 0x950)
2373833Sxw161283 			t1_sge_set_ptimeout(chp, pe->pe_reg_val);
2383833Sxw161283 		else {
2393833Sxw161283 			if (pe->pe_mask32 != 0xffffffff) {
2403833Sxw161283 				reg = t1_read_reg_4(chp, pe->addr);
2413833Sxw161283 				pe->pe_reg_val |= (reg & ~pe->pe_mask32);
2423833Sxw161283 			}
2433833Sxw161283 
2443833Sxw161283 			t1_write_reg_4(chp, pe->addr,  pe->pe_reg_val);
2453833Sxw161283 		}
2463833Sxw161283 
2473833Sxw161283 		if (mp->b_cont)
2483833Sxw161283 			freemsg(mp->b_cont);
2493833Sxw161283 		mp->b_cont = NULL;
2503833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
2513833Sxw161283 		break;
2523833Sxw161283 
2533833Sxw161283 	case PE_READ_PCI:
2543833Sxw161283 
2553833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
2563833Sxw161283 			iocp->ioc_error = ENOTTY;
2573833Sxw161283 			goto bad;
2583833Sxw161283 		}
2593833Sxw161283 
2603833Sxw161283 		/* protect against bad addr values */
2613833Sxw161283 		pe->addr &= (uint32_t)~3;
2623833Sxw161283 
2633833Sxw161283 		pe->pe_mask32 = 0xFFFFFFFF;
2643833Sxw161283 		pe->pe_reg_val = reg = pci_config_get32(chp->ch_hpci, pe->addr);
2653833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
2663833Sxw161283 		iocp->ioc_count = sizeof (*pe);
2673833Sxw161283 
2683833Sxw161283 		break;
2693833Sxw161283 
2703833Sxw161283 	case PE_WRITE_PCI:
2713833Sxw161283 
2723833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*pe)) {
2733833Sxw161283 			iocp->ioc_error = ENOTTY;
2743833Sxw161283 			goto bad;
2753833Sxw161283 		}
2763833Sxw161283 
2773833Sxw161283 		if (pe->pe_mask32 != 0xffffffff) {
2783833Sxw161283 			reg = pci_config_get32(chp->ch_hpci, pe->addr);
2793833Sxw161283 			pe->pe_reg_val |= (reg & ~pe->pe_mask32);
2803833Sxw161283 		}
2813833Sxw161283 
2823833Sxw161283 		pci_config_put32(chp->ch_hpci, pe->addr,  pe->pe_reg_val);
2833833Sxw161283 
2843833Sxw161283 		if (mp->b_cont)
2853833Sxw161283 			freemsg(mp->b_cont);
2863833Sxw161283 		mp->b_cont = NULL;
2873833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
2883833Sxw161283 		break;
2893833Sxw161283 
2903833Sxw161283 	case PE_READ_INTR:
2913833Sxw161283 
2923833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*se)) {
2933833Sxw161283 			iocp->ioc_error = ENOTTY;
2943833Sxw161283 			goto bad;
2953833Sxw161283 		}
2963833Sxw161283 
2973833Sxw161283 		sep = sge_get_stat(chp->sge);
2983833Sxw161283 		bcopy(sep, se, sizeof (*se));
2993833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
3003833Sxw161283 		iocp->ioc_count = sizeof (*se);
3013833Sxw161283 		break;
3023833Sxw161283 
3033833Sxw161283 	case TOETOOL_GETTPI:
3043833Sxw161283 
3053833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) {
3063833Sxw161283 			iocp->ioc_error = ENOTTY;
3073833Sxw161283 			goto bad;
3083833Sxw161283 		}
3093833Sxw161283 
3103833Sxw161283 		/* protect against bad addr values */
3113833Sxw161283 		if ((te->addr & 3) != 0) {
3123833Sxw161283 			iocp->ioc_error = ENOTTY;
3133833Sxw161283 			goto bad;
3143833Sxw161283 		}
3153833Sxw161283 
3163833Sxw161283 		(void) t1_tpi_read(chp, te->addr, &te->val);
3173833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
3183833Sxw161283 		iocp->ioc_count = sizeof (*te);
3193833Sxw161283 
3203833Sxw161283 		break;
3213833Sxw161283 
3223833Sxw161283 	case TOETOOL_SETTPI:
3233833Sxw161283 
3243833Sxw161283 		if ((dmp->b_wptr - dmp->b_rptr) != sizeof (*te)) {
3253833Sxw161283 			iocp->ioc_error = ENOTTY;
3263833Sxw161283 			goto bad;
3273833Sxw161283 		}
3283833Sxw161283 
3293833Sxw161283 		/* protect against bad addr values */
3303833Sxw161283 		if ((te->addr & 3) != 0) {
3313833Sxw161283 			iocp->ioc_error = ENOTTY;
3323833Sxw161283 			goto bad;
3333833Sxw161283 		}
3343833Sxw161283 
3353833Sxw161283 		(void) t1_tpi_write(chp, te->addr, te->val);
3363833Sxw161283 
3373833Sxw161283 		mp->b_datap->db_type = M_IOCACK;
3383833Sxw161283 		iocp->ioc_count = sizeof (*te);
3393833Sxw161283 
3403833Sxw161283 		break;
3413833Sxw161283 
3423833Sxw161283 	default:
3433833Sxw161283 		iocp->ioc_error = ENOTTY;
3443833Sxw161283 		goto bad;
3453833Sxw161283 	}
3463833Sxw161283 
3473833Sxw161283 	qreply(q, mp);
3483833Sxw161283 
3493833Sxw161283 	return;
3503833Sxw161283 
3513833Sxw161283 bad:
3523833Sxw161283 	if (mp->b_cont)
3533833Sxw161283 		freemsg(mp->b_cont);
3543833Sxw161283 	mp->b_cont = NULL;
3553833Sxw161283 	mp->b_datap->db_type = M_IOCNAK;
3563833Sxw161283 
3573833Sxw161283 	qreply(q, mp);
3583833Sxw161283 }
3593833Sxw161283 
3603833Sxw161283 /*
3613833Sxw161283  * Can't wait for memory here, since we have to use the Solaris dma
3623833Sxw161283  * mechanisms to determine the physical address.
3633833Sxw161283  * flg is either 0 (read) or DMA_OUT (write).
3643833Sxw161283  */
3653833Sxw161283 void *
pe_os_malloc_contig_wait_zero(ch_t * chp,size_t len,uint64_t * dma_addr,ulong_t * dh,ulong_t * ah,uint32_t flg)3663833Sxw161283 pe_os_malloc_contig_wait_zero(ch_t *chp, size_t len, uint64_t *dma_addr,
3673833Sxw161283 	ulong_t *dh, ulong_t *ah, uint32_t flg)
3683833Sxw161283 {
3693833Sxw161283 	void *mem = NULL;
3703833Sxw161283 	uint64_t pa;
3713833Sxw161283 
3723833Sxw161283 	/*
3733833Sxw161283 	 * byte swap, consistant mapping & 4k aligned
3743833Sxw161283 	 */
3753833Sxw161283 	mem = ch_alloc_dma_mem(chp, 1, DMA_4KALN|flg, len, &pa, dh, ah);
3763833Sxw161283 	if (mem == NULL) {
3773833Sxw161283 		return (0);
3783833Sxw161283 	}
3793833Sxw161283 
3803833Sxw161283 	if (dma_addr)
3813833Sxw161283 		*dma_addr = pa;
3823833Sxw161283 
3833833Sxw161283 	bzero(mem, len);
3843833Sxw161283 
3853833Sxw161283 	return ((void *)mem);
3863833Sxw161283 }
3873833Sxw161283 
3883833Sxw161283 /* ARGSUSED */
3893833Sxw161283 void
pe_os_free_contig(ch_t * obj,size_t len,void * addr,uint64_t dma_addr,ulong_t dh,ulong_t ah)3903833Sxw161283 pe_os_free_contig(ch_t *obj, size_t len, void *addr, uint64_t dma_addr,
3913833Sxw161283 			ulong_t dh, ulong_t ah)
3923833Sxw161283 {
3933833Sxw161283 	ch_free_dma_mem(dh, ah);
3943833Sxw161283 }
3953833Sxw161283 
3963833Sxw161283 void
t1_fatal_err(ch_t * adapter)3973833Sxw161283 t1_fatal_err(ch_t *adapter)
3983833Sxw161283 {
3993833Sxw161283 	if (adapter->ch_flags & PEINITDONE) {
4003833Sxw161283 		(void) sge_stop(adapter->sge);
4013833Sxw161283 		t1_interrupts_disable(adapter);
4023833Sxw161283 	}
4033833Sxw161283 	CH_ALERT("%s: encountered fatal error, operation suspended\n",
404*7656SSherry.Moore@Sun.COM 	    adapter_name(adapter));
4053833Sxw161283 }
4063833Sxw161283 
4073833Sxw161283 void
CH_ALERT(const char * fmt,...)4083833Sxw161283 CH_ALERT(const char *fmt, ...)
4093833Sxw161283 {
4103833Sxw161283 	va_list	ap;
4113833Sxw161283 	char	buf[128];
4123833Sxw161283 
4133833Sxw161283 	/* format buf using fmt and arguments contained in ap */
4143833Sxw161283 
4153833Sxw161283 	va_start(ap, fmt);
4163833Sxw161283 	(void) vsprintf(buf, fmt, ap);
4173833Sxw161283 	va_end(ap);
4183833Sxw161283 
4193833Sxw161283 	/* pass formatted string to cmn_err(9F) */
4203833Sxw161283 	cmn_err(CE_WARN, "%s", buf);
4213833Sxw161283 }
4223833Sxw161283 
4233833Sxw161283 void
CH_WARN(const char * fmt,...)4243833Sxw161283 CH_WARN(const char *fmt, ...)
4253833Sxw161283 {
4263833Sxw161283 	va_list	ap;
4273833Sxw161283 	char	buf[128];
4283833Sxw161283 
4293833Sxw161283 	/* format buf using fmt and arguments contained in ap */
4303833Sxw161283 
4313833Sxw161283 	va_start(ap, fmt);
4323833Sxw161283 	(void) vsprintf(buf, fmt, ap);
4333833Sxw161283 	va_end(ap);
4343833Sxw161283 
4353833Sxw161283 	/* pass formatted string to cmn_err(9F) */
4363833Sxw161283 	cmn_err(CE_WARN, "%s", buf);
4373833Sxw161283 }
4383833Sxw161283 
4393833Sxw161283 void
CH_ERR(const char * fmt,...)4403833Sxw161283 CH_ERR(const char *fmt, ...)
4413833Sxw161283 {
4423833Sxw161283 	va_list	ap;
4433833Sxw161283 	char	buf[128];
4443833Sxw161283 
4453833Sxw161283 	/* format buf using fmt and arguments contained in ap */
4463833Sxw161283 
4473833Sxw161283 	va_start(ap, fmt);
4483833Sxw161283 	(void) vsprintf(buf, fmt, ap);
4493833Sxw161283 	va_end(ap);
4503833Sxw161283 
4513833Sxw161283 	/* pass formatted string to cmn_err(9F) */
4523833Sxw161283 	cmn_err(CE_WARN, "%s", buf);
4533833Sxw161283 }
4543833Sxw161283 
4553833Sxw161283 u32
le32_to_cpu(u32 data)4563833Sxw161283 le32_to_cpu(u32 data)
4573833Sxw161283 {
4583833Sxw161283 #if BYTE_ORDER == BIG_ENDIAN
4593833Sxw161283 	uint8_t *in, t;
4603833Sxw161283 	in = (uint8_t *)&data;
4613833Sxw161283 	t = in[0];
4623833Sxw161283 	in[0] = in[3];
4633833Sxw161283 	in[3] = t;
4643833Sxw161283 	t = in[1];
4653833Sxw161283 	in[1] = in[2];
4663833Sxw161283 	in[2] = t;
4673833Sxw161283 #endif
4683833Sxw161283 	return (data);
4693833Sxw161283 }
4703833Sxw161283 
4713833Sxw161283 /*
4723833Sxw161283  * This function initializes a polling routine, Poll_func
4733833Sxw161283  * which will be polled ever N Microsecond, where N is
4743833Sxw161283  * provided in the cyclic start routine.
4753833Sxw161283  */
4763833Sxw161283 /* ARGSUSED */
4773833Sxw161283 void
ch_init_cyclic(void * adapter,p_ch_cyclic_t cyclic,void (* poll_func)(void *),void * arg)4783833Sxw161283 ch_init_cyclic(void *adapter, p_ch_cyclic_t cyclic,
4793833Sxw161283 		void (*poll_func)(void *), void *arg)
4803833Sxw161283 {
4813833Sxw161283 	cyclic->func = poll_func;
4823833Sxw161283 	cyclic->arg = arg;
4833833Sxw161283 	cyclic->timer = 0;
4843833Sxw161283 }
4853833Sxw161283 
4863833Sxw161283 /*
4873833Sxw161283  * Cyclic function which provides a periodic polling
4883833Sxw161283  * capability to Solaris. The poll function provided by
4893833Sxw161283  * the 'ch_init_cyclic' function is called from this
4903833Sxw161283  * here, and this routine launches a new one-shot
4913833Sxw161283  * timer to bring it back in some period later.
4923833Sxw161283  */
4933833Sxw161283 void
ch_cyclic(p_ch_cyclic_t cyclic)4943833Sxw161283 ch_cyclic(p_ch_cyclic_t cyclic)
4953833Sxw161283 {
4963833Sxw161283 	if (cyclic->timer != 0) {
4973833Sxw161283 		cyclic->func(cyclic->arg);
4983833Sxw161283 		cyclic->timer = timeout((void(*)(void  *))ch_cyclic,
499*7656SSherry.Moore@Sun.COM 		    (void *)cyclic, cyclic->period);
5003833Sxw161283 	}
5013833Sxw161283 }
5023833Sxw161283 
5033833Sxw161283 /*
5043833Sxw161283  * The 'ch_start_cyclic' starts the polling.
5053833Sxw161283  */
5063833Sxw161283 void
ch_start_cyclic(p_ch_cyclic_t cyclic,unsigned long period)5073833Sxw161283 ch_start_cyclic(p_ch_cyclic_t cyclic, unsigned long period)
5083833Sxw161283 {
5093833Sxw161283 	cyclic->period = drv_usectohz(period * 1000);
5103833Sxw161283 	if (cyclic->timer == 0) {
5113833Sxw161283 		cyclic->timer = timeout((void(*)(void  *))ch_cyclic,
512*7656SSherry.Moore@Sun.COM 		    (void *)cyclic, cyclic->period);
5133833Sxw161283 	}
5143833Sxw161283 }
5153833Sxw161283 
5163833Sxw161283 /*
5173833Sxw161283  * The 'ch_stop_cyclic' stops the polling.
5183833Sxw161283  */
5193833Sxw161283 void
ch_stop_cyclic(p_ch_cyclic_t cyclic)5203833Sxw161283 ch_stop_cyclic(p_ch_cyclic_t cyclic)
5213833Sxw161283 {
5223833Sxw161283 	timeout_id_t timer;
5233833Sxw161283 	clock_t value;
5243833Sxw161283 
5253833Sxw161283 	do {
5263833Sxw161283 		timer = cyclic->timer;
5273833Sxw161283 		cyclic->timer = 0;
5283833Sxw161283 		value = untimeout(timer);
5293833Sxw161283 		if (value == 0)
530*7656SSherry.Moore@Sun.COM 			drv_usecwait(drv_hztousec(2 * cyclic->period));
5313833Sxw161283 	} while ((timer != 0) && (value == 0));
5323833Sxw161283 }
533