1 /* $NetBSD: if_es.c,v 1.47 2009/10/21 23:53:38 snj Exp $ */
4 * Copyright (c) 1995 Michael L. Hitch
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * SMC 91C90 Single-Chip Ethernet Controller
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: if_es.c,v 1.47 2009/10/21 23:53:38 snj Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
44 #include <sys/protosw.h>
45 #include <sys/socket.h>
46 #include <sys/syslog.h>
47 #include <sys/ioctl.h>
48 #include <sys/errno.h>
49 #include <sys/device.h>
52 #include <net/if_dl.h>
53 #include <net/if_ether.h>
54 #include <net/if_media.h>
57 #include <netinet/in.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip.h>
61 #include <netinet/if_inarp.h>
66 #include <netns/ns_if.h>
69 #include <machine/cpu.h>
70 #include <amiga/amiga/device.h>
71 #include <amiga/amiga/isr.h>
72 #include <amiga/dev/zbusvar.h>
73 #include <amiga/dev/if_esreg.h>
75 #define SWAP(x) (((x & 0xff) << 8) | ((x >> 8) & 0xff))
80 * Ethernet software status per interface.
82 * Each interface is referenced by a network interface structure,
83 * es_if, which the routing code uses to locate the interface.
84 * This structure contains the output queue for the interface, its address, ...
89 struct ethercom sc_ethercom
; /* common Ethernet structures */
90 struct ifmedia sc_media
; /* our supported media */
91 void *sc_base
; /* base address of board */
93 unsigned short sc_intctl
;
96 short sc_intbusy
; /* counter for interrupt rentered */
97 short sc_smcbusy
; /* counter for other rentry checks */
103 #include <net/bpfdesc.h>
107 /* console error messages */
109 int estxints
= 0; /* IST_TX with TX enabled */
110 int estxint2
= 0; /* IST_TX active after IST_TX_EMPTY */
111 int estxint3
= 0; /* IST_TX interrupt processed */
112 int estxint4
= 0; /* ~TEMPTY counts */
113 int estxint5
= 0; /* IST_TX_EMPTY interrupts */
114 void es_dump_smcregs(char *, union smcregs
*);
118 void esstart(struct ifnet
*);
119 void eswatchdog(struct ifnet
*);
120 int esioctl(struct ifnet
*, u_long
, void *);
121 void esrint(struct es_softc
*);
122 void estint(struct es_softc
*);
123 void esinit(struct es_softc
*);
124 void esreset(struct es_softc
*);
125 void esstop(struct es_softc
*);
126 int esmediachange(struct ifnet
*);
127 void esmediastatus(struct ifnet
*, struct ifmediareq
*);
129 int esmatch(struct device
*, struct cfdata
*, void *);
130 void esattach(struct device
*, struct device
*, void *);
132 CFATTACH_DECL(es
, sizeof(struct es_softc
),
133 esmatch
, esattach
, NULL
, NULL
);
136 esmatch(struct device
*parent
, struct cfdata
*cfp
, void *aux
)
138 struct zbus_args
*zap
= aux
;
140 /* Ameristar A4066 ethernet card */
141 if (zap
->manid
== 1053 && zap
->prodid
== 10)
148 * Interface exists: make available by filling in network interface
149 * record. System will initialize the interface when it is ready
153 esattach(struct device
*parent
, struct device
*self
, void *aux
)
155 struct es_softc
*sc
= (void *)self
;
156 struct zbus_args
*zap
= aux
;
157 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
159 u_int8_t myaddr
[ETHER_ADDR_LEN
];
161 sc
->sc_base
= zap
->va
;
164 * Manufacturer decides the 3 first bytes, i.e. ethernet vendor ID.
165 * (Currently only Ameristar.)
172 * Serial number for board contains last 3 bytes.
174 ser
= (unsigned long) zap
->serno
;
176 myaddr
[3] = (ser
>> 16) & 0xff;
177 myaddr
[4] = (ser
>> 8) & 0xff;
178 myaddr
[5] = (ser
) & 0xff;
180 /* Initialize ifnet structure. */
181 memcpy(ifp
->if_xname
, sc
->sc_dev
.dv_xname
, IFNAMSIZ
);
183 ifp
->if_ioctl
= esioctl
;
184 ifp
->if_start
= esstart
;
185 ifp
->if_watchdog
= eswatchdog
;
186 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
|
189 ifmedia_init(&sc
->sc_media
, 0, esmediachange
, esmediastatus
);
190 ifmedia_add(&sc
->sc_media
, IFM_ETHER
|IFM_MANUAL
, 0, NULL
);
191 ifmedia_set(&sc
->sc_media
, IFM_ETHER
|IFM_MANUAL
);
193 /* Attach the interface. */
195 ether_ifattach(ifp
, myaddr
);
197 /* Print additional info when attached. */
198 printf(": address %s\n", ether_sprintf(myaddr
));
200 sc
->sc_isr
.isr_intr
= esintr
;
201 sc
->sc_isr
.isr_arg
= sc
;
202 sc
->sc_isr
.isr_ipl
= 2;
203 add_isr(&sc
->sc_isr
);
208 es_dump_smcregs(char *where
, union smcregs
*smc
)
210 u_short cur_bank
= smc
->b0
.bsr
& BSR_MASK
;
212 printf("SMC registers %p from %s bank %04x\n", smc
, where
,
214 smc
->b0
.bsr
= BSR_BANK0
;
215 printf("TCR %04x EPHSR %04x RCR %04x ECR %04x MIR %04x MCR %04x\n",
216 SWAP(smc
->b0
.tcr
), SWAP(smc
->b0
.ephsr
), SWAP(smc
->b0
.rcr
),
217 SWAP(smc
->b0
.ecr
), SWAP(smc
->b0
.mir
), SWAP(smc
->b0
.mcr
));
218 smc
->b1
.bsr
= BSR_BANK1
;
219 printf("CR %04x BAR %04x IAR %04x %04x %04x GPR %04x CTR %04x\n",
220 SWAP(smc
->b1
.cr
), SWAP(smc
->b1
.bar
), smc
->b1
.iar
[0], smc
->b1
.iar
[1],
221 smc
->b1
.iar
[2], smc
->b1
.gpr
, SWAP(smc
->b1
.ctr
));
222 smc
->b2
.bsr
= BSR_BANK2
;
223 printf("MMUCR %04x PNR %02x ARR %02x FIFO %04x PTR %04x",
224 SWAP(smc
->b2
.mmucr
), smc
->b2
.pnr
, smc
->b2
.arr
, smc
->b2
.fifo
,
226 printf(" DATA %04x %04x IST %02x MSK %02x\n", smc
->b2
.data
,
227 smc
->b2
.datax
, smc
->b2
.ist
, smc
->b2
.msk
);
228 smc
->b3
.bsr
= BSR_BANK3
;
229 printf("MT %04x %04x %04x %04x\n",
230 smc
->b3
.mt
[0], smc
->b3
.mt
[1], smc
->b3
.mt
[2], smc
->b3
.mt
[3]);
231 smc
->b3
.bsr
= cur_bank
;
236 esstop(struct es_softc
*sc
)
238 union smcregs
*smc
= sc
->sc_base
;
241 * Clear interrupt mask; disable all interrupts.
243 smc
->b2
.bsr
= BSR_BANK2
;
247 * Disable transmitter and receiver.
249 smc
->b0
.bsr
= BSR_BANK0
;
254 * Cancel watchdog timer.
256 sc
->sc_ethercom
.ec_if
.if_timer
= 0;
260 esinit(struct es_softc
*sc
)
262 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
263 union smcregs
*smc
= sc
->sc_base
;
269 if (ifp
->if_flags
& IFF_RUNNING
)
270 es_dump_smcregs("esinit", smc
);
272 smc
->b0
.bsr
= BSR_BANK0
; /* Select bank 0 */
273 smc
->b0
.rcr
= RCR_EPH_RST
;
275 smc
->b3
.bsr
= BSR_BANK3
; /* Select bank 3 */
276 smc
->b3
.mt
[0] = 0; /* clear Multicast table */
280 /* XXX set Multicast table from Multicast list */
281 smc
->b1
.bsr
= BSR_BANK1
; /* Select bank 1 */
282 smc
->b1
.cr
= CR_RAM32K
| CR_NO_WAIT_ST
| CR_SET_SQLCH
;
283 smc
->b1
.ctr
= CTR_AUTO_RLSE
| CTR_TE_ENA
;
284 smc
->b1
.iar
[0] = *((const unsigned short *) &CLLADDR(ifp
->if_sadl
)[0]);
285 smc
->b1
.iar
[1] = *((const unsigned short *) &CLLADDR(ifp
->if_sadl
)[2]);
286 smc
->b1
.iar
[2] = *((const unsigned short *) &CLLADDR(ifp
->if_sadl
)[4]);
287 smc
->b2
.bsr
= BSR_BANK2
; /* Select bank 2 */
288 smc
->b2
.mmucr
= MMUCR_RESET
;
289 smc
->b0
.bsr
= BSR_BANK0
; /* Select bank 0 */
290 smc
->b0
.mcr
= SWAP(0x0020); /* reserve 8K for transmit buffers */
291 smc
->b0
.tcr
= TCR_PAD_EN
| (TCR_TXENA
+ TCR_MON_CSN
);
292 smc
->b0
.rcr
= RCR_FILT_CAR
| RCR_STRIP_CRC
| RCR_RXEN
| RCR_ALLMUL
;
293 /* XXX add promiscuous flags */
294 smc
->b2
.bsr
= BSR_BANK2
; /* Select bank 2 */
295 smc
->b2
.msk
= sc
->sc_intctl
= MSK_RX_OVRN
| MSK_RX
| MSK_EPHINT
;
297 /* Interface is now 'running', with no output active. */
298 ifp
->if_flags
|= IFF_RUNNING
;
299 ifp
->if_flags
&= ~IFF_OACTIVE
;
301 /* Attempt to start output, if any. */
310 struct es_softc
*sc
= arg
;
311 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
312 u_short intsts
, intact
;
318 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
&&
319 ifp
->if_flags
& IFF_RUNNING
) {
320 printf("%s: intr BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
322 smc
->b2
.bsr
= BSR_BANK2
;
325 intsts
= smc
->b2
.ist
;
326 intact
= smc
->b2
.msk
& intsts
;
333 printf ("%s: esintr ist %02x msk %02x",
334 sc
->sc_dev
.dv_xname
, intsts
, smc
->b2
.msk
);
335 if (sc
->sc_intbusy
++) {
336 printf("%s: esintr re-entered\n", sc
->sc_dev
.dv_xname
);
337 panic("esintr re-entered");
340 printf("%s: esintr interrupted busy %d\n", sc
->sc_dev
.dv_xname
,
346 printf ("=>%02x%02x pnr %02x arr %02x fifo %04x\n",
347 smc
->b2
.ist
, smc
->b2
.ist
, smc
->b2
.pnr
, smc
->b2
.arr
,
350 if (intact
& IST_ALLOC
) {
351 sc
->sc_intctl
&= ~MSK_ALLOC
;
354 printf ("%s: ist %02x", sc
->sc_dev
.dv_xname
,
357 if ((smc
->b2
.arr
& ARR_FAILED
) == 0) {
361 printf (" arr %02x\n", smc
->b2
.arr
);
363 save_pnr
= smc
->b2
.pnr
;
364 smc
->b2
.pnr
= smc
->b2
.arr
;
365 smc
->b2
.mmucr
= MMUCR_RLSPKT
;
366 while (smc
->b2
.mmucr
& MMUCR_BUSY
)
368 smc
->b2
.pnr
= save_pnr
;
369 ifp
->if_flags
&= ~IFF_OACTIVE
;
373 else if (esdebug
|| 1)
374 printf (" IST_ALLOC with ARR_FAILED?\n");
378 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
379 printf("%s: intr+ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
381 smc
->b2
.bsr
= BSR_BANK2
;
384 while ((smc
->b2
.fifo
& FIFO_REMPTY
) == 0) {
388 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
389 printf("%s: intr++ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
391 smc
->b2
.bsr
= BSR_BANK2
;
394 if (intact
& IST_RX_OVRN
) {
395 printf ("%s: Overrun ist %02x", sc
->sc_dev
.dv_xname
,
397 smc
->b2
.ist
= ACK_RX_OVRN
;
398 printf ("->%02x\n", smc
->b2
.ist
);
401 if (intact
& IST_TX_EMPTY
) {
405 printf ("%s: TX EMPTY %02x",
406 sc
->sc_dev
.dv_xname
, intsts
);
407 ++estxint5
; /* count # IST_TX_EMPTY ints */
409 smc
->b2
.ist
= ACK_TX_EMPTY
;
410 sc
->sc_intctl
&= ~(MSK_TX_EMPTY
| MSK_TX
);
414 printf ("->%02x intcl %x pnr %02x arr %02x\n",
415 smc
->b2
.ist
, sc
->sc_intctl
, smc
->b2
.pnr
,
418 if (smc
->b2
.ist
& IST_TX
) {
421 ++estxint2
; /* count # TX after TX_EMPTY */
424 smc
->b0
.bsr
= BSR_BANK0
;
425 ecr
= smc
->b0
.ecr
; /* Get error counters */
427 ifp
->if_collisions
+= ((ecr
>> 8) & 15) +
428 ((ecr
>> 11) & 0x1e);
429 smc
->b2
.bsr
= BSR_BANK2
;
431 smc
->b2
.mmucr
= MMUCR_RESET_TX
; /* XXX reset TX FIFO */
435 if (intact
& IST_TX
) {
436 u_char tx_pnr
, save_pnr
;
437 u_short save_ptr
, ephsr
, tcr
;
441 printf ("%s: TX INT ist %02x",
442 sc
->sc_dev
.dv_xname
, intsts
);
443 printf ("->%02x\n", smc
->b2
.ist
);
445 ++estxint3
; /* count # IST_TX */
449 ++estxint4
; /* count # ~TEMPTY */
451 smc
->b0
.bsr
= BSR_BANK0
;
452 ephsr
= smc
->b0
.ephsr
; /* get EPHSR */
453 tcr
= smc
->b0
.tcr
; /* and TCR */
454 smc
->b2
.bsr
= BSR_BANK2
;
455 save_ptr
= smc
->b2
.ptr
;
456 save_pnr
= smc
->b2
.pnr
;
457 tx_pnr
= smc
->b2
.fifo
>> 8; /* pktno from completion fifo */
458 smc
->b2
.pnr
= tx_pnr
; /* set TX packet number */
459 smc
->b2
.ptr
= PTR_READ
; /* point to status word */
461 printf("%s: esintr TXINT IST %02x PNR %02x(%d)",
462 sc
->sc_dev
.dv_xname
, smc
->b2
.ist
,
464 printf(" Status %04x", smc
->b2
.data
);
465 printf(" EPHSR %04x\n", ephsr
);
467 if ((smc
->b2
.data
& EPHSR_TX_SUC
) == 0 && (tcr
& TCR_TXENA
) == 0) {
469 * Transmitter was stopped for some error. Enqueue
470 * the packet again and restart the transmitter.
471 * May need some check to limit the number of retries.
473 smc
->b2
.mmucr
= MMUCR_ENQ_TX
;
474 smc
->b0
.bsr
= BSR_BANK0
;
475 smc
->b0
.tcr
|= TCR_TXENA
;
476 smc
->b2
.bsr
= BSR_BANK2
;
478 sc
->sc_intctl
|= MSK_TX_EMPTY
| MSK_TX
;
481 * This shouldn't have happened: IST_TX indicates
482 * the TX completion FIFO is not empty, but the
483 * status for the packet on the completion FIFO
484 * shows that the transmit was successful. Since
485 * AutoRelease is being used, a successful transmit
486 * should not result in a packet on the completion
487 * FIFO. Also, that packet doesn't seem to want
488 * to be acknowledged. If this occurs, just reset
492 if (smc
->b2
.ist
& IST_TX_EMPTY
) {
493 smc
->b2
.mmucr
= MMUCR_RESET_TX
;
494 sc
->sc_intctl
&= ~(MSK_TX_EMPTY
| MSK_TX
);
499 ++estxints
; /* count IST_TX with TX enabled */
502 smc
->b2
.pnr
= save_pnr
;
503 smc
->b2
.ptr
= save_ptr
;
504 smc
->b2
.ist
= ACK_TX
;
506 if ((smc
->b2
.fifo
& FIFO_TEMPTY
) == 0 && n
++ < 32) {
508 printf("%s: multiple TX int(%2d) pnr %02x ist %02x fifo %04x",
509 sc
->sc_dev
.dv_xname
, n
, tx_pnr
, smc
->b2
.ist
, smc
->b2
.fifo
);
510 smc
->w2
.istmsk
= ACK_TX
<< 8;
511 printf(" %04x\n", smc
->b2
.fifo
);
513 if (tx_pnr
!= (smc
->b2
.fifo
>> 8))
517 if (intact
& IST_EPHINT
) {
524 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
525 printf("%s: intr+++ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
527 smc
->b2
.bsr
= BSR_BANK2
;
530 smc
->b2
.msk
= sc
->sc_intctl
;
532 if (--sc
->sc_intbusy
) {
533 printf("%s: esintr busy on exit\n", sc
->sc_dev
.dv_xname
);
534 panic("esintr busy on exit");
542 esrint(struct es_softc
*sc
)
544 union smcregs
*smc
= sc
->sc_base
;
547 u_short pktctlw
, pktlen
, *buf
;
548 volatile u_short
*data
;
551 volatile u_long
*ldata
;
554 struct mbuf
*top
, **mp
, *m
;
556 u_char
*b
, pktbuf
[1530];
562 ifp
= &sc
->sc_ethercom
.ec_if
;
565 printf ("%s: esrint fifo %04x", sc
->sc_dev
.dv_xname
,
567 if (sc
->sc_smcbusy
++) {
568 printf("%s: esrint re-entered\n", sc
->sc_dev
.dv_xname
);
569 panic("esrint re-entered");
571 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
572 printf("%s: rint BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
574 smc
->b2
.bsr
= BSR_BANK2
;
577 data
= (volatile u_short
*)&smc
->b2
.data
;
578 smc
->b2
.ptr
= PTR_RCV
| PTR_AUTOINCR
| PTR_READ
| SWAP(0x0002);
579 (void) smc
->b2
.mmucr
;
582 printf ("->%04x", smc
->b2
.fifo
);
585 len
= SWAP(len
); /* Careful of macro side-effects */
588 printf (" length %d", len
);
590 smc
->b2
.ptr
= PTR_RCV
| (PTR_AUTOINCR
+ PTR_READ
) | SWAP(0x0000);
591 (void) smc
->b2
.mmucr
;
594 pktctlw
= SWAP(pktctlw
);
595 pktlen
= SWAP(pktlen
) - 6;
596 if (pktctlw
& RFSW_ODDFRM
)
599 printf("%s: Corrupted packet length-sts %04x bytcnt %04x len %04x bank %04x\n",
600 sc
->sc_dev
.dv_xname
, pktctlw
, pktlen
, len
, smc
->b2
.bsr
);
601 /* XXX ignore packet, or just truncate? */
602 #if defined(ESDEBUG) && defined(DDB)
603 if ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
)
606 smc
->b2
.bsr
= BSR_BANK2
;
607 smc
->b2
.mmucr
= MMUCR_REMRLS_RX
;
608 while (smc
->b2
.mmucr
& MMUCR_BUSY
)
612 if (--sc
->sc_smcbusy
) {
613 printf("%s: esrintr busy on bad packet exit\n",
614 sc
->sc_dev
.dv_xname
);
615 panic("esrintr busy on exit");
622 lbuf
= (u_long
*) pktbuf
;
623 ldata
= (u_long
*)data
;
628 buf
= (u_short
*) lbuf
;
632 buf
= (u_short
*)pktbuf
;
637 smc
->b2
.mmucr
= MMUCR_REMRLS_RX
;
638 while (smc
->b2
.mmucr
& MMUCR_BUSY
)
641 if (pktctlw
& (RFSW_ALGNERR
| RFSW_BADCRC
| RFSW_TOOLNG
| RFSW_TOOSHORT
)) {
642 printf ("%s: Packet error %04x\n", sc
->sc_dev
.dv_xname
, pktctlw
);
643 /* count input error? */
646 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw
, pktlen
,
648 for (i
= 0; i
< pktlen
; ++i
)
649 printf ("%02x%s", pktbuf
[i
], ((i
& 31) == 31) ? "\n" :
655 #else /* USEPKTBUF */
656 /* XXX copy directly from controller to mbuf */
658 if (pktctlw
& (RFSW_ALGNERR
| RFSW_BADCRC
| RFSW_TOOLNG
| RFSW_TOOSHORT
)) {
659 printf ("%s: Packet error %04x\n", sc
->sc_dev
.dv_xname
, pktctlw
);
660 /* count input error? */
663 printf (" pktctlw %04x pktlen %04x fifo %04x\n", pktctlw
, pktlen
,
667 #endif /* USEPKTBUF */
669 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
672 m
->m_pkthdr
.rcvif
= ifp
;
673 m
->m_pkthdr
.len
= pktlen
;
682 MGET(m
, M_DONTWAIT
, MT_DATA
);
689 if (pktlen
>= MINCLSIZE
) {
690 MCLGET(m
, M_DONTWAIT
);
691 if (m
->m_flags
& M_EXT
)
694 m
->m_len
= len
= min(pktlen
, len
);
696 memcpy(mtod(m
, void *), (void *)b
, len
);
698 #else /* USEPKTBUF */
699 buf
= mtod(m
, u_short
*);
704 *buf
= *data
; /* XXX should be byte store */
707 buf
= mtod(m
, u_short
*);
708 for (i
= 0; i
< len
; ++i
)
709 printf ("%02x%s", ((u_char
*)buf
)[i
],
710 ((i
& 31) == 31) ? "\n" : "");
715 #endif /* USEPKTBUF */
721 smc
->b2
.mmucr
= MMUCR_REMRLS_RX
;
722 while (smc
->b2
.mmucr
& MMUCR_BUSY
)
727 * Check if there's a BPF listener on this interface. If so, hand off
728 * the raw packet to bpf.
731 bpf_mtap(ifp
->if_bpf
, top
);
733 (*ifp
->if_input
)(ifp
, top
);
735 if (--sc
->sc_smcbusy
) {
736 printf("%s: esintr busy on exit\n", sc
->sc_dev
.dv_xname
);
737 panic("esintr busy on exit");
743 estint(struct es_softc
*sc
)
746 esstart(&sc
->sc_ethercom
.ec_if
);
750 esstart(struct ifnet
*ifp
)
752 struct es_softc
*sc
= ifp
->if_softc
;
753 union smcregs
*smc
= sc
->sc_base
;
756 u_short pktbuf
[ETHERMTU
+ 2];
758 u_short oddbyte
, needbyte
;
760 u_short pktctlw
, pktlen
;
762 volatile u_short
*data
;
765 volatile u_long
*ldata
;
771 if ((sc
->sc_ethercom
.ec_if
.if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) !=
776 if (sc
->sc_smcbusy
++) {
777 printf("%s: esstart re-entered\n", sc
->sc_dev
.dv_xname
);
778 panic("esstart re-entred");
780 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
781 printf("%s: esstart BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
783 smc
->b2
.bsr
= BSR_BANK2
;
788 u_short start_ptr
, end_ptr
;
791 * Sneak a peek at the next packet to get the length
792 * and see if the SMC 91C90 can accept it.
794 m
= sc
->sc_ethercom
.ec_if
.if_snd
.ifq_head
;
798 if (esdebug
&& (m
->m_next
|| m
->m_len
& 1))
799 printf("%s: esstart m_next %p m_len %d\n",
800 sc
->sc_dev
.dv_xname
, m
->m_next
, m
->m_len
);
802 for (m0
= m
, pktlen
= 0; m0
; m0
= m0
->m_next
)
807 ++pktlen
; /* control byte after last byte */
809 pktlen
+= 2; /* control byte after pad byte */
810 smc
->b2
.mmucr
= MMUCR_ALLOC
| (pktlen
& 0x0700);
811 for (i
= 0; i
<= 5; ++i
)
812 if ((smc
->b2
.arr
& ARR_FAILED
) == 0)
814 if (smc
->b2
.arr
& ARR_FAILED
) {
815 sc
->sc_ethercom
.ec_if
.if_flags
|= IFF_OACTIVE
;
816 sc
->sc_intctl
|= MSK_ALLOC
;
817 sc
->sc_ethercom
.ec_if
.if_timer
= 5;
820 active_pnr
= smc
->b2
.pnr
= smc
->b2
.arr
;
823 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
824 printf("%s: esstart+ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
826 smc
->b2
.bsr
= BSR_BANK2
;
829 IF_DEQUEUE(&sc
->sc_ethercom
.ec_if
.if_snd
, m
);
830 smc
->b2
.ptr
= PTR_AUTOINCR
;
831 (void) smc
->b2
.mmucr
;
832 data
= (volatile u_short
*)&smc
->b2
.data
;
833 *data
= SWAP(pktctlw
);
834 *data
= SWAP(pktlen
);
836 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
837 printf("%s: esstart++ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
839 smc
->b2
.bsr
= BSR_BANK2
;
844 for (m0
= m
; m
; m
= m
->m_next
) {
845 memcpy((char *)pktbuf
+ i
, mtod(m
, void *), m
->m_len
);
849 if (i
& 1) /* Figure out where to put control byte */
850 pktbuf
[i
/2] = (pktbuf
[i
/2] & 0xff00) | CTLB_ODD
;
855 if (pktlen
> sizeof(pktbuf
) && i
> (sizeof(pktbuf
) * 2))
856 printf("%s: esstart packet longer than pktbuf\n",
857 sc
->sc_dev
.dv_xname
);
859 #if 0 /* doesn't quite work? */
860 lbuf
= (u_long
*)(pktbuf
);
861 ldata
= (u_long
*)data
;
866 buf
= (u_short
*)lbuf
;
871 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
872 printf("%s: esstart++2 BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
874 smc
->b2
.bsr
= BSR_BANK2
;
876 start_ptr
= SWAP(smc
->b2
.ptr
); /* save PTR before copy */
883 end_ptr
= SWAP(smc
->b2
.ptr
); /* save PTR after copy */
886 #else /* USEPKTBUF */
888 oddbyte
= needbyte
= 0;
889 for (m0
= m
; m
; m
= m
->m_next
) {
890 buf
= mtod(m
, u_short
*);
893 oddbyte
|= *buf
>> 8;
899 pktctlw
= (*buf
& 0xff00) | CTLB_ODD
;
900 if (m
->m_len
& 1 && m
->m_next
)
901 printf("%s: esstart odd byte count in mbuf\n",
902 sc
->sc_dev
.dv_xname
);
905 #endif /* USEPKTBUF */
906 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
908 * The bank select register has changed. This seems
909 * to happen with my A2000/Zeus once in a while. It
910 * appears that the Ethernet chip resets while
911 * copying the transmit buffer. Requeue the current
912 * transmit buffer and reinitialize the interface.
913 * The initialize routine will take care of
914 * retransmitting the buffer. mhitch
917 printf("%s: esstart+++ BSR not 2: %04x\n",
918 sc
->sc_dev
.dv_xname
, smc
->b2
.bsr
);
920 smc
->b2
.bsr
= BSR_BANK2
;
922 printf("start_ptr %04x end_ptr %04x cur ptr %04x\n",
923 start_ptr
, end_ptr
, SWAP(smc
->b2
.ptr
));
926 IF_PREPEND(&sc
->sc_ethercom
.ec_if
.if_snd
, m0
);
927 esinit(sc
); /* It's really hosed - reset */
930 smc
->b2
.mmucr
= MMUCR_ENQ_TX
;
931 if (smc
->b2
.pnr
!= active_pnr
)
932 printf("%s: esstart - PNR changed %x->%x\n",
933 sc
->sc_dev
.dv_xname
, active_pnr
, smc
->b2
.pnr
);
935 if (sc
->sc_ethercom
.ec_if
.if_bpf
)
936 bpf_mtap(sc
->sc_ethercom
.ec_if
.if_bpf
, m0
);
939 sc
->sc_ethercom
.ec_if
.if_opackets
++; /* move to interrupt? */
940 sc
->sc_intctl
|= MSK_TX_EMPTY
| MSK_TX
;
941 sc
->sc_ethercom
.ec_if
.if_timer
= 5;
943 smc
->b2
.msk
= sc
->sc_intctl
;
945 while ((smc
->b2
.bsr
& BSR_MASK
) != BSR_BANK2
) {
946 printf("%s: esstart++++ BSR not 2: %04x\n", sc
->sc_dev
.dv_xname
,
948 smc
->b2
.bsr
= BSR_BANK2
;
950 if (--sc
->sc_smcbusy
) {
951 printf("%s: esstart busy on exit\n", sc
->sc_dev
.dv_xname
);
952 panic("esstart busy on exit");
958 esioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
960 struct es_softc
*sc
= ifp
->if_softc
;
961 register struct ifaddr
*ifa
= (struct ifaddr
*)data
;
962 struct ifreq
*ifr
= (struct ifreq
*)data
;
970 ifp
->if_flags
|= IFF_UP
;
972 switch (ifa
->ifa_addr
->sa_family
) {
976 arp_ifinit(ifp
, ifa
);
982 register struct ns_addr
*ina
= &IA_SNS(ifa
)->sns_addr
;
984 if (ns_nullhost(*ina
))
986 *(union ns_host
*)LLADDR(ifp
->if_sadl
);
988 bcopy(ina
->x_host
.c_host
,
989 LLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
990 /* Set new address. */
1002 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
1004 /* XXX see the comment in ed_ioctl() about code re-use */
1006 * If interface is marked down and it is running, then stop it
1008 if ((ifp
->if_flags
& IFF_UP
) == 0 &&
1009 (ifp
->if_flags
& IFF_RUNNING
) != 0) {
1011 * If interface is marked down and it is running, then
1015 ifp
->if_flags
&= ~IFF_RUNNING
;
1016 } else if ((ifp
->if_flags
& IFF_UP
) != 0 &&
1017 (ifp
->if_flags
& IFF_RUNNING
) == 0) {
1019 * If interface is marked up and it is stopped, then
1025 * Reset the interface to pick up changes in any other
1026 * flags that affect hardware registers.
1032 if (ifp
->if_flags
& IFF_DEBUG
)
1033 esdebug
= sc
->sc_debug
= 1;
1035 esdebug
= sc
->sc_debug
= 0;
1041 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
1043 * Multicast list has changed; set the hardware filter
1046 if (ifp
->if_flags
& IFF_RUNNING
) {
1055 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->sc_media
, cmd
);
1059 error
= ether_ioctl(ifp
, cmd
, data
);
1068 * Reset the interface.
1071 esreset(struct es_softc
*sc
)
1082 eswatchdog(struct ifnet
*ifp
)
1084 struct es_softc
*sc
= ifp
->if_softc
;
1086 log(LOG_ERR
, "%s: device timeout\n", sc
->sc_dev
.dv_xname
);
1093 esmediachange(struct ifnet
*ifp
)
1099 esmediastatus(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)