1 /* $NetBSD: if_il.c,v 1.23 2009/05/12 13:19:12 cegger Exp $ */
3 * Copyright (c) 1982, 1986 Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * @(#)if_il.c 7.8 (Berkeley) 12/16/90
34 * Interlan Ethernet Communications Controller interface
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: if_il.c,v 1.23 2009/05/12 13:19:12 cegger Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/ioctl.h>
49 #include <sys/errno.h>
50 #include <sys/syslog.h>
51 #include <sys/device.h>
54 #include <net/if_ether.h>
55 #include <net/if_dl.h>
58 #include <netinet/in.h>
64 #include <dev/qbus/ubareg.h>
65 #include <dev/qbus/ubavar.h>
66 #include <dev/qbus/if_uba.h>
68 #include <dev/qbus/if_il.h>
69 #include <dev/qbus/if_ilreg.h>
72 * Ethernet software status per interface.
74 * Each interface is referenced by a network interface structure,
75 * is_if, which the routing code uses to locate the interface.
76 * This structure contains the output queue for the interface, its address, ...
77 * We also have, for each interface, a UBA interface structure, which
78 * contains information about the UNIBUS resources held by the interface:
79 * map registers, buffered data paths, etc. Information is cached in this
80 * structure for use by the if_uba.c routines in running the interface
85 struct device sc_dev
; /* Configuration common part */
86 struct ethercom sc_ec
; /* Ethernet common part */
87 #define sc_if sc_ec.ec_if /* network-visible interface */
88 struct evcnt sc_cintrcnt
; /* Command interrupts */
89 struct evcnt sc_rintrcnt
; /* Receive interrupts */
90 bus_space_tag_t sc_iot
;
92 bus_dma_tag_t sc_dmat
;
95 struct ifuba sc_ifuba
; /* UNIBUS resources */
97 #define ILF_RCVPENDING 0x2 /* start rcv in ilcint */
98 #define ILF_STATPENDING 0x4 /* stat cmd pending */
99 #define ILF_RUNNING 0x8 /* board is running */
100 #define ILF_SETADDR 0x10 /* physical address is changed */
101 short sc_lastcmd
; /* can't read csr, so must save it */
102 short sc_scaninterval
; /* interval of stat collection */
103 #define ILWATCHINTERVAL 60 /* once every 60 seconds */
105 struct il_stats isu_stats
; /* holds on-board statistics */
106 struct ether_addr isu_maddrs
[63]; /* multicast addrs */
108 #define sc_stats sc_isu.isu_stats
109 #define sc_maddrs sc_isu.isu_maddrs
110 struct il_stats sc_sum
; /* summation over time */
111 int sc_ubaddr
; /* mapping registers of is_stats */
114 static int ilmatch(device_t
, cfdata_t
, void *);
115 static void ilattach(device_t
, device_t
, void *);
116 static void ilcint(void *);
117 static void ilrint(void *);
118 static void ilreset(device_t
);
119 static int ilwait(struct il_softc
*, char *);
120 static int ilinit(struct ifnet
*);
121 static void ilstart(struct ifnet
*);
122 static void ilwatch(struct ifnet
*);
123 static void iltotal(struct il_softc
*);
124 static void ilstop(struct ifnet
*, int);
126 CFATTACH_DECL(il
, sizeof(struct il_softc
),
127 ilmatch
, ilattach
, NULL
, NULL
);
129 #define IL_WCSR(csr, val) \
130 bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
131 #define IL_RCSR(csr) \
132 bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
133 #define LOWORD(x) ((int)(x) & 0xffff)
134 #define HIWORD(x) (((int)(x) >> 16) & 0x3)
137 ilmatch(device_t parent
, cfdata_t cf
, void *aux
)
139 struct uba_attach_args
*ua
= aux
;
142 bus_space_write_2(ua
->ua_iot
, ua
->ua_ioh
, IL_CSR
, ILC_OFFLINE
|IL_CIE
);
144 i
= bus_space_read_2(ua
->ua_iot
, ua
->ua_ioh
, IL_CSR
); /* clear CDONE */
150 * Interface exists: make available by filling in network interface
151 * record. System will initialize the interface when it is ready
152 * to accept packets. A STATUS command is done to get the ethernet
153 * address and other interesting data.
156 ilattach(device_t parent
, device_t self
, void *aux
)
158 struct uba_attach_args
*ua
= aux
;
159 struct il_softc
*sc
= device_private(self
);
160 struct ifnet
*ifp
= &sc
->sc_if
;
163 sc
->sc_iot
= ua
->ua_iot
;
164 sc
->sc_ioh
= ua
->ua_ioh
;
165 sc
->sc_dmat
= ua
->ua_dmat
;
168 * Map interrupt vectors and reset function.
170 uba_intr_establish(ua
->ua_icookie
, ua
->ua_cvec
, ilcint
,
171 sc
, &sc
->sc_cintrcnt
);
172 evcnt_attach_dynamic(&sc
->sc_cintrcnt
, EVCNT_TYPE_INTR
, ua
->ua_evcnt
,
173 device_xname(&sc
->sc_dev
), "intr");
174 uba_intr_establish(ua
->ua_icookie
, ua
->ua_cvec
-4, ilrint
,
175 sc
, &sc
->sc_rintrcnt
);
176 evcnt_attach_dynamic(&sc
->sc_rintrcnt
, EVCNT_TYPE_INTR
, ua
->ua_evcnt
,
177 device_xname(&sc
->sc_dev
), "intr");
178 uba_reset_establish(ilreset
, &sc
->sc_dev
);
181 * Reset the board and map the statistics
182 * buffer onto the Unibus.
184 IL_WCSR(IL_CSR
, ILC_RESET
);
185 (void)ilwait(sc
, "reset");
186 sc
->sc_ui
.ui_size
= sizeof(struct il_stats
);
187 sc
->sc_ui
.ui_vaddr
= (void *)&sc
->sc_stats
;
188 if ((error
= uballoc((struct uba_softc
*)parent
, &sc
->sc_ui
, 0)))
189 return printf(": failed uballoc, error = %d\n", error
);
191 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ui
.ui_baddr
));
192 IL_WCSR(IL_BCR
, sizeof(struct il_stats
));
193 IL_WCSR(IL_CSR
, ((sc
->sc_ui
.ui_baddr
>> 2) & IL_EUA
)|ILC_STAT
);
194 (void)ilwait(sc
, "status");
195 ubfree((struct uba_softc
*)parent
, &sc
->sc_ui
);
196 printf("%s: module=%s firmware=%s\n", device_xname(&sc
->sc_dev
),
197 sc
->sc_stats
.ils_module
, sc
->sc_stats
.ils_firmware
);
198 printf("%s: hardware address %s\n", device_xname(&sc
->sc_dev
),
199 ether_sprintf(sc
->sc_stats
.ils_addr
));
201 strlcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
203 ifp
->if_flags
= IFF_BROADCAST
;
204 ifp
->if_init
= ilinit
;
205 ifp
->if_stop
= ilstop
;
206 ifp
->if_ioctl
= ether_ioctl
;
207 ifp
->if_start
= ilstart
;
208 ifp
->if_watchdog
= ilwatch
;
209 IFQ_SET_READY(&ifp
->if_snd
);
212 ether_ifattach(ifp
, sc
->sc_stats
.ils_addr
);
216 ilstop(struct ifnet
*ifp
, int a
)
218 struct il_softc
*sc
= ifp
->if_softc
;
220 IL_WCSR(IL_CSR
, ILC_RESET
);
225 ilwait(struct il_softc
*sc
, char *op
)
228 while ((IL_RCSR(IL_CSR
)&IL_CDONE
) == 0)
230 if (IL_RCSR(IL_CSR
)&IL_STATUS
) {
233 snprintb(bits
, sizeof(bits
), IL_BITS
, IL_RCSR(IL_CSR
));
234 aprint_error_dev(&sc
->sc_dev
, "%s failed, csr=%s\n", op
, bits
);
241 * Reset of interface after UNIBUS reset.
242 * If interface is on specified uba, reset its state.
245 ilreset(device_t dev
)
247 struct il_softc
*sc
= (void *)dev
;
249 printf(" %s", device_xname(&sc
->sc_dev
));
250 sc
->sc_if
.if_flags
&= ~IFF_RUNNING
;
251 sc
->sc_flags
&= ~ILF_RUNNING
;
256 * Initialization of interface; clear recorded pending
257 * operations, and reinitialize UNIBUS usage.
260 ilinit(struct ifnet
*ifp
)
262 struct il_softc
*sc
= ifp
->if_softc
;
265 if (sc
->sc_flags
& ILF_RUNNING
)
268 if ((ifp
->if_flags
& IFF_RUNNING
) == 0) {
269 if (if_ubainit(&sc
->sc_ifuba
,
270 (void *)device_parent(&sc
->sc_dev
),
272 aprint_error_dev(&sc
->sc_dev
, "can't initialize\n");
273 sc
->sc_if
.if_flags
&= ~IFF_UP
;
276 sc
->sc_ui
.ui_size
= sizeof(sc
->sc_isu
);
277 sc
->sc_ui
.ui_vaddr
= (void *)&sc
->sc_isu
;
278 uballoc((void *)device_parent(&sc
->sc_dev
), &sc
->sc_ui
, 0);
280 sc
->sc_scaninterval
= ILWATCHINTERVAL
;
281 ifp
->if_timer
= sc
->sc_scaninterval
;
284 * Turn off source address insertion (it's faster this way),
285 * and set board online. Former doesn't work if board is
286 * already online (happens on ubareset), so we put it offline
290 IL_WCSR(IL_CSR
, ILC_RESET
);
291 if (ilwait(sc
, "hardware diag")) {
292 sc
->sc_if
.if_flags
&= ~IFF_UP
;
296 IL_WCSR(IL_CSR
, ILC_CISA
);
297 while ((IL_RCSR(IL_CSR
) & IL_CDONE
) == 0)
300 * If we must reprogram this board's physical ethernet
301 * address (as for secondary XNS interfaces), we do so
302 * before putting it on line, and starting receive requests.
303 * If you try this on an older 1010 board, it will total
306 if (sc
->sc_flags
& ILF_SETADDR
) {
307 memcpy(&sc
->sc_isu
, CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
308 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ui
.ui_baddr
));
309 IL_WCSR(IL_BCR
, ETHER_ADDR_LEN
);
310 IL_WCSR(IL_CSR
, ((sc
->sc_ui
.ui_baddr
>> 2) & IL_EUA
)|ILC_LDPA
);
311 if (ilwait(sc
, "setaddr"))
313 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ui
.ui_baddr
));
314 IL_WCSR(IL_BCR
, sizeof (struct il_stats
));
315 IL_WCSR(IL_CSR
, ((sc
->sc_ui
.ui_baddr
>> 2) & IL_EUA
)|ILC_STAT
);
316 if (ilwait(sc
, "verifying setaddr"))
318 if (memcmp(sc
->sc_stats
.ils_addr
,
319 CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
) != 0) {
320 aprint_error_dev(&sc
->sc_dev
, "setaddr didn't work\n");
325 if (is
->is_if
.if_flags
& IFF_PROMISC
) {
326 addr
->il_csr
= ILC_PRMSC
;
327 if (ilwait(ui
, "all multi"))
329 } else if (is
->is_if
.if_flags
& IFF_ALLMULTI
) {
331 addr
->il_csr
= ILC_ALLMC
;
332 if (ilwait(ui
, "all multi"))
336 register struct ether_addr
*ep
= is
->is_maddrs
;
337 struct ether_multi
*enm
;
338 struct ether_multistep step
;
340 * Step through our list of multicast addresses. If we have
341 * too many multicast addresses, or if we have to listen to
342 * a range of multicast addresses, turn on reception of all
346 ETHER_FIRST_MULTI(step
, &is
->is_ac
, enm
);
347 while (enm
!= NULL
) {
348 if (++i
> 63 && k
!= 0) {
351 *ep
++ = *(struct ether_addr
*)enm
->enm_addrlo
;
352 ETHER_NEXT_MULTI(step
, enm
);
356 } else if (i
<= 63) {
357 addr
->il_bar
= is
->is_ubaddr
& 0xffff;
358 addr
->il_bcr
= i
* sizeof (struct ether_addr
);
359 addr
->il_csr
= ((is
->is_ubaddr
>> 2) & IL_EUA
)|
361 if (ilwait(ui
, "load multi"))
364 is
->is_if
.if_flags
|= IFF_ALLMULTI
;
365 goto too_many_multis
;
368 #endif /* MULTICAST */
371 * Hang receive buffer and start any pending
372 * writes by faking a transmit complete.
373 * Receive bcr is not a multiple of 8 so buffer
374 * chaining can't happen.
376 IL_WCSR(IL_CSR
, ILC_ONLINE
);
377 while ((IL_RCSR(IL_CSR
) & IL_CDONE
) == 0)
380 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ifuba
.ifu_r
.ifrw_info
));
381 IL_WCSR(IL_BCR
, sizeof(struct il_rheader
) + ETHERMTU
+ 6);
383 ((sc
->sc_ifuba
.ifu_r
.ifrw_info
>> 2) & IL_EUA
)|ILC_RCV
|IL_RIE
);
384 while ((IL_RCSR(IL_CSR
) & IL_CDONE
) == 0)
386 ifp
->if_flags
|= IFF_RUNNING
| IFF_OACTIVE
;
387 sc
->sc_flags
|= ILF_RUNNING
;
395 * Start output on interface.
396 * Get another datagram to send off of the interface queue,
397 * and map it to the interface before starting the output.
400 ilstart(struct ifnet
*ifp
)
402 struct il_softc
*sc
= ifp
->if_softc
;
407 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
409 if ((sc
->sc_flags
& ILF_STATPENDING
) == 0)
411 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ui
.ui_baddr
));
412 IL_WCSR(IL_BCR
, sizeof (struct il_stats
));
413 csr
= ((sc
->sc_ui
.ui_baddr
>> 2) & IL_EUA
)|ILC_STAT
|IL_RIE
|IL_CIE
;
414 sc
->sc_flags
&= ~ILF_STATPENDING
;
417 len
= if_wubaput(&sc
->sc_ifuba
, m
);
419 if (sc
->sc_ifuba
.ifu_flags
& UBA_NEEDBDP
)
420 UBAPURGE(is
->is_ifuba
.ifu_uba
, is
->is_ifuba
.ifu_w
.ifrw_bdp
);
422 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ifuba
.ifu_w
.ifrw_info
));
423 IL_WCSR(IL_BCR
, len
);
425 ((sc
->sc_ifuba
.ifu_w
.ifrw_info
>> 2) & IL_EUA
)|ILC_XMIT
|IL_CIE
|IL_RIE
;
428 sc
->sc_lastcmd
= csr
& IL_CMD
;
429 IL_WCSR(IL_CSR
, csr
);
430 ifp
->if_flags
|= IFF_OACTIVE
;
435 * Command done interrupt.
440 struct il_softc
*sc
= arg
;
443 if ((sc
->sc_if
.if_flags
& IFF_OACTIVE
) == 0) {
446 snprintb(bits
, sizeof(bits
), IL_BITS
, IL_RCSR(IL_CSR
));
447 aprint_error_dev(&sc
->sc_dev
, "stray xmit interrupt, csr=%s\n",
451 csr
= IL_RCSR(IL_CSR
);
453 * Hang receive buffer if it couldn't
454 * be done earlier (in ilrint).
456 if (sc
->sc_flags
& ILF_RCVPENDING
) {
459 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ifuba
.ifu_r
.ifrw_info
));
460 IL_WCSR(IL_BCR
, sizeof(struct il_rheader
) + ETHERMTU
+ 6);
462 ((sc
->sc_ifuba
.ifu_r
.ifrw_info
>>2) & IL_EUA
)|ILC_RCV
|IL_RIE
);
464 while ((IL_RCSR(IL_CSR
) & IL_CDONE
) == 0)
467 sc
->sc_flags
&= ~ILF_RCVPENDING
;
469 sc
->sc_if
.if_flags
&= ~IFF_OACTIVE
;
471 switch (sc
->sc_lastcmd
) {
474 sc
->sc_if
.if_opackets
++;
475 if (csr
> ILERR_RETRIES
)
476 sc
->sc_if
.if_oerrors
++;
480 if (csr
== ILERR_SUCCESS
)
484 if_wubaend(&sc
->sc_ifuba
);
489 * Ethernet interface receiver interrupt.
490 * If input error just drop packet.
491 * Otherwise purge input buffered data path and examine
492 * packet to determine type. If can't determine length
493 * from type, then have to drop packet. Othewise decapsulate
494 * packet based on type and pass to type specific higher-level
500 struct il_softc
*sc
= arg
;
501 struct il_rheader
*il
;
505 sc
->sc_if
.if_ipackets
++;
507 if (sc
->sc_ifuba
.ifu_flags
& UBA_NEEDBDP
)
508 UBAPURGE(is
->is_ifuba
.ifu_uba
, is
->is_ifuba
.ifu_r
.ifrw_bdp
);
510 il
= (struct il_rheader
*)(sc
->sc_ifuba
.ifu_r
.ifrw_addr
);
511 len
= il
->ilr_length
- sizeof(struct il_rheader
);
512 if ((il
->ilr_status
&(ILFSTAT_A
|ILFSTAT_C
)) || len
< 46 ||
514 sc
->sc_if
.if_ierrors
++;
516 if (sc
->sc_if
.if_ierrors
% 100 == 0)
517 printf("il%d: += 100 input errors\n", unit
);
526 * Pull packet off interface.
528 m
= if_rubaget(&sc
->sc_ifuba
, &sc
->sc_if
, len
);
532 /* Shave off status hdr */
534 (*sc
->sc_if
.if_input
)(&sc
->sc_if
, m
);
537 * Reset for next packet if possible.
538 * If waiting for transmit command completion, set flag
539 * and wait until command completes.
541 if (sc
->sc_if
.if_flags
& IFF_OACTIVE
) {
542 sc
->sc_flags
|= ILF_RCVPENDING
;
545 IL_WCSR(IL_BAR
, LOWORD(sc
->sc_ifuba
.ifu_r
.ifrw_info
));
546 IL_WCSR(IL_BCR
, sizeof(struct il_rheader
) + ETHERMTU
+ 6);
548 ((sc
->sc_ifuba
.ifu_r
.ifrw_info
>> 2) & IL_EUA
)|ILC_RCV
|IL_RIE
);
550 while ((IL_RCSR(IL_CSR
) & IL_CDONE
) == 0)
555 * Watchdog routine, request statistics from board.
558 ilwatch(struct ifnet
*ifp
)
560 struct il_softc
*sc
= ifp
->if_softc
;
563 if (sc
->sc_flags
& ILF_STATPENDING
) {
564 ifp
->if_timer
= sc
->sc_scaninterval
;
568 sc
->sc_flags
|= ILF_STATPENDING
;
569 if ((sc
->sc_if
.if_flags
& IFF_OACTIVE
) == 0)
572 ifp
->if_timer
= sc
->sc_scaninterval
;
576 * Total up the on-board statistics.
579 iltotal(struct il_softc
*sc
)
581 struct ifnet
*ifp
= &sc
->sc_if
;
582 u_short
*interval
, *sum
, *end
;
584 interval
= &sc
->sc_stats
.ils_frames
;
585 sum
= &sc
->sc_sum
.ils_frames
;
586 end
= sc
->sc_sum
.ils_fill2
;
588 *sum
++ += *interval
++;
589 sc
->sc_if
.if_collisions
= sc
->sc_sum
.ils_collis
;
590 if ((sc
->sc_flags
& ILF_SETADDR
) &&
591 (memcmp(sc
->sc_stats
.ils_addr
, CLLADDR(ifp
->if_sadl
),
592 ETHER_ADDR_LEN
) != 0)) {
593 log(LOG_ERR
, "%s: physaddr reverted\n", device_xname(&sc
->sc_dev
));
594 sc
->sc_flags
&= ~ILF_RUNNING
;
601 * set ethernet address for unit
604 il_setaddr(u_char
*physaddr
, struct il_softc
*sc
)
606 if (! (sc
->sc_flags
& ILF_RUNNING
))
609 memcpy((void *)is
->is_addr
, (void *)physaddr
, sizeof is
->is_addr
);
610 sc
->sc_flags
&= ~ILF_RUNNING
;
611 sc
->sc_flags
|= ILF_SETADDR
;