* Copyright (C) 1990 W. Jolitz
* @(#)if_ne.c 1.2 (Berkeley) %G%
* Parts inspired from Tim Tucker's if_wd driver for the wd8003,
* insight on the ne2000 gained from Robert Clements PC/FTP driver.
#include "../net/netisr.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/in_var.h"
#include "../netinet/ip.h"
#include "../netinet/if_ether.h"
#include "../netns/ns_if.h"
#include "machine/isa/device.h"
int neprobe(), neattach(), neintr();
int neinit(), neoutput(), neioctl();
struct isa_driver nedriver
= {
* Ethernet software status per interface.
* Each interface is referenced by a network interface structure,
* ns_if, which the routing code uses to locate the interface.
* This structure contains the output queue for the interface, its address, ...
struct arpcom ns_ac
; /* Ethernet common part */
#define ns_if ns_ac.ac_if /* network-visible interface */
#define ns_addr ns_ac.ac_enaddr /* hardware Ethernet address */
#define DSF_LOCK 1 /* block re-entering enstart */
int ns_ba
; /* byte addr in buffer ram of inc pkt */
int ns_cur
; /* current page being filled */
struct prhdr ns_ph
; /* hardware header of incoming packet*/
struct ether_header ns_eh
; /* header of incoming packet */
u_char ns_pb
[2048 /*ETHERMTU+sizeof(long)*/];
#define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + 64)
register struct ne_softc
*ns
= &ne_softc
[0];
outb(nec
+ds_cmd
, DSCM_STOP
|DSCM_NODMA
);
while ((inb(nec
+ds0_isr
)&DSIS_RESET
) == 0 && i
-- > 0) nulldev();
/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
outb(nec
+ds0_dcr
, DSDC_WTS
|DSDC_BMS
|DSDC_FT1
);
outb(nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_STOP
);
/* check cmd reg and fail if not right */
if ((i
=inb(nec
+ds_cmd
)) != (DSCM_NODMA
|DSCM_PG0
|DSCM_STOP
))
outb(nec
+ds0_rcr
, DSRC_MON
);
outb(nec
+ds0_pstart
, RBUF
/DS_PGSIZE
);
outb(nec
+ds0_pstop
, RBUFEND
/DS_PGSIZE
);
outb(nec
+ds0_bnry
, RBUFEND
/DS_PGSIZE
);
outb(nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG1
|DSCM_STOP
);
outb(nec
+ds1_curr
, RBUF
/DS_PGSIZE
);
outb(nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_STOP
);
fetchrom (boarddata
, 0, sizeof(boarddata
));
for (i = 0; i < 0xfff0; i+=4) {
if (pat == 0xa55a+i*37) {
if (rom) { rom=0; printf(" %x", i); }
if (!rom) { rom=1; printf("..%x ", i); }
/* extract board address */
for(i
=0; i
< 6; i
++) ns
->ns_addr
[i
] = boarddata
[i
];
fetchrom (up
, ad
, len
) u_short
*up
; {
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_STOP
);
outb (nec
+ds0_isr
, DSIS_RDC
);
outb (nec
+ds0_rbcr0
, len
&0xff);
outb (nec
+ds0_rbcr1
, (len
>>8)&0xff);
outb (nec
+ds0_rsar0
, ad
&0xff);
outb (nec
+ds0_rsar1
, (ad
>>8)&0xff);
outb (nec
+ds_cmd
, DSCM_RREAD
|DSCM_PG0
|DSCM_START
);
insw (nec
+ne_data
, up
, len
/2);
while ((inb (nec
+ds0_isr
) & DSIS_RDC
) == 0) pausestr("fetchrom",0);
outb (nec
+ds0_isr
, DSIS_RDC
);
fetchram (up
, ad
, len
) caddr_t up
; {
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_START
);
outb (nec
+ds0_isr
, DSIS_RDC
);
outb (nec
+ds0_rbcr0
, len
&0xff);
outb (nec
+ds0_rbcr1
, (len
>>8)&0xff);
outb (nec
+ds0_rsar0
, ad
&0xff);
outb (nec
+ds0_rsar1
, (ad
>>8)&0xff);
outb (nec
+ds_cmd
, DSCM_RREAD
|DSCM_PG0
|DSCM_START
);
insw (nec
+ne_data
, up
, len
/2);
while ((inb (nec
+ds0_isr
) & DSIS_RDC
) == 0) pausestr("fetchram",0);
outb (nec
+ds0_isr
, DSIS_RDC
);
putram (up
, ad
, len
) caddr_t up
; {
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_START
);
outb (nec
+ds0_isr
, DSIS_RDC
);
outb (nec
+ds0_rbcr0
, len
&0xff);
outb (nec
+ds0_rbcr1
, (len
>>8)&0xff);
outb (nec
+ds0_rsar0
, ad
&0xff);
outb (nec
+ds0_rsar1
, (ad
>>8)&0xff);
outb (nec
+ds_cmd
, DSCM_RWRITE
|DSCM_PG0
|DSCM_START
);
outsw (nec
+ne_data
, up
, len
/2);
while ((inb (nec
+ds0_isr
) & DSIS_RDC
) == 0)
if(pausestr("putram",0)<0) break;
outb (nec
+ds0_isr
, DSIS_RDC
);
printf("ne%d: reset\n", unit
);
ne_softc
[unit
].ns_flags
&= ~DSF_LOCK
;
* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready
* to accept packets. We get the ethernet address here.
register struct ne_softc
*ns
= &ne_softc
[unit
];
register struct ifnet
*ifp
= &ns
->ns_if
;
ifp
->if_name
= nedriver
.name
;
printf (" physical address %s", ether_sprintf(ns
->ns_addr
)) ;
ifp
->if_flags
= IFF_BROADCAST
|IFF_NOTRAILERS
;
ifp
->if_output
= neoutput
;
* Initialization of interface; set up initialization block
* and transmit/receive descriptor rings.
register struct ne_softc
*ns
= &ne_softc
[unit
];
struct ifnet
*ifp
= &ns
->ns_if
;
if (ifp
->if_addrlist
== (struct ifaddr
*)0) return;
if (ifp
->if_flags
& IFF_RUNNING
) return;
/* set physical address on ethernet */
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG1
|DSCM_STOP
);
for (i
=0 ; i
< 6 ; i
++) outb(nec
+ds1_par0
+i
,ns
->ns_addr
[i
]);
/* clr logical address hash filter for now */
for (i
=0 ; i
< 8 ; i
++) outb(nec
+ds1_mar0
+i
,0xff);
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_STOP
);
outb (nec
+ds0_isr
, 0xff);
/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
outb(nec
+ds0_dcr
, DSDC_WTS
|DSDC_BMS
|DSDC_FT1
);
outb (nec
+ds0_rcr
, DSRC_MON
);
outb(nec
+ds0_pstart
, RBUF
/DS_PGSIZE
);
outb(nec
+ds0_pstop
, RBUFEND
/DS_PGSIZE
);
outb(nec
+ds0_bnry
, RBUFEND
/DS_PGSIZE
);
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG1
|DSCM_STOP
);
outb(nec
+ds1_curr
, RBUF
/DS_PGSIZE
);
ns
->ns_cur
= RBUF
/DS_PGSIZE
;
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_START
);
outb (nec
+ds0_rcr
, DSRC_AB
);
outb(nec
+ds0_dcr
, DSDC_WTS
|DSDC_BMS
|DSDC_FT1
);
outb (nec
+ds0_imr
, 0xff);
ns
->ns_if
.if_flags
|= IFF_RUNNING
;
ns
->ns_oactive
= 0; ns
->ns_mask
= ~0;
if (ns
->ns_if
.if_snd
.ifq_head
) nestart(ns
);
* Setup output on interface.
* Get another datagram to send off of the interface queue,
* and map it to the interface before starting the output.
* called only at splimp or interrupt level.
register struct ne_softc
*ns
;
* The DS8390 has only one transmit buffer, if it is busy we
* must wait until the transmit interrupt completes.
outb(nec
+ds_cmd
,DSCM_NODMA
|DSCM_START
);
if (ns
->ns_flags
& DSF_LOCK
)
if (inb(nec
+ds_cmd
) & DSCM_TRANS
)
if ((ns
->ns_if
.if_flags
& IFF_RUNNING
) == 0)
IF_DEQUEUE(&ns
->ns_if
.if_snd
, m
);
* Copy the mbuf chain into the transmit buffer
ns
->ns_flags
|= DSF_LOCK
; /* prevent entering nestart */
buffer
= TBUF
; len
= i
= 0;
for (m0
= m
; m
!= 0; m
= m
->m_next
) {
putram(mtod(m
, caddr_t
), buffer
, m
->m_len
);
/*for(j=0; i < len;i++,j++) puthex(mtod(m,u_char *)[j]);
* If this was a broadcast packet loop it
* back because the hardware can't hear its own
/*if (bcmp((caddr_t)(mtod(m0, struct ether_header *)->ether_dhost),
(caddr_t)etherbroadcastaddr,
sizeof(etherbroadcastaddr)) == 0) {
* Init transmit length registers, and set transmit start flag.
if(len
< 0 || len
> 1536)
pg("T Bogus Length %d\n", len
);
dprintf(DEXPAND
,"snd %d ", len
);
outb(nec
+ds0_tbcr0
,len
&0xff);
outb(nec
+ds0_tbcr1
,(len
>>8)&0xff);
outb(nec
+ds0_tpsr
, TBUF
/DS_PGSIZE
);
outb(nec
+ds_cmd
, DSCM_TRANS
|DSCM_NODMA
|DSCM_START
);
#define succ(n) (((n)+1 > RBUFEND/DS_PGSIZE) ? RBUF/DS_PGSIZE : (n)+1)
#define pred(n) (((n)-1 < RBUF/DS_PGSIZE) ? RBUFEND/DS_PGSIZE : (n)-1)
register struct ne_softc
*ns
= &ne_softc
[0];
/* save cmd, clear interrupt */
dprintf(DEXPAND
,"|ppl %x isr %x ", ppl
, isr
);
outb(nec
+ds_cmd
,DSCM_NODMA
|DSCM_START
);
if (isr
& (/*DSIS_RXE|*/DSIS_TXE
|DSIS_ROVRN
))
log(LOG_ERR
, "ne%d: error: isr %x\n", ns
-ne_softc
, isr
/*, DSIS_BITS*/);
outb(nec
+ds_cmd
, DSCM_STOP
|DSCM_NODMA
);
outb(nec
+ds_cmd
, DSCM_STOP
|DSCM_NODMA
|DSCM_PG1
);
pend
= inb(nec
+ds1_curr
);
outb(nec
+ds_cmd
, DSCM_STOP
|DSCM_NODMA
|DSCM_PG0
);
lastfree
= inb(nec
+ds0_bnry
);
printf("Cur %x pend %x lastfree %x ", ns
->ns_cur
, pend
, lastfree
);
if (lastfree
> RBUFEND
/DS_PGSIZE
)
lastfree
= RBUF
/DS_PGSIZE
;
/* something in the buffer? */
if (pend
!= succ(lastfree
)) {
fetchram(&ns
->ns_ph
,ns
->ns_cur
*DS_PGSIZE
, sizeof(ns
->ns_ph
));
ns
->ns_ba
= ns
->ns_cur
*DS_PGSIZE
+sizeof(ns
->ns_ph
);
if (ns
->ns_ph
.pr_status
& DSRS_RPC
)
nxt
= ns
->ns_ph
.pr_nxtpg
;
if ( nxt
>= RBUF
/DS_PGSIZE
&& nxt
<= RBUFEND
/DS_PGSIZE
&& nxt
<= pend
)
else ns
->ns_cur
= nxt
= pend
;
outb(nec
+ds0_bnry
, lastfree
);
} else ns
->ns_cur
= pend
;
outb(nec
+ds0_tcr
,DSTC_LB0
);
outb(nec
+ds0_rcr
, DSRC_MON
);
outb(nec
+ds_cmd
, DSCM_START
|DSCM_NODMA
);
outb (nec
+ds0_rcr
, DSRC_AB
);
/* need to read these registers to clear status */
(void) inb(nec
+ ds0_rsr
);
if (isr
& (DSIS_RX
|DSIS_RXE
)) {
outb(nec
+ds_cmd
, DSCM_START
|DSCM_NODMA
|DSCM_PG1
);
pend
= inb(nec
+ds1_curr
);
outb(nec
+ds_cmd
, DSCM_START
|DSCM_NODMA
|DSCM_PG0
);
lastfree
= inb(nec
+ds0_bnry
);
dprintf(DEXPAND
,"cur %x pnd %x lfr %x ", ns
->ns_cur
, pend
, lastfree
);
if (lastfree
> RBUFEND
/DS_PGSIZE
)
lastfree
= RBUF
/DS_PGSIZE
;
/* something in the buffer? */
if (pend
!= succ(lastfree
)) {
fetchram(&ns
->ns_ph
,ns
->ns_cur
*DS_PGSIZE
, sizeof(ns
->ns_ph
));
ns
->ns_ba
= ns
->ns_cur
*DS_PGSIZE
+sizeof(ns
->ns_ph
);
if (ns
->ns_ph
.pr_status
== DSRS_RPC
||
ns
->ns_ph
.pr_status
== 0x21)
printf("cur %x pnd %x lfr %x ", ns
->ns_cur
, pend
, lastfree
);
printf("nxt %x len %x ", ns
->ns_ph
.pr_nxtpg
, (ns
->ns_ph
.pr_sz1
<<8)+
pg("Bogus Sts %x ", ns
->ns_ph
.pr_status
);
nxt
= ns
->ns_ph
.pr_nxtpg
;
dprintf(DEXPAND
,"nxt %x ", nxt
);
if ( nxt
>= RBUF
/DS_PGSIZE
&& nxt
<= RBUFEND
/DS_PGSIZE
&& nxt
<= pend
)
else ns
->ns_cur
= nxt
= pend
;
outb(nec
+ds0_bnry
, lastfree
);
pend
= inb(nec
+ds1_curr
);
} else ns
->ns_cur
= pend
;
outb(nec
+ds_cmd
, DSCM_START
|DSCM_NODMA
);
ns
->ns_flags
&= ~DSF_LOCK
;
dprintf(DEXPAND
," clsn");
/* need to read these registers to clear status */
ns
->ns_if
.if_collisions
+= inb(nec
+ds0_tbcr0
);
ns
->ns_flags
&= ~DSF_LOCK
;
ns
->ns_if
.if_collisions
+=
outb (nec
+ds_cmd
, DSCM_NODMA
|DSCM_PG0
|DSCM_START
);
outb (nec
+ds0_imr
, 0xff);
if(++cnt
% 10 == 0) dprintf(DEXPAND
,"\n");
* Ethernet interface receiver interface.
* If input error just drop packet.
* Otherwise examine packet to determine type. If can't determine length
* from type, then have to drop packet. Othewise decapsulate
* packet based on type and pass to type specific higher-level
register struct ne_softc
*ns
;
len
= ns
->ns_ph
.pr_sz0
+ (ns
->ns_ph
.pr_sz1
<<8);
if(len
< 60 || len
> 1536) {
pg(DEXPAND
,"R Bogus Length %d", len
);
fetchram(ns
->ns_pb
,ns
->ns_ba
,min(len
,DS_PGSIZE
-sizeof(ns
->ns_ph
)));
if (!bcmp((caddr_t
)ns
->ns_pb
, (caddr_t
)ns
->ns_addr
, 6)
&& !bcmp((caddr_t
)ns
->ns_pb
, (caddr_t
)etherbroadcastaddr
, 6)) {
printf("G%x ", ns
->ns_cur
);
printf("P%x ", ns->ns_cur);*/
if(len
> DS_PGSIZE
-sizeof(ns
->ns_ph
)) {
int l
= len
- (DS_PGSIZE
-sizeof(ns
->ns_ph
)), b
;
u_char
*p
= ns
->ns_pb
+ (DS_PGSIZE
-sizeof(ns
->ns_ph
));
dprintf(DEXPAND
,"len %d(%d|", len
, p
- ns
->ns_pb
);
if(++ns
->ns_cur
> 0x7f) ns
->ns_cur
= 0x46;
b
= ns
->ns_cur
*DS_PGSIZE
;
p
+= DS_PGSIZE
; l
-= DS_PGSIZE
;
if(++ns
->ns_cur
> 0x7f) ns
->ns_cur
= 0x46;
b
= ns
->ns_cur
*DS_PGSIZE
;
dprintf(DEXPAND
,"%d|", p
- ns
->ns_pb
);
dprintf(DEXPAND
,"%d) ", l
);
sizeof(struct ether_header
)
+ sizeof(long); /* don't forget checksum! */
neread(ns
,(caddr_t
)(ns
->ns_pb
), len
);
if(n
) { downcnt
= 0xffff; return(0); }
if(--downcnt
> 0) return(0);
pg(" <%s> recur %d sts %x ", s
, recur
, inb (nec
+ds0_isr
));
* Pass a packet to the higher levels.
* We deal with the trailer protocol here.
register struct ne_softc
*ns
;
register struct ether_header
*eh
;
register struct ifqueue
*inq
;
* Deal with trailer protocol: if type is trailer type
* get true type from first 16-bit word past data.
* Remember that type was trailer by setting off.
eh
= (struct ether_header
*)buf
;
eh
->ether_type
= ntohs((u_short
)eh
->ether_type
);
#define nedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off))))
if (eh
->ether_type
>= ETHERTYPE_TRAIL
&&
eh
->ether_type
< ETHERTYPE_TRAIL
+ETHERTYPE_NTRAILER
) {
off
= (eh
->ether_type
- ETHERTYPE_TRAIL
) * 512;
if (off
>= ETHERMTU
) return; /* sanity */
eh
->ether_type
= ntohs(*nedataaddr(eh
, off
, u_short
*));
resid
= ntohs(*(nedataaddr(eh
, off
+2, u_short
*)));
if (off
+ resid
> len
) return; /* sanity */
* Pull packet off interface. Off is nonzero if packet
* has trailing header; neget will then force this header
* information to be at the front, but we still have to drop
* the type and length which are at the front of any trailer data.
m
= neget(buf
, len
, off
, &ns
->ns_if
);
ifp
= *(mtod(m
, struct ifnet
**));
m
->m_off
+= 2 * sizeof (u_short
);
m
->m_len
-= 2 * sizeof (u_short
);
*(mtod(m
, struct ifnet
**)) = ifp
;
switch (eh
->ether_type
) {
/*if (ns->ns_ac.ac_ipaddr == 0) goto raw;*/
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
* Use trailer local net encapsulation if enough data in first
* packet leaves a multiple of 512 bytes of data in remainder.
register struct ne_softc
*ns
= &ne_softc
[ifp
->if_unit
];
register struct mbuf
*m
= m0
;
register struct ether_header
*eh
;
extern struct ifnet loif
;
struct mbuf
*mcopy
= (struct mbuf
*)0;
if ((ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) != (IFF_UP
|IFF_RUNNING
)) {
switch (dst
->sa_family
) {
idst
= ((struct sockaddr_in
*)dst
)->sin_addr
;
if (!arpresolve(&ns
->ns_ac
, m
, &idst
, edst
, &usetrailers
))
return (0); /* if not yet resolved */
if (!bcmp((caddr_t
)edst
, (caddr_t
)etherbroadcastaddr
,
mcopy
= m_copy(m
, 0, (int)M_COPYALL
);
off
= ntohs((u_short
)mtod(m
, struct ip
*)->ip_len
) - m
->m_len
;
/* need per host negotiation */
if (usetrailers
&& off
> 0 && (off
& 0x1ff) == 0 &&
m
->m_off
>= MMINOFF
+ 2 * sizeof (u_short
)) {
type
= ETHERTYPE_TRAIL
+ (off
>>9);
m
->m_off
-= 2 * sizeof (u_short
);
m
->m_len
+= 2 * sizeof (u_short
);
*mtod(m
, u_short
*) = ntohs((u_short
)ETHERTYPE_IP
);
*(mtod(m
, u_short
*) + 1) = ntohs((u_short
)m
->m_len
);
bcopy((caddr_t
)&(((struct sockaddr_ns
*)dst
)->sns_addr
.x_host
),
(caddr_t
)edst
, sizeof (edst
));
if (!bcmp((caddr_t
)edst
, (caddr_t
)&ns_broadhost
,
mcopy
= m_copy(m
, 0, (int)M_COPYALL
);
} else if (!bcmp((caddr_t
)edst
, (caddr_t
)&ns_thishost
,
return(looutput(&loif
, m
, dst
));
eh
= (struct ether_header
*)dst
->sa_data
;
bcopy((caddr_t
)eh
->ether_dhost
, (caddr_t
)edst
, sizeof (edst
));
printf("ne%d: can't handle af%d\n", ifp
->if_unit
,
* Packet to be sent as trailer: move first packet
* (control information) to end of chain.
* Add local net header. If no space in first mbuf,
if (m
->m_off
> MMAXOFF
||
MMINOFF
+ sizeof (struct ether_header
) > m
->m_off
) {
m
= m_get(M_DONTWAIT
, MT_HEADER
);
m
->m_len
= sizeof (struct ether_header
);
m
->m_off
-= sizeof (struct ether_header
);
m
->m_len
+= sizeof (struct ether_header
);
eh
= mtod(m
, struct ether_header
*);
bcopy((caddr_t
)edst
, (caddr_t
)eh
->ether_dhost
, sizeof (edst
));
bcopy((caddr_t
)ns
->ns_addr
, (caddr_t
)eh
->ether_shost
,
sizeof (eh
->ether_shost
));
eh
->ether_type
= htons((u_short
)type
);
* Queue message on interface, and start output if interface
if (IF_QFULL(&ifp
->if_snd
)) {
IF_ENQUEUE(&ifp
->if_snd
, m
);
return (mcopy
? looutput(&loif
, mcopy
, dst
) : 0);
* Pull read data off a interface.
* Len is length of data, with local net header stripped.
* Off is non-zero if a trailer protocol was used, and
* gives the offset of the trailer information.
* We copy the trailer information and then all the normal
* data into mbufs. When full cluster sized units are present
neget(buf
, totlen
, off0
, ifp
)
struct mbuf
*top
, **mp
, *m
, *p
;
register caddr_t cp
= buf
;
cp
= buf
+ sizeof(struct ether_header
);
MGET(m
, M_DONTWAIT
, MT_DATA
);
cp
= buf
+ off
+ sizeof (struct ether_header
);
m
->m_len
= len
= MIN(len
, CLBYTES
);
m
->m_len
= len
= MIN(MLEN
, len
);
m
->m_len
= len
= MIN(MLEN
, len
);
* Prepend interface pointer to first mbuf.
*(mtod(m
, struct ifnet
**)) = ifp
;
cp
= buf
+ sizeof (struct ether_header
);
* Map a chain of mbufs onto a network interface
* in preparation for an i/o operation.
* The argument chain of mbufs includes the local network
* header which is copied to be in the mapped, aligned
register struct mbuf
*mp
;
bcopy(mtod(m
, caddr_t
), cp
, (unsigned)m
->m_len
);
return (max(cc
, ETHERMIN
+ sizeof(struct ether_header
)));
* Process an ioctl request.
register struct ifnet
*ifp
;
register struct ifaddr
*ifa
= (struct ifaddr
*)data
;
struct ne_softc
*ns
= &ne_softc
[ifp
->if_unit
];
struct ifreq
*ifr
= (struct ifreq
*)data
;
int s
= splimp(), error
= 0;
switch (ifa
->ifa_addr
.sa_family
) {
neinit(ifp
->if_unit
); /* before arpwhohas */
((struct arpcom
*)ifp
)->ac_ipaddr
=
arpwhohas((struct arpcom
*)ifp
, &IA_SIN(ifa
)->sin_addr
);
register struct ns_addr
*ina
= &(IA_SNS(ifa
)->sns_addr
);
ina
->x_host
= *(union ns_host
*)(ns
->ns_addr
);
* The manual says we can't change the address
* while the receiver is armed,
ifp
->if_flags
&= ~IFF_RUNNING
;
bcopy((caddr_t
)ina
->x_host
.c_host
,
(caddr_t
)ns
->ns_addr
, sizeof(ns
->ns_addr
));
neinit(ifp
->if_unit
); /* does ne_setaddr() */
if ((ifp
->if_flags
& IFF_UP
) == 0 &&
ifp
->if_flags
& IFF_RUNNING
) {
ifp
->if_flags
&= ~IFF_RUNNING
;
outb(nec
+ds_cmd
,DSCM_STOP
|DSCM_NODMA
);
} else if (ifp
->if_flags
& IFF_UP
&&
(ifp
->if_flags
& IFF_RUNNING
) == 0)
bcopy((caddr_t
)ns
->ns_addr
, (caddr_t
) &ifr
->ifr_data
,
register struct ifnet
*ifp
;
register struct sockaddr_in
*sin
;
ifp
->if_addr
= *(struct sockaddr
*)sin
;
ifp
->if_net
= in_netof(sin
->sin_addr
);
ifp
->if_host
[0] = in_lnaof(sin
->sin_addr
);
if (nepaddr
[ifp
->if_unit
][0] == '3')
nepaddr
[ifp
->if_unit
][0] = ifp
->if_host
[0] << 1;
sin
= (struct sockaddr_in
*)&ifp
->if_broadaddr
;
sin
->sin_family
= AF_INET
;
sin
->sin_addr
= in_makeaddr(ifp
->if_net
, INADDR_ANY
);
ifp
->if_flags
|= IFF_BROADCAST
;