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