all statistics are unsigned
[unix-history] / usr / src / sys / tahoe / if / if_enp.c
CommitLineData
bc2cef1e 1/* if_enp.c 1.2 86/11/29 */
6013a59e
SL
2
3#include "enp.h"
6013a59e 4#if NENP > 0
6013a59e 5/*
bc2cef1e 6 * Modified 3Com Ethernet Controller interface
6013a59e 7 * enp modifications added S. F. Holmgren
bc2cef1e
SL
8 *
9 * UNTESTED WITH 4.3
6013a59e 10 */
6013a59e
SL
11#include "param.h"
12#include "systm.h"
13#include "mbuf.h"
14#include "buf.h"
15#include "protosw.h"
16#include "socket.h"
17#include "vmmac.h"
bc2cef1e 18#include "ioctl.h"
6013a59e 19#include "errno.h"
bc2cef1e
SL
20#include "vmparam.h"
21#include "syslog.h"
6013a59e
SL
22#include "uio.h"
23
24#include "../net/if.h"
25#include "../net/netisr.h"
26#include "../net/route.h"
bc2cef1e 27#ifdef INET
6013a59e 28#include "../netinet/in.h"
6013a59e 29#include "../netinet/in_systm.h"
bc2cef1e 30#include "../netinet/in_var.h"
6013a59e
SL
31#include "../netinet/ip.h"
32#include "../netinet/ip_var.h"
33#include "../netinet/if_ether.h"
bc2cef1e
SL
34#endif
35#ifdef NS
36#include "../netns/ns.h"
37#include "../netns/ns_if.h"
38#endif
39
40#include "../tahoe/cpu.h"
41#include "../tahoe/pte.h"
42#include "../tahoe/mtpr.h"
6013a59e
SL
43
44#include "../tahoevba/vbavar.h"
bc2cef1e 45#include "../tahoeif/if_enpreg.h"
6013a59e 46
bc2cef1e
SL
47#define ENPVEC 0xc1
48#define ENPSTART 0xf02000 /* standard enp start addr */
49#define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */
6013a59e
SL
50
51int enpprobe(), enpattach(), enpintr();
bc2cef1e
SL
52long enpstd[] = { 0xf41000, 0xf61000, 0 };
53struct vba_device *enpinfo[NENP];
6013a59e 54struct vba_driver enpdriver =
bc2cef1e 55 { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 };
6013a59e 56
bc2cef1e 57int enpinit(), enpioctl(), enpreset(), enpoutput();
6013a59e
SL
58struct mbuf *enpget();
59
6013a59e
SL
60/*
61 * Ethernet software status per interface.
62 *
63 * Each interface is referenced by a network interface structure,
64 * es_if, which the routing code uses to locate the interface.
65 * This structure contains the output queue for the interface, its address, ...
66 */
bc2cef1e
SL
67struct enp_softc {
68 struct arpcom es_ac; /* common ethernet structures */
69#define es_if es_ac.ac_if
70#define es_enaddr es_ac.ac_enaddr
71 short es_flags; /* flags for devices */
72 short es_ivec; /* interrupt vector */
73 struct pte *es_map; /* map for dual ported memory */
74 caddr_t es_ram; /* virtual address of mapped memory */
75} enp_softc[NENP];
76extern struct ifnet loif;
77
78enpprobe(reg, vi)
79 caddr_t reg;
80 struct vba_device *vi;
6013a59e 81{
bc2cef1e
SL
82 register br, cvec; /* must be r12, r11 */
83 register struct enpdevice *addr = (struct enpdevice *)reg;
84 struct enp_softc *es = &enp_softc[vi->ui_unit];
6013a59e 85
bc2cef1e
SL
86#ifdef lint
87 enpintr(0);
88#endif
89 if (badaddr(addr, 2) || badaddr(&addr->enp_ram[0], 2))
90 return (0);
91 es->es_ivec = --vi->ui_hd->vh_lastiv;
92 addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */
93 br = 0x14, cvec = es->es_ivec; /* XXX */
94 return (sizeof (struct enpdevice));
6013a59e
SL
95}
96
97/*
98 * Interface exists: make available by filling in network interface
99 * record. System will initialize the interface when it is ready
100 * to accept packets.
101 */
bc2cef1e
SL
102enpattach(ui)
103 register struct vba_device *ui;
6013a59e 104{
bc2cef1e
SL
105 struct enp_softc *es = &enp_softc[ui->ui_unit];
106 register struct ifnet *ifp = &es->es_if;
107 register struct enpdevice *addr = (struct enpdevice *)ui->ui_addr;
6013a59e 108
bc2cef1e 109 ifp->if_unit = ui->ui_unit;
6013a59e
SL
110 ifp->if_name = "enp";
111 ifp->if_mtu = ETHERMTU;
bc2cef1e
SL
112 /*
113 * Get station's addresses.
114 */
115 enpcopy(&addr->enp_addr.e_baseaddr, es->es_enaddr,
116 sizeof (es->es_enaddr));
117 printf("enp%d: hardware address %s\n", ui->ui_unit,
118 ether_sprintf(es->es_enaddr));
119 /*
120 * Allocate and map ram.
121 */
122 vbmemalloc(128, ((caddr_t)addr)+0x1000, &es->es_map, &es->es_ram);
6013a59e
SL
123
124 ifp->if_init = enpinit;
125 ifp->if_ioctl = enpioctl;
126 ifp->if_output = enpoutput;
127 ifp->if_reset = enpreset;
bc2cef1e 128 ifp->if_flags = IFF_BROADCAST;
6013a59e
SL
129 if_attach(ifp);
130}
131
6013a59e 132/*
bc2cef1e 133 * Reset of interface after "system" reset.
6013a59e 134 */
bc2cef1e
SL
135enpreset(unit, vban)
136 int unit, vban;
6013a59e 137{
bc2cef1e 138 register struct vba_device *ui;
6013a59e 139
bc2cef1e
SL
140 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
141 ui->ui_vbanum != vban)
142 return;
143 printf(" enp%d", unit);
6013a59e
SL
144 enpinit(unit);
145}
146
147/*
bc2cef1e 148 * Initialization of interface; clear recorded pending operations.
6013a59e 149 */
bc2cef1e
SL
150enpinit(unit)
151 int unit;
6013a59e 152{
bc2cef1e
SL
153 struct enp_softc *es = &enp_softc[unit];
154 register struct vba_device *ui = enpinfo[unit];
155 struct enpdevice *addr;
156 register struct ifnet *ifp = &es->es_if;
157 int s;
6013a59e 158
bc2cef1e
SL
159 if (ifp->if_addrlist == (struct ifaddr *)0)
160 return;
161 if ((ifp->if_flags & IFF_RUNNING) == 0) {
162 addr = (struct enpdevice *)ui->ui_addr;
163 s = splimp();
164 RESET_ENP(addr);
165 DELAY(200000);
166 addr->enp_intrvec = es->es_ivec;
167 es->es_if.if_flags |= IFF_RUNNING;
168 splx(s);
169 }
6013a59e
SL
170}
171
6013a59e
SL
172/*
173 * Ethernet interface interrupt.
174 */
bc2cef1e
SL
175enpintr(unit)
176 int unit;
6013a59e 177{
bc2cef1e
SL
178 register struct enpdevice *addr;
179 register BCB *bcbp;
6013a59e 180
bc2cef1e
SL
181 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
182 if (!IS_ENP_INTR(addr))
6013a59e 183 return;
bc2cef1e
SL
184 ACK_ENP_INTR(addr);
185 while ((bcbp = (BCB *)ringget(&addr->enp_tohost )) != 0) {
186 (void) enpread(&enp_softc[unit], bcbp, unit);
187 ringput(&addr->enp_enpfree, bcbp);
6013a59e 188 }
6013a59e
SL
189}
190
191/*
192 * Read input packet, examine its packet type, and enqueue it.
193 */
bc2cef1e
SL
194enpread(es, bcbp, unit)
195 struct enp_softc *es;
196 register BCB *bcbp;
197 int unit;
6013a59e
SL
198{
199 register struct ether_header *enp;
200 struct mbuf *m;
bc2cef1e 201 long int s;
6013a59e
SL
202 int len, off, resid, enptype;
203 register struct ifqueue *inq;
204
205 es->es_if.if_ipackets++;
6013a59e
SL
206 /*
207 * Get input data length.
208 * Get pointer to ethernet header (in input buffer).
209 * Deal with trailer protocol: if type is PUP trailer
210 * get true type from first 16-bit word past data.
211 * Remember that type was trailer by setting off.
212 */
bc2cef1e 213 len = bcbp->b_msglen - sizeof (struct ether_header);
6013a59e 214 enp = (struct ether_header *)bcbp->b_addr;
bc2cef1e
SL
215#define enpdataaddr(enp, off, type) \
216 ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off))))
217 enp->ether_type = ntohs((u_short)enp->ether_type);
218 if (enp->ether_type >= ETHERTYPE_TRAIL &&
219 enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
220 off = (enp->ether_type - ETHERTYPE_TRAIL) * 512;
221 if (off >= ETHERMTU)
222 goto setup;
223 enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *));
224 resid = ntohs(*(enpdataaddr(enp, off+2, u_short *)));
225 if (off + resid > len)
226 goto setup;
6013a59e 227 len = off + resid;
bc2cef1e 228 } else
6013a59e 229 off = 0;
bc2cef1e
SL
230 if (len == 0)
231 goto setup;
6013a59e 232
6013a59e
SL
233 /*
234 * Pull packet off interface. Off is nonzero if packet
235 * has trailing header; enpget will then force this header
236 * information to be at the front, but we still have to drop
237 * the type and length which are at the front of any trailer data.
238 */
bc2cef1e
SL
239 m = enpget(bcbp->b_addr, len, off, &es->es_if);
240 if (m == 0)
241 goto setup;
242 if (off) {
243 struct ifnet *ifp;
6013a59e 244
bc2cef1e 245 ifp = *(mtod(m, struct ifnet **));
6013a59e
SL
246 m->m_off += 2 * sizeof (u_short);
247 m->m_len -= 2 * sizeof (u_short);
bc2cef1e 248 *(mtod(m, struct ifnet **)) = ifp;
6013a59e 249 }
bc2cef1e 250 switch (enp->ether_type) {
6013a59e 251
6013a59e 252#ifdef INET
bc2cef1e 253 case ETHERTYPE_IP:
6013a59e
SL
254 schednetisr(NETISR_IP);
255 inq = &ipintrq;
256 break;
bc2cef1e
SL
257#endif
258 case ETHERTYPE_ARP:
6013a59e 259 arpinput(&es->es_ac, m);
bc2cef1e
SL
260 goto setup;
261
262#ifdef NS
263 case ETHERTYPE_NS:
264 schednetisr(NETISR_NS);
265 inq = &nsintrq;
266 break;
6013a59e 267#endif
bc2cef1e 268 default:
6013a59e 269 m_freem(m);
bc2cef1e 270 goto setup;
6013a59e 271 }
bc2cef1e 272 if (IF_QFULL(inq)) {
6013a59e
SL
273 IF_DROP(inq);
274 m_freem(m);
bc2cef1e 275 goto setup;
6013a59e
SL
276 }
277 s = splimp();
278 IF_ENQUEUE(inq, m);
279 splx(s);
bc2cef1e
SL
280setup:
281 return (0);
6013a59e
SL
282}
283
284/*
285 * Ethernet output routine. (called by user)
286 * Encapsulate a packet of type family for the local net.
287 * Use trailer local net encapsulation if enough data in first
288 * packet leaves a multiple of 512 bytes of data in remainder.
289 * If destination is this address or broadcast, send packet to
290 * loop device to kludge around the fact that 3com interfaces can't
291 * talk to themselves.
292 */
6013a59e 293enpoutput(ifp, m0, dst)
bc2cef1e
SL
294 struct ifnet *ifp;
295 struct mbuf *m0;
296 struct sockaddr *dst;
6013a59e 297{
6013a59e
SL
298 register struct enp_softc *es = &enp_softc[ifp->if_unit];
299 register struct mbuf *m = m0;
300 register struct ether_header *enp;
301 register int off, i;
bc2cef1e
SL
302 struct mbuf *mcopy = (struct mbuf *)0;
303 int type, s, error, usetrailers;
304 u_char edst[6];
305 struct in_addr idst;
6013a59e 306
bc2cef1e
SL
307 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
308 error = ENETDOWN;
309 goto bad;
310 }
311 switch (dst->sa_family) {
6013a59e
SL
312#ifdef INET
313 case AF_INET:
314 idst = ((struct sockaddr_in *)dst)->sin_addr;
bc2cef1e
SL
315 if (!arpresolve(&es->es_ac, m, &idst, edst, &usetrailers))
316 return (0); /* if not yet resolved */
317 if (!bcmp((caddr_t)edst, (caddr_t)etherbroadcastaddr,
318 sizeof (edst)))
319 mcopy = m_copy(m, 0, (int)M_COPYALL);
320 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
321 if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
322 m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
323 type = ETHERTYPE_TRAIL + (off>>9);
324 m->m_off -= 2 * sizeof (u_short);
325 m->m_len += 2 * sizeof (u_short);
326 *mtod(m, u_short *) = ETHERTYPE_IP;
327 *(mtod(m, u_short *) + 1) = m->m_len;
328 goto gottrailertype;
6013a59e 329 }
bc2cef1e 330 type = ETHERTYPE_IP;
6013a59e
SL
331 off = 0;
332 goto gottype;
333#endif
bc2cef1e
SL
334#ifdef NS
335 case AF_NS:
336 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
337 (caddr_t)edst, sizeof (edst));
338 if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof (edst)))
339 mcopy = m_copy(m, 0, (int)M_COPYALL);
340 else if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost,
341 sizeof (edst)))
342 return (looutput(&loif, m, dst));
343 type = ETHERTYPE_NS;
344 off = 0;
345 goto gottype;
6013a59e 346#endif
6013a59e
SL
347 case AF_UNSPEC:
348 enp = (struct ether_header *)dst->sa_data;
bc2cef1e 349 bcopy((caddr_t)enp->ether_dhost, (caddr_t)edst, sizeof (edst));
6013a59e
SL
350 type = enp->ether_type;
351 goto gottype;
352
353 default:
bc2cef1e
SL
354 log(LOG_ERR, "enp%d: can't handle af%d\n",
355 ifp->if_unit, dst->sa_family);
6013a59e
SL
356 error = EAFNOSUPPORT;
357 goto bad;
358 }
359
360gottrailertype:
361 /*
362 * Packet to be sent as trailer: move first packet
363 * (control information) to end of chain.
364 */
365 while (m->m_next)
366 m = m->m_next;
367 m->m_next = m0;
368 m = m0->m_next;
369 m0->m_next = 0;
370 m0 = m;
371
372gottype:
373 /*
374 * Add local net header. If no space in first mbuf,
375 * allocate another.
376 */
377 if (m->m_off > MMAXOFF ||
bc2cef1e 378 MMINOFF + sizeof (struct ether_header) > m->m_off) {
6013a59e 379 m = m_get(M_DONTWAIT, MT_HEADER);
bc2cef1e 380 if (m == 0) {
6013a59e
SL
381 error = ENOBUFS;
382 goto bad;
383 }
384 m->m_next = m0;
385 m->m_off = MMINOFF;
bc2cef1e
SL
386 m->m_len = sizeof (struct ether_header);
387 } else {
388 m->m_off -= sizeof (struct ether_header);
389 m->m_len += sizeof (struct ether_header);
6013a59e
SL
390 }
391 enp = mtod(m, struct ether_header *);
bc2cef1e
SL
392 bcopy((caddr_t)edst, (caddr_t)enp->ether_dhost, sizeof (edst));
393 bcopy((caddr_t)es->es_enaddr, (caddr_t)enp->ether_shost,
394 sizeof (es->es_enaddr));
395 enp->ether_type = htons((u_short)type);
6013a59e
SL
396
397 /*
398 * Queue message on interface if possible
399 */
6013a59e 400 s = splimp();
bc2cef1e 401 if (enpput(ifp->if_unit, m)) {
6013a59e 402 error = ENOBUFS;
6013a59e
SL
403 goto qfull;
404 }
bc2cef1e 405 splx(s);
6013a59e 406 es->es_if.if_opackets++;
bc2cef1e 407 return (mcopy ? looutput(&loif, mcopy, dst) : 0);
6013a59e 408qfull:
bc2cef1e 409 splx(s);
6013a59e
SL
410 m0 = m;
411bad:
412 m_freem(m0);
bc2cef1e
SL
413 if (mcopy)
414 m_freem(mcopy);
415 return (error);
6013a59e
SL
416}
417
418/*
bc2cef1e 419 * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus.
6013a59e 420 */
bc2cef1e
SL
421enpput(unit, m)
422 int unit;
423 struct mbuf *m;
6013a59e
SL
424{
425 register BCB *bcbp;
bc2cef1e 426 register struct enpdevice *addr;
6013a59e
SL
427 register struct mbuf *mp;
428 register u_char *bp;
bc2cef1e
SL
429 register u_int len;
430 u_char *mcp;
6013a59e 431
bc2cef1e
SL
432 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
433 if (ringempty(&addr->enp_hostfree))
434 return (1);
435 bcbp = (BCB *)ringget(&addr->enp_hostfree);
6013a59e 436 bcbp->b_len = 0;
6013a59e 437 bp = (u_char *)bcbp->b_addr;
bc2cef1e 438 for (mp = m; mp; mp = mp->m_next) {
6013a59e 439 len = mp->m_len;
bc2cef1e 440 if (len == 0)
6013a59e 441 continue;
bc2cef1e
SL
442 mcp = mtod(mp, u_char *);
443 enpcopy(mcp, bp, len);
6013a59e
SL
444 bp += len;
445 bcbp->b_len += len;
446 }
bc2cef1e 447 bcbp->b_len = max(ETHERMIN, bcbp->b_len);
6013a59e 448 bcbp->b_reserved = 0;
bc2cef1e
SL
449 if (ringput(&addr->enp_toenp, bcbp) == 1)
450 INTR_ENP(addr);
6013a59e 451 m_freem(m);
bc2cef1e 452 return (0);
6013a59e
SL
453}
454
455/*
bc2cef1e 456 * Routine to copy from VERSAbus memory into mbufs.
6013a59e
SL
457 *
458 * Warning: This makes the fairly safe assumption that
459 * mbufs have even lengths.
460 */
461struct mbuf *
bc2cef1e
SL
462enpget(rxbuf, totlen, off0, ifp)
463 u_char *rxbuf;
464 int totlen, off0;
465 struct ifnet *ifp;
6013a59e 466{
bc2cef1e 467 register u_char *cp, *mcp;
6013a59e 468 register struct mbuf *m;
bc2cef1e
SL
469 struct mbuf *top = 0, **mp = &top;
470 int len, off = off0;
6013a59e 471
bc2cef1e
SL
472 cp = rxbuf + sizeof (struct ether_header);
473 while (totlen > 0) {
6013a59e
SL
474 MGET(m, M_DONTWAIT, MT_DATA);
475 if (m == 0)
476 goto bad;
bc2cef1e 477 if (off) {
6013a59e 478 len = totlen - off;
bc2cef1e
SL
479 cp = rxbuf + sizeof (struct ether_header) + off;
480 } else
6013a59e 481 len = totlen;
bc2cef1e 482 if (len >= NBPG) {
6013a59e
SL
483 struct mbuf *p;
484
bc2cef1e
SL
485 MCLGET(m);
486 if (m->m_len == CLBYTES)
487 m->m_len = len = MIN(len, CLBYTES);
488 else
6013a59e 489 m->m_len = len = MIN(MLEN, len);
bc2cef1e 490 } else {
6013a59e
SL
491 m->m_len = len = MIN(MLEN, len);
492 m->m_off = MMINOFF;
493 }
6013a59e 494 mcp = mtod(m, u_char *);
bc2cef1e
SL
495 if (ifp) {
496 /*
497 * Prepend interface pointer to first mbuf.
498 */
499 *(mtod(m, struct ifnet **)) = ifp;
500 mcp += sizeof (ifp);
501 len -= sizeof (ifp);
502 ifp = (struct ifnet *)0;
503 }
6013a59e
SL
504 enpcopy(cp, mcp, len);
505 cp += len;
506 *mp = m;
507 mp = &m->m_next;
bc2cef1e 508 if (off == 0) {
6013a59e
SL
509 totlen -= len;
510 continue;
511 }
512 off += len;
bc2cef1e
SL
513 if (off == totlen) {
514 cp = rxbuf + sizeof (struct ether_header);
6013a59e
SL
515 off = 0;
516 totlen = off0;
517 }
518 }
519 return (top);
520bad:
521 m_freem(top);
522 return (0);
523}
524
bc2cef1e
SL
525enpcopy(from, to, cnt)
526 register char *from, *to;
527 register cnt;
528{
529 register c;
530 register short *f, *t;
531
532 if (((int)from&01) && ((int)to&01)) {
533 /* source & dest at odd addresses */
534 *to++ = *from++;
535 --cnt;
536 }
537 if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
538 t = (short *)to;
539 f = (short *)from;
540 for (c = cnt>>1; c; --c) /* even address copy */
541 *t++ = *f++;
542 cnt &= 1;
543 if (cnt) { /* odd len */
544 from = (char *)f;
545 to = (char *)t;
546 *to = *from;
547 }
548 }
549 while (cnt-- > 0) /* one of the address(es) must be odd */
550 *to++ = *from++;
551}
552
6013a59e
SL
553/*
554 * Process an ioctl request.
6013a59e 555 */
6013a59e 556enpioctl(ifp, cmd, data)
bc2cef1e
SL
557 register struct ifnet *ifp;
558 int cmd;
559 caddr_t data;
6013a59e 560{
bc2cef1e
SL
561 register struct ifaddr *ifa = (struct ifaddr *)data;
562 struct enpdevice *addr;
563 int s = splimp(), error = 0;
6013a59e
SL
564
565 switch (cmd) {
566
567 case SIOCSIFADDR:
bc2cef1e
SL
568 ifp->if_flags |= IFF_UP;
569 switch (ifa->ifa_addr.sa_family) {
570#ifdef INET
571 case AF_INET:
572 enpinit(ifp->if_unit);
573 ((struct arpcom *)ifp)->ac_ipaddr =
574 IA_SIN(ifa)->sin_addr;
575 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
576 break;
577#endif
578#ifdef NS
579 case AF_NS: {
580 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
581 struct enp_softc *es = &enp_softc[ifp->if_unit];
582
583 if (!ns_nullhost(*ina)) {
584 ifp->if_flags &= ~IFF_RUNNING;
585 addr = (struct enpdevice *)
586 enpinfo[ifp->if_unit]->ui_addr;
587 enpsetaddr(ifp->if_unit, addr,
588 ina->x_host.c_host);
589 } else
590 ina->x_host = *(union ns_host *)es->es_enaddr;
591 enpinit(ifp->if_unit);
6013a59e
SL
592 break;
593 }
bc2cef1e
SL
594#endif
595 default:
596 enpinit(ifp->if_unit);
597 break;
6013a59e 598 }
6013a59e
SL
599 break;
600
bc2cef1e
SL
601 case SIOCSIFFLAGS:
602 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
603 enpinit(ifp->if_unit); /* reset board */
604 ifp->if_flags &= ~IFF_RUNNING;
605 } else if (ifp->if_flags&IFF_UP &&
606 (ifp->if_flags&IFF_RUNNING) == 0)
607 enpinit(ifp->if_unit);
6013a59e
SL
608 break;
609
610 default:
611 error = EINVAL;
612 }
bc2cef1e
SL
613 splx(s);
614 return (error);
6013a59e
SL
615}
616
bc2cef1e
SL
617enpsetaddr(unit, addr, enaddr)
618 int unit;
619 struct enpdevice *addr;
620 u_char *enaddr;
6013a59e 621{
bc2cef1e
SL
622 u_char *cp;
623 int i, code;
624
625 cp = &addr->enp_addr.e_baseaddr.ea_addr[0];
626 for (i = 0; i < 6; i++)
627 *cp++ = ~*enaddr++;
628 enpcopy(&addr->enp_addr.e_listsize, &code, sizeof (code));
629 code |= E_ADDR_SUPP;
630 enpcopy(&code, &addr->enp_addr.e_listsize, sizeof (code));
631 enpinit(unit);
6013a59e
SL
632}
633
634/*
bc2cef1e 635 * Routines to synchronize enp and host.
6013a59e 636 */
6013a59e 637static
bc2cef1e
SL
638ringinit(rp, size)
639 register RING *rp;
6013a59e 640{
bc2cef1e 641 register int i;
6013a59e
SL
642 register short *sp;
643
644 rp->r_rdidx = rp->r_wrtidx = 0;
645 rp->r_size = size;
646}
647
648static
bc2cef1e
SL
649ringempty(rp)
650 register RING *rp;
6013a59e 651{
bc2cef1e
SL
652
653 return (rp->r_rdidx == rp->r_wrtidx);
6013a59e
SL
654}
655
656static
bc2cef1e
SL
657ringfull(rp)
658 register RING *rp;
6013a59e
SL
659{
660 register short idx;
661
662 idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
bc2cef1e 663 return (idx == rp->r_rdidx);
6013a59e
SL
664}
665
666static
bc2cef1e
SL
667ringput(rp, v)
668 register RING *rp;
6013a59e
SL
669{
670 register int idx;
6013a59e
SL
671
672 idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
bc2cef1e
SL
673 if (idx != rp->r_rdidx) {
674 rp->r_slot[rp->r_wrtidx] = v;
6013a59e 675 rp->r_wrtidx = idx;
bc2cef1e 676 if ((idx -= rp->r_rdidx) < 0)
6013a59e 677 idx += rp->r_size;
bc2cef1e 678 return (idx); /* num ring entries */
6013a59e 679 }
bc2cef1e 680 return (0);
6013a59e
SL
681}
682
683static
bc2cef1e
SL
684ringget(rp)
685 register RING *rp;
6013a59e
SL
686{
687 register int i = 0;
bc2cef1e
SL
688
689 if (rp->r_rdidx != rp->r_wrtidx) {
690 i = rp->r_slot[rp->r_rdidx];
6013a59e
SL
691 rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
692 }
bc2cef1e 693 return (i);
6013a59e
SL
694}
695
6013a59e 696static
bc2cef1e
SL
697fir(rp)
698 register RING *rp;
6013a59e 699{
6013a59e 700
bc2cef1e
SL
701 return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0);
702}
6013a59e 703
bc2cef1e
SL
704/*
705 * ENP Ram device.
706 */
707enpr_open(dev)
708 dev_t dev;
6013a59e 709{
bc2cef1e
SL
710 register int unit = ENPUNIT(dev);
711 struct vba_device *ui;
712 struct enpdevice *addr;
6013a59e 713
bc2cef1e
SL
714 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
715 (addr = (struct enpdevice *)ui->ui_addr) == 0)
716 return (ENODEV);
717 if (addr->enp_state != S_ENPRESET)
718 return (EACCES); /* enp is not in reset state, don't open */
719 return (0);
6013a59e
SL
720}
721
bc2cef1e
SL
722enpr_close(dev)
723 dev_t dev;
6013a59e 724{
6013a59e 725
bc2cef1e 726 return (0);
6013a59e
SL
727}
728
bc2cef1e
SL
729enpr_read(dev, uio)
730 dev_t dev;
731 register struct uio *uio;
6013a59e 732{
bc2cef1e
SL
733 register struct iovec *iov;
734 struct enpdevice *addr;
735 int error;
6013a59e 736
bc2cef1e
SL
737 if (uio->uio_offset > RAM_SIZE)
738 return (ENODEV);
739 if (uio->uio_offset + iov->iov_len > RAM_SIZE)
740 iov->iov_len = RAM_SIZE - uio->uio_offset;
741 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
742 iov = uio->uio_iov;
743 error = useracc(iov->iov_base, iov->iov_len, 0);
744 if (error)
745 return (error);
746 enpcopy(&addr->enp_ram[uio->uio_offset], iov->iov_base, iov->iov_len);
747 uio->uio_resid -= iov->iov_len;
748 iov->iov_len = 0;
749 return (0);
6013a59e
SL
750}
751
bc2cef1e
SL
752enpr_write(dev, uio)
753 dev_t dev;
754 register struct uio *uio;
755{
756 register struct enpdevice *addr;
757 register struct iovec *iov;
758 register error;
6013a59e 759
bc2cef1e
SL
760 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
761 iov = uio->uio_iov;
762 if (uio->uio_offset > RAM_SIZE)
763 return (ENODEV);
764 if (uio->uio_offset + iov->iov_len > RAM_SIZE)
765 iov->iov_len = RAM_SIZE - uio->uio_offset;
766 error = useracc(iov->iov_base, iov->iov_len, 1);
767 if (error)
768 return (error);
769 enpcopy(iov->iov_base, &addr->enp_ram[uio->uio_offset], iov->iov_len);
770 uio->uio_resid -= iov->iov_len;
771 iov->iov_len = 0;
772 return (0);
773}
774
775enpr_ioctl(dev, cmd, data)
776 dev_t dev;
777 caddr_t data;
6013a59e 778{
bc2cef1e
SL
779 register struct enpdevice *addr;
780 register unit = ENPUNIT(dev);
781 register struct vba_device *ui;
6013a59e 782
bc2cef1e
SL
783 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
784 switch(cmd) {
785
786 case ENPIOGO:
787/* not needed if prom based version */
788 addr->enp_base = (int)addr;
789 addr->enp_intrvec = enp_softc[unit].es_ivec;
790 ENP_GO(addr, ENPSTART);
791 DELAY(200000);
792 enpinit(unit);
793 addr->enp_state = S_ENPRUN; /* it is running now */
794/* end of not needed */
795 break;
796
797 case ENPIORESET:
798 RESET_ENP(addr);
799 addr->enp_state = S_ENPRESET; /* it is reset now */
800 DELAY(100000);
801 break;
6013a59e 802 }
bc2cef1e 803 return (0);
6013a59e
SL
804}
805#endif