This source file includes following definitions.
- xl_power
- xl_wait
- xl_mii_sync
- xl_mii_send
- xl_mii_readreg
- xl_mii_writereg
- xl_miibus_readreg
- xl_miibus_writereg
- xl_miibus_statchg
- xl_eeprom_wait
- xl_read_eeprom
- xl_setmulti
- xl_setmulti_hash
- xl_setpromisc
- xl_testpacket
- xl_setcfg
- xl_setmode
- xl_reset
- xl_mediacheck
- xl_choose_xcvr
- xl_list_tx_init
- xl_list_tx_init_90xB
- xl_list_rx_init
- xl_newbuf
- xl_rx_resync
- xl_rxeof
- xl_txeof
- xl_txeof_90xB
- xl_txeoc
- xl_intr
- xl_stats_update
- xl_encap
- xl_start
- xl_start_90xB
- xl_init
- xl_ifmedia_upd
- xl_ifmedia_sts
- xl_ioctl
- xl_watchdog
- xl_freetxrx
- xl_stop
- xl_attach
- xl_shutdown
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 #include "bpfilter.h"
104
105 #include <sys/param.h>
106 #include <sys/systm.h>
107 #include <sys/mbuf.h>
108 #include <sys/protosw.h>
109 #include <sys/socket.h>
110 #include <sys/ioctl.h>
111 #include <sys/errno.h>
112 #include <sys/malloc.h>
113 #include <sys/kernel.h>
114 #include <sys/proc.h>
115 #include <sys/device.h>
116
117 #include <net/if.h>
118 #include <net/if_dl.h>
119 #include <net/if_types.h>
120 #include <net/if_media.h>
121
122 #ifdef INET
123 #include <netinet/in.h>
124 #include <netinet/in_systm.h>
125 #include <netinet/in_var.h>
126 #include <netinet/ip.h>
127 #include <netinet/if_ether.h>
128 #endif
129
130 #include <dev/mii/mii.h>
131 #include <dev/mii/miivar.h>
132
133 #include <machine/bus.h>
134
135 #if NBPFILTER > 0
136 #include <net/bpf.h>
137 #endif
138
139 #include <dev/ic/xlreg.h>
140
141
142
143
144
145
146
147
148
149 #define XL905B_TXCSUM_BROKEN 1
150
151 int xl_newbuf(struct xl_softc *, struct xl_chain_onefrag *);
152 void xl_stats_update(void *);
153 int xl_encap(struct xl_softc *, struct xl_chain *,
154 struct mbuf * );
155 void xl_rxeof(struct xl_softc *);
156 int xl_rx_resync(struct xl_softc *);
157 void xl_txeof(struct xl_softc *);
158 void xl_txeof_90xB(struct xl_softc *);
159 void xl_txeoc(struct xl_softc *);
160 int xl_intr(void *);
161 void xl_start(struct ifnet *);
162 void xl_start_90xB(struct ifnet *);
163 int xl_ioctl(struct ifnet *, u_long, caddr_t);
164 void xl_init(void *);
165 void xl_stop(struct xl_softc *);
166 void xl_freetxrx(struct xl_softc *);
167 void xl_watchdog(struct ifnet *);
168 void xl_shutdown(void *);
169 int xl_ifmedia_upd(struct ifnet *);
170 void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
171
172 int xl_eeprom_wait(struct xl_softc *);
173 int xl_read_eeprom(struct xl_softc *, caddr_t, int, int, int);
174 void xl_mii_sync(struct xl_softc *);
175 void xl_mii_send(struct xl_softc *, u_int32_t, int);
176 int xl_mii_readreg(struct xl_softc *, struct xl_mii_frame *);
177 int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *);
178
179 void xl_setcfg(struct xl_softc *);
180 void xl_setmode(struct xl_softc *, int);
181 void xl_setmulti(struct xl_softc *);
182 void xl_setmulti_hash(struct xl_softc *);
183 void xl_setpromisc(struct xl_softc *);
184 void xl_reset(struct xl_softc *);
185 int xl_list_rx_init(struct xl_softc *);
186 int xl_list_tx_init(struct xl_softc *);
187 int xl_list_tx_init_90xB(struct xl_softc *);
188 void xl_wait(struct xl_softc *);
189 void xl_mediacheck(struct xl_softc *);
190 void xl_choose_xcvr(struct xl_softc *, int);
191 #ifdef notdef
192 void xl_testpacket(struct xl_softc *);
193 #endif
194
195 int xl_miibus_readreg(struct device *, int, int);
196 void xl_miibus_writereg(struct device *, int, int, int);
197 void xl_miibus_statchg(struct device *);
198
199 void xl_power(int, void *);
200
201 void
202 xl_power(int why, void *arg)
203 {
204 struct xl_softc *sc = arg;
205 struct ifnet *ifp;
206 int s;
207
208 s = splnet();
209 if (why != PWR_RESUME)
210 xl_stop(sc);
211 else {
212 ifp = &sc->sc_arpcom.ac_if;
213 if (ifp->if_flags & IFF_UP) {
214 xl_reset(sc);
215 xl_init(sc);
216 }
217 }
218 splx(s);
219 }
220
221
222
223
224
225
226
227
228
229 void
230 xl_wait(struct xl_softc *sc)
231 {
232 int i;
233
234 for (i = 0; i < XL_TIMEOUT; i++) {
235 if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY))
236 break;
237 }
238
239 if (i == XL_TIMEOUT)
240 printf("%s: command never completed!\n", sc->sc_dev.dv_xname);
241 }
242
243
244
245
246
247
248
249
250
251
252 #define MII_SET(x) \
253 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \
254 CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x))
255
256 #define MII_CLR(x) \
257 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, \
258 CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x))
259
260
261
262
263 void
264 xl_mii_sync(struct xl_softc *sc)
265 {
266 int i;
267
268 XL_SEL_WIN(4);
269 MII_SET(XL_MII_DIR|XL_MII_DATA);
270
271 for (i = 0; i < 32; i++) {
272 MII_SET(XL_MII_CLK);
273 MII_SET(XL_MII_DATA);
274 MII_SET(XL_MII_DATA);
275 MII_CLR(XL_MII_CLK);
276 MII_SET(XL_MII_DATA);
277 MII_SET(XL_MII_DATA);
278 }
279 }
280
281
282
283
284 void
285 xl_mii_send(struct xl_softc *sc, u_int32_t bits, int cnt)
286 {
287 int i;
288
289 XL_SEL_WIN(4);
290 MII_CLR(XL_MII_CLK);
291
292 for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
293 if (bits & i) {
294 MII_SET(XL_MII_DATA);
295 } else {
296 MII_CLR(XL_MII_DATA);
297 }
298 MII_CLR(XL_MII_CLK);
299 MII_SET(XL_MII_CLK);
300 }
301 }
302
303
304
305
306 int
307 xl_mii_readreg(struct xl_softc *sc, struct xl_mii_frame *frame)
308 {
309 int i, ack, s;
310
311 s = splnet();
312
313
314
315
316 frame->mii_stdelim = XL_MII_STARTDELIM;
317 frame->mii_opcode = XL_MII_READOP;
318 frame->mii_turnaround = 0;
319 frame->mii_data = 0;
320
321
322
323
324
325 XL_SEL_WIN(4);
326
327 CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0);
328
329
330
331 MII_SET(XL_MII_DIR);
332
333 xl_mii_sync(sc);
334
335
336
337
338 xl_mii_send(sc, frame->mii_stdelim, 2);
339 xl_mii_send(sc, frame->mii_opcode, 2);
340 xl_mii_send(sc, frame->mii_phyaddr, 5);
341 xl_mii_send(sc, frame->mii_regaddr, 5);
342
343
344 MII_CLR((XL_MII_CLK|XL_MII_DATA));
345 MII_SET(XL_MII_CLK);
346
347
348 MII_CLR(XL_MII_DIR);
349
350
351 MII_CLR(XL_MII_CLK);
352 ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA;
353 MII_SET(XL_MII_CLK);
354
355
356
357
358
359 if (ack) {
360 for(i = 0; i < 16; i++) {
361 MII_CLR(XL_MII_CLK);
362 MII_SET(XL_MII_CLK);
363 }
364 goto fail;
365 }
366
367 for (i = 0x8000; i; i >>= 1) {
368 MII_CLR(XL_MII_CLK);
369 if (!ack) {
370 if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)
371 frame->mii_data |= i;
372 }
373 MII_SET(XL_MII_CLK);
374 }
375
376 fail:
377
378 MII_CLR(XL_MII_CLK);
379 MII_SET(XL_MII_CLK);
380
381 splx(s);
382
383 if (ack)
384 return (1);
385 return (0);
386 }
387
388
389
390
391 int
392 xl_mii_writereg(struct xl_softc *sc, struct xl_mii_frame *frame)
393 {
394 int s;
395
396 s = splnet();
397
398
399
400
401
402 frame->mii_stdelim = XL_MII_STARTDELIM;
403 frame->mii_opcode = XL_MII_WRITEOP;
404 frame->mii_turnaround = XL_MII_TURNAROUND;
405
406
407
408
409 XL_SEL_WIN(4);
410
411
412
413
414 MII_SET(XL_MII_DIR);
415
416 xl_mii_sync(sc);
417
418 xl_mii_send(sc, frame->mii_stdelim, 2);
419 xl_mii_send(sc, frame->mii_opcode, 2);
420 xl_mii_send(sc, frame->mii_phyaddr, 5);
421 xl_mii_send(sc, frame->mii_regaddr, 5);
422 xl_mii_send(sc, frame->mii_turnaround, 2);
423 xl_mii_send(sc, frame->mii_data, 16);
424
425
426 MII_SET(XL_MII_CLK);
427 MII_CLR(XL_MII_CLK);
428
429
430
431
432 MII_CLR(XL_MII_DIR);
433
434 splx(s);
435
436 return (0);
437 }
438
439 int
440 xl_miibus_readreg(struct device *self, int phy, int reg)
441 {
442 struct xl_softc *sc = (struct xl_softc *)self;
443 struct xl_mii_frame frame;
444
445 if (!(sc->xl_flags & XL_FLAG_PHYOK) && phy != 24)
446 return (0);
447
448 bzero((char *)&frame, sizeof(frame));
449
450 frame.mii_phyaddr = phy;
451 frame.mii_regaddr = reg;
452 xl_mii_readreg(sc, &frame);
453
454 return (frame.mii_data);
455 }
456
457 void
458 xl_miibus_writereg(struct device *self, int phy, int reg, int data)
459 {
460 struct xl_softc *sc = (struct xl_softc *)self;
461 struct xl_mii_frame frame;
462
463 if (!(sc->xl_flags & XL_FLAG_PHYOK) && phy != 24)
464 return;
465
466 bzero((char *)&frame, sizeof(frame));
467
468 frame.mii_phyaddr = phy;
469 frame.mii_regaddr = reg;
470 frame.mii_data = data;
471
472 xl_mii_writereg(sc, &frame);
473 }
474
475 void
476 xl_miibus_statchg(struct device *self)
477 {
478 struct xl_softc *sc = (struct xl_softc *)self;
479
480 xl_setcfg(sc);
481
482
483 XL_SEL_WIN(3);
484 if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
485 CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX);
486 else
487 CSR_WRITE_1(sc, XL_W3_MAC_CTRL,
488 (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX));
489 }
490
491
492
493
494
495 int
496 xl_eeprom_wait(struct xl_softc *sc)
497 {
498 int i;
499
500 for (i = 0; i < 100; i++) {
501 if (CSR_READ_2(sc, XL_W0_EE_CMD) & XL_EE_BUSY)
502 DELAY(162);
503 else
504 break;
505 }
506
507 if (i == 100) {
508 printf("%s: eeprom failed to come ready\n", sc->sc_dev.dv_xname);
509 return (1);
510 }
511
512 return (0);
513 }
514
515
516
517
518
519 int
520 xl_read_eeprom(struct xl_softc *sc, caddr_t dest, int off, int cnt, int swap)
521 {
522 int err = 0, i;
523 u_int16_t word = 0, *ptr;
524 #define EEPROM_5BIT_OFFSET(A) ((((A) << 2) & 0x7F00) | ((A) & 0x003F))
525 #define EEPROM_8BIT_OFFSET(A) ((A) & 0x003F)
526
527
528
529
530 XL_SEL_WIN(0);
531
532 if (xl_eeprom_wait(sc))
533 return (1);
534
535 if (sc->xl_flags & XL_FLAG_EEPROM_OFFSET_30)
536 off += 0x30;
537
538 for (i = 0; i < cnt; i++) {
539 if (sc->xl_flags & XL_FLAG_8BITROM)
540 CSR_WRITE_2(sc, XL_W0_EE_CMD,
541 XL_EE_8BIT_READ | EEPROM_8BIT_OFFSET(off + i));
542 else
543 CSR_WRITE_2(sc, XL_W0_EE_CMD,
544 XL_EE_READ | EEPROM_5BIT_OFFSET(off + i));
545 err = xl_eeprom_wait(sc);
546 if (err)
547 break;
548 word = CSR_READ_2(sc, XL_W0_EE_DATA);
549 ptr = (u_int16_t *)(dest + (i * 2));
550 if (swap)
551 *ptr = ntohs(word);
552 else
553 *ptr = word;
554 }
555
556 return (err ? 1 : 0);
557 }
558
559
560
561
562
563 void
564 xl_setmulti(struct xl_softc *sc)
565 {
566 struct ifnet *ifp;
567 struct arpcom *ac = &sc->sc_arpcom;
568 u_int8_t rxfilt;
569
570 ifp = &sc->sc_arpcom.ac_if;
571
572 XL_SEL_WIN(5);
573 rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
574
575 if (ifp->if_flags & IFF_ALLMULTI) {
576 rxfilt |= XL_RXFILTER_ALLMULTI;
577 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
578 return;
579 }
580
581 if (ac->ac_multicnt > 0)
582 rxfilt |= XL_RXFILTER_ALLMULTI;
583 else
584 rxfilt &= ~XL_RXFILTER_ALLMULTI;
585
586 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
587 }
588
589
590
591
592 void
593 xl_setmulti_hash(struct xl_softc *sc)
594 {
595 struct ifnet *ifp;
596 int h = 0, i;
597 struct arpcom *ac = &sc->sc_arpcom;
598 struct ether_multi *enm;
599 struct ether_multistep step;
600 u_int8_t rxfilt;
601 int mcnt = 0;
602
603 ifp = &sc->sc_arpcom.ac_if;
604
605 XL_SEL_WIN(5);
606 rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
607
608 if (ifp->if_flags & IFF_ALLMULTI) {
609 allmulti:
610 rxfilt |= XL_RXFILTER_ALLMULTI;
611 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
612 return;
613 } else
614 rxfilt &= ~XL_RXFILTER_ALLMULTI;
615
616
617
618 for (i = 0; i < XL_HASHFILT_SIZE; i++)
619 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
620
621
622 ETHER_FIRST_MULTI(step, ac, enm);
623 while (enm != NULL) {
624 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
625 ifp->if_flags |= IFF_ALLMULTI;
626 goto allmulti;
627 }
628 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) &
629 0x000000FF;
630 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|XL_HASH_SET|h);
631 mcnt++;
632 ETHER_NEXT_MULTI(step, enm);
633 }
634
635 if (mcnt)
636 rxfilt |= XL_RXFILTER_MULTIHASH;
637 else
638 rxfilt &= ~XL_RXFILTER_MULTIHASH;
639
640 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
641 }
642
643 void
644 xl_setpromisc(struct xl_softc *sc)
645 {
646 struct ifnet *ifp;
647 u_int8_t rxfilt;
648
649 ifp = &sc->sc_arpcom.ac_if;
650
651 XL_SEL_WIN(5);
652 rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
653
654 if (ifp->if_flags & IFF_PROMISC)
655 rxfilt |= XL_RXFILTER_ALLFRAMES;
656 else
657 rxfilt &= ~XL_RXFILTER_ALLFRAMES;
658
659 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
660 }
661
662
663 #ifdef notdef
664 void
665 xl_testpacket(struct xl_softc *sc)
666 {
667 struct mbuf *m;
668 struct ifnet *ifp;
669 int error;
670
671 ifp = &sc->sc_arpcom.ac_if;
672
673 MGETHDR(m, M_DONTWAIT, MT_DATA);
674
675 if (m == NULL)
676 return;
677
678 bcopy(&sc->sc_arpcom.ac_enaddr,
679 mtod(m, struct ether_header *)->ether_dhost, ETHER_ADDR_LEN);
680 bcopy(&sc->sc_arpcom.ac_enaddr,
681 mtod(m, struct ether_header *)->ether_shost, ETHER_ADDR_LEN);
682 mtod(m, struct ether_header *)->ether_type = htons(3);
683 mtod(m, unsigned char *)[14] = 0;
684 mtod(m, unsigned char *)[15] = 0;
685 mtod(m, unsigned char *)[16] = 0xE3;
686 m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
687 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
688 xl_start(ifp);
689 }
690 #endif
691
692 void
693 xl_setcfg(struct xl_softc *sc)
694 {
695 u_int32_t icfg;
696
697 XL_SEL_WIN(3);
698 icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG);
699 icfg &= ~XL_ICFG_CONNECTOR_MASK;
700 if (sc->xl_media & XL_MEDIAOPT_MII ||
701 sc->xl_media & XL_MEDIAOPT_BT4)
702 icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS);
703 if (sc->xl_media & XL_MEDIAOPT_BTX)
704 icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS);
705
706 CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg);
707 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
708 }
709
710 void
711 xl_setmode(struct xl_softc *sc, int media)
712 {
713 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
714 u_int32_t icfg;
715 u_int16_t mediastat;
716
717 XL_SEL_WIN(4);
718 mediastat = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
719 XL_SEL_WIN(3);
720 icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG);
721
722 if (sc->xl_media & XL_MEDIAOPT_BT) {
723 if (IFM_SUBTYPE(media) == IFM_10_T) {
724 ifp->if_baudrate = IF_Mbps(10);
725 sc->xl_xcvr = XL_XCVR_10BT;
726 icfg &= ~XL_ICFG_CONNECTOR_MASK;
727 icfg |= (XL_XCVR_10BT << XL_ICFG_CONNECTOR_BITS);
728 mediastat |= XL_MEDIASTAT_LINKBEAT|
729 XL_MEDIASTAT_JABGUARD;
730 mediastat &= ~XL_MEDIASTAT_SQEENB;
731 }
732 }
733
734 if (sc->xl_media & XL_MEDIAOPT_BFX) {
735 if (IFM_SUBTYPE(media) == IFM_100_FX) {
736 ifp->if_baudrate = IF_Mbps(100);
737 sc->xl_xcvr = XL_XCVR_100BFX;
738 icfg &= ~XL_ICFG_CONNECTOR_MASK;
739 icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS);
740 mediastat |= XL_MEDIASTAT_LINKBEAT;
741 mediastat &= ~XL_MEDIASTAT_SQEENB;
742 }
743 }
744
745 if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) {
746 if (IFM_SUBTYPE(media) == IFM_10_5) {
747 ifp->if_baudrate = IF_Mbps(10);
748 sc->xl_xcvr = XL_XCVR_AUI;
749 icfg &= ~XL_ICFG_CONNECTOR_MASK;
750 icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS);
751 mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
752 XL_MEDIASTAT_JABGUARD);
753 mediastat |= ~XL_MEDIASTAT_SQEENB;
754 }
755 if (IFM_SUBTYPE(media) == IFM_10_FL) {
756 ifp->if_baudrate = IF_Mbps(10);
757 sc->xl_xcvr = XL_XCVR_AUI;
758 icfg &= ~XL_ICFG_CONNECTOR_MASK;
759 icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS);
760 mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
761 XL_MEDIASTAT_JABGUARD);
762 mediastat |= ~XL_MEDIASTAT_SQEENB;
763 }
764 }
765
766 if (sc->xl_media & XL_MEDIAOPT_BNC) {
767 if (IFM_SUBTYPE(media) == IFM_10_2) {
768 ifp->if_baudrate = IF_Mbps(10);
769 sc->xl_xcvr = XL_XCVR_COAX;
770 icfg &= ~XL_ICFG_CONNECTOR_MASK;
771 icfg |= (XL_XCVR_COAX << XL_ICFG_CONNECTOR_BITS);
772 mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
773 XL_MEDIASTAT_JABGUARD|
774 XL_MEDIASTAT_SQEENB);
775 }
776 }
777
778 if ((media & IFM_GMASK) == IFM_FDX ||
779 IFM_SUBTYPE(media) == IFM_100_FX) {
780 XL_SEL_WIN(3);
781 CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX);
782 } else {
783 XL_SEL_WIN(3);
784 CSR_WRITE_1(sc, XL_W3_MAC_CTRL,
785 (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX));
786 }
787
788 if (IFM_SUBTYPE(media) == IFM_10_2)
789 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START);
790 else
791 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
792 CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg);
793 XL_SEL_WIN(4);
794 CSR_WRITE_2(sc, XL_W4_MEDIA_STATUS, mediastat);
795 DELAY(800);
796 XL_SEL_WIN(7);
797 }
798
799 void
800 xl_reset(struct xl_softc *sc)
801 {
802 int i;
803
804 XL_SEL_WIN(0);
805 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RESET |
806 ((sc->xl_flags & XL_FLAG_WEIRDRESET) ?
807 XL_RESETOPT_DISADVFD:0));
808
809
810
811
812
813
814
815 DELAY(100000);
816
817 for (i = 0; i < XL_TIMEOUT; i++) {
818 DELAY(10);
819 if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY))
820 break;
821 }
822
823 if (i == XL_TIMEOUT)
824 printf("%s: reset didn't complete\n", sc->sc_dev.dv_xname);
825
826
827
828
829
830
831
832 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
833 DELAY(100000);
834 xl_wait(sc);
835 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
836 xl_wait(sc);
837
838 if (sc->xl_flags & XL_FLAG_INVERT_LED_PWR ||
839 sc->xl_flags & XL_FLAG_INVERT_MII_PWR) {
840 XL_SEL_WIN(2);
841 CSR_WRITE_2(sc, XL_W2_RESET_OPTIONS, CSR_READ_2(sc,
842 XL_W2_RESET_OPTIONS)
843 | ((sc->xl_flags & XL_FLAG_INVERT_LED_PWR)?XL_RESETOPT_INVERT_LED:0)
844 | ((sc->xl_flags & XL_FLAG_INVERT_MII_PWR)?XL_RESETOPT_INVERT_MII:0)
845 );
846 }
847
848
849 DELAY(100000);
850 }
851
852
853
854
855
856
857
858
859
860
861
862
863
864 void
865 xl_mediacheck(struct xl_softc *sc)
866 {
867
868
869
870
871
872
873 if (sc->xl_media & (XL_MEDIAOPT_MASK & ~XL_MEDIAOPT_VCO)) {
874
875
876
877
878 if (sc->xl_xcvr <= XL_XCVR_AUTO)
879 return;
880 else {
881 printf("%s: bogus xcvr value "
882 "in EEPROM (%x)\n", sc->sc_dev.dv_xname, sc->xl_xcvr);
883 printf("%s: choosing new default based "
884 "on card type\n", sc->sc_dev.dv_xname);
885 }
886 } else {
887 if (sc->xl_type == XL_TYPE_905B &&
888 sc->xl_media & XL_MEDIAOPT_10FL)
889 return;
890 printf("%s: WARNING: no media options bits set in "
891 "the media options register!!\n", sc->sc_dev.dv_xname);
892 printf("%s: this could be a manufacturing defect in "
893 "your adapter or system\n", sc->sc_dev.dv_xname);
894 printf("%s: attempting to guess media type; you "
895 "should probably consult your vendor\n", sc->sc_dev.dv_xname);
896 }
897
898 xl_choose_xcvr(sc, 1);
899 }
900
901 void
902 xl_choose_xcvr(struct xl_softc *sc, int verbose)
903 {
904 u_int16_t devid;
905
906
907
908
909
910
911 xl_read_eeprom(sc, (caddr_t)&devid, XL_EE_PRODID, 1, 0);
912
913 switch(devid) {
914 case TC_DEVICEID_BOOMERANG_10BT:
915 case TC_DEVICEID_KRAKATOA_10BT:
916 sc->xl_media = XL_MEDIAOPT_BT;
917 sc->xl_xcvr = XL_XCVR_10BT;
918 if (verbose)
919 printf("%s: guessing 10BaseT transceiver\n",
920 sc->sc_dev.dv_xname);
921 break;
922 case TC_DEVICEID_BOOMERANG_10BT_COMBO:
923 case TC_DEVICEID_KRAKATOA_10BT_COMBO:
924 sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI;
925 sc->xl_xcvr = XL_XCVR_10BT;
926 if (verbose)
927 printf("%s: guessing COMBO (AUI/BNC/TP)\n",
928 sc->sc_dev.dv_xname);
929 break;
930 case TC_DEVICEID_KRAKATOA_10BT_TPC:
931 sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC;
932 sc->xl_xcvr = XL_XCVR_10BT;
933 if (verbose)
934 printf("%s: guessing TPC (BNC/TP)\n", sc->sc_dev.dv_xname);
935 break;
936 case TC_DEVICEID_CYCLONE_10FL:
937 sc->xl_media = XL_MEDIAOPT_10FL;
938 sc->xl_xcvr = XL_XCVR_AUI;
939 if (verbose)
940 printf("%s: guessing 10baseFL\n", sc->sc_dev.dv_xname);
941 break;
942 case TC_DEVICEID_BOOMERANG_10_100BT:
943 case TC_DEVICEID_HURRICANE_555:
944 case TC_DEVICEID_HURRICANE_556:
945 case TC_DEVICEID_HURRICANE_556B:
946 case TC_DEVICEID_HURRICANE_575A:
947 case TC_DEVICEID_HURRICANE_575B:
948 case TC_DEVICEID_HURRICANE_575C:
949 case TC_DEVICEID_HURRICANE_656:
950 case TC_DEVICEID_HURRICANE_656B:
951 case TC_DEVICEID_TORNADO_656C:
952 case TC_DEVICEID_TORNADO_10_100BT_920B:
953 sc->xl_media = XL_MEDIAOPT_MII;
954 sc->xl_xcvr = XL_XCVR_MII;
955 if (verbose)
956 printf("%s: guessing MII\n", sc->sc_dev.dv_xname);
957 break;
958 case TC_DEVICEID_BOOMERANG_100BT4:
959 case TC_DEVICEID_CYCLONE_10_100BT4:
960 sc->xl_media = XL_MEDIAOPT_BT4;
961 sc->xl_xcvr = XL_XCVR_MII;
962 if (verbose)
963 printf("%s: guessing 100BaseT4/MII\n", sc->sc_dev.dv_xname);
964 break;
965 case TC_DEVICEID_HURRICANE_10_100BT:
966 case TC_DEVICEID_HURRICANE_10_100BT_SERV:
967 case TC_DEVICEID_TORNADO_10_100BT_SERV:
968 case TC_DEVICEID_HURRICANE_SOHO100TX:
969 case TC_DEVICEID_TORNADO_10_100BT:
970 case TC_DEVICEID_TORNADO_HOMECONNECT:
971 sc->xl_media = XL_MEDIAOPT_BTX;
972 sc->xl_xcvr = XL_XCVR_AUTO;
973 if (verbose)
974 printf("%s: guessing 10/100 internal\n",
975 sc->sc_dev.dv_xname);
976 break;
977 case TC_DEVICEID_CYCLONE_10_100_COMBO:
978 sc->xl_media = XL_MEDIAOPT_BTX|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI;
979 sc->xl_xcvr = XL_XCVR_AUTO;
980 if (verbose)
981 printf("%s: guessing 10/100 plus BNC/AUI\n",
982 sc->sc_dev.dv_xname);
983 break;
984 default:
985 printf("%s: unknown device ID: %x -- "
986 "defaulting to 10baseT\n", sc->sc_dev.dv_xname, devid);
987 sc->xl_media = XL_MEDIAOPT_BT;
988 break;
989 }
990 }
991
992
993
994
995 int
996 xl_list_tx_init(struct xl_softc *sc)
997 {
998 struct xl_chain_data *cd;
999 struct xl_list_data *ld;
1000 int i;
1001
1002 cd = &sc->xl_cdata;
1003 ld = sc->xl_ldata;
1004 for (i = 0; i < XL_TX_LIST_CNT; i++) {
1005 cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
1006 if (i == (XL_TX_LIST_CNT - 1))
1007 cd->xl_tx_chain[i].xl_next = NULL;
1008 else
1009 cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1];
1010 }
1011
1012 cd->xl_tx_free = &cd->xl_tx_chain[0];
1013 cd->xl_tx_tail = cd->xl_tx_head = NULL;
1014
1015 return (0);
1016 }
1017
1018
1019
1020
1021 int
1022 xl_list_tx_init_90xB(struct xl_softc *sc)
1023 {
1024 struct xl_chain_data *cd;
1025 struct xl_list_data *ld;
1026 int i, next, prev;
1027
1028 cd = &sc->xl_cdata;
1029 ld = sc->xl_ldata;
1030 for (i = 0; i < XL_TX_LIST_CNT; i++) {
1031 if (i == (XL_TX_LIST_CNT - 1))
1032 next = 0;
1033 else
1034 next = i + 1;
1035 if (i == 0)
1036 prev = XL_TX_LIST_CNT - 1;
1037 else
1038 prev = i - 1;
1039 cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
1040 cd->xl_tx_chain[i].xl_phys =
1041 sc->sc_listmap->dm_segs[0].ds_addr +
1042 offsetof(struct xl_list_data, xl_tx_list[i]);
1043 cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[next];
1044 cd->xl_tx_chain[i].xl_prev = &cd->xl_tx_chain[prev];
1045 }
1046
1047 bzero((char *)ld->xl_tx_list, sizeof(struct xl_list) * XL_TX_LIST_CNT);
1048 ld->xl_tx_list[0].xl_status = htole32(XL_TXSTAT_EMPTY);
1049
1050 cd->xl_tx_prod = 1;
1051 cd->xl_tx_cons = 1;
1052 cd->xl_tx_cnt = 0;
1053
1054 return (0);
1055 }
1056
1057
1058
1059
1060
1061
1062 int
1063 xl_list_rx_init(struct xl_softc *sc)
1064 {
1065 struct xl_chain_data *cd;
1066 struct xl_list_data *ld;
1067 int i, n;
1068 bus_addr_t next;
1069
1070 cd = &sc->xl_cdata;
1071 ld = sc->xl_ldata;
1072
1073 for (i = 0; i < XL_RX_LIST_CNT; i++) {
1074 cd->xl_rx_chain[i].xl_ptr =
1075 (struct xl_list_onefrag *)&ld->xl_rx_list[i];
1076 if (xl_newbuf(sc, &cd->xl_rx_chain[i]) == ENOBUFS)
1077 return(ENOBUFS);
1078 if (i == (XL_RX_LIST_CNT - 1))
1079 n = 0;
1080 else
1081 n = i + 1;
1082 cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[n];
1083 next = sc->sc_listmap->dm_segs[0].ds_addr +
1084 offsetof(struct xl_list_data, xl_rx_list[n]);
1085 ld->xl_rx_list[i].xl_next = htole32(next);
1086 }
1087
1088 cd->xl_rx_head = &cd->xl_rx_chain[0];
1089
1090 return (0);
1091 }
1092
1093
1094
1095
1096 int
1097 xl_newbuf(struct xl_softc *sc, struct xl_chain_onefrag *c)
1098 {
1099 struct mbuf *m_new = NULL;
1100 bus_dmamap_t map;
1101
1102 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1103 if (m_new == NULL)
1104 return (ENOBUFS);
1105
1106 MCLGET(m_new, M_DONTWAIT);
1107 if (!(m_new->m_flags & M_EXT)) {
1108 m_freem(m_new);
1109 return (ENOBUFS);
1110 }
1111
1112 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
1113 if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_sparemap,
1114 mtod(m_new, caddr_t), MCLBYTES, NULL, BUS_DMA_NOWAIT) != 0) {
1115 m_freem(m_new);
1116 return (ENOBUFS);
1117 }
1118
1119
1120 if (c->map->dm_nsegs != 0) {
1121 bus_dmamap_sync(sc->sc_dmat, c->map,
1122 0, c->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1123 bus_dmamap_unload(sc->sc_dmat, c->map);
1124 }
1125
1126 map = c->map;
1127 c->map = sc->sc_rx_sparemap;
1128 sc->sc_rx_sparemap = map;
1129
1130
1131 m_adj(m_new, ETHER_ALIGN);
1132
1133 bus_dmamap_sync(sc->sc_dmat, c->map, 0, c->map->dm_mapsize,
1134 BUS_DMASYNC_PREREAD);
1135
1136 c->xl_mbuf = m_new;
1137 c->xl_ptr->xl_frag.xl_addr =
1138 htole32(c->map->dm_segs[0].ds_addr + ETHER_ALIGN);
1139 c->xl_ptr->xl_frag.xl_len =
1140 htole32(c->map->dm_segs[0].ds_len | XL_LAST_FRAG);
1141 c->xl_ptr->xl_status = htole32(0);
1142
1143 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1144 ((caddr_t)c->xl_ptr - sc->sc_listkva), sizeof(struct xl_list),
1145 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1146
1147 return (0);
1148 }
1149
1150 int
1151 xl_rx_resync(struct xl_softc *sc)
1152 {
1153 struct xl_chain_onefrag *pos;
1154 int i;
1155
1156 pos = sc->xl_cdata.xl_rx_head;
1157
1158 for (i = 0; i < XL_RX_LIST_CNT; i++) {
1159 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1160 ((caddr_t)pos->xl_ptr - sc->sc_listkva),
1161 sizeof(struct xl_list),
1162 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1163
1164 if (pos->xl_ptr->xl_status)
1165 break;
1166 pos = pos->xl_next;
1167 }
1168
1169 if (i == XL_RX_LIST_CNT)
1170 return (0);
1171
1172 sc->xl_cdata.xl_rx_head = pos;
1173
1174 return (EAGAIN);
1175 }
1176
1177
1178
1179
1180
1181 void
1182 xl_rxeof(struct xl_softc *sc)
1183 {
1184 struct mbuf *m;
1185 struct ifnet *ifp;
1186 struct xl_chain_onefrag *cur_rx;
1187 int total_len = 0, sumflags = 0;
1188 u_int32_t rxstat;
1189
1190 ifp = &sc->sc_arpcom.ac_if;
1191
1192 again:
1193
1194 while ((rxstat = letoh32(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))
1195 != 0) {
1196 cur_rx = sc->xl_cdata.xl_rx_head;
1197 sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
1198 total_len = rxstat & XL_RXSTAT_LENMASK;
1199
1200 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1201 ((caddr_t)cur_rx->xl_ptr - sc->sc_listkva),
1202 sizeof(struct xl_list),
1203 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1204
1205
1206
1207
1208
1209
1210
1211 if (total_len > XL_MAX_FRAMELEN)
1212 rxstat |= (XL_RXSTAT_UP_ERROR|XL_RXSTAT_OVERSIZE);
1213
1214
1215
1216
1217
1218
1219
1220 if (rxstat & XL_RXSTAT_UP_ERROR) {
1221 ifp->if_ierrors++;
1222 cur_rx->xl_ptr->xl_status = htole32(0);
1223 continue;
1224 }
1225
1226
1227
1228
1229
1230
1231 if (!(rxstat & XL_RXSTAT_UP_CMPLT)) {
1232 printf("%s: bad receive status -- "
1233 "packet dropped\n", sc->sc_dev.dv_xname);
1234 ifp->if_ierrors++;
1235 cur_rx->xl_ptr->xl_status = htole32(0);
1236 continue;
1237 }
1238
1239
1240 m = cur_rx->xl_mbuf;
1241
1242
1243
1244
1245
1246
1247
1248
1249 if (xl_newbuf(sc, cur_rx) == ENOBUFS) {
1250 ifp->if_ierrors++;
1251 cur_rx->xl_ptr->xl_status = htole32(0);
1252 continue;
1253 }
1254
1255 ifp->if_ipackets++;
1256 m->m_pkthdr.rcvif = ifp;
1257 m->m_pkthdr.len = m->m_len = total_len;
1258 #if NBPFILTER > 0
1259
1260
1261
1262 if (ifp->if_bpf) {
1263 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1264 }
1265 #endif
1266
1267 if (sc->xl_type == XL_TYPE_905B) {
1268 if (!(rxstat & XL_RXSTAT_IPCKERR) &&
1269 (rxstat & XL_RXSTAT_IPCKOK))
1270 sumflags |= M_IPV4_CSUM_IN_OK;
1271
1272 if (!(rxstat & XL_RXSTAT_TCPCKERR) &&
1273 (rxstat & XL_RXSTAT_TCPCKOK))
1274 sumflags |= M_TCP_CSUM_IN_OK;
1275
1276 if (!(rxstat & XL_RXSTAT_UDPCKERR) &&
1277 (rxstat & XL_RXSTAT_UDPCKOK))
1278 sumflags |= M_UDP_CSUM_IN_OK;
1279
1280 m->m_pkthdr.csum_flags = sumflags;
1281 }
1282
1283 ether_input_mbuf(ifp, m);
1284 }
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298 if (CSR_READ_4(sc, XL_UPLIST_PTR) == 0 ||
1299 CSR_READ_4(sc, XL_UPLIST_STATUS) & XL_PKTSTAT_UP_STALLED) {
1300 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
1301 xl_wait(sc);
1302 CSR_WRITE_4(sc, XL_UPLIST_PTR,
1303 sc->sc_listmap->dm_segs[0].ds_addr +
1304 offsetof(struct xl_list_data, xl_rx_list[0]));
1305 sc->xl_cdata.xl_rx_head = &sc->xl_cdata.xl_rx_chain[0];
1306 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
1307 goto again;
1308 }
1309 }
1310
1311
1312
1313
1314
1315 void
1316 xl_txeof(struct xl_softc *sc)
1317 {
1318 struct xl_chain *cur_tx;
1319 struct ifnet *ifp;
1320
1321 ifp = &sc->sc_arpcom.ac_if;
1322
1323
1324 ifp->if_timer = 0;
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335 while (sc->xl_cdata.xl_tx_head != NULL) {
1336 cur_tx = sc->xl_cdata.xl_tx_head;
1337
1338 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1339 ((caddr_t)cur_tx->xl_ptr - sc->sc_listkva),
1340 sizeof(struct xl_list),
1341 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1342
1343 if (CSR_READ_4(sc, XL_DOWNLIST_PTR))
1344 break;
1345
1346 sc->xl_cdata.xl_tx_head = cur_tx->xl_next;
1347 ifp->if_opackets++;
1348 if (cur_tx->map->dm_nsegs != 0) {
1349 bus_dmamap_t map = cur_tx->map;
1350
1351 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
1352 BUS_DMASYNC_POSTWRITE);
1353 bus_dmamap_unload(sc->sc_dmat, map);
1354 }
1355 if (cur_tx->xl_mbuf != NULL) {
1356 m_freem(cur_tx->xl_mbuf);
1357 cur_tx->xl_mbuf = NULL;
1358 }
1359 cur_tx->xl_next = sc->xl_cdata.xl_tx_free;
1360 sc->xl_cdata.xl_tx_free = cur_tx;
1361 }
1362
1363 if (sc->xl_cdata.xl_tx_head == NULL) {
1364 ifp->if_flags &= ~IFF_OACTIVE;
1365 sc->xl_cdata.xl_tx_tail = NULL;
1366 } else {
1367 if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED ||
1368 !CSR_READ_4(sc, XL_DOWNLIST_PTR)) {
1369 CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
1370 sc->sc_listmap->dm_segs[0].ds_addr +
1371 ((caddr_t)sc->xl_cdata.xl_tx_head->xl_ptr -
1372 sc->sc_listkva));
1373 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
1374 }
1375 }
1376 }
1377
1378 void
1379 xl_txeof_90xB(struct xl_softc *sc)
1380 {
1381 struct xl_chain *cur_tx = NULL;
1382 struct ifnet *ifp;
1383 int idx;
1384
1385 ifp = &sc->sc_arpcom.ac_if;
1386
1387 idx = sc->xl_cdata.xl_tx_cons;
1388 while (idx != sc->xl_cdata.xl_tx_prod) {
1389
1390 cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
1391
1392 if ((cur_tx->xl_ptr->xl_status &
1393 htole32(XL_TXSTAT_DL_COMPLETE)) == 0)
1394 break;
1395
1396 if (cur_tx->xl_mbuf != NULL) {
1397 m_freem(cur_tx->xl_mbuf);
1398 cur_tx->xl_mbuf = NULL;
1399 }
1400
1401 if (cur_tx->map->dm_nsegs != 0) {
1402 bus_dmamap_sync(sc->sc_dmat, cur_tx->map,
1403 0, cur_tx->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1404 bus_dmamap_unload(sc->sc_dmat, cur_tx->map);
1405 }
1406
1407 ifp->if_opackets++;
1408
1409 sc->xl_cdata.xl_tx_cnt--;
1410 XL_INC(idx, XL_TX_LIST_CNT);
1411 ifp->if_timer = 0;
1412 }
1413
1414 sc->xl_cdata.xl_tx_cons = idx;
1415
1416 if (cur_tx != NULL)
1417 ifp->if_flags &= ~IFF_OACTIVE;
1418 }
1419
1420
1421
1422
1423
1424
1425 void
1426 xl_txeoc(struct xl_softc *sc)
1427 {
1428 u_int8_t txstat;
1429
1430 while ((txstat = CSR_READ_1(sc, XL_TX_STATUS))) {
1431 if (txstat & XL_TXSTATUS_UNDERRUN ||
1432 txstat & XL_TXSTATUS_JABBER ||
1433 txstat & XL_TXSTATUS_RECLAIM) {
1434 if (txstat != 0x90) {
1435 printf("%s: transmission error: %x\n",
1436 sc->sc_dev.dv_xname, txstat);
1437 }
1438 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
1439 xl_wait(sc);
1440 if (sc->xl_type == XL_TYPE_905B) {
1441 if (sc->xl_cdata.xl_tx_cnt) {
1442 int i;
1443 struct xl_chain *c;
1444
1445 i = sc->xl_cdata.xl_tx_cons;
1446 c = &sc->xl_cdata.xl_tx_chain[i];
1447 CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
1448 c->xl_phys);
1449 CSR_WRITE_1(sc, XL_DOWN_POLL, 64);
1450 }
1451 } else {
1452 if (sc->xl_cdata.xl_tx_head != NULL)
1453 CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
1454 sc->sc_listmap->dm_segs[0].ds_addr +
1455 ((caddr_t)sc->xl_cdata.xl_tx_head->xl_ptr -
1456 sc->sc_listkva));
1457 }
1458
1459
1460
1461
1462 CSR_WRITE_1(sc, XL_TX_FREETHRESH, XL_PACKET_SIZE >> 8);
1463 if (txstat & XL_TXSTATUS_UNDERRUN &&
1464 sc->xl_tx_thresh < XL_PACKET_SIZE) {
1465 sc->xl_tx_thresh += XL_MIN_FRAMELEN;
1466 #ifdef notdef
1467 printf("%s: tx underrun, increasing tx start"
1468 " threshold to %d\n", sc->sc_dev.dv_xname,
1469 sc->xl_tx_thresh);
1470 #endif
1471 }
1472 CSR_WRITE_2(sc, XL_COMMAND,
1473 XL_CMD_TX_SET_START|sc->xl_tx_thresh);
1474 if (sc->xl_type == XL_TYPE_905B) {
1475 CSR_WRITE_2(sc, XL_COMMAND,
1476 XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4));
1477 }
1478 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
1479 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
1480 } else {
1481 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
1482 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
1483 }
1484
1485
1486
1487
1488 CSR_WRITE_1(sc, XL_TX_STATUS, 0x01);
1489 }
1490 }
1491
1492 int
1493 xl_intr(void *arg)
1494 {
1495 struct xl_softc *sc;
1496 struct ifnet *ifp;
1497 u_int16_t status;
1498 int claimed = 0;
1499
1500 sc = arg;
1501 ifp = &sc->sc_arpcom.ac_if;
1502
1503 while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && status != 0xFFFF) {
1504
1505 claimed = 1;
1506
1507 CSR_WRITE_2(sc, XL_COMMAND,
1508 XL_CMD_INTR_ACK|(status & XL_INTRS));
1509
1510 if (sc->intr_ack)
1511 (*sc->intr_ack)(sc);
1512
1513 if (status & XL_STAT_UP_COMPLETE) {
1514 int curpkts;
1515
1516 curpkts = ifp->if_ipackets;
1517 xl_rxeof(sc);
1518 if (curpkts == ifp->if_ipackets) {
1519 while (xl_rx_resync(sc))
1520 xl_rxeof(sc);
1521 }
1522 }
1523
1524 if (status & XL_STAT_DOWN_COMPLETE) {
1525 if (sc->xl_type == XL_TYPE_905B)
1526 xl_txeof_90xB(sc);
1527 else
1528 xl_txeof(sc);
1529 }
1530
1531 if (status & XL_STAT_TX_COMPLETE) {
1532 ifp->if_oerrors++;
1533 xl_txeoc(sc);
1534 }
1535
1536 if (status & XL_STAT_ADFAIL) {
1537 xl_reset(sc);
1538 xl_init(sc);
1539 }
1540
1541 if (status & XL_STAT_STATSOFLOW) {
1542 sc->xl_stats_no_timeout = 1;
1543 xl_stats_update(sc);
1544 sc->xl_stats_no_timeout = 0;
1545 }
1546 }
1547
1548 if (!IFQ_IS_EMPTY(&ifp->if_snd))
1549 (*ifp->if_start)(ifp);
1550
1551 return (claimed);
1552 }
1553
1554 void
1555 xl_stats_update(void *xsc)
1556 {
1557 struct xl_softc *sc;
1558 struct ifnet *ifp;
1559 struct xl_stats xl_stats;
1560 u_int8_t *p;
1561 int i;
1562 struct mii_data *mii = NULL;
1563
1564 bzero((char *)&xl_stats, sizeof(struct xl_stats));
1565
1566 sc = xsc;
1567 ifp = &sc->sc_arpcom.ac_if;
1568 if (sc->xl_hasmii)
1569 mii = &sc->sc_mii;
1570
1571 p = (u_int8_t *)&xl_stats;
1572
1573
1574 XL_SEL_WIN(6);
1575
1576 for (i = 0; i < 16; i++)
1577 *p++ = CSR_READ_1(sc, XL_W6_CARRIER_LOST + i);
1578
1579 ifp->if_ierrors += xl_stats.xl_rx_overrun;
1580
1581 ifp->if_collisions += xl_stats.xl_tx_multi_collision +
1582 xl_stats.xl_tx_single_collision +
1583 xl_stats.xl_tx_late_collision;
1584
1585
1586
1587
1588
1589
1590
1591 XL_SEL_WIN(4);
1592 CSR_READ_1(sc, XL_W4_BADSSD);
1593
1594 if (mii != NULL && (!sc->xl_stats_no_timeout))
1595 mii_tick(mii);
1596
1597 XL_SEL_WIN(7);
1598
1599 if (!sc->xl_stats_no_timeout)
1600 timeout_add(&sc->xl_stsup_tmo, hz);
1601 }
1602
1603
1604
1605
1606
1607 int
1608 xl_encap(struct xl_softc *sc, struct xl_chain *c, struct mbuf *m_head)
1609 {
1610 int error, frag, total_len;
1611 u_int32_t status;
1612 bus_dmamap_t map;
1613
1614 map = sc->sc_tx_sparemap;
1615
1616 reload:
1617 error = bus_dmamap_load_mbuf(sc->sc_dmat, map,
1618 m_head, BUS_DMA_NOWAIT);
1619
1620 if (error && error != EFBIG) {
1621 m_freem(m_head);
1622 return (1);
1623 }
1624
1625
1626
1627
1628
1629
1630 for (frag = 0, total_len = 0; frag < map->dm_nsegs; frag++) {
1631 if (frag == XL_MAXFRAGS)
1632 break;
1633 total_len += map->dm_segs[frag].ds_len;
1634 c->xl_ptr->xl_frag[frag].xl_addr =
1635 htole32(map->dm_segs[frag].ds_addr);
1636 c->xl_ptr->xl_frag[frag].xl_len =
1637 htole32(map->dm_segs[frag].ds_len);
1638 }
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648 if (error) {
1649 struct mbuf *m_new = NULL;
1650
1651 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1652 if (m_new == NULL) {
1653 m_freem(m_head);
1654 return (1);
1655 }
1656 if (m_head->m_pkthdr.len > MHLEN) {
1657 MCLGET(m_new, M_DONTWAIT);
1658 if (!(m_new->m_flags & M_EXT)) {
1659 m_freem(m_new);
1660 m_freem(m_head);
1661 return (1);
1662 }
1663 }
1664 m_copydata(m_head, 0, m_head->m_pkthdr.len,
1665 mtod(m_new, caddr_t));
1666 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
1667 m_freem(m_head);
1668 m_head = m_new;
1669 goto reload;
1670 }
1671
1672 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
1673 BUS_DMASYNC_PREWRITE);
1674
1675 if (c->map->dm_nsegs != 0) {
1676 bus_dmamap_sync(sc->sc_dmat, c->map,
1677 0, c->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1678 bus_dmamap_unload(sc->sc_dmat, c->map);
1679 }
1680
1681 c->xl_mbuf = m_head;
1682 sc->sc_tx_sparemap = c->map;
1683 c->map = map;
1684 c->xl_ptr->xl_frag[frag - 1].xl_len |= htole32(XL_LAST_FRAG);
1685 c->xl_ptr->xl_status = htole32(total_len);
1686 c->xl_ptr->xl_next = 0;
1687
1688 if (sc->xl_type == XL_TYPE_905B) {
1689 status = XL_TXSTAT_RND_DEFEAT;
1690
1691 #ifndef XL905B_TXCSUM_BROKEN
1692 if (m_head->m_pkthdr.csum_flags) {
1693 if (m_head->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
1694 status |= XL_TXSTAT_IPCKSUM;
1695 if (m_head->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
1696 status |= XL_TXSTAT_TCPCKSUM;
1697 if (m_head->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
1698 status |= XL_TXSTAT_UDPCKSUM;
1699 }
1700 #endif
1701 c->xl_ptr->xl_status = htole32(status);
1702 }
1703
1704 bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
1705 offsetof(struct xl_list_data, xl_tx_list[0]),
1706 sizeof(struct xl_list) * XL_TX_LIST_CNT,
1707 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1708
1709 return (0);
1710 }
1711
1712
1713
1714
1715
1716
1717
1718 void
1719 xl_start(struct ifnet *ifp)
1720 {
1721 struct xl_softc *sc;
1722 struct mbuf *m_head = NULL;
1723 struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
1724 struct xl_chain *prev_tx;
1725 int error;
1726
1727 sc = ifp->if_softc;
1728
1729
1730
1731
1732
1733 if (sc->xl_cdata.xl_tx_free == NULL) {
1734 xl_txeoc(sc);
1735 xl_txeof(sc);
1736 if (sc->xl_cdata.xl_tx_free == NULL) {
1737 ifp->if_flags |= IFF_OACTIVE;
1738 return;
1739 }
1740 }
1741
1742 start_tx = sc->xl_cdata.xl_tx_free;
1743
1744 while (sc->xl_cdata.xl_tx_free != NULL) {
1745 IFQ_DEQUEUE(&ifp->if_snd, m_head);
1746 if (m_head == NULL)
1747 break;
1748
1749
1750 prev_tx = cur_tx;
1751 cur_tx = sc->xl_cdata.xl_tx_free;
1752
1753
1754 error = xl_encap(sc, cur_tx, m_head);
1755 if (error) {
1756 cur_tx = prev_tx;
1757 continue;
1758 }
1759
1760 sc->xl_cdata.xl_tx_free = cur_tx->xl_next;
1761 cur_tx->xl_next = NULL;
1762
1763
1764 if (prev != NULL) {
1765 prev->xl_next = cur_tx;
1766 prev->xl_ptr->xl_next =
1767 sc->sc_listmap->dm_segs[0].ds_addr +
1768 ((caddr_t)cur_tx->xl_ptr - sc->sc_listkva);
1769
1770 }
1771 prev = cur_tx;
1772
1773 #if NBPFILTER > 0
1774
1775
1776
1777
1778 if (ifp->if_bpf)
1779 bpf_mtap(ifp->if_bpf, cur_tx->xl_mbuf,
1780 BPF_DIRECTION_OUT);
1781 #endif
1782 }
1783
1784
1785
1786
1787 if (cur_tx == NULL)
1788 return;
1789
1790
1791
1792
1793
1794
1795
1796
1797 cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR);
1798
1799
1800
1801
1802
1803 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL);
1804 xl_wait(sc);
1805
1806 if (sc->xl_cdata.xl_tx_head != NULL) {
1807 sc->xl_cdata.xl_tx_tail->xl_next = start_tx;
1808 sc->xl_cdata.xl_tx_tail->xl_ptr->xl_next =
1809 sc->sc_listmap->dm_segs[0].ds_addr +
1810 ((caddr_t)start_tx->xl_ptr - sc->sc_listkva);
1811 sc->xl_cdata.xl_tx_tail->xl_ptr->xl_status &=
1812 htole32(~XL_TXSTAT_DL_INTR);
1813 sc->xl_cdata.xl_tx_tail = cur_tx;
1814 } else {
1815 sc->xl_cdata.xl_tx_head = start_tx;
1816 sc->xl_cdata.xl_tx_tail = cur_tx;
1817 }
1818 if (!CSR_READ_4(sc, XL_DOWNLIST_PTR))
1819 CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
1820 sc->sc_listmap->dm_segs[0].ds_addr +
1821 ((caddr_t)start_tx->xl_ptr - sc->sc_listkva));
1822
1823 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
1824
1825 XL_SEL_WIN(7);
1826
1827
1828
1829
1830 ifp->if_timer = 5;
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847 xl_rxeof(sc);
1848 }
1849
1850 void
1851 xl_start_90xB(struct ifnet *ifp)
1852 {
1853 struct xl_softc *sc;
1854 struct mbuf *m_head = NULL;
1855 struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
1856 struct xl_chain *prev_tx;
1857 int error, idx;
1858
1859 sc = ifp->if_softc;
1860
1861 if (ifp->if_flags & IFF_OACTIVE)
1862 return;
1863
1864 idx = sc->xl_cdata.xl_tx_prod;
1865 start_tx = &sc->xl_cdata.xl_tx_chain[idx];
1866
1867 while (sc->xl_cdata.xl_tx_chain[idx].xl_mbuf == NULL) {
1868
1869 if ((XL_TX_LIST_CNT - sc->xl_cdata.xl_tx_cnt) < 3) {
1870 ifp->if_flags |= IFF_OACTIVE;
1871 break;
1872 }
1873
1874 IFQ_DEQUEUE(&ifp->if_snd, m_head);
1875 if (m_head == NULL)
1876 break;
1877
1878 prev_tx = cur_tx;
1879 cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
1880
1881
1882 error = xl_encap(sc, cur_tx, m_head);
1883 if (error) {
1884 cur_tx = prev_tx;
1885 continue;
1886 }
1887
1888
1889 if (prev != NULL)
1890 prev->xl_ptr->xl_next = htole32(cur_tx->xl_phys);
1891 prev = cur_tx;
1892
1893 #if NBPFILTER > 0
1894
1895
1896
1897
1898 if (ifp->if_bpf)
1899 bpf_mtap(ifp->if_bpf, cur_tx->xl_mbuf,
1900 BPF_DIRECTION_OUT);
1901 #endif
1902
1903 XL_INC(idx, XL_TX_LIST_CNT);
1904 sc->xl_cdata.xl_tx_cnt++;
1905 }
1906
1907
1908
1909
1910 if (cur_tx == NULL)
1911 return;
1912
1913
1914
1915
1916
1917
1918
1919
1920 cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR);
1921
1922
1923 sc->xl_cdata.xl_tx_prod = idx;
1924 start_tx->xl_prev->xl_ptr->xl_next = htole32(start_tx->xl_phys);
1925
1926
1927
1928
1929 ifp->if_timer = 5;
1930 }
1931
1932 void
1933 xl_init(void *xsc)
1934 {
1935 struct xl_softc *sc = xsc;
1936 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1937 int s, i;
1938 u_int16_t rxfilt = 0;
1939 struct mii_data *mii = NULL;
1940
1941 s = splnet();
1942
1943
1944
1945
1946 xl_stop(sc);
1947
1948 if (sc->xl_hasmii)
1949 mii = &sc->sc_mii;
1950
1951 if (mii == NULL) {
1952 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
1953 xl_wait(sc);
1954 }
1955 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
1956 xl_wait(sc);
1957 DELAY(10000);
1958
1959
1960 XL_SEL_WIN(2);
1961 for (i = 0; i < ETHER_ADDR_LEN; i++) {
1962 CSR_WRITE_1(sc, XL_W2_STATION_ADDR_LO + i,
1963 sc->sc_arpcom.ac_enaddr[i]);
1964 }
1965
1966
1967 for (i = 0; i < 3; i++)
1968 CSR_WRITE_2(sc, XL_W2_STATION_MASK_LO + (i * 2), 0);
1969 #ifdef notdef
1970
1971 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
1972 xl_wait(sc);
1973 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
1974 xl_wait(sc);
1975 #endif
1976
1977 if (xl_list_rx_init(sc) == ENOBUFS) {
1978 printf("%s: initialization failed: no "
1979 "memory for rx buffers\n", sc->sc_dev.dv_xname);
1980 xl_stop(sc);
1981 splx(s);
1982 return;
1983 }
1984
1985
1986 if (sc->xl_type == XL_TYPE_905B)
1987 xl_list_tx_init_90xB(sc);
1988 else
1989 xl_list_tx_init(sc);
1990
1991
1992
1993
1994
1995
1996
1997 CSR_WRITE_1(sc, XL_TX_FREETHRESH, XL_PACKET_SIZE >> 8);
1998
1999
2000 sc->xl_tx_thresh = XL_MIN_FRAMELEN;
2001 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_SET_START|sc->xl_tx_thresh);
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012 if (sc->xl_type == XL_TYPE_905B) {
2013 CSR_WRITE_2(sc, XL_COMMAND,
2014 XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4));
2015 }
2016
2017
2018 XL_SEL_WIN(5);
2019 rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
2020
2021
2022 rxfilt |= XL_RXFILTER_INDIVIDUAL;
2023
2024 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
2025
2026
2027 xl_setpromisc(sc);
2028
2029 rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
2030
2031
2032
2033
2034 if (ifp->if_flags & IFF_BROADCAST)
2035 rxfilt |= XL_RXFILTER_BROADCAST;
2036 else
2037 rxfilt &= ~XL_RXFILTER_BROADCAST;
2038
2039 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
2040
2041
2042
2043
2044 if (sc->xl_type == XL_TYPE_905B)
2045 xl_setmulti_hash(sc);
2046 else
2047 xl_setmulti(sc);
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
2060 xl_wait(sc);
2061 CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->sc_listmap->dm_segs[0].ds_addr +
2062 offsetof(struct xl_list_data, xl_rx_list[0]));
2063 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
2064 xl_wait(sc);
2065
2066 if (sc->xl_type == XL_TYPE_905B) {
2067
2068 CSR_WRITE_1(sc, XL_DOWN_POLL, 64);
2069
2070 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL);
2071 xl_wait(sc);
2072 CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
2073 sc->sc_listmap->dm_segs[0].ds_addr +
2074 offsetof(struct xl_list_data, xl_tx_list[0]));
2075 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
2076 xl_wait(sc);
2077 }
2078
2079
2080
2081
2082
2083 XL_SEL_WIN(3);
2084 if (sc->xl_xcvr == XL_XCVR_COAX)
2085 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START);
2086 else
2087 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
2088
2089
2090
2091
2092
2093
2094
2095
2096 if (sc->xl_type == XL_TYPE_905B)
2097 CSR_WRITE_2(sc, XL_W3_MAXPKTSIZE, XL_PACKET_SIZE);
2098 else {
2099 u_int8_t macctl;
2100 macctl = CSR_READ_1(sc, XL_W3_MAC_CTRL);
2101 macctl |= XL_MACCTRL_ALLOW_LARGE_PACK;
2102 CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl);
2103 }
2104
2105
2106 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
2107 sc->xl_stats_no_timeout = 1;
2108 xl_stats_update(sc);
2109 sc->xl_stats_no_timeout = 0;
2110 XL_SEL_WIN(4);
2111 CSR_WRITE_2(sc, XL_W4_NET_DIAG, XL_NETDIAG_UPPER_BYTES_ENABLE);
2112 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_ENABLE);
2113
2114
2115
2116
2117 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
2118 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|XL_INTRS);
2119 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
2120
2121 if (sc->intr_ack)
2122 (*sc->intr_ack)(sc);
2123
2124
2125 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_THRESH|(XL_PACKET_SIZE >>2));
2126 CSR_WRITE_2(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY);
2127
2128
2129 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
2130 xl_wait(sc);
2131 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE);
2132 xl_wait(sc);
2133
2134
2135 if (mii != NULL)
2136 mii_mediachg(mii);
2137
2138
2139 XL_SEL_WIN(7);
2140
2141 ifp->if_flags |= IFF_RUNNING;
2142 ifp->if_flags &= ~IFF_OACTIVE;
2143
2144 splx(s);
2145
2146 timeout_add(&sc->xl_stsup_tmo, hz);
2147 }
2148
2149
2150
2151
2152 int
2153 xl_ifmedia_upd(struct ifnet *ifp)
2154 {
2155 struct xl_softc *sc;
2156 struct ifmedia *ifm = NULL;
2157 struct mii_data *mii = NULL;
2158
2159 sc = ifp->if_softc;
2160
2161 if (sc->xl_hasmii)
2162 mii = &sc->sc_mii;
2163 if (mii == NULL)
2164 ifm = &sc->ifmedia;
2165 else
2166 ifm = &mii->mii_media;
2167
2168 switch(IFM_SUBTYPE(ifm->ifm_media)) {
2169 case IFM_100_FX:
2170 case IFM_10_FL:
2171 case IFM_10_2:
2172 case IFM_10_5:
2173 xl_setmode(sc, ifm->ifm_media);
2174 return (0);
2175 break;
2176 default:
2177 break;
2178 }
2179
2180 if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX
2181 || sc->xl_media & XL_MEDIAOPT_BT4) {
2182 xl_init(sc);
2183 } else {
2184 xl_setmode(sc, ifm->ifm_media);
2185 }
2186
2187 return (0);
2188 }
2189
2190
2191
2192
2193 void
2194 xl_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
2195 {
2196 struct xl_softc *sc;
2197 u_int32_t icfg;
2198 u_int16_t status = 0;
2199 struct mii_data *mii = NULL;
2200
2201 sc = ifp->if_softc;
2202 if (sc->xl_hasmii != 0)
2203 mii = &sc->sc_mii;
2204
2205 XL_SEL_WIN(4);
2206 status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
2207
2208 XL_SEL_WIN(3);
2209 icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG) & XL_ICFG_CONNECTOR_MASK;
2210 icfg >>= XL_ICFG_CONNECTOR_BITS;
2211
2212 ifmr->ifm_active = IFM_ETHER;
2213 ifmr->ifm_status = IFM_AVALID;
2214
2215 if ((status & XL_MEDIASTAT_CARRIER) == 0)
2216 ifmr->ifm_status |= IFM_ACTIVE;
2217
2218 switch(icfg) {
2219 case XL_XCVR_10BT:
2220 ifmr->ifm_active = IFM_ETHER|IFM_10_T;
2221 if (CSR_READ_1(sc, XL_W3_MAC_CTRL) & XL_MACCTRL_DUPLEX)
2222 ifmr->ifm_active |= IFM_FDX;
2223 else
2224 ifmr->ifm_active |= IFM_HDX;
2225 break;
2226 case XL_XCVR_AUI:
2227 if (sc->xl_type == XL_TYPE_905B &&
2228 sc->xl_media == XL_MEDIAOPT_10FL) {
2229 ifmr->ifm_active = IFM_ETHER|IFM_10_FL;
2230 if (CSR_READ_1(sc, XL_W3_MAC_CTRL) & XL_MACCTRL_DUPLEX)
2231 ifmr->ifm_active |= IFM_FDX;
2232 else
2233 ifmr->ifm_active |= IFM_FDX;
2234 } else
2235 ifmr->ifm_active = IFM_ETHER|IFM_10_5;
2236 break;
2237 case XL_XCVR_COAX:
2238 ifmr->ifm_active = IFM_ETHER|IFM_10_2;
2239 break;
2240
2241
2242
2243
2244 case XL_XCVR_100BTX:
2245 case XL_XCVR_AUTO:
2246 case XL_XCVR_MII:
2247 if (mii != NULL) {
2248 mii_pollstat(mii);
2249 ifmr->ifm_active = mii->mii_media_active;
2250 ifmr->ifm_status = mii->mii_media_status;
2251 }
2252 break;
2253 case XL_XCVR_100BFX:
2254 ifmr->ifm_active = IFM_ETHER|IFM_100_FX;
2255 break;
2256 default:
2257 printf("%s: unknown XCVR type: %d\n", sc->sc_dev.dv_xname, icfg);
2258 break;
2259 }
2260 }
2261
2262 int
2263 xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
2264 {
2265 struct xl_softc *sc = ifp->if_softc;
2266 struct ifreq *ifr = (struct ifreq *)data;
2267 struct ifaddr *ifa = (struct ifaddr *)data;
2268 int s, error = 0;
2269 struct mii_data *mii = NULL;
2270
2271 s = splnet();
2272
2273 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
2274 splx(s);
2275 return error;
2276 }
2277
2278 switch(command) {
2279 case SIOCSIFADDR:
2280 ifp->if_flags |= IFF_UP;
2281 if (!(ifp->if_flags & IFF_RUNNING))
2282 xl_init(sc);
2283 #ifdef INET
2284 if (ifa->ifa_addr->sa_family == AF_INET)
2285 arp_ifinit(&sc->sc_arpcom, ifa);
2286 #endif
2287 break;
2288
2289 case SIOCSIFMTU:
2290 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN)
2291 error = EINVAL;
2292 else if (ifp->if_mtu != ifr->ifr_mtu)
2293 ifp->if_mtu = ifr->ifr_mtu;
2294 break;
2295
2296 case SIOCSIFFLAGS:
2297 XL_SEL_WIN(5);
2298 if (ifp->if_flags & IFF_UP) {
2299 if (ifp->if_flags & IFF_RUNNING &&
2300 (ifp->if_flags ^ sc->xl_if_flags) &
2301 IFF_PROMISC) {
2302 xl_setpromisc(sc);
2303 XL_SEL_WIN(7);
2304 } else {
2305 if (!(ifp->if_flags & IFF_RUNNING))
2306 xl_init(sc);
2307 }
2308 } else {
2309 if (ifp->if_flags & IFF_RUNNING)
2310 xl_stop(sc);
2311 }
2312 sc->xl_if_flags = ifp->if_flags;
2313 break;
2314 case SIOCADDMULTI:
2315 case SIOCDELMULTI:
2316 error = (command == SIOCADDMULTI) ?
2317 ether_addmulti(ifr, &sc->sc_arpcom) :
2318 ether_delmulti(ifr, &sc->sc_arpcom);
2319
2320 if (error == ENETRESET) {
2321
2322
2323
2324
2325 if (ifp->if_flags & IFF_RUNNING) {
2326 if (sc->xl_type == XL_TYPE_905B)
2327 xl_setmulti_hash(sc);
2328 else
2329 xl_setmulti(sc);
2330 }
2331 error = 0;
2332 }
2333 break;
2334 case SIOCGIFMEDIA:
2335 case SIOCSIFMEDIA:
2336 if (sc->xl_hasmii != 0)
2337 mii = &sc->sc_mii;
2338 if (mii == NULL)
2339 error = ifmedia_ioctl(ifp, ifr,
2340 &sc->ifmedia, command);
2341 else
2342 error = ifmedia_ioctl(ifp, ifr,
2343 &mii->mii_media, command);
2344 break;
2345 default:
2346 error = EINVAL;
2347 break;
2348 }
2349
2350 splx(s);
2351
2352 return (error);
2353 }
2354
2355 void
2356 xl_watchdog(struct ifnet *ifp)
2357 {
2358 struct xl_softc *sc;
2359 u_int16_t status = 0;
2360
2361 sc = ifp->if_softc;
2362
2363 ifp->if_oerrors++;
2364 XL_SEL_WIN(4);
2365 status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
2366 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
2367
2368 if (status & XL_MEDIASTAT_CARRIER)
2369 printf("%s: no carrier - transceiver cable problem?\n",
2370 sc->sc_dev.dv_xname);
2371 xl_txeoc(sc);
2372 xl_txeof(sc);
2373 xl_rxeof(sc);
2374 xl_reset(sc);
2375 xl_init(sc);
2376
2377 if (!IFQ_IS_EMPTY(&ifp->if_snd))
2378 (*ifp->if_start)(ifp);
2379 }
2380
2381 void
2382 xl_freetxrx(struct xl_softc *sc)
2383 {
2384 bus_dmamap_t map;
2385 int i;
2386
2387
2388
2389
2390 for (i = 0; i < XL_RX_LIST_CNT; i++) {
2391 if (sc->xl_cdata.xl_rx_chain[i].map->dm_nsegs != 0) {
2392 map = sc->xl_cdata.xl_rx_chain[i].map;
2393
2394 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
2395 BUS_DMASYNC_POSTREAD);
2396 bus_dmamap_unload(sc->sc_dmat, map);
2397 }
2398 if (sc->xl_cdata.xl_rx_chain[i].xl_mbuf != NULL) {
2399 m_freem(sc->xl_cdata.xl_rx_chain[i].xl_mbuf);
2400 sc->xl_cdata.xl_rx_chain[i].xl_mbuf = NULL;
2401 }
2402 }
2403 bzero((char *)&sc->xl_ldata->xl_rx_list,
2404 sizeof(sc->xl_ldata->xl_rx_list));
2405
2406
2407
2408 for (i = 0; i < XL_TX_LIST_CNT; i++) {
2409 if (sc->xl_cdata.xl_tx_chain[i].map->dm_nsegs != 0) {
2410 map = sc->xl_cdata.xl_tx_chain[i].map;
2411
2412 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
2413 BUS_DMASYNC_POSTWRITE);
2414 bus_dmamap_unload(sc->sc_dmat, map);
2415 }
2416 if (sc->xl_cdata.xl_tx_chain[i].xl_mbuf != NULL) {
2417 m_freem(sc->xl_cdata.xl_tx_chain[i].xl_mbuf);
2418 sc->xl_cdata.xl_tx_chain[i].xl_mbuf = NULL;
2419 }
2420 }
2421 bzero((char *)&sc->xl_ldata->xl_tx_list,
2422 sizeof(sc->xl_ldata->xl_tx_list));
2423 }
2424
2425
2426
2427
2428
2429 void
2430 xl_stop(struct xl_softc *sc)
2431 {
2432 struct ifnet *ifp;
2433
2434 ifp = &sc->sc_arpcom.ac_if;
2435 ifp->if_timer = 0;
2436
2437 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISABLE);
2438 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
2439 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB);
2440 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISCARD);
2441 xl_wait(sc);
2442 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_DISABLE);
2443 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
2444 DELAY(800);
2445
2446 #ifdef foo
2447 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
2448 xl_wait(sc);
2449 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
2450 xl_wait(sc);
2451 #endif
2452
2453 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|XL_STAT_INTLATCH);
2454 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|0);
2455 CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
2456
2457 if (sc->intr_ack)
2458 (*sc->intr_ack)(sc);
2459
2460
2461 timeout_del(&sc->xl_stsup_tmo);
2462
2463 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
2464
2465 xl_freetxrx(sc);
2466 }
2467
2468 void
2469 xl_attach(struct xl_softc *sc)
2470 {
2471 u_int8_t enaddr[ETHER_ADDR_LEN];
2472 u_int16_t xcvr[2];
2473 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
2474 int i, media = IFM_ETHER|IFM_100_TX|IFM_FDX;
2475 struct ifmedia *ifm;
2476
2477 i = splnet();
2478 xl_reset(sc);
2479 splx(i);
2480
2481
2482
2483
2484 if (xl_read_eeprom(sc, (caddr_t)&enaddr, XL_EE_OEM_ADR0, 3, 1)) {
2485 printf("\n%s: failed to read station address\n",
2486 sc->sc_dev.dv_xname);
2487 return;
2488 }
2489 bcopy(enaddr, (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
2490
2491 if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct xl_list_data),
2492 PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
2493 BUS_DMA_NOWAIT) != 0) {
2494 printf(": can't alloc list mem\n");
2495 return;
2496 }
2497 if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
2498 sizeof(struct xl_list_data), &sc->sc_listkva,
2499 BUS_DMA_NOWAIT) != 0) {
2500 printf(": can't map list mem\n");
2501 return;
2502 }
2503 if (bus_dmamap_create(sc->sc_dmat, sizeof(struct xl_list_data), 1,
2504 sizeof(struct xl_list_data), 0, BUS_DMA_NOWAIT,
2505 &sc->sc_listmap) != 0) {
2506 printf(": can't alloc list map\n");
2507 return;
2508 }
2509 if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
2510 sizeof(struct xl_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
2511 printf(": can't load list map\n");
2512 return;
2513 }
2514 sc->xl_ldata = (struct xl_list_data *)sc->sc_listkva;
2515 bzero(sc->xl_ldata, sizeof(struct xl_list_data));
2516
2517 for (i = 0; i < XL_RX_LIST_CNT; i++) {
2518 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
2519 0, BUS_DMA_NOWAIT,
2520 &sc->xl_cdata.xl_rx_chain[i].map) != 0) {
2521 printf(": can't create rx map\n");
2522 return;
2523 }
2524 }
2525 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
2526 BUS_DMA_NOWAIT, &sc->sc_rx_sparemap) != 0) {
2527 printf(": can't create rx spare map\n");
2528 return;
2529 }
2530
2531 for (i = 0; i < XL_TX_LIST_CNT; i++) {
2532 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
2533 XL_TX_LIST_CNT - 3, MCLBYTES, 0, BUS_DMA_NOWAIT,
2534 &sc->xl_cdata.xl_tx_chain[i].map) != 0) {
2535 printf(": can't create tx map\n");
2536 return;
2537 }
2538 }
2539 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, XL_TX_LIST_CNT - 3,
2540 MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
2541 printf(": can't create tx spare map\n");
2542 return;
2543 }
2544
2545 printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
2546
2547 if (sc->xl_flags & (XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR)) {
2548 u_int16_t n;
2549
2550 XL_SEL_WIN(2);
2551 n = CSR_READ_2(sc, 12);
2552
2553 if (sc->xl_flags & XL_FLAG_INVERT_LED_PWR)
2554 n |= 0x0010;
2555
2556 if (sc->xl_flags & XL_FLAG_INVERT_MII_PWR)
2557 n |= 0x4000;
2558
2559 CSR_WRITE_2(sc, 12, n);
2560 }
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572 xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0);
2573 if (sc->xl_caps & XL_CAPS_NO_TXLENGTH ||
2574 !(sc->xl_caps & XL_CAPS_LARGE_PKTS))
2575 sc->xl_type = XL_TYPE_905B;
2576 else
2577 sc->xl_type = XL_TYPE_90X;
2578
2579 timeout_set(&sc->xl_stsup_tmo, xl_stats_update, sc);
2580
2581 ifp->if_softc = sc;
2582 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
2583 ifp->if_ioctl = xl_ioctl;
2584 if (sc->xl_type == XL_TYPE_905B)
2585 ifp->if_start = xl_start_90xB;
2586 else
2587 ifp->if_start = xl_start;
2588 ifp->if_watchdog = xl_watchdog;
2589 ifp->if_baudrate = 10000000;
2590 IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1);
2591 IFQ_SET_READY(&ifp->if_snd);
2592 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
2593
2594 ifp->if_capabilities = IFCAP_VLAN_MTU;
2595
2596 #ifndef XL905B_TXCSUM_BROKEN
2597 ifp->if_capabilities |= IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4|
2598 IFCAP_CSUM_UDPv4;
2599 #endif
2600
2601 XL_SEL_WIN(3);
2602 sc->xl_media = CSR_READ_2(sc, XL_W3_MEDIA_OPT);
2603
2604 xl_read_eeprom(sc, (char *)&xcvr, XL_EE_ICFG_0, 2, 0);
2605 sc->xl_xcvr = xcvr[0] | xcvr[1] << 16;
2606 sc->xl_xcvr &= XL_ICFG_CONNECTOR_MASK;
2607 sc->xl_xcvr >>= XL_ICFG_CONNECTOR_BITS;
2608
2609 xl_mediacheck(sc);
2610
2611 if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX
2612 || sc->xl_media & XL_MEDIAOPT_BT4) {
2613 ifmedia_init(&sc->sc_mii.mii_media, 0,
2614 xl_ifmedia_upd, xl_ifmedia_sts);
2615 sc->xl_hasmii = 1;
2616 sc->sc_mii.mii_ifp = ifp;
2617 sc->sc_mii.mii_readreg = xl_miibus_readreg;
2618 sc->sc_mii.mii_writereg = xl_miibus_writereg;
2619 sc->sc_mii.mii_statchg = xl_miibus_statchg;
2620 xl_setcfg(sc);
2621 mii_attach((struct device *)sc, &sc->sc_mii, 0xffffffff,
2622 MII_PHY_ANY, MII_OFFSET_ANY, 0);
2623
2624 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
2625 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,
2626 0, NULL);
2627 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
2628 }
2629 else {
2630 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
2631 }
2632 ifm = &sc->sc_mii.mii_media;
2633 }
2634 else {
2635 ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts);
2636 sc->xl_hasmii = 0;
2637 ifm = &sc->ifmedia;
2638 }
2639
2640
2641
2642
2643
2644
2645 if (sc->xl_xcvr == XL_XCVR_AUTO) {
2646 xl_choose_xcvr(sc, 0);
2647 i = splnet();
2648 xl_reset(sc);
2649 splx(i);
2650 }
2651
2652 if (sc->xl_media & XL_MEDIAOPT_BT) {
2653 ifmedia_add(ifm, IFM_ETHER|IFM_10_T, 0, NULL);
2654 ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
2655 if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
2656 ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
2657 }
2658
2659 if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) {
2660
2661
2662
2663 if (sc->xl_type == XL_TYPE_905B &&
2664 sc->xl_media == XL_MEDIAOPT_10FL) {
2665 ifmedia_add(ifm, IFM_ETHER|IFM_10_FL, 0, NULL);
2666 ifmedia_add(ifm, IFM_ETHER|IFM_10_FL|IFM_HDX,
2667 0, NULL);
2668 if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
2669 ifmedia_add(ifm,
2670 IFM_ETHER|IFM_10_FL|IFM_FDX, 0, NULL);
2671 } else {
2672 ifmedia_add(ifm, IFM_ETHER|IFM_10_5, 0, NULL);
2673 }
2674 }
2675
2676 if (sc->xl_media & XL_MEDIAOPT_BNC) {
2677 ifmedia_add(ifm, IFM_ETHER|IFM_10_2, 0, NULL);
2678 }
2679
2680 if (sc->xl_media & XL_MEDIAOPT_BFX) {
2681 ifp->if_baudrate = 100000000;
2682 ifmedia_add(ifm, IFM_ETHER|IFM_100_FX, 0, NULL);
2683 }
2684
2685
2686 switch(sc->xl_xcvr) {
2687 case XL_XCVR_10BT:
2688 media = IFM_ETHER|IFM_10_T;
2689 xl_setmode(sc, media);
2690 break;
2691 case XL_XCVR_AUI:
2692 if (sc->xl_type == XL_TYPE_905B &&
2693 sc->xl_media == XL_MEDIAOPT_10FL) {
2694 media = IFM_ETHER|IFM_10_FL;
2695 xl_setmode(sc, media);
2696 } else {
2697 media = IFM_ETHER|IFM_10_5;
2698 xl_setmode(sc, media);
2699 }
2700 break;
2701 case XL_XCVR_COAX:
2702 media = IFM_ETHER|IFM_10_2;
2703 xl_setmode(sc, media);
2704 break;
2705 case XL_XCVR_AUTO:
2706 case XL_XCVR_100BTX:
2707 case XL_XCVR_MII:
2708
2709 break;
2710 case XL_XCVR_100BFX:
2711 media = IFM_ETHER|IFM_100_FX;
2712 xl_setmode(sc, media);
2713 break;
2714 default:
2715 printf("%s: unknown XCVR type: %d\n", sc->sc_dev.dv_xname,
2716 sc->xl_xcvr);
2717
2718
2719
2720
2721 media = IFM_ETHER | IFM_10_T;
2722 break;
2723 }
2724
2725 if (sc->xl_hasmii == 0)
2726 ifmedia_set(&sc->ifmedia, media);
2727
2728 if (sc->xl_flags & XL_FLAG_NO_XCVR_PWR) {
2729 XL_SEL_WIN(0);
2730 CSR_WRITE_2(sc, XL_W0_MFG_ID, XL_NO_XCVR_PWR_MAGICBITS);
2731 }
2732
2733
2734
2735
2736 if_attach(ifp);
2737 ether_ifattach(ifp);
2738
2739 sc->sc_sdhook = shutdownhook_establish(xl_shutdown, sc);
2740 sc->sc_pwrhook = powerhook_establish(xl_power, sc);
2741 }
2742
2743 void
2744 xl_shutdown(void *v)
2745 {
2746 struct xl_softc *sc = (struct xl_softc *)v;
2747
2748 xl_reset(sc);
2749 xl_stop(sc);
2750 }
2751
2752 struct cfdriver xl_cd = {
2753 0, "xl", DV_IFNET
2754 };