xref: /illumos-gate/usr/src/uts/common/io/chxge/glue.c (revision d39a76e7)
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