This source file includes following definitions.
- look_for_card
- ex_probe
- ex_attach
- ex_init
- ex_start
- ex_stop
- exintr
- ex_tx_intr
- ex_rx_intr
- ex_ioctl
- ex_reset
- ex_watchdog
- eeprom_read
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 #include "ex.h"
39 #if NEX > 0
40 #include "bpfilter.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/conf.h>
45 #include <sys/sockio.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/device.h>
49
50 #include <net/if.h>
51
52 #ifdef INET
53 #include <netinet/in.h>
54 #include <netinet/if_ether.h>
55 #endif
56
57 #if NBPFILTER > 0
58 #include <net/bpf.h>
59 #endif
60
61 #include <machine/cpu.h>
62 #include <machine/bus.h>
63
64 #include <dev/isa/isavar.h>
65 #include <dev/isa/if_exreg.h>
66
67
68 #ifdef EXDEBUG
69 #define Start_End 1
70 #define Rcvd_Pkts 2
71 #define Sent_Pkts 4
72 #define Status 8
73 static int debug_mask = 0;
74 static int exintr_count = 0;
75 #define DODEBUG(level, action) if (level & debug_mask) action
76 #else
77 #define DODEBUG(level, action)
78 #endif
79
80
81 #define Conn_BNC 1
82 #define Conn_TPE 2
83 #define Conn_AUI 3
84
85 struct ex_softc {
86 struct arpcom arpcom;
87 int iobase;
88 u_short connector;
89 u_short irq_no;
90 u_int mem_size;
91 u_int rx_mem_size;
92
93 u_int rx_lower_limit,
94 rx_upper_limit;
95 u_int rx_head;
96 u_int tx_mem_size;
97
98 u_int tx_lower_limit,
99 tx_upper_limit;
100 u_int tx_head, tx_tail;
101 u_int tx_last;
102
103 bus_space_tag_t sc_iot;
104 bus_space_handle_t sc_ioh;
105 void *sc_ih;
106 };
107
108
109
110
111 static char irq2eemap[] = { -1, -1, 0, 1, -1, 2, -1, -1, -1, 0, 3, 4, -1, -1,
112 -1, -1 };
113 static u_char ee2irqmap[] = { 9, 3, 5, 10, 11, 0, 0, 0 };
114
115 static int ex_probe(struct device *, void *, void *);
116 static void ex_attach(struct device *, struct device *, void *);
117 static void ex_init(struct ex_softc *);
118 static void ex_start(struct ifnet *);
119 static void ex_stop(struct ex_softc *);
120 static int ex_ioctl(struct ifnet *, u_long, caddr_t);
121 static void ex_reset(struct ex_softc *);
122 static void ex_watchdog(struct ifnet *);
123
124 static u_short eeprom_read(struct ex_softc *, int);
125 static int look_for_card(struct isa_attach_args *, struct ex_softc *sc);
126 static int exintr(void *);
127 static void ex_tx_intr(struct ex_softc *);
128 static void ex_rx_intr(struct ex_softc *);
129
130
131 struct cfattach ex_ca = {
132 sizeof(struct ex_softc), ex_probe, ex_attach
133 };
134
135 struct cfdriver ex_cd = {
136 NULL, "ex", DV_IFNET
137 };
138
139 #define BANK_SEL(X) bus_space_write_1(sc->sc_iot, sc->sc_ioh, CMD_REG, \
140 (X))
141 #define ISA_GET(offset) bus_space_read_1(sc->sc_iot, sc->sc_ioh, (offset))
142 #define ISA_PUT(offset, value) bus_space_write_1(sc->sc_iot, sc->sc_ioh, \
143 (offset), (value))
144 #define ISA_GET_2(offset) bus_space_read_2(sc->sc_iot, sc->sc_ioh, \
145 (offset))
146 #define ISA_PUT_2(offset, value) bus_space_write_2(sc->sc_iot, sc->sc_ioh, \
147 (offset), (value))
148 #define ISA_GET_2_MULTI(offset, addr, count) bus_space_read_multi_2( \
149 sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
150 #define ISA_PUT_2_MULTI(offset, addr, count) bus_space_write_multi_2( \
151 sc->sc_iot, sc->sc_ioh, (offset), (addr), (count))
152
153
154 static int
155 look_for_card(ia, sc)
156 struct isa_attach_args *ia;
157 struct ex_softc *sc;
158 {
159 int count1, count2;
160
161
162
163
164
165 if (((count1 = ISA_GET(ID_REG)) & Id_Mask) != Id_Sig)
166 return(0);
167 count2 = ISA_GET(ID_REG);
168 count2 = ISA_GET(ID_REG);
169 count2 = ISA_GET(ID_REG);
170 if ((count2 & Counter_bits) == ((count1 + 0xc0) & Counter_bits))
171 return(1);
172 else
173 return(0);
174 }
175
176
177 int
178 ex_probe(parent, match, aux)
179 struct device *parent;
180 void *match, *aux;
181 {
182 struct ex_softc *sc = match;
183 struct isa_attach_args *ia = aux;
184 u_short eaddr_tmp;
185 int tmp;
186
187 DODEBUG(Start_End, printf("ex_probe: start\n"););
188
189 if ((ia->ia_iobase >= 0x200) && (ia->ia_iobase <= 0x3a0)) {
190 sc->sc_iot = ia->ia_iot;
191 if(bus_space_map(sc->sc_iot, ia->ia_iobase, EX_IOSIZE, 0,
192 &sc->sc_ioh))
193 return(0);
194
195 if (!look_for_card(ia, sc)) {
196 bus_space_unmap(sc->sc_iot, sc->sc_ioh, EX_IOSIZE);
197 return(0);
198 }
199 } else
200 return(0);
201
202 ia->ia_iosize = EX_IOSIZE;
203
204
205
206
207 ISA_PUT(CMD_REG, Reset_CMD);
208 delay(200);
209
210
211
212
213
214
215
216
217
218 sc->iobase = ia->ia_iobase;
219 eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Lo);
220 sc->arpcom.ac_enaddr[5] = eaddr_tmp & 0xff;
221 sc->arpcom.ac_enaddr[4] = eaddr_tmp >> 8;
222 eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Mid);
223 sc->arpcom.ac_enaddr[3] = eaddr_tmp & 0xff;
224 sc->arpcom.ac_enaddr[2] = eaddr_tmp >> 8;
225 eaddr_tmp = eeprom_read(sc, EE_Eth_Addr_Hi);
226 sc->arpcom.ac_enaddr[1] = eaddr_tmp & 0xff;
227 sc->arpcom.ac_enaddr[0] = eaddr_tmp >> 8;
228 tmp = eeprom_read(sc, EE_IRQ_No) & IRQ_No_Mask;
229 if (ia->ia_irq > 0) {
230 if (ee2irqmap[tmp] != ia->ia_irq)
231 printf("ex: WARING: board's EEPROM is configured for IRQ %d, using %d\n", ee2irqmap[tmp], ia->ia_irq);
232 sc->irq_no = ia->ia_irq;
233 }
234 else {
235 sc->irq_no = ee2irqmap[tmp];
236 ia->ia_irq = sc->irq_no;
237 }
238 if (sc->irq_no == 0) {
239 printf("ex: invalid IRQ.\n");
240 return(0);
241 }
242 BANK_SEL(Bank2_Sel);
243 tmp = ISA_GET(REG3);
244 if (tmp & TPE_bit)
245 sc->connector = Conn_TPE;
246 else if (tmp & BNC_bit)
247 sc->connector = Conn_BNC;
248 else
249 sc->connector = Conn_AUI;
250 sc->mem_size = CARD_RAM_SIZE;
251
252
253 BANK_SEL(Bank0_Sel);
254
255 DODEBUG(Start_End, printf("ex_probe: finish\n"););
256 return(1);
257 }
258
259
260 void
261 ex_attach(parent, self, aux)
262 struct device *parent, *self;
263 void *aux;
264 {
265 struct ex_softc *sc = (void *)self;
266 struct isa_attach_args *ia = aux;
267 struct ifnet *ifp = &sc->arpcom.ac_if;
268
269
270
271
272 DODEBUG(Start_End, printf("ex_attach: start\n"););
273
274
275
276
277
278 ifp->if_softc = sc;
279 bcopy(self->dv_xname, ifp->if_xname, IFNAMSIZ);
280 ifp->if_start = ex_start;
281 ifp->if_ioctl = ex_ioctl;
282 ifp->if_watchdog = ex_watchdog;
283 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST;
284
285 IFQ_SET_READY(&ifp->if_snd);
286
287
288
289
290 if_attach(ifp);
291 ether_ifattach(ifp);
292 printf(": address %s, connecter ",
293 ether_sprintf(sc->arpcom.ac_enaddr));
294 switch(sc->connector) {
295 case Conn_TPE: printf("TPE\n"); break;
296 case Conn_BNC: printf("BNC\n"); break;
297 case Conn_AUI: printf("AUI\n"); break;
298 default: printf("???\n");
299 }
300
301 sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
302 IPL_NET, exintr, sc, self->dv_xname);
303 ex_init(sc);
304
305 DODEBUG(Start_End, printf("ex_attach: finish\n"););
306 }
307
308
309 void
310 ex_init(sc)
311 struct ex_softc *sc;
312 {
313 struct ifnet *ifp = &sc->arpcom.ac_if;
314 int s, i;
315 unsigned short temp_reg;
316
317 DODEBUG(Start_End, printf("ex_init: start\n"););
318
319 if (TAILQ_EMPTY(&ifp->if_addrlist))
320 return;
321 s = splnet();
322 sc->arpcom.ac_if.if_timer = 0;
323
324
325
326
327 BANK_SEL(Bank2_Sel);
328 temp_reg = ISA_GET(EEPROM_REG);
329 if (temp_reg & Trnoff_Enable)
330 ISA_PUT(EEPROM_REG, temp_reg & ~Trnoff_Enable);
331 for (i = 0; i < ETHER_ADDR_LEN; i++)
332 ISA_PUT(I_ADDR_REG0 + i, sc->arpcom.ac_enaddr[i]);
333
334
335
336
337
338
339
340 ISA_PUT(REG1, ISA_GET(REG1) | Tx_Chn_Int_Md | Tx_Chn_ErStp |
341 Disc_Bad_Fr);
342 ISA_PUT(REG2, ISA_GET(REG2) | No_SA_Ins | RX_CRC_InMem);
343 ISA_PUT(REG3, (ISA_GET(REG3) & 0x3f));
344 BANK_SEL(Bank1_Sel);
345 ISA_PUT(INT_NO_REG, (ISA_GET(INT_NO_REG) & 0xf8) |
346 irq2eemap[sc->irq_no]);
347
348
349
350
351
352
353 sc->rx_mem_size = sc->mem_size * 3 / 4;
354 sc->tx_mem_size = sc->mem_size - sc->rx_mem_size;
355 sc->rx_lower_limit = 0x0000;
356 sc->rx_upper_limit = sc->rx_mem_size - 2;
357 sc->tx_lower_limit = sc->rx_mem_size;
358 sc->tx_upper_limit = sc->mem_size - 2;
359 ISA_PUT(RCV_LOWER_LIMIT_REG, sc->rx_lower_limit >> 8);
360 ISA_PUT(RCV_UPPER_LIMIT_REG, sc->rx_upper_limit >> 8);
361 ISA_PUT(XMT_LOWER_LIMIT_REG, sc->tx_lower_limit >> 8);
362 ISA_PUT(XMT_UPPER_LIMIT_REG, sc->tx_upper_limit >> 8);
363
364
365
366
367 ISA_PUT(REG1, ISA_GET(REG1) | TriST_INT);
368 BANK_SEL(Bank0_Sel);
369 ISA_PUT(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
370 ISA_PUT(STATUS_REG, All_Int);
371
372
373
374
375 ISA_PUT_2(RCV_BAR, sc->rx_lower_limit);
376 sc->rx_head = sc->rx_lower_limit;
377 ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit | 0xfe);
378 ISA_PUT_2(XMT_BAR, sc->tx_lower_limit);
379 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
380
381 ifp->if_flags |= IFF_RUNNING;
382 ifp->if_flags &= ~IFF_OACTIVE;
383 DODEBUG(Status, printf("OIDLE init\n"););
384
385
386
387
388 ISA_PUT(CMD_REG, Sel_Reset_CMD);
389 delay(2);
390 ISA_PUT(CMD_REG, Rcv_Enable_CMD);
391
392 ex_start(ifp);
393 splx(s);
394
395 DODEBUG(Start_End, printf("ex_init: finish\n"););
396 }
397
398
399 void
400 ex_start(ifp)
401 struct ifnet *ifp;
402 {
403 register struct ex_softc *sc = ifp->if_softc;
404 int i, s, len, data_len, avail, dest, next;
405 unsigned char tmp16[2];
406 struct mbuf *opkt;
407 register struct mbuf *m;
408
409 DODEBUG(Start_End, printf("ex_start: start\n"););
410
411 s = splnet();
412
413
414
415
416
417 while (!(ifp->if_flags & IFF_OACTIVE)) {
418 IFQ_POLL(&ifp->if_snd, opkt);
419 if (opkt == NULL)
420 break;
421
422
423
424
425
426
427
428
429 for (len = 0, m = opkt; m != NULL; m = m->m_next)
430 len += m->m_len;
431 data_len = len;
432 DODEBUG(Sent_Pkts, printf("1. Sending packet with %d data bytes. ", data_len););
433 if (len & 1)
434 len += XMT_HEADER_LEN + 1;
435 else
436 len += XMT_HEADER_LEN;
437 if ((i = sc->tx_tail - sc->tx_head) >= 0)
438 avail = sc->tx_mem_size - i;
439 else
440 avail = -i;
441 DODEBUG(Sent_Pkts, printf("i=%d, avail=%d\n", i, avail););
442 if (avail >= len + XMT_HEADER_LEN) {
443 IFQ_DEQUEUE(&ifp->if_snd, opkt);
444
445 #ifdef EX_PSA_INTR
446
447
448
449
450
451
452 ISA_WRITE(MASK_REG, All_Int);
453 #endif
454
455
456
457
458
459 dest = sc->tx_tail;
460 next = dest + len;
461 if (next > sc->tx_upper_limit) {
462 if ((sc->tx_upper_limit + 2 - sc->tx_tail) <=
463 XMT_HEADER_LEN) {
464 dest = sc->tx_lower_limit;
465 next = dest + len;
466 } else
467 next = sc->tx_lower_limit + next -
468 sc->tx_upper_limit - 2;
469 }
470
471
472 DODEBUG(Sent_Pkts, printf("2. dest=%d, next=%d. ", dest, next););
473 ISA_PUT_2(HOST_ADDR_REG, dest);
474 ISA_PUT_2(IO_PORT_REG, Transmit_CMD);
475 ISA_PUT_2(IO_PORT_REG, 0);
476 ISA_PUT_2(IO_PORT_REG, next);
477 ISA_PUT_2(IO_PORT_REG, data_len);
478
479
480
481
482
483
484
485 for (m = opkt, i = 0; m != NULL; m = m->m_next) {
486 DODEBUG(Sent_Pkts, printf("[%d]", m->m_len););
487 if (i) {
488 tmp16[1] = *(mtod(m, caddr_t));
489 ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
490 }
491 ISA_PUT_2_MULTI(IO_PORT_REG, mtod(m, caddr_t)
492 + i, (m->m_len - i) / 2);
493 if ((i = (m->m_len - i) & 1))
494 tmp16[0] = *(mtod(m, caddr_t) +
495 m->m_len - 1);
496 }
497 if (i)
498 ISA_PUT_2_MULTI(IO_PORT_REG, tmp16, 1);
499
500
501
502
503
504 if (sc->tx_head != sc->tx_tail) {
505 if (sc->tx_tail != dest) {
506 ISA_PUT_2(HOST_ADDR_REG,
507 sc->tx_last + XMT_Chain_Point);
508 ISA_PUT_2(IO_PORT_REG, dest);
509 }
510 ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
511 XMT_Byte_Count);
512 i = ISA_GET_2(IO_PORT_REG);
513 ISA_PUT_2(HOST_ADDR_REG, sc->tx_last +
514 XMT_Byte_Count);
515 ISA_PUT_2(IO_PORT_REG, i | Ch_bit);
516 }
517
518
519
520
521
522
523
524 ISA_GET_2(IO_PORT_REG);
525 #ifdef EX_PSA_INTR
526 ISA_PUT_2(MASK_REG, All_Int & ~(Rx_Int | Tx_Int));
527 #endif
528 if (sc->tx_head == sc->tx_tail) {
529 ISA_PUT_2(XMT_BAR, dest);
530 ISA_PUT(CMD_REG, Transmit_CMD);
531 sc->tx_head = dest;
532 DODEBUG(Sent_Pkts, printf("Transmit\n"););
533 } else {
534 ISA_PUT(CMD_REG, Resume_XMT_List_CMD);
535 DODEBUG(Sent_Pkts, printf("Resume\n"););
536 }
537 sc->tx_last = dest;
538 sc->tx_tail = next;
539 #if NBPFILTER > 0
540 if (ifp->if_bpf != NULL)
541 bpf_mtap(ifp->if_bpf, opkt,
542 BPF_DIRECTION_OUT);
543 #endif
544 ifp->if_timer = 2;
545 ifp->if_opackets++;
546 m_freem(opkt);
547 } else {
548 ifp->if_flags |= IFF_OACTIVE;
549 DODEBUG(Status, printf("OACTIVE start\n"););
550 }
551 }
552
553 splx(s);
554
555 DODEBUG(Start_End, printf("ex_start: finish\n"););
556 }
557
558
559 void
560 ex_stop(sc)
561 struct ex_softc *sc;
562 {
563 DODEBUG(Start_End, printf("ex_stop: start\n"););
564
565
566
567
568
569
570
571
572 BANK_SEL(Bank1_Sel);
573 ISA_PUT(REG1, ISA_GET(REG1) & ~TriST_INT);
574 BANK_SEL(Bank0_Sel);
575 ISA_PUT(CMD_REG, Rcv_Stop);
576 sc->tx_head = sc->tx_tail = sc->tx_lower_limit;
577 sc->tx_last = 0;
578
579
580 ISA_PUT(MASK_REG, All_Int);
581 ISA_PUT(STATUS_REG, All_Int);
582 ISA_PUT(CMD_REG, Reset_CMD);
583 delay(200);
584
585 DODEBUG(Start_End, printf("ex_stop: finish\n"););
586 }
587
588
589 int
590 exintr(arg)
591 void *arg;
592 {
593 struct ex_softc *sc = arg;
594 struct ifnet *ifp = &sc->arpcom.ac_if;
595 int int_status, send_pkts;
596 int handled;
597
598 DODEBUG(Start_End, printf("exintr: start\n"););
599
600 #ifdef EXDEBUG
601 if (++exintr_count != 1)
602 printf("WARNING: nested interrupt (%d). Mail the author.\n",
603 exintr_count);
604 #endif
605
606 send_pkts = 0;
607 while ((int_status = ISA_GET(STATUS_REG)) & (Tx_Int | Rx_Int)) {
608 if (int_status & Rx_Int) {
609 ISA_PUT(STATUS_REG, Rx_Int);
610 handled = 1;
611 ex_rx_intr(sc);
612 } else if (int_status & Tx_Int) {
613 ISA_PUT(STATUS_REG, Tx_Int);
614 handled = 1;
615 ex_tx_intr(sc);
616 send_pkts = 1;
617 } else
618 handled = 0;
619 }
620
621
622
623
624
625
626 if (send_pkts && IFQ_IS_EMPTY(&ifp->if_snd) == 0)
627 ex_start(ifp);
628 #ifdef EXDEBUG
629 exintr_count--;
630 #endif
631 DODEBUG(Start_End, printf("exintr: finish\n"););
632
633 return handled;
634 }
635
636
637 void
638 ex_tx_intr(sc)
639 struct ex_softc *sc;
640 {
641 register struct ifnet *ifp = &sc->arpcom.ac_if;
642 int tx_status;
643
644 DODEBUG(Start_End, printf("ex_tx_intr: start\n"););
645
646
647
648
649
650
651 ifp->if_timer = 0;
652 while (sc->tx_head != sc->tx_tail) {
653 ISA_PUT_2(HOST_ADDR_REG, sc->tx_head);
654 if (! ISA_GET_2(IO_PORT_REG) & Done_bit)
655 break;
656 tx_status = ISA_GET_2(IO_PORT_REG);
657 sc->tx_head = ISA_GET_2(IO_PORT_REG);
658 if (tx_status & TX_OK_bit)
659 ifp->if_opackets++;
660 else
661 ifp->if_oerrors++;
662 ifp->if_collisions += tx_status & No_Collisions_bits;
663 }
664
665
666 ifp->if_flags &= ~IFF_OACTIVE;
667 DODEBUG(Status, printf("OIDLE tx_intr\n"););
668
669 DODEBUG(Start_End, printf("ex_tx_intr: finish\n"););
670 }
671
672
673 void
674 ex_rx_intr(sc)
675 struct ex_softc *sc;
676 {
677 register struct ifnet *ifp = &sc->arpcom.ac_if;
678 int rx_status, pkt_len, QQQ;
679 register struct mbuf *m, *ipkt;
680
681 DODEBUG(Start_End, printf("ex_rx_intr: start\n"););
682
683
684
685
686
687
688
689 ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
690 while (ISA_GET_2(IO_PORT_REG) == RCV_Done) {
691 rx_status = ISA_GET_2(IO_PORT_REG);
692 sc->rx_head = ISA_GET_2(IO_PORT_REG);
693 QQQ = pkt_len = ISA_GET_2(IO_PORT_REG);
694 if (rx_status & RCV_OK_bit) {
695 MGETHDR(m, M_DONTWAIT, MT_DATA);
696 ipkt = m;
697 if (ipkt == NULL)
698 ifp->if_iqdrops++;
699 else {
700 ipkt->m_pkthdr.rcvif = ifp;
701 ipkt->m_pkthdr.len = pkt_len;
702 ipkt->m_len = MHLEN;
703 while (pkt_len > 0) {
704 if (pkt_len > MINCLSIZE) {
705 MCLGET(m, M_DONTWAIT);
706 if (m->m_flags & M_EXT)
707 m->m_len = MCLBYTES;
708 else {
709 m_freem(ipkt);
710 ifp->if_iqdrops++;
711 goto rx_another;
712 }
713 }
714 m->m_len = min(m->m_len, pkt_len);
715
716
717
718
719
720
721 ISA_GET_2_MULTI(IO_PORT_REG,
722 mtod(m, caddr_t), m->m_len / 2);
723 if (m->m_len & 1)
724 *(mtod(m, caddr_t) +
725 m->m_len - 1) =
726 ISA_GET(IO_PORT_REG);
727 pkt_len -= m->m_len;
728 if (pkt_len > 0) {
729 MGET(m->m_next, M_DONTWAIT,
730 MT_DATA);
731 if (m->m_next == NULL) {
732 m_freem(ipkt);
733 ifp->if_iqdrops++;
734 goto rx_another;
735 }
736 m = m->m_next;
737 m->m_len = MLEN;
738 }
739 }
740 #ifdef EXDEBUG
741 if (debug_mask & Rcvd_Pkts) {
742 if ((eh->ether_dhost[5] != 0xff) ||
743 (eh->ether_dhost[0] != 0xff)) {
744 printf("Receive packet with %d data bytes: %6D -> ", QQQ, eh->ether_shost, ":");
745 printf("%6D\n", eh->ether_dhost, ":");
746 }
747 }
748 #endif
749 #if NBPFILTER > 0
750 if (ifp->if_bpf != NULL)
751 bpf_mtap(ifp->if_bpf, ipkt,
752 BPF_DIRECTION_IN);
753 #endif
754 ether_input_mbuf(ifp, ipkt);
755 ifp->if_ipackets++;
756 }
757 } else
758 ifp->if_ierrors++;
759 ISA_PUT_2(HOST_ADDR_REG, sc->rx_head);
760 rx_another: ;
761 }
762 if (sc->rx_head < sc->rx_lower_limit + 2)
763 ISA_PUT_2(RCV_STOP_REG, sc->rx_upper_limit);
764 else
765 ISA_PUT_2(RCV_STOP_REG, sc->rx_head - 2);
766
767 DODEBUG(Start_End, printf("ex_rx_intr: finish\n"););
768 }
769
770
771 int
772 ex_ioctl(ifp, cmd, data)
773 register struct ifnet *ifp;
774 u_long cmd;
775 caddr_t data;
776 {
777 register struct ifaddr *ifa = (struct ifaddr *) data;
778 struct ex_softc *sc = ifp->if_softc;
779 struct ifreq *ifr = (struct ifreq *) data;
780 int s, error = 0;
781
782 DODEBUG(Start_End, printf("ex_ioctl: start "););
783
784 s = splnet();
785
786 switch(cmd) {
787 case SIOCSIFADDR:
788 DODEBUG(Start_End, printf("SIOCSIFADDR"););
789 ifp->if_flags |= IFF_UP;
790
791 switch(ifa->ifa_addr->sa_family) {
792 #ifdef INET
793 case AF_INET:
794 ex_init(sc);
795 arp_ifinit((struct arpcom *) ifp, ifa);
796 break;
797 #endif
798 default:
799 ex_init(sc);
800 break;
801 }
802 break;
803 case SIOCGIFADDR:
804 {
805 struct sockaddr *sa;
806
807 DODEBUG(Start_End, printf("SIOCGIFADDR"););
808 sa = (struct sockaddr *) &ifr->ifr_data;
809 bcopy((caddr_t) sc->arpcom.ac_enaddr, (caddr_t) sa->sa_data,
810 ETHER_ADDR_LEN);
811 }
812 break;
813 case SIOCSIFFLAGS:
814 DODEBUG(Start_End, printf("SIOCSIFFLAGS"););
815 if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) {
816 ifp->if_flags &= ~IFF_RUNNING;
817 ex_stop(sc);
818 }
819 else
820 ex_init(sc);
821 break;
822 #ifdef NODEF
823 case SIOCGHWADDR:
824 DODEBUG(Start_End, printf("SIOCGHWADDR"););
825 bcopy((caddr_t) sc->sc_addr, (caddr_t) &ifr->ifr_data, sizeof(sc->sc_addr));
826 break;
827 #endif
828 case SIOCSIFMTU:
829 DODEBUG(Start_End, printf("SIOCSIFMTU"););
830 if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
831 error = EINVAL;
832 } else if (ifp->if_mtu != ifr->ifr_mtu) {
833 ifp->if_mtu = ifr->ifr_mtu;
834 }
835 break;
836 case SIOCADDMULTI:
837 DODEBUG(Start_End, printf("SIOCADDMULTI"););
838 case SIOCDELMULTI:
839 DODEBUG(Start_End, printf("SIOCDELMULTI"););
840
841 error = EINVAL;
842 break;
843 default:
844 DODEBUG(Start_End, printf("unknown"););
845 error = EINVAL;
846 }
847
848 splx(s);
849
850 DODEBUG(Start_End, printf("\nex_ioctl: finish\n"););
851 return(error);
852 }
853
854
855 void
856 ex_reset(sc)
857 struct ex_softc *sc;
858 {
859 int s;
860
861 DODEBUG(Start_End, printf("ex_reset: start\n"););
862
863 s = splnet();
864 ex_stop(sc);
865 ex_init(sc);
866 splx(s);
867
868 DODEBUG(Start_End, printf("ex_reset: finish\n"););
869 }
870
871
872 void
873 ex_watchdog(ifp)
874 struct ifnet *ifp;
875 {
876 struct ex_softc *sc = ifp->if_softc;
877
878 DODEBUG(Start_End, printf("ex_watchdog: start\n"););
879
880 ifp->if_flags &= ~IFF_OACTIVE;
881 DODEBUG(Status, printf("OIDLE watchdog\n"););
882 ifp->if_oerrors++;
883 ex_reset(sc);
884 ex_start(ifp);
885
886 DODEBUG(Start_End, printf("ex_watchdog: finish\n"););
887 }
888
889
890 static u_short
891 eeprom_read(sc, location)
892 struct ex_softc *sc;
893 int location;
894 {
895 int i;
896 u_short data = 0;
897 int read_cmd = location | EE_READ_CMD;
898 short ctrl_val = EECS;
899
900 BANK_SEL(Bank2_Sel);
901 ISA_PUT(EEPROM_REG, EECS);
902 for (i = 8; i >= 0; i--) {
903 short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI :
904 ctrl_val;
905 ISA_PUT(EEPROM_REG, outval);
906 ISA_PUT(EEPROM_REG, outval | EESK);
907 delay(3);
908 ISA_PUT(EEPROM_REG, outval);
909 delay(2);
910 }
911 ISA_PUT(EEPROM_REG, ctrl_val);
912 for (i = 16; i > 0; i--) {
913 ISA_PUT(EEPROM_REG, ctrl_val | EESK);
914 delay(3);
915 data = (data << 1) | ((ISA_GET(EEPROM_REG) & EEDO) ? 1 : 0);
916 ISA_PUT(EEPROM_REG, ctrl_val);
917 delay(2);
918 }
919 ctrl_val &= ~EECS;
920 ISA_PUT(EEPROM_REG, ctrl_val | EESK);
921 delay(3);
922 ISA_PUT(EEPROM_REG, ctrl_val);
923 delay(2);
924 BANK_SEL(Bank0_Sel);
925 return(data);
926 }
927
928 #endif