This source file includes following definitions.
- wb_eeprom_putbyte
- wb_eeprom_getword
- wb_read_eeprom
- wb_mii_sync
- wb_mii_send
- wb_mii_readreg
- wb_mii_writereg
- wb_miibus_readreg
- wb_miibus_writereg
- wb_miibus_statchg
- wb_setmulti
- wb_setcfg
- wb_reset
- wb_fixmedia
- wb_probe
- wb_attach
- wb_list_tx_init
- wb_list_rx_init
- wb_bfree
- wb_newbuf
- wb_rxeof
- wb_rxeoc
- wb_txeof
- wb_txeoc
- wb_intr
- wb_tick
- wb_encap
- wb_start
- wb_init
- wb_ifmedia_upd
- wb_ifmedia_sts
- wb_ioctl
- wb_watchdog
- wb_stop
- wb_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 #include "bpfilter.h"
89
90 #include <sys/param.h>
91 #include <sys/systm.h>
92 #include <sys/sockio.h>
93 #include <sys/mbuf.h>
94 #include <sys/malloc.h>
95 #include <sys/kernel.h>
96 #include <sys/socket.h>
97 #include <sys/device.h>
98 #include <sys/queue.h>
99 #include <sys/timeout.h>
100
101 #include <net/if.h>
102 #include <net/if_dl.h>
103 #include <net/if_types.h>
104
105 #ifdef INET
106 #include <netinet/in.h>
107 #include <netinet/in_systm.h>
108 #include <netinet/in_var.h>
109 #include <netinet/ip.h>
110 #include <netinet/if_ether.h>
111 #endif
112
113 #include <net/if_media.h>
114
115 #if NBPFILTER > 0
116 #include <net/bpf.h>
117 #endif
118
119 #include <uvm/uvm_extern.h>
120 #define VTOPHYS(v) vtophys((vaddr_t)(v))
121
122 #include <dev/mii/mii.h>
123 #include <dev/mii/miivar.h>
124 #include <dev/pci/pcireg.h>
125 #include <dev/pci/pcivar.h>
126 #include <dev/pci/pcidevs.h>
127
128 #define WB_USEIOSPACE
129
130
131
132 #include <dev/pci/if_wbreg.h>
133
134 int wb_probe(struct device *, void *, void *);
135 void wb_attach(struct device *, struct device *, void *);
136
137 void wb_bfree(caddr_t, u_int, void *);
138 int wb_newbuf(struct wb_softc *, struct wb_chain_onefrag *,
139 struct mbuf *);
140 int wb_encap(struct wb_softc *, struct wb_chain *,
141 struct mbuf *);
142
143 void wb_rxeof(struct wb_softc *);
144 void wb_rxeoc(struct wb_softc *);
145 void wb_txeof(struct wb_softc *);
146 void wb_txeoc(struct wb_softc *);
147 int wb_intr(void *);
148 void wb_tick(void *);
149 void wb_start(struct ifnet *);
150 int wb_ioctl(struct ifnet *, u_long, caddr_t);
151 void wb_init(void *);
152 void wb_stop(struct wb_softc *);
153 void wb_watchdog(struct ifnet *);
154 void wb_shutdown(void *);
155 int wb_ifmedia_upd(struct ifnet *);
156 void wb_ifmedia_sts(struct ifnet *, struct ifmediareq *);
157
158 void wb_eeprom_putbyte(struct wb_softc *, int);
159 void wb_eeprom_getword(struct wb_softc *, int, u_int16_t *);
160 void wb_read_eeprom(struct wb_softc *, caddr_t, int, int, int);
161 void wb_mii_sync(struct wb_softc *);
162 void wb_mii_send(struct wb_softc *, u_int32_t, int);
163 int wb_mii_readreg(struct wb_softc *, struct wb_mii_frame *);
164 int wb_mii_writereg(struct wb_softc *, struct wb_mii_frame *);
165
166 void wb_setcfg(struct wb_softc *, u_int32_t);
167 u_int8_t wb_calchash(caddr_t);
168 void wb_setmulti(struct wb_softc *);
169 void wb_reset(struct wb_softc *);
170 void wb_fixmedia(struct wb_softc *);
171 int wb_list_rx_init(struct wb_softc *);
172 int wb_list_tx_init(struct wb_softc *);
173
174 int wb_miibus_readreg(struct device *, int, int);
175 void wb_miibus_writereg(struct device *, int, int, int);
176 void wb_miibus_statchg(struct device *);
177
178 #define WB_SETBIT(sc, reg, x) \
179 CSR_WRITE_4(sc, reg, \
180 CSR_READ_4(sc, reg) | x)
181
182 #define WB_CLRBIT(sc, reg, x) \
183 CSR_WRITE_4(sc, reg, \
184 CSR_READ_4(sc, reg) & ~x)
185
186 #define SIO_SET(x) \
187 CSR_WRITE_4(sc, WB_SIO, \
188 CSR_READ_4(sc, WB_SIO) | x)
189
190 #define SIO_CLR(x) \
191 CSR_WRITE_4(sc, WB_SIO, \
192 CSR_READ_4(sc, WB_SIO) & ~x)
193
194
195
196
197 void wb_eeprom_putbyte(sc, addr)
198 struct wb_softc *sc;
199 int addr;
200 {
201 int d, i;
202
203 d = addr | WB_EECMD_READ;
204
205
206
207
208 for (i = 0x400; i; i >>= 1) {
209 if (d & i) {
210 SIO_SET(WB_SIO_EE_DATAIN);
211 } else {
212 SIO_CLR(WB_SIO_EE_DATAIN);
213 }
214 DELAY(100);
215 SIO_SET(WB_SIO_EE_CLK);
216 DELAY(150);
217 SIO_CLR(WB_SIO_EE_CLK);
218 DELAY(100);
219 }
220
221 return;
222 }
223
224
225
226
227 void wb_eeprom_getword(sc, addr, dest)
228 struct wb_softc *sc;
229 int addr;
230 u_int16_t *dest;
231 {
232 int i;
233 u_int16_t word = 0;
234
235
236 CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
237
238
239
240
241 wb_eeprom_putbyte(sc, addr);
242
243 CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
244
245
246
247
248 for (i = 0x8000; i; i >>= 1) {
249 SIO_SET(WB_SIO_EE_CLK);
250 DELAY(100);
251 if (CSR_READ_4(sc, WB_SIO) & WB_SIO_EE_DATAOUT)
252 word |= i;
253 SIO_CLR(WB_SIO_EE_CLK);
254 DELAY(100);
255 }
256
257
258 CSR_WRITE_4(sc, WB_SIO, 0);
259
260 *dest = word;
261
262 return;
263 }
264
265
266
267
268 void wb_read_eeprom(sc, dest, off, cnt, swap)
269 struct wb_softc *sc;
270 caddr_t dest;
271 int off;
272 int cnt;
273 int swap;
274 {
275 int i;
276 u_int16_t word = 0, *ptr;
277
278 for (i = 0; i < cnt; i++) {
279 wb_eeprom_getword(sc, off + i, &word);
280 ptr = (u_int16_t *)(dest + (i * 2));
281 if (swap)
282 *ptr = ntohs(word);
283 else
284 *ptr = word;
285 }
286
287 return;
288 }
289
290
291
292
293 void wb_mii_sync(sc)
294 struct wb_softc *sc;
295 {
296 int i;
297
298 SIO_SET(WB_SIO_MII_DIR|WB_SIO_MII_DATAIN);
299
300 for (i = 0; i < 32; i++) {
301 SIO_SET(WB_SIO_MII_CLK);
302 DELAY(1);
303 SIO_CLR(WB_SIO_MII_CLK);
304 DELAY(1);
305 }
306
307 return;
308 }
309
310
311
312
313 void wb_mii_send(sc, bits, cnt)
314 struct wb_softc *sc;
315 u_int32_t bits;
316 int cnt;
317 {
318 int i;
319
320 SIO_CLR(WB_SIO_MII_CLK);
321
322 for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
323 if (bits & i) {
324 SIO_SET(WB_SIO_MII_DATAIN);
325 } else {
326 SIO_CLR(WB_SIO_MII_DATAIN);
327 }
328 DELAY(1);
329 SIO_CLR(WB_SIO_MII_CLK);
330 DELAY(1);
331 SIO_SET(WB_SIO_MII_CLK);
332 }
333 }
334
335
336
337
338 int wb_mii_readreg(sc, frame)
339 struct wb_softc *sc;
340 struct wb_mii_frame *frame;
341
342 {
343 int i, ack, s;
344
345 s = splnet();
346
347
348
349
350 frame->mii_stdelim = WB_MII_STARTDELIM;
351 frame->mii_opcode = WB_MII_READOP;
352 frame->mii_turnaround = 0;
353 frame->mii_data = 0;
354
355 CSR_WRITE_4(sc, WB_SIO, 0);
356
357
358
359
360 SIO_SET(WB_SIO_MII_DIR);
361
362 wb_mii_sync(sc);
363
364
365
366
367 wb_mii_send(sc, frame->mii_stdelim, 2);
368 wb_mii_send(sc, frame->mii_opcode, 2);
369 wb_mii_send(sc, frame->mii_phyaddr, 5);
370 wb_mii_send(sc, frame->mii_regaddr, 5);
371
372
373 SIO_CLR((WB_SIO_MII_CLK|WB_SIO_MII_DATAIN));
374 DELAY(1);
375 SIO_SET(WB_SIO_MII_CLK);
376 DELAY(1);
377
378
379 SIO_CLR(WB_SIO_MII_DIR);
380
381 SIO_CLR(WB_SIO_MII_CLK);
382 DELAY(1);
383 ack = CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT;
384 SIO_SET(WB_SIO_MII_CLK);
385 DELAY(1);
386 SIO_CLR(WB_SIO_MII_CLK);
387 DELAY(1);
388 SIO_SET(WB_SIO_MII_CLK);
389 DELAY(1);
390
391
392
393
394
395 if (ack) {
396 for(i = 0; i < 16; i++) {
397 SIO_CLR(WB_SIO_MII_CLK);
398 DELAY(1);
399 SIO_SET(WB_SIO_MII_CLK);
400 DELAY(1);
401 }
402 goto fail;
403 }
404
405 for (i = 0x8000; i; i >>= 1) {
406 SIO_CLR(WB_SIO_MII_CLK);
407 DELAY(1);
408 if (!ack) {
409 if (CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT)
410 frame->mii_data |= i;
411 DELAY(1);
412 }
413 SIO_SET(WB_SIO_MII_CLK);
414 DELAY(1);
415 }
416
417 fail:
418
419 SIO_CLR(WB_SIO_MII_CLK);
420 DELAY(1);
421 SIO_SET(WB_SIO_MII_CLK);
422 DELAY(1);
423
424 splx(s);
425
426 if (ack)
427 return(1);
428 return(0);
429 }
430
431
432
433
434 int wb_mii_writereg(sc, frame)
435 struct wb_softc *sc;
436 struct wb_mii_frame *frame;
437
438 {
439 int s;
440
441 s = splnet();
442
443
444
445
446 frame->mii_stdelim = WB_MII_STARTDELIM;
447 frame->mii_opcode = WB_MII_WRITEOP;
448 frame->mii_turnaround = WB_MII_TURNAROUND;
449
450
451
452
453 SIO_SET(WB_SIO_MII_DIR);
454
455 wb_mii_sync(sc);
456
457 wb_mii_send(sc, frame->mii_stdelim, 2);
458 wb_mii_send(sc, frame->mii_opcode, 2);
459 wb_mii_send(sc, frame->mii_phyaddr, 5);
460 wb_mii_send(sc, frame->mii_regaddr, 5);
461 wb_mii_send(sc, frame->mii_turnaround, 2);
462 wb_mii_send(sc, frame->mii_data, 16);
463
464
465 SIO_SET(WB_SIO_MII_CLK);
466 DELAY(1);
467 SIO_CLR(WB_SIO_MII_CLK);
468 DELAY(1);
469
470
471
472
473 SIO_CLR(WB_SIO_MII_DIR);
474
475 splx(s);
476
477 return(0);
478 }
479
480 int
481 wb_miibus_readreg(dev, phy, reg)
482 struct device *dev;
483 int phy, reg;
484 {
485 struct wb_softc *sc = (struct wb_softc *)dev;
486 struct wb_mii_frame frame;
487
488 bzero((char *)&frame, sizeof(frame));
489
490 frame.mii_phyaddr = phy;
491 frame.mii_regaddr = reg;
492 wb_mii_readreg(sc, &frame);
493
494 return(frame.mii_data);
495 }
496
497 void
498 wb_miibus_writereg(dev, phy, reg, data)
499 struct device *dev;
500 int phy, reg, data;
501 {
502 struct wb_softc *sc = (struct wb_softc *)dev;
503 struct wb_mii_frame frame;
504
505 bzero((char *)&frame, sizeof(frame));
506
507 frame.mii_phyaddr = phy;
508 frame.mii_regaddr = reg;
509 frame.mii_data = data;
510
511 wb_mii_writereg(sc, &frame);
512
513 return;
514 }
515
516 void
517 wb_miibus_statchg(dev)
518 struct device *dev;
519 {
520 struct wb_softc *sc = (struct wb_softc *)dev;
521
522 wb_setcfg(sc, sc->sc_mii.mii_media_active);
523 }
524
525
526
527
528 void wb_setmulti(sc)
529 struct wb_softc *sc;
530 {
531 struct ifnet *ifp;
532 int h = 0;
533 u_int32_t hashes[2] = { 0, 0 };
534 struct arpcom *ac = &sc->arpcom;
535 struct ether_multi *enm;
536 struct ether_multistep step;
537 u_int32_t rxfilt;
538 int mcnt = 0;
539
540 ifp = &sc->arpcom.ac_if;
541
542 rxfilt = CSR_READ_4(sc, WB_NETCFG);
543
544 allmulti:
545 if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
546 rxfilt |= WB_NETCFG_RX_MULTI;
547 CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
548 CSR_WRITE_4(sc, WB_MAR0, 0xFFFFFFFF);
549 CSR_WRITE_4(sc, WB_MAR1, 0xFFFFFFFF);
550 return;
551 }
552
553
554 CSR_WRITE_4(sc, WB_MAR0, 0);
555 CSR_WRITE_4(sc, WB_MAR1, 0);
556
557
558 ETHER_FIRST_MULTI(step, ac, enm);
559 while (enm != NULL) {
560 if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
561 ifp->if_flags |= IFF_ALLMULTI;
562 goto allmulti;
563 }
564 h = ~(ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26);
565 if (h < 32)
566 hashes[0] |= (1 << h);
567 else
568 hashes[1] |= (1 << (h - 32));
569 mcnt++;
570 ETHER_NEXT_MULTI(step, enm);
571 }
572
573 if (mcnt)
574 rxfilt |= WB_NETCFG_RX_MULTI;
575 else
576 rxfilt &= ~WB_NETCFG_RX_MULTI;
577
578 CSR_WRITE_4(sc, WB_MAR0, hashes[0]);
579 CSR_WRITE_4(sc, WB_MAR1, hashes[1]);
580 CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
581
582 return;
583 }
584
585
586
587
588
589
590 void
591 wb_setcfg(sc, media)
592 struct wb_softc *sc;
593 u_int32_t media;
594 {
595 int i, restart = 0;
596
597 if (CSR_READ_4(sc, WB_NETCFG) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) {
598 restart = 1;
599 WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON));
600
601 for (i = 0; i < WB_TIMEOUT; i++) {
602 DELAY(10);
603 if ((CSR_READ_4(sc, WB_ISR) & WB_ISR_TX_IDLE) &&
604 (CSR_READ_4(sc, WB_ISR) & WB_ISR_RX_IDLE))
605 break;
606 }
607
608 if (i == WB_TIMEOUT)
609 printf("%s: failed to force tx and "
610 "rx to idle state\n", sc->sc_dev.dv_xname);
611 }
612
613 if (IFM_SUBTYPE(media) == IFM_10_T)
614 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
615 else
616 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
617
618 if ((media & IFM_GMASK) == IFM_FDX)
619 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
620 else
621 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
622
623 if (restart)
624 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON|WB_NETCFG_RX_ON);
625
626 return;
627 }
628
629 void
630 wb_reset(sc)
631 struct wb_softc *sc;
632 {
633 int i;
634 struct mii_data *mii = &sc->sc_mii;
635
636 CSR_WRITE_4(sc, WB_NETCFG, 0);
637 CSR_WRITE_4(sc, WB_BUSCTL, 0);
638 CSR_WRITE_4(sc, WB_TXADDR, 0);
639 CSR_WRITE_4(sc, WB_RXADDR, 0);
640
641 WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
642 WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
643
644 for (i = 0; i < WB_TIMEOUT; i++) {
645 DELAY(10);
646 if (!(CSR_READ_4(sc, WB_BUSCTL) & WB_BUSCTL_RESET))
647 break;
648 }
649 if (i == WB_TIMEOUT)
650 printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
651
652
653 DELAY(1000);
654
655 if (mii->mii_instance) {
656 struct mii_softc *miisc;
657 LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
658 mii_phy_reset(miisc);
659 }
660 }
661
662 void
663 wb_fixmedia(sc)
664 struct wb_softc *sc;
665 {
666 struct mii_data *mii = &sc->sc_mii;
667 u_int32_t media;
668
669 if (LIST_FIRST(&mii->mii_phys) == NULL)
670 return;
671
672 mii_pollstat(mii);
673 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) {
674 media = mii->mii_media_active & ~IFM_10_T;
675 media |= IFM_100_TX;
676 } if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
677 media = mii->mii_media_active & ~IFM_100_TX;
678 media |= IFM_10_T;
679 } else
680 return;
681
682 ifmedia_set(&mii->mii_media, media);
683 }
684
685 const struct pci_matchid wb_devices[] = {
686 { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F },
687 { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX },
688 };
689
690
691
692
693
694 int
695 wb_probe(parent, match, aux)
696 struct device *parent;
697 void *match, *aux;
698 {
699 return (pci_matchbyid((struct pci_attach_args *)aux, wb_devices,
700 sizeof(wb_devices)/sizeof(wb_devices[0])));
701 }
702
703
704
705
706
707 void
708 wb_attach(parent, self, aux)
709 struct device *parent, *self;
710 void *aux;
711 {
712 struct wb_softc *sc = (struct wb_softc *)self;
713 struct pci_attach_args *pa = aux;
714 pci_chipset_tag_t pc = pa->pa_pc;
715 pci_intr_handle_t ih;
716 const char *intrstr = NULL;
717 struct ifnet *ifp = &sc->arpcom.ac_if;
718 bus_size_t size;
719 int rseg;
720 pcireg_t command;
721 bus_dma_segment_t seg;
722 bus_dmamap_t dmamap;
723 caddr_t kva;
724
725
726
727
728
729 command = pci_conf_read(pc, pa->pa_tag, WB_PCI_CAPID) & 0x000000FF;
730 if (command == 0x01) {
731
732 command = pci_conf_read(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL);
733 if (command & WB_PSTATE_MASK) {
734 u_int32_t io, mem, irq;
735
736
737 io = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOIO);
738 mem = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOMEM);
739 irq = pci_conf_read(pc, pa->pa_tag, WB_PCI_INTLINE);
740
741
742 printf("%s: chip is in D%d power mode "
743 "-- setting to D0\n", sc->sc_dev.dv_xname,
744 command & WB_PSTATE_MASK);
745 command &= 0xFFFFFFFC;
746 pci_conf_write(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL,
747 command);
748
749
750 pci_conf_write(pc, pa->pa_tag, WB_PCI_LOIO, io);
751 pci_conf_write(pc, pa->pa_tag, WB_PCI_LOMEM, mem);
752 pci_conf_write(pc, pa->pa_tag, WB_PCI_INTLINE, irq);
753 }
754 }
755
756
757
758
759
760 #ifdef WB_USEIOSPACE
761 if (pci_mapreg_map(pa, WB_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
762 &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)) {
763 printf(": can't map i/o space\n");
764 return;
765 }
766 #else
767 if (pci_mapreg_map(pa, WB_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
768 &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)){
769 printf(": can't map mem space\n");
770 return;
771 }
772 #endif
773
774
775 if (pci_intr_map(pa, &ih)) {
776 printf(": couldn't map interrupt\n");
777 goto fail_1;
778 }
779 intrstr = pci_intr_string(pc, ih);
780 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wb_intr, sc,
781 self->dv_xname);
782 if (sc->sc_ih == NULL) {
783 printf(": couldn't establish interrupt");
784 if (intrstr != NULL)
785 printf(" at %s", intrstr);
786 printf("\n");
787 goto fail_1;
788 }
789 printf(": %s", intrstr);
790
791 sc->wb_cachesize = pci_conf_read(pc, pa->pa_tag, WB_PCI_CACHELEN)&0xff;
792
793
794 wb_reset(sc);
795
796
797
798
799 wb_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, 0, 3, 0);
800 printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
801
802 if (bus_dmamem_alloc(pa->pa_dmat, sizeof(struct wb_list_data),
803 PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
804 printf(": can't alloc list data\n");
805 goto fail_2;
806 }
807 if (bus_dmamem_map(pa->pa_dmat, &seg, rseg,
808 sizeof(struct wb_list_data), &kva, BUS_DMA_NOWAIT)) {
809 printf(": can't map list data, size %d\n",
810 sizeof(struct wb_list_data));
811 goto fail_3;
812 }
813 if (bus_dmamap_create(pa->pa_dmat, sizeof(struct wb_list_data), 1,
814 sizeof(struct wb_list_data), 0, BUS_DMA_NOWAIT, &dmamap)) {
815 printf(": can't create dma map\n");
816 goto fail_4;
817 }
818 if (bus_dmamap_load(pa->pa_dmat, dmamap, kva,
819 sizeof(struct wb_list_data), NULL, BUS_DMA_NOWAIT)) {
820 printf(": can't load dma map\n");
821 goto fail_5;
822 }
823 sc->wb_ldata = (struct wb_list_data *)kva;
824 bzero(sc->wb_ldata, sizeof(struct wb_list_data));
825
826 ifp->if_softc = sc;
827 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
828 ifp->if_ioctl = wb_ioctl;
829 ifp->if_start = wb_start;
830 ifp->if_watchdog = wb_watchdog;
831 ifp->if_baudrate = 10000000;
832 IFQ_SET_MAXLEN(&ifp->if_snd, WB_TX_LIST_CNT - 1);
833 IFQ_SET_READY(&ifp->if_snd);
834
835 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
836
837
838
839
840 wb_stop(sc);
841
842 ifmedia_init(&sc->sc_mii.mii_media, 0, wb_ifmedia_upd, wb_ifmedia_sts);
843 sc->sc_mii.mii_ifp = ifp;
844 sc->sc_mii.mii_readreg = wb_miibus_readreg;
845 sc->sc_mii.mii_writereg = wb_miibus_writereg;
846 sc->sc_mii.mii_statchg = wb_miibus_statchg;
847 mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
848 0);
849 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
850 ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,0,NULL);
851 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
852 } else
853 ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
854
855
856
857
858 if_attach(ifp);
859 ether_ifattach(ifp);
860
861 shutdownhook_establish(wb_shutdown, sc);
862 return;
863
864 fail_5:
865 bus_dmamap_destroy(pa->pa_dmat, dmamap);
866
867 fail_4:
868 bus_dmamem_unmap(pa->pa_dmat, kva,
869 sizeof(struct wb_list_data));
870
871 fail_3:
872 bus_dmamem_free(pa->pa_dmat, &seg, rseg);
873
874 fail_2:
875 pci_intr_disestablish(pc, sc->sc_ih);
876
877 fail_1:
878 bus_space_unmap(sc->wb_btag, sc->wb_bhandle, size);
879 }
880
881
882
883
884 int wb_list_tx_init(sc)
885 struct wb_softc *sc;
886 {
887 struct wb_chain_data *cd;
888 struct wb_list_data *ld;
889 int i;
890
891 cd = &sc->wb_cdata;
892 ld = sc->wb_ldata;
893
894 for (i = 0; i < WB_TX_LIST_CNT; i++) {
895 cd->wb_tx_chain[i].wb_ptr = &ld->wb_tx_list[i];
896 if (i == (WB_TX_LIST_CNT - 1)) {
897 cd->wb_tx_chain[i].wb_nextdesc =
898 &cd->wb_tx_chain[0];
899 } else {
900 cd->wb_tx_chain[i].wb_nextdesc =
901 &cd->wb_tx_chain[i + 1];
902 }
903 }
904
905 cd->wb_tx_free = &cd->wb_tx_chain[0];
906 cd->wb_tx_tail = cd->wb_tx_head = NULL;
907
908 return(0);
909 }
910
911
912
913
914
915
916
917 int wb_list_rx_init(sc)
918 struct wb_softc *sc;
919 {
920 struct wb_chain_data *cd;
921 struct wb_list_data *ld;
922 int i;
923
924 cd = &sc->wb_cdata;
925 ld = sc->wb_ldata;
926
927 for (i = 0; i < WB_RX_LIST_CNT; i++) {
928 cd->wb_rx_chain[i].wb_ptr =
929 (struct wb_desc *)&ld->wb_rx_list[i];
930 cd->wb_rx_chain[i].wb_buf = (void *)&ld->wb_rxbufs[i];
931 if (wb_newbuf(sc, &cd->wb_rx_chain[i], NULL) == ENOBUFS)
932 return(ENOBUFS);
933 if (i == (WB_RX_LIST_CNT - 1)) {
934 cd->wb_rx_chain[i].wb_nextdesc = &cd->wb_rx_chain[0];
935 ld->wb_rx_list[i].wb_next =
936 VTOPHYS(&ld->wb_rx_list[0]);
937 } else {
938 cd->wb_rx_chain[i].wb_nextdesc =
939 &cd->wb_rx_chain[i + 1];
940 ld->wb_rx_list[i].wb_next =
941 VTOPHYS(&ld->wb_rx_list[i + 1]);
942 }
943 }
944
945 cd->wb_rx_head = &cd->wb_rx_chain[0];
946
947 return(0);
948 }
949
950 void
951 wb_bfree(buf, size, arg)
952 caddr_t buf;
953 u_int size;
954 void *arg;
955 {
956 }
957
958
959
960
961 int
962 wb_newbuf(sc, c, m)
963 struct wb_softc *sc;
964 struct wb_chain_onefrag *c;
965 struct mbuf *m;
966 {
967 struct mbuf *m_new = NULL;
968
969 if (m == NULL) {
970 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
971 if (m_new == NULL)
972 return(ENOBUFS);
973 m_new->m_data = m_new->m_ext.ext_buf = c->wb_buf;
974 m_new->m_flags |= M_EXT;
975 m_new->m_ext.ext_size = m_new->m_pkthdr.len =
976 m_new->m_len = WB_BUFBYTES;
977 m_new->m_ext.ext_free = wb_bfree;
978 m_new->m_ext.ext_arg = NULL;
979 MCLINITREFERENCE(m_new);
980 } else {
981 m_new = m;
982 m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES;
983 m_new->m_data = m_new->m_ext.ext_buf;
984 }
985
986 m_adj(m_new, sizeof(u_int64_t));
987
988 c->wb_mbuf = m_new;
989 c->wb_ptr->wb_data = VTOPHYS(mtod(m_new, caddr_t));
990 c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | ETHER_MAX_DIX_LEN;
991 c->wb_ptr->wb_status = WB_RXSTAT;
992
993 return(0);
994 }
995
996
997
998
999
1000 void wb_rxeof(sc)
1001 struct wb_softc *sc;
1002 {
1003 struct mbuf *m = NULL;
1004 struct ifnet *ifp;
1005 struct wb_chain_onefrag *cur_rx;
1006 int total_len = 0;
1007 u_int32_t rxstat;
1008
1009 ifp = &sc->arpcom.ac_if;
1010
1011 while(!((rxstat = sc->wb_cdata.wb_rx_head->wb_ptr->wb_status) &
1012 WB_RXSTAT_OWN)) {
1013 struct mbuf *m0 = NULL;
1014
1015 cur_rx = sc->wb_cdata.wb_rx_head;
1016 sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
1017
1018 m = cur_rx->wb_mbuf;
1019
1020 if ((rxstat & WB_RXSTAT_MIIERR) ||
1021 (WB_RXBYTES(cur_rx->wb_ptr->wb_status) < WB_MIN_FRAMELEN) ||
1022 (WB_RXBYTES(cur_rx->wb_ptr->wb_status) > ETHER_MAX_DIX_LEN) ||
1023 !(rxstat & WB_RXSTAT_LASTFRAG) ||
1024 !(rxstat & WB_RXSTAT_RXCMP)) {
1025 ifp->if_ierrors++;
1026 wb_newbuf(sc, cur_rx, m);
1027 printf("%s: receiver babbling: possible chip "
1028 "bug, forcing reset\n", sc->sc_dev.dv_xname);
1029 wb_fixmedia(sc);
1030 wb_reset(sc);
1031 wb_init(sc);
1032 return;
1033 }
1034
1035 if (rxstat & WB_RXSTAT_RXERR) {
1036 ifp->if_ierrors++;
1037 wb_newbuf(sc, cur_rx, m);
1038 break;
1039 }
1040
1041
1042 total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
1043
1044
1045
1046
1047
1048
1049
1050
1051 total_len -= ETHER_CRC_LEN;
1052
1053 m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
1054 total_len + ETHER_ALIGN, 0, ifp, NULL);
1055 wb_newbuf(sc, cur_rx, m);
1056 if (m0 == NULL) {
1057 ifp->if_ierrors++;
1058 break;
1059 }
1060 m_adj(m0, ETHER_ALIGN);
1061 m = m0;
1062
1063 ifp->if_ipackets++;
1064
1065 #if NBPFILTER > 0
1066
1067
1068
1069 if (ifp->if_bpf)
1070 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1071 #endif
1072
1073 ether_input_mbuf(ifp, m);
1074 }
1075
1076 return;
1077 }
1078
1079 void wb_rxeoc(sc)
1080 struct wb_softc *sc;
1081 {
1082 wb_rxeof(sc);
1083
1084 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
1085 CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
1086 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
1087 if (CSR_READ_4(sc, WB_ISR) & WB_RXSTATE_SUSPEND)
1088 CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
1089
1090 return;
1091 }
1092
1093
1094
1095
1096
1097 void wb_txeof(sc)
1098 struct wb_softc *sc;
1099 {
1100 struct wb_chain *cur_tx;
1101 struct ifnet *ifp;
1102
1103 ifp = &sc->arpcom.ac_if;
1104
1105
1106 ifp->if_timer = 0;
1107
1108 if (sc->wb_cdata.wb_tx_head == NULL)
1109 return;
1110
1111
1112
1113
1114
1115 while(sc->wb_cdata.wb_tx_head->wb_mbuf != NULL) {
1116 u_int32_t txstat;
1117
1118 cur_tx = sc->wb_cdata.wb_tx_head;
1119 txstat = WB_TXSTATUS(cur_tx);
1120
1121 if ((txstat & WB_TXSTAT_OWN) || txstat == WB_UNSENT)
1122 break;
1123
1124 if (txstat & WB_TXSTAT_TXERR) {
1125 ifp->if_oerrors++;
1126 if (txstat & WB_TXSTAT_ABORT)
1127 ifp->if_collisions++;
1128 if (txstat & WB_TXSTAT_LATECOLL)
1129 ifp->if_collisions++;
1130 }
1131
1132 ifp->if_collisions += (txstat & WB_TXSTAT_COLLCNT) >> 3;
1133
1134 ifp->if_opackets++;
1135 m_freem(cur_tx->wb_mbuf);
1136 cur_tx->wb_mbuf = NULL;
1137
1138 if (sc->wb_cdata.wb_tx_head == sc->wb_cdata.wb_tx_tail) {
1139 sc->wb_cdata.wb_tx_head = NULL;
1140 sc->wb_cdata.wb_tx_tail = NULL;
1141 break;
1142 }
1143
1144 sc->wb_cdata.wb_tx_head = cur_tx->wb_nextdesc;
1145 }
1146
1147 return;
1148 }
1149
1150
1151
1152
1153 void wb_txeoc(sc)
1154 struct wb_softc *sc;
1155 {
1156 struct ifnet *ifp;
1157
1158 ifp = &sc->arpcom.ac_if;
1159
1160 ifp->if_timer = 0;
1161
1162 if (sc->wb_cdata.wb_tx_head == NULL) {
1163 ifp->if_flags &= ~IFF_OACTIVE;
1164 sc->wb_cdata.wb_tx_tail = NULL;
1165 } else {
1166 if (WB_TXOWN(sc->wb_cdata.wb_tx_head) == WB_UNSENT) {
1167 WB_TXOWN(sc->wb_cdata.wb_tx_head) = WB_TXSTAT_OWN;
1168 ifp->if_timer = 5;
1169 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
1170 }
1171 }
1172
1173 return;
1174 }
1175
1176 int wb_intr(arg)
1177 void *arg;
1178 {
1179 struct wb_softc *sc;
1180 struct ifnet *ifp;
1181 u_int32_t status;
1182 int r = 0;
1183
1184 sc = arg;
1185 ifp = &sc->arpcom.ac_if;
1186
1187 if (!(ifp->if_flags & IFF_UP))
1188 return (r);
1189
1190
1191 CSR_WRITE_4(sc, WB_IMR, 0x00000000);
1192
1193 for (;;) {
1194
1195 status = CSR_READ_4(sc, WB_ISR);
1196 if (status)
1197 CSR_WRITE_4(sc, WB_ISR, status);
1198
1199 if ((status & WB_INTRS) == 0)
1200 break;
1201
1202 r = 1;
1203
1204 if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
1205 ifp->if_ierrors++;
1206 wb_reset(sc);
1207 if (status & WB_ISR_RX_ERR)
1208 wb_fixmedia(sc);
1209 wb_init(sc);
1210 continue;
1211 }
1212
1213 if (status & WB_ISR_RX_OK)
1214 wb_rxeof(sc);
1215
1216 if (status & WB_ISR_RX_IDLE)
1217 wb_rxeoc(sc);
1218
1219 if (status & WB_ISR_TX_OK)
1220 wb_txeof(sc);
1221
1222 if (status & WB_ISR_TX_NOBUF)
1223 wb_txeoc(sc);
1224
1225 if (status & WB_ISR_TX_IDLE) {
1226 wb_txeof(sc);
1227 if (sc->wb_cdata.wb_tx_head != NULL) {
1228 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
1229 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
1230 }
1231 }
1232
1233 if (status & WB_ISR_TX_UNDERRUN) {
1234 ifp->if_oerrors++;
1235 wb_txeof(sc);
1236 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
1237
1238 sc->wb_txthresh += WB_TXTHRESH_CHUNK;
1239 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
1240 WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
1241 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
1242 }
1243
1244 if (status & WB_ISR_BUS_ERR) {
1245 wb_reset(sc);
1246 wb_init(sc);
1247 }
1248
1249 }
1250
1251
1252 CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
1253
1254 if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
1255 wb_start(ifp);
1256 }
1257
1258 return (r);
1259 }
1260
1261 void
1262 wb_tick(xsc)
1263 void *xsc;
1264 {
1265 struct wb_softc *sc = xsc;
1266 int s;
1267
1268 s = splnet();
1269 mii_tick(&sc->sc_mii);
1270 splx(s);
1271 timeout_add(&sc->wb_tick_tmo, hz);
1272 }
1273
1274
1275
1276
1277
1278 int wb_encap(sc, c, m_head)
1279 struct wb_softc *sc;
1280 struct wb_chain *c;
1281 struct mbuf *m_head;
1282 {
1283 int frag = 0;
1284 struct wb_desc *f = NULL;
1285 int total_len;
1286 struct mbuf *m;
1287
1288
1289
1290
1291
1292
1293 m = m_head;
1294 total_len = 0;
1295
1296 for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
1297 if (m->m_len != 0) {
1298 if (frag == WB_MAXFRAGS)
1299 break;
1300 total_len += m->m_len;
1301 f = &c->wb_ptr->wb_frag[frag];
1302 f->wb_ctl = WB_TXCTL_TLINK | m->m_len;
1303 if (frag == 0) {
1304 f->wb_ctl |= WB_TXCTL_FIRSTFRAG;
1305 f->wb_status = 0;
1306 } else
1307 f->wb_status = WB_TXSTAT_OWN;
1308 f->wb_next = VTOPHYS(&c->wb_ptr->wb_frag[frag + 1]);
1309 f->wb_data = VTOPHYS(mtod(m, vaddr_t));
1310 frag++;
1311 }
1312 }
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322 if (m != NULL) {
1323 struct mbuf *m_new = NULL;
1324
1325 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
1326 if (m_new == NULL)
1327 return(1);
1328 if (m_head->m_pkthdr.len > MHLEN) {
1329 MCLGET(m_new, M_DONTWAIT);
1330 if (!(m_new->m_flags & M_EXT)) {
1331 m_freem(m_new);
1332 return(1);
1333 }
1334 }
1335 m_copydata(m_head, 0, m_head->m_pkthdr.len,
1336 mtod(m_new, caddr_t));
1337 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
1338 m_freem(m_head);
1339 m_head = m_new;
1340 f = &c->wb_ptr->wb_frag[0];
1341 f->wb_status = 0;
1342 f->wb_data = VTOPHYS(mtod(m_new, caddr_t));
1343 f->wb_ctl = total_len = m_new->m_len;
1344 f->wb_ctl |= WB_TXCTL_TLINK|WB_TXCTL_FIRSTFRAG;
1345 frag = 1;
1346 }
1347
1348 if (total_len < WB_MIN_FRAMELEN) {
1349 f = &c->wb_ptr->wb_frag[frag];
1350 f->wb_ctl = WB_MIN_FRAMELEN - total_len;
1351 f->wb_data = VTOPHYS(&sc->wb_cdata.wb_pad);
1352 f->wb_ctl |= WB_TXCTL_TLINK;
1353 f->wb_status = WB_TXSTAT_OWN;
1354 frag++;
1355 }
1356
1357 c->wb_mbuf = m_head;
1358 c->wb_lastdesc = frag - 1;
1359 WB_TXCTL(c) |= WB_TXCTL_LASTFRAG;
1360 WB_TXNEXT(c) = VTOPHYS(&c->wb_nextdesc->wb_ptr->wb_frag[0]);
1361
1362 return(0);
1363 }
1364
1365
1366
1367
1368
1369
1370
1371
1372 void wb_start(ifp)
1373 struct ifnet *ifp;
1374 {
1375 struct wb_softc *sc;
1376 struct mbuf *m_head = NULL;
1377 struct wb_chain *cur_tx = NULL, *start_tx;
1378
1379 sc = ifp->if_softc;
1380
1381
1382
1383
1384
1385 if (sc->wb_cdata.wb_tx_free->wb_mbuf != NULL) {
1386 ifp->if_flags |= IFF_OACTIVE;
1387 return;
1388 }
1389
1390 start_tx = sc->wb_cdata.wb_tx_free;
1391
1392 while(sc->wb_cdata.wb_tx_free->wb_mbuf == NULL) {
1393 IFQ_DEQUEUE(&ifp->if_snd, m_head);
1394 if (m_head == NULL)
1395 break;
1396
1397
1398 cur_tx = sc->wb_cdata.wb_tx_free;
1399 sc->wb_cdata.wb_tx_free = cur_tx->wb_nextdesc;
1400
1401
1402 wb_encap(sc, cur_tx, m_head);
1403
1404 if (cur_tx != start_tx)
1405 WB_TXOWN(cur_tx) = WB_TXSTAT_OWN;
1406
1407 #if NBPFILTER > 0
1408
1409
1410
1411
1412 if (ifp->if_bpf)
1413 bpf_mtap(ifp->if_bpf, cur_tx->wb_mbuf,
1414 BPF_DIRECTION_OUT);
1415 #endif
1416 }
1417
1418
1419
1420
1421 if (cur_tx == NULL)
1422 return;
1423
1424
1425
1426
1427
1428
1429
1430
1431 WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
1432 cur_tx->wb_ptr->wb_frag[0].wb_ctl |= WB_TXCTL_FINT;
1433 sc->wb_cdata.wb_tx_tail = cur_tx;
1434
1435 if (sc->wb_cdata.wb_tx_head == NULL) {
1436 sc->wb_cdata.wb_tx_head = start_tx;
1437 WB_TXOWN(start_tx) = WB_TXSTAT_OWN;
1438 CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
1439 } else {
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452 WB_TXOWN(start_tx) = WB_UNSENT;
1453 }
1454
1455
1456
1457
1458 ifp->if_timer = 5;
1459
1460 return;
1461 }
1462
1463 void wb_init(xsc)
1464 void *xsc;
1465 {
1466 struct wb_softc *sc = xsc;
1467 struct ifnet *ifp = &sc->arpcom.ac_if;
1468 int s, i;
1469
1470 s = splnet();
1471
1472
1473
1474
1475 wb_stop(sc);
1476 wb_reset(sc);
1477
1478 sc->wb_txthresh = WB_TXTHRESH_INIT;
1479
1480
1481
1482
1483 #ifdef foo
1484 CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_CONFIG);
1485 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
1486 WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
1487 #endif
1488
1489 CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION);
1490 WB_SETBIT(sc, WB_BUSCTL, WB_BURSTLEN_16LONG);
1491 switch(sc->wb_cachesize) {
1492 case 32:
1493 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_32LONG);
1494 break;
1495 case 16:
1496 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_16LONG);
1497 break;
1498 case 8:
1499 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_8LONG);
1500 break;
1501 case 0:
1502 default:
1503 WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_NONE);
1504 break;
1505 }
1506
1507
1508 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_EARLY_ON);
1509
1510
1511 for (i = 0; i < ETHER_ADDR_LEN; i++) {
1512 CSR_WRITE_1(sc, WB_NODE0 + i, sc->arpcom.ac_enaddr[i]);
1513 }
1514
1515
1516 if (wb_list_rx_init(sc) == ENOBUFS) {
1517 printf("%s: initialization failed: no "
1518 "memory for rx buffers\n", sc->sc_dev.dv_xname);
1519 wb_stop(sc);
1520 splx(s);
1521 return;
1522 }
1523
1524
1525 wb_list_tx_init(sc);
1526
1527
1528 if (ifp->if_flags & IFF_PROMISC) {
1529 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
1530 } else {
1531 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
1532 }
1533
1534
1535
1536
1537 if (ifp->if_flags & IFF_BROADCAST) {
1538 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
1539 } else {
1540 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
1541 }
1542
1543
1544
1545
1546 wb_setmulti(sc);
1547
1548
1549
1550
1551 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
1552 CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
1553
1554
1555
1556
1557 CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
1558 CSR_WRITE_4(sc, WB_ISR, 0xFFFFFFFF);
1559
1560
1561 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
1562 CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
1563
1564 WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
1565 CSR_WRITE_4(sc, WB_TXADDR, VTOPHYS(&sc->wb_ldata->wb_tx_list[0]));
1566 WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
1567
1568 ifp->if_flags |= IFF_RUNNING;
1569 ifp->if_flags &= ~IFF_OACTIVE;
1570
1571 splx(s);
1572
1573 timeout_set(&sc->wb_tick_tmo, wb_tick, sc);
1574 timeout_add(&sc->wb_tick_tmo, hz);
1575
1576 return;
1577 }
1578
1579
1580
1581
1582 int
1583 wb_ifmedia_upd(ifp)
1584 struct ifnet *ifp;
1585 {
1586 struct wb_softc *sc = ifp->if_softc;
1587
1588 if (ifp->if_flags & IFF_UP)
1589 wb_init(sc);
1590
1591 return(0);
1592 }
1593
1594
1595
1596
1597 void
1598 wb_ifmedia_sts(ifp, ifmr)
1599 struct ifnet *ifp;
1600 struct ifmediareq *ifmr;
1601 {
1602 struct wb_softc *sc = ifp->if_softc;
1603 struct mii_data *mii = &sc->sc_mii;
1604
1605 mii_pollstat(mii);
1606 ifmr->ifm_active = mii->mii_media_active;
1607 ifmr->ifm_status = mii->mii_media_status;
1608 }
1609
1610 int wb_ioctl(ifp, command, data)
1611 struct ifnet *ifp;
1612 u_long command;
1613 caddr_t data;
1614 {
1615 struct wb_softc *sc = ifp->if_softc;
1616 struct ifreq *ifr = (struct ifreq *) data;
1617 struct ifaddr *ifa = (struct ifaddr *)data;
1618 int s, error = 0;
1619
1620 s = splnet();
1621
1622 if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
1623 splx(s);
1624 return (error);
1625 }
1626
1627 switch(command) {
1628 case SIOCSIFADDR:
1629 ifp->if_flags |= IFF_UP;
1630 switch (ifa->ifa_addr->sa_family) {
1631 #ifdef INET
1632 case AF_INET:
1633 wb_init(sc);
1634 arp_ifinit(&sc->arpcom, ifa);
1635 break;
1636 #endif
1637 default:
1638 wb_init(sc);
1639 }
1640 break;
1641 case SIOCSIFFLAGS:
1642 if (ifp->if_flags & IFF_UP) {
1643 wb_init(sc);
1644 } else {
1645 if (ifp->if_flags & IFF_RUNNING)
1646 wb_stop(sc);
1647 }
1648 error = 0;
1649 break;
1650 case SIOCADDMULTI:
1651 case SIOCDELMULTI:
1652 error = (command == SIOCADDMULTI) ?
1653 ether_addmulti(ifr, &sc->arpcom) :
1654 ether_delmulti(ifr, &sc->arpcom);
1655
1656 if (error == ENETRESET) {
1657
1658
1659
1660
1661 if (ifp->if_flags & IFF_RUNNING)
1662 wb_setmulti(sc);
1663 error = 0;
1664 }
1665 break;
1666 case SIOCGIFMEDIA:
1667 case SIOCSIFMEDIA:
1668 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
1669 break;
1670 default:
1671 error = ENOTTY;
1672 break;
1673 }
1674
1675 splx(s);
1676
1677 return(error);
1678 }
1679
1680 void wb_watchdog(ifp)
1681 struct ifnet *ifp;
1682 {
1683 struct wb_softc *sc;
1684
1685 sc = ifp->if_softc;
1686
1687 ifp->if_oerrors++;
1688 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
1689
1690 #ifdef foo
1691 if (!(wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
1692 printf("%s: no carrier - transceiver cable problem?\n",
1693 sc->sc_dev.dv_xname);
1694 #endif
1695 wb_stop(sc);
1696 wb_reset(sc);
1697 wb_init(sc);
1698
1699 if (!IFQ_IS_EMPTY(&ifp->if_snd))
1700 wb_start(ifp);
1701
1702 return;
1703 }
1704
1705
1706
1707
1708
1709 void wb_stop(sc)
1710 struct wb_softc *sc;
1711 {
1712 int i;
1713 struct ifnet *ifp;
1714
1715 ifp = &sc->arpcom.ac_if;
1716 ifp->if_timer = 0;
1717
1718 timeout_del(&sc->wb_tick_tmo);
1719
1720 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1721
1722 WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_RX_ON|WB_NETCFG_TX_ON));
1723 CSR_WRITE_4(sc, WB_IMR, 0x00000000);
1724 CSR_WRITE_4(sc, WB_TXADDR, 0x00000000);
1725 CSR_WRITE_4(sc, WB_RXADDR, 0x00000000);
1726
1727
1728
1729
1730 for (i = 0; i < WB_RX_LIST_CNT; i++) {
1731 if (sc->wb_cdata.wb_rx_chain[i].wb_mbuf != NULL) {
1732 m_freem(sc->wb_cdata.wb_rx_chain[i].wb_mbuf);
1733 sc->wb_cdata.wb_rx_chain[i].wb_mbuf = NULL;
1734 }
1735 }
1736 bzero((char *)&sc->wb_ldata->wb_rx_list,
1737 sizeof(sc->wb_ldata->wb_rx_list));
1738
1739
1740
1741
1742 for (i = 0; i < WB_TX_LIST_CNT; i++) {
1743 if (sc->wb_cdata.wb_tx_chain[i].wb_mbuf != NULL) {
1744 m_freem(sc->wb_cdata.wb_tx_chain[i].wb_mbuf);
1745 sc->wb_cdata.wb_tx_chain[i].wb_mbuf = NULL;
1746 }
1747 }
1748
1749 bzero((char *)&sc->wb_ldata->wb_tx_list,
1750 sizeof(sc->wb_ldata->wb_tx_list));
1751 }
1752
1753
1754
1755
1756
1757 void wb_shutdown(arg)
1758 void *arg;
1759 {
1760 struct wb_softc *sc = (struct wb_softc *)arg;
1761
1762 wb_stop(sc);
1763
1764 return;
1765 }
1766
1767 struct cfattach wb_ca = {
1768 sizeof(struct wb_softc), wb_probe, wb_attach
1769 };
1770
1771 struct cfdriver wb_cd = {
1772 0, "wb", DV_IFNET
1773 };