bmake-ify mega_sas
[unleashed.git] / usr / src / uts / common / io / efe / efe.c
blob2b5c5b1fbe498b39d2d9f1566a3a47009ff56342
1 /*
2 * Copyright (c) 2010 Steven Stallion. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
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.
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.
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>
56 #include "efe.h"
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 *);
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);
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);
83 /* ISR/periodic callbacks */
84 static uint_t efe_intr(caddr_t, caddr_t);
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 *);
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 **);
103 static void efe_intr_enable(efe_t *);
104 static void efe_intr_disable(efe_t *);
106 static mblk_t *efe_recv(efe_t *);
107 static mblk_t *efe_recv_pkt(efe_t *, efe_desc_t *);
109 static int efe_send(efe_t *, mblk_t *);
110 static void efe_send_done(efe_t *);
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 *);
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);
121 static void efe_dprintf(dev_info_t *, int, const char *, ...);
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
130 #define efe_error(dip, ...) \
131 efe_dprintf((dip), CE_WARN, __VA_ARGS__)
133 extern struct mod_ops mod_driverops;
135 DDI_DEFINE_STREAM_OPS(efe_dev_ops, nulldev, nulldev, efe_attach, efe_detach,
136 nodev, NULL, D_MP, NULL, efe_quiesce);
138 static struct modldrv modldrv = {
139 &mod_driverops, /* drv_modops */
140 "EPIC/100 Fast Ethernet", /* drv_linkinfo */
141 &efe_dev_ops /* drv_dev_ops */
144 static struct modlinkage modlinkage = {
145 MODREV_1, /* ml_rev */
146 { &modldrv, NULL } /* ml_linkage */
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 */
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 */
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 */
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 */
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 */
202 static uint8_t efe_broadcast[] = {
203 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
206 static uint16_t efe_mchash_promisc[] = {
207 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF
211 * Loadable module entry points.
214 _init(void)
216 int error;
218 mac_init_ops(&efe_dev_ops, "efe");
219 if ((error = mod_install(&modlinkage)) != DDI_SUCCESS) {
220 mac_fini_ops(&efe_dev_ops);
223 return (error);
227 _fini(void)
229 int error;
231 if ((error = mod_remove(&modlinkage)) == DDI_SUCCESS) {
232 mac_fini_ops(&efe_dev_ops);
235 return (error);
239 _info(struct modinfo *modinfop)
241 return (mod_info(&modlinkage, modinfop));
245 * Autoconfiguration entry points.
248 efe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
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;
258 switch (cmd) {
259 case DDI_ATTACH:
260 break;
262 case DDI_RESUME:
263 efep = ddi_get_driver_private(dip);
264 return (efe_resume(efep));
266 default:
267 return (DDI_FAILURE);
271 * PCI configuration.
273 if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
274 efe_error(dip, "unable to setup PCI configuration!");
275 return (DDI_FAILURE);
278 pci_config_put16(pci, PCI_CONF_COMM,
279 pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME);
281 pci_config_teardown(&pci);
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);
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);
296 * Initialize soft state.
298 efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP);
299 ddi_set_driver_private(dip, efep);
301 efep->efe_dip = dip;
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;
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;
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;
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;
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;
334 mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER,
335 DDI_INTR_PRI(pri));
337 mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER,
338 DDI_INTR_PRI(pri));
341 * Initialize device.
343 mutex_enter(&efep->efe_intrlock);
344 mutex_enter(&efep->efe_txlock);
346 efe_reset(efep);
348 mutex_exit(&efep->efe_txlock);
349 mutex_exit(&efep->efe_intrlock);
351 /* Use factory address as default */
352 efe_getaddr(efep, efep->efe_macaddr);
355 * Enable the ISR.
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;
363 if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) {
364 efe_error(dip, "unable to enable interrupt!");
365 goto failure;
369 * Allocate MII resources.
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;
377 * Allocate MAC resources.
379 if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
380 efe_error(dip, "unable to allocate mac resources!");
381 goto failure;
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;
393 if (mac_register(macp, &efep->efe_mh) != 0) {
394 efe_error(dip, "unable to register with mac!");
395 goto failure;
397 mac_free(macp);
399 ddi_report_dev(dip);
401 return (DDI_SUCCESS);
403 failure:
404 if (macp != NULL) {
405 mac_free(macp);
408 if (efep->efe_miih != NULL) {
409 mii_free(efep->efe_miih);
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);
418 mutex_destroy(&efep->efe_txlock);
419 mutex_destroy(&efep->efe_intrlock);
421 if (efep->efe_tx_ring != NULL) {
422 efe_ring_free(&efep->efe_tx_ring);
424 if (efep->efe_rx_ring != NULL) {
425 efe_ring_free(&efep->efe_rx_ring);
428 if (efep->efe_regs_acch != NULL) {
429 ddi_regs_map_free(&efep->efe_regs_acch);
432 kmem_free(efep, sizeof (efe_t));
434 return (DDI_FAILURE);
438 efe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
440 efe_t *efep = ddi_get_driver_private(dip);
442 switch (cmd) {
443 case DDI_DETACH:
444 break;
446 case DDI_SUSPEND:
447 return (efe_suspend(efep));
449 default:
450 return (DDI_FAILURE);
453 if (mac_unregister(efep->efe_mh) != 0) {
454 efe_error(dip, "unable to unregister from mac!");
455 return (DDI_FAILURE);
458 mii_free(efep->efe_miih);
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);
464 mutex_destroy(&efep->efe_txlock);
465 mutex_destroy(&efep->efe_intrlock);
467 if (efep->efe_tx_ring != NULL) {
468 efe_ring_free(&efep->efe_tx_ring);
470 if (efep->efe_rx_ring != NULL) {
471 efe_ring_free(&efep->efe_rx_ring);
474 ddi_regs_map_free(&efep->efe_regs_acch);
476 kmem_free(efep, sizeof (efe_t));
478 return (DDI_SUCCESS);
482 efe_quiesce(dev_info_t *dip)
484 efe_t *efep = ddi_get_driver_private(dip);
486 PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
487 drv_usecwait(RESET_DELAY);
489 PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
491 return (DDI_SUCCESS);
495 * MII entry points.
497 uint16_t
498 efe_mii_read(void *arg, uint8_t phy, uint8_t reg)
500 efe_t *efep = arg;
502 PUTCSR(efep, CSR_MMCTL, MMCTL_READ |
503 reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
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));
509 drv_usecwait(MII_DELAY);
511 efe_error(efep->efe_dip, "timed out reading from MII!");
513 return (0);
516 void
517 efe_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t data)
519 efe_t *efep = arg;
521 PUTCSR(efep, CSR_MMDATA, data);
523 PUTCSR(efep, CSR_MMCTL, MMCTL_WRITE |
524 reg << MMCTL_PHYREG | phy << MMCTL_PHYADDR);
526 for (int i = 0; i < MII_DELAY_CYCLES; ++i) {
527 if (!(GETCSR(efep, CSR_MMCTL) & MMCTL_WRITE)) {
528 return;
530 drv_usecwait(MII_DELAY);
532 efe_error(efep->efe_dip, "timed out writing to MII!");
535 void
536 efe_mii_notify(void *arg, link_state_t link)
538 efe_t *efep = arg;
540 mac_link_update(efep->efe_mh, link);
544 * MAC entry points.
547 efe_m_getstat(void *arg, uint_t stat, uint64_t *val)
549 efe_t *efep = arg;
551 if (mii_m_getstat(efep->efe_miih, stat, val) == 0) {
552 return (0);
555 switch (stat) {
556 case MAC_STAT_MULTIRCV:
557 *val = efep->efe_multircv;
558 break;
560 case MAC_STAT_BRDCSTRCV:
561 *val = efep->efe_brdcstrcv;
562 break;
564 case MAC_STAT_MULTIXMT:
565 *val = efep->efe_multixmt;
566 break;
568 case MAC_STAT_BRDCSTXMT:
569 *val = efep->efe_brdcstxmt;
570 break;
572 case MAC_STAT_NORCVBUF:
573 *val = efep->efe_norcvbuf;
574 break;
576 case MAC_STAT_IERRORS:
577 *val = efep->efe_ierrors;
578 break;
580 case MAC_STAT_NOXMTBUF:
581 *val = efep->efe_noxmtbuf;
582 break;
584 case MAC_STAT_OERRORS:
585 *val = efep->efe_oerrors;
586 break;
588 case MAC_STAT_COLLISIONS:
589 *val = efep->efe_collisions;
590 break;
592 case MAC_STAT_RBYTES:
593 *val = efep->efe_rbytes;
594 break;
596 case MAC_STAT_IPACKETS:
597 *val = efep->efe_ipackets;
598 break;
600 case MAC_STAT_OBYTES:
601 *val = efep->efe_obytes;
602 break;
604 case MAC_STAT_OPACKETS:
605 *val = efep->efe_opackets;
606 break;
608 case MAC_STAT_UNDERFLOWS:
609 *val = efep->efe_uflo;
610 break;
612 case MAC_STAT_OVERFLOWS:
613 *val = efep->efe_oflo;
614 break;
616 case ETHER_STAT_ALIGN_ERRORS:
617 *val = efep->efe_align_errors;
618 break;
620 case ETHER_STAT_FCS_ERRORS:
621 *val = efep->efe_fcs_errors;
622 break;
624 case ETHER_STAT_FIRST_COLLISIONS:
625 *val = efep->efe_first_collisions;
626 break;
628 case ETHER_STAT_TX_LATE_COLLISIONS:
629 *val = efep->efe_tx_late_collisions;
630 break;
632 case ETHER_STAT_DEFER_XMTS:
633 *val = efep->efe_defer_xmts;
634 break;
636 case ETHER_STAT_EX_COLLISIONS:
637 *val = efep->efe_ex_collisions;
638 break;
640 case ETHER_STAT_MACXMT_ERRORS:
641 *val = efep->efe_macxmt_errors;
642 break;
644 case ETHER_STAT_CARRIER_ERRORS:
645 *val = efep->efe_carrier_errors;
646 break;
648 case ETHER_STAT_TOOLONG_ERRORS:
649 *val = efep->efe_toolong_errors;
650 break;
652 case ETHER_STAT_MACRCV_ERRORS:
653 *val = efep->efe_macrcv_errors;
654 break;
656 case ETHER_STAT_TOOSHORT_ERRORS:
657 *val = efep->efe_runt_errors;
658 break;
660 case ETHER_STAT_JABBER_ERRORS:
661 *val = efep->efe_jabber_errors;
662 break;
664 default:
665 return (ENOTSUP);
668 return (0);
672 efe_m_start(void *arg)
674 efe_t *efep = arg;
676 mutex_enter(&efep->efe_intrlock);
677 mutex_enter(&efep->efe_txlock);
679 efe_start(efep);
680 efep->efe_flags |= FLAG_RUNNING;
682 mutex_exit(&efep->efe_txlock);
683 mutex_exit(&efep->efe_intrlock);
685 mii_start(efep->efe_miih);
687 return (0);
690 void
691 efe_m_stop(void *arg)
693 efe_t *efep = arg;
695 mutex_enter(&efep->efe_intrlock);
696 mutex_enter(&efep->efe_txlock);
698 efe_stop(efep);
699 efep->efe_flags &= ~FLAG_RUNNING;
701 mutex_exit(&efep->efe_txlock);
702 mutex_exit(&efep->efe_intrlock);
704 mii_stop(efep->efe_miih);
708 efe_m_setpromisc(void *arg, boolean_t on)
710 efe_t *efep = arg;
712 mutex_enter(&efep->efe_intrlock);
713 mutex_enter(&efep->efe_txlock);
715 if (efep->efe_flags & FLAG_SUSPENDED) {
716 mutex_exit(&efep->efe_txlock);
717 mutex_exit(&efep->efe_intrlock);
718 return (0);
721 efep->efe_promisc = on;
723 if (efep->efe_flags & FLAG_RUNNING) {
724 efe_restart(efep);
727 mutex_exit(&efep->efe_txlock);
728 mutex_exit(&efep->efe_intrlock);
730 return (0);
734 efe_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
736 efe_t *efep = arg;
737 uint32_t val;
738 int index;
739 int bit;
740 boolean_t restart = B_FALSE;
742 mutex_enter(&efep->efe_intrlock);
743 mutex_enter(&efep->efe_txlock);
745 if (efep->efe_flags & FLAG_SUSPENDED) {
746 mutex_exit(&efep->efe_txlock);
747 mutex_exit(&efep->efe_intrlock);
748 return (0);
751 CRC32(val, macaddr, ETHERADDRL, -1U, crc32_table);
752 val %= MCHASHL;
754 index = val / MCHASHSZ;
755 bit = 1U << (val % MCHASHSZ);
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;
764 } else {
765 efep->efe_mccount[val]--;
766 if (efep->efe_mccount[val] == 0) {
767 efep->efe_mchash[index] &= ~bit;
768 restart = B_TRUE;
772 if (restart && efep->efe_flags & FLAG_RUNNING) {
773 efe_restart(efep);
776 mutex_exit(&efep->efe_txlock);
777 mutex_exit(&efep->efe_intrlock);
779 return (0);
783 efe_m_unicst(void *arg, const uint8_t *macaddr)
785 efe_t *efep = arg;
787 mutex_enter(&efep->efe_intrlock);
788 mutex_enter(&efep->efe_txlock);
790 if (efep->efe_flags & FLAG_SUSPENDED) {
791 mutex_exit(&efep->efe_txlock);
792 mutex_exit(&efep->efe_intrlock);
793 return (0);
796 bcopy(macaddr, efep->efe_macaddr, ETHERADDRL);
798 if (efep->efe_flags & FLAG_RUNNING) {
799 efe_restart(efep);
802 mutex_exit(&efep->efe_txlock);
803 mutex_exit(&efep->efe_intrlock);
805 return (0);
808 mblk_t *
809 efe_m_tx(void *arg, mblk_t *mp)
811 efe_t *efep = arg;
813 mutex_enter(&efep->efe_txlock);
815 if (efep->efe_flags & FLAG_SUSPENDED) {
816 mutex_exit(&efep->efe_txlock);
817 return (mp);
820 while (mp != NULL) {
821 mblk_t *tmp = mp->b_next;
822 mp->b_next = NULL;
824 if (efe_send(efep, mp) != DDI_SUCCESS) {
825 mp->b_next = tmp;
826 break;
828 mp = tmp;
831 /* Kick the transmitter */
832 PUTCSR(efep, CSR_COMMAND, COMMAND_TXQUEUED);
834 mutex_exit(&efep->efe_txlock);
836 return (mp);
840 efe_m_setprop(void *arg, const char *name, mac_prop_id_t id,
841 uint_t valsize, const void *val)
843 efe_t *efep = arg;
845 return (mii_m_setprop(efep->efe_miih, name, id, valsize, val));
849 efe_m_getprop(void *arg, const char *name, mac_prop_id_t id,
850 uint_t valsize, void *val)
852 efe_t *efep = arg;
854 return (mii_m_getprop(efep->efe_miih, name, id, valsize, val));
857 void
858 efe_m_propinfo(void *arg, const char *name, mac_prop_id_t id,
859 mac_prop_info_handle_t state)
861 efe_t *efep = arg;
863 mii_m_propinfo(efep->efe_miih, name, id, state);
867 * ISR/periodic callbacks.
869 uint_t
870 efe_intr(caddr_t arg1, caddr_t arg2)
872 efe_t *efep = (void *)arg1;
873 uint32_t status;
874 mblk_t *mp = NULL;
876 _NOTE(ARGUNUSED(arg2));
878 mutex_enter(&efep->efe_intrlock);
880 if (efep->efe_flags & FLAG_SUSPENDED) {
881 mutex_exit(&efep->efe_intrlock);
882 return (DDI_INTR_UNCLAIMED);
885 status = GETCSR(efep, CSR_INTSTAT);
886 if (!(status & INTSTAT_ACTV)) {
887 mutex_exit(&efep->efe_intrlock);
888 return (DDI_INTR_UNCLAIMED);
890 PUTCSR(efep, CSR_INTSTAT, status);
892 if (status & INTSTAT_RCC) {
893 mp = efe_recv(efep);
896 if (status & INTSTAT_RQE) {
897 efep->efe_ierrors++;
898 efep->efe_macrcv_errors++;
900 /* Kick the receiver */
901 PUTCSR(efep, CSR_COMMAND, COMMAND_RXQUEUED);
904 if (status & INTSTAT_TXC) {
905 mutex_enter(&efep->efe_txlock);
907 efe_send_done(efep);
909 mutex_exit(&efep->efe_txlock);
912 if (status & INTSTAT_FATAL) {
913 mutex_enter(&efep->efe_txlock);
915 efe_error(efep->efe_dip, "bus error; resetting!");
916 efe_restart(efep);
918 mutex_exit(&efep->efe_txlock);
921 mutex_exit(&efep->efe_intrlock);
923 if (mp != NULL) {
924 mac_rx(efep->efe_mh, NULL, mp);
927 if (status & INTSTAT_TXC) {
928 mac_tx_update(efep->efe_mh);
931 if (status & INTSTAT_FATAL) {
932 mii_reset(efep->efe_miih);
935 return (DDI_INTR_CLAIMED);
939 * Support functions.
941 void
942 efe_init(efe_t *efep)
944 uint32_t val;
946 ASSERT(mutex_owned(&efep->efe_intrlock));
947 ASSERT(mutex_owned(&efep->efe_txlock));
949 efe_reset(efep);
951 val = GENCTL_ONECOPY | GENCTL_RFT_128 | GENCTL_MRM;
952 #ifdef _BIG_ENDIAN
953 val |= GENCTL_BE;
954 #endif /* _BIG_ENDIAN */
956 PUTCSR(efep, CSR_GENCTL, val);
957 PUTCSR(efep, CSR_PBLCNT, BURSTLEN);
959 efe_init_rx_ring(efep);
960 efe_init_tx_ring(efep);
962 efe_setaddr(efep, efep->efe_macaddr);
964 if (efep->efe_promisc) {
965 efe_setmchash(efep, efe_mchash_promisc);
966 } else {
967 efe_setmchash(efep, efep->efe_mchash);
971 void
972 efe_init_rx_ring(efe_t *efep)
974 efe_ring_t *rp;
976 ASSERT(mutex_owned(&efep->efe_intrlock));
978 rp = efep->efe_rx_ring;
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);
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));
991 SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
994 efep->efe_rx_desc = 0;
996 PUTCSR(efep, CSR_PRCDAR, DESCADDR(rp, 0));
999 void
1000 efe_init_tx_ring(efe_t *efep)
1002 efe_ring_t *rp;
1004 ASSERT(mutex_owned(&efep->efe_txlock));
1006 rp = efep->efe_tx_ring;
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);
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));
1019 SYNCDESC(rp, i, DDI_DMA_SYNC_FORDEV);
1022 efep->efe_tx_desc = 0;
1023 efep->efe_tx_sent = 0;
1025 PUTCSR(efep, CSR_PTCDAR, DESCADDR(rp, 0));
1028 void
1029 efe_reset(efe_t *efep)
1031 ASSERT(mutex_owned(&efep->efe_intrlock));
1032 ASSERT(mutex_owned(&efep->efe_txlock));
1034 PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
1035 drv_usecwait(RESET_DELAY);
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);
1043 void
1044 efe_start(efe_t *efep)
1046 ASSERT(mutex_owned(&efep->efe_intrlock));
1047 ASSERT(mutex_owned(&efep->efe_txlock));
1049 efe_init(efep);
1051 PUTCSR(efep, CSR_RXCON,
1052 RXCON_SEP | RXCON_RRF | RXCON_RBF | RXCON_RMF |
1053 (efep->efe_promisc ? RXCON_PROMISC : 0));
1055 PUTCSR(efep, CSR_TXCON, TXCON_LB_3);
1057 efe_intr_enable(efep);
1059 SETBIT(efep, CSR_COMMAND,
1060 COMMAND_START_RX | COMMAND_RXQUEUED);
1063 void
1064 efe_stop(efe_t *efep)
1066 ASSERT(mutex_owned(&efep->efe_intrlock));
1067 ASSERT(mutex_owned(&efep->efe_txlock));
1069 efe_intr_disable(efep);
1071 PUTCSR(efep, CSR_COMMAND, COMMAND_STOP_RX);
1073 efe_stop_dma(efep);
1075 PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
1076 drv_usecwait(RESET_DELAY);
1078 PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);
1081 void
1082 efe_stop_dma(efe_t *efep)
1084 ASSERT(mutex_owned(&efep->efe_intrlock));
1085 ASSERT(mutex_owned(&efep->efe_txlock));
1087 PUTCSR(efep, CSR_COMMAND,
1088 COMMAND_STOP_RDMA | COMMAND_STOP_TDMA);
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;
1096 drv_usecwait(STOP_DELAY);
1098 efe_error(efep->efe_dip, "timed out stopping DMA engine!");
1101 static inline void
1102 efe_restart(efe_t *efep)
1104 efe_stop(efep);
1105 efe_start(efep);
1109 efe_suspend(efe_t *efep)
1111 mutex_enter(&efep->efe_intrlock);
1112 mutex_enter(&efep->efe_txlock);
1114 if (efep->efe_flags & FLAG_RUNNING) {
1115 efe_stop(efep);
1117 efep->efe_flags |= FLAG_SUSPENDED;
1119 mutex_exit(&efep->efe_txlock);
1120 mutex_exit(&efep->efe_intrlock);
1122 mii_suspend(efep->efe_miih);
1124 return (DDI_SUCCESS);
1128 efe_resume(efe_t *efep)
1130 mutex_enter(&efep->efe_intrlock);
1131 mutex_enter(&efep->efe_txlock);
1133 if (efep->efe_flags & FLAG_RUNNING) {
1134 efe_start(efep);
1136 efep->efe_flags &= ~FLAG_SUSPENDED;
1138 mutex_exit(&efep->efe_txlock);
1139 mutex_exit(&efep->efe_intrlock);
1141 mii_resume(efep->efe_miih);
1143 return (DDI_SUCCESS);
1146 efe_ring_t *
1147 efe_ring_alloc(dev_info_t *dip, size_t len)
1149 efe_ring_t *rp;
1150 size_t rlen;
1151 uint_t ccount;
1153 ASSERT(len > 1);
1155 rp = kmem_zalloc(sizeof (efe_ring_t), KM_SLEEP);
1156 rp->r_len = len;
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;
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;
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;
1178 rp->r_bufpp = kmem_zalloc(BUFPSZ(len), KM_SLEEP);
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;
1185 rp->r_bufpp[i] = bp;
1188 return (rp);
1190 failure:
1191 efe_ring_free(&rp);
1193 return (NULL);
1196 void
1197 efe_ring_free(efe_ring_t **rpp)
1199 efe_ring_t *rp = *rpp;
1201 ASSERT(rp != NULL);
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);
1209 kmem_free(rp->r_bufpp, BUFPSZ(DESCLEN(rp)));
1211 if (rp->r_descp != NULL) {
1212 (void) ddi_dma_unbind_handle(rp->r_dmah);
1214 if (rp->r_acch != NULL) {
1215 ddi_dma_mem_free(&rp->r_acch);
1217 if (rp->r_dmah != NULL) {
1218 ddi_dma_free_handle(&rp->r_dmah);
1220 kmem_free(rp, sizeof (efe_ring_t));
1222 *rpp = NULL;
1225 efe_buf_t *
1226 efe_buf_alloc(dev_info_t *dip, size_t len)
1228 efe_buf_t *bp;
1229 size_t rlen;
1230 uint_t ccount;
1232 bp = kmem_zalloc(sizeof (efe_buf_t), KM_SLEEP);
1233 bp->b_len = len;
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;
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;
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;
1255 return (bp);
1257 failure:
1258 efe_buf_free(&bp);
1260 return (NULL);
1263 void
1264 efe_buf_free(efe_buf_t **bpp)
1266 efe_buf_t *bp = *bpp;
1268 ASSERT(bp != NULL);
1270 if (bp->b_kaddr != NULL) {
1271 (void) ddi_dma_unbind_handle(bp->b_dmah);
1273 if (bp->b_acch != NULL) {
1274 ddi_dma_mem_free(&bp->b_acch);
1276 if (bp->b_dmah != NULL) {
1277 ddi_dma_free_handle(&bp->b_dmah);
1279 kmem_free(bp, sizeof (efe_buf_t));
1281 *bpp = NULL;
1284 void
1285 efe_intr_enable(efe_t *efep)
1287 PUTCSR(efep, CSR_INTMASK,
1288 INTMASK_RCC | INTMASK_RQE | INTMASK_TXC | INTMASK_FATAL);
1290 SETBIT(efep, CSR_GENCTL, GENCTL_INT);
1293 void
1294 efe_intr_disable(efe_t *efep)
1296 PUTCSR(efep, CSR_INTMASK, 0);
1298 CLRBIT(efep, CSR_GENCTL, GENCTL_INT);
1301 mblk_t *
1302 efe_recv(efe_t *efep)
1304 efe_ring_t *rp;
1305 mblk_t *mp = NULL;
1306 mblk_t **mpp = &mp;
1308 ASSERT(mutex_owned(&efep->efe_intrlock));
1310 rp = efep->efe_rx_ring;
1312 for (;;) {
1313 efe_desc_t *dp;
1314 uint16_t status;
1316 dp = GETDESC(rp, efep->efe_rx_desc);
1317 SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORKERNEL);
1319 status = GETDESC16(rp, &dp->d_status);
1321 /* Stop if device owns descriptor */
1322 if (status & RXSTAT_OWNER) {
1323 break;
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;
1333 } else {
1334 efep->efe_ierrors++;
1336 if (status & RXSTAT_FAE) {
1337 efep->efe_align_errors++;
1339 if (status & RXSTAT_CRC) {
1340 efep->efe_fcs_errors++;
1342 if (status & RXSTAT_MP) {
1343 efep->efe_oflo++;
1347 /* Release ownership to device */
1348 PUTDESC16(rp, &dp->d_status, RXSTAT_OWNER);
1350 SYNCDESC(rp, efep->efe_rx_desc, DDI_DMA_SYNC_FORDEV);
1352 efep->efe_rx_desc = NEXTDESC(rp, efep->efe_rx_desc);
1355 return (mp);
1358 mblk_t *
1359 efe_recv_pkt(efe_t *efep, efe_desc_t *dp)
1361 efe_ring_t *rp;
1362 efe_buf_t *bp;
1363 uint16_t len;
1364 mblk_t *mp;
1365 uint16_t status;
1367 ASSERT(mutex_owned(&efep->efe_intrlock));
1369 rp = efep->efe_rx_ring;
1371 len = GETDESC16(rp, &dp->d_len) - ETHERFCSL;
1373 if (len < ETHERMIN) {
1374 efep->efe_ierrors++;
1375 efep->efe_runt_errors++;
1376 return (NULL);
1379 if (len > ETHERMAX + VLAN_TAGSZ) {
1380 efep->efe_ierrors++;
1381 efep->efe_toolong_errors++;
1382 return (NULL);
1385 mp = allocb(len, 0);
1386 if (mp == NULL) {
1387 efep->efe_ierrors++;
1388 efep->efe_norcvbuf++;
1389 return (NULL);
1391 mp->b_wptr = mp->b_rptr + len;
1393 bp = GETBUF(rp, efep->efe_rx_desc);
1394 SYNCBUF(bp, DDI_DMA_SYNC_FORKERNEL);
1396 bcopy(bp->b_kaddr, mp->b_rptr, len);
1398 efep->efe_ipackets++;
1399 efep->efe_rbytes += len;
1401 status = GETDESC16(rp, &dp->d_status);
1403 if (status & RXSTAT_BAR) {
1404 efep->efe_brdcstrcv++;
1406 } else if (status & RXSTAT_MAR) {
1407 efep->efe_multircv++;
1410 return (mp);
1414 efe_send(efe_t *efep, mblk_t *mp)
1416 efe_ring_t *rp;
1417 uint16_t len;
1418 efe_desc_t *dp;
1419 uint16_t status;
1420 efe_buf_t *bp;
1422 ASSERT(mutex_owned(&efep->efe_txlock));
1424 rp = efep->efe_tx_ring;
1426 len = msgsize(mp);
1428 if (len > ETHERMAX + VLAN_TAGSZ) {
1429 efep->efe_oerrors++;
1430 efep->efe_macxmt_errors++;
1431 freemsg(mp);
1432 return (DDI_SUCCESS);
1435 dp = GETDESC(rp, efep->efe_tx_desc);
1436 SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORKERNEL);
1438 status = GETDESC16(efep->efe_tx_ring, &dp->d_status);
1440 /* Stop if device owns descriptor */
1441 if (status & TXSTAT_OWNER) {
1442 return (DDI_FAILURE);
1445 bp = GETBUF(rp, efep->efe_tx_desc);
1447 mcopymsg(mp, bp->b_kaddr);
1450 * Packets must contain at least ETHERMIN octets.
1451 * Padded octets are zeroed out prior to sending.
1453 if (len < ETHERMIN) {
1454 bzero(bp->b_kaddr + len, ETHERMIN - len);
1455 len = ETHERMIN;
1458 SYNCBUF(bp, DDI_DMA_SYNC_FORDEV);
1460 PUTDESC16(rp, &dp->d_status, TXSTAT_OWNER);
1461 PUTDESC16(rp, &dp->d_len, len);
1462 PUTDESC16(rp, &dp->d_control, TXCTL_LASTDESCR);
1464 SYNCDESC(rp, efep->efe_tx_desc, DDI_DMA_SYNC_FORDEV);
1466 efep->efe_opackets++;
1467 efep->efe_obytes += len;
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++;
1477 efep->efe_tx_desc = NEXTDESC(rp, efep->efe_tx_desc);
1479 return (DDI_SUCCESS);
1482 void
1483 efe_send_done(efe_t *efep)
1485 efe_ring_t *rp;
1487 ASSERT(mutex_owned(&efep->efe_txlock));
1489 rp = efep->efe_tx_ring;
1491 for (;;) {
1492 efe_desc_t *dp;
1493 uint16_t status;
1495 dp = GETDESC(rp, efep->efe_tx_sent);
1496 SYNCDESC(rp, efep->efe_tx_sent, DDI_DMA_SYNC_FORKERNEL);
1498 status = GETDESC16(rp, &dp->d_status);
1500 /* Stop if device owns descriptor */
1501 if (status & TXSTAT_OWNER) {
1502 break;
1505 if (status & TXSTAT_PTX) {
1506 if (!(status & TXSTAT_ND)) {
1507 efep->efe_defer_xmts++;
1509 if (status & TXSTAT_COLL) {
1510 efep->efe_first_collisions++;
1513 } else {
1514 efep->efe_oerrors++;
1516 if (status & TXSTAT_CSL) {
1517 efep->efe_carrier_errors++;
1519 if (status & TXSTAT_UFLO) {
1520 efep->efe_uflo++;
1522 if (status & TXSTAT_OWC) {
1523 efep->efe_tx_late_collisions++;
1525 if (status & TXSTAT_DEFER) {
1526 efep->efe_jabber_errors++;
1528 if (status & TXSTAT_EXCOLL) {
1529 efep->efe_ex_collisions++;
1533 efep->efe_collisions +=
1534 (status >> TXSTAT_CCNT) & TXSTAT_CCNTMASK;
1536 efep->efe_tx_sent = NEXTDESC(rp, efep->efe_tx_sent);
1540 void
1541 efe_getaddr(efe_t *efep, uint8_t *macaddr)
1543 efe_eeprom_read(efep, macaddr, ETHERADDRL, 0x0);
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]);
1551 void
1552 efe_setaddr(efe_t *efep, uint8_t *macaddr)
1554 uint16_t val;
1556 bcopy(macaddr, &val, sizeof (uint16_t));
1557 PUTCSR(efep, CSR_LAN0, val);
1558 macaddr += sizeof (uint16_t);
1560 bcopy(macaddr, &val, sizeof (uint16_t));
1561 PUTCSR(efep, CSR_LAN1, val);
1562 macaddr += sizeof (uint16_t);
1564 bcopy(macaddr, &val, sizeof (uint16_t));
1565 PUTCSR(efep, CSR_LAN2, val);
1568 void
1569 efe_setmchash(efe_t *efep, uint16_t *mchash)
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]);
1577 void
1578 efe_eeprom_read(efe_t *efep, uint8_t *buf, size_t len, uint8_t addr)
1580 int addrlen;
1582 ASSERT(len & ~0x1); /* non-zero; word-aligned */
1584 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1585 drv_usecwait(EEPROM_DELAY);
1587 addrlen = (GETCSR(efep, CSR_EECTL) & EECTL_SIZE ?
1588 AT93C46_ADDRLEN : AT93C56_ADDRLEN);
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);
1597 uint16_t
1598 efe_eeprom_readw(efe_t *efep, int addrlen, uint8_t addr)
1600 uint16_t val = 0;
1602 ASSERT(addrlen > 0);
1604 /* Write Start Bit (SB) */
1605 efe_eeprom_writebit(efep, 1);
1607 /* Write READ instruction */
1608 efe_eeprom_writebit(efep, 1);
1609 efe_eeprom_writebit(efep, 0);
1611 /* Write EEPROM address */
1612 for (int i = addrlen - 1; i >= 0; --i) {
1613 efe_eeprom_writebit(efep, addr & 1U << i);
1616 /* Read EEPROM word */
1617 for (int i = EEPROM_WORDSZ - 1; i >= 0; --i) {
1618 val |= efe_eeprom_readbit(efep) << i;
1621 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE);
1622 drv_usecwait(EEPROM_DELAY);
1624 return (val);
1627 inline int
1628 efe_eeprom_readbit(efe_t *efep)
1630 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1631 drv_usecwait(EEPROM_DELAY);
1633 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
1634 EECTL_EESK);
1635 drv_usecwait(EEPROM_DELAY);
1637 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1638 drv_usecwait(EEPROM_DELAY);
1640 return (!!(GETCSR(efep, CSR_EECTL) & EECTL_EEDO));
1643 inline void
1644 efe_eeprom_writebit(efe_t *efep, int bit)
1646 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1647 drv_usecwait(EEPROM_DELAY);
1649 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS |
1650 EECTL_EESK | (bit ? EECTL_EEDI : 0));
1651 drv_usecwait(EEPROM_DELAY);
1653 PUTCSR(efep, CSR_EECTL, EECTL_ENABLE | EECTL_EECS);
1654 drv_usecwait(EEPROM_DELAY);
1657 void
1658 efe_dprintf(dev_info_t *dip, int level, const char *format, ...)
1660 va_list ap;
1661 char buf[255];
1663 va_start(ap, format);
1665 (void) vsnprintf(buf, sizeof (buf), format, ap);
1667 cmn_err(level, "?%s%d %s", ddi_driver_name(dip),
1668 ddi_get_instance(dip), buf);
1670 va_end(ap);