xref: /onnv-gate/usr/src/uts/common/io/chxge/ch.c (revision 3833:45d8d0ee8613)
1*3833Sxw161283 /*
2*3833Sxw161283  * CDDL HEADER START
3*3833Sxw161283  *
4*3833Sxw161283  * The contents of this file are subject to the terms of the
5*3833Sxw161283  * Common Development and Distribution License (the "License").
6*3833Sxw161283  * You may not use this file except in compliance with the License.
7*3833Sxw161283  *
8*3833Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3833Sxw161283  * or http://www.opensolaris.org/os/licensing.
10*3833Sxw161283  * See the License for the specific language governing permissions
11*3833Sxw161283  * and limitations under the License.
12*3833Sxw161283  *
13*3833Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
14*3833Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3833Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
16*3833Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
17*3833Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3833Sxw161283  *
19*3833Sxw161283  * CDDL HEADER END
20*3833Sxw161283  */
21*3833Sxw161283 
22*3833Sxw161283 /*
23*3833Sxw161283  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*3833Sxw161283  * Use is subject to license terms.
25*3833Sxw161283  */
26*3833Sxw161283 
27*3833Sxw161283 /*
28*3833Sxw161283  * This file is part of the Chelsio T1 Ethernet driver.
29*3833Sxw161283  *
30*3833Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
31*3833Sxw161283  */
32*3833Sxw161283 
33*3833Sxw161283 /*
34*3833Sxw161283  * Solaris Multithreaded STREAMS DLPI Chelsio PCI Ethernet Driver
35*3833Sxw161283  */
36*3833Sxw161283 
37*3833Sxw161283 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38*3833Sxw161283 
39*3833Sxw161283 /* #define CH_DEBUG 1 */
40*3833Sxw161283 #ifdef CH_DEBUG
41*3833Sxw161283 #define	DEBUG_ENTER(a) debug_enter(a)
42*3833Sxw161283 #define	PRINT(a) printf a
43*3833Sxw161283 #else
44*3833Sxw161283 #define	DEBUG_ENTER(a)
45*3833Sxw161283 #define	PRINT(a)
46*3833Sxw161283 #endif
47*3833Sxw161283 
48*3833Sxw161283 #include <sys/types.h>
49*3833Sxw161283 #include <sys/conf.h>
50*3833Sxw161283 #include <sys/debug.h>
51*3833Sxw161283 #include <sys/stropts.h>
52*3833Sxw161283 #include <sys/stream.h>
53*3833Sxw161283 #include <sys/strlog.h>
54*3833Sxw161283 #include <sys/kmem.h>
55*3833Sxw161283 #include <sys/stat.h>
56*3833Sxw161283 #include <sys/kstat.h>
57*3833Sxw161283 #include <sys/modctl.h>
58*3833Sxw161283 #include <sys/errno.h>
59*3833Sxw161283 #include <sys/cmn_err.h>
60*3833Sxw161283 #include <sys/ddi.h>
61*3833Sxw161283 #include <sys/sunddi.h>
62*3833Sxw161283 #include <sys/dlpi.h>
63*3833Sxw161283 #include <sys/ethernet.h>
64*3833Sxw161283 #include <sys/strsun.h>
65*3833Sxw161283 #include <sys/strsubr.h>
66*3833Sxw161283 #include <inet/common.h>
67*3833Sxw161283 #include <inet/nd.h>
68*3833Sxw161283 #include <inet/ip.h>
69*3833Sxw161283 #include <inet/tcp.h>
70*3833Sxw161283 #include <sys/pattr.h>
71*3833Sxw161283 #include <sys/gld.h>
72*3833Sxw161283 #include "ostypes.h"
73*3833Sxw161283 #include "common.h"
74*3833Sxw161283 #include "oschtoe.h"
75*3833Sxw161283 #include "sge.h"
76*3833Sxw161283 #include "ch.h"			/* Chelsio Driver specific parameters */
77*3833Sxw161283 #include "version.h"
78*3833Sxw161283 
79*3833Sxw161283 /*
80*3833Sxw161283  * Function prototypes.
81*3833Sxw161283  */
82*3833Sxw161283 static int ch_attach(dev_info_t *, ddi_attach_cmd_t);
83*3833Sxw161283 static int ch_detach(dev_info_t *, ddi_detach_cmd_t);
84*3833Sxw161283 static void ch_free_dma_handles(ch_t *chp);
85*3833Sxw161283 static void ch_set_name(ch_t *chp, int unit);
86*3833Sxw161283 static void ch_free_name(ch_t *chp);
87*3833Sxw161283 static void ch_get_prop(ch_t *chp);
88*3833Sxw161283 
89*3833Sxw161283 #if defined(__sparc)
90*3833Sxw161283 static void ch_free_dvma_handles(ch_t *chp);
91*3833Sxw161283 #endif
92*3833Sxw161283 
93*3833Sxw161283 /* GLD interfaces */
94*3833Sxw161283 static int ch_reset(gld_mac_info_t *);
95*3833Sxw161283 static int ch_start(gld_mac_info_t *);
96*3833Sxw161283 static int ch_stop(gld_mac_info_t *);
97*3833Sxw161283 static int ch_set_mac_address(gld_mac_info_t *, uint8_t *);
98*3833Sxw161283 static int ch_set_multicast(gld_mac_info_t *, uint8_t *, int);
99*3833Sxw161283 static int ch_ioctl(gld_mac_info_t *, queue_t *, mblk_t *);
100*3833Sxw161283 static int ch_set_promiscuous(gld_mac_info_t *, int);
101*3833Sxw161283 static int ch_get_stats(gld_mac_info_t *, struct gld_stats *);
102*3833Sxw161283 static int ch_send(gld_mac_info_t *, mblk_t *);
103*3833Sxw161283 static uint_t ch_intr(gld_mac_info_t *);
104*3833Sxw161283 
105*3833Sxw161283 /*
106*3833Sxw161283  * Data access requirements.
107*3833Sxw161283  */
108*3833Sxw161283 static struct ddi_device_acc_attr le_attr = {
109*3833Sxw161283 	DDI_DEVICE_ATTR_V0,
110*3833Sxw161283 	DDI_STRUCTURE_LE_ACC,
111*3833Sxw161283 	DDI_STRICTORDER_ACC
112*3833Sxw161283 };
113*3833Sxw161283 
114*3833Sxw161283 /*
115*3833Sxw161283  * No swap mapping device attributes
116*3833Sxw161283  */
117*3833Sxw161283 static struct ddi_device_acc_attr null_attr = {
118*3833Sxw161283 	DDI_DEVICE_ATTR_V0,
119*3833Sxw161283 	DDI_NEVERSWAP_ACC,
120*3833Sxw161283 	DDI_STRICTORDER_ACC
121*3833Sxw161283 };
122*3833Sxw161283 
123*3833Sxw161283 /*
124*3833Sxw161283  * STREAMS driver identification struture module_info(9s)
125*3833Sxw161283  *
126*3833Sxw161283  * driver limit values
127*3833Sxw161283  */
128*3833Sxw161283 
129*3833Sxw161283 static	struct module_info ch_minfo = {
130*3833Sxw161283 	CHIDNUM,	/* mi_idnum */
131*3833Sxw161283 	CHNAME,		/* mi_idname */
132*3833Sxw161283 	CHMINPSZ,	/* mi_minpsz */
133*3833Sxw161283 	CHMAXPSZ,	/* mi_maxpsz */
134*3833Sxw161283 	CHHIWAT,	/* mi_hiwat */
135*3833Sxw161283 	CHLOWAT		/* mi_lowat */
136*3833Sxw161283 };
137*3833Sxw161283 
138*3833Sxw161283 /*
139*3833Sxw161283  * STREAMS queue processiong procedures qinit(9s)
140*3833Sxw161283  *
141*3833Sxw161283  * read queue procedures
142*3833Sxw161283  */
143*3833Sxw161283 
144*3833Sxw161283 static struct qinit ch_rinit = {
145*3833Sxw161283 	(int (*)()) NULL, 	/* qi_putp */
146*3833Sxw161283 	gld_rsrv,		/* qi_srvp */
147*3833Sxw161283 	gld_open,		/* qi_qopen */
148*3833Sxw161283 	gld_close,		/* qi_qclose */
149*3833Sxw161283 	(int (*)()) NULL, 	/* qi_qadmin */
150*3833Sxw161283 	&ch_minfo,		/* qi_minfo */
151*3833Sxw161283 	NULL			/* qi_mstat */
152*3833Sxw161283 };
153*3833Sxw161283 
154*3833Sxw161283 /*
155*3833Sxw161283  * STREAMS queue processiong procedures qinit(9s)
156*3833Sxw161283  *
157*3833Sxw161283  * write queue procedures
158*3833Sxw161283  */
159*3833Sxw161283 
160*3833Sxw161283 static struct qinit ch_winit = {
161*3833Sxw161283 	gld_wput,		/* qi_putp */
162*3833Sxw161283 	gld_wsrv,		/* qi_srvp */
163*3833Sxw161283 	(int (*)()) NULL, 	/* qi_qopen */
164*3833Sxw161283 	(int (*)()) NULL, 	/* qi_qclose */
165*3833Sxw161283 	(int (*)()) NULL, 	/* qi_qadmin */
166*3833Sxw161283 	&ch_minfo,		/* qi_minfo */
167*3833Sxw161283 	NULL			/* qi_mstat */
168*3833Sxw161283 };
169*3833Sxw161283 
170*3833Sxw161283 /*
171*3833Sxw161283  * STREAMS entity declaration structure - streamtab(9s)
172*3833Sxw161283  */
173*3833Sxw161283 static struct streamtab	chinfo = {
174*3833Sxw161283 	&ch_rinit,	/* read queue information */
175*3833Sxw161283 	&ch_winit,	/* write queue information */
176*3833Sxw161283 	NULL,		/* st_muxrinit */
177*3833Sxw161283 	NULL		/* st_muxwrinit */
178*3833Sxw161283 };
179*3833Sxw161283 
180*3833Sxw161283 /*
181*3833Sxw161283  * Device driver ops vector - cb_ops(9s)
182*3833Sxw161283  *
183*3833Sxw161283  * charater/block entry points structure.
184*3833Sxw161283  * chinfo identifies driver as a STREAMS driver.
185*3833Sxw161283  */
186*3833Sxw161283 
187*3833Sxw161283 static struct cb_ops cb_ch_ops = {
188*3833Sxw161283 	nulldev,	/* cb_open */
189*3833Sxw161283 	nulldev,	/* cb_close */
190*3833Sxw161283 	nodev,		/* cb_strategy */
191*3833Sxw161283 	nodev,		/* cb_print */
192*3833Sxw161283 	nodev,		/* cb_dump */
193*3833Sxw161283 	nodev,		/* cb_read */
194*3833Sxw161283 	nodev,		/* cb_write */
195*3833Sxw161283 	nodev,		/* cb_ioctl */
196*3833Sxw161283 	nodev,		/* cb_devmap */
197*3833Sxw161283 	nodev,		/* cb_mmap */
198*3833Sxw161283 	nodev,		/* cb_segmap */
199*3833Sxw161283 	nochpoll,	/* cb_chpoll */
200*3833Sxw161283 	ddi_prop_op,	/* report driver property information - prop_op(9e) */
201*3833Sxw161283 	&chinfo,	/* cb_stream */
202*3833Sxw161283 #if defined(__sparc)
203*3833Sxw161283 	D_MP | D_64BIT,
204*3833Sxw161283 #else
205*3833Sxw161283 	D_MP,		/* cb_flag (supports multi-threading) */
206*3833Sxw161283 #endif
207*3833Sxw161283 	CB_REV,		/* cb_rev */
208*3833Sxw161283 	nodev,		/* cb_aread */
209*3833Sxw161283 	nodev		/* cb_awrite */
210*3833Sxw161283 };
211*3833Sxw161283 
212*3833Sxw161283 /*
213*3833Sxw161283  * dev_ops(9S) structure
214*3833Sxw161283  *
215*3833Sxw161283  * Device Operations table, for autoconfiguration
216*3833Sxw161283  */
217*3833Sxw161283 
218*3833Sxw161283 static	struct dev_ops ch_ops = {
219*3833Sxw161283 	DEVO_REV,	/* Driver build version */
220*3833Sxw161283 	0,		/* Initial driver reference count */
221*3833Sxw161283 	gld_getinfo,	/* funcp: get driver information - getinfo(9e) */
222*3833Sxw161283 	nulldev,	/* funcp: entry point obsolute - identify(9e) */
223*3833Sxw161283 	nulldev,	/* funp: probe for device - probe(9e) */
224*3833Sxw161283 	ch_attach,	/* funp: attach driver to dev_info - attach(9e) */
225*3833Sxw161283 	ch_detach,	/* funp: detach driver to unload - detach(9e) */
226*3833Sxw161283 	nodev,		/* funp: reset device (not supported) - dev_ops(9s) */
227*3833Sxw161283 	&cb_ch_ops,	/* ptr to cb_ops structure */
228*3833Sxw161283 	NULL,		/* ptr to nexus bus operations structure (leaf) */
229*3833Sxw161283 	NULL		/* funp: change device power level - power(9e) */
230*3833Sxw161283 };
231*3833Sxw161283 
232*3833Sxw161283 /*
233*3833Sxw161283  * modldrv(9s) structure
234*3833Sxw161283  *
235*3833Sxw161283  * Definition for module specific device driver linkage structures (modctl.h)
236*3833Sxw161283  */
237*3833Sxw161283 
238*3833Sxw161283 static struct modldrv modldrv = {
239*3833Sxw161283 	&mod_driverops,		/* driver module */
240*3833Sxw161283 	VERSION,
241*3833Sxw161283 	&ch_ops,		/* driver ops */
242*3833Sxw161283 };
243*3833Sxw161283 
244*3833Sxw161283 /*
245*3833Sxw161283  * modlinkage(9s) structure
246*3833Sxw161283  *
247*3833Sxw161283  * module linkage base structure (modctl.h)
248*3833Sxw161283  */
249*3833Sxw161283 
250*3833Sxw161283 static struct modlinkage modlinkage = {
251*3833Sxw161283 	MODREV_1,		/* revision # of system */
252*3833Sxw161283 	&modldrv,		/* NULL terminated list of linkage strucures */
253*3833Sxw161283 	NULL
254*3833Sxw161283 };
255*3833Sxw161283 
256*3833Sxw161283 /* ===================== start of STREAMS driver code ================== */
257*3833Sxw161283 
258*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
259*3833Sxw161283 /*
260*3833Sxw161283  * global pointer to toe per-driver control structure.
261*3833Sxw161283  */
262*3833Sxw161283 #define	MAX_CARDS	4
263*3833Sxw161283 ch_t *gchp[MAX_CARDS];
264*3833Sxw161283 #endif
265*3833Sxw161283 
266*3833Sxw161283 kmutex_t in_use_l;
267*3833Sxw161283 uint32_t buffers_in_use[SZ_INUSE];
268*3833Sxw161283 uint32_t in_use_index;
269*3833Sxw161283 
270*3833Sxw161283 /*
271*3833Sxw161283  * Ethernet broadcast address definition.
272*3833Sxw161283  */
273*3833Sxw161283 static struct ether_addr etherbroadcastaddr = {
274*3833Sxw161283 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
275*3833Sxw161283 };
276*3833Sxw161283 
277*3833Sxw161283 /*
278*3833Sxw161283  * Module initialization functions.
279*3833Sxw161283  *
280*3833Sxw161283  *      Routine         Called by
281*3833Sxw161283  *      _init(9E)       modload(9F)
282*3833Sxw161283  *      _info(9E)       modinfo(9F)
283*3833Sxw161283  *      _fini(9E)       modunload(9F)
284*3833Sxw161283  */
285*3833Sxw161283 
286*3833Sxw161283 /*
287*3833Sxw161283  * _init(9E):
288*3833Sxw161283  *
289*3833Sxw161283  * Initial, one-time, resource allocation and data initialization.
290*3833Sxw161283  */
291*3833Sxw161283 
292*3833Sxw161283 int
293*3833Sxw161283 _init(void)
294*3833Sxw161283 {
295*3833Sxw161283 	int status;
296*3833Sxw161283 
297*3833Sxw161283 	status = mod_install(&modlinkage);
298*3833Sxw161283 
299*3833Sxw161283 	mutex_init(&in_use_l, NULL, MUTEX_DRIVER, NULL);
300*3833Sxw161283 
301*3833Sxw161283 	return (status);
302*3833Sxw161283 }
303*3833Sxw161283 
304*3833Sxw161283 /*
305*3833Sxw161283  * _fini(9E): It is here that any device information that was allocated
306*3833Sxw161283  * during the _init(9E) routine should be released and the module removed
307*3833Sxw161283  * from the system.  In the case of per-instance information, that information
308*3833Sxw161283  * should be released in the _detach(9E) routine.
309*3833Sxw161283  */
310*3833Sxw161283 
311*3833Sxw161283 int
312*3833Sxw161283 _fini(void)
313*3833Sxw161283 {
314*3833Sxw161283 	int status;
315*3833Sxw161283 	int i;
316*3833Sxw161283 	uint32_t t = 0;
317*3833Sxw161283 
318*3833Sxw161283 	for (i = 0; i < SZ_INUSE; i++)
319*3833Sxw161283 		t += buffers_in_use[i];
320*3833Sxw161283 
321*3833Sxw161283 	if (t != NULL)
322*3833Sxw161283 		return (DDI_FAILURE);
323*3833Sxw161283 
324*3833Sxw161283 	status = mod_remove(&modlinkage);
325*3833Sxw161283 
326*3833Sxw161283 	if (status == DDI_SUCCESS)
327*3833Sxw161283 		mutex_destroy(&in_use_l);
328*3833Sxw161283 
329*3833Sxw161283 	return (status);
330*3833Sxw161283 }
331*3833Sxw161283 
332*3833Sxw161283 int
333*3833Sxw161283 _info(struct modinfo *modinfop)
334*3833Sxw161283 {
335*3833Sxw161283 	int status;
336*3833Sxw161283 
337*3833Sxw161283 
338*3833Sxw161283 	status = mod_info(&modlinkage, modinfop);
339*3833Sxw161283 
340*3833Sxw161283 	return (status);
341*3833Sxw161283 }
342*3833Sxw161283 
343*3833Sxw161283 /*
344*3833Sxw161283  * Attach(9E) - This is called on the open to the device.  It creates
345*3833Sxw161283  * an instance of the driver.  In this routine we create the minor
346*3833Sxw161283  * device node.  The routine also initializes all per-unit
347*3833Sxw161283  * mutex's and conditional variables.
348*3833Sxw161283  *
349*3833Sxw161283  * If we were resuming a suspended instance of a device due to power
350*3833Sxw161283  * management, then that would be handled here as well.  For more on
351*3833Sxw161283  * that subject see the man page for pm(9E)
352*3833Sxw161283  *
353*3833Sxw161283  * Interface exists: make available by filling in network interface
354*3833Sxw161283  * record.  System will initialize the interface when it is ready
355*3833Sxw161283  * to accept packets.
356*3833Sxw161283  */
357*3833Sxw161283 int chdebug = 0;
358*3833Sxw161283 int ch_abort_debug = 0;
359*3833Sxw161283 
360*3833Sxw161283 static int
361*3833Sxw161283 ch_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
362*3833Sxw161283 {
363*3833Sxw161283 	ch_t *chp;
364*3833Sxw161283 	int rv;
365*3833Sxw161283 	int unit;
366*3833Sxw161283 #ifdef CH_DEBUG
367*3833Sxw161283 	int Version;
368*3833Sxw161283 	int VendorID;
369*3833Sxw161283 	int DeviceID;
370*3833Sxw161283 	int SubDeviceID;
371*3833Sxw161283 	int Command;
372*3833Sxw161283 #endif
373*3833Sxw161283 	gld_mac_info_t *macinfo;		/* GLD stuff follows */
374*3833Sxw161283 	char *driver;
375*3833Sxw161283 
376*3833Sxw161283 	if (ch_abort_debug)
377*3833Sxw161283 		debug_enter("ch_attach");
378*3833Sxw161283 
379*3833Sxw161283 	if (chdebug)
380*3833Sxw161283 		return (DDI_FAILURE);
381*3833Sxw161283 
382*3833Sxw161283 
383*3833Sxw161283 	if (cmd == DDI_ATTACH) {
384*3833Sxw161283 
385*3833Sxw161283 		unit = ddi_get_instance(dip);
386*3833Sxw161283 
387*3833Sxw161283 		driver = (char *)ddi_driver_name(dip);
388*3833Sxw161283 
389*3833Sxw161283 		PRINT(("driver %s unit: %d\n", driver, unit));
390*3833Sxw161283 
391*3833Sxw161283 		macinfo = gld_mac_alloc(dip);
392*3833Sxw161283 		if (macinfo == NULL) {
393*3833Sxw161283 			PRINT(("macinfo allocation failed\n"));
394*3833Sxw161283 			DEBUG_ENTER("ch_attach");
395*3833Sxw161283 			return (DDI_FAILURE);
396*3833Sxw161283 		}
397*3833Sxw161283 
398*3833Sxw161283 		chp = (ch_t *)kmem_zalloc(sizeof (ch_t), KM_SLEEP);
399*3833Sxw161283 
400*3833Sxw161283 		if (chp == NULL) {
401*3833Sxw161283 			PRINT(("zalloc of chp failed\n"));
402*3833Sxw161283 			DEBUG_ENTER("ch_attach");
403*3833Sxw161283 
404*3833Sxw161283 			gld_mac_free(macinfo);
405*3833Sxw161283 
406*3833Sxw161283 			return (DDI_FAILURE);
407*3833Sxw161283 		}
408*3833Sxw161283 
409*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
410*3833Sxw161283 		/* Solaris TOE support */
411*3833Sxw161283 		gchp[unit] = chp;
412*3833Sxw161283 #endif
413*3833Sxw161283 
414*3833Sxw161283 		PRINT(("attach macinfo: %p chp: %p\n", macinfo, chp));
415*3833Sxw161283 
416*3833Sxw161283 		chp->ch_dip  = dip;
417*3833Sxw161283 		chp->ch_macp = macinfo;
418*3833Sxw161283 		chp->ch_unit = unit;
419*3833Sxw161283 		ch_set_name(chp, unit);
420*3833Sxw161283 
421*3833Sxw161283 		/*
422*3833Sxw161283 		 * map in PCI register spaces
423*3833Sxw161283 		 *
424*3833Sxw161283 		 * PCI register set 0 - PCI configuration space
425*3833Sxw161283 		 * PCI register set 1 - T101 card register space #1
426*3833Sxw161283 		 */
427*3833Sxw161283 
428*3833Sxw161283 		/* map in T101 PCI configuration space */
429*3833Sxw161283 		rv = pci_config_setup(
430*3833Sxw161283 			dip,		/* ptr to dev's dev_info struct */
431*3833Sxw161283 			&chp->ch_hpci);	/* ptr to data access handle */
432*3833Sxw161283 
433*3833Sxw161283 		if (rv != DDI_SUCCESS) {
434*3833Sxw161283 			PRINT(("PCI config setup failed\n"));
435*3833Sxw161283 			DEBUG_ENTER("ch_attach");
436*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
437*3833Sxw161283 			gchp[unit] = NULL;
438*3833Sxw161283 #endif
439*3833Sxw161283 			cmn_err(CE_WARN, "%s: ddi_config_setup PCI error %d\n",
440*3833Sxw161283 				chp->ch_name, rv);
441*3833Sxw161283 
442*3833Sxw161283 			ch_free_name(chp);
443*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
444*3833Sxw161283 			gld_mac_free(macinfo);
445*3833Sxw161283 
446*3833Sxw161283 			return (DDI_FAILURE);
447*3833Sxw161283 		}
448*3833Sxw161283 
449*3833Sxw161283 		ch_get_prop(chp);
450*3833Sxw161283 
451*3833Sxw161283 		macinfo->gldm_devinfo = dip;
452*3833Sxw161283 		macinfo->gldm_private = (caddr_t)chp;
453*3833Sxw161283 		macinfo->gldm_reset = ch_reset;
454*3833Sxw161283 		macinfo->gldm_start = ch_start;
455*3833Sxw161283 		macinfo->gldm_stop = ch_stop;
456*3833Sxw161283 		macinfo->gldm_set_mac_addr = ch_set_mac_address;
457*3833Sxw161283 		macinfo->gldm_send = ch_send;
458*3833Sxw161283 		macinfo->gldm_set_promiscuous = ch_set_promiscuous;
459*3833Sxw161283 		macinfo->gldm_get_stats = ch_get_stats;
460*3833Sxw161283 		macinfo->gldm_ioctl = ch_ioctl;
461*3833Sxw161283 		macinfo->gldm_set_multicast = ch_set_multicast;
462*3833Sxw161283 		macinfo->gldm_intr = ch_intr;
463*3833Sxw161283 		macinfo->gldm_mctl = NULL;
464*3833Sxw161283 
465*3833Sxw161283 		macinfo->gldm_ident = driver;
466*3833Sxw161283 		macinfo->gldm_type = DL_ETHER;
467*3833Sxw161283 		macinfo->gldm_minpkt = 0;
468*3833Sxw161283 		macinfo->gldm_maxpkt = chp->ch_mtu;
469*3833Sxw161283 		macinfo->gldm_addrlen = ETHERADDRL;
470*3833Sxw161283 		macinfo->gldm_saplen = -2;
471*3833Sxw161283 		macinfo->gldm_ppa = unit;
472*3833Sxw161283 		macinfo->gldm_broadcast_addr =
473*3833Sxw161283 				etherbroadcastaddr.ether_addr_octet;
474*3833Sxw161283 
475*3833Sxw161283 
476*3833Sxw161283 		/*
477*3833Sxw161283 		 * do a power reset of card
478*3833Sxw161283 		 *
479*3833Sxw161283 		 * 1. set PwrState to D3hot (3)
480*3833Sxw161283 		 * 2. clear PwrState flags
481*3833Sxw161283 		 */
482*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 3);
483*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 0);
484*3833Sxw161283 
485*3833Sxw161283 		/* delay .5 sec */
486*3833Sxw161283 		DELAY(500000);
487*3833Sxw161283 
488*3833Sxw161283 #ifdef CH_DEBUG
489*3833Sxw161283 		VendorID    = pci_config_get16(chp->ch_hpci, 0);
490*3833Sxw161283 		DeviceID    = pci_config_get16(chp->ch_hpci, 2);
491*3833Sxw161283 		SubDeviceID = pci_config_get16(chp->ch_hpci, 0x2e);
492*3833Sxw161283 		Command = pci_config_get16(chp->ch_hpci, 4);
493*3833Sxw161283 
494*3833Sxw161283 		PRINT(("IDs: %x,%x,%x\n", VendorID, DeviceID, SubDeviceID));
495*3833Sxw161283 		PRINT(("Command: %x\n", Command));
496*3833Sxw161283 #endif
497*3833Sxw161283 		/* map in T101 register space (BAR0) */
498*3833Sxw161283 		rv = ddi_regs_map_setup(
499*3833Sxw161283 			dip,		/* ptr to dev's dev_info struct */
500*3833Sxw161283 			BAR0,		/* register address space */
501*3833Sxw161283 			&chp->ch_bar0,	/* address of offset */
502*3833Sxw161283 			0,		/* offset into register address space */
503*3833Sxw161283 			0,		/* length mapped (everything) */
504*3833Sxw161283 			&le_attr,	/* ptr to device attr structure */
505*3833Sxw161283 			&chp->ch_hbar0);	/* ptr to data access handle */
506*3833Sxw161283 
507*3833Sxw161283 		if (rv != DDI_SUCCESS) {
508*3833Sxw161283 			PRINT(("map registers failed\n"));
509*3833Sxw161283 			DEBUG_ENTER("ch_attach");
510*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
511*3833Sxw161283 			gchp[unit] = NULL;
512*3833Sxw161283 #endif
513*3833Sxw161283 			cmn_err(CE_WARN,
514*3833Sxw161283 				"%s: ddi_regs_map_setup BAR0 error %d\n",
515*3833Sxw161283 				chp->ch_name, rv);
516*3833Sxw161283 
517*3833Sxw161283 			pci_config_teardown(&chp->ch_hpci);
518*3833Sxw161283 			ch_free_name(chp);
519*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
520*3833Sxw161283 			gld_mac_free(macinfo);
521*3833Sxw161283 
522*3833Sxw161283 			return (DDI_FAILURE);
523*3833Sxw161283 		}
524*3833Sxw161283 
525*3833Sxw161283 #ifdef CH_DEBUG
526*3833Sxw161283 		Version  = ddi_get32(chp->ch_hbar0,
527*3833Sxw161283 			(uint32_t *)(chp->ch_bar0+0x6c));
528*3833Sxw161283 #endif
529*3833Sxw161283 
530*3833Sxw161283 		(void) ddi_dev_regsize(dip, 1, &chp->ch_bar0sz);
531*3833Sxw161283 
532*3833Sxw161283 		PRINT(("PCI BAR0 space addr: %p\n", chp->ch_bar0));
533*3833Sxw161283 		PRINT(("PCI BAR0 space size: %x\n", chp->ch_bar0sz));
534*3833Sxw161283 		PRINT(("PE Version: %x\n", Version));
535*3833Sxw161283 
536*3833Sxw161283 		/*
537*3833Sxw161283 		 * Add interrupt to system.
538*3833Sxw161283 		 */
539*3833Sxw161283 		rv = ddi_get_iblock_cookie(
540*3833Sxw161283 			dip,		   /* ptr to dev's dev_info struct */
541*3833Sxw161283 			0,		   /* interrupt # (0) */
542*3833Sxw161283 			&chp->ch_icookp); /* ptr to interrupt block cookie */
543*3833Sxw161283 
544*3833Sxw161283 		if (rv != DDI_SUCCESS) {
545*3833Sxw161283 			PRINT(("iblock cookie failed\n"));
546*3833Sxw161283 			DEBUG_ENTER("ch_attach");
547*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
548*3833Sxw161283 			gchp[unit] = NULL;
549*3833Sxw161283 #endif
550*3833Sxw161283 			cmn_err(CE_WARN,
551*3833Sxw161283 				"%s: ddi_get_iblock_cookie error %d\n",
552*3833Sxw161283 				chp->ch_name, rv);
553*3833Sxw161283 
554*3833Sxw161283 			ddi_regs_map_free(&chp->ch_hbar0);
555*3833Sxw161283 			pci_config_teardown(&chp->ch_hpci);
556*3833Sxw161283 			ch_free_name(chp);
557*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
558*3833Sxw161283 			gld_mac_free(macinfo);
559*3833Sxw161283 
560*3833Sxw161283 			return (DDI_FAILURE);
561*3833Sxw161283 		}
562*3833Sxw161283 
563*3833Sxw161283 		/*
564*3833Sxw161283 		 * add interrupt handler before card setup.
565*3833Sxw161283 		 */
566*3833Sxw161283 		rv = ddi_add_intr(
567*3833Sxw161283 			dip,		/* ptr to dev's dev_info struct */
568*3833Sxw161283 			0,		/* interrupt # (0) */
569*3833Sxw161283 			0,		/* iblock cookie ptr (NULL) */
570*3833Sxw161283 			0,		/* idevice cookie ptr (NULL) */
571*3833Sxw161283 			gld_intr,	/* function ptr to interrupt handler */
572*3833Sxw161283 			(caddr_t)macinfo);	/* handler argument */
573*3833Sxw161283 
574*3833Sxw161283 		if (rv != DDI_SUCCESS) {
575*3833Sxw161283 			PRINT(("add_intr failed\n"));
576*3833Sxw161283 			DEBUG_ENTER("ch_attach");
577*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
578*3833Sxw161283 			gchp[unit] = NULL;
579*3833Sxw161283 #endif
580*3833Sxw161283 			cmn_err(CE_WARN, "%s: ddi_add_intr error %d\n",
581*3833Sxw161283 				chp->ch_name, rv);
582*3833Sxw161283 
583*3833Sxw161283 			ddi_regs_map_free(&chp->ch_hbar0);
584*3833Sxw161283 			pci_config_teardown(&chp->ch_hpci);
585*3833Sxw161283 			ch_free_name(chp);
586*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
587*3833Sxw161283 			gld_mac_free(macinfo);
588*3833Sxw161283 
589*3833Sxw161283 			return (DDI_FAILURE);
590*3833Sxw161283 		}
591*3833Sxw161283 
592*3833Sxw161283 		/* initalize all the remaining per-card locks */
593*3833Sxw161283 		mutex_init(&chp->ch_lock, NULL, MUTEX_DRIVER,
594*3833Sxw161283 					(void *)chp->ch_icookp);
595*3833Sxw161283 		mutex_init(&chp->ch_intr, NULL, MUTEX_DRIVER,
596*3833Sxw161283 					(void *)chp->ch_icookp);
597*3833Sxw161283 		mutex_init(&chp->ch_mc_lck, NULL, MUTEX_DRIVER, NULL);
598*3833Sxw161283 		mutex_init(&chp->ch_dh_lck, NULL, MUTEX_DRIVER, NULL);
599*3833Sxw161283 		mutex_init(&chp->mac_lock, NULL, MUTEX_DRIVER, NULL);
600*3833Sxw161283 
601*3833Sxw161283 		/* ------- initialize Chelsio card ------- */
602*3833Sxw161283 
603*3833Sxw161283 		if (pe_attach(chp)) {
604*3833Sxw161283 			PRINT(("card initialization failed\n"));
605*3833Sxw161283 			DEBUG_ENTER("ch_attach");
606*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
607*3833Sxw161283 			gchp[unit] = NULL;
608*3833Sxw161283 #endif
609*3833Sxw161283 			cmn_err(CE_WARN, "%s: pe_attach failed\n",
610*3833Sxw161283 				chp->ch_name);
611*3833Sxw161283 
612*3833Sxw161283 			mutex_destroy(&chp->ch_lock);
613*3833Sxw161283 			mutex_destroy(&chp->ch_intr);
614*3833Sxw161283 			mutex_destroy(&chp->ch_mc_lck);
615*3833Sxw161283 			mutex_destroy(&chp->ch_dh_lck);
616*3833Sxw161283 			mutex_destroy(&chp->mac_lock);
617*3833Sxw161283 			ddi_remove_intr(dip, 0, chp->ch_icookp);
618*3833Sxw161283 			ddi_regs_map_free(&chp->ch_hbar0);
619*3833Sxw161283 			pci_config_teardown(&chp->ch_hpci);
620*3833Sxw161283 			ch_free_name(chp);
621*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
622*3833Sxw161283 			gld_mac_free(macinfo);
623*3833Sxw161283 
624*3833Sxw161283 			return (DDI_FAILURE);
625*3833Sxw161283 		}
626*3833Sxw161283 
627*3833Sxw161283 		/* ------- done with Chelsio card ------- */
628*3833Sxw161283 
629*3833Sxw161283 		/* now can  set mac address */
630*3833Sxw161283 		macinfo->gldm_vendor_addr = pe_get_mac(chp);
631*3833Sxw161283 
632*3833Sxw161283 		macinfo->gldm_cookie = chp->ch_icookp;
633*3833Sxw161283 
634*3833Sxw161283 		/*
635*3833Sxw161283 		 * We only active checksum offload for T2 architectures.
636*3833Sxw161283 		 */
637*3833Sxw161283 		if (is_T2(chp)) {
638*3833Sxw161283 			if (chp->ch_config.cksum_enabled)
639*3833Sxw161283 				macinfo->gldm_capabilities |=
640*3833Sxw161283 				    GLD_CAP_CKSUM_FULL_V4;
641*3833Sxw161283 		} else
642*3833Sxw161283 			chp->ch_config.cksum_enabled = 0;
643*3833Sxw161283 
644*3833Sxw161283 		rv = gld_register(
645*3833Sxw161283 			dip,		/* ptr to dev's dev_info struct */
646*3833Sxw161283 			(char *)ddi_driver_name(dip),	/* driver name */
647*3833Sxw161283 			macinfo);	/* ptr to gld macinfo buffer */
648*3833Sxw161283 
649*3833Sxw161283 		/*
650*3833Sxw161283 		 * The Jumbo frames capability is not yet available
651*3833Sxw161283 		 * in Solaris 10 so registration will fail. MTU > 1500 is
652*3833Sxw161283 		 * supported in Update 1.
653*3833Sxw161283 		 */
654*3833Sxw161283 		if (rv != DDI_SUCCESS) {
655*3833Sxw161283 			cmn_err(CE_NOTE, "MTU > 1500 not supported by GLD.\n");
656*3833Sxw161283 			cmn_err(CE_NOTE, "Setting MTU to 1500. \n");
657*3833Sxw161283 			macinfo->gldm_maxpkt = chp->ch_mtu = 1500;
658*3833Sxw161283 			rv = gld_register(
659*3833Sxw161283 				dip,	/* ptr to dev's dev_info struct */
660*3833Sxw161283 				(char *)ddi_driver_name(dip), /* driver name */
661*3833Sxw161283 				macinfo); /* ptr to gld macinfo buffer */
662*3833Sxw161283 		}
663*3833Sxw161283 
664*3833Sxw161283 
665*3833Sxw161283 		if (rv != DDI_SUCCESS) {
666*3833Sxw161283 			PRINT(("gld_register failed\n"));
667*3833Sxw161283 			DEBUG_ENTER("ch_attach");
668*3833Sxw161283 
669*3833Sxw161283 			cmn_err(CE_WARN, "%s: gld_register error %d\n",
670*3833Sxw161283 				chp->ch_name, rv);
671*3833Sxw161283 
672*3833Sxw161283 			pe_detach(chp);
673*3833Sxw161283 
674*3833Sxw161283 			mutex_destroy(&chp->ch_lock);
675*3833Sxw161283 			mutex_destroy(&chp->ch_intr);
676*3833Sxw161283 			mutex_destroy(&chp->ch_mc_lck);
677*3833Sxw161283 			mutex_destroy(&chp->ch_dh_lck);
678*3833Sxw161283 			mutex_destroy(&chp->mac_lock);
679*3833Sxw161283 			ddi_remove_intr(dip, 0, chp->ch_icookp);
680*3833Sxw161283 			ddi_regs_map_free(&chp->ch_hbar0);
681*3833Sxw161283 			pci_config_teardown(&chp->ch_hpci);
682*3833Sxw161283 			ch_free_name(chp);
683*3833Sxw161283 			kmem_free(chp, sizeof (ch_t));
684*3833Sxw161283 			gld_mac_free(macinfo);
685*3833Sxw161283 
686*3833Sxw161283 			return (DDI_FAILURE);
687*3833Sxw161283 		}
688*3833Sxw161283 
689*3833Sxw161283 		/*
690*3833Sxw161283 		 * print a banner at boot time (verbose mode), announcing
691*3833Sxw161283 		 * the device pointed to by dip
692*3833Sxw161283 		 */
693*3833Sxw161283 		ddi_report_dev(dip);
694*3833Sxw161283 
695*3833Sxw161283 		if (ch_abort_debug)
696*3833Sxw161283 			debug_enter("ch_attach");
697*3833Sxw161283 
698*3833Sxw161283 		return (DDI_SUCCESS);
699*3833Sxw161283 
700*3833Sxw161283 	} else if (cmd == DDI_RESUME) {
701*3833Sxw161283 		PRINT(("attach resume\n"));
702*3833Sxw161283 		DEBUG_ENTER("ch_attach");
703*3833Sxw161283 		if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
704*3833Sxw161283 			return (DDI_FAILURE);
705*3833Sxw161283 
706*3833Sxw161283 		mutex_enter(&chp->ch_lock);
707*3833Sxw161283 		chp->ch_flags &= ~PESUSPENDED;
708*3833Sxw161283 		mutex_exit(&chp->ch_lock);
709*3833Sxw161283 		return (DDI_SUCCESS);
710*3833Sxw161283 	} else {
711*3833Sxw161283 		PRINT(("attach: bad command\n"));
712*3833Sxw161283 		DEBUG_ENTER("ch_attach");
713*3833Sxw161283 
714*3833Sxw161283 		return (DDI_FAILURE);
715*3833Sxw161283 	}
716*3833Sxw161283 }
717*3833Sxw161283 
718*3833Sxw161283 static int
719*3833Sxw161283 ch_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
720*3833Sxw161283 {
721*3833Sxw161283 	gld_mac_info_t *macinfo;
722*3833Sxw161283 	ch_t *chp;
723*3833Sxw161283 
724*3833Sxw161283 	if (cmd == DDI_DETACH) {
725*3833Sxw161283 		macinfo = (gld_mac_info_t *)ddi_get_driver_private(dip);
726*3833Sxw161283 		chp = (ch_t *)macinfo->gldm_private;
727*3833Sxw161283 
728*3833Sxw161283 		/*
729*3833Sxw161283 		 * fail detach if there are outstanding mblks still
730*3833Sxw161283 		 * in use somewhere.
731*3833Sxw161283 		 */
732*3833Sxw161283 		DEBUG_ENTER("ch_detach");
733*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
734*3833Sxw161283 		mutex_enter(&chp->ch_lock);
735*3833Sxw161283 		if (chp->ch_refcnt > 0) {
736*3833Sxw161283 			mutex_exit(&chp->ch_lock);
737*3833Sxw161283 			return (DDI_FAILURE);
738*3833Sxw161283 		}
739*3833Sxw161283 		mutex_exit(&chp->ch_lock);
740*3833Sxw161283 		gchp[chp->ch_unit] = NULL;
741*3833Sxw161283 #endif
742*3833Sxw161283 		/*
743*3833Sxw161283 		 * set driver state for this card to IDLE. We're
744*3833Sxw161283 		 * shutting down.
745*3833Sxw161283 		 */
746*3833Sxw161283 		mutex_enter(&chp->ch_lock);
747*3833Sxw161283 		chp->ch_state = PEIDLE;
748*3833Sxw161283 		mutex_exit(&chp->ch_lock);
749*3833Sxw161283 
750*3833Sxw161283 		/*
751*3833Sxw161283 		 * do a power reset of card
752*3833Sxw161283 		 *
753*3833Sxw161283 		 * 1. set PwrState to D3hot (3)
754*3833Sxw161283 		 * 2. clear PwrState flags
755*3833Sxw161283 		 */
756*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 3);
757*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 0);
758*3833Sxw161283 
759*3833Sxw161283 		/* delay .5 sec */
760*3833Sxw161283 		DELAY(500000);
761*3833Sxw161283 
762*3833Sxw161283 		/* free register resources */
763*3833Sxw161283 		(void) gld_unregister(macinfo);
764*3833Sxw161283 
765*3833Sxw161283 		/* make sure no interrupts while shutting down card */
766*3833Sxw161283 		ddi_remove_intr(dip, 0, chp->ch_icookp);
767*3833Sxw161283 
768*3833Sxw161283 		/*
769*3833Sxw161283 		 * reset device and recover resources
770*3833Sxw161283 		 */
771*3833Sxw161283 		pe_detach(chp);
772*3833Sxw161283 
773*3833Sxw161283 		ddi_regs_map_free(&chp->ch_hbar0);
774*3833Sxw161283 		pci_config_teardown(&chp->ch_hpci);
775*3833Sxw161283 		mutex_destroy(&chp->ch_lock);
776*3833Sxw161283 		mutex_destroy(&chp->ch_intr);
777*3833Sxw161283 		mutex_destroy(&chp->ch_mc_lck);
778*3833Sxw161283 		mutex_destroy(&chp->ch_dh_lck);
779*3833Sxw161283 		mutex_destroy(&chp->mac_lock);
780*3833Sxw161283 		ch_free_dma_handles(chp);
781*3833Sxw161283 #if defined(__sparc)
782*3833Sxw161283 		ch_free_dvma_handles(chp);
783*3833Sxw161283 #endif
784*3833Sxw161283 		ch_free_name(chp);
785*3833Sxw161283 		kmem_free(chp, sizeof (ch_t));
786*3833Sxw161283 		gld_mac_free(macinfo);
787*3833Sxw161283 
788*3833Sxw161283 		DEBUG_ENTER("ch_detach end");
789*3833Sxw161283 
790*3833Sxw161283 		return (DDI_SUCCESS);
791*3833Sxw161283 
792*3833Sxw161283 	} else if ((cmd == DDI_SUSPEND) || (cmd == DDI_PM_SUSPEND)) {
793*3833Sxw161283 		DEBUG_ENTER("suspend");
794*3833Sxw161283 		if ((chp = (ch_t *)ddi_get_driver_private(dip)) == NULL)
795*3833Sxw161283 			return (DDI_FAILURE);
796*3833Sxw161283 		mutex_enter(&chp->ch_lock);
797*3833Sxw161283 		chp->ch_flags |= PESUSPENDED;
798*3833Sxw161283 		mutex_exit(&chp->ch_lock);
799*3833Sxw161283 #ifdef TODO
800*3833Sxw161283 		/* Un-initialize (STOP) T101 */
801*3833Sxw161283 #endif
802*3833Sxw161283 		return (DDI_SUCCESS);
803*3833Sxw161283 	} else
804*3833Sxw161283 		return (DDI_FAILURE);
805*3833Sxw161283 }
806*3833Sxw161283 
807*3833Sxw161283 /*
808*3833Sxw161283  * ch_alloc_dma_mem
809*3833Sxw161283  *
810*3833Sxw161283  * allocates DMA handle
811*3833Sxw161283  * allocates kernel memory
812*3833Sxw161283  * allocates DMA access handle
813*3833Sxw161283  *
814*3833Sxw161283  * chp - per-board descriptor
815*3833Sxw161283  * type - byteswap mapping?
816*3833Sxw161283  * flags - type of mapping
817*3833Sxw161283  * size - # bytes mapped
818*3833Sxw161283  * paddr - physical address
819*3833Sxw161283  * dh - ddi dma handle
820*3833Sxw161283  * ah - ddi access handle
821*3833Sxw161283  */
822*3833Sxw161283 
823*3833Sxw161283 void *
824*3833Sxw161283 ch_alloc_dma_mem(ch_t *chp, int type, int flags, int size, uint64_t *paddr,
825*3833Sxw161283 	ulong_t *dh, ulong_t *ah)
826*3833Sxw161283 {
827*3833Sxw161283 	ddi_dma_attr_t ch_dma_attr;
828*3833Sxw161283 	ddi_dma_cookie_t cookie;
829*3833Sxw161283 	ddi_dma_handle_t ch_dh;
830*3833Sxw161283 	ddi_acc_handle_t ch_ah;
831*3833Sxw161283 	ddi_device_acc_attr_t *dev_attrp;
832*3833Sxw161283 	caddr_t ch_vaddr;
833*3833Sxw161283 	size_t rlen;
834*3833Sxw161283 	uint_t count;
835*3833Sxw161283 	uint_t mapping;
836*3833Sxw161283 	uint_t align;
837*3833Sxw161283 	uint_t rv;
838*3833Sxw161283 	uint_t direction;
839*3833Sxw161283 
840*3833Sxw161283 	mapping = (flags&DMA_STREAM)?DDI_DMA_STREAMING:DDI_DMA_CONSISTENT;
841*3833Sxw161283 	if (flags & DMA_4KALN)
842*3833Sxw161283 		align = 0x4000;
843*3833Sxw161283 	else if (flags & DMA_SMALN)
844*3833Sxw161283 		align = chp->ch_sm_buf_aln;
845*3833Sxw161283 	else if (flags & DMA_BGALN)
846*3833Sxw161283 		align = chp->ch_bg_buf_aln;
847*3833Sxw161283 	else {
848*3833Sxw161283 		cmn_err(CE_WARN, "ch_alloc_dma_mem(%s): bad alignment flag\n",
849*3833Sxw161283 		    chp->ch_name);
850*3833Sxw161283 		return (0);
851*3833Sxw161283 	}
852*3833Sxw161283 	direction = (flags&DMA_OUT)?DDI_DMA_WRITE:DDI_DMA_READ;
853*3833Sxw161283 
854*3833Sxw161283 	/*
855*3833Sxw161283 	 * dynamically create a dma attribute structure
856*3833Sxw161283 	 */
857*3833Sxw161283 	ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
858*3833Sxw161283 	ch_dma_attr.dma_attr_addr_lo = 0;
859*3833Sxw161283 	ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
860*3833Sxw161283 	ch_dma_attr.dma_attr_count_max = 0x00ffffff;
861*3833Sxw161283 	ch_dma_attr.dma_attr_align = align;
862*3833Sxw161283 	ch_dma_attr.dma_attr_burstsizes = 0xfff;
863*3833Sxw161283 	ch_dma_attr.dma_attr_minxfer = 1;
864*3833Sxw161283 	ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
865*3833Sxw161283 	ch_dma_attr.dma_attr_seg = 0xffffffff;
866*3833Sxw161283 	ch_dma_attr.dma_attr_sgllen = 1;
867*3833Sxw161283 	ch_dma_attr.dma_attr_granular = 1;
868*3833Sxw161283 	ch_dma_attr.dma_attr_flags = 0;
869*3833Sxw161283 
870*3833Sxw161283 	rv = ddi_dma_alloc_handle(
871*3833Sxw161283 	    chp->ch_dip,		/* device dev_info structure */
872*3833Sxw161283 	    &ch_dma_attr,		/* DMA attributes */
873*3833Sxw161283 	    DDI_DMA_SLEEP,		/* Wait if no memory */
874*3833Sxw161283 	    NULL,			/* no argument to callback */
875*3833Sxw161283 	    &ch_dh);			/* DMA handle */
876*3833Sxw161283 	if (rv != DDI_SUCCESS) {
877*3833Sxw161283 
878*3833Sxw161283 		cmn_err(CE_WARN,
879*3833Sxw161283 			"%s: ch_alloc_dma_mem: ddi_dma_alloc_handle error %d\n",
880*3833Sxw161283 			chp->ch_name, rv);
881*3833Sxw161283 
882*3833Sxw161283 		return (0);
883*3833Sxw161283 	}
884*3833Sxw161283 
885*3833Sxw161283 	/* set byte order for data xfer */
886*3833Sxw161283 	if (type)
887*3833Sxw161283 		dev_attrp = &null_attr;
888*3833Sxw161283 	else
889*3833Sxw161283 		dev_attrp = &le_attr;
890*3833Sxw161283 
891*3833Sxw161283 	rv = ddi_dma_mem_alloc(
892*3833Sxw161283 	    ch_dh,		/* dma handle */
893*3833Sxw161283 	    size,		/* size desired allocate */
894*3833Sxw161283 	    dev_attrp,		/* access attributes */
895*3833Sxw161283 	    mapping,
896*3833Sxw161283 	    DDI_DMA_SLEEP,	/* wait for resources */
897*3833Sxw161283 	    NULL,		/* no argument */
898*3833Sxw161283 	    &ch_vaddr,		/* allocated memory */
899*3833Sxw161283 	    &rlen,		/* real size allocated */
900*3833Sxw161283 	    &ch_ah);		/* data access handle */
901*3833Sxw161283 	if (rv != DDI_SUCCESS) {
902*3833Sxw161283 		ddi_dma_free_handle(&ch_dh);
903*3833Sxw161283 
904*3833Sxw161283 		cmn_err(CE_WARN,
905*3833Sxw161283 			"%s: ch_alloc_dma_mem: ddi_dma_mem_alloc error %d\n",
906*3833Sxw161283 			chp->ch_name, rv);
907*3833Sxw161283 
908*3833Sxw161283 		return (0);
909*3833Sxw161283 	}
910*3833Sxw161283 
911*3833Sxw161283 	rv = ddi_dma_addr_bind_handle(
912*3833Sxw161283 	    ch_dh,				/* dma handle */
913*3833Sxw161283 	    (struct as *)0,			/* kernel address space */
914*3833Sxw161283 	    ch_vaddr,				/* virtual address */
915*3833Sxw161283 	    rlen,				/* length of object */
916*3833Sxw161283 	    direction|mapping,
917*3833Sxw161283 	    DDI_DMA_SLEEP,			/* Wait for resources */
918*3833Sxw161283 	    NULL,				/* no argument */
919*3833Sxw161283 	    &cookie,				/* dma cookie */
920*3833Sxw161283 	    &count);
921*3833Sxw161283 	if (rv != DDI_DMA_MAPPED) {
922*3833Sxw161283 		ddi_dma_mem_free(&ch_ah);
923*3833Sxw161283 		ddi_dma_free_handle(&ch_dh);
924*3833Sxw161283 
925*3833Sxw161283 		cmn_err(CE_WARN,
926*3833Sxw161283 		    "%s: ch_alloc_dma_mem: ddi_dma_addr_bind_handle error %d\n",
927*3833Sxw161283 			chp->ch_name, rv);
928*3833Sxw161283 
929*3833Sxw161283 		return (0);
930*3833Sxw161283 	}
931*3833Sxw161283 
932*3833Sxw161283 	if (count != 1) {
933*3833Sxw161283 		cmn_err(CE_WARN,
934*3833Sxw161283 		    "%s: ch_alloc_dma_mem: ch_alloc_dma_mem cookie count %d\n",
935*3833Sxw161283 			chp->ch_name, count);
936*3833Sxw161283 		PRINT(("ch_alloc_dma_mem cookie count %d\n", count));
937*3833Sxw161283 
938*3833Sxw161283 		ddi_dma_mem_free(&ch_ah);
939*3833Sxw161283 		ddi_dma_free_handle(&ch_dh);
940*3833Sxw161283 
941*3833Sxw161283 		return (0);
942*3833Sxw161283 	}
943*3833Sxw161283 
944*3833Sxw161283 	*paddr = cookie.dmac_laddress;
945*3833Sxw161283 
946*3833Sxw161283 	*(ddi_dma_handle_t *)dh = ch_dh;
947*3833Sxw161283 	*(ddi_acc_handle_t *)ah = ch_ah;
948*3833Sxw161283 
949*3833Sxw161283 	return ((void *)ch_vaddr);
950*3833Sxw161283 }
951*3833Sxw161283 
952*3833Sxw161283 /*
953*3833Sxw161283  * ch_free_dma_mem
954*3833Sxw161283  *
955*3833Sxw161283  * frees resources allocated by ch_alloc_dma_mem()
956*3833Sxw161283  *
957*3833Sxw161283  * frees DMA handle
958*3833Sxw161283  * frees kernel memory
959*3833Sxw161283  * frees DMA access handle
960*3833Sxw161283  */
961*3833Sxw161283 
962*3833Sxw161283 void
963*3833Sxw161283 ch_free_dma_mem(ulong_t dh, ulong_t ah)
964*3833Sxw161283 {
965*3833Sxw161283 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dh;
966*3833Sxw161283 	ddi_acc_handle_t ch_ah = (ddi_acc_handle_t)ah;
967*3833Sxw161283 
968*3833Sxw161283 	(void) ddi_dma_unbind_handle(ch_dh);
969*3833Sxw161283 	ddi_dma_mem_free(&ch_ah);
970*3833Sxw161283 	ddi_dma_free_handle(&ch_dh);
971*3833Sxw161283 }
972*3833Sxw161283 
973*3833Sxw161283 /*
974*3833Sxw161283  * create a dma handle and return a dma handle entry.
975*3833Sxw161283  */
976*3833Sxw161283 free_dh_t *
977*3833Sxw161283 ch_get_dma_handle(ch_t *chp)
978*3833Sxw161283 {
979*3833Sxw161283 	ddi_dma_handle_t ch_dh;
980*3833Sxw161283 	ddi_dma_attr_t ch_dma_attr;
981*3833Sxw161283 	free_dh_t *dhe;
982*3833Sxw161283 	int rv;
983*3833Sxw161283 
984*3833Sxw161283 	dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
985*3833Sxw161283 
986*3833Sxw161283 	ch_dma_attr.dma_attr_version = DMA_ATTR_V0;
987*3833Sxw161283 	ch_dma_attr.dma_attr_addr_lo = 0;
988*3833Sxw161283 	ch_dma_attr.dma_attr_addr_hi = 0xffffffffffffffff;
989*3833Sxw161283 	ch_dma_attr.dma_attr_count_max = 0x00ffffff;
990*3833Sxw161283 	ch_dma_attr.dma_attr_align = 1;
991*3833Sxw161283 	ch_dma_attr.dma_attr_burstsizes = 0xfff;
992*3833Sxw161283 	ch_dma_attr.dma_attr_minxfer = 1;
993*3833Sxw161283 	ch_dma_attr.dma_attr_maxxfer = 0x00ffffff;
994*3833Sxw161283 	ch_dma_attr.dma_attr_seg = 0xffffffff;
995*3833Sxw161283 	ch_dma_attr.dma_attr_sgllen = 5;
996*3833Sxw161283 	ch_dma_attr.dma_attr_granular = 1;
997*3833Sxw161283 	ch_dma_attr.dma_attr_flags = 0;
998*3833Sxw161283 
999*3833Sxw161283 	rv = ddi_dma_alloc_handle(
1000*3833Sxw161283 	    chp->ch_dip,		/* device dev_info */
1001*3833Sxw161283 	    &ch_dma_attr,		/* DMA attributes */
1002*3833Sxw161283 	    DDI_DMA_SLEEP,		/* Wait if no memory */
1003*3833Sxw161283 	    NULL,			/* no argument */
1004*3833Sxw161283 	    &ch_dh);			/* DMA handle */
1005*3833Sxw161283 	if (rv != DDI_SUCCESS) {
1006*3833Sxw161283 
1007*3833Sxw161283 		cmn_err(CE_WARN,
1008*3833Sxw161283 		    "%s: ch_get_dma_handle: ddi_dma_alloc_handle error %d\n",
1009*3833Sxw161283 			chp->ch_name, rv);
1010*3833Sxw161283 
1011*3833Sxw161283 		kmem_free(dhe, sizeof (*dhe));
1012*3833Sxw161283 
1013*3833Sxw161283 		return ((free_dh_t *)0);
1014*3833Sxw161283 	}
1015*3833Sxw161283 
1016*3833Sxw161283 	dhe->dhe_dh = (ulong_t)ch_dh;
1017*3833Sxw161283 
1018*3833Sxw161283 	return (dhe);
1019*3833Sxw161283 }
1020*3833Sxw161283 
1021*3833Sxw161283 /*
1022*3833Sxw161283  * free the linked list of dma descriptor entries.
1023*3833Sxw161283  */
1024*3833Sxw161283 static void
1025*3833Sxw161283 ch_free_dma_handles(ch_t *chp)
1026*3833Sxw161283 {
1027*3833Sxw161283 	free_dh_t *dhe, *the;
1028*3833Sxw161283 
1029*3833Sxw161283 	dhe = chp->ch_dh;
1030*3833Sxw161283 	while (dhe) {
1031*3833Sxw161283 		ddi_dma_free_handle((ddi_dma_handle_t *)&dhe->dhe_dh);
1032*3833Sxw161283 		the = dhe;
1033*3833Sxw161283 		dhe = dhe->dhe_next;
1034*3833Sxw161283 		kmem_free(the, sizeof (*the));
1035*3833Sxw161283 	}
1036*3833Sxw161283 	chp->ch_dh = NULL;
1037*3833Sxw161283 }
1038*3833Sxw161283 
1039*3833Sxw161283 /*
1040*3833Sxw161283  * ch_bind_dma_handle()
1041*3833Sxw161283  *
1042*3833Sxw161283  * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
1043*3833Sxw161283  *
1044*3833Sxw161283  * chp - per-board descriptor
1045*3833Sxw161283  * size - # bytes mapped
1046*3833Sxw161283  * vaddr - virtual address
1047*3833Sxw161283  * cmp - array of cmdQ_ce_t entries
1048*3833Sxw161283  * cnt - # free entries in cmp array
1049*3833Sxw161283  */
1050*3833Sxw161283 
1051*3833Sxw161283 uint32_t
1052*3833Sxw161283 ch_bind_dma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
1053*3833Sxw161283 	uint32_t cnt)
1054*3833Sxw161283 {
1055*3833Sxw161283 	ddi_dma_cookie_t cookie;
1056*3833Sxw161283 	ddi_dma_handle_t ch_dh;
1057*3833Sxw161283 	uint_t count;
1058*3833Sxw161283 	uint32_t n = 1;
1059*3833Sxw161283 	free_dh_t *dhe;
1060*3833Sxw161283 	uint_t rv;
1061*3833Sxw161283 
1062*3833Sxw161283 	mutex_enter(&chp->ch_dh_lck);
1063*3833Sxw161283 	if ((dhe = chp->ch_dh) != NULL) {
1064*3833Sxw161283 		chp->ch_dh = dhe->dhe_next;
1065*3833Sxw161283 	}
1066*3833Sxw161283 	mutex_exit(&chp->ch_dh_lck);
1067*3833Sxw161283 
1068*3833Sxw161283 	if (dhe == NULL) {
1069*3833Sxw161283 		return (0);
1070*3833Sxw161283 	}
1071*3833Sxw161283 
1072*3833Sxw161283 	ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1073*3833Sxw161283 
1074*3833Sxw161283 	rv = ddi_dma_addr_bind_handle(
1075*3833Sxw161283 	    ch_dh,		/* dma handle */
1076*3833Sxw161283 	    (struct as *)0,	/* kernel address space */
1077*3833Sxw161283 	    vaddr,		/* virtual address */
1078*3833Sxw161283 	    size,		/* length of object */
1079*3833Sxw161283 	    DDI_DMA_WRITE|DDI_DMA_STREAMING,
1080*3833Sxw161283 	    DDI_DMA_SLEEP,	/* Wait for resources */
1081*3833Sxw161283 	    NULL,		/* no argument */
1082*3833Sxw161283 	    &cookie,	/* dma cookie */
1083*3833Sxw161283 	    &count);
1084*3833Sxw161283 	if (rv != DDI_DMA_MAPPED) {
1085*3833Sxw161283 
1086*3833Sxw161283 		/* return dma header descriptor back to free list */
1087*3833Sxw161283 		mutex_enter(&chp->ch_dh_lck);
1088*3833Sxw161283 		dhe->dhe_next = chp->ch_dh;
1089*3833Sxw161283 		chp->ch_dh = dhe;
1090*3833Sxw161283 		mutex_exit(&chp->ch_dh_lck);
1091*3833Sxw161283 
1092*3833Sxw161283 		cmn_err(CE_WARN,
1093*3833Sxw161283 		    "%s: ch_bind_dma_handle: ddi_dma_addr_bind_handle err %d\n",
1094*3833Sxw161283 			chp->ch_name, rv);
1095*3833Sxw161283 
1096*3833Sxw161283 		return (0);
1097*3833Sxw161283 	}
1098*3833Sxw161283 
1099*3833Sxw161283 	/*
1100*3833Sxw161283 	 * abort if we've run out of space
1101*3833Sxw161283 	 */
1102*3833Sxw161283 	if (count > cnt) {
1103*3833Sxw161283 		/* return dma header descriptor back to free list */
1104*3833Sxw161283 		mutex_enter(&chp->ch_dh_lck);
1105*3833Sxw161283 		dhe->dhe_next = chp->ch_dh;
1106*3833Sxw161283 		chp->ch_dh = dhe;
1107*3833Sxw161283 		mutex_exit(&chp->ch_dh_lck);
1108*3833Sxw161283 
1109*3833Sxw161283 		return (0);
1110*3833Sxw161283 	}
1111*3833Sxw161283 
1112*3833Sxw161283 	cmp->ce_pa = cookie.dmac_laddress;
1113*3833Sxw161283 	cmp->ce_dh = NULL;
1114*3833Sxw161283 	cmp->ce_len = cookie.dmac_size;
1115*3833Sxw161283 	cmp->ce_mp = NULL;
1116*3833Sxw161283 	cmp->ce_flg = DH_DMA;
1117*3833Sxw161283 
1118*3833Sxw161283 	while (--count) {
1119*3833Sxw161283 		cmp++;
1120*3833Sxw161283 		n++;
1121*3833Sxw161283 		ddi_dma_nextcookie(ch_dh, &cookie);
1122*3833Sxw161283 		cmp->ce_pa = cookie.dmac_laddress;
1123*3833Sxw161283 		cmp->ce_dh = NULL;
1124*3833Sxw161283 		cmp->ce_len = cookie.dmac_size;
1125*3833Sxw161283 		cmp->ce_mp = NULL;
1126*3833Sxw161283 		cmp->ce_flg = DH_DMA;
1127*3833Sxw161283 	}
1128*3833Sxw161283 
1129*3833Sxw161283 	cmp->ce_dh = dhe;
1130*3833Sxw161283 
1131*3833Sxw161283 	return (n);
1132*3833Sxw161283 }
1133*3833Sxw161283 
1134*3833Sxw161283 /*
1135*3833Sxw161283  * ch_unbind_dma_handle()
1136*3833Sxw161283  *
1137*3833Sxw161283  * frees resources alloacted by ch_bind_dma_handle().
1138*3833Sxw161283  *
1139*3833Sxw161283  * frees DMA handle
1140*3833Sxw161283  */
1141*3833Sxw161283 
1142*3833Sxw161283 void
1143*3833Sxw161283 ch_unbind_dma_handle(ch_t *chp, free_dh_t *dhe)
1144*3833Sxw161283 {
1145*3833Sxw161283 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1146*3833Sxw161283 
1147*3833Sxw161283 	if (ddi_dma_unbind_handle(ch_dh))
1148*3833Sxw161283 		cmn_err(CE_WARN, "%s: ddi_dma_unbind_handle failed",
1149*3833Sxw161283 			chp->ch_name);
1150*3833Sxw161283 
1151*3833Sxw161283 	mutex_enter(&chp->ch_dh_lck);
1152*3833Sxw161283 	dhe->dhe_next = chp->ch_dh;
1153*3833Sxw161283 	chp->ch_dh = dhe;
1154*3833Sxw161283 	mutex_exit(&chp->ch_dh_lck);
1155*3833Sxw161283 }
1156*3833Sxw161283 
1157*3833Sxw161283 #if defined(__sparc)
1158*3833Sxw161283 /*
1159*3833Sxw161283  * DVMA stuff. Solaris only.
1160*3833Sxw161283  */
1161*3833Sxw161283 
1162*3833Sxw161283 /*
1163*3833Sxw161283  * create a dvma handle and return a dma handle entry.
1164*3833Sxw161283  * DVMA is on sparc only!
1165*3833Sxw161283  */
1166*3833Sxw161283 
1167*3833Sxw161283 free_dh_t *
1168*3833Sxw161283 ch_get_dvma_handle(ch_t *chp)
1169*3833Sxw161283 {
1170*3833Sxw161283 	ddi_dma_handle_t ch_dh;
1171*3833Sxw161283 	ddi_dma_lim_t ch_dvma_attr;
1172*3833Sxw161283 	free_dh_t *dhe;
1173*3833Sxw161283 	int rv;
1174*3833Sxw161283 
1175*3833Sxw161283 	dhe = (free_dh_t *)kmem_zalloc(sizeof (*dhe), KM_SLEEP);
1176*3833Sxw161283 
1177*3833Sxw161283 	ch_dvma_attr.dlim_addr_lo = 0;
1178*3833Sxw161283 	ch_dvma_attr.dlim_addr_hi = 0xffffffff;
1179*3833Sxw161283 	ch_dvma_attr.dlim_cntr_max = 0xffffffff;
1180*3833Sxw161283 	ch_dvma_attr.dlim_burstsizes = 0xfff;
1181*3833Sxw161283 	ch_dvma_attr.dlim_minxfer = 1;
1182*3833Sxw161283 	ch_dvma_attr.dlim_dmaspeed = 0;
1183*3833Sxw161283 
1184*3833Sxw161283 	rv = dvma_reserve(
1185*3833Sxw161283 		chp->ch_dip,		/* device dev_info */
1186*3833Sxw161283 		&ch_dvma_attr,		/* DVMA attributes */
1187*3833Sxw161283 		3,			/* number of pages */
1188*3833Sxw161283 		&ch_dh);		/* DVMA handle */
1189*3833Sxw161283 
1190*3833Sxw161283 	if (rv != DDI_SUCCESS) {
1191*3833Sxw161283 
1192*3833Sxw161283 		cmn_err(CE_WARN,
1193*3833Sxw161283 		    "%s: ch_get_dvma_handle: dvma_reserve() error %d\n",
1194*3833Sxw161283 			chp->ch_name, rv);
1195*3833Sxw161283 
1196*3833Sxw161283 		kmem_free(dhe, sizeof (*dhe));
1197*3833Sxw161283 
1198*3833Sxw161283 		return ((free_dh_t *)0);
1199*3833Sxw161283 	}
1200*3833Sxw161283 
1201*3833Sxw161283 	dhe->dhe_dh = (ulong_t)ch_dh;
1202*3833Sxw161283 
1203*3833Sxw161283 	return (dhe);
1204*3833Sxw161283 }
1205*3833Sxw161283 
1206*3833Sxw161283 /*
1207*3833Sxw161283  * free the linked list of dvma descriptor entries.
1208*3833Sxw161283  * DVMA is only on sparc!
1209*3833Sxw161283  */
1210*3833Sxw161283 
1211*3833Sxw161283 static void
1212*3833Sxw161283 ch_free_dvma_handles(ch_t *chp)
1213*3833Sxw161283 {
1214*3833Sxw161283 	free_dh_t *dhe, *the;
1215*3833Sxw161283 
1216*3833Sxw161283 	dhe = chp->ch_vdh;
1217*3833Sxw161283 	while (dhe) {
1218*3833Sxw161283 		dvma_release((ddi_dma_handle_t)dhe->dhe_dh);
1219*3833Sxw161283 		the = dhe;
1220*3833Sxw161283 		dhe = dhe->dhe_next;
1221*3833Sxw161283 		kmem_free(the, sizeof (*the));
1222*3833Sxw161283 	}
1223*3833Sxw161283 	chp->ch_vdh = NULL;
1224*3833Sxw161283 }
1225*3833Sxw161283 
1226*3833Sxw161283 /*
1227*3833Sxw161283  * ch_bind_dvma_handle()
1228*3833Sxw161283  *
1229*3833Sxw161283  * returns # of entries used off of cmdQ_ce_t array to hold physical addrs.
1230*3833Sxw161283  * DVMA in sparc only
1231*3833Sxw161283  *
1232*3833Sxw161283  * chp - per-board descriptor
1233*3833Sxw161283  * size - # bytes mapped
1234*3833Sxw161283  * vaddr - virtual address
1235*3833Sxw161283  * cmp - array of cmdQ_ce_t entries
1236*3833Sxw161283  * cnt - # free entries in cmp array
1237*3833Sxw161283  */
1238*3833Sxw161283 
1239*3833Sxw161283 uint32_t
1240*3833Sxw161283 ch_bind_dvma_handle(ch_t *chp, int size, caddr_t vaddr, cmdQ_ce_t *cmp,
1241*3833Sxw161283 	uint32_t cnt)
1242*3833Sxw161283 {
1243*3833Sxw161283 	ddi_dma_cookie_t cookie;
1244*3833Sxw161283 	ddi_dma_handle_t ch_dh;
1245*3833Sxw161283 	uint32_t n = 1;
1246*3833Sxw161283 	free_dh_t *dhe;
1247*3833Sxw161283 
1248*3833Sxw161283 	mutex_enter(&chp->ch_dh_lck);
1249*3833Sxw161283 	if ((dhe = chp->ch_vdh) != NULL) {
1250*3833Sxw161283 		chp->ch_vdh = dhe->dhe_next;
1251*3833Sxw161283 	}
1252*3833Sxw161283 	mutex_exit(&chp->ch_dh_lck);
1253*3833Sxw161283 
1254*3833Sxw161283 	if (dhe == NULL) {
1255*3833Sxw161283 		return (0);
1256*3833Sxw161283 	}
1257*3833Sxw161283 
1258*3833Sxw161283 	ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1259*3833Sxw161283 	n = cnt;
1260*3833Sxw161283 
1261*3833Sxw161283 	dvma_kaddr_load(
1262*3833Sxw161283 		ch_dh,		/* dvma handle */
1263*3833Sxw161283 		vaddr,		/* virtual address */
1264*3833Sxw161283 		size,		/* length of object */
1265*3833Sxw161283 		0,		/* start at index 0 */
1266*3833Sxw161283 		&cookie);
1267*3833Sxw161283 
1268*3833Sxw161283 	dvma_sync(ch_dh, 0, DDI_DMA_SYNC_FORDEV);
1269*3833Sxw161283 
1270*3833Sxw161283 	cookie.dmac_notused = 0;
1271*3833Sxw161283 	n = 1;
1272*3833Sxw161283 
1273*3833Sxw161283 	cmp->ce_pa = cookie.dmac_laddress;
1274*3833Sxw161283 	cmp->ce_dh = dhe;
1275*3833Sxw161283 	cmp->ce_len = cookie.dmac_size;
1276*3833Sxw161283 	cmp->ce_mp = NULL;
1277*3833Sxw161283 	cmp->ce_flg = DH_DVMA;	/* indicate a dvma descriptor */
1278*3833Sxw161283 
1279*3833Sxw161283 	return (n);
1280*3833Sxw161283 }
1281*3833Sxw161283 
1282*3833Sxw161283 /*
1283*3833Sxw161283  * ch_unbind_dvma_handle()
1284*3833Sxw161283  *
1285*3833Sxw161283  * frees resources alloacted by ch_bind_dvma_handle().
1286*3833Sxw161283  *
1287*3833Sxw161283  * frees DMA handle
1288*3833Sxw161283  */
1289*3833Sxw161283 
1290*3833Sxw161283 void
1291*3833Sxw161283 ch_unbind_dvma_handle(ch_t *chp, free_dh_t *dhe)
1292*3833Sxw161283 {
1293*3833Sxw161283 	ddi_dma_handle_t ch_dh = (ddi_dma_handle_t)dhe->dhe_dh;
1294*3833Sxw161283 
1295*3833Sxw161283 	dvma_unload(ch_dh, 0, -1);
1296*3833Sxw161283 
1297*3833Sxw161283 	mutex_enter(&chp->ch_dh_lck);
1298*3833Sxw161283 	dhe->dhe_next = chp->ch_vdh;
1299*3833Sxw161283 	chp->ch_vdh = dhe;
1300*3833Sxw161283 	mutex_exit(&chp->ch_dh_lck);
1301*3833Sxw161283 }
1302*3833Sxw161283 
1303*3833Sxw161283 #endif	/* defined(__sparc) */
1304*3833Sxw161283 
1305*3833Sxw161283 /*
1306*3833Sxw161283  * send received packet up stream.
1307*3833Sxw161283  *
1308*3833Sxw161283  * if driver has been stopped, then we drop the message.
1309*3833Sxw161283  */
1310*3833Sxw161283 void
1311*3833Sxw161283 ch_send_up(ch_t *chp, mblk_t *mp, uint32_t cksum, int flg)
1312*3833Sxw161283 {
1313*3833Sxw161283 	/*
1314*3833Sxw161283 	 * probably do not need a lock here. When we set PESTOP in
1315*3833Sxw161283 	 * ch_stop() a packet could have just passed here and gone
1316*3833Sxw161283 	 * upstream. The next one will be dropped.
1317*3833Sxw161283 	 */
1318*3833Sxw161283 	if (chp->ch_state == PERUNNING) {
1319*3833Sxw161283 		/*
1320*3833Sxw161283 		 * note that flg will not be set unless enable_checksum_offload
1321*3833Sxw161283 		 * set in /etc/system (see sge.c).
1322*3833Sxw161283 		 */
1323*3833Sxw161283 		if (flg)
1324*3833Sxw161283 			(void) hcksum_assoc(mp, NULL, NULL, 0, 0, 0, cksum,
1325*3833Sxw161283 				HCK_FULLCKSUM, 0);
1326*3833Sxw161283 		gld_recv(chp->ch_macp, mp);
1327*3833Sxw161283 	} else {
1328*3833Sxw161283 		freemsg(mp);
1329*3833Sxw161283 	}
1330*3833Sxw161283 }
1331*3833Sxw161283 
1332*3833Sxw161283 /*
1333*3833Sxw161283  * unblock gld driver.
1334*3833Sxw161283  */
1335*3833Sxw161283 void
1336*3833Sxw161283 ch_gld_ok(ch_t *chp)
1337*3833Sxw161283 {
1338*3833Sxw161283 	gld_sched(chp->ch_macp);
1339*3833Sxw161283 }
1340*3833Sxw161283 
1341*3833Sxw161283 
1342*3833Sxw161283 /*
1343*3833Sxw161283  * reset the card.
1344*3833Sxw161283  *
1345*3833Sxw161283  * Note: we only do this after the card has been initialized.
1346*3833Sxw161283  */
1347*3833Sxw161283 static int
1348*3833Sxw161283 ch_reset(gld_mac_info_t *mp)
1349*3833Sxw161283 {
1350*3833Sxw161283 	ch_t *chp;
1351*3833Sxw161283 
1352*3833Sxw161283 	if (mp == NULL) {
1353*3833Sxw161283 		return (GLD_FAILURE);
1354*3833Sxw161283 	}
1355*3833Sxw161283 
1356*3833Sxw161283 	chp = (ch_t *)mp->gldm_private;
1357*3833Sxw161283 
1358*3833Sxw161283 	if (chp == NULL) {
1359*3833Sxw161283 		return (GLD_FAILURE);
1360*3833Sxw161283 	}
1361*3833Sxw161283 
1362*3833Sxw161283 #ifdef NOTYET
1363*3833Sxw161283 	/*
1364*3833Sxw161283 	 * do a reset of card
1365*3833Sxw161283 	 *
1366*3833Sxw161283 	 * 1. set PwrState to D3hot (3)
1367*3833Sxw161283 	 * 2. clear PwrState flags
1368*3833Sxw161283 	 */
1369*3833Sxw161283 	/*
1370*3833Sxw161283 	 * When we did this, the card didn't start. First guess is that
1371*3833Sxw161283 	 * the initialization is not quite correct. For now, we don't
1372*3833Sxw161283 	 * reset things.
1373*3833Sxw161283 	 */
1374*3833Sxw161283 	if (chp->ch_hpci) {
1375*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 3);
1376*3833Sxw161283 		pci_config_put32(chp->ch_hpci, 0x44, 0);
1377*3833Sxw161283 
1378*3833Sxw161283 		/* delay .5 sec */
1379*3833Sxw161283 		DELAY(500000);
1380*3833Sxw161283 	}
1381*3833Sxw161283 #endif
1382*3833Sxw161283 
1383*3833Sxw161283 	return (GLD_SUCCESS);
1384*3833Sxw161283 }
1385*3833Sxw161283 
1386*3833Sxw161283 static int
1387*3833Sxw161283 ch_start(gld_mac_info_t *macinfo)
1388*3833Sxw161283 {
1389*3833Sxw161283 	ch_t *chp = (ch_t *)macinfo->gldm_private;
1390*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1391*3833Sxw161283 	/* only initialize card on first attempt */
1392*3833Sxw161283 	mutex_enter(&chp->ch_lock);
1393*3833Sxw161283 	chp->ch_refcnt++;
1394*3833Sxw161283 	if (chp->ch_refcnt == 1) {
1395*3833Sxw161283 		chp->ch_state = PERUNNING;
1396*3833Sxw161283 		mutex_exit(&chp->ch_lock);
1397*3833Sxw161283 		pe_init((void *)chp);
1398*3833Sxw161283 	} else
1399*3833Sxw161283 		mutex_exit(&chp->ch_lock);
1400*3833Sxw161283 #else
1401*3833Sxw161283 	pe_init((void *)chp);
1402*3833Sxw161283 
1403*3833Sxw161283 	/* go to running state, we're being started */
1404*3833Sxw161283 	mutex_enter(&chp->ch_lock);
1405*3833Sxw161283 	chp->ch_state = PERUNNING;
1406*3833Sxw161283 	mutex_exit(&chp->ch_lock);
1407*3833Sxw161283 #endif
1408*3833Sxw161283 
1409*3833Sxw161283 	return (GLD_SUCCESS);
1410*3833Sxw161283 }
1411*3833Sxw161283 
1412*3833Sxw161283 static int
1413*3833Sxw161283 ch_stop(gld_mac_info_t *mp)
1414*3833Sxw161283 {
1415*3833Sxw161283 	ch_t *chp = (ch_t *)mp->gldm_private;
1416*3833Sxw161283 
1417*3833Sxw161283 	/*
1418*3833Sxw161283 	 * can only stop the chip if it's been initialized
1419*3833Sxw161283 	 */
1420*3833Sxw161283 	mutex_enter(&chp->ch_lock);
1421*3833Sxw161283 	if (chp->ch_state == PEIDLE) {
1422*3833Sxw161283 		mutex_exit(&chp->ch_lock);
1423*3833Sxw161283 		return (GLD_FAILURE);
1424*3833Sxw161283 	}
1425*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1426*3833Sxw161283 	chp->ch_refcnt--;
1427*3833Sxw161283 	if (chp->ch_refcnt == 0) {
1428*3833Sxw161283 		chp->ch_state = PESTOP;
1429*3833Sxw161283 		mutex_exit(&chp->ch_lock);
1430*3833Sxw161283 		pe_stop(chp);
1431*3833Sxw161283 	} else
1432*3833Sxw161283 		mutex_exit(&chp->ch_lock);
1433*3833Sxw161283 #else
1434*3833Sxw161283 	chp->ch_state = PESTOP;
1435*3833Sxw161283 	mutex_exit(&chp->ch_lock);
1436*3833Sxw161283 	pe_stop(chp);
1437*3833Sxw161283 #endif
1438*3833Sxw161283 	return (GLD_SUCCESS);
1439*3833Sxw161283 }
1440*3833Sxw161283 
1441*3833Sxw161283 static int
1442*3833Sxw161283 ch_set_mac_address(gld_mac_info_t *mp, uint8_t *mac)
1443*3833Sxw161283 {
1444*3833Sxw161283 	ch_t *chp;
1445*3833Sxw161283 
1446*3833Sxw161283 	if (mp) {
1447*3833Sxw161283 		chp = (ch_t *)mp->gldm_private;
1448*3833Sxw161283 	} else {
1449*3833Sxw161283 		return (GLD_FAILURE);
1450*3833Sxw161283 	}
1451*3833Sxw161283 
1452*3833Sxw161283 	pe_set_mac(chp, mac);
1453*3833Sxw161283 
1454*3833Sxw161283 	return (GLD_SUCCESS);
1455*3833Sxw161283 }
1456*3833Sxw161283 
1457*3833Sxw161283 static int
1458*3833Sxw161283 ch_set_multicast(gld_mac_info_t *mp, uint8_t *ep, int flg)
1459*3833Sxw161283 {
1460*3833Sxw161283 	ch_t *chp = (ch_t *)mp->gldm_private;
1461*3833Sxw161283 
1462*3833Sxw161283 	return (pe_set_mc(chp, ep, flg));
1463*3833Sxw161283 }
1464*3833Sxw161283 
1465*3833Sxw161283 static int
1466*3833Sxw161283 ch_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp)
1467*3833Sxw161283 {
1468*3833Sxw161283 	struct iocblk *iocp;
1469*3833Sxw161283 
1470*3833Sxw161283 	switch (mp->b_datap->db_type) {
1471*3833Sxw161283 	case M_IOCTL:
1472*3833Sxw161283 		/* pe_ioctl() does qreply() */
1473*3833Sxw161283 		pe_ioctl((ch_t *)(macinfo->gldm_private), q, mp);
1474*3833Sxw161283 		break;
1475*3833Sxw161283 
1476*3833Sxw161283 	default:
1477*3833Sxw161283 /*
1478*3833Sxw161283  *		cmn_err(CE_NOTE, "ch_ioctl not M_IOCTL\n");
1479*3833Sxw161283  *		debug_enter("bad ch_ioctl");
1480*3833Sxw161283  */
1481*3833Sxw161283 
1482*3833Sxw161283 		iocp = (struct iocblk *)mp->b_rptr;
1483*3833Sxw161283 
1484*3833Sxw161283 		if (mp->b_cont)
1485*3833Sxw161283 			freemsg(mp->b_cont);
1486*3833Sxw161283 		mp->b_cont = NULL;
1487*3833Sxw161283 
1488*3833Sxw161283 		mp->b_datap->db_type = M_IOCNAK;
1489*3833Sxw161283 		iocp->ioc_error = EINVAL;
1490*3833Sxw161283 		qreply(q, mp);
1491*3833Sxw161283 		break;
1492*3833Sxw161283 	}
1493*3833Sxw161283 
1494*3833Sxw161283 	return (GLD_SUCCESS);
1495*3833Sxw161283 }
1496*3833Sxw161283 
1497*3833Sxw161283 static int
1498*3833Sxw161283 ch_set_promiscuous(gld_mac_info_t *mp, int flag)
1499*3833Sxw161283 {
1500*3833Sxw161283 	ch_t *chp = (ch_t *)mp->gldm_private;
1501*3833Sxw161283 
1502*3833Sxw161283 	switch (flag) {
1503*3833Sxw161283 	case GLD_MAC_PROMISC_MULTI:
1504*3833Sxw161283 		pe_set_promiscuous(chp, 2);
1505*3833Sxw161283 		break;
1506*3833Sxw161283 
1507*3833Sxw161283 	case GLD_MAC_PROMISC_NONE:
1508*3833Sxw161283 		pe_set_promiscuous(chp, 0);
1509*3833Sxw161283 		break;
1510*3833Sxw161283 
1511*3833Sxw161283 	case GLD_MAC_PROMISC_PHYS:
1512*3833Sxw161283 	default:
1513*3833Sxw161283 		pe_set_promiscuous(chp, 1);
1514*3833Sxw161283 		break;
1515*3833Sxw161283 	}
1516*3833Sxw161283 
1517*3833Sxw161283 	return (GLD_SUCCESS);
1518*3833Sxw161283 }
1519*3833Sxw161283 
1520*3833Sxw161283 static int
1521*3833Sxw161283 ch_get_stats(gld_mac_info_t *mp, struct gld_stats *gs)
1522*3833Sxw161283 {
1523*3833Sxw161283 	ch_t *chp = (ch_t *)mp->gldm_private;
1524*3833Sxw161283 	uint64_t speed;
1525*3833Sxw161283 	uint32_t intrcnt;
1526*3833Sxw161283 	uint32_t norcvbuf;
1527*3833Sxw161283 	uint32_t oerrors;
1528*3833Sxw161283 	uint32_t ierrors;
1529*3833Sxw161283 	uint32_t underrun;
1530*3833Sxw161283 	uint32_t overrun;
1531*3833Sxw161283 	uint32_t framing;
1532*3833Sxw161283 	uint32_t crc;
1533*3833Sxw161283 	uint32_t carrier;
1534*3833Sxw161283 	uint32_t collisions;
1535*3833Sxw161283 	uint32_t xcollisions;
1536*3833Sxw161283 	uint32_t late;
1537*3833Sxw161283 	uint32_t defer;
1538*3833Sxw161283 	uint32_t xerrs;
1539*3833Sxw161283 	uint32_t rerrs;
1540*3833Sxw161283 	uint32_t toolong;
1541*3833Sxw161283 	uint32_t runt;
1542*3833Sxw161283 	ulong_t multixmt;
1543*3833Sxw161283 	ulong_t multircv;
1544*3833Sxw161283 	ulong_t brdcstxmt;
1545*3833Sxw161283 	ulong_t brdcstrcv;
1546*3833Sxw161283 
1547*3833Sxw161283 	/*
1548*3833Sxw161283 	 * race looks benign here.
1549*3833Sxw161283 	 */
1550*3833Sxw161283 	if (chp->ch_state != PERUNNING) {
1551*3833Sxw161283 		return (GLD_FAILURE);
1552*3833Sxw161283 	}
1553*3833Sxw161283 
1554*3833Sxw161283 	(void) pe_get_stats(chp,
1555*3833Sxw161283 			&speed,
1556*3833Sxw161283 			&intrcnt,
1557*3833Sxw161283 			&norcvbuf,
1558*3833Sxw161283 			&oerrors,
1559*3833Sxw161283 			&ierrors,
1560*3833Sxw161283 			&underrun,
1561*3833Sxw161283 			&overrun,
1562*3833Sxw161283 			&framing,
1563*3833Sxw161283 			&crc,
1564*3833Sxw161283 			&carrier,
1565*3833Sxw161283 			&collisions,
1566*3833Sxw161283 			&xcollisions,
1567*3833Sxw161283 			&late,
1568*3833Sxw161283 			&defer,
1569*3833Sxw161283 			&xerrs,
1570*3833Sxw161283 			&rerrs,
1571*3833Sxw161283 			&toolong,
1572*3833Sxw161283 			&runt,
1573*3833Sxw161283 			&multixmt,
1574*3833Sxw161283 			&multircv,
1575*3833Sxw161283 			&brdcstxmt,
1576*3833Sxw161283 			&brdcstrcv);
1577*3833Sxw161283 
1578*3833Sxw161283 	gs->glds_speed = speed;
1579*3833Sxw161283 	gs->glds_media = GLDM_UNKNOWN;
1580*3833Sxw161283 	gs->glds_intr  = intrcnt;
1581*3833Sxw161283 	gs->glds_norcvbuf = norcvbuf;
1582*3833Sxw161283 	gs->glds_errxmt = oerrors;
1583*3833Sxw161283 	gs->glds_errrcv = ierrors;
1584*3833Sxw161283 	gs->glds_missed = ierrors;	/* ??? */
1585*3833Sxw161283 	gs->glds_underflow = underrun;
1586*3833Sxw161283 	gs->glds_overflow = overrun;
1587*3833Sxw161283 	gs->glds_frame = framing;
1588*3833Sxw161283 	gs->glds_crc = crc;
1589*3833Sxw161283 	gs->glds_duplex = GLD_DUPLEX_FULL;
1590*3833Sxw161283 	gs->glds_nocarrier = carrier;
1591*3833Sxw161283 	gs->glds_collisions = collisions;
1592*3833Sxw161283 	gs->glds_excoll = xcollisions;
1593*3833Sxw161283 	gs->glds_xmtlatecoll = late;
1594*3833Sxw161283 	gs->glds_defer = defer;
1595*3833Sxw161283 	gs->glds_dot3_first_coll = 0;	/* Not available */
1596*3833Sxw161283 	gs->glds_dot3_multi_coll = 0;	/* Not available */
1597*3833Sxw161283 	gs->glds_dot3_sqe_error = 0;	/* Not available */
1598*3833Sxw161283 	gs->glds_dot3_mac_xmt_error = xerrs;
1599*3833Sxw161283 	gs->glds_dot3_mac_rcv_error = rerrs;
1600*3833Sxw161283 	gs->glds_dot3_frame_too_long = toolong;
1601*3833Sxw161283 	gs->glds_short = runt;
1602*3833Sxw161283 
1603*3833Sxw161283 	gs->glds_noxmtbuf = 0;		/* not documented */
1604*3833Sxw161283 	gs->glds_xmtretry = 0;		/* not documented */
1605*3833Sxw161283 	gs->glds_multixmt = multixmt;	/* not documented */
1606*3833Sxw161283 	gs->glds_multircv = multircv;	/* not documented */
1607*3833Sxw161283 	gs->glds_brdcstxmt = brdcstxmt;	/* not documented */
1608*3833Sxw161283 	gs->glds_brdcstrcv = brdcstrcv;	/* not documented */
1609*3833Sxw161283 
1610*3833Sxw161283 	return (GLD_SUCCESS);
1611*3833Sxw161283 }
1612*3833Sxw161283 
1613*3833Sxw161283 
1614*3833Sxw161283 static int
1615*3833Sxw161283 ch_send(gld_mac_info_t *macinfo, mblk_t *mp)
1616*3833Sxw161283 {
1617*3833Sxw161283 	ch_t *chp = (ch_t *)macinfo->gldm_private;
1618*3833Sxw161283 	uint32_t flg;
1619*3833Sxw161283 	uint32_t msg_flg;
1620*3833Sxw161283 
1621*3833Sxw161283 #ifdef TX_CKSUM_FIX
1622*3833Sxw161283 	mblk_t *nmp;
1623*3833Sxw161283 	int frags;
1624*3833Sxw161283 	size_t msg_len;
1625*3833Sxw161283 	struct ether_header *ehdr;
1626*3833Sxw161283 	ipha_t *ihdr;
1627*3833Sxw161283 	int tflg = 0;
1628*3833Sxw161283 #endif	/* TX_CKSUM_FIX */
1629*3833Sxw161283 
1630*3833Sxw161283 	/*
1631*3833Sxw161283 	 * race looks benign here.
1632*3833Sxw161283 	 */
1633*3833Sxw161283 	if (chp->ch_state != PERUNNING) {
1634*3833Sxw161283 		return (GLD_FAILURE);
1635*3833Sxw161283 	}
1636*3833Sxw161283 
1637*3833Sxw161283 	msg_flg = 0;
1638*3833Sxw161283 	if (chp->ch_config.cksum_enabled) {
1639*3833Sxw161283 		if (is_T2(chp)) {
1640*3833Sxw161283 			hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL,
1641*3833Sxw161283 				NULL, &msg_flg);
1642*3833Sxw161283 			flg = (msg_flg & HCK_FULLCKSUM)?
1643*3833Sxw161283 				CH_NO_CPL: CH_NO_HWCKSUM|CH_NO_CPL;
1644*3833Sxw161283 		} else
1645*3833Sxw161283 			flg = CH_NO_CPL;
1646*3833Sxw161283 	} else
1647*3833Sxw161283 	flg = CH_NO_HWCKSUM | CH_NO_CPL;
1648*3833Sxw161283 
1649*3833Sxw161283 #ifdef TX_CKSUM_FIX
1650*3833Sxw161283 	/*
1651*3833Sxw161283 	 * Check if the message spans more than one mblk or
1652*3833Sxw161283 	 * if it does and the ip header is not in the first
1653*3833Sxw161283 	 * fragment then pull up the message. This case is
1654*3833Sxw161283 	 * expected to be rare.
1655*3833Sxw161283 	 */
1656*3833Sxw161283 	frags = 0;
1657*3833Sxw161283 	msg_len = 0;
1658*3833Sxw161283 	nmp = mp;
1659*3833Sxw161283 	do {
1660*3833Sxw161283 		frags++;
1661*3833Sxw161283 		msg_len += MBLKL(nmp);
1662*3833Sxw161283 		nmp = nmp->b_cont;
1663*3833Sxw161283 	} while (nmp);
1664*3833Sxw161283 #define	MAX_ALL_HDRLEN SZ_CPL_TX_PKT + sizeof (struct ether_header) + \
1665*3833Sxw161283 				TCP_MAX_COMBINED_HEADER_LENGTH
1666*3833Sxw161283 	/*
1667*3833Sxw161283 	 * If the first mblk has enough space at the beginning of
1668*3833Sxw161283 	 * the data buffer to hold a CPL header, then, we'll expancd
1669*3833Sxw161283 	 * the front of the buffer so a pullup will leave space for
1670*3833Sxw161283 	 * pe_start() to add the CPL header in line. We need to remember
1671*3833Sxw161283 	 * that we've done this so we can undo it after the pullup.
1672*3833Sxw161283 	 *
1673*3833Sxw161283 	 * Note that if we decide to do an allocb to hold the CPL header,
1674*3833Sxw161283 	 * we need to catch the case where we've added an empty mblk for
1675*3833Sxw161283 	 * the header but never did a pullup. This would result in the
1676*3833Sxw161283 	 * tests for etherheader, etc. being done on the initial, empty,
1677*3833Sxw161283 	 * mblk instead of the one with data. See PR3646 for further
1678*3833Sxw161283 	 * details. (note this PR is closed since it is no longer relevant).
1679*3833Sxw161283 	 *
1680*3833Sxw161283 	 * Another point is that if we do add an allocb to add space for
1681*3833Sxw161283 	 * a CPL header, after a pullup, the initial pointer, mp, in GLD will
1682*3833Sxw161283 	 * no longer point to a valid mblk. When we get the mblk (by allocb),
1683*3833Sxw161283 	 * we need to switch the mblk structure values between it and the
1684*3833Sxw161283 	 * mp structure values referenced by GLD. This handles the case where
1685*3833Sxw161283 	 * we've run out of cmdQ entries and report GLD_NORESOURCES back to
1686*3833Sxw161283 	 * GLD. The pointer to the mblk data will have been modified to hold
1687*3833Sxw161283 	 * an empty 8 bytes for the CPL header, For now, we let the pe_start()
1688*3833Sxw161283 	 * routine prepend an 8 byte mblk.
1689*3833Sxw161283 	 */
1690*3833Sxw161283 	if (MBLKHEAD(mp) >= SZ_CPL_TX_PKT) {
1691*3833Sxw161283 		mp->b_rptr -= SZ_CPL_TX_PKT;
1692*3833Sxw161283 		tflg = 1;
1693*3833Sxw161283 	}
1694*3833Sxw161283 	if (frags > 3) {
1695*3833Sxw161283 		chp->sge->intr_cnt.tx_msg_pullups++;
1696*3833Sxw161283 		if (pullupmsg(mp, -1) == 0) {
1697*3833Sxw161283 			freemsg(mp);
1698*3833Sxw161283 			return (GLD_SUCCESS);
1699*3833Sxw161283 		}
1700*3833Sxw161283 	} else if ((msg_len > MAX_ALL_HDRLEN) &&
1701*3833Sxw161283 			(MBLKL(mp) < MAX_ALL_HDRLEN)) {
1702*3833Sxw161283 		chp->sge->intr_cnt.tx_hdr_pullups++;
1703*3833Sxw161283 		if (pullupmsg(mp, MAX_ALL_HDRLEN) == 0) {
1704*3833Sxw161283 			freemsg(mp);
1705*3833Sxw161283 			return (GLD_SUCCESS);
1706*3833Sxw161283 		}
1707*3833Sxw161283 	}
1708*3833Sxw161283 	if (tflg)
1709*3833Sxw161283 		mp->b_rptr += SZ_CPL_TX_PKT;
1710*3833Sxw161283 
1711*3833Sxw161283 	ehdr = (struct ether_header *)mp->b_rptr;
1712*3833Sxw161283 	if (ehdr->ether_type == htons(ETHERTYPE_IP)) {
1713*3833Sxw161283 		ihdr = (ipha_t *)&mp->b_rptr[sizeof (struct ether_header)];
1714*3833Sxw161283 		if ((ihdr->ipha_fragment_offset_and_flags & IPH_MF)) {
1715*3833Sxw161283 			if (ihdr->ipha_protocol == IPPROTO_UDP) {
1716*3833Sxw161283 				flg |= CH_UDP_MF;
1717*3833Sxw161283 				chp->sge->intr_cnt.tx_udp_ip_frag++;
1718*3833Sxw161283 			} else if (ihdr->ipha_protocol == IPPROTO_TCP) {
1719*3833Sxw161283 				flg |= CH_TCP_MF;
1720*3833Sxw161283 				chp->sge->intr_cnt.tx_tcp_ip_frag++;
1721*3833Sxw161283 			}
1722*3833Sxw161283 		} else if (ihdr->ipha_protocol == IPPROTO_UDP)
1723*3833Sxw161283 			flg |= CH_UDP;
1724*3833Sxw161283 	}
1725*3833Sxw161283 #endif	/* TX_CKSUM_FIX */
1726*3833Sxw161283 
1727*3833Sxw161283 	/*
1728*3833Sxw161283 	 * return 0 - data send successfully
1729*3833Sxw161283 	 * return 1 - no resources, reschedule
1730*3833Sxw161283 	 */
1731*3833Sxw161283 	if (pe_start(chp, mp, flg))
1732*3833Sxw161283 		return (GLD_NORESOURCES);
1733*3833Sxw161283 	else
1734*3833Sxw161283 		return (GLD_SUCCESS);
1735*3833Sxw161283 }
1736*3833Sxw161283 
1737*3833Sxw161283 static uint_t
1738*3833Sxw161283 ch_intr(gld_mac_info_t *mp)
1739*3833Sxw161283 {
1740*3833Sxw161283 	return (pe_intr((ch_t *)mp->gldm_private));
1741*3833Sxw161283 }
1742*3833Sxw161283 
1743*3833Sxw161283 /*
1744*3833Sxw161283  * generate name of driver with unit# postpended.
1745*3833Sxw161283  */
1746*3833Sxw161283 void
1747*3833Sxw161283 ch_set_name(ch_t *chp, int unit)
1748*3833Sxw161283 {
1749*3833Sxw161283 	chp->ch_name = (char *)kmem_alloc(sizeof ("chxge00"), KM_SLEEP);
1750*3833Sxw161283 	if (unit > 9) {
1751*3833Sxw161283 		bcopy("chxge00", (void *)chp->ch_name, sizeof ("chxge00"));
1752*3833Sxw161283 		chp->ch_name[5] += unit/10;
1753*3833Sxw161283 		chp->ch_name[6] += unit%10;
1754*3833Sxw161283 	} else {
1755*3833Sxw161283 		bcopy("chxge0", (void *)chp->ch_name, sizeof ("chxge0"));
1756*3833Sxw161283 		chp->ch_name[5] += unit;
1757*3833Sxw161283 	}
1758*3833Sxw161283 }
1759*3833Sxw161283 
1760*3833Sxw161283 void
1761*3833Sxw161283 ch_free_name(ch_t *chp)
1762*3833Sxw161283 {
1763*3833Sxw161283 	if (chp->ch_name)
1764*3833Sxw161283 		kmem_free(chp->ch_name, sizeof ("chxge00"));
1765*3833Sxw161283 	chp->ch_name = NULL;
1766*3833Sxw161283 }
1767*3833Sxw161283 
1768*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1769*3833Sxw161283 /*
1770*3833Sxw161283  * register toe offload.
1771*3833Sxw161283  */
1772*3833Sxw161283 void *
1773*3833Sxw161283 ch_register(void *instp, void *toe_rcv, void *toe_free, void *toe_tunnel,
1774*3833Sxw161283     kmutex_t *toe_tx_mx, kcondvar_t *toe_of_cv, int unit)
1775*3833Sxw161283 {
1776*3833Sxw161283 	ch_t *chp = gchp[unit];
1777*3833Sxw161283 	if (chp != NULL) {
1778*3833Sxw161283 		mutex_enter(&chp->ch_lock);
1779*3833Sxw161283 
1780*3833Sxw161283 		chp->toe_rcv = (void (*)(void *, mblk_t *))toe_rcv;
1781*3833Sxw161283 		chp->ch_toeinst = instp;
1782*3833Sxw161283 		chp->toe_free = (void (*)(void *, tbuf_t *))toe_free;
1783*3833Sxw161283 		chp->toe_tunnel = (int (*)(void *, mblk_t *))toe_tunnel;
1784*3833Sxw161283 		chp->ch_tx_overflow_mutex = toe_tx_mx;
1785*3833Sxw161283 		chp->ch_tx_overflow_cv = toe_of_cv;
1786*3833Sxw161283 		chp->open_device_map |= TOEDEV_DEVMAP_BIT;
1787*3833Sxw161283 
1788*3833Sxw161283 		/* start up adapter if first user */
1789*3833Sxw161283 		chp->ch_refcnt++;
1790*3833Sxw161283 		if (chp->ch_refcnt == 1) {
1791*3833Sxw161283 			chp->ch_state = PERUNNING;
1792*3833Sxw161283 			mutex_exit(&chp->ch_lock);
1793*3833Sxw161283 			pe_init((void *)chp);
1794*3833Sxw161283 		} else
1795*3833Sxw161283 			mutex_exit(&chp->ch_lock);
1796*3833Sxw161283 	}
1797*3833Sxw161283 	return ((void *)gchp[unit]);
1798*3833Sxw161283 }
1799*3833Sxw161283 
1800*3833Sxw161283 /*
1801*3833Sxw161283  * unregister toe offload.
1802*3833Sxw161283  * XXX Need to fix races here.
1803*3833Sxw161283  *     1. turn off SGE interrupts.
1804*3833Sxw161283  *     2. do update
1805*3833Sxw161283  *     3. re-enable SGE interrupts
1806*3833Sxw161283  *     4. SGE doorbell to make sure things get restarted.
1807*3833Sxw161283  */
1808*3833Sxw161283 void
1809*3833Sxw161283 ch_unregister(void)
1810*3833Sxw161283 {
1811*3833Sxw161283 	int i;
1812*3833Sxw161283 	ch_t *chp;
1813*3833Sxw161283 
1814*3833Sxw161283 	for (i = 0; i < MAX_CARDS; i++) {
1815*3833Sxw161283 		chp = gchp[i];
1816*3833Sxw161283 		if (chp == NULL)
1817*3833Sxw161283 			continue;
1818*3833Sxw161283 
1819*3833Sxw161283 		mutex_enter(&chp->ch_lock);
1820*3833Sxw161283 
1821*3833Sxw161283 		chp->ch_refcnt--;
1822*3833Sxw161283 		if (chp->ch_refcnt == 0) {
1823*3833Sxw161283 			chp->ch_state = PESTOP;
1824*3833Sxw161283 			mutex_exit(&chp->ch_lock);
1825*3833Sxw161283 			pe_stop(chp);
1826*3833Sxw161283 		} else
1827*3833Sxw161283 			mutex_exit(&chp->ch_lock);
1828*3833Sxw161283 
1829*3833Sxw161283 		chp->open_device_map &= ~TOEDEV_DEVMAP_BIT;
1830*3833Sxw161283 		chp->toe_rcv = NULL;
1831*3833Sxw161283 		chp->ch_toeinst =  NULL;
1832*3833Sxw161283 		chp->toe_free = NULL;
1833*3833Sxw161283 		chp->toe_tunnel = NULL;
1834*3833Sxw161283 		chp->ch_tx_overflow_mutex = NULL;
1835*3833Sxw161283 		chp->ch_tx_overflow_cv = NULL;
1836*3833Sxw161283 	}
1837*3833Sxw161283 }
1838*3833Sxw161283 #endif	/* CONFIG_CHELSIO_T1_OFFLOAD */
1839*3833Sxw161283 
1840*3833Sxw161283 /*
1841*3833Sxw161283  * get properties from chxge.conf
1842*3833Sxw161283  */
1843*3833Sxw161283 static void
1844*3833Sxw161283 ch_get_prop(ch_t *chp)
1845*3833Sxw161283 {
1846*3833Sxw161283 	int val;
1847*3833Sxw161283 	int tval = 0;
1848*3833Sxw161283 	extern int enable_latency_timer;
1849*3833Sxw161283 	extern uint32_t sge_cmdq0_cnt;
1850*3833Sxw161283 	extern uint32_t sge_cmdq1_cnt;
1851*3833Sxw161283 	extern uint32_t sge_flq0_cnt;
1852*3833Sxw161283 	extern uint32_t sge_flq1_cnt;
1853*3833Sxw161283 	extern uint32_t sge_respq_cnt;
1854*3833Sxw161283 	extern uint32_t sge_cmdq0_cnt_orig;
1855*3833Sxw161283 	extern uint32_t sge_cmdq1_cnt_orig;
1856*3833Sxw161283 	extern uint32_t sge_flq0_cnt_orig;
1857*3833Sxw161283 	extern uint32_t sge_flq1_cnt_orig;
1858*3833Sxw161283 	extern uint32_t sge_respq_cnt_orig;
1859*3833Sxw161283 	dev_info_t *pdip;
1860*3833Sxw161283 	uint32_t vendor_id, device_id, revision_id;
1861*3833Sxw161283 	uint32_t *prop_val = NULL;
1862*3833Sxw161283 	uint32_t prop_len = NULL;
1863*3833Sxw161283 
1864*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1865*3833Sxw161283 		"enable_dvma", -1);
1866*3833Sxw161283 	if (val == -1)
1867*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1868*3833Sxw161283 			"enable-dvma", -1);
1869*3833Sxw161283 	if (val != -1) {
1870*3833Sxw161283 		if (val != 0)
1871*3833Sxw161283 			chp->ch_config.enable_dvma = 1;
1872*3833Sxw161283 	}
1873*3833Sxw161283 
1874*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1875*3833Sxw161283 		"amd_bug_workaround", -1);
1876*3833Sxw161283 	if (val == -1)
1877*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
1878*3833Sxw161283 			"amd-bug-workaround", -1);
1879*3833Sxw161283 
1880*3833Sxw161283 	if (val != -1) {
1881*3833Sxw161283 		if (val == 0) {
1882*3833Sxw161283 			chp->ch_config.burstsize_set = 0;
1883*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 0;
1884*3833Sxw161283 			goto fail_exit;
1885*3833Sxw161283 		}
1886*3833Sxw161283 	}
1887*3833Sxw161283 	/*
1888*3833Sxw161283 	 * Step up to the parent node,  That's the node above us
1889*3833Sxw161283 	 * in the device tree. And will typically be the PCI host
1890*3833Sxw161283 	 * Controller.
1891*3833Sxw161283 	 */
1892*3833Sxw161283 	pdip = ddi_get_parent(chp->ch_dip);
1893*3833Sxw161283 
1894*3833Sxw161283 	/*
1895*3833Sxw161283 	 * Now get the 'Vendor id' properties
1896*3833Sxw161283 	 */
1897*3833Sxw161283 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "vendor-id",
1898*3833Sxw161283 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1899*3833Sxw161283 		chp->ch_config.burstsize_set = 0;
1900*3833Sxw161283 		chp->ch_config.transaction_cnt_set = 0;
1901*3833Sxw161283 		goto fail_exit;
1902*3833Sxw161283 	}
1903*3833Sxw161283 	vendor_id = *(uint32_t *)prop_val;
1904*3833Sxw161283 	ddi_prop_free(prop_val);
1905*3833Sxw161283 
1906*3833Sxw161283 	/*
1907*3833Sxw161283 	 * Now get the 'Device id' properties
1908*3833Sxw161283 	 */
1909*3833Sxw161283 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "device-id",
1910*3833Sxw161283 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1911*3833Sxw161283 		chp->ch_config.burstsize_set = 0;
1912*3833Sxw161283 		chp->ch_config.transaction_cnt_set = 0;
1913*3833Sxw161283 		goto fail_exit;
1914*3833Sxw161283 	}
1915*3833Sxw161283 	device_id = *(uint32_t *)prop_val;
1916*3833Sxw161283 	ddi_prop_free(prop_val);
1917*3833Sxw161283 
1918*3833Sxw161283 	/*
1919*3833Sxw161283 	 * Now get the 'Revision id' properties
1920*3833Sxw161283 	 */
1921*3833Sxw161283 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, pdip, 0, "revision-id",
1922*3833Sxw161283 	    (int **)&prop_val, &prop_len) != DDI_PROP_SUCCESS) {
1923*3833Sxw161283 		chp->ch_config.burstsize_set = 0;
1924*3833Sxw161283 		chp->ch_config.transaction_cnt_set = 0;
1925*3833Sxw161283 		goto fail_exit;
1926*3833Sxw161283 	}
1927*3833Sxw161283 	revision_id = *(uint32_t *)prop_val;
1928*3833Sxw161283 	ddi_prop_free(prop_val);
1929*3833Sxw161283 
1930*3833Sxw161283 	/*
1931*3833Sxw161283 	 * set default values based on node above us.
1932*3833Sxw161283 	 */
1933*3833Sxw161283 	if ((vendor_id == AMD_VENDOR_ID) && (device_id == AMD_BRIDGE) &&
1934*3833Sxw161283 	    (revision_id <= AMD_BRIDGE_REV)) {
1935*3833Sxw161283 		uint32_t v;
1936*3833Sxw161283 		uint32_t burst;
1937*3833Sxw161283 		uint32_t cnt;
1938*3833Sxw161283 
1939*3833Sxw161283 		/* if 133 Mhz not enabled, then do nothing - we're not PCIx */
1940*3833Sxw161283 		v = pci_config_get32(chp->ch_hpci, 0x64);
1941*3833Sxw161283 		if ((v & 0x20000) == NULL) {
1942*3833Sxw161283 			chp->ch_config.burstsize_set = 0;
1943*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 0;
1944*3833Sxw161283 			goto fail_exit;
1945*3833Sxw161283 		}
1946*3833Sxw161283 
1947*3833Sxw161283 		/* check burst size and transaction count */
1948*3833Sxw161283 		v = pci_config_get32(chp->ch_hpci, 0x60);
1949*3833Sxw161283 		burst = (v >> 18) & 3;
1950*3833Sxw161283 		cnt = (v >> 20) & 7;
1951*3833Sxw161283 
1952*3833Sxw161283 		switch (burst) {
1953*3833Sxw161283 		case 0:	/* 512 */
1954*3833Sxw161283 			/* 512 burst size legal with split cnts 1,2,3 */
1955*3833Sxw161283 			if (cnt <= 2) {
1956*3833Sxw161283 				chp->ch_config.burstsize_set = 0;
1957*3833Sxw161283 				chp->ch_config.transaction_cnt_set = 0;
1958*3833Sxw161283 				goto fail_exit;
1959*3833Sxw161283 			}
1960*3833Sxw161283 			break;
1961*3833Sxw161283 		case 1:	/* 1024 */
1962*3833Sxw161283 			/* 1024 burst size legal with split cnts 1,2 */
1963*3833Sxw161283 			if (cnt <= 1) {
1964*3833Sxw161283 				chp->ch_config.burstsize_set = 0;
1965*3833Sxw161283 				chp->ch_config.transaction_cnt_set = 0;
1966*3833Sxw161283 				goto fail_exit;
1967*3833Sxw161283 			}
1968*3833Sxw161283 			break;
1969*3833Sxw161283 		case 2:	/* 2048 */
1970*3833Sxw161283 			/* 2048 burst size legal with split cnts 1 */
1971*3833Sxw161283 			if (cnt == 0) {
1972*3833Sxw161283 				chp->ch_config.burstsize_set = 0;
1973*3833Sxw161283 				chp->ch_config.transaction_cnt_set = 0;
1974*3833Sxw161283 				goto fail_exit;
1975*3833Sxw161283 			}
1976*3833Sxw161283 			break;
1977*3833Sxw161283 		case 3:	/* 4096 */
1978*3833Sxw161283 			break;
1979*3833Sxw161283 		}
1980*3833Sxw161283 	} else {
1981*3833Sxw161283 		goto fail_exit;
1982*3833Sxw161283 	}
1983*3833Sxw161283 
1984*3833Sxw161283 	/*
1985*3833Sxw161283 	 * if illegal burst size seen, then default to 1024 burst size
1986*3833Sxw161283 	 */
1987*3833Sxw161283 	chp->ch_config.burstsize = 1;
1988*3833Sxw161283 	chp->ch_config.burstsize_set = 1;
1989*3833Sxw161283 	/*
1990*3833Sxw161283 	 * if illegal transaction cnt seen, then default to 2
1991*3833Sxw161283 	 */
1992*3833Sxw161283 	chp->ch_config.transaction_cnt = 1;
1993*3833Sxw161283 	chp->ch_config.transaction_cnt_set = 1;
1994*3833Sxw161283 
1995*3833Sxw161283 
1996*3833Sxw161283 fail_exit:
1997*3833Sxw161283 
1998*3833Sxw161283 	/*
1999*3833Sxw161283 	 * alter the burstsize parameter via an entry
2000*3833Sxw161283 	 * in chxge.conf
2001*3833Sxw161283 	 */
2002*3833Sxw161283 
2003*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2004*3833Sxw161283 		"pci_burstsize", -1);
2005*3833Sxw161283 	if (val == -1)
2006*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2007*3833Sxw161283 			"pci-burstsize", -1);
2008*3833Sxw161283 
2009*3833Sxw161283 	if (val != -1) {
2010*3833Sxw161283 
2011*3833Sxw161283 		switch (val) {
2012*3833Sxw161283 		case 0:	/* use default */
2013*3833Sxw161283 			chp->ch_config.burstsize_set = 0;
2014*3833Sxw161283 			break;
2015*3833Sxw161283 
2016*3833Sxw161283 		case 1024:
2017*3833Sxw161283 			chp->ch_config.burstsize_set = 1;
2018*3833Sxw161283 			chp->ch_config.burstsize = 1;
2019*3833Sxw161283 			break;
2020*3833Sxw161283 
2021*3833Sxw161283 		case 2048:
2022*3833Sxw161283 			chp->ch_config.burstsize_set = 1;
2023*3833Sxw161283 			chp->ch_config.burstsize = 2;
2024*3833Sxw161283 			break;
2025*3833Sxw161283 
2026*3833Sxw161283 		case 4096:
2027*3833Sxw161283 			cmn_err(CE_WARN, "%s not supported %d\n",
2028*3833Sxw161283 			    chp->ch_name, val);
2029*3833Sxw161283 			break;
2030*3833Sxw161283 
2031*3833Sxw161283 		default:
2032*3833Sxw161283 			cmn_err(CE_WARN, "%s illegal burst size %d\n",
2033*3833Sxw161283 			    chp->ch_name, val);
2034*3833Sxw161283 			break;
2035*3833Sxw161283 		}
2036*3833Sxw161283 	}
2037*3833Sxw161283 
2038*3833Sxw161283 	/*
2039*3833Sxw161283 	 * set transaction count
2040*3833Sxw161283 	 */
2041*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2042*3833Sxw161283 		"pci_split_transaction_cnt", -1);
2043*3833Sxw161283 	if (val == -1)
2044*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2045*3833Sxw161283 			"pci-split-transaction-cnt", -1);
2046*3833Sxw161283 
2047*3833Sxw161283 	if (val != -1) {
2048*3833Sxw161283 		switch (val) {
2049*3833Sxw161283 		case 0:	/* use default */
2050*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 0;
2051*3833Sxw161283 			break;
2052*3833Sxw161283 
2053*3833Sxw161283 		case 1:
2054*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2055*3833Sxw161283 			chp->ch_config.transaction_cnt = 0;
2056*3833Sxw161283 			break;
2057*3833Sxw161283 
2058*3833Sxw161283 		case 2:
2059*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2060*3833Sxw161283 			chp->ch_config.transaction_cnt = 1;
2061*3833Sxw161283 			break;
2062*3833Sxw161283 
2063*3833Sxw161283 		case 3:
2064*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2065*3833Sxw161283 			chp->ch_config.transaction_cnt = 2;
2066*3833Sxw161283 			break;
2067*3833Sxw161283 
2068*3833Sxw161283 		case 4:
2069*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2070*3833Sxw161283 			chp->ch_config.transaction_cnt = 3;
2071*3833Sxw161283 			break;
2072*3833Sxw161283 
2073*3833Sxw161283 		case 8:
2074*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2075*3833Sxw161283 			chp->ch_config.transaction_cnt = 4;
2076*3833Sxw161283 			break;
2077*3833Sxw161283 
2078*3833Sxw161283 		case 12:
2079*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2080*3833Sxw161283 			chp->ch_config.transaction_cnt = 5;
2081*3833Sxw161283 			break;
2082*3833Sxw161283 
2083*3833Sxw161283 		case 16:
2084*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2085*3833Sxw161283 			chp->ch_config.transaction_cnt = 6;
2086*3833Sxw161283 			break;
2087*3833Sxw161283 
2088*3833Sxw161283 		case 32:
2089*3833Sxw161283 			chp->ch_config.transaction_cnt_set = 1;
2090*3833Sxw161283 			chp->ch_config.transaction_cnt = 7;
2091*3833Sxw161283 			break;
2092*3833Sxw161283 
2093*3833Sxw161283 		default:
2094*3833Sxw161283 			cmn_err(CE_WARN, "%s illegal transaction cnt %d\n",
2095*3833Sxw161283 			    chp->ch_name, val);
2096*3833Sxw161283 			break;
2097*3833Sxw161283 		}
2098*3833Sxw161283 	}
2099*3833Sxw161283 
2100*3833Sxw161283 	/*
2101*3833Sxw161283 	 * set relaxed ordering bit?
2102*3833Sxw161283 	 */
2103*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2104*3833Sxw161283 		"pci_relaxed_ordering_on", -1);
2105*3833Sxw161283 	if (val == -1)
2106*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2107*3833Sxw161283 			"pci-relaxed-ordering-on", -1);
2108*3833Sxw161283 
2109*3833Sxw161283 	/*
2110*3833Sxw161283 	 * default is to use system default value.
2111*3833Sxw161283 	 */
2112*3833Sxw161283 	chp->ch_config.relaxed_ordering = 0;
2113*3833Sxw161283 
2114*3833Sxw161283 	if (val != -1) {
2115*3833Sxw161283 		if (val)
2116*3833Sxw161283 			chp->ch_config.relaxed_ordering = 1;
2117*3833Sxw161283 	}
2118*3833Sxw161283 
2119*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2120*3833Sxw161283 		"enable_latency_timer", -1);
2121*3833Sxw161283 	if (val == -1)
2122*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2123*3833Sxw161283 			"enable-latency-timer", -1);
2124*3833Sxw161283 	if (val != -1)
2125*3833Sxw161283 		enable_latency_timer = (val == 0)? 0: 1;
2126*3833Sxw161283 
2127*3833Sxw161283 	/*
2128*3833Sxw161283 	 * default maximum Jumbo Frame size.
2129*3833Sxw161283 	 */
2130*3833Sxw161283 	chp->ch_maximum_mtu = 9198;	/* tunable via chxge.conf */
2131*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2132*3833Sxw161283 		"maximum_mtu", -1);
2133*3833Sxw161283 	if (val == -1) {
2134*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2135*3833Sxw161283 			"maximum-mtu", -1);
2136*3833Sxw161283 	}
2137*3833Sxw161283 	if (val != -1) {
2138*3833Sxw161283 		if (val > 9582) {
2139*3833Sxw161283 			cmn_err(CE_WARN,
2140*3833Sxw161283 			    "maximum_mtu value %d > 9582. Value set to 9582",
2141*3833Sxw161283 			    val);
2142*3833Sxw161283 			val = 9582;
2143*3833Sxw161283 		} else if (val < 1500) {
2144*3833Sxw161283 			cmn_err(CE_WARN,
2145*3833Sxw161283 			    "maximum_mtu value %d < 1500. Value set to 1500",
2146*3833Sxw161283 			    val);
2147*3833Sxw161283 			val = 1500;
2148*3833Sxw161283 		}
2149*3833Sxw161283 
2150*3833Sxw161283 		if (val)
2151*3833Sxw161283 			chp->ch_maximum_mtu = val;
2152*3833Sxw161283 	}
2153*3833Sxw161283 
2154*3833Sxw161283 	/*
2155*3833Sxw161283 	 * default value for this instance mtu
2156*3833Sxw161283 	 */
2157*3833Sxw161283 	chp->ch_mtu = ETHERMTU;
2158*3833Sxw161283 
2159*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2160*3833Sxw161283 		"accept_jumbo", -1);
2161*3833Sxw161283 	if (val == -1) {
2162*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2163*3833Sxw161283 			"accept-jumbo", -1);
2164*3833Sxw161283 	}
2165*3833Sxw161283 	if (val != -1) {
2166*3833Sxw161283 		if (val)
2167*3833Sxw161283 			chp->ch_mtu = chp->ch_maximum_mtu;
2168*3833Sxw161283 	}
2169*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
2170*3833Sxw161283 	chp->ch_sm_buf_sz = 0x800;
2171*3833Sxw161283 	chp->ch_sm_buf_aln = 0x800;
2172*3833Sxw161283 	chp->ch_bg_buf_sz = 0x4000;
2173*3833Sxw161283 	chp->ch_bg_buf_aln = 0x4000;
2174*3833Sxw161283 #else
2175*3833Sxw161283 	chp->ch_sm_buf_sz = 0x200;
2176*3833Sxw161283 	chp->ch_sm_buf_aln = 0x200;
2177*3833Sxw161283 	chp->ch_bg_buf_sz = 0x800;
2178*3833Sxw161283 	chp->ch_bg_buf_aln = 0x800;
2179*3833Sxw161283 	if ((chp->ch_mtu > 0x800) && (chp->ch_mtu <= 0x1000)) {
2180*3833Sxw161283 		chp->ch_sm_buf_sz = 0x400;
2181*3833Sxw161283 		chp->ch_sm_buf_aln = 0x400;
2182*3833Sxw161283 		chp->ch_bg_buf_sz = 0x1000;
2183*3833Sxw161283 		chp->ch_bg_buf_aln = 0x1000;
2184*3833Sxw161283 	} else if ((chp->ch_mtu > 0x1000) && (chp->ch_mtu <= 0x2000)) {
2185*3833Sxw161283 		chp->ch_sm_buf_sz = 0x400;
2186*3833Sxw161283 		chp->ch_sm_buf_aln = 0x400;
2187*3833Sxw161283 		chp->ch_bg_buf_sz = 0x2000;
2188*3833Sxw161283 		chp->ch_bg_buf_aln = 0x2000;
2189*3833Sxw161283 	} else if (chp->ch_mtu > 0x2000) {
2190*3833Sxw161283 		chp->ch_sm_buf_sz = 0x400;
2191*3833Sxw161283 		chp->ch_sm_buf_aln = 0x400;
2192*3833Sxw161283 		chp->ch_bg_buf_sz = 0x3000;
2193*3833Sxw161283 		chp->ch_bg_buf_aln = 0x4000;
2194*3833Sxw161283 	}
2195*3833Sxw161283 #endif
2196*3833Sxw161283 	chp->ch_config.cksum_enabled = 1;
2197*3833Sxw161283 
2198*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2199*3833Sxw161283 		"enable_checksum_offload", -1);
2200*3833Sxw161283 	if (val == -1)
2201*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2202*3833Sxw161283 			"enable-checksum-offload", -1);
2203*3833Sxw161283 	if (val != -1) {
2204*3833Sxw161283 		if (val == NULL)
2205*3833Sxw161283 			chp->ch_config.cksum_enabled = 0;
2206*3833Sxw161283 	}
2207*3833Sxw161283 
2208*3833Sxw161283 	/*
2209*3833Sxw161283 	 * Provides a tuning capability for the command queue 0 size.
2210*3833Sxw161283 	 */
2211*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2212*3833Sxw161283 		"sge_cmdq0_cnt", -1);
2213*3833Sxw161283 	if (val == -1)
2214*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2215*3833Sxw161283 			"sge-cmdq0-cnt", -1);
2216*3833Sxw161283 	if (val != -1) {
2217*3833Sxw161283 		if (val > 10)
2218*3833Sxw161283 			sge_cmdq0_cnt = val;
2219*3833Sxw161283 	}
2220*3833Sxw161283 
2221*3833Sxw161283 	if (sge_cmdq0_cnt > 65535) {
2222*3833Sxw161283 		cmn_err(CE_WARN,
2223*3833Sxw161283 		    "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
2224*3833Sxw161283 			chp->ch_name);
2225*3833Sxw161283 		sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
2226*3833Sxw161283 	}
2227*3833Sxw161283 	tval += sge_cmdq0_cnt;
2228*3833Sxw161283 
2229*3833Sxw161283 	/*
2230*3833Sxw161283 	 * Provides a tuning capability for the command queue 1 size.
2231*3833Sxw161283 	 */
2232*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2233*3833Sxw161283 		"sge_cmdq1_cnt", -1);
2234*3833Sxw161283 	if (val == -1)
2235*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2236*3833Sxw161283 			"sge-cmdq1-cnt", -1);
2237*3833Sxw161283 	if (val != -1) {
2238*3833Sxw161283 		if (val > 10)
2239*3833Sxw161283 			sge_cmdq1_cnt = val;
2240*3833Sxw161283 	}
2241*3833Sxw161283 
2242*3833Sxw161283 	if (sge_cmdq1_cnt > 65535) {
2243*3833Sxw161283 		cmn_err(CE_WARN,
2244*3833Sxw161283 		    "%s: sge-cmdQ0-cnt > 65535 - resetting value to default",
2245*3833Sxw161283 			chp->ch_name);
2246*3833Sxw161283 		sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
2247*3833Sxw161283 	}
2248*3833Sxw161283 
2249*3833Sxw161283 	/*
2250*3833Sxw161283 	 * Provides a tuning capability for the free list 0 size.
2251*3833Sxw161283 	 */
2252*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2253*3833Sxw161283 		"sge_flq0_cnt", -1);
2254*3833Sxw161283 	if (val == -1)
2255*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2256*3833Sxw161283 			"sge-flq0-cnt", -1);
2257*3833Sxw161283 	if (val != -1) {
2258*3833Sxw161283 		if (val > 512)
2259*3833Sxw161283 			sge_flq0_cnt = val;
2260*3833Sxw161283 	}
2261*3833Sxw161283 
2262*3833Sxw161283 	if (sge_flq0_cnt > 65535) {
2263*3833Sxw161283 		cmn_err(CE_WARN,
2264*3833Sxw161283 		    "%s: sge-flq0-cnt > 65535 - resetting value to default",
2265*3833Sxw161283 			chp->ch_name);
2266*3833Sxw161283 		sge_flq0_cnt = sge_flq0_cnt_orig;
2267*3833Sxw161283 	}
2268*3833Sxw161283 
2269*3833Sxw161283 	tval += sge_flq0_cnt;
2270*3833Sxw161283 
2271*3833Sxw161283 	/*
2272*3833Sxw161283 	 * Provides a tuning capability for the free list 1 size.
2273*3833Sxw161283 	 */
2274*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2275*3833Sxw161283 		"sge_flq1_cnt", -1);
2276*3833Sxw161283 	if (val == -1)
2277*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2278*3833Sxw161283 			"sge-flq1-cnt", -1);
2279*3833Sxw161283 	if (val != -1) {
2280*3833Sxw161283 		if (val > 512)
2281*3833Sxw161283 			sge_flq1_cnt = val;
2282*3833Sxw161283 	}
2283*3833Sxw161283 
2284*3833Sxw161283 	if (sge_flq1_cnt > 65535) {
2285*3833Sxw161283 		cmn_err(CE_WARN,
2286*3833Sxw161283 		    "%s: sge-flq1-cnt > 65535 - resetting value to default",
2287*3833Sxw161283 			chp->ch_name);
2288*3833Sxw161283 		sge_flq1_cnt = sge_flq1_cnt_orig;
2289*3833Sxw161283 	}
2290*3833Sxw161283 
2291*3833Sxw161283 	tval += sge_flq1_cnt;
2292*3833Sxw161283 
2293*3833Sxw161283 	/*
2294*3833Sxw161283 	 * Provides a tuning capability for the responce queue size.
2295*3833Sxw161283 	 */
2296*3833Sxw161283 	val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2297*3833Sxw161283 		"sge_respq_cnt", -1);
2298*3833Sxw161283 	if (val == -1)
2299*3833Sxw161283 		val = ddi_getprop(DDI_DEV_T_ANY, chp->ch_dip, DDI_PROP_DONTPASS,
2300*3833Sxw161283 			"sge-respq-cnt", -1);
2301*3833Sxw161283 	if (val != -1) {
2302*3833Sxw161283 		if (val > 30)
2303*3833Sxw161283 			sge_respq_cnt = val;
2304*3833Sxw161283 	}
2305*3833Sxw161283 
2306*3833Sxw161283 	if (sge_respq_cnt > 65535) {
2307*3833Sxw161283 		cmn_err(CE_WARN,
2308*3833Sxw161283 		    "%s: sge-respq-cnt > 65535 - resetting value to default",
2309*3833Sxw161283 			chp->ch_name);
2310*3833Sxw161283 		sge_respq_cnt = sge_respq_cnt_orig;
2311*3833Sxw161283 	}
2312*3833Sxw161283 
2313*3833Sxw161283 	if (tval > sge_respq_cnt) {
2314*3833Sxw161283 		if (tval <= 65535) {
2315*3833Sxw161283 			cmn_err(CE_WARN,
2316*3833Sxw161283 	    "%s: sge-respq-cnt < %d - setting value to %d (cmdQ+flq0+flq1)",
2317*3833Sxw161283 			    chp->ch_name, tval, tval);
2318*3833Sxw161283 
2319*3833Sxw161283 			sge_respq_cnt = tval;
2320*3833Sxw161283 		} else {
2321*3833Sxw161283 			cmn_err(CE_WARN,
2322*3833Sxw161283 			    "%s: Q sizes invalid - resetting to default values",
2323*3833Sxw161283 			    chp->ch_name);
2324*3833Sxw161283 
2325*3833Sxw161283 			sge_cmdq0_cnt = sge_cmdq0_cnt_orig;
2326*3833Sxw161283 			sge_cmdq1_cnt = sge_cmdq1_cnt_orig;
2327*3833Sxw161283 			sge_flq0_cnt = sge_flq0_cnt_orig;
2328*3833Sxw161283 			sge_flq1_cnt = sge_flq1_cnt_orig;
2329*3833Sxw161283 			sge_respq_cnt = sge_respq_cnt_orig;
2330*3833Sxw161283 		}
2331*3833Sxw161283 	}
2332*3833Sxw161283 }
2333