xref: /illumos-gate/usr/src/uts/common/io/efe/efe.c (revision e65fcc69)
1 /*
2  * Copyright (c) 2010 Steven Stallion.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     1. Redistributions of source code must retain the above copyright
9  *        notice, this list of conditions and the following disclaimer.
10  *     2. Redistributions in binary form must reproduce the above
11  *        copyright notice, this list of conditions and the following
12  *        disclaimer in the documentation and/or other materials provided
13  *        with the distribution.
14  *     3. Neither the name of the copyright owner nor the names of any
15  *        contributors may be used to endorse or promote products derived
16  *        from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/byteorder.h>
32 #include <sys/types.h>
33 #include <sys/errno.h>
34 #include <sys/varargs.h>
35 #include <sys/cmn_err.h>
36 #include <sys/note.h>
37 #include <sys/kmem.h>
38 #include <sys/conf.h>
39 #include <sys/devops.h>
40 #include <sys/modctl.h>
41 #include <sys/sysmacros.h>
42 #include <sys/ddi.h>
43 #include <sys/ddi_intr.h>
44 #include <sys/sunddi.h>
45 #include <sys/stream.h>
46 #include <sys/strsun.h>
47 #include <sys/pci.h>
48 #include <sys/ethernet.h>
49 #include <sys/vlan.h>
50 #include <sys/crc32.h>
51 #include <sys/mii.h>
52 #include <sys/mac.h>
53 #include <sys/mac_ether.h>
54 #include <sys/mac_provider.h>
55 
56 #include "efe.h"
57 
58 /* Autoconfiguration entry points */
59 static int	efe_attach(dev_info_t *, ddi_attach_cmd_t);
60 static int	efe_detach(dev_info_t *, ddi_detach_cmd_t);
61 static int	efe_quiesce(dev_info_t *);
62 
63 /* MII entry points */
64 static uint16_t	efe_mii_read(void *, uint8_t, uint8_t);
65 static void	efe_mii_write(void *, uint8_t, uint8_t, uint16_t);
66 static void	efe_mii_notify(void *, link_state_t);
67 
68 /* MAC entry points */
69 static int	efe_m_getstat(void *, uint_t, uint64_t *);
70 static int	efe_m_start(void *);
71 static void	efe_m_stop(void *);
72 static int	efe_m_setpromisc(void *, boolean_t);
73 static int	efe_m_multicst(void *, boolean_t, const uint8_t *);
74 static int	efe_m_unicst(void *, const uint8_t *);
75 static mblk_t	*efe_m_tx(void *, mblk_t *);
76 static int	efe_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
77     const void *);
78 static int	efe_m_getprop(void *, const char *, mac_prop_id_t, uint_t,
79     void *);
80 static void	efe_m_propinfo(void *, const char *, mac_prop_id_t,
81     mac_prop_info_handle_t);
82 
83 /* ISR/periodic callbacks */
84 static uint_t	efe_intr(caddr_t, caddr_t);
85 
86 /* Support functions */
87 static void		efe_init(efe_t *);
88 static void		efe_init_rx_ring(efe_t *);
89 static void		efe_init_tx_ring(efe_t *);
90 static void		efe_reset(efe_t *);
91 static void		efe_start(efe_t *);
92 static void		efe_stop(efe_t *);
93 static void		efe_stop_dma(efe_t *);
94 static inline void	efe_restart(efe_t *);
95 static int		efe_suspend(efe_t *);
96 static int		efe_resume(efe_t *);
97 
98 static efe_ring_t	*efe_ring_alloc(dev_info_t *, size_t);
99 static void		efe_ring_free(efe_ring_t **);
100 static efe_buf_t	*efe_buf_alloc(dev_info_t *, size_t);
101 static void		efe_buf_free(efe_buf_t **);
102 
103 static void		efe_intr_enable(efe_t *);
104 static void		efe_intr_disable(efe_t *);
105 
106 static mblk_t		*efe_recv(efe_t *);
107 static mblk_t		*efe_recv_pkt(efe_t *, efe_desc_t *);
108 
109 static int		efe_send(efe_t *, mblk_t *);
110 static void		efe_send_done(efe_t *);
111 
112 static void		efe_getaddr(efe_t *, uint8_t *);
113 static void		efe_setaddr(efe_t *, uint8_t *);
114 static void		efe_setmchash(efe_t *, uint16_t *);
115 
116 static void		efe_eeprom_read(efe_t *, uint8_t *, size_t, uint8_t);
117 static uint16_t		efe_eeprom_readw(efe_t *, int, uint8_t);
118 static inline int	efe_eeprom_readbit(efe_t *);
119 static inline void	efe_eeprom_writebit(efe_t *, int);
120 
121 static void		efe_dprintf(dev_info_t *, int, const char *, ...);
122 
123 #ifdef DEBUG
124 #define	efe_debug(dip, ...) \
125 	efe_dprintf((dip), CE_CONT, __VA_ARGS__)
126 #else
127 #define	efe_debug(dip, ...)	/*EMPTY*/
128 #endif
129 
130 #define	efe_error(dip, ...) \
131 	efe_dprintf((dip), CE_WARN, __VA_ARGS__)
132 
133 extern struct mod_ops mod_driverops;
134 
135 DDI_DEFINE_STREAM_OPS(efe_dev_ops, nulldev, nulldev, efe_attach, efe_detach,
136     nodev, NULL, D_MP, NULL, efe_quiesce);
137 
138 static struct modldrv modldrv = {
139 	&mod_driverops,			/* drv_modops */
140 	"EPIC/100 Fast Ethernet",	/* drv_linkinfo */
141 	&efe_dev_ops			/* drv_dev_ops */
142 };
143 
144 static struct modlinkage modlinkage = {
145 	MODREV_1,		/* ml_rev */
146 	{ &modldrv, NULL }	/* ml_linkage */
147 };
148 
149 static ddi_device_acc_attr_t efe_regs_acc_attr = {
150 	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
151 	DDI_STRUCTURE_LE_ACC,	/* devacc_attr_endian_flags */
152 	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
153 };
154 
155 static ddi_device_acc_attr_t efe_buf_acc_attr = {
156 	DDI_DEVICE_ATTR_V0,	/* devacc_attr_version */
157 	DDI_NEVERSWAP_ACC,	/* devacc_attr_endian_flags */
158 	DDI_STRICTORDER_ACC	/* devacc_attr_dataorder */
159 };
160 
161 static ddi_dma_attr_t efe_dma_attr = {
162 	DMA_ATTR_V0,		/* dma_attr_version */
163 	0,			/* dma_attr_addr_lo */
164 	0xFFFFFFFFUL,		/* dma_attr_addr_hi */
165 	0x7FFFFFFFUL,		/* dma_attr_count_max */
166 	4,			/* dma_attr_align */
167 	0x7F,			/* dma_attr_burstsizes */
168 	1,			/* dma_attr_minxfer */
169 	0xFFFFFFFFUL,		/* dma_attr_maxxfer */
170 	0xFFFFFFFFUL,		/* dma_attr_seg */
171 	1,			/* dma_attr_sgllen */
172 	1,			/* dma_attr_granular */
173 	0			/* dma_attr_flags */
174 };
175 
176 static mii_ops_t efe_mii_ops = {
177 	MII_OPS_VERSION,	/* mii_version */
178 	efe_mii_read,		/* mii_read */
179 	efe_mii_write,		/* mii_write */
180 	efe_mii_notify		/* mii_notify */
181 };
182 
183 static mac_callbacks_t efe_m_callbacks = {
184 	MC_SETPROP | MC_GETPROP,	/* mc_callbacks */
185 	efe_m_getstat,			/* mc_getstat */
186 	efe_m_start,			/* mc_start */
187 	efe_m_stop,			/* mc_stop */
188 	efe_m_setpromisc,		/* mc_setpromisc */
189 	efe_m_multicst,			/* mc_multicst */
190 	efe_m_unicst,			/* mc_unicst */
191 	efe_m_tx,			/* mc_tx */
192 	NULL,				/* mc_reserved */
193 	NULL,				/* mc_ioctl */
194 	NULL,				/* mc_getcapab */
195 	NULL,				/* mc_open */
196 	NULL,				/* mc_close */
197 	efe_m_setprop,			/* mc_setprop */
198 	efe_m_getprop,			/* mc_getprop */
199 	efe_m_propinfo			/* mc_propinfo */
200 };
201 
202 static uint8_t efe_broadcast[] = {
203 	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
204 };
205 
206 static uint16_t efe_mchash_promisc[] = {
207 	0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
208 };
209 
210 /*
211  * Loadable module entry points.
212  */
213 int
_init(void)214 _init(void)
215 {
216 	int error;
217 
218 	mac_init_ops(&efe_dev_ops, "efe");
219 	if ((error = mod_install(&modlinkage)) != DDI_SUCCESS) {
220 		mac_fini_ops(&efe_dev_ops);
221 	}
222 
223 	return (error);
224 }
225 
226 int
_fini(void)227 _fini(void)
228 {
229 	int error;
230 
231 	if ((error = mod_remove(&modlinkage)) == DDI_SUCCESS) {
232 		mac_fini_ops(&efe_dev_ops);
233 	}
234 
235 	return (error);
236 }
237 
238 int
_info(struct modinfo * modinfop)239 _info(struct modinfo *modinfop)
240 {
241 	return (mod_info(&modlinkage, modinfop));
242 }
243 
244 /*
245  * Autoconfiguration entry points.
246  */
247 int
efe_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)248 efe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
249 {
250 	ddi_acc_handle_t pci;
251 	int types;
252 	int count;
253 	int actual;
254 	uint_t pri;
255 	efe_t *efep;
256 	mac_register_t *macp;
257 
258 	switch (cmd) {
259 	case DDI_ATTACH:
260 		break;
261 
262 	case DDI_RESUME:
263 		efep = ddi_get_driver_private(dip);
264 		return (efe_resume(efep));
265 
266 	default:
267 		return (DDI_FAILURE);
268 	}
269 
270 	/*
271 	 * PCI configuration.
272 	 */
273 	if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
274 		efe_error(dip, "unable to setup PCI configuration!");
275 		return (DDI_FAILURE);
276 	}
277 
278 	pci_config_put16(pci, PCI_CONF_COMM,
279 	    pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME);
280 
281 	pci_config_teardown(&pci);
282 
283 	if (ddi_intr_get_supported_types(dip, &types)
284 	    != DDI_SUCCESS || !(types & DDI_INTR_TYPE_FIXED)) {
285 		efe_error(dip, "fixed interrupts not supported!");
286 		return (DDI_FAILURE);
287 	}
288 
289 	if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count)
290 	    != DDI_SUCCESS || count != 1) {
291 		efe_error(dip, "no fixed interrupts available!");
292 		return (DDI_FAILURE);
293 	}
294 
295 	/*
296 	 * Initialize soft state.
297 	 */
298 	efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP);
299 	ddi_set_driver_private(dip, efep);
300 
301 	efep->efe_dip = dip;
302 
303 	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&efep->efe_regs, 0, 0,
304 	    &efe_regs_acc_attr, &efep->efe_regs_acch) != DDI_SUCCESS) {
305 		efe_error(dip, "unable to setup register mapping!");
306 		goto failure;
307 	}
308 
309 	efep->efe_rx_ring = efe_ring_alloc(efep->efe_dip, RXDESCL);
310 	if (efep->efe_rx_ring == NULL) {
311 		efe_error(efep->efe_dip, "unable to allocate rx ring!");
312 		goto failure;
313 	}
314 
315 	efep->efe_tx_ring = efe_ring_alloc(efep->efe_dip, TXDESCL);
316 	if (efep->efe_tx_ring == NULL) {
317 		efe_error(efep->efe_dip, "unable to allocate tx ring!");
318 		goto failure;
319 	}
320 
321 	if (ddi_intr_alloc(dip, &efep->efe_intrh, DDI_INTR_TYPE_FIXED, 0,
322 	    count, &actual, DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS ||
323 	    actual != count) {
324 		efe_error(dip, "unable to allocate fixed interrupt!");
325 		goto failure;
326 	}
327 
328 	if (ddi_intr_get_pri(efep->efe_intrh, &pri) != DDI_SUCCESS ||
329 	    pri >= ddi_intr_get_hilevel_pri()) {
330 		efe_error(dip, "unable to get valid interrupt priority!");
331 		goto failure;
332 	}
333 
334 	mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER,
335 	    DDI_INTR_PRI(pri));
336 
337 	mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER,
338 	    DDI_INTR_PRI(pri));
339 
340 	/*
341 	 * Initialize device.
342 	 */
343 	mutex_enter(&efep->efe_intrlock);
344 	mutex_enter(&efep->efe_txlock);
345 
346 	efe_reset(efep);
347 
348 	mutex_exit(&efep->efe_txlock);
349 	mutex_exit(&efep->efe_intrlock);
350 
351 	/* Use factory address as default */
352 	efe_getaddr(efep, efep->efe_macaddr);
353 
354 	/*
355 	 * Enable the ISR.
356 	 */
357 	if (ddi_intr_add_handler(efep->efe_intrh, efe_intr, efep, NULL)
358 	    != DDI_SUCCESS) {
359 		efe_error(dip, "unable to add interrupt handler!");
360 		goto failure;
361 	}
362 
363 	if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) {
364 		efe_error(dip, "unable to enable interrupt!");
365 		goto failure;
366 	}
367 
368 	/*
369 	 * Allocate MII resources.
370 	 */
371 	if ((efep->efe_miih = mii_alloc(efep, dip, &efe_mii_ops)) == NULL) {
372 		efe_error(dip, "unable to allocate mii resources!");
373 		goto failure;
374 	}
375 
376 	/*
377 	 * Allocate MAC resources.
378 	 */
379 	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
380 		efe_error(dip, "unable to allocate mac resources!");
381 		goto failure;
382 	}
383 
384 	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
385 	macp->m_driver = efep;
386 	macp->m_dip = dip;
387 	macp->m_src_addr = efep->efe_macaddr;
388 	macp->m_callbacks = &efe_m_callbacks;
389 	macp->m_min_sdu = 0;
390 	macp->m_max_sdu = ETHERMTU;
391 	macp->m_margin = VLAN_TAGSZ;
392 
393 	if (mac_register(macp, &efep->efe_mh) != 0) {
394 		efe_error(dip, "unable to register with mac!");
395 		goto failure;
396 	}
397 	mac_free(macp);
398 
399 	ddi_report_dev(dip);
400 
401 	return (DDI_SUCCESS);
402 
403 failure:
404 	if (macp != NULL) {
405 		mac_free(macp);
406 	}
407 
408 	if (efep->efe_miih != NULL) {
409 		mii_free(efep->efe_miih);
410 	}
411 
412 	if (efep->efe_intrh != NULL) {
413 		(void) ddi_intr_disable(efep->efe_intrh);
414 		(void) ddi_intr_remove_handler(efep->efe_intrh);
415 		(void) ddi_intr_free(efep->efe_intrh);
416 	}
417 
418 	mutex_destroy(&efep->efe_txlock);
419 	mutex_destroy(&efep->efe_intrlock);
420 
421 	if (efep->efe_tx_ring != NULL) {
422 		efe_ring_free(&efep->efe_tx_ring);
423 	}
424 	if (efep->efe_rx_ring != NULL) {
425 		efe_ring_free(&efep->efe_rx_ring);
426 	}
427 
428 	if (efep->efe_regs_acch != NULL) {
429 		ddi_regs_map_free(&efep->efe_regs_acch);
430 	}
431 
432 	kmem_free(efep, sizeof (efe_t));
433 
434 	return (DDI_FAILURE);
435 }
436 
437 int
efe_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)438 efe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
439 {
440 	efe_t *efep = ddi_get_driver_private(dip);
441 
442 	switch (cmd) {
443 	case DDI_DETACH:
444 		break;
445 
446 	case DDI_SUSPEND:
447 		return (efe_suspend(efep));
448 
449 	default:
450 		return (DDI_FAILURE);
451 	}
452 
453 	if (mac_unregister(efep->efe_mh) != 0) {
454 		efe_error(dip, "unable to unregister from mac!");
455 		return (DDI_FAILURE);
456 	}
457 
458 	mii_free(efep->efe_miih);
459 
460 	(void) ddi_intr_disable(efep->efe_intrh);
461 	(void) ddi_intr_remove_handler(efep->efe_intrh);
462 	(void) ddi_intr_free(efep->efe_intrh);
463 
464 	mutex_destroy(&efep->efe_txlock);
465 	mutex_destroy(&efep->efe_intrlock);
466 
467 	if (efep->efe_tx_ring != NULL) {
468 		efe_ring_free(&efep->efe_tx_ring);
469 	}
470 	if (efep->efe_rx_ring != NULL) {
471 		efe_ring_free(&efep->efe_rx_ring);
472 	}
473 
474 	ddi_regs_map_free(&efep->efe_regs_acch);
475 
476 	kmem_free(efep, sizeof (efe_t));
477 
478 	return (DDI_SUCCESS);
479 }
480 
481 int
efe_quiesce(dev_info_t * dip)482 efe_quiesce(dev_info_t *dip)
483 {
484 	efe_t *efep = ddi_get_driver_private(dip);
485 
486 	PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
487 	drv_usecwait(RESET_DELAY);
488 
489 	PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
490 
491 	return (DDI_SUCCESS);
492 }
493 
494 /*
495  * MII entry points.
496  */
497 uint16_t
efe_mii_read(void * arg,uint8_t phy,uint8_t reg)498 efe_mii_read(void *arg, uint8_t phy, uint8_t reg)
499 {
500 	efe_t *efep = arg;
501 
502 	PUTCSR(efep, CSR_MMCTL, MMCTL_READ |
503 	    reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
504 
505 	for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
506 		if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_READ)) {
507 			return ((uint16_t)GETCSR(efep, CSR_MMDATA));
508 		}
509 		drv_usecwait(MII_DELAY);
510 	}
511 	efe_error(efep->efe_dip, "timed out reading from MII!");
512 
513 	return (0);
514 }
515 
516 void
efe_mii_write(void * arg,uint8_t phy,uint8_t reg,uint16_t data)517 efe_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
518 {
519 	efe_t *efep = arg;
520 
521 	PUTCSR(efep, CSR_MMDATA, data);
522 
523 	PUTCSR(efep, CSR_MMCTL, MMCTL_WRITE |
524 	    reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
525 
526 	for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
527 		if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_WRITE)) {
528 			return;
529 		}
530 		drv_usecwait(MII_DELAY);
531 	}
532 	efe_error(efep->efe_dip, "timed out writing to MII!");
533 }
534 
535 void
efe_mii_notify(void * arg,link_state_t link)536 efe_mii_notify(void *arg, link_state_t link)
537 {
538 	efe_t *efep = arg;
539 
540 	mac_link_update(efep->efe_mh, link);
541 }
542 
543 /*
544  * MAC entry points.
545  */
546 int
efe_m_getstat(void * arg,uint_t stat,uint64_t * val)547 efe_m_getstat(void *arg, uint_t stat, uint64_t *val)
548 {
549 	efe_t *efep = arg;
550 
551 	if (mii_m_getstat(efep->efe_miih, stat, val) == 0) {
552 		return (0);
553 	}
554 
555 	switch (stat) {
556 	case MAC_STAT_MULTIRCV:
557 		*val = efep->efe_multircv;
558 		break;
559 
560 	case MAC_STAT_BRDCSTRCV:
561 		*val = efep->efe_brdcstrcv;
562 		break;
563 
564 	case MAC_STAT_MULTIXMT:
565 		*val = efep->efe_multixmt;
566 		break;
567 
568 	case MAC_STAT_BRDCSTXMT:
569 		*val = efep->efe_brdcstxmt;
570 		break;
571 
572 	case MAC_STAT_NORCVBUF:
573 		*val = efep->efe_norcvbuf;
574 		break;
575 
576 	case MAC_STAT_IERRORS:
577 		*val = efep->efe_ierrors;
578 		break;
579 
580 	case MAC_STAT_NOXMTBUF:
581 		*val = efep->efe_noxmtbuf;
582 		break;
583 
584 	case MAC_STAT_OERRORS:
585 		*val = efep->efe_oerrors;
586 		break;
587 
588 	case MAC_STAT_COLLISIONS:
589 		*val = efep->efe_collisions;
590 		break;
591 
592 	case MAC_STAT_RBYTES:
593 		*val = efep->efe_rbytes;
594 		break;
595 
596 	case MAC_STAT_IPACKETS:
597 		*val = efep->efe_ipackets;
598 		break;
599 
600 	case MAC_STAT_OBYTES:
601 		*val = efep->efe_obytes;
602 		break;
603 
604 	case MAC_STAT_OPACKETS:
605 		*val = efep->efe_opackets;
606 		break;
607 
608 	case MAC_STAT_UNDERFLOWS:
609 		*val = efep->efe_uflo;
610 		break;
611 
612 	case MAC_STAT_OVERFLOWS:
613 		*val = efep->efe_oflo;
614 		break;
615 
616 	case ETHER_STAT_ALIGN_ERRORS:
617 		*val = efep->efe_align_errors;
618 		break;
619 
620 	case ETHER_STAT_FCS_ERRORS:
621 		*val = efep->efe_fcs_errors;
622 		break;
623 
624 	case ETHER_STAT_FIRST_COLLISIONS:
625 		*val = efep->efe_first_collisions;
626 		break;
627 
628 	case ETHER_STAT_TX_LATE_COLLISIONS:
629 		*val = efep->efe_tx_late_collisions;
630 		break;
631 
632 	case ETHER_STAT_DEFER_XMTS:
633 		*val = efep->efe_defer_xmts;
634 		break;
635 
636 	case ETHER_STAT_EX_COLLISIONS:
637 		*val = efep->efe_ex_collisions;
638 		break;
639 
640 	case ETHER_STAT_MACXMT_ERRORS:
641 		*val = efep->efe_macxmt_errors;
642 		break;
643 
644 	case ETHER_STAT_CARRIER_ERRORS:
645 		*val = efep->efe_carrier_errors;
646 		break;
647 
648 	case ETHER_STAT_TOOLONG_ERRORS:
649 		*val = efep->efe_toolong_errors;
650 		break;
651 
652 	case ETHER_STAT_MACRCV_ERRORS:
653 		*val = efep->efe_macrcv_errors;
654 		break;
655 
656 	case ETHER_STAT_TOOSHORT_ERRORS:
657 		*val = efep->efe_runt_errors;
658 		break;
659 
660 	case ETHER_STAT_JABBER_ERRORS:
661 		*val = efep->efe_jabber_errors;
662 		break;
663 
664 	default:
665 		return (ENOTSUP);
666 	}
667 
668 	return (0);
669 }
670 
671 int
efe_m_start(void * arg)672 efe_m_start(void *arg)
673 {
674 	efe_t *efep = arg;
675 
676 	mutex_enter(&efep->efe_intrlock);
677 	mutex_enter(&efep->efe_txlock);
678 
679 	efe_start(efep);
680 	efep->efe_flags |= FLAG_RUNNING;
681 
682 	mutex_exit(&efep->efe_txlock);
683 	mutex_exit(&efep->efe_intrlock);
684 
685 	mii_start(efep->efe_miih);
686 
687 	return (0);
688 }
689 
690 void
efe_m_stop(void * arg)691 efe_m_stop(void *arg)
692 {
693 	efe_t *efep = arg;
694 
695 	mutex_enter(&efep->efe_intrlock);
696 	mutex_enter(&efep->efe_txlock);
697 
698 	efe_stop(efep);
699 	efep->efe_flags &= ~FLAG_RUNNING;
700 
701 	mutex_exit(&efep->efe_txlock);
702 	mutex_exit(&efep->efe_intrlock);
703 
704 	mii_stop(efep->efe_miih);
705 }
706 
707 int
efe_m_setpromisc(void * arg,boolean_t on)708 efe_m_setpromisc(void *arg, boolean_t on)
709 {
710 	efe_t *efep = arg;
711 
712 	mutex_enter(&efep->efe_intrlock);
713 	mutex_enter(&efep->efe_txlock);
714 
715 	if (efep->efe_flags & FLAG_SUSPENDED) {
716 		mutex_exit(&efep->efe_txlock);
717 		mutex_exit(&efep->efe_intrlock);
718 		return (0);
719 	}
720 
721 	efep->efe_promisc = on;
722 
723 	if (efep->efe_flags & FLAG_RUNNING) {
724 		efe_restart(efep);
725 	}
726 
727 	mutex_exit(&efep->efe_txlock);
728 	mutex_exit(&efep->efe_intrlock);
729 
730 	return (0);
731 }
732 
733 int
efe_m_multicst(void * arg,boolean_t add,const uint8_t * macaddr)734 efe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
735 {
736 	efe_t *efep = arg;
737 	uint32_t val;
738 	int index;
739 	int bit;
740 	boolean_t restart = B_FALSE;
741 
742 	mutex_enter(&efep->efe_intrlock);
743 	mutex_enter(&efep->efe_txlock);
744 
745 	if (efep->efe_flags & FLAG_SUSPENDED) {
746 		mutex_exit(&efep->efe_txlock);
747 		mutex_exit(&efep->efe_intrlock);
748 		return (0);
749 	}
750 
751 	CRC32(val, macaddr, ETHERADDRL, -1U, crc32_table);
752 	val %= MCHASHL;
753 
754 	index = val / MCHASHSZ;
755 	bit = 1U << (val % MCHASHSZ);
756 
757 	if (add) {
758 		efep->efe_mccount[val]++;
759 		if (efep->efe_mccount[val] == 1) {
760 			efep->efe_mchash[index] |= bit;
761 			restart = B_TRUE;
762 		}
763 
764 	} else {
765 		efep->efe_mccount[val]--;
766 		if (efep->efe_mccount[val] == 0) {
767 			efep->efe_mchash[index] &= ~bit;
768 			restart = B_TRUE;
769 		}
770 	}
771 
772 	if (restart && efep->efe_flags & FLAG_RUNNING) {
773 		efe_restart(efep);
774 	}
775 
776 	mutex_exit(&efep->efe_txlock);
777 	mutex_exit(&efep->efe_intrlock);
778 
779 	return (0);
780 }
781 
782 int
efe_m_unicst(void * arg,const uint8_t * macaddr)783 efe_m_unicst(void *arg, const uint8_t *macaddr)
784 {
785 	efe_t *efep = arg;
786 
787 	mutex_enter(&efep->efe_intrlock);
788 	mutex_enter(&efep->efe_txlock);
789 
790 	if (efep->efe_flags & FLAG_SUSPENDED) {
791 		mutex_exit(&efep->efe_txlock);
792 		mutex_exit(&efep->efe_intrlock);
793 		return (0);
794 	}
795 
796 	bcopy(macaddr, efep->efe_macaddr, ETHERADDRL);
797 
798 	if (efep->efe_flags & FLAG_RUNNING) {
799 		efe_restart(efep);
800 	}
801 
802 	mutex_exit(&efep->efe_txlock);
803 	mutex_exit(&efep->efe_intrlock);
804 
805 	return (0);
806 }
807 
808 mblk_t *
efe_m_tx(void * arg,mblk_t * mp)809 efe_m_tx(void *arg, mblk_t *mp)
810 {
811 	efe_t *efep = arg;
812 
813 	mutex_enter(&efep->efe_txlock);
814 
815 	if (efep->efe_flags & FLAG_SUSPENDED) {
816 		mutex_exit(&efep->efe_txlock);
817 		return (mp);
818 	}
819 
820 	while (mp != NULL) {
821 		mblk_t *tmp = mp->b_next;
822 		mp->b_next = NULL;
823 
824 		if (efe_send(efep, mp) != DDI_SUCCESS) {
825 			mp->b_next = tmp;
826 			break;
827 		}
828 		mp = tmp;
829 	}
830 
831 	/* Kick the transmitter */
832 	PUTCSR(efep, CSR_COMMAND, COMMAND_TXQUEUED);
833 
834 	mutex_exit(&efep->efe_txlock);
835 
836 	return (mp);
837 }
838 
839 int
efe_m_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t valsize,const void * val)840 efe_m_setprop(void *arg, const char *name, mac_prop_id_t id,
841     uint_t valsize, const void *val)
842 {
843 	efe_t *efep = arg;
844 
845 	return (mii_m_setprop(efep->efe_miih, name, id, valsize, val));
846 }
847 
848 int
efe_m_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t valsize,void * val)849 efe_m_getprop(void *arg, const char *name, mac_prop_id_t id,
850     uint_t valsize, void *val)
851 {
852 	efe_t *efep = arg;
853 
854 	return (mii_m_getprop(efep->efe_miih, name, id, valsize, val));
855 }
856 
857 void
efe_m_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t state)858 efe_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
859     mac_prop_info_handle_t state)
860 {
861 	efe_t *efep = arg;
862 
863 	mii_m_propinfo(efep->efe_miih, name, id, state);
864 }
865 
866 /*
867  * ISR/periodic callbacks.
868  */
869 uint_t
efe_intr(caddr_t arg1,caddr_t arg2)870 efe_intr(caddr_t arg1, caddr_t arg2)
871 {
872 	efe_t *efep = (void *)arg1;
873 	uint32_t status;
874 	mblk_t *mp = NULL;
875 
876 	_NOTE(ARGUNUSED(arg2));
877 
878 	mutex_enter(&efep->efe_intrlock);
879 
880 	if (efep->efe_flags & FLAG_SUSPENDED) {
881 		mutex_exit(&efep->efe_intrlock);
882 		return (DDI_INTR_UNCLAIMED);
883 	}
884 
885 	status = GETCSR(efep, CSR_INTSTAT);
886 	if (!(status & INTSTAT_ACTV)) {
887 		mutex_exit(&efep->efe_intrlock);
888 		return (DDI_INTR_UNCLAIMED);
889 	}
890 	PUTCSR(efep, CSR_INTSTAT, status);
891 
892 	if (status & INTSTAT_RCC) {
893 		mp = efe_recv(efep);
894 	}
895 
896 	if (status & INTSTAT_RQE) {
897 		efep->efe_ierrors++;
898 		efep->efe_macrcv_errors++;
899 
900 		/* Kick the receiver */
901 		PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED);
902 	}
903 
904 	if (status & INTSTAT_TXC) {
905 		mutex_enter(&efep->efe_txlock);
906 
907 		efe_send_done(efep);
908 
909 		mutex_exit(&efep->efe_txlock);
910 	}
911 
912 	if (status & INTSTAT_FATAL) {
913 		mutex_enter(&efep->efe_txlock);
914 
915 		efe_error(efep->efe_dip, "bus error; resetting!");
916 		efe_restart(efep);
917 
918 		mutex_exit(&efep->efe_txlock);
919 	}
920 
921 	mutex_exit(&efep->efe_intrlock);
922 
923 	if (mp != NULL) {
924 		mac_rx(efep->efe_mh, NULL, mp);
925 	}
926 
927 	if (status & INTSTAT_TXC) {
928 		mac_tx_update(efep->efe_mh);
929 	}
930 
931 	if (status & INTSTAT_FATAL) {
932 		mii_reset(efep->efe_miih);
933 	}
934 
935 	return (DDI_INTR_CLAIMED);
936 }
937 
938 /*
939  * Support functions.
940  */
941 void
efe_init(efe_t * efep)942 efe_init(efe_t *efep)
943 {
944 	uint32_t val;
945 
946 	ASSERT(mutex_owned(&efep->efe_intrlock));
947 	ASSERT(mutex_owned(&efep->efe_txlock));
948 
949 	efe_reset(efep);
950 
951 	val = GENCTL_ONECOPY | GENCTL_RFT_128 | GENCTL_MRM;
952 #ifdef _BIG_ENDIAN
953 	val |= GENCTL_BE;
954 #endif	/* _BIG_ENDIAN */
955 
956 	PUTCSR(efep, CSR_GENCTL, val);
957 	PUTCSR(efep, CSR_PBLCNT, BURSTLEN);
958 
959 	efe_init_rx_ring(efep);
960 	efe_init_tx_ring(efep);
961 
962 	efe_setaddr(efep, efep->efe_macaddr);
963 
964 	if (efep->efe_promisc) {
965 		efe_setmchash(efep, efe_mchash_promisc);
966 	} else {
967 		efe_setmchash(efep, efep->efe_mchash);
968 	}
969 }
970 
971 void
efe_init_rx_ring(efe_t * efep)972 efe_init_rx_ring(efe_t *efep)
973 {
974 	efe_ring_t *rp;
975 
976 	ASSERT(mutex_owned(&efep->efe_intrlock));
977 
978 	rp = efep->efe_rx_ring;
979 
980 	for (int i = 0; i < DESCLEN(rp); ++i) {
981 		efe_desc_t *dp = GETDESC(rp, i);
982 		efe_buf_t *bp = GETBUF(rp, i);
983 
984 		PUTDESC16(rp, &dp->d_status, RXSTAT_OWNER);
985 		PUTDESC16(rp, &dp->d_len, 0);
986 		PUTDESC32(rp, &dp->d_bufaddr, BUFADDR(bp));
987 		PUTDESC16(rp, &dp->d_buflen, BUFLEN(bp));
988 		PUTDESC16(rp, &dp->d_control, 0);
989 		PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
990 
991 		SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
992 	}
993 
994 	efep->efe_rx_desc = 0;
995 
996 	PUTCSR(efep, CSR_PRCDAR, DESCADDR(rp, 0));
997 }
998 
999 void
efe_init_tx_ring(efe_t * efep)1000 efe_init_tx_ring(efe_t *efep)
1001 {
1002 	efe_ring_t *rp;
1003 
1004 	ASSERT(mutex_owned(&efep->efe_txlock));
1005 
1006 	rp = efep->efe_tx_ring;
1007 
1008 	for (int i = 0; i < DESCLEN(rp); ++i) {
1009 		efe_desc_t *dp = GETDESC(rp, i);
1010 		efe_buf_t *bp = GETBUF(rp, i);
1011 
1012 		PUTDESC16(rp, &dp->d_status, 0);
1013 		PUTDESC16(rp, &dp->d_len, 0);
1014 		PUTDESC32(rp, &dp->d_bufaddr, BUFADDR(bp));
1015 		PUTDESC16(rp, &dp->d_buflen, BUFLEN(bp));
1016 		PUTDESC16(rp, &dp->d_control, 0);
1017 		PUTDESC32(rp, &dp->d_next, NEXTDESCADDR(rp, i));
1018 
1019 		SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
1020 	}
1021 
1022 	efep->efe_tx_desc = 0;
1023 	efep->efe_tx_sent = 0;
1024 
1025 	PUTCSR(efep, CSR_PTCDAR, DESCADDR(rp, 0));
1026 }
1027 
1028 void
efe_reset(efe_t * efep)1029 efe_reset(efe_t *efep)
1030 {
1031 	ASSERT(mutex_owned(&efep->efe_intrlock));
1032 	ASSERT(mutex_owned(&efep->efe_txlock));
1033 
1034 	PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
1035 	drv_usecwait(RESET_DELAY);
1036 
1037 	/* Assert internal clock source (AN 7.15) */
1038 	for (int i = 0; i < RESET_TEST_CYCLES; ++i) {
1039 		PUTCSR(efep, CSR_TEST, TEST_CLOCK);
1040 	}
1041 }
1042 
1043 void
efe_start(efe_t * efep)1044 efe_start(efe_t *efep)
1045 {
1046 	ASSERT(mutex_owned(&efep->efe_intrlock));
1047 	ASSERT(mutex_owned(&efep->efe_txlock));
1048 
1049 	efe_init(efep);
1050 
1051 	PUTCSR(efep, CSR_RXCON,
1052 	    RXCON_SEP | RXCON_RRF | RXCON_RBF | RXCON_RMF |
1053 	    (efep->efe_promisc ? RXCON_PROMISC : 0));
1054 
1055 	PUTCSR(efep, CSR_TXCON, TXCON_LB_3);
1056 
1057 	efe_intr_enable(efep);
1058 
1059 	SETBIT(efep, CSR_COMMAND,
1060 	    COMMAND_START_RX | COMMAND_RXQUEUED);
1061 }
1062 
1063 void
efe_stop(efe_t * efep)1064 efe_stop(efe_t *efep)
1065 {
1066 	ASSERT(mutex_owned(&efep->efe_intrlock));
1067 	ASSERT(mutex_owned(&efep->efe_txlock));
1068 
1069 	efe_intr_disable(efep);
1070 
1071 	PUTCSR(efep, CSR_COMMAND, COMMAND_STOP_RX);
1072 
1073 	efe_stop_dma(efep);
1074 
1075 	PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
1076 	drv_usecwait(RESET_DELAY);
1077 
1078 	PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
1079 }
1080 
1081 void
efe_stop_dma(efe_t * efep)1082 efe_stop_dma(efe_t *efep)
1083 {
1084 	ASSERT(mutex_owned(&efep->efe_intrlock));
1085 	ASSERT(mutex_owned(&efep->efe_txlock));
1086 
1087 	PUTCSR(efep, CSR_COMMAND,
1088 	    COMMAND_STOP_RDMA | COMMAND_STOP_TDMA);
1089 
1090 	for (int i = 0; i < STOP_DELAY_CYCLES; ++i) {
1091 		uint32_t status = GETCSR(efep, CSR_INTSTAT);
1092 		if (status & INTSTAT_RXIDLE &&
1093 		    status & INTSTAT_TXIDLE) {
1094 			return;
1095 		}
1096 		drv_usecwait(STOP_DELAY);
1097 	}
1098 	efe_error(efep->efe_dip, "timed out stopping DMA engine!");
1099 }
1100 
1101 static inline void
efe_restart(efe_t * efep)1102 efe_restart(efe_t *efep)
1103 {
1104 	efe_stop(efep);
1105 	efe_start(efep);
1106 }
1107 
1108 int
efe_suspend(efe_t * efep)1109 efe_suspend(efe_t *efep)
1110 {
1111 	mutex_enter(&efep->efe_intrlock);
1112 	mutex_enter(&efep->efe_txlock);
1113 
1114 	if (efep->efe_flags & FLAG_RUNNING) {
1115 		efe_stop(efep);
1116 	}
1117 	efep->efe_flags |= FLAG_SUSPENDED;
1118 
1119 	mutex_exit(&efep->efe_txlock);
1120 	mutex_exit(&efep->efe_intrlock);
1121 
1122 	mii_suspend(efep->efe_miih);
1123 
1124 	return (DDI_SUCCESS);
1125 }
1126 
1127 int
efe_resume(efe_t * efep)1128 efe_resume(efe_t *efep)
1129 {
1130 	mutex_enter(&efep->efe_intrlock);
1131 	mutex_enter(&efep->efe_txlock);
1132 
1133 	if (efep->efe_flags & FLAG_RUNNING) {
1134 		efe_start(efep);
1135 	}
1136 	efep->efe_flags &= ~FLAG_SUSPENDED;
1137 
1138 	mutex_exit(&efep->efe_txlock);
1139 	mutex_exit(&efep->efe_intrlock);
1140 
1141 	mii_resume(efep->efe_miih);
1142 
1143 	return (DDI_SUCCESS);
1144 }
1145 
1146 efe_ring_t *
efe_ring_alloc(dev_info_t * dip,size_t len)1147 efe_ring_alloc(dev_info_t *dip, size_t len)
1148 {
1149 	efe_ring_t *rp;
1150 	size_t rlen;
1151 	uint_t ccount;
1152 
1153 	ASSERT(len > 1);
1154 
1155 	rp = kmem_zalloc(sizeof (efe_ring_t), KM_SLEEP);
1156 	rp->r_len = len;
1157 
1158 	if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
1159 	    &rp->r_dmah) != DDI_SUCCESS) {
1160 		efe_error(dip, "unable to allocate DMA handle!");
1161 		goto failure;
1162 	}
1163 
1164 	if (ddi_dma_mem_alloc(rp->r_dmah, DESCSZ(len), &efe_buf_acc_attr,
1165 	    DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&rp->r_descp,
1166 	    &rlen, &rp->r_acch) != DDI_SUCCESS) {
1167 		efe_error(dip, "unable to allocate descriptors!");
1168 		goto failure;
1169 	}
1170 
1171 	if (ddi_dma_addr_bind_handle(rp->r_dmah, NULL, (caddr_t)rp->r_descp,
1172 	    DESCSZ(len), DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
1173 	    NULL, &rp->r_dmac, &ccount) != DDI_DMA_MAPPED) {
1174 		efe_error(dip, "unable to bind DMA handle to descriptors!");
1175 		goto failure;
1176 	}
1177 
1178 	rp->r_bufpp = kmem_zalloc(BUFPSZ(len), KM_SLEEP);
1179 
1180 	for (int i = 0; i < len; ++i) {
1181 		efe_buf_t *bp = efe_buf_alloc(dip, BUFSZ);
1182 		if (bp == NULL) {
1183 			goto failure;
1184 		}
1185 		rp->r_bufpp[i] = bp;
1186 	}
1187 
1188 	return (rp);
1189 
1190 failure:
1191 	efe_ring_free(&rp);
1192 
1193 	return (NULL);
1194 }
1195 
1196 void
efe_ring_free(efe_ring_t ** rpp)1197 efe_ring_free(efe_ring_t **rpp)
1198 {
1199 	efe_ring_t *rp = *rpp;
1200 
1201 	ASSERT(rp != NULL);
1202 
1203 	for (int i = 0; i < DESCLEN(rp); ++i) {
1204 		efe_buf_t *bp = GETBUF(rp, i);
1205 		if (bp != NULL) {
1206 			efe_buf_free(&bp);
1207 		}
1208 	}
1209 	kmem_free(rp->r_bufpp, BUFPSZ(DESCLEN(rp)));
1210 
1211 	if (rp->r_descp != NULL) {
1212 		(void) ddi_dma_unbind_handle(rp->r_dmah);
1213 	}
1214 	if (rp->r_acch != NULL) {
1215 		ddi_dma_mem_free(&rp->r_acch);
1216 	}
1217 	if (rp->r_dmah != NULL) {
1218 		ddi_dma_free_handle(&rp->r_dmah);
1219 	}
1220 	kmem_free(rp, sizeof (efe_ring_t));
1221 
1222 	*rpp = NULL;
1223 }
1224 
1225 efe_buf_t *
efe_buf_alloc(dev_info_t * dip,size_t len)1226 efe_buf_alloc(dev_info_t *dip, size_t len)
1227 {
1228 	efe_buf_t *bp;
1229 	size_t rlen;
1230 	uint_t ccount;
1231 
1232 	bp = kmem_zalloc(sizeof (efe_buf_t), KM_SLEEP);
1233 	bp->b_len = len;
1234 
1235 	if (ddi_dma_alloc_handle(dip, &efe_dma_attr, DDI_DMA_SLEEP, NULL,
1236 	    &bp->b_dmah) != DDI_SUCCESS) {
1237 		efe_error(dip, "unable to allocate DMA handle!");
1238 		goto failure;
1239 	}
1240 
1241 	if (ddi_dma_mem_alloc(bp->b_dmah, len, &efe_buf_acc_attr,
1242 	    DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, &bp->b_kaddr, &rlen,
1243 	    &bp->b_acch) != DDI_SUCCESS) {
1244 		efe_error(dip, "unable to allocate buffer!");
1245 		goto failure;
1246 	}
1247 
1248 	if (ddi_dma_addr_bind_handle(bp->b_dmah, NULL, bp->b_kaddr,
1249 	    len, DDI_DMA_RDWR | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL,
1250 	    &bp->b_dmac, &ccount) != DDI_DMA_MAPPED) {
1251 		efe_error(dip, "unable to bind DMA handle to buffer!");
1252 		goto failure;
1253 	}
1254 
1255 	return (bp);
1256 
1257 failure:
1258 	efe_buf_free(&bp);
1259 
1260 	return (NULL);
1261 }
1262 
1263 void
efe_buf_free(efe_buf_t ** bpp)1264 efe_buf_free(efe_buf_t **bpp)
1265 {
1266 	efe_buf_t *bp = *bpp;
1267 
1268 	ASSERT(bp != NULL);
1269 
1270 	if (bp->b_kaddr != NULL) {
1271 		(void) ddi_dma_unbind_handle(bp->b_dmah);
1272 	}
1273 	if (bp->b_acch != NULL) {
1274 		ddi_dma_mem_free(&bp->b_acch);
1275 	}
1276 	if (bp->b_dmah != NULL) {
1277 		ddi_dma_free_handle(&bp->b_dmah);
1278 	}
1279 	kmem_free(bp, sizeof (efe_buf_t));
1280 
1281 	*bpp = NULL;
1282 }
1283 
1284 void
efe_intr_enable(efe_t * efep)1285 efe_intr_enable(efe_t *efep)
1286 {
1287 	PUTCSR(efep, CSR_INTMASK,
1288 	    INTMASK_RCC | INTMASK_RQE | INTMASK_TXC | INTMASK_FATAL);
1289 
1290 	SETBIT(efep, CSR_GENCTL, GENCTL_INT);
1291 }
1292 
1293 void
efe_intr_disable(efe_t * efep)1294 efe_intr_disable(efe_t *efep)
1295 {
1296 	PUTCSR(efep, CSR_INTMASK, 0);
1297 
1298 	CLRBIT(efep, CSR_GENCTL, GENCTL_INT);
1299 }
1300 
1301 mblk_t *
efe_recv(efe_t * efep)1302 efe_recv(efe_t *efep)
1303 {
1304 	efe_ring_t *rp;
1305 	mblk_t *mp = NULL;
1306 	mblk_t **mpp = &mp;
1307 
1308 	ASSERT(mutex_owned(&efep->efe_intrlock));
1309 
1310 	rp = efep->efe_rx_ring;
1311 
1312 	for (;;) {
1313 		efe_desc_t *dp;
1314 		uint16_t status;
1315 
1316 		dp = GETDESC(rp, efep->efe_rx_desc);
1317 		SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORKERNEL);
1318 
1319 		status = GETDESC16(rp, &dp->d_status);
1320 
1321 		/* Stop if device owns descriptor */
1322 		if (status & RXSTAT_OWNER) {
1323 			break;
1324 		}
1325 
1326 		if (status & RXSTAT_PRI) {
1327 			mblk_t *tmp = efe_recv_pkt(efep, dp);
1328 			if (tmp != NULL) {
1329 				*mpp = tmp;
1330 				mpp = &tmp->b_next;
1331 			}
1332 
1333 		} else {
1334 			efep->efe_ierrors++;
1335 
1336 			if (status & RXSTAT_FAE) {
1337 				efep->efe_align_errors++;
1338 			}
1339 			if (status & RXSTAT_CRC) {
1340 				efep->efe_fcs_errors++;
1341 			}
1342 			if (status & RXSTAT_MP) {
1343 				efep->efe_oflo++;
1344 			}
1345 		}
1346 
1347 		/* Release ownership to device */
1348 		PUTDESC16(rp, &dp->d_status, RXSTAT_OWNER);
1349 
1350 		SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORDEV);
1351 
1352 		efep->efe_rx_desc = NEXTDESC(rp, efep->efe_rx_desc);
1353 	}
1354 
1355 	return (mp);
1356 }
1357 
1358 mblk_t *
efe_recv_pkt(efe_t * efep,efe_desc_t * dp)1359 efe_recv_pkt(efe_t *efep, efe_desc_t *dp)
1360 {
1361 	efe_ring_t *rp;
1362 	efe_buf_t *bp;
1363 	uint16_t len;
1364 	mblk_t *mp;
1365 	uint16_t status;
1366 
1367 	ASSERT(mutex_owned(&efep->efe_intrlock));
1368 
1369 	rp = efep->efe_rx_ring;
1370 
1371 	len = GETDESC16(rp, &dp->d_len) - ETHERFCSL;
1372 
1373 	if (len < ETHERMIN) {
1374 		efep->efe_ierrors++;
1375 		efep->efe_runt_errors++;
1376 		return (NULL);
1377 	}
1378 
1379 	if (len > ETHERMAX + VLAN_TAGSZ) {
1380 		efep->efe_ierrors++;
1381 		efep->efe_toolong_errors++;
1382 		return (NULL);
1383 	}
1384 
1385 	mp = allocb(len, 0);
1386 	if (mp == NULL) {
1387 		efep->efe_ierrors++;
1388 		efep->efe_norcvbuf++;
1389 		return (NULL);
1390 	}
1391 	mp->b_wptr = mp->b_rptr + len;
1392 
1393 	bp = GETBUF(rp, efep->efe_rx_desc);
1394 	SYNCBUF(bp, DDI_DMA_SYNC_FORKERNEL);
1395 
1396 	bcopy(bp->b_kaddr, mp->b_rptr, len);
1397 
1398 	efep->efe_ipackets++;
1399 	efep->efe_rbytes += len;
1400 
1401 	status = GETDESC16(rp, &dp->d_status);
1402 
1403 	if (status & RXSTAT_BAR) {
1404 		efep->efe_brdcstrcv++;
1405 
1406 	} else if (status & RXSTAT_MAR) {
1407 		efep->efe_multircv++;
1408 	}
1409 
1410 	return (mp);
1411 }
1412 
1413 int
efe_send(efe_t * efep,mblk_t * mp)1414 efe_send(efe_t *efep, mblk_t *mp)
1415 {
1416 	efe_ring_t *rp;
1417 	uint16_t len;
1418 	efe_desc_t *dp;
1419 	uint16_t status;
1420 	efe_buf_t *bp;
1421 
1422 	ASSERT(mutex_owned(&efep->efe_txlock));
1423 
1424 	rp = efep->efe_tx_ring;
1425 
1426 	len = msgsize(mp);
1427 
1428 	if (len > ETHERMAX + VLAN_TAGSZ) {
1429 		efep->efe_oerrors++;
1430 		efep->efe_macxmt_errors++;
1431 		freemsg(mp);
1432 		return (DDI_SUCCESS);
1433 	}
1434 
1435 	dp = GETDESC(rp, efep->efe_tx_desc);
1436 	SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORKERNEL);
1437 
1438 	status = GETDESC16(efep->efe_tx_ring, &dp->d_status);
1439 
1440 	/* Stop if device owns descriptor */
1441 	if (status & TXSTAT_OWNER) {
1442 		return (DDI_FAILURE);
1443 	}
1444 
1445 	bp = GETBUF(rp, efep->efe_tx_desc);
1446 
1447 	mcopymsg(mp, bp->b_kaddr);
1448 
1449 	/*
1450 	 * Packets must contain at least ETHERMIN octets.
1451 	 * Padded octets are zeroed out prior to sending.
1452 	 */
1453 	if (len < ETHERMIN) {
1454 		bzero(bp->b_kaddr + len, ETHERMIN - len);
1455 		len = ETHERMIN;
1456 	}
1457 
1458 	SYNCBUF(bp, DDI_DMA_SYNC_FORDEV);
1459 
1460 	PUTDESC16(rp, &dp->d_status, TXSTAT_OWNER);
1461 	PUTDESC16(rp, &dp->d_len, len);
1462 	PUTDESC16(rp, &dp->d_control, TXCTL_LASTDESCR);
1463 
1464 	SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORDEV);
1465 
1466 	efep->efe_opackets++;
1467 	efep->efe_obytes += len;
1468 
1469 	if (*bp->b_kaddr & 0x01) {
1470 		if (bcmp(bp->b_kaddr, efe_broadcast, ETHERADDRL) == 0) {
1471 			efep->efe_brdcstxmt++;
1472 		} else {
1473 			efep->efe_multixmt++;
1474 		}
1475 	}
1476 
1477 	efep->efe_tx_desc = NEXTDESC(rp, efep->efe_tx_desc);
1478 
1479 	return (DDI_SUCCESS);
1480 }
1481 
1482 void
efe_send_done(efe_t * efep)1483 efe_send_done(efe_t *efep)
1484 {
1485 	efe_ring_t *rp;
1486 
1487 	ASSERT(mutex_owned(&efep->efe_txlock));
1488 
1489 	rp = efep->efe_tx_ring;
1490 
1491 	for (;;) {
1492 		efe_desc_t *dp;
1493 		uint16_t status;
1494 
1495 		dp = GETDESC(rp, efep->efe_tx_sent);
1496 		SYNCDESC(rp, efep->efe_tx_sent, DDI_DMA_SYNC_FORKERNEL);
1497 
1498 		status = GETDESC16(rp, &dp->d_status);
1499 
1500 		/* Stop if device owns descriptor */
1501 		if (status & TXSTAT_OWNER) {
1502 			break;
1503 		}
1504 
1505 		if (status & TXSTAT_PTX) {
1506 			if (!(status & TXSTAT_ND)) {
1507 				efep->efe_defer_xmts++;
1508 			}
1509 			if (status & TXSTAT_COLL) {
1510 				efep->efe_first_collisions++;
1511 			}
1512 
1513 		} else {
1514 			efep->efe_oerrors++;
1515 
1516 			if (status & TXSTAT_CSL) {
1517 				efep->efe_carrier_errors++;
1518 			}
1519 			if (status & TXSTAT_UFLO) {
1520 				efep->efe_uflo++;
1521 			}
1522 			if (status & TXSTAT_OWC) {
1523 				efep->efe_tx_late_collisions++;
1524 			}
1525 			if (status & TXSTAT_DEFER) {
1526 				efep->efe_jabber_errors++;
1527 			}
1528 			if (status & TXSTAT_EXCOLL) {
1529 				efep->efe_ex_collisions++;
1530 			}
1531 		}
1532 
1533 		efep->efe_collisions +=
1534 		    (status >> TXSTAT_CCNT) & TXSTAT_CCNTMASK;
1535 
1536 		efep->efe_tx_sent = NEXTDESC(rp, efep->efe_tx_sent);
1537 	}
1538 }
1539 
1540 void
efe_getaddr(efe_t * efep,uint8_t * macaddr)1541 efe_getaddr(efe_t *efep, uint8_t *macaddr)
1542 {
1543 	efe_eeprom_read(efep, macaddr, ETHERADDRL, 0x0);
1544 
1545 	efe_debug(efep->efe_dip,
1546 	    "factory address is %02x:%02x:%02x:%02x:%02x:%02x\n",
1547 	    macaddr[0], macaddr[1], macaddr[2], macaddr[3],
1548 	    macaddr[4], macaddr[5]);
1549 }
1550 
1551 void
efe_setaddr(efe_t * efep,uint8_t * macaddr)1552 efe_setaddr(efe_t *efep, uint8_t *macaddr)
1553 {
1554 	uint16_t val;
1555 
1556 	bcopy(macaddr, &val, sizeof (uint16_t));
1557 	PUTCSR(efep, CSR_LAN0, val);
1558 	macaddr += sizeof (uint16_t);
1559 
1560 	bcopy(macaddr, &val, sizeof (uint16_t));
1561 	PUTCSR(efep, CSR_LAN1, val);
1562 	macaddr += sizeof (uint16_t);
1563 
1564 	bcopy(macaddr, &val, sizeof (uint16_t));
1565 	PUTCSR(efep, CSR_LAN2, val);
1566 }
1567 
1568 void
efe_setmchash(efe_t * efep,uint16_t * mchash)1569 efe_setmchash(efe_t *efep, uint16_t *mchash)
1570 {
1571 	PUTCSR(efep, CSR_MC0, mchash[0]);
1572 	PUTCSR(efep, CSR_MC1, mchash[1]);
1573 	PUTCSR(efep, CSR_MC2, mchash[2]);
1574 	PUTCSR(efep, CSR_MC3, mchash[3]);
1575 }
1576 
1577 void
efe_eeprom_read(efe_t * efep,uint8_t * buf,size_t len,uint8_t addr)1578 efe_eeprom_read(efe_t *efep, uint8_t *buf, size_t len, uint8_t addr)
1579 {
1580 	int addrlen;
1581 
1582 	ASSERT(len & ~0x1);	/* non-zero; word-aligned */
1583 
1584 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1585 	drv_usecwait(EEPROM_DELAY);
1586 
1587 	addrlen = (GETCSR(efep, CSR_EECTL) & EECTL_SIZE ?
1588 	    AT93C46_ADDRLEN : AT93C56_ADDRLEN);
1589 
1590 	for (int i = 0; i < len / sizeof (uint16_t); ++i) {
1591 		uint16_t val = efe_eeprom_readw(efep, addrlen, addr + i);
1592 		bcopy(&val, buf, sizeof (uint16_t));
1593 		buf += sizeof (uint16_t);
1594 	}
1595 }
1596 
1597 uint16_t
efe_eeprom_readw(efe_t * efep,int addrlen,uint8_t addr)1598 efe_eeprom_readw(efe_t *efep, int addrlen, uint8_t addr)
1599 {
1600 	uint16_t val = 0;
1601 
1602 	ASSERT(addrlen > 0);
1603 
1604 	/* Write Start Bit (SB) */
1605 	efe_eeprom_writebit(efep, 1);
1606 
1607 	/* Write READ instruction */
1608 	efe_eeprom_writebit(efep, 1);
1609 	efe_eeprom_writebit(efep, 0);
1610 
1611 	/* Write EEPROM address */
1612 	for (int i = addrlen - 1; i >= 0; --i) {
1613 		efe_eeprom_writebit(efep, addr & 1U << i);
1614 	}
1615 
1616 	/* Read EEPROM word */
1617 	for (int i = EEPROM_WORDSZ - 1; i >= 0; --i) {
1618 		val |= efe_eeprom_readbit(efep) << i;
1619 	}
1620 
1621 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE);
1622 	drv_usecwait(EEPROM_DELAY);
1623 
1624 	return (val);
1625 }
1626 
1627 inline int
efe_eeprom_readbit(efe_t * efep)1628 efe_eeprom_readbit(efe_t *efep)
1629 {
1630 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1631 	drv_usecwait(EEPROM_DELAY);
1632 
1633 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
1634 	    EECTL_EESK);
1635 	drv_usecwait(EEPROM_DELAY);
1636 
1637 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1638 	drv_usecwait(EEPROM_DELAY);
1639 
1640 	return (!!(GETCSR(efep, CSR_EECTL) & EECTL_EEDO));
1641 }
1642 
1643 inline void
efe_eeprom_writebit(efe_t * efep,int bit)1644 efe_eeprom_writebit(efe_t *efep, int bit)
1645 {
1646 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1647 	drv_usecwait(EEPROM_DELAY);
1648 
1649 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
1650 	    EECTL_EESK | (bit ? EECTL_EEDI : 0));
1651 	drv_usecwait(EEPROM_DELAY);
1652 
1653 	PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1654 	drv_usecwait(EEPROM_DELAY);
1655 }
1656 
1657 void
efe_dprintf(dev_info_t * dip,int level,const char * format,...)1658 efe_dprintf(dev_info_t *dip, int level, const char *format, ...)
1659 {
1660 	va_list ap;
1661 	char buf[255];
1662 
1663 	va_start(ap, format);
1664 
1665 	(void) vsnprintf(buf, sizeof (buf), format, ap);
1666 
1667 	cmn_err(level, "?%s%d %s", ddi_driver_name(dip),
1668 	    ddi_get_instance(dip), buf);
1669 
1670 	va_end(ap);
1671 }
1672