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