if_es.c revision 1.1 1 /* $NetBSD: if_es.c,v 1.1 1995/02/13 00:27:08 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 int done = 0;
278 union smcregs *smc;
279
280 smc = sc->sc_base;
281 if ((smc->b2.msk & smc->b2.ist) == 0)
282 return (0);
283 #ifdef ESDEBUG
284 if (esdebug)
285 printf ("%s: esintr ist %02x msk %02x",
286 sc->sc_dev.dv_xname, smc->b2.ist, smc->b2.msk);
287 #endif
288 smc->b2.msk = 0;
289 #ifdef ESDEBUG
290 if (esdebug)
291 printf ("=>%02x%02x pnr %02x arr %02x fifo %04x\n",
292 smc->b2.ist, smc->b2.ist, smc->b2.pnr, smc->b2.arr,
293 smc->b2.fifo);
294 #endif
295 if (smc->b2.ist & IST_ALLOC && sc->sc_intctl & MSK_ALLOC) {
296 sc->sc_intctl &= ~MSK_ALLOC;
297 #ifdef ESDEBUG
298 if (esdebug || 1)
299 printf ("%s: ist %02x\n", sc->sc_dev.dv_xname,
300 smc->b2.ist);
301 #endif
302 if ((smc->b2.arr & ARR_FAILED) == 0) {
303 #ifdef ESDEBUG
304 if (esdebug || 1)
305 printf ("%s: arr %02x\n", sc->sc_dev.dv_xname,
306 smc->b2.arr);
307 #endif
308 smc->b2.pnr = smc->b2.arr;
309 smc->b2.mmucr = MMUCR_RLSPKT;
310 while (smc->b2.mmucr & MMUCR_BUSY)
311 ;
312 sc->sc_ac.ac_if.if_flags &= ~IFF_OACTIVE;
313 }
314 }
315 while ((smc->b2.fifo & FIFO_REMPTY) == 0) {
316 esrint(sc);
317 }
318 if (smc->b2.ist & IST_RX_OVRN) {
319 printf ("%s: Overrun ist %02x", sc->sc_dev.dv_xname,
320 smc->b2.ist);
321 smc->b2.ist = ACK_RX_OVRN;
322 printf ("->%02x\n", smc->b2.ist);
323 sc->sc_if.if_ierrors++;
324 }
325 if (smc->b2.ist & IST_TX) {
326 #ifdef ESDEBUG
327 if (esdebug)
328 printf ("%s: TX INT ist %02x",
329 sc->sc_dev.dv_xname, smc->b2.ist);
330 #endif
331 smc->b2.ist = ACK_TX;
332 #ifdef ESDEBUG
333 if (esdebug)
334 printf ("->%02x\n", smc->b2.ist);
335 #endif
336 smc->b0.bsr = 0x0000;
337 printf ("%s: EPH status %04x\n", sc->sc_dev.dv_xname,
338 smc->b0.ephsr);
339 if ((smc->b0.ephsr & EPHSR_TX_SUC) == 0) {
340 smc->b0.tcr |= TCR_TXENA;
341 sc->sc_if.if_oerrors++;
342 }
343 smc->b2.bsr = 0x0200;
344 }
345 if (smc->b2.ist & IST_TX_EMPTY) {
346 u_short ecr;
347 #ifdef ESDEBUG
348 if (esdebug)
349 printf ("%s: TX EMPTY %02x",
350 sc->sc_dev.dv_xname, smc->b2.ist);
351 #endif
352 smc->b2.ist = ACK_TX_EMPTY;
353 #ifdef ESDEBUG
354 if (esdebug)
355 printf ("->%02x intcl %x pnr %02x arr %02x\n",
356 smc->b2.ist, sc->sc_intctl, smc->b2.pnr,
357 smc->b2.arr);
358 #endif
359 sc->sc_intctl &= ~(MSK_TX_EMPTY | MSK_TX);
360 smc->b0.bsr = 0x0000;
361 ecr = smc->b0.ecr; /* Get error counters */
362 if (ecr & 0xff00)
363 sc->sc_if.if_collisions += ((ecr >> 8) & 15) +
364 ((ecr >> 11) & 0x1e);
365 smc->b2.bsr = 0x0200;
366 }
367 /* output packets */
368 estint(sc);
369 smc->b2.msk = sc->sc_intctl;
370 return (1);
371 }
372
373 void
374 esrint (sc)
375 struct es_softc *sc;
376 {
377 union smcregs *smc = sc->sc_base;
378 int i;
379 u_short len;
380 short cnt;
381 u_short pktctlw, pktlen, *buf;
382 u_long *lbuf;
383 volatile u_short *data;
384 volatile u_long *ldata;
385 struct ifnet *ifp;
386 struct mbuf *top, **mp, *m;
387 struct ether_header *eh;
388 #ifdef USEPKTBUF
389 u_char *b, pktbuf[1530];
390 #endif
391
392 #ifdef ESDEBUG
393 if (esdebug)
394 printf ("%s: esrint fifo %04x", sc->sc_dev.dv_xname,
395 smc->b2.fifo);
396 #endif
397 data = (u_short *)&smc->b2.data;
398 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR | PTR_READ | SWAP (0x0002);
399 (void) smc->b2.mmucr;
400 #ifdef ESDEBUG
401 if (esdebug)
402 printf ("->%04x", smc->b2.fifo);
403 #endif
404 len = *data;
405 len = SWAP (len); /* Careful of macro side-effects */
406 #ifdef ESDEBUG
407 if (esdebug)
408 printf (" length %d", len);
409 #endif
410 smc->b2.ptr = PTR_RCV | PTR_AUTOINCR + PTR_READ | SWAP (0x0000);
411 (void) smc->b2.mmucr;
412 pktctlw = *data;
413 pktlen = *data;
414 pktctlw = SWAP (pktctlw);
415 pktlen = SWAP (pktlen) - 6;
416 if (pktctlw & RFSW_ODDFRM)
417 pktlen++;
418 /* XXX copy directly from controller to mbuf */
419 #ifdef USEPKTBUF
420 #if 1
421 lbuf = (u_long *) pktbuf;
422 ldata = (u_long *)data;
423 cnt = (len - 4) / 4;
424 while (cnt--)
425 *lbuf++ = *ldata;
426 if ((len - 4) & 2) {
427 buf = (u_short *) lbuf;
428 *buf = *data;
429 }
430 #else
431 buf = (u_short *)pktbuf;
432 cnt = (len - 4) / 2;
433 while (cnt--)
434 *buf++ = *data;
435 #endif
436 smc->b2.mmucr = MMUCR_REMRLS_RX;
437 while (smc->b2.mmucr & MMUCR_BUSY)
438 ;
439 #ifdef ESDEBUG
440 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) {
441 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw);
442 /* count input error? */
443 }
444 if (esdebug) {
445 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen,
446 smc->b2.fifo);
447 for (i = 0; i < pktlen; ++i)
448 printf ("%02x%s", pktbuf[i], ((i & 31) == 31) ? "\n" :
449 "");
450 if (i & 31)
451 printf ("\n");
452 }
453 #endif
454 #else /* USEPKTBUF */
455 #ifdef ESDEBUG
456 if (pktctlw & (RFSW_ALGNERR | RFSW_BADCRC | RFSW_TOOLNG | RFSW_TOOSHORT)) {
457 printf ("%s: Packet error %04x\n", sc->sc_dev.dv_xname, pktctlw);
458 /* count input error? */
459 }
460 if (esdebug) {
461 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw, pktlen,
462 smc->b2.fifo);
463 }
464 #endif
465 #endif /* USEPKTBUF */
466 ifp = &sc->sc_ac.ac_if;
467 ifp->if_ipackets++;
468 MGETHDR(m, M_DONTWAIT, MT_DATA);
469 if (m == NULL)
470 return;
471 m->m_pkthdr.rcvif = ifp;
472 m->m_pkthdr.len = pktlen;
473 len = MHLEN;
474 top = NULL;
475 mp = ⊤
476 #ifdef USEPKTBUF
477 b = pktbuf;
478 #endif
479 while (pktlen > 0) {
480 if (top) {
481 MGET(m, M_DONTWAIT, MT_DATA);
482 if (m == 0) {
483 m_freem(top);
484 return;
485 }
486 len = MLEN;
487 }
488 if (pktlen >= MINCLSIZE) {
489 MCLGET(m, M_DONTWAIT);
490 if (m->m_flags & M_EXT)
491 len = MCLBYTES;
492 }
493 m->m_len = len = min(pktlen, len);
494 #ifdef USEPKTBUF
495 bcopy((caddr_t)b, mtod(m, caddr_t), len);
496 b += len;
497 #else /* USEPKTBUF */
498 buf = mtod(m, u_short *);
499 cnt = len / 2;
500 while (cnt--)
501 *buf++ = *data;
502 if (len & 1)
503 *buf = *data; /* XXX should be byte store */
504 #ifdef ESDEBUG
505 if (esdebug) {
506 buf = mtod(m, u_short *);
507 for (i = 0; i < len; ++i)
508 printf ("%02x%s", ((u_char *)buf)[i],
509 ((i & 31) == 31) ? "\n" : "");
510 if (i & 31)
511 printf ("\n");
512 }
513 #endif
514 #endif /* USEPKTBUF */
515 pktlen -= len;
516 *mp = m;
517 mp = &m->m_next;
518 }
519 #ifndef USEPKTBUF
520 smc->b2.mmucr = MMUCR_REMRLS_RX;
521 while (smc->b2.mmucr & MMUCR_BUSY)
522 ;
523 #endif
524 eh = mtod(top, struct ether_header *);
525 top->m_pkthdr.len -= sizeof (*eh);
526 top->m_len -= sizeof (*eh);
527 top->m_data += sizeof (*eh);
528
529 ether_input(ifp, eh, top);
530 }
531
532 void
533 estint (sc)
534 struct es_softc *sc;
535 {
536 esstart (&sc->sc_ac.ac_if);
537 }
538
539 int
540 esstart(ifp)
541 struct ifnet *ifp;
542 {
543 struct es_softc *sc = escd.cd_devs[ifp->if_unit];
544 union smcregs *smc = sc->sc_base;
545 struct mbuf *m0, *m;
546 #ifdef USEPKTBUF
547 u_short pktbuf[ETHER_MAX_LEN + 2];
548 #endif
549 u_short pktctlw, pktlen;
550 u_short *buf;
551 volatile u_short *data;
552 u_long *lbuf;
553 volatile u_long *ldata;
554 short cnt;
555 int i;
556
557 if ((sc->sc_ac.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
558 IFF_RUNNING)
559 return;
560
561 for (;;) {
562 /*
563 * Sneak a peek at the next packet to get the length
564 * and see if the SMC 91C90 can accept it.
565 */
566 m = sc->sc_ac.ac_if.if_snd.ifq_head;
567 if (!m)
568 break;
569 #ifdef ESDEBUG
570 if (esdebug && (m->m_next || m->m_len & 1))
571 printf("%s: esstart m_next %x m_len %d\n", sc->sc_dev.dv_xname,
572 m->m_next, m->m_len);
573 #endif
574 for (m0 = m, pktlen = 0; m0; m0 = m0->m_next)
575 pktlen += m0->m_len;
576 #ifdef ESDEBUG
577 if (esdebug)
578 printf("%s: esstart r1 %x len %d", sc->sc_dev.dv_xname, smc->b2.pnr, pktlen);
579 #endif
580 pktctlw = 0;
581 pktlen += 4;
582 if (pktlen & 1)
583 ++pktlen; /* control byte after last byte */
584 else
585 pktlen += 2; /* control byte after pad byte */
586 smc->b2.mmucr = MMUCR_ALLOC | (pktlen & 0x0700);
587 for (i = 0; i <= 5; ++i)
588 if ((smc->b2.arr & ARR_FAILED) == 0)
589 break;
590 if (smc->b2.arr & ARR_FAILED) {
591 sc->sc_ac.ac_if.if_flags |= IFF_OACTIVE;
592 #ifdef ESDEBUG
593 if (esdebug)
594 printf("-no xmit bufs r1 %x\n", smc->b2.pnr);
595 #endif
596 sc->sc_intctl |= 0x0008;
597 break;
598 }
599 smc->b2.pnr = smc->b2.arr;
600
601 IF_DEQUEUE(&sc->sc_ac.ac_if.if_snd, m);
602 smc->b2.ptr = PTR_AUTOINCR;
603 (void) smc->b2.mmucr;
604 data = (u_short *)&smc->b2.data;
605 *data = SWAP (pktctlw);
606 *data = SWAP (pktlen);
607 #ifdef USEPKTBUF
608 i = 0;
609 for (m0 = m; m; m = m->m_next) {
610 bcopy(mtod(m, caddr_t), (char *)pktbuf + i, m->m_len);
611 i += m->m_len;
612 }
613
614 if (i & 1) /* Figure out where to put control byte */
615 pktbuf[i/2] = (pktbuf[i/2] & 0xff00) | CTLB_ODD;
616 else
617 pktbuf[i/2] = 0;
618 #ifdef ESDEBUG
619 if (esdebug) {
620 int j;
621 printf("-sending len %d pktlen %d r1 %04x\n", i, pktlen, smc->b2.pnr);
622 for (j = 0; j < pktlen - 4; ++j)
623 printf("%02x%s", ((u_char *)pktbuf)[j], ((j & 31) == 31) ? "\n" : "");
624 if (j & 31)
625 printf("\n");
626 }
627 #endif
628 #if 0 /* doesn't quite work? */
629 lbuf = (u_long *)(pktbuf);
630 ldata = (u_long *)data;
631 cnt = pktlen / 4;
632 while(cnt--)
633 *ldata = *lbuf++;
634 if (pktlen & 2) {
635 buf = (u_short *)lbuf;
636 *data = *buf;
637 }
638 #else
639 buf = pktbuf;
640 cnt = pktlen / 2;
641 while (cnt--)
642 *data = *buf++;
643 #endif
644 #else /* USEPKTBUF */
645 #ifdef ESDEBUG
646 if (esdebug)
647 printf("-sending pktlen %d r1 %04x\n", pktlen, smc->b2.pnr);
648 #endif
649 pktctlw = 0;
650 for (m0 = m; m; m = m->m_next) {
651 buf = mtod(m, u_short *);
652 #ifdef ESDEBUG
653 if (esdebug) {
654 printf(" m->m_len %d\n", m->m_len);
655 for (i = 0; i < m->m_len; ++i)
656 printf("%02x%s", ((u_char *)buf)[i], ((i & 31) == 31) ? "\n" : "");
657 if (i & 31)
658 printf("\n");
659 }
660 #endif
661 cnt = m->m_len / 2;
662 while (cnt--)
663 *data = *buf++;
664 if (m->m_len & 1)
665 pktctlw = (*buf & 0xff00) | CTLB_ODD;
666 }
667 *data = pktctlw;
668 #endif /* USEPKTBUF */
669 smc->b2.mmucr = MMUCR_ENQ_TX;
670 #ifdef ESDEBUG
671 if (esdebug)
672 printf("%s: esstart packet sent r1 %x\n", sc->sc_dev.dv_xname, smc->b2.pnr);
673 #endif
674 #if NBPFILTER > 0
675 if (sc->sc_ac.ac_if.if_bpf)
676 bpf_mtap(sc->sc_ac.ac_if.if_bpf, m0);
677 #endif
678 m_freem(m0);
679 sc->sc_ac.ac_if.if_opackets++; /* move to interrupt? */
680 sc->sc_intctl |= 0x0006;
681 }
682 smc->b2.msk = sc->sc_intctl;
683 return 0;
684 }
685
686 int
687 esioctl(ifp, cmd, data)
688 struct ifnet *ifp;
689 u_long cmd;
690 caddr_t data;
691 {
692 struct es_softc *sc = escd.cd_devs[ifp->if_unit];
693 struct ifaddr *ifa = (struct ifaddr *)data;
694 struct ifreq *ifr = (struct ifreq *)data;
695 int s, error = 0;
696
697 #ifdef ESDEBUG
698 if (esdebug)
699 printf ("esioctl called: cmd %x\n", cmd);
700 #endif
701
702 s = splimp();
703
704 switch (cmd) {
705 case SIOCSIFADDR:
706 ifp->if_flags |= IFF_UP;
707
708 switch (ifa->ifa_addr->sa_family) {
709 #ifdef INET
710 case AF_INET:
711 esinit(sc);
712 sc->sc_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr;
713 arpwhohas(&sc->sc_ac, &IA_SIN(ifa)->sin_addr);
714 break;
715 #endif
716 #ifdef NS
717 case AF_NS:
718 {
719 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
720
721 if (ns_nullhost(*ina))
722 ina->x_host =
723 *(uniion ns_host *)(sc->sc_addr);
724 else
725 bcopy(ina->x_host.c_host,
726 sc->sc_addr, sizeof(sc->sc_addr));
727 /* Set new address */
728 esinit(sc);
729 break;
730 #endif
731 default:
732 esinit(sc);
733 break;
734 }
735 break;
736 case SIOCSIFFLAGS:
737 /*
738 * If interface is marked down and it is running, then stop it
739 */
740 if ((ifp->if_flags & IFF_UP) == 0 &&
741 (ifp->if_flags & IFF_RUNNING) != 0) {
742 /*
743 * If interface is marked down and it is running, then
744 * stop it.
745 */
746 /* esstop(sc); */
747 ifp->if_flags &= ~IFF_RUNNING;
748 } else if ((ifp->if_flags & IFF_UP) != 0 &&
749 (ifp->if_flags & IFF_RUNNING) == 0) {
750 /*
751 * If interface is marked up and it is stopped, then
752 * start it.
753 */
754 esinit(sc);
755 } else {
756 /*
757 * Reset the interface to pick up changes in any other
758 * flags that affect hardware registers.
759 */
760 /* esstop(sc); */
761 esinit(sc);
762 }
763 #ifdef ESDEBUG
764 if (ifp->if_flags & IFF_DEBUG)
765 esdebug = sc->sc_debug = 1;
766 else
767 esdebug = sc->sc_debug = 0;
768 #endif
769 break;
770 case SIOCADDMULTI:
771 case SIOCDELMULTI:
772
773 default:
774 error = EINVAL;
775 }
776
777 splx(s);
778 return (error);
779 }
780
781 void
782 esreset(sc)
783 struct es_softc *sc;
784 {
785 int s;
786
787 s = splimp();
788 /* esstop(sc); */
789 esinit(sc);
790 splx(s);
791 }
792
793 int
794 eswatchdog(unit)
795 int unit;
796 {
797 register struct es_softc *sc = escd.cd_devs[unit];
798
799 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
800 esreset(sc);
801 return (0);
802 }
803