153897Smckusick /*
2*63305Sbostic * Copyright (c) 1992, 1993
3*63305Sbostic * The Regents of the University of California. All rights reserved.
453897Smckusick *
553897Smckusick * This code is derived from software contributed to Berkeley by
653897Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
753897Smckusick *
853897Smckusick * %sccs.include.redist.c%
953897Smckusick *
1053897Smckusick * from: $Hdr: if_en.c,v 4.300 91/06/09 06:25:54 root Rel41 $ SONY
1153897Smckusick *
12*63305Sbostic * @(#)if_en.c 8.1 (Berkeley) 06/11/93
1353897Smckusick */
1453897Smckusick
1553897Smckusick #include "en.h"
1653897Smckusick #include "rawether.h"
1753897Smckusick #include "bpfilter.h"
1853897Smckusick
1953897Smckusick #if NEN > 0
2053897Smckusick
2153897Smckusick /*
2253897Smckusick * Interlan Ethernet Communications Controller interface
2353897Smckusick */
2457180Sutashiro #include <sys/types.h>
2557180Sutashiro #include <machine/pte.h>
2653897Smckusick
2757180Sutashiro #include <sys/param.h>
2857180Sutashiro #include <sys/systm.h>
2957180Sutashiro #include <sys/mbuf.h>
3057180Sutashiro #include <sys/buf.h>
3157180Sutashiro #include <sys/protosw.h>
3257180Sutashiro #include <sys/socket.h>
3357180Sutashiro #include <sys/ioctl.h>
3457180Sutashiro #include <sys/errno.h>
3557180Sutashiro #include <sys/time.h>
3657180Sutashiro #include <sys/cdefs.h>
3753897Smckusick
3857180Sutashiro #include <net/if.h>
3957180Sutashiro #include <net/netisr.h>
4057180Sutashiro #include <net/route.h>
4153897Smckusick
4253897Smckusick #ifdef INET
4357180Sutashiro #include <netinet/in.h>
4457180Sutashiro #include <netinet/in_systm.h>
4557180Sutashiro #include <netinet/in_var.h>
4657180Sutashiro #include <netinet/ip.h>
4757180Sutashiro #include <netinet/if_ether.h>
4853897Smckusick #endif
4953897Smckusick
5057180Sutashiro #include <news3400/if/if_news.h>
5157180Sutashiro #include <news3400/if/if_en.h>
5253897Smckusick
5353897Smckusick #ifdef CPU_SINGLE
5457180Sutashiro #include <news3400/hbdev/hbvar.h>
5553897Smckusick #define iop_device hb_device
5653897Smckusick #define iop_driver hb_driver
5753897Smckusick #define ii_unit hi_unit
5853897Smckusick #define ii_intr hi_intr
5953897Smckusick #define ii_alive hi_alive
6053897Smckusick #else
6157180Sutashiro #include <news3400/iop/iopvar.h>
6253897Smckusick #endif
6353897Smckusick
6453897Smckusick int enprobe(), enattach(), enrint(), enxint();
6553897Smckusick struct mbuf *m_devget();
6653897Smckusick
6753897Smckusick #ifdef CPU_SINGLE
6853897Smckusick struct hb_device *eninfo[NEN];
6953897Smckusick struct hb_driver endriver = { enprobe, 0, enattach, 0, 0, "en", eninfo };
7053897Smckusick #else
7153897Smckusick struct iop_device *eninfo[NEN];
7253897Smckusick struct iop_driver endriver = { enprobe, 0, enattach, 0, "en", eninfo };
7353897Smckusick #endif
7453897Smckusick
7553897Smckusick #define ENUNIT(x) minor(x)
7653897Smckusick
7754473Sutashiro int eninit(),enioctl(),enreset(),enwatch(),enstart();
7853897Smckusick int endebug = 0;
7953897Smckusick
8053897Smckusick struct ether_addr {
8153897Smckusick u_char addr[6];
8253897Smckusick };
8353897Smckusick
8453897Smckusick extern struct ifnet loif;
8553897Smckusick
8653897Smckusick struct en_softc en_softc[NEN];
8753897Smckusick
8853897Smckusick #if NBPFILTER > 0
8957180Sutashiro #include <net/bpf.h>
9053897Smckusick #endif
9153897Smckusick
9253897Smckusick enprobe(ii)
9353897Smckusick struct iop_device *ii;
9453897Smckusick {
9553897Smckusick
9653897Smckusick return (en_probe(ii));
9753897Smckusick }
9853897Smckusick
9953897Smckusick /*
10053897Smckusick * Interface exists: make available by filling in network interface
10153897Smckusick * record. System will initialize the interface when it is ready
10253897Smckusick * to accept packets. A STATUS command is done to get the ethernet
10353897Smckusick * address and other interesting data.
10453897Smckusick */
enattach(ii)10553897Smckusick enattach(ii)
10653897Smckusick register struct iop_device *ii;
10753897Smckusick {
10853897Smckusick register struct en_softc *es = &en_softc[ii->ii_unit];
10953897Smckusick register struct ifnet *ifp = &es->es_if;
11053897Smckusick extern char *ether_sprintf();
11153897Smckusick
11253897Smckusick en_attach(ii->ii_unit);
11353897Smckusick printf("en%d: hardware address %s\n",
11453897Smckusick ii->ii_unit, ether_sprintf((u_char *)es->es_addr));
11553897Smckusick ifp->if_unit = ii->ii_unit;
11653897Smckusick ifp->if_name = "en";
11753897Smckusick ifp->if_mtu = ETHERMTU;
11853897Smckusick ifp->if_init = eninit;
11953897Smckusick ifp->if_ioctl = enioctl;
12053897Smckusick ifp->if_output = ether_output;
12153897Smckusick #ifdef NOTDEF /* KU:XXX if_reset is obsolete */
12253897Smckusick ifp->if_reset = enreset;
12353897Smckusick #endif
12453897Smckusick ifp->if_start = enstart;
12554517Sutashiro ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
12653897Smckusick #if NBPFILTER > 0
12754517Sutashiro bpfattach(&es->es_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
12853897Smckusick #endif
12953897Smckusick if_attach(ifp);
13053897Smckusick }
13153897Smckusick
13253897Smckusick /*
13353897Smckusick * Reset of interface after IOP reset.
13453897Smckusick */
enreset(unit)13553897Smckusick enreset(unit)
13653897Smckusick int unit;
13753897Smckusick {
13853897Smckusick register struct iop_device *ii;
13953897Smckusick
14053897Smckusick if (unit >= NEN || (ii = eninfo[unit]) == 0 || ii->ii_alive == 0)
14153897Smckusick return;
14253897Smckusick printf(" en%d", unit);
14353897Smckusick en_softc[unit].es_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
14453897Smckusick en_softc[unit].es_flags &= ~ENF_RUNNING;
14553897Smckusick eninit(unit);
14653897Smckusick }
14753897Smckusick
14853897Smckusick /*
14953897Smckusick * Initialization of interface; clear recorded pending
15053897Smckusick * operations, and reinitialize IOP usage.
15153897Smckusick */
eninit(unit)15253897Smckusick eninit(unit)
15353897Smckusick int unit;
15453897Smckusick {
15553897Smckusick register struct en_softc *es = &en_softc[unit];
15653897Smckusick register struct ifnet *ifp = &es->es_if;
15753897Smckusick int s;
15853897Smckusick
15953897Smckusick /* not yet, if address still unknown */
16053897Smckusick if (ifp->if_addrlist == (struct ifaddr *)0)
16153897Smckusick return;
16253897Smckusick if (es->es_flags & ENF_RUNNING)
16353897Smckusick return;
16453897Smckusick if ((ifp->if_flags & IFF_RUNNING) == 0) {
16553897Smckusick if (if_newsinit(&es->es_ifnews,
16653897Smckusick sizeof (struct en_rheader), (int)btoc(ETHERMTU)) == 0) {
16753897Smckusick printf("en%d: can't initialize\n", unit);
16853897Smckusick es->es_if.if_flags &= ~IFF_UP;
16953897Smckusick return;
17053897Smckusick }
17153897Smckusick ifp->if_watchdog = enwatch;
17253897Smckusick es->es_interval = ENWATCHINTERVAL;
17353897Smckusick ifp->if_timer = es->es_interval;
17453897Smckusick s = splimp();
17553897Smckusick en_init(unit);
17653897Smckusick splx(s);
17753897Smckusick }
17853897Smckusick es->es_if.if_flags |= IFF_RUNNING|IFF_NOTRAILERS;
17953897Smckusick es->es_flags |= ENF_RUNNING;
18053897Smckusick }
18153897Smckusick
18253897Smckusick /*
18353897Smckusick * Start output on interface.
18453897Smckusick * Get another datagram to send off of the interface queue,
18553897Smckusick * and map it to the interface before starting the output.
18653897Smckusick */
enstart(ifp)18753897Smckusick enstart(ifp)
18853897Smckusick register struct ifnet *ifp;
18953897Smckusick {
19053897Smckusick int unit = ifp->if_unit, len;
19153897Smckusick register struct en_softc *es = &en_softc[unit];
19253897Smckusick register struct mbuf *m;
19354584Sutashiro int s;
19453897Smckusick
19553897Smckusick IF_DEQUEUE(&es->es_if.if_snd, m);
19653897Smckusick if (m == 0)
19753897Smckusick return(0);
19853897Smckusick #ifdef CPU_SINGLE
19953897Smckusick es->es_ifnews.ifn_waddr = (caddr_t)get_xmit_buffer(unit);
20053897Smckusick #endif
20153897Smckusick len = if_wnewsput(&es->es_ifnews, m);
20253897Smckusick /*
20353897Smckusick * Ensure minimum packet length.
20453897Smckusick * This makes the safe assumtion that there are no virtual holes
20553897Smckusick * after the data.
20653897Smckusick * For security, it might be wise to zero out the added bytes,
20753897Smckusick * but we're mainly interested in speed at the moment.
20853897Smckusick */
20953897Smckusick if (len - sizeof(struct ether_header) < ETHERMIN)
21053897Smckusick len = ETHERMIN + sizeof(struct ether_header);
21154584Sutashiro s = splclock(); /* KU:XXX should be gone */
21253897Smckusick en_start(unit, len);
21354584Sutashiro es->es_if.if_flags |= IFF_OACTIVE;
21454584Sutashiro (void) splx(s); /* KU:XXX */
21553897Smckusick #if NBPFILTER > 0
21653897Smckusick /*
21753897Smckusick * If bpf is listening on this interface, let it
21853897Smckusick * see the packet before we commit it to the wire.
21953897Smckusick */
22054517Sutashiro if (es->es_bpf) {
22153897Smckusick #ifdef CPU_SINGLE
22254517Sutashiro bpf_tap(es->es_bpf, es->es_ifnews.ifn_waddr, len);
22353897Smckusick #else
22454517Sutashiro bpf_mtap(es->es_bpf, m);
22553897Smckusick #endif
22653897Smckusick }
22753897Smckusick #endif /* NBPFILTER > 0 */
22853897Smckusick return(0);
22953897Smckusick }
23053897Smckusick
23153897Smckusick /*
23253897Smckusick * Transmit done interrupt.
23353897Smckusick */
_enxint(unit,error,collision)23453897Smckusick _enxint(unit, error, collision)
23553897Smckusick int unit;
23653897Smckusick int error, collision;
23753897Smckusick {
23853897Smckusick register struct en_softc *es = &en_softc[unit];
23953897Smckusick
24053897Smckusick #ifdef notyet /* KU:XXX */
24153897Smckusick intrcnt[INTR_ETHER0 + unit]++;
24253897Smckusick #endif
24353897Smckusick if ((es->es_if.if_flags & IFF_OACTIVE) == 0) {
24453897Smckusick printf("en%d: stray xmit interrupt\n", unit);
24553897Smckusick return;
24653897Smckusick } else {
24753897Smckusick es->es_if.if_flags &= ~IFF_OACTIVE;
24853897Smckusick es->es_if.if_opackets++;
24953897Smckusick }
25058612Sutashiro if (error)
25153897Smckusick es->es_if.if_oerrors++;
25258612Sutashiro if (collision)
25353897Smckusick es->es_if.if_collisions++;
25453897Smckusick enstart(&es->es_if);
25553897Smckusick }
25653897Smckusick
25753897Smckusick /*
25853897Smckusick * Ethernet interface receiver interrupt.
25953897Smckusick * If input error just drop packet.
26053897Smckusick * Otherwise purge input buffered data path and examine
26153897Smckusick * packet to determine type. If can't determine length
26253897Smckusick * from type, then have to drop packet. Othewise decapsulate
26353897Smckusick * packet based on type and pass to type specific higher-level
26453897Smckusick * input routine.
26553897Smckusick */
_enrint(unit,len)26653897Smckusick _enrint(unit, len)
26753897Smckusick int unit;
26853897Smckusick register int len;
26953897Smckusick {
27053897Smckusick register struct en_softc *es = &en_softc[unit];
27153897Smckusick register struct en_rheader *en;
27253897Smckusick struct mbuf *m;
27353897Smckusick int off, resid, s;
27454522Sutashiro int type;
27553897Smckusick register struct ensw *esp;
27653897Smckusick extern struct mbuf *if_rnewsget();
27754522Sutashiro #if defined(mips) && defined(CPU_SINGLE)
27854522Sutashiro int bxcopy();
27954522Sutashiro #endif
28053897Smckusick
28153897Smckusick #ifdef notyet /* KU:XXX */
28253897Smckusick intrcnt[INTR_ETHER0 + unit]++;
28353897Smckusick #endif
28453897Smckusick es->es_if.if_ipackets++;
28553897Smckusick if ((es->es_flags & ENF_RUNNING) == 0)
28653897Smckusick return;
28753897Smckusick en = (struct en_rheader *)(es->es_ifnews.ifn_raddr);
28853897Smckusick if (len < ETHERMIN || len > ETHERMTU) {
28953897Smckusick es->es_if.if_ierrors++;
29053897Smckusick return;
29153897Smckusick }
29253897Smckusick #if NBPFILTER > 0
29353897Smckusick /*
29453897Smckusick * Check if there's a bpf filter listening on this interface.
29553897Smckusick * If so, hand off the raw packet to enet.
29653897Smckusick */
29754517Sutashiro if (es->es_bpf) {
29854517Sutashiro bpf_tap(es->es_bpf, es->es_ifnews.ifn_raddr,
29953897Smckusick len + sizeof(struct en_rheader));
30053897Smckusick /*
30153897Smckusick * Note that the interface cannot be in promiscuous mode if
30253897Smckusick * there are no bpf listeners. And if we are in promiscuous
30353897Smckusick * mode, we have to check if this packet is really ours.
30453897Smckusick *
30553897Smckusick * XXX This test does not support multicasts.
30653897Smckusick */
30753897Smckusick if ((es->es_if.if_flags & IFF_PROMISC)
30853897Smckusick && bcmp(en->enr_dhost, es->es_addr,
30953897Smckusick sizeof(en->enr_dhost)) != 0
31053897Smckusick && bcmp(en->enr_dhost, etherbroadcastaddr,
31153897Smckusick sizeof(en->enr_dhost)) != 0)
31253897Smckusick return;
31353897Smckusick }
31453897Smckusick #endif /* NBPFILTER > 0 */
31553897Smckusick /*
31653897Smckusick * Deal with trailer protocol: if type is trailer type
31753897Smckusick * get true type from first 16-bit word past data.
31853897Smckusick * Remember that type was trailer by setting off.
31953897Smckusick */
32053897Smckusick en->enr_type = ntohs((u_short)en->enr_type);
32153897Smckusick #define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off))))
32253897Smckusick if (en->enr_type >= ETHERTYPE_TRAIL &&
32353897Smckusick en->enr_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
32453897Smckusick off = (en->enr_type - ETHERTYPE_TRAIL) * 512;
32553897Smckusick if (off >= ETHERMTU)
32653897Smckusick return;
32753897Smckusick en->enr_type = ntohs(*endataaddr(en, off, u_short *));
32853897Smckusick resid = ntohs(*(endataaddr(en, off+2, u_short *)));
32953897Smckusick if (off + resid > len)
33053897Smckusick return;
33153897Smckusick len = off + resid;
33253897Smckusick } else
33353897Smckusick off = 0;
33453897Smckusick /*
33553897Smckusick * Pull packet off interface. Off is nonzero if packet
33653897Smckusick * has trailing header; m_devget will then force this header
33753897Smckusick * information to be at the front, but we still have to drop
33853897Smckusick * the type and length which are at the front of any trailer data.
33953897Smckusick * KU:XXX really?
34053897Smckusick */
34153897Smckusick type = en->enr_type;
34254522Sutashiro #if defined(mips) && defined(CPU_SINGLE)
34354522Sutashiro m = m_devget((char *)(en + 1), len, off, &es->es_if, bxcopy);
34454522Sutashiro #else
34553897Smckusick m = m_devget((char *)(en + 1), len, off, &es->es_if, 0);
34654522Sutashiro #endif
34753897Smckusick if (m == 0)
34853897Smckusick return;
34953897Smckusick ether_input(&es->es_if, (struct ether_header *) en->enr_dhost, m);
35053897Smckusick }
35153897Smckusick
35253897Smckusick /*
35353897Smckusick * Watchdog routine, request statistics from board.
35453897Smckusick */
enwatch(unit)35553897Smckusick enwatch(unit)
35653897Smckusick int unit;
35753897Smckusick {
35853897Smckusick register struct en_softc *es = &en_softc[unit];
35953897Smckusick register struct ifnet *ifp = &es->es_if;
36053897Smckusick
36153897Smckusick ifp->if_timer = es->es_interval;
36253897Smckusick }
36353897Smckusick
36453897Smckusick /*
36553897Smckusick * Process an ioctl request.
36653897Smckusick */
enioctl(ifp,cmd,data)36753897Smckusick enioctl(ifp, cmd, data)
36853897Smckusick register struct ifnet *ifp;
36953897Smckusick int cmd;
37053897Smckusick caddr_t data;
37153897Smckusick {
37253897Smckusick register struct ifaddr *ifa = (struct ifaddr *)data;
37353897Smckusick register struct en_softc *es = &en_softc[ifp->if_unit];
37453897Smckusick register struct ensw *esp;
37553897Smckusick register int family;
37653897Smckusick int s = splimp(), error = 0;
37753897Smckusick
37853897Smckusick switch (cmd) {
37953897Smckusick
38053897Smckusick case SIOCSIFADDR:
38153897Smckusick ifp->if_flags |= IFF_UP;
38253897Smckusick eninit(ifp->if_unit);
38353897Smckusick switch (ifa->ifa_addr->sa_family) {
38453897Smckusick #ifdef INET
38553897Smckusick case AF_INET:
38653897Smckusick ((struct arpcom *)ifp)->ac_ipaddr =
38753897Smckusick IA_SIN(ifa)->sin_addr;
38853897Smckusick arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
38953897Smckusick break;
39053897Smckusick #endif
39153897Smckusick }
39253897Smckusick break;
39353897Smckusick
39453897Smckusick case SIOCSIFFLAGS:
39553897Smckusick if ((ifp->if_flags & IFF_UP) == 0 &&
39653897Smckusick es->es_flags & ENF_RUNNING) {
39753897Smckusick es->es_flags &= ~ENF_RUNNING;
39853897Smckusick } else if (ifp->if_flags & IFF_UP &&
39953897Smckusick (es->es_flags & ENF_RUNNING) == 0)
40053897Smckusick eninit(ifp->if_unit);
40153897Smckusick #if NBPFILTER > 0
40253897Smckusick else if (ifp->if_flags & IFF_UP &&
40353897Smckusick (ifp->if_flags & IFF_RUNNING) == 0) {
40453897Smckusick en_prom_mode(ifp->if_unit,
40553897Smckusick ifp->if_flags & IFF_PROMISC);
40653897Smckusick ifp->if_flags |= IFF_RUNNING;
40753897Smckusick }
40853897Smckusick #endif
40953897Smckusick break;
41053897Smckusick
41153897Smckusick default:
41253897Smckusick error = EINVAL;
41353897Smckusick }
41453897Smckusick splx(s);
41553897Smckusick return (error);
41653897Smckusick }
41753897Smckusick
41853897Smckusick /*
41953897Smckusick * set ethernet address for unit
42053897Smckusick */
ensetaddr(physaddr,unit)42153897Smckusick ensetaddr(physaddr, unit)
42253897Smckusick u_char *physaddr;
42353897Smckusick int unit;
42453897Smckusick {
42553897Smckusick register struct en_softc *es = &en_softc[unit];
42653897Smckusick
42753897Smckusick if (!(es->es_flags & ENF_RUNNING))
42853897Smckusick return;
42953897Smckusick
43053897Smckusick bcopy((caddr_t)physaddr, (caddr_t)es->es_addr, sizeof es->es_addr);
43153897Smckusick es->es_flags &= ~ENF_RUNNING;
43253897Smckusick es->es_flags |= ENF_SETADDR;
43353897Smckusick eninit(unit);
43453897Smckusick }
43553897Smckusick
43653897Smckusick /*
43753897Smckusick * Machine dependent functions
43853897Smckusick *
43953897Smckusick * en_probe();
44053897Smckusick * en_attach();
44153897Smckusick * en_init();
44253897Smckusick * enxint();
44353897Smckusick * enrint();
44453897Smckusick * en_prom_mode()
44553897Smckusick */
44653897Smckusick #ifdef CPU_SINGLE
44757180Sutashiro #include <machine/cpu.h>
44853897Smckusick
44953897Smckusick en_probe(hi)
45053897Smckusick struct hb_device *hi;
45153897Smckusick {
45253897Smckusick
45353897Smckusick return (lance_probe(hi->hi_unit));
45453897Smckusick }
45553897Smckusick
en_attach(unit)45653897Smckusick en_attach(unit)
45753897Smckusick int unit;
45853897Smckusick {
45953897Smckusick register struct en_softc *es = &en_softc[unit];
46053897Smckusick register u_char *p;
46153897Smckusick register int i;
46253897Smckusick extern lance_intr();
46353897Smckusick
46453897Smckusick #if !defined(news700) && !defined(mips)
46553897Smckusick register_hb_intr4(lance_intr, unit, eninfo[unit]->ii_intr);
46653897Smckusick #endif
46753897Smckusick if (lance_open(unit) < 0)
46853897Smckusick printf("lance initialize error\n");
46953897Smckusick lance_get_addr(unit, (caddr_t)es->es_addr);
47053897Smckusick }
47153897Smckusick
en_init(unit)47253897Smckusick en_init(unit)
47353897Smckusick int unit;
47453897Smckusick {
47553897Smckusick
47653897Smckusick }
47753897Smckusick
en_start(unit,len)47853897Smckusick en_start(unit, len)
47953897Smckusick int unit;
48053897Smckusick int len;
48153897Smckusick {
48253897Smckusick
48353897Smckusick lance_transmit(unit, len);
48453897Smckusick }
48553897Smckusick
enxint(unit)48653897Smckusick enxint(unit)
48753897Smckusick register int unit;
48853897Smckusick {
48953897Smckusick
49053897Smckusick _enxint(unit, lance_xmit_error(unit), lance_collision(unit));
49153897Smckusick }
49253897Smckusick
enrint(unit)49353897Smckusick enrint(unit)
49453897Smckusick register int unit;
49553897Smckusick {
49653897Smckusick register struct en_softc *es = &en_softc[unit];
49753897Smckusick caddr_t get_recv_buffer();
49853897Smckusick
49953897Smckusick while (es->es_ifnews.ifn_raddr = get_recv_buffer(unit)) {
50053897Smckusick _enrint(unit,
50153897Smckusick get_recv_length(unit) - sizeof(struct en_rheader));
50253897Smckusick free_recv_buffer(unit);
50353897Smckusick }
50453897Smckusick }
50553897Smckusick
en_prom_mode(unit,mode)50653897Smckusick en_prom_mode(unit, mode)
50753897Smckusick int unit, mode;
50853897Smckusick {
50953897Smckusick
51053897Smckusick lance_prom_mode(unit, mode);
51153897Smckusick }
51253897Smckusick #endif /* CPU_SINGLE */
51353897Smckusick
51453897Smckusick #ifdef IPC_MRX
51553897Smckusick #include "../ipc/newsipc.h"
51653897Smckusick #include "../mrx/h/lancereg.h"
51753897Smckusick #include "../mrx/h/lance.h"
51853897Smckusick
51953897Smckusick int port_enxmit[NEN];
52053897Smckusick int port_enrecv[NEN];
52153897Smckusick int port_enctrl[NEN];
52253897Smckusick int port_enxmit_iop[NEN];
52353897Smckusick int port_enrecv_iop[NEN];
52453897Smckusick int port_enctrl_iop[NEN];
52553897Smckusick
en_probe(ii)52653897Smckusick en_probe(ii)
52753897Smckusick register struct iop_device *ii;
52853897Smckusick {
52953897Smckusick int unit = ii->ii_unit;
53053897Smckusick int lance_func, *reply;
53153897Smckusick char name[32];
53253897Smckusick extern char *make_name();
53353897Smckusick
53453897Smckusick if (port_enrecv[unit] == 0) {
53553897Smckusick
53653897Smckusick #define PT_CREATE(buf, name, unit, func) \
53753897Smckusick port_create(make_name(buf, name, unit), func, unit)
53853897Smckusick #define OB_QUERY(buf, name, unit) \
53953897Smckusick object_query(make_name(buf, name, unit))
54053897Smckusick
54153897Smckusick make_name(name, "@enrecvX", unit);
54253897Smckusick port_enrecv[unit] = PT_CREATE(name, "@enrecvX", unit, enrint);
54353897Smckusick port_enxmit[unit] = PT_CREATE(name, "@enxmitX", unit, enxint);
54453897Smckusick port_enctrl[unit] = PT_CREATE(name, "@enctrlX", unit, NULL);
54553897Smckusick /* use NULL action port */
54653897Smckusick port_enrecv_iop[unit] = OB_QUERY(name, "lance_inputX", unit);
54753897Smckusick port_enxmit_iop[unit] = OB_QUERY(name, "lance_outputX", unit);
54853897Smckusick port_enctrl_iop[unit] = OB_QUERY(name, "lance_ctrlX", unit);
54953897Smckusick }
55053897Smckusick if (port_enctrl_iop[unit] < 0)
55153897Smckusick goto bad;
55253897Smckusick lance_func = EN_START;
55353897Smckusick msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func,
55453897Smckusick sizeof(lance_func), 0);
55553897Smckusick msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0);
55653897Smckusick if (*reply < 0)
55753897Smckusick goto bad;
55853897Smckusick lance_func = EN_STOP;
55953897Smckusick msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func,
56053897Smckusick sizeof(lance_func), 0);
56153897Smckusick msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0);
56253897Smckusick return (1);
56353897Smckusick bad:
56453897Smckusick return (0);
56553897Smckusick }
56653897Smckusick
en_attach(unit)56753897Smckusick en_attach(unit)
56853897Smckusick int unit;
56953897Smckusick {
57053897Smckusick register struct en_softc *es = &en_softc[unit];
57153897Smckusick int lance_func;
57253897Smckusick struct ether_addr *ether_addr;
57353897Smckusick
57453897Smckusick lance_func = EN_GETADDR;
57553897Smckusick msg_send(port_enctrl_iop[unit], port_enctrl[unit], &lance_func,
57653897Smckusick sizeof(lance_func), 0);
57753897Smckusick msg_recv(port_enctrl[unit], NULL, ðer_addr, NULL, 0);
57853897Smckusick bcopy(ether_addr, es->es_addr, sizeof(struct ether_addr));
57953897Smckusick msg_free(port_enctrl[unit]);
58053897Smckusick }
58153897Smckusick
en_init(unit)58253897Smckusick en_init(unit)
58353897Smckusick int unit;
58453897Smckusick {
58553897Smckusick register struct en_softc *es = &en_softc[unit];
58653897Smckusick register int port;
58753897Smckusick struct lance_ctrl_req req;
58853897Smckusick int *reply;
58953897Smckusick
59053897Smckusick req.lance_func = EN_SETXMITBUF;
59153897Smckusick mapsetup(&req.lance_map, es->es_ifnews.ifn_waddr,
59253897Smckusick ETHERMTU + sizeof(struct en_rheader));
59353897Smckusick msg_send(port_enctrl_iop[unit], port_enctrl[unit],
59453897Smckusick &req, sizeof(req), 0);
59553897Smckusick msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0);
59653897Smckusick
59753897Smckusick req.lance_func = EN_START;
59853897Smckusick msg_send(port_enctrl_iop[unit], port_enctrl[unit],
59953897Smckusick &req, sizeof(req), 0);
60053897Smckusick msg_recv(port_enctrl[unit], NULL, &reply, NULL, 0);
60153897Smckusick msg_free(port_enctrl[unit]);
60253897Smckusick
60353897Smckusick msg_send(port_enrecv_iop[unit], port_enrecv[unit],
60453897Smckusick es->es_ifnews.ifn_raddr,
60553897Smckusick ETHERMTU + sizeof(struct en_rheader), MSG_INDIRECT);
60653897Smckusick }
60753897Smckusick
en_start(unit,len)60853897Smckusick en_start(unit, len)
60953897Smckusick int unit;
61053897Smckusick int len;
61153897Smckusick {
61253897Smckusick
61353897Smckusick msg_send(port_enxmit_iop[unit], port_enxmit[unit], &len, sizeof(len), 0);
61453897Smckusick }
61553897Smckusick
enxint(unit)61653897Smckusick enxint(unit)
61753897Smckusick register int unit;
61853897Smckusick {
61953897Smckusick int *len;
62053897Smckusick struct en_softc *es = &en_softc[unit];
62153897Smckusick
62253897Smckusick if (msg_recv(port_enxmit[unit], NULL, &len, NULL, 0) < 0) {
62353897Smckusick printf("stray enxint\n");
62453897Smckusick return;
62553897Smckusick }
62653897Smckusick if (es->es_ifnews.ifn_mbuf)
62753897Smckusick m_freem(es->es_ifnews.ifn_mbuf);
62853897Smckusick _enxint(unit, *len < 0, *len & 0x10000);
62953897Smckusick }
63053897Smckusick
enrint(unit)63153897Smckusick enrint(unit)
63253897Smckusick int unit;
63353897Smckusick {
63453897Smckusick int len;
63553897Smckusick int *reply;
63653897Smckusick
63753897Smckusick if (msg_recv(port_enrecv[unit], NULL, &reply, NULL, 0) < 0) {
63853897Smckusick printf("stray enrint\n");
63953897Smckusick return;
64053897Smckusick }
64153897Smckusick len = *reply - sizeof(struct en_rheader);
64253897Smckusick msg_free(port_enrecv[unit]);
64353897Smckusick #ifdef mips
64453897Smckusick /*
64553897Smckusick * cache flush address must aligned long word boundary.
64653897Smckusick * so, add 3 for sanity.
64753897Smckusick */
64853897Smckusick clean_k2dcache((int)en_softc[unit].es_ifnews.ifn_raddr & ~03,
64953897Smckusick len + sizeof (struct en_rheader) + 3);
65053897Smckusick #endif
65153897Smckusick _enrint(unit, len);
65253897Smckusick msg_send(port_enrecv_iop[unit], port_enrecv[unit],
65353897Smckusick en_softc[unit].es_ifnews.ifn_raddr,
65453897Smckusick ETHERMTU + sizeof(struct en_rheader), MSG_INDIRECT);
65553897Smckusick }
65653897Smckusick
en_prom_mode(unit,mode)65753897Smckusick en_prom_mode(unit, mode)
65853897Smckusick int unit, mode;
65953897Smckusick {
66053897Smckusick static int port;
66153897Smckusick struct lance_ctrl_req req;
66253897Smckusick extern int port_enctrl_iop[];
66353897Smckusick
66453897Smckusick req.lance_func = EN_PROMMODE;
66553897Smckusick req.lance_mode = mode;
66653897Smckusick msg_send(port_enctrl_iop[unit], 0, &req, sizeof(req), 0);
66753897Smckusick }
66853897Smckusick #endif /* IPC_MRX */
66953897Smckusick #endif /* NEN > 0 */
670