This source file includes following definitions.
- ether_cmp
- smc91cxx_attach
- smc91cxx_mediachange
- smc91cxx_set_media
- smc91cxx_mediastatus
- smc91cxx_init
- smc91cxx_start
- smc91cxx_intr
- smc91cxx_read
- smc91cxx_ioctl
- smc91cxx_reset
- smc91cxx_watchdog
- smc91cxx_stop
- smc91cxx_enable
- smc91cxx_disable
- smc91cxx_activate
- smc91cxx_detach
- smc91cxx_mii_bitbang_read
- smc91cxx_mii_bitbang_write
- smc91cxx_mii_readreg
- smc91cxx_mii_writereg
- smc91cxx_statchg
- smc91cxx_tick
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 #include "bpfilter.h"
82
83 #include <sys/param.h>
84 #include <sys/systm.h>
85 #include <sys/mbuf.h>
86 #include <sys/syslog.h>
87 #include <sys/socket.h>
88 #include <sys/device.h>
89 #include <sys/timeout.h>
90 #include <sys/kernel.h>
91 #include <sys/malloc.h>
92 #include <sys/ioctl.h>
93 #include <sys/errno.h>
94
95 #include <machine/bus.h>
96 #include <machine/intr.h>
97
98 #include <net/if.h>
99 #include <net/if_dl.h>
100 #include <net/if_media.h>
101
102 #ifdef INET
103 #include <netinet/in.h>
104 #include <netinet/if_ether.h>
105 #include <netinet/in_systm.h>
106 #include <netinet/in_var.h>
107 #include <netinet/ip.h>
108 #endif
109
110 #if NBPFILTER > 0
111 #include <net/bpf.h>
112 #endif
113
114 #include <dev/mii/mii.h>
115 #include <dev/mii/miivar.h>
116 #include <dev/mii/mii_bitbang.h>
117
118 #include <dev/ic/smc91cxxreg.h>
119 #include <dev/ic/smc91cxxvar.h>
120
121 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
122 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
123 #define bus_space_write_multi_stream_4 bus_space_write_multi_4
124 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
125 #define bus_space_read_multi_stream_4 bus_space_read_multi_4
126 #endif
127
128
129 #define SMC91CXX_SW_PAD
130
131 const char *smc91cxx_idstrs[] = {
132 NULL,
133 NULL,
134 NULL,
135 "SMC91C90/91C92",
136 "SMC91C94/91C96",
137 "SMC91C95",
138 NULL,
139 "SMC91C100",
140 "SMC91C100FD",
141 NULL,
142 NULL,
143 NULL,
144 NULL,
145 NULL,
146 NULL,
147 NULL,
148 };
149
150
151 const int smc91cxx_media[] = {
152 IFM_ETHER|IFM_10_T,
153 IFM_ETHER|IFM_10_5,
154 };
155 #define NSMC91CxxMEDIA (sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0]))
156
157
158
159
160 u_int32_t smc91cxx_mii_bitbang_read(struct device *);
161 void smc91cxx_mii_bitbang_write(struct device *, u_int32_t);
162
163 const struct mii_bitbang_ops smc91cxx_mii_bitbang_ops = {
164 smc91cxx_mii_bitbang_read,
165 smc91cxx_mii_bitbang_write,
166 {
167 MR_MDO,
168 MR_MDI,
169 MR_MCLK,
170 MR_MDOE,
171 0,
172 }
173 };
174
175 struct cfdriver sm_cd = {
176 NULL, "sm", DV_IFNET
177 };
178
179
180 int smc91cxx_mii_readreg(struct device *, int, int);
181 void smc91cxx_mii_writereg(struct device *, int, int, int);
182 void smc91cxx_statchg(struct device *);
183 void smc91cxx_tick(void *);
184
185 int smc91cxx_mediachange(struct ifnet *);
186 void smc91cxx_mediastatus(struct ifnet *, struct ifmediareq *);
187
188 int smc91cxx_set_media(struct smc91cxx_softc *, int);
189
190 void smc91cxx_read(struct smc91cxx_softc *);
191 void smc91cxx_reset(struct smc91cxx_softc *);
192 void smc91cxx_start(struct ifnet *);
193 void smc91cxx_resume(struct smc91cxx_softc *);
194 void smc91cxx_watchdog(struct ifnet *);
195 int smc91cxx_ioctl(struct ifnet *, u_long, caddr_t);
196
197 static __inline int ether_cmp(void *, void *);
198 static __inline int
199 ether_cmp(va, vb)
200 void *va, *vb;
201 {
202 u_int8_t *a = va;
203 u_int8_t *b = vb;
204
205 return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
206 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
207 }
208
209 void
210 smc91cxx_attach(sc, myea)
211 struct smc91cxx_softc *sc;
212 u_int8_t *myea;
213 {
214 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
215 bus_space_tag_t bst = sc->sc_bst;
216 bus_space_handle_t bsh = sc->sc_bsh;
217 struct ifmedia *ifm = &sc->sc_mii.mii_media;
218 u_int32_t miicapabilities;
219 u_int16_t tmp;
220 int i, aui;
221 const char *idstr;
222
223
224 smc91cxx_stop(sc);
225
226 SMC_SELECT_BANK(sc, 3);
227 tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
228 sc->sc_chipid = RR_ID(tmp);
229
230 if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
231 idstr = NULL;
232 printf("%s: invalid BSR 0x%04x\n", sc->sc_dev.dv_xname, tmp);
233 } else
234 idstr = smc91cxx_idstrs[RR_ID(tmp)];
235 #ifdef SMC_DEBUG
236 printf("\n%s: ", sc->sc_dev.dv_xname);
237 if (idstr != NULL)
238 printf("%s, ", idstr);
239 else
240 printf("unknown chip id %d, ", sc->sc_chipid);
241 printf("revision %d", RR_REV(tmp));
242 #endif
243
244
245 SMC_SELECT_BANK(sc, 1);
246 if (myea == NULL) {
247 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
248 tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
249 sc->sc_arpcom.ac_enaddr[i + 1] = (tmp >>8) & 0xff;
250 sc->sc_arpcom.ac_enaddr[i] = tmp & 0xff;
251 }
252 } else {
253 bcopy(myea, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
254 }
255
256 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
257
258
259 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
260 ifp->if_softc = sc;
261 ifp->if_start = smc91cxx_start;
262 ifp->if_ioctl = smc91cxx_ioctl;
263 ifp->if_watchdog = smc91cxx_watchdog;
264 ifp->if_flags =
265 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
266 IFQ_SET_READY(&ifp->if_snd);
267
268
269 if_attach(ifp);
270 ether_ifattach(ifp);
271
272
273
274
275
276 sc->sc_mii.mii_ifp = ifp;
277 sc->sc_mii.mii_readreg = smc91cxx_mii_readreg;
278 sc->sc_mii.mii_writereg = smc91cxx_mii_writereg;
279 sc->sc_mii.mii_statchg = smc91cxx_statchg;
280 ifmedia_init(ifm, 0, smc91cxx_mediachange, smc91cxx_mediastatus);
281
282 SMC_SELECT_BANK(sc, 1);
283 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
284
285 miicapabilities = BMSR_MEDIAMASK|BMSR_ANEG;
286 switch (sc->sc_chipid) {
287 case CHIP_91100:
288
289
290
291
292 miicapabilities &= ~(BMSR_100TXFDX | BMSR_10TFDX);
293 case CHIP_91100FD:
294 if (tmp & CR_MII_SELECT) {
295 #ifdef SMC_DEBUG
296 printf("%s: default media MII\n",
297 sc->sc_dev.dv_xname);
298 #endif
299 mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff,
300 MII_PHY_ANY, MII_OFFSET_ANY, 0);
301 if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
302 ifmedia_add(&sc->sc_mii.mii_media,
303 IFM_ETHER|IFM_NONE, 0, NULL);
304 ifmedia_set(&sc->sc_mii.mii_media,
305 IFM_ETHER|IFM_NONE);
306 } else {
307 ifmedia_set(&sc->sc_mii.mii_media,
308 IFM_ETHER|IFM_AUTO);
309 }
310 sc->sc_flags |= SMC_FLAGS_HAS_MII;
311 break;
312 }
313
314 default:
315 aui = tmp & CR_AUI_SELECT;
316 #ifdef SMC_DEBUG
317 printf("%s: default media %s\n", sc->sc_dev.dv_xname,
318 aui ? "AUI" : "UTP");
319 #endif
320 for (i = 0; i < NSMC91CxxMEDIA; i++)
321 ifmedia_add(ifm, smc91cxx_media[i], 0, NULL);
322 ifmedia_set(ifm, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T));
323 break;
324 }
325
326
327 sc->sc_flags |= SMC_FLAGS_ATTACHED;
328 }
329
330
331
332
333 int
334 smc91cxx_mediachange(ifp)
335 struct ifnet *ifp;
336 {
337 struct smc91cxx_softc *sc = ifp->if_softc;
338
339 return (smc91cxx_set_media(sc, sc->sc_mii.mii_media.ifm_media));
340 }
341
342 int
343 smc91cxx_set_media(sc, media)
344 struct smc91cxx_softc *sc;
345 int media;
346 {
347 bus_space_tag_t bst = sc->sc_bst;
348 bus_space_handle_t bsh = sc->sc_bsh;
349 u_int16_t tmp;
350
351
352
353
354
355
356 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0)
357 return (0);
358
359 if (IFM_TYPE(media) != IFM_ETHER)
360 return (EINVAL);
361
362 if (sc->sc_flags & SMC_FLAGS_HAS_MII)
363 return (mii_mediachg(&sc->sc_mii));
364
365 switch (IFM_SUBTYPE(media)) {
366 case IFM_10_T:
367 case IFM_10_5:
368 SMC_SELECT_BANK(sc, 1);
369 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
370 if (IFM_SUBTYPE(media) == IFM_10_5)
371 tmp |= CR_AUI_SELECT;
372 else
373 tmp &= ~CR_AUI_SELECT;
374 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
375 delay(20000);
376 break;
377
378 default:
379 return (EINVAL);
380 }
381
382 return (0);
383 }
384
385
386
387
388 void
389 smc91cxx_mediastatus(ifp, ifmr)
390 struct ifnet *ifp;
391 struct ifmediareq *ifmr;
392 {
393 struct smc91cxx_softc *sc = ifp->if_softc;
394 bus_space_tag_t bst = sc->sc_bst;
395 bus_space_handle_t bsh = sc->sc_bsh;
396 u_int16_t tmp;
397
398 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
399 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
400 ifmr->ifm_status = 0;
401 return;
402 }
403
404
405
406
407 if (sc->sc_flags & SMC_FLAGS_HAS_MII) {
408 mii_pollstat(&sc->sc_mii);
409 ifmr->ifm_active = sc->sc_mii.mii_media_active;
410 ifmr->ifm_status = sc->sc_mii.mii_media_status;
411 return;
412 }
413
414 SMC_SELECT_BANK(sc, 1);
415 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
416 ifmr->ifm_active =
417 IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
418 }
419
420
421
422
423 void
424 smc91cxx_init(sc)
425 struct smc91cxx_softc *sc;
426 {
427 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
428 bus_space_tag_t bst = sc->sc_bst;
429 bus_space_handle_t bsh = sc->sc_bsh;
430 u_int16_t tmp;
431 int s, i;
432
433 s = splnet();
434
435
436
437
438
439
440
441
442 SMC_SELECT_BANK(sc, 0);
443 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
444 delay(100);
445 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
446 delay(200);
447
448 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
449
450
451 SMC_SELECT_BANK(sc, 1);
452 for (i = 0; i < ETHER_ADDR_LEN; i++ )
453 bus_space_write_1(bst, bsh, IAR_ADDR0_REG_W + i,
454 sc->sc_arpcom.ac_enaddr[i]);
455
456
457
458
459
460
461 bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
462 CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
463
464
465
466
467 SMC_SELECT_BANK(sc, 2);
468 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
469 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
470 ;
471
472
473
474
475 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
476
477
478
479
480 smc91cxx_set_media(sc, sc->sc_mii.mii_media.ifm_cur->ifm_media);
481
482
483
484
485
486
487
488
489
490 SMC_SELECT_BANK(sc, 0);
491
492 tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
493 if (ifp->if_flags & IFF_PROMISC)
494 tmp |= RCR_PROMISC;
495
496 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
497
498
499
500
501 tmp = TCR_ENABLE;
502
503 #ifndef SMC91CXX_SW_PAD
504
505
506
507
508 tmp |= TCR_PAD_ENABLE;
509 #endif
510
511 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
512
513
514
515
516 SMC_SELECT_BANK(sc, 2);
517
518 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
519 IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
520
521
522 ifp->if_flags |= IFF_RUNNING;
523 ifp->if_flags &= ~IFF_OACTIVE;
524
525 if (sc->sc_flags & SMC_FLAGS_HAS_MII) {
526
527 timeout_set(&sc->sc_mii_timeout, smc91cxx_tick, sc);
528 timeout_add(&sc->sc_mii_timeout, hz);
529 }
530
531
532
533
534 smc91cxx_start(ifp);
535
536 splx(s);
537 }
538
539
540
541
542
543 void
544 smc91cxx_start(ifp)
545 struct ifnet *ifp;
546 {
547 struct smc91cxx_softc *sc = ifp->if_softc;
548 bus_space_tag_t bst = sc->sc_bst;
549 bus_space_handle_t bsh = sc->sc_bsh;
550 u_int len;
551 struct mbuf *m, *top;
552 u_int16_t length, npages;
553 u_int8_t packetno;
554 int timo, pad;
555
556 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
557 return;
558
559 again:
560
561
562
563 IFQ_POLL(&ifp->if_snd, m);
564 if (m == NULL)
565 return;
566
567
568
569
570
571
572 for (len = 0, top = m; m != NULL; m = m->m_next)
573 len += m->m_len;
574 pad = (len & 1);
575
576
577
578
579
580 if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
581 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
582 ifp->if_oerrors++;
583 IFQ_DEQUEUE(&ifp->if_snd, m);
584 m_freem(m);
585 goto readcheck;
586 }
587
588 #ifdef SMC91CXX_SW_PAD
589
590
591
592 if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
593 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
594 #endif
595
596 length = pad + len;
597
598
599
600
601
602
603 npages = (length + 6) >> 8;
604
605
606
607
608 SMC_SELECT_BANK(sc, 2);
609 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
610
611 timo = MEMORY_WAIT_TIME;
612 do {
613 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
614 break;
615 delay(1);
616 } while (--timo);
617
618 packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
619
620 if (packetno & ARR_FAILED || timo == 0) {
621
622
623
624
625
626
627
628
629 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
630 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
631
632 ifp->if_timer = 5;
633 ifp->if_flags |= IFF_OACTIVE;
634
635 return;
636 }
637
638
639
640
641 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
642
643
644
645
646 bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC );
647
648
649
650
651
652 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
653 bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
654 bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
655
656
657
658
659
660 IFQ_DEQUEUE(&ifp->if_snd, m);
661
662
663
664
665 for (top = m; m != NULL; m = m->m_next) {
666
667 if (m->m_len > 1)
668 bus_space_write_multi_stream_2(bst, bsh, DATA_REG_W,
669 mtod(m, u_int16_t *), m->m_len >> 1);
670
671
672 if (m->m_len & 1)
673 bus_space_write_1(bst, bsh, DATA_REG_B,
674 *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
675 }
676
677 #ifdef SMC91CXX_SW_PAD
678
679
680
681 while (pad > 1) {
682 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
683 pad -= 2;
684 }
685 if (pad)
686 bus_space_write_1(bst, bsh, DATA_REG_B, 0);
687 #endif
688
689
690
691
692
693
694 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
695
696
697
698
699
700 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
701 bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
702 IM_TX_INT | IM_TX_EMPTY_INT);
703
704 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
705
706 ifp->if_timer = 5;
707
708 #if NBPFILTER > 0
709
710 if (ifp->if_bpf)
711 bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_OUT);
712 #endif
713
714 ifp->if_opackets++;
715 m_freem(top);
716
717 readcheck:
718
719
720
721
722
723 if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
724 goto again;
725 }
726
727
728
729
730 int
731 smc91cxx_intr(arg)
732 void *arg;
733 {
734 struct smc91cxx_softc *sc = arg;
735 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
736 bus_space_tag_t bst = sc->sc_bst;
737 bus_space_handle_t bsh = sc->sc_bsh;
738 u_int8_t mask, interrupts, status;
739 u_int16_t packetno, tx_status, card_stats;
740
741 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 ||
742 (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
743 return (0);
744
745 SMC_SELECT_BANK(sc, 2);
746
747
748
749
750 mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
751
752
753
754
755
756 interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
757 status = interrupts & mask;
758
759
760 if (status == 0)
761 return (0);
762
763
764
765
766 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
767
768
769
770
771 if (status & IM_RX_OVRN_INT) {
772 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
773 ifp->if_ierrors++;
774 }
775
776
777
778
779 if (status & IM_RCV_INT) {
780 #if 1
781 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
782 if (packetno & FIFO_REMPTY) {
783 printf("%s: receive interrupt on empty fifo\n",
784 sc->sc_dev.dv_xname);
785 goto out;
786 } else
787 #endif
788 smc91cxx_read(sc);
789 }
790
791
792
793
794 if (status & IM_ALLOC_INT) {
795
796 mask &= ~IM_ALLOC_INT;
797
798
799
800
801
802 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
803 ;
804 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
805
806 ifp->if_flags &= ~IFF_OACTIVE;
807 ifp->if_timer = 0;
808 }
809
810
811
812
813
814
815 if (status & IM_TX_INT) {
816 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
817
818 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
819 FIFO_TX_MASK;
820
821
822
823
824 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
825
826
827
828
829 bus_space_write_2(bst, bsh, POINTER_REG_W,
830 PTR_AUTOINC | PTR_READ );
831
832
833
834
835
836
837 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
838
839 if (tx_status & EPHSR_TX_SUC)
840 printf("%s: successful packet caused TX interrupt?!\n",
841 sc->sc_dev.dv_xname);
842 else
843 ifp->if_oerrors++;
844
845 if (tx_status & EPHSR_LATCOL)
846 ifp->if_collisions++;
847
848
849
850
851 SMC_SELECT_BANK(sc, 0);
852 #ifdef SMC91CXX_SW_PAD
853 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
854 #else
855 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
856 TCR_ENABLE | TCR_PAD_ENABLE);
857 #endif
858
859
860
861
862 SMC_SELECT_BANK(sc, 2);
863 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
864 ;
865 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
866
867 ifp->if_timer = 0;
868 }
869
870
871
872
873
874 if (status & IM_TX_EMPTY_INT) {
875 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
876
877
878 mask &= ~IM_TX_EMPTY_INT;
879
880 SMC_SELECT_BANK(sc, 0);
881 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
882
883
884 ifp->if_collisions += card_stats & ECR_COLN_MASK;
885
886
887 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
888
889 SMC_SELECT_BANK(sc, 2);
890
891 ifp->if_timer = 0;
892 }
893
894
895
896
897 if (status & IM_EPH_INT) {
898 smc91cxx_stop(sc);
899 smc91cxx_init(sc);
900 }
901
902
903
904
905 smc91cxx_start(ifp);
906
907 out:
908
909
910
911
912 mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
913 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
914
915 return (1);
916 }
917
918
919
920
921
922 void
923 smc91cxx_read(sc)
924 struct smc91cxx_softc *sc;
925 {
926 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
927 bus_space_tag_t bst = sc->sc_bst;
928 bus_space_handle_t bsh = sc->sc_bsh;
929 struct mbuf *m;
930 u_int16_t status, packetno, packetlen;
931 u_int8_t *data;
932
933 again:
934
935
936
937
938
939 bus_space_write_2(bst, bsh, POINTER_REG_W,
940 PTR_READ | PTR_RCV | PTR_AUTOINC );
941
942
943
944
945 status = bus_space_read_2(bst, bsh, DATA_REG_W);
946 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
947
948
949
950
951
952 packetlen -= 6;
953
954
955
956
957 if (status & RS_ERRORS) {
958 ifp->if_ierrors++;
959 goto out;
960 }
961
962
963
964
965 if (status & RS_ODDFRAME)
966 packetlen++;
967
968
969
970
971 MGETHDR(m, M_DONTWAIT, MT_DATA);
972 if (m == NULL)
973 goto out;
974 m->m_pkthdr.rcvif = ifp;
975 m->m_pkthdr.len = packetlen;
976
977
978
979
980
981 MCLGET(m, M_DONTWAIT);
982 if ((m->m_flags & M_EXT) == 0) {
983 m_freem(m);
984 ifp->if_ierrors++;
985 printf("%s: can't allocate cluster for incoming packet\n",
986 sc->sc_dev.dv_xname);
987 goto out;
988 }
989
990
991
992
993
994 m->m_data = (caddr_t) ALIGN(mtod(m, caddr_t) +
995 sizeof(struct ether_header)) - sizeof(struct ether_header);
996
997 data = mtod(m, u_int8_t *);
998 if (packetlen > 1)
999 bus_space_read_multi_stream_2(bst, bsh, DATA_REG_W,
1000 (u_int16_t *)data, packetlen >> 1);
1001 if (packetlen & 1) {
1002 data += packetlen & ~1;
1003 *data = bus_space_read_1(bst, bsh, DATA_REG_B);
1004 }
1005
1006 ifp->if_ipackets++;
1007
1008 #if NBPFILTER > 0
1009
1010
1011
1012
1013 if (ifp->if_bpf)
1014 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1015 #endif
1016
1017 m->m_pkthdr.len = m->m_len = packetlen;
1018 ether_input_mbuf(ifp, m);
1019
1020 out:
1021
1022
1023
1024 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
1025 ;
1026 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
1027
1028
1029
1030
1031 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
1032 if (packetno & FIFO_REMPTY)
1033 return;
1034 goto again;
1035 }
1036
1037
1038
1039
1040 int
1041 smc91cxx_ioctl(ifp, cmd, data)
1042 struct ifnet *ifp;
1043 u_long cmd;
1044 caddr_t data;
1045 {
1046 struct smc91cxx_softc *sc = ifp->if_softc;
1047 struct ifaddr *ifa = (struct ifaddr *)data;
1048 struct ifreq *ifr = (struct ifreq *)data;
1049 int s, error = 0;
1050
1051 s = splnet();
1052
1053 switch (cmd) {
1054 case SIOCSIFADDR:
1055 if ((error = smc91cxx_enable(sc)) != 0)
1056 break;
1057 ifp->if_flags |= IFF_UP;
1058 switch (ifa->ifa_addr->sa_family) {
1059 #ifdef INET
1060 case AF_INET:
1061 smc91cxx_init(sc);
1062 arp_ifinit(&sc->sc_arpcom, ifa);
1063 break;
1064 #endif
1065 default:
1066 smc91cxx_init(sc);
1067 break;
1068 }
1069 break;
1070
1071 case SIOCSIFFLAGS:
1072 if ((ifp->if_flags & IFF_UP) == 0 &&
1073 (ifp->if_flags & IFF_RUNNING) != 0) {
1074
1075
1076
1077
1078 smc91cxx_stop(sc);
1079 ifp->if_flags &= ~IFF_RUNNING;
1080 smc91cxx_disable(sc);
1081 } else if ((ifp->if_flags & IFF_UP) != 0 &&
1082 (ifp->if_flags & IFF_RUNNING) == 0) {
1083
1084
1085
1086
1087 if ((error = smc91cxx_enable(sc)) != 0)
1088 break;
1089 smc91cxx_init(sc);
1090 } else if ((ifp->if_flags & IFF_UP) != 0) {
1091
1092
1093
1094
1095 smc91cxx_reset(sc);
1096 }
1097 break;
1098
1099 case SIOCADDMULTI:
1100 case SIOCDELMULTI:
1101 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
1102 error = EIO;
1103 break;
1104 }
1105
1106 error = (cmd == SIOCADDMULTI) ?
1107 ether_addmulti(ifr, &sc->sc_arpcom) :
1108 ether_delmulti(ifr, &sc->sc_arpcom);
1109 if (error == ENETRESET) {
1110
1111
1112
1113
1114 if (ifp->if_flags & IFF_RUNNING)
1115 smc91cxx_reset(sc);
1116 error = 0;
1117 }
1118 break;
1119
1120 case SIOCGIFMEDIA:
1121 case SIOCSIFMEDIA:
1122 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1123 break;
1124
1125 default:
1126 error = EINVAL;
1127 break;
1128 }
1129
1130 splx(s);
1131 return (error);
1132 }
1133
1134
1135
1136
1137 void
1138 smc91cxx_reset(sc)
1139 struct smc91cxx_softc *sc;
1140 {
1141 int s;
1142
1143 s = splnet();
1144 smc91cxx_stop(sc);
1145 smc91cxx_init(sc);
1146 splx(s);
1147 }
1148
1149
1150
1151
1152 void
1153 smc91cxx_watchdog(ifp)
1154 struct ifnet *ifp;
1155 {
1156 struct smc91cxx_softc *sc = ifp->if_softc;
1157
1158 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1159 ++sc->sc_arpcom.ac_if.if_oerrors;
1160
1161 smc91cxx_reset(sc);
1162 }
1163
1164
1165
1166
1167 void
1168 smc91cxx_stop(sc)
1169 struct smc91cxx_softc *sc;
1170 {
1171 bus_space_tag_t bst = sc->sc_bst;
1172 bus_space_handle_t bsh = sc->sc_bsh;
1173
1174
1175
1176
1177 SMC_SELECT_BANK(sc, 2);
1178 bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
1179
1180
1181
1182
1183 SMC_SELECT_BANK(sc, 0);
1184 bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
1185 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
1186
1187
1188
1189
1190 sc->sc_arpcom.ac_if.if_timer = 0;
1191 }
1192
1193
1194
1195
1196 int
1197 smc91cxx_enable(sc)
1198 struct smc91cxx_softc *sc;
1199 {
1200 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 && sc->sc_enable != NULL) {
1201 if ((*sc->sc_enable)(sc) != 0) {
1202 printf("%s: device enable failed\n",
1203 sc->sc_dev.dv_xname);
1204 return (EIO);
1205 }
1206 }
1207
1208 sc->sc_flags |= SMC_FLAGS_ENABLED;
1209 return (0);
1210 }
1211
1212
1213
1214
1215 void
1216 smc91cxx_disable(sc)
1217 struct smc91cxx_softc *sc;
1218 {
1219 if ((sc->sc_flags & SMC_FLAGS_ENABLED) != 0 && sc->sc_disable != NULL) {
1220 (*sc->sc_disable)(sc);
1221 sc->sc_flags &= ~SMC_FLAGS_ENABLED;
1222 }
1223 }
1224
1225 int
1226 smc91cxx_activate(self, act)
1227 struct device *self;
1228 enum devact act;
1229 {
1230 #if 0
1231 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1232 #endif
1233 int rv = 0, s;
1234
1235 s = splnet();
1236 switch (act) {
1237 case DVACT_ACTIVATE:
1238 break;
1239
1240 case DVACT_DEACTIVATE:
1241 #if 0
1242 if_deactivate(&sc->sc_ic.ic_if);
1243 #endif
1244 break;
1245 }
1246 splx(s);
1247 return(rv);
1248 }
1249
1250 int
1251 smc91cxx_detach(self, flags)
1252 struct device *self;
1253 int flags;
1254 {
1255 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1256 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1257
1258
1259 if ((sc->sc_flags & SMC_FLAGS_ATTACHED) == 0)
1260 return(0);
1261
1262
1263 smc91cxx_disable(sc);
1264
1265
1266
1267
1268 ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
1269
1270 #if NBPFILTER > 0
1271 bpfdetach(ifp);
1272 #endif
1273 ether_ifdetach(ifp);
1274 if_detach(ifp);
1275
1276 return (0);
1277 }
1278
1279 u_int32_t
1280 smc91cxx_mii_bitbang_read(self)
1281 struct device *self;
1282 {
1283 struct smc91cxx_softc *sc = (void *) self;
1284
1285
1286 return (bus_space_read_2(sc->sc_bst, sc->sc_bsh, MGMT_REG_W));
1287 }
1288
1289 void
1290 smc91cxx_mii_bitbang_write(self, val)
1291 struct device *self;
1292 u_int32_t val;
1293 {
1294 struct smc91cxx_softc *sc = (void *) self;
1295
1296
1297 bus_space_write_2(sc->sc_bst, sc->sc_bsh, MGMT_REG_W, val);
1298 }
1299
1300 int
1301 smc91cxx_mii_readreg(self, phy, reg)
1302 struct device *self;
1303 int phy, reg;
1304 {
1305 struct smc91cxx_softc *sc = (void *) self;
1306 int val;
1307
1308 SMC_SELECT_BANK(sc, 3);
1309
1310 val = mii_bitbang_readreg(self, &smc91cxx_mii_bitbang_ops, phy, reg);
1311
1312 SMC_SELECT_BANK(sc, 2);
1313
1314 return (val);
1315 }
1316
1317 void
1318 smc91cxx_mii_writereg(self, phy, reg, val)
1319 struct device *self;
1320 int phy, reg, val;
1321 {
1322 struct smc91cxx_softc *sc = (void *) self;
1323
1324 SMC_SELECT_BANK(sc, 3);
1325
1326 mii_bitbang_writereg(self, &smc91cxx_mii_bitbang_ops, phy, reg, val);
1327
1328 SMC_SELECT_BANK(sc, 2);
1329 }
1330
1331 void
1332 smc91cxx_statchg(self)
1333 struct device *self;
1334 {
1335 struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
1336 bus_space_tag_t bst = sc->sc_bst;
1337 bus_space_handle_t bsh = sc->sc_bsh;
1338 int mctl;
1339
1340 SMC_SELECT_BANK(sc, 0);
1341 mctl = bus_space_read_2(bst, bsh, TXMIT_CONTROL_REG_W);
1342 if (sc->sc_mii.mii_media_active & IFM_FDX)
1343 mctl |= TCR_SWFDUP;
1344 else
1345 mctl &= ~TCR_SWFDUP;
1346 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, mctl);
1347 SMC_SELECT_BANK(sc, 2);
1348 }
1349
1350
1351
1352
1353 void
1354 smc91cxx_tick(arg)
1355 void *arg;
1356 {
1357 struct smc91cxx_softc *sc = arg;
1358 int s;
1359
1360 #ifdef DIAGNOSTIC
1361 if ((sc->sc_flags & SMC_FLAGS_HAS_MII) == 0)
1362 panic("smc91cxx_tick");
1363 #endif
1364
1365 if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
1366 return;
1367
1368 s = splnet();
1369 mii_tick(&sc->sc_mii);
1370 splx(s);
1371
1372 timeout_add(&sc->sc_mii_timeout, hz);
1373 }