if_es.c revision 1.2 1 /* $NetBSD: if_es.c,v 1.2 1995/04/02 20:38:45 chopps Exp $ */
2
3 /*
4 * Copyright (c) 1995 Michael L. Hitch
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Michael L. Hitch.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * SMC 91C90 Single-Chip Ethernet Controller
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40 #include <sys/buf.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/syslog.h>
44 #include <sys/ioctl.h>
45 #include <sys/errno.h>
46 #include <sys/device.h>
47
48 #include <net/if.h>
49 #include <net/netisr.h>
50 #include <net/route.h>
51
52 #ifdef INET
53 #include <netinet/in.h>
54 #include <netinet/in_systm.h>
55 #include <netinet/in_var.h>
56 #include <netinet/ip.h>
57 #include <netinet/if_ether.h>
58 #endif
59
60 #ifdef NS
61 #include <netns/ns.h>
62 #include <netns/ns_if.h>
63 #endif
64
65 #include <machine/cpu.h>
66 #include <machine/mtpr.h>
67 #include <amiga/amiga/device.h>
68 #include <amiga/amiga/isr.h>
69 #include <amiga/dev/zbusvar.h>
70 #include <amiga/dev/if_esreg.h>
71
72 #define SWAP(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff))
73
74 #define ESDEBUG
75 #define USEPKTBUF
76
77 #define ETHER_MIN_LEN 64
78 #define ETHER_MAX_LEN 1518
79 #define ETHER_ADDR_LEN 6
80
81 /*
82 * Ethernet software status per interface.
83 *
84 * Each interface is referenced by a network interface structure,
85 * es_if, which the routing code uses to locate the interface.
86 * This structure contains the output queue for the interface, its address, ...
87 */
88 struct es_softc {
89 struct device sc_dev;
90 struct isr sc_isr;
91 struct arpcom sc_ac; /* common Ethernet structures */
92 #define sc_if sc_ac.ac_if /* network-visible interface */
93 #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
94 void *sc_base; /* base address of board */
95 short sc_iflags;
96 #if NBPFILTER > 0
97 caddr_t sc_bpf;
98 #endif
99 unsigned short sc_intctl;
100 #ifdef ESDEBUG
101 int sc_debug;
102 #endif
103 };
104
105 #if NBPFILTER > 0
106 #include <net/bpf.h>
107 #include <net/bpfdesc.h>
108 #endif
109
110 #ifdef ESDEBUG
111 /* console error messages */
112 int esdebug = 0;
113 #endif
114
115 int esintr __P((struct es_softc *));
116 int esstart __P((struct ifnet *));
117 int eswatchdog __P((int));
118 int esioctl __P((struct ifnet *, u_long, caddr_t));
119 void esrint __P((struct es_softc *));
120 void estint __P((struct es_softc *));
121 void esinit __P((struct es_softc *));
122 void esreset __P((struct es_softc *));
123
124 extern struct ifnet loif;
125
126 void esattach __P((struct device *, struct device *, void *));
127 int esmatch __P((struct device *, struct cfdata *, void *args));
128
129 struct cfdriver escd = {
130 NULL, "es", (cfmatch_t)esmatch, esattach, DV_IFNET,
131 sizeof(struct es_softc), NULL, 0};
132
133 int
134 esmatch(pdp, cfp, auxp)
135 struct device *pdp;
136 struct cfdata *cfp;
137 void *auxp;
138 {
139
140 struct zbus_args *zap;
141
142 zap = (struct zbus_args *)auxp;
143
144 /* Ameristar A4066 ethernet card */
145 if ( zap->manid == 1053 && zap->prodid == 10)
146 return(1);
147
148 return (0);
149 }
150
151 /*
152 * Interface exists: make available by filling in network interface
153 * record. System will initialize the interface when it is ready
154 * to accept packets.
155 */
156 void
157 esattach(pdp, dp, auxp)
158 struct device *pdp, *dp;
159 void *auxp;
160 {
161 struct zbus_args *zap;
162 struct es_softc *sc = (struct es_softc *) dp;
163 struct ifnet *ifp = &sc->sc_if;
164 char *cp;
165 int i;
166 unsigned long ser;
167
168 zap =(struct zbus_args *)auxp;
169
170 /*
171 * Make config msgs look nicer.
172 */
173 /* printf("\n");*/
174
175 sc->sc_base = zap->va;
176
177 /*
178 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID.
179 * (Currently only Ameristar.)
180 */
181 sc->sc_addr[0] = 0x00;
182 sc->sc_addr[1] = 0x00;
183 sc->sc_addr[2] = 0x9f;
184
185 /*
186 * Serial number for board contains last 3 bytes.
187 */
188 ser = (unsigned long) zap->serno;
189
190 sc->sc_addr[3] = (ser >> 16) & 0xff;
191 sc->sc_addr[4] = (ser >> 8) & 0xff;
192 sc->sc_addr[5] = (ser ) & 0xff;
193
194 #if 0
195 printf("es%d: hardware address %s\n",
196 dp->dv_unit, ether_sprintf(sc->sc_addr));
197 #else
198 printf(": address %s\n", ether_sprintf(sc->sc_addr));
199 #endif
200
201 ifp->if_unit = dp->dv_unit;
202 ifp->if_name = escd.cd_name;
203 ifp->if_mtu = ETHERMTU;
204 ifp->if_output = ether_output;
205 ifp->if_ioctl = esioctl;
206 ifp->if_start = esstart;
207 ifp->if_watchdog = eswatchdog;
208 /* XXX IFF_MULTICAST */
209 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
210
211 if_attach(ifp);
212 ether_ifattach(ifp);
213 #if NBPFILTER > 0
214 bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
215 #endif
216
217 sc->sc_isr.isr_intr = esintr;
218 sc->sc_isr.isr_arg = sc;
219 sc->sc_isr.isr_ipl = 2;
220 add_isr (&sc->sc_isr);
221 return;
222 }
223
224 void
225 esinit(sc)
226 struct es_softc *sc;
227 {
228 struct ifnet *ifp = &sc->sc_ac.ac_if;
229 union smcregs *smc = sc->sc_base;
230 int s;
231
232 if (!ifp->if_addrlist)
233 return;
234
235 s = splimp();
236
237 smc->b0.bsr = 0x0000; /* Select bank 0 */
238 smc->b0.rcr = RCR_EPH_RST;
239 smc->b0.rcr = 0;
240 smc->b3.bsr = 0x0300; /* Select bank 3 */
241 smc->b3.mt[0] = 0; /* clear Multicast table */
242 smc->b3.mt[1] = 0;
243 smc->b3.mt[2] = 0;
244 smc->b3.mt[3] = 0;
245 /* XXX set Multicast table from Multicast list */
246 smc->b1.bsr = 0x0100; /* Select bank 1 */
247 smc->b1.cr = CR_RAM32K | CR_NO_WAIT_ST | CR_SET_SQLCH;
248 smc->b1.ctr = CTR_AUTO_RLSE;
249 smc->b1.iar[0] = *((unsigned short *) &sc->sc_addr[0]);
250 smc->b1.iar[1] = *((unsigned short *) &sc->sc_addr[2]);
251 smc->b1.iar[2] = *((unsigned short *) &sc->sc_addr[4]);
252 smc->b2.bsr = 0x0200; /* Select bank 2 */
253 smc->b2.mmucr = MMUCR_RESET;
254 smc->b0.bsr = 0x0000; /* Select bank 0 */
255 smc->b0.mcr = SWAP (0x0020); /* reserve 8K for transmit buffers */
256 smc->b0.tcr = TCR_PAD_EN | TCR_TXENA + TCR_MON_CSN;
257 smc->b0.rcr = RCR_FILT_CAR | RCR_STRIP_CRC | RCR_RXEN;
258 /* XXX add multicast/promiscuous flags */
259 smc->b2.bsr = 0x0200; /* Select bank 2 */
260 smc->b2.msk = sc->sc_intctl = MSK_RX_OVRN | MSK_RX;
261
262 /* Interface is now 'running', with no output active. */
263 ifp->if_flags |= IFF_RUNNING;
264 ifp->if_flags &= ~IFF_OACTIVE;
265
266 /* Attempt to start output, if any. */
267 esstart(ifp);
268
269 splx(s);
270 }
271
272 int
273 esintr(sc)
274 struct es_softc *sc;
275 {
276 int i;
277 u_short intsts, intact;
278 int done = 0;
279 union smcregs *smc;
280
281 smc = sc->sc_base;
282 intsts = smc->b2.ist;
283 intact = smc->b2.msk & intsts;
284 if ((intact) == 0)
285 return (0);
286 #ifdef ESDEBUG
287 if (esdebug)
288 printf ("%s: esintr ist %02x msk %02x",
289 sc->sc_dev.dv_xname, intsts, smc->b2.msk);
290 #endif
291 smc->b2.msk = 0;
292 #ifdef ESDEBUG
293 if (esdebug)
294 printf ("=>%02x%02x pnr %02x arr %02x fifo %04x\n",
295 smc->b2.ist, smc->b2.ist, smc->b2.pnr, smc->b2.arr,
296 smc->b2.fifo);
297 #endif
298 if (intact & IST_ALLOC) {
299 sc->sc_intctl &= ~MSK_ALLOC;
300 #ifdef ESDEBUG
301 if (esdebug || 1)
302 printf ("%s: ist %02x\n", sc->sc_dev.dv_xname,
303 intsts);
304 #endif
305 if ((smc->b2.arr & ARR_FAILED) == 0) {
306 #ifdef ESDEBUG
307 if (esdebug || 1)
308 printf ("%s: arr %02x\n", sc->sc_dev.dv_xname,
309 smc->b2.arr);
310 #endif
311 smc->b2.pnr = smc->b2.arr;
312 smc->b2.mmucr = MMUCR_RLSPKT;
313 while (smc->b2.mmucr & MMUCR_BUSY)
314 ;
315 sc->sc_ac.ac_if.if_flags &= ~IFF_OACTIVE;
316 }
317 }
318 while ((smc->b2.fifo & FIFO_REMPTY) == 0) {
319 esrint(sc);
320 }
321 if (intact & IST_RX_OVRN) {
322 printf ("%s: Overrun ist %02x", sc->sc_dev.dv_xname,
323 intsts);
324 smc->b2.ist = ACK_RX_OVRN;
325 printf ("->%02x\n", smc->b2.ist);
326 sc->sc_if.if_ierrors++;
327 }
328 if (intact & IST_TX) {
329 #ifdef ESDEBUG
330 if (esdebug)
331 printf ("%s: TX INT ist %02x",
332 sc->sc_dev.dv_xname, intsts);
333 #endif
334 smc->b2.ist = ACK_TX;
335 #ifdef ESDEBUG
336 if (esdebug)
337 printf ("->%02x\n", smc->b2.ist);
338 #endif
339 smc->b0.bsr = 0x0000;
340 if ((smc->b0.tcr & TCR_TXENA) == 0) {
341 printf ("%s: IST %02x masked %02x EPH status %04x tcr %04x\n",
342 sc->sc_dev.dv_xname, intsts, intact, smc->b0.ephsr,
343 smc->b0.tcr);
344 if ((smc->b0.ephsr & EPHSR_TX_SUC) == 0) {
345 smc->b0.tcr |= TCR_TXENA;
346 sc->sc_if.if_oerrors++;
347 }
348 }
349 /*
350 * else - got a TX interrupt, but TCR_TXENA is still set??
351 */
352 #if 0
353 else if ((intact & IST_TX_EMPTY) == 0) {
354 printf("%s: unexpected TX interrupt %02x %02x",
355 sc->sc_dev.dv_xname, intsts, intact);
356 smc->b2.bsr = 0x0200;
357 printf (" %02x\n", smc->b2.ist);
358 }
359 #endif
360 smc->b2.bsr = 0x0200;
361 }
362 if (intact & IST_TX_EMPTY) {
363 u_short ecr;
364 #ifdef ESDEBUG
365 if (esdebug)
366 printf ("%s: TX EMPTY %02x",
367 sc->sc_dev.dv_xname, intsts);
368 #endif
369 smc->b2.ist = ACK_TX_EMPTY;
370 #ifdef ESDEBUG
371 if (esdebug)
372 printf ("->%02x intcl %x pnr %02x arr %02x\n",
373 smc->b2.ist, sc->sc_intctl, smc->b2.pnr,
374 smc->b2.arr);
375 #endif
376 sc->sc_intctl &= ~(MSK_TX_EMPTY | MSK_TX);
377 smc->b0.bsr = 0x0000;
378 ecr = smc->b0.ecr; /* Get error counters */
379 if (ecr & 0xff00)
380 sc->sc_if.if_collisions += ((ecr >> 8) & 15) +
381 ((ecr >> 11) & 0x1e);
382 smc->b2.bsr = 0x0200;
383 }
384 /* output packets */
385 estint(sc);
386 smc->b2.msk = sc->sc_intctl;
387 return (1);
388 }
389
390 void
391 esrint (sc)
392 struct es_softc *sc;
393 {
394 union smcregs *smc = sc->sc_base;
395 int i;
396 u_short len;
397 short cnt;
398 u_short pktctlw, pktlen, *buf;
399 u_long *lbuf;
400 volatile u_short *data;
401 volatile u_long *ldata;
402 struct ifnet *ifp;
403 struct mbuf *top, **mp, *m;
404 struct ether_header *eh;
405 #ifdef USEPKTBUF
406 u_char *b, pktbuf[1530];
407 #endif
408
409 #ifdef ESDEBUG
410 if (esdebug)
411 printf ("%s: esrint fifo %04x", sc->sc_dev.dv_xname,
412 smc->b2.fifo);
413 #endif
414 data = (u_short *)&smc->b2.data;
415 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR | PTR_READ | SWAP (0x0002);
416 (void) smc->b2.mmucr;
417 #ifdef ESDEBUG
418 if (esdebug)
419 printf ("->%04x", smc->b2.fifo);
420 #endif
421 len = *data;
422 len = SWAP (len); /* Careful of macro side-effects */
423 #ifdef ESDEBUG
424 if (esdebug)
425 printf (" length %d", len);
426 #endif
427 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR + PTR_READ | SWAP (0x0000);
428 (void) smc->b2.mmucr;
429 pktctlw = *data;
430 pktlen = *data;
431 pktctlw = SWAP (pktctlw);
432 pktlen = SWAP (pktlen) - 6;
433 if (pktctlw & RFSW_ODDFRM)
434 pktlen++;
435 /* XXX copy directly from controller to mbuf */
436 #ifdef USEPKTBUF
437 #if 1
438 lbuf = (u_long *) pktbuf;
439 ldata = (u_long *)data;
440 cnt = (len - 4) / 4;
441 while (cnt--)
442 *lbuf++ = *ldata;
443 if ((len - 4) & 2) {
444 buf = (u_short *) lbuf;
445 *buf = *data;
446 }
447 #else
448 buf = (u_short *)pktbuf;
449 cnt = (len - 4) / 2;
450 while (cnt--)
451 *buf++ = *data;
452 #endif
453 smc->b2.mmucr = MMUCR_REMRLS_RX;
454 while (smc->b2.mmucr & MMUCR_BUSY)
455 ;
456 #ifdef ESDEBUG
457 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) {
458 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw);
459 /* count input error? */
460 }
461 if (esdebug) {
462 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen,
463 smc->b2.fifo);
464 for (i = 0; i < pktlen; ++i)
465 printf ("%02x%s", pktbuf[i], ((i & 31) == 31) ? "\n" :
466 "");
467 if (i & 31)
468 printf ("\n");
469 }
470 #endif
471 #else /* USEPKTBUF */
472 #ifdef ESDEBUG
473 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) {
474 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw);
475 /* count input error? */
476 }
477 if (esdebug) {
478 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen,
479 smc->b2.fifo);
480 }
481 #endif
482 #endif /* USEPKTBUF */
483 ifp = &sc->sc_ac.ac_if;
484 ifp->if_ipackets++;
485 MGETHDR(m, M_DONTWAIT, MT_DATA);
486 if (m == NULL)
487 return;
488 m->m_pkthdr.rcvif = ifp;
489 m->m_pkthdr.len = pktlen;
490 len = MHLEN;
491 top = NULL;
492 mp = ⊤
493 #ifdef USEPKTBUF
494 b = pktbuf;
495 #endif
496 while (pktlen > 0) {
497 if (top) {
498 MGET(m, M_DONTWAIT, MT_DATA);
499 if (m == 0) {
500 m_freem(top);
501 return;
502 }
503 len = MLEN;
504 }
505 if (pktlen >= MINCLSIZE) {
506 MCLGET(m, M_DONTWAIT);
507 if (m->m_flags & M_EXT)
508 len = MCLBYTES;
509 }
510 m->m_len = len = min(pktlen, len);
511 #ifdef USEPKTBUF
512 bcopy((caddr_t)b, mtod(m, caddr_t), len);
513 b += len;
514 #else /* USEPKTBUF */
515 buf = mtod(m, u_short *);
516 cnt = len / 2;
517 while (cnt--)
518 *buf++ = *data;
519 if (len & 1)
520 *buf = *data; /* XXX should be byte store */
521 #ifdef ESDEBUG
522 if (esdebug) {
523 buf = mtod(m, u_short *);
524 for (i = 0; i < len; ++i)
525 printf ("%02x%s", ((u_char *)buf)[i],
526 ((i & 31) == 31) ? "\n" : "");
527 if (i & 31)
528 printf ("\n");
529 }
530 #endif
531 #endif /* USEPKTBUF */
532 pktlen -= len;
533 *mp = m;
534 mp = &m->m_next;
535 }
536 #ifndef USEPKTBUF
537 smc->b2.mmucr = MMUCR_REMRLS_RX;
538 while (smc->b2.mmucr & MMUCR_BUSY)
539 ;
540 #endif
541 eh = mtod(top, struct ether_header *);
542 top->m_pkthdr.len -= sizeof (*eh);
543 top->m_len -= sizeof (*eh);
544 top->m_data += sizeof (*eh);
545
546 ether_input(ifp, eh, top);
547 }
548
549 void
550 estint (sc)
551 struct es_softc *sc;
552 {
553 esstart (&sc->sc_ac.ac_if);
554 }
555
556 int
557 esstart(ifp)
558 struct ifnet *ifp;
559 {
560 struct es_softc *sc = escd.cd_devs[ifp->if_unit];
561 union smcregs *smc = sc->sc_base;
562 struct mbuf *m0, *m;
563 #ifdef USEPKTBUF
564 u_short pktbuf[ETHER_MAX_LEN + 2];
565 #endif
566 u_short pktctlw, pktlen;
567 u_short *buf;
568 volatile u_short *data;
569 u_long *lbuf;
570 volatile u_long *ldata;
571 short cnt;
572 int i;
573
574 if ((sc->sc_ac.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
575 IFF_RUNNING)
576 return;
577
578 for (;;) {
579 /*
580 * Sneak a peek at the next packet to get the length
581 * and see if the SMC 91C90 can accept it.
582 */
583 m = sc->sc_ac.ac_if.if_snd.ifq_head;
584 if (!m)
585 break;
586 #ifdef ESDEBUG
587 if (esdebug && (m->m_next || m->m_len & 1))
588 printf("%s: esstart m_next %x m_len %d\n", sc->sc_dev.dv_xname,
589 m->m_next, m->m_len);
590 #endif
591 for (m0 = m, pktlen = 0; m0; m0 = m0->m_next)
592 pktlen += m0->m_len;
593 #ifdef ESDEBUG
594 if (esdebug)
595 printf("%s: esstart r1 %x len %d", sc->sc_dev.dv_xname, smc->b2.pnr, pktlen);
596 #endif
597 pktctlw = 0;
598 pktlen += 4;
599 if (pktlen & 1)
600 ++pktlen; /* control byte after last byte */
601 else
602 pktlen += 2; /* control byte after pad byte */
603 smc->b2.mmucr = MMUCR_ALLOC | (pktlen & 0x0700);
604 for (i = 0; i <= 5; ++i)
605 if ((smc->b2.arr & ARR_FAILED) == 0)
606 break;
607 if (smc->b2.arr & ARR_FAILED) {
608 sc->sc_ac.ac_if.if_flags |= IFF_OACTIVE;
609 #ifdef ESDEBUG
610 if (esdebug)
611 printf("-no xmit bufs r1 %x\n", smc->b2.pnr);
612 #endif
613 sc->sc_intctl |= MSK_ALLOC;
614 break;
615 }
616 smc->b2.pnr = smc->b2.arr;
617
618 IF_DEQUEUE(&sc->sc_ac.ac_if.if_snd, m);
619 smc->b2.ptr = PTR_AUTOINCR;
620 (void) smc->b2.mmucr;
621 data = (u_short *)&smc->b2.data;
622 *data = SWAP (pktctlw);
623 *data = SWAP (pktlen);
624 #ifdef USEPKTBUF
625 i = 0;
626 for (m0 = m; m; m = m->m_next) {
627 bcopy(mtod(m, caddr_t), (char *)pktbuf + i, m->m_len);
628 i += m->m_len;
629 }
630
631 if (i & 1) /* Figure out where to put control byte */
632 pktbuf[i/2] = (pktbuf[i/2] & 0xff00) | CTLB_ODD;
633 else
634 pktbuf[i/2] = 0;
635 #ifdef ESDEBUG
636 if (esdebug) {
637 int j;
638 printf("-sending len %d pktlen %d r1 %04x\n", i, pktlen, smc->b2.pnr);
639 for (j = 0; j < pktlen - 4; ++j)
640 printf("%02x%s", ((u_char *)pktbuf)[j], ((j & 31) == 31) ? "\n" : "");
641 if (j & 31)
642 printf("\n");
643 }
644 #endif
645 #if 0 /* doesn't quite work? */
646 lbuf = (u_long *)(pktbuf);
647 ldata = (u_long *)data;
648 cnt = pktlen / 4;
649 while(cnt--)
650 *ldata = *lbuf++;
651 if (pktlen & 2) {
652 buf = (u_short *)lbuf;
653 *data = *buf;
654 }
655 #else
656 buf = pktbuf;
657 cnt = pktlen / 2;
658 while (cnt--)
659 *data = *buf++;
660 #endif
661 #else /* USEPKTBUF */
662 #ifdef ESDEBUG
663 if (esdebug)
664 printf("-sending pktlen %d r1 %04x\n", pktlen, smc->b2.pnr);
665 #endif
666 pktctlw = 0;
667 for (m0 = m; m; m = m->m_next) {
668 buf = mtod(m, u_short *);
669 #ifdef ESDEBUG
670 if (esdebug) {
671 printf(" m->m_len %d\n", m->m_len);
672 for (i = 0; i < m->m_len; ++i)
673 printf("%02x%s", ((u_char *)buf)[i], ((i & 31) == 31) ? "\n" : "");
674 if (i & 31)
675 printf("\n");
676 }
677 #endif
678 cnt = m->m_len / 2;
679 while (cnt--)
680 *data = *buf++;
681 if (m->m_len & 1)
682 pktctlw = (*buf & 0xff00) | CTLB_ODD;
683 }
684 *data = pktctlw;
685 #endif /* USEPKTBUF */
686 smc->b2.mmucr = MMUCR_ENQ_TX;
687 #ifdef ESDEBUG
688 if (esdebug)
689 printf("%s: esstart packet sent r1 %x\n", sc->sc_dev.dv_xname, smc->b2.pnr);
690 #endif
691 #if NBPFILTER > 0
692 if (sc->sc_ac.ac_if.if_bpf)
693 bpf_mtap(sc->sc_ac.ac_if.if_bpf, m0);
694 #endif
695 m_freem(m0);
696 sc->sc_ac.ac_if.if_opackets++; /* move to interrupt? */
697 sc->sc_intctl |= MSK_TX_EMPTY | MSK_TX;
698 }
699 smc->b2.msk = sc->sc_intctl;
700 return 0;
701 }
702
703 int
704 esioctl(ifp, cmd, data)
705 struct ifnet *ifp;
706 u_long cmd;
707 caddr_t data;
708 {
709 struct es_softc *sc = escd.cd_devs[ifp->if_unit];
710 struct ifaddr *ifa = (struct ifaddr *)data;
711 struct ifreq *ifr = (struct ifreq *)data;
712 int s, error = 0;
713
714 #ifdef ESDEBUG
715 if (esdebug)
716 printf ("esioctl called: cmd %x\n", cmd);
717 #endif
718
719 s = splimp();
720
721 switch (cmd) {
722 case SIOCSIFADDR:
723 ifp->if_flags |= IFF_UP;
724
725 switch (ifa->ifa_addr->sa_family) {
726 #ifdef INET
727 case AF_INET:
728 esinit(sc);
729 sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
730 arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
731 break;
732 #endif
733 #ifdef NS
734 case AF_NS:
735 {
736 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
737
738 if (ns_nullhost(*ina))
739 ina->x_host =
740 *(uniion ns_host *)(sc->sc_addr);
741 else
742 bcopy(ina->x_host.c_host,
743 sc->sc_addr, sizeof(sc->sc_addr));
744 /* Set new address */
745 esinit(sc);
746 break;
747 #endif
748 default:
749 esinit(sc);
750 break;
751 }
752 break;
753 case SIOCSIFFLAGS:
754 /*
755 * If interface is marked down and it is running, then stop it
756 */
757 if ((ifp->if_flags & IFF_UP) == 0 &&
758 (ifp->if_flags & IFF_RUNNING) != 0) {
759 /*
760 * If interface is marked down and it is running, then
761 * stop it.
762 */
763 /* esstop(sc); */
764 ifp->if_flags &= ~IFF_RUNNING;
765 } else if ((ifp->if_flags & IFF_UP) != 0 &&
766 (ifp->if_flags & IFF_RUNNING) == 0) {
767 /*
768 * If interface is marked up and it is stopped, then
769 * start it.
770 */
771 esinit(sc);
772 } else {
773 /*
774 * Reset the interface to pick up changes in any other
775 * flags that affect hardware registers.
776 */
777 /* esstop(sc); */
778 esinit(sc);
779 }
780 #ifdef ESDEBUG
781 if (ifp->if_flags & IFF_DEBUG)
782 esdebug = sc->sc_debug = 1;
783 else
784 esdebug = sc->sc_debug = 0;
785 #endif
786 break;
787 case SIOCADDMULTI:
788 case SIOCDELMULTI:
789
790 default:
791 error = EINVAL;
792 }
793
794 splx(s);
795 return (error);
796 }
797
798 void
799 esreset(sc)
800 struct es_softc *sc;
801 {
802 int s;
803
804 s = splimp();
805 /* esstop(sc); */
806 esinit(sc);
807 splx(s);
808 }
809
810 int
811 eswatchdog(unit)
812 int unit;
813 {
814 register struct es_softc *sc = escd.cd_devs[unit];
815
816 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
817 esreset(sc);
818 return (0);
819 }
820