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 = ∓
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