BSD 4_4 release
[unix-history] / usr / src / sys / tahoe / if / if_enp.c
CommitLineData
357f1ef5
MK
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
979ea28d
MK
5 * This code is derived from software contributed to Berkeley by
6 * Computer Consoles Inc.
7 *
ad787160
C
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
357f1ef5 23 *
ad787160
C
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)if_enp.c 7.8 (Berkeley) 12/16/90
357f1ef5 37 */
6013a59e
SL
38
39#include "enp.h"
6013a59e 40#if NENP > 0
6013a59e 41/*
7779e59b 42 * CMC ENP-20 Ethernet Controller.
6013a59e 43 */
b28b3a13
KB
44#include "sys/param.h"
45#include "sys/systm.h"
46#include "sys/mbuf.h"
47#include "sys/buf.h"
48#include "sys/protosw.h"
49#include "sys/socket.h"
50#include "sys/vmmac.h"
51#include "sys/ioctl.h"
52#include "sys/errno.h"
53#include "sys/vmparam.h"
54#include "sys/syslog.h"
55#include "sys/uio.h"
6013a59e 56
b28b3a13
KB
57#include "net/if.h"
58#include "net/netisr.h"
59#include "net/route.h"
bc2cef1e 60#ifdef INET
b28b3a13
KB
61#include "netinet/in.h"
62#include "netinet/in_systm.h"
63#include "netinet/in_var.h"
64#include "netinet/ip.h"
65#include "netinet/ip_var.h"
66#include "netinet/if_ether.h"
bc2cef1e
SL
67#endif
68#ifdef NS
b28b3a13
KB
69#include "netns/ns.h"
70#include "netns/ns_if.h"
bc2cef1e
SL
71#endif
72
b28b3a13
KB
73#include "../include/cpu.h"
74#include "../include/pte.h"
75#include "../include/mtpr.h"
6013a59e 76
b28b3a13
KB
77#include "../vba/vbavar.h"
78#include "../if/if_enpreg.h"
6013a59e 79
bc2cef1e
SL
80#define ENPSTART 0xf02000 /* standard enp start addr */
81#define ENPUNIT(dev) (minor(dev)) /* for enp ram devices */
7779e59b
SL
82/* macros for dealing with longs in i/o space */
83#define ENPGETLONG(a) ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1]))
84#define ENPSETLONG(a,v) \
85 { register u_short *wp = (u_short *)(a); \
86 wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];}
6013a59e
SL
87
88int enpprobe(), enpattach(), enpintr();
fea301bf 89long enpstd[] = { 0xfff41000, 0xfff61000, 0 };
bc2cef1e 90struct vba_device *enpinfo[NENP];
6013a59e 91struct vba_driver enpdriver =
bc2cef1e 92 { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 };
6013a59e 93
979ea28d 94int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart();
6013a59e
SL
95struct mbuf *enpget();
96
6013a59e
SL
97/*
98 * Ethernet software status per interface.
99 *
100 * Each interface is referenced by a network interface structure,
101 * es_if, which the routing code uses to locate the interface.
102 * This structure contains the output queue for the interface, its address, ...
103 */
bc2cef1e
SL
104struct enp_softc {
105 struct arpcom es_ac; /* common ethernet structures */
106#define es_if es_ac.ac_if
7779e59b 107#define es_addr es_ac.ac_enaddr
bc2cef1e 108 short es_ivec; /* interrupt vector */
bc2cef1e
SL
109} enp_softc[NENP];
110extern struct ifnet loif;
111
112enpprobe(reg, vi)
113 caddr_t reg;
114 struct vba_device *vi;
6013a59e 115{
bc2cef1e
SL
116 register br, cvec; /* must be r12, r11 */
117 register struct enpdevice *addr = (struct enpdevice *)reg;
118 struct enp_softc *es = &enp_softc[vi->ui_unit];
6013a59e 119
bc2cef1e 120#ifdef lint
9d61b7ff 121 br = 0; cvec = br; br = cvec;
bc2cef1e
SL
122 enpintr(0);
123#endif
9d61b7ff 124 if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2))
bc2cef1e
SL
125 return (0);
126 es->es_ivec = --vi->ui_hd->vh_lastiv;
127 addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */
128 br = 0x14, cvec = es->es_ivec; /* XXX */
129 return (sizeof (struct enpdevice));
6013a59e
SL
130}
131
132/*
133 * Interface exists: make available by filling in network interface
134 * record. System will initialize the interface when it is ready
135 * to accept packets.
136 */
bc2cef1e
SL
137enpattach(ui)
138 register struct vba_device *ui;
6013a59e 139{
bc2cef1e
SL
140 struct enp_softc *es = &enp_softc[ui->ui_unit];
141 register struct ifnet *ifp = &es->es_if;
6013a59e 142
bc2cef1e 143 ifp->if_unit = ui->ui_unit;
6013a59e
SL
144 ifp->if_name = "enp";
145 ifp->if_mtu = ETHERMTU;
6013a59e
SL
146 ifp->if_init = enpinit;
147 ifp->if_ioctl = enpioctl;
385e8f24 148 ifp->if_output = ether_output;
979ea28d 149 ifp->if_start = enpstart;
003ca8a0
MK
150 ifp->if_reset = enpreset;
151 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
6013a59e
SL
152 if_attach(ifp);
153}
154
6013a59e 155/*
bc2cef1e 156 * Reset of interface after "system" reset.
6013a59e 157 */
bc2cef1e
SL
158enpreset(unit, vban)
159 int unit, vban;
6013a59e 160{
bc2cef1e 161 register struct vba_device *ui;
6013a59e 162
bc2cef1e
SL
163 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
164 ui->ui_vbanum != vban)
165 return;
166 printf(" enp%d", unit);
6013a59e
SL
167 enpinit(unit);
168}
169
170/*
bc2cef1e 171 * Initialization of interface; clear recorded pending operations.
6013a59e 172 */
bc2cef1e
SL
173enpinit(unit)
174 int unit;
6013a59e 175{
bc2cef1e
SL
176 struct enp_softc *es = &enp_softc[unit];
177 register struct vba_device *ui = enpinfo[unit];
178 struct enpdevice *addr;
179 register struct ifnet *ifp = &es->es_if;
180 int s;
6013a59e 181
bc2cef1e
SL
182 if (ifp->if_addrlist == (struct ifaddr *)0)
183 return;
184 if ((ifp->if_flags & IFF_RUNNING) == 0) {
185 addr = (struct enpdevice *)ui->ui_addr;
186 s = splimp();
187 RESET_ENP(addr);
188 DELAY(200000);
bc2cef1e
SL
189 es->es_if.if_flags |= IFF_RUNNING;
190 splx(s);
191 }
6013a59e
SL
192}
193
6013a59e
SL
194/*
195 * Ethernet interface interrupt.
196 */
bc2cef1e
SL
197enpintr(unit)
198 int unit;
6013a59e 199{
bc2cef1e
SL
200 register struct enpdevice *addr;
201 register BCB *bcbp;
6013a59e 202
bc2cef1e 203 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
9d61b7ff 204#if ENP == 30
bc2cef1e 205 if (!IS_ENP_INTR(addr))
6013a59e 206 return;
bc2cef1e 207 ACK_ENP_INTR(addr);
9d61b7ff
SL
208#endif
209 while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) {
979ea28d 210 enpread(&enp_softc[unit], bcbp);
9d61b7ff 211 (void) ringput((RING *)&addr->enp_enpfree, bcbp);
6013a59e 212 }
6013a59e
SL
213}
214
215/*
216 * Read input packet, examine its packet type, and enqueue it.
217 */
9d61b7ff 218enpread(es, bcbp)
bc2cef1e
SL
219 struct enp_softc *es;
220 register BCB *bcbp;
6013a59e
SL
221{
222 register struct ether_header *enp;
223 struct mbuf *m;
9d61b7ff 224 int s, len, off, resid;
6013a59e
SL
225
226 es->es_if.if_ipackets++;
6013a59e
SL
227 /*
228 * Get input data length.
229 * Get pointer to ethernet header (in input buffer).
230 * Deal with trailer protocol: if type is PUP trailer
231 * get true type from first 16-bit word past data.
232 * Remember that type was trailer by setting off.
233 */
bc2cef1e 234 len = bcbp->b_msglen - sizeof (struct ether_header);
7779e59b 235 enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr);
bc2cef1e
SL
236#define enpdataaddr(enp, off, type) \
237 ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off))))
238 enp->ether_type = ntohs((u_short)enp->ether_type);
239 if (enp->ether_type >= ETHERTYPE_TRAIL &&
240 enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
241 off = (enp->ether_type - ETHERTYPE_TRAIL) * 512;
242 if (off >= ETHERMTU)
979ea28d 243 return;
bc2cef1e
SL
244 enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *));
245 resid = ntohs(*(enpdataaddr(enp, off+2, u_short *)));
246 if (off + resid > len)
979ea28d 247 return;
6013a59e 248 len = off + resid;
bc2cef1e 249 } else
6013a59e 250 off = 0;
bc2cef1e 251 if (len == 0)
979ea28d 252 return;
6013a59e 253
6013a59e
SL
254 /*
255 * Pull packet off interface. Off is nonzero if packet
256 * has trailing header; enpget will then force this header
979ea28d 257 * information to be at the front.
6013a59e 258 */
7779e59b 259 m = enpget((u_char *)enp, len, off, &es->es_if);
bc2cef1e 260 if (m == 0)
979ea28d 261 return;
385e8f24 262 ether_input(&es->es_if, enp, m);
6013a59e
SL
263}
264
979ea28d 265enpstart(ifp)
bc2cef1e 266 struct ifnet *ifp;
6013a59e 267{
6013a59e 268
979ea28d 269 if (enpput(ifp))
003ca8a0
MK
270 return (ENOBUFS);
271 else
272 return (0);
6013a59e
SL
273}
274
275/*
bc2cef1e 276 * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus.
6013a59e 277 */
979ea28d
MK
278enpput(ifp)
279struct ifnet *ifp;
6013a59e
SL
280{
281 register BCB *bcbp;
bc2cef1e 282 register struct enpdevice *addr;
6013a59e
SL
283 register struct mbuf *mp;
284 register u_char *bp;
bc2cef1e 285 register u_int len;
003ca8a0 286 int unit = ifp->if_unit, ret = 1;
979ea28d 287 struct mbuf *m;
6013a59e 288
bc2cef1e 289 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
979ea28d 290again:
003ca8a0
MK
291 if (ringempty((RING *)&addr->enp_hostfree)) {
292 /* ifp->if_flags |= IFF_OACTIVE; */
293 return (ret);
294 }
979ea28d 295 IF_DEQUEUE(&ifp->if_snd, m);
003ca8a0
MK
296 if (m == 0) {
297 ifp->if_flags &= ~IFF_OACTIVE;
298 return (0);
299 }
9d61b7ff 300 bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree);
6013a59e 301 bcbp->b_len = 0;
7779e59b 302 bp = (u_char *)ENPGETLONG(&bcbp->b_addr);
bc2cef1e 303 for (mp = m; mp; mp = mp->m_next) {
6013a59e 304 len = mp->m_len;
bc2cef1e 305 if (len == 0)
6013a59e 306 continue;
003ca8a0 307 enpcopy(mtod(mp, u_char *), bp, len);
6013a59e
SL
308 bp += len;
309 bcbp->b_len += len;
310 }
003ca8a0 311 bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len);
6013a59e 312 bcbp->b_reserved = 0;
9d61b7ff 313 if (ringput((RING *)&addr->enp_toenp, bcbp) == 1)
bc2cef1e 314 INTR_ENP(addr);
6013a59e 315 m_freem(m);
003ca8a0 316 ret = 0;
979ea28d 317 goto again;
6013a59e
SL
318}
319
320/*
bc2cef1e 321 * Routine to copy from VERSAbus memory into mbufs.
6013a59e
SL
322 *
323 * Warning: This makes the fairly safe assumption that
324 * mbufs have even lengths.
325 */
326struct mbuf *
979ea28d 327enpget(rxbuf, totlen, off, ifp)
bc2cef1e 328 u_char *rxbuf;
979ea28d 329 int totlen, off;
bc2cef1e 330 struct ifnet *ifp;
6013a59e 331{
003ca8a0 332 register u_char *cp;
6013a59e 333 register struct mbuf *m;
bc2cef1e 334 struct mbuf *top = 0, **mp = &top;
979ea28d
MK
335 int len;
336 u_char *packet_end;
337
338 rxbuf += sizeof (struct ether_header);
339 cp = rxbuf;
340 packet_end = cp + totlen;
341 if (off) {
342 off += 2 * sizeof(u_short);
343 totlen -= 2 *sizeof(u_short);
344 cp = rxbuf + off;
345 }
346
347 MGETHDR(m, M_DONTWAIT, MT_DATA);
348 if (m == 0)
349 return (0);
350 m->m_pkthdr.rcvif = ifp;
351 m->m_pkthdr.len = totlen;
352 m->m_len = MHLEN;
6013a59e 353
bc2cef1e 354 while (totlen > 0) {
979ea28d
MK
355 if (top) {
356 MGET(m, M_DONTWAIT, MT_DATA);
357 if (m == 0) {
358 m_freem(top);
359 return (0);
360 }
361 m->m_len = MLEN;
362 }
363 len = min(totlen, (packet_end - cp));
364 if (len >= MINCLSIZE) {
365 MCLGET(m, M_DONTWAIT);
366 if (m->m_flags & M_EXT)
367 m->m_len = len = min(len, MCLBYTES);
bc2cef1e 368 else
979ea28d 369 len = m->m_len;
bc2cef1e 370 } else {
bc2cef1e 371 /*
979ea28d 372 * Place initial small packet/header at end of mbuf.
bc2cef1e 373 */
979ea28d 374 if (len < m->m_len) {
003ca8a0 375 if (top == 0 && len + max_linkhdr <= m->m_len)
979ea28d
MK
376 m->m_data += max_linkhdr;
377 m->m_len = len;
378 } else
379 len = m->m_len;
bc2cef1e 380 }
003ca8a0 381 enpcopy(cp, mtod(m, u_char *), (u_int)len);
6013a59e
SL
382 *mp = m;
383 mp = &m->m_next;
979ea28d
MK
384 totlen -= len;
385 cp += len;
386 if (cp == packet_end)
387 cp = rxbuf;
6013a59e
SL
388 }
389 return (top);
6013a59e
SL
390}
391
bc2cef1e 392enpcopy(from, to, cnt)
9d61b7ff
SL
393 register u_char *from, *to;
394 register u_int cnt;
bc2cef1e
SL
395{
396 register c;
397 register short *f, *t;
398
399 if (((int)from&01) && ((int)to&01)) {
400 /* source & dest at odd addresses */
401 *to++ = *from++;
402 --cnt;
403 }
404 if (cnt > 1 && (((int)to&01) == 0) && (((int)from&01) == 0)) {
405 t = (short *)to;
406 f = (short *)from;
407 for (c = cnt>>1; c; --c) /* even address copy */
408 *t++ = *f++;
409 cnt &= 1;
410 if (cnt) { /* odd len */
9d61b7ff
SL
411 from = (u_char *)f;
412 to = (u_char *)t;
bc2cef1e
SL
413 *to = *from;
414 }
415 }
9d61b7ff 416 while ((int)cnt-- > 0) /* one of the address(es) must be odd */
bc2cef1e
SL
417 *to++ = *from++;
418}
419
6013a59e
SL
420/*
421 * Process an ioctl request.
6013a59e 422 */
6013a59e 423enpioctl(ifp, cmd, data)
bc2cef1e
SL
424 register struct ifnet *ifp;
425 int cmd;
426 caddr_t data;
6013a59e 427{
bc2cef1e
SL
428 register struct ifaddr *ifa = (struct ifaddr *)data;
429 struct enpdevice *addr;
430 int s = splimp(), error = 0;
6013a59e
SL
431
432 switch (cmd) {
433
434 case SIOCSIFADDR:
bc2cef1e 435 ifp->if_flags |= IFF_UP;
385e8f24 436 switch (ifa->ifa_addr->sa_family) {
bc2cef1e
SL
437#ifdef INET
438 case AF_INET:
439 enpinit(ifp->if_unit);
440 ((struct arpcom *)ifp)->ac_ipaddr =
441 IA_SIN(ifa)->sin_addr;
442 arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
443 break;
444#endif
445#ifdef NS
446 case AF_NS: {
447 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
448 struct enp_softc *es = &enp_softc[ifp->if_unit];
449
450 if (!ns_nullhost(*ina)) {
451 ifp->if_flags &= ~IFF_RUNNING;
452 addr = (struct enpdevice *)
453 enpinfo[ifp->if_unit]->ui_addr;
454 enpsetaddr(ifp->if_unit, addr,
455 ina->x_host.c_host);
456 } else
7779e59b 457 ina->x_host = *(union ns_host *)es->es_addr;
bc2cef1e 458 enpinit(ifp->if_unit);
6013a59e
SL
459 break;
460 }
bc2cef1e
SL
461#endif
462 default:
463 enpinit(ifp->if_unit);
464 break;
6013a59e 465 }
6013a59e
SL
466 break;
467
bc2cef1e
SL
468 case SIOCSIFFLAGS:
469 if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) {
470 enpinit(ifp->if_unit); /* reset board */
471 ifp->if_flags &= ~IFF_RUNNING;
472 } else if (ifp->if_flags&IFF_UP &&
473 (ifp->if_flags&IFF_RUNNING) == 0)
474 enpinit(ifp->if_unit);
6013a59e
SL
475 break;
476
477 default:
478 error = EINVAL;
479 }
bc2cef1e
SL
480 splx(s);
481 return (error);
6013a59e
SL
482}
483
bc2cef1e
SL
484enpsetaddr(unit, addr, enaddr)
485 int unit;
486 struct enpdevice *addr;
487 u_char *enaddr;
6013a59e 488{
7779e59b
SL
489
490 enpcopy(enaddr, addr->enp_addr.e_baseaddr.ea_addr,
491 sizeof (struct ether_addr));
bc2cef1e 492 enpinit(unit);
7779e59b
SL
493 enpgetaddr(unit, addr);
494}
495
496enpgetaddr(unit, addr)
497 int unit;
498 struct enpdevice *addr;
499{
500 struct enp_softc *es = &enp_softc[unit];
501
502 enpcopy(addr->enp_addr.e_baseaddr.ea_addr, es->es_addr,
503 sizeof (struct ether_addr));
504 printf("enp%d: hardware address %s\n",
505 unit, ether_sprintf(es->es_addr));
6013a59e
SL
506}
507
508/*
bc2cef1e 509 * Routines to synchronize enp and host.
6013a59e 510 */
9d61b7ff 511#ifdef notdef
6013a59e 512static
bc2cef1e
SL
513ringinit(rp, size)
514 register RING *rp;
6013a59e 515{
6013a59e
SL
516
517 rp->r_rdidx = rp->r_wrtidx = 0;
518 rp->r_size = size;
519}
520
521static
9d61b7ff 522ringfull(rp)
bc2cef1e 523 register RING *rp;
6013a59e 524{
9d61b7ff 525 register short idx;
bc2cef1e 526
9d61b7ff
SL
527 idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
528 return (idx == rp->r_rdidx);
6013a59e
SL
529}
530
531static
9d61b7ff 532fir(rp)
bc2cef1e 533 register RING *rp;
6013a59e 534{
6013a59e 535
9d61b7ff
SL
536 return (rp->r_rdidx != rp->r_wrtidx ? rp->r_slot[rp->r_rdidx] : 0);
537}
538#endif
539
540static
541ringempty(rp)
542 register RING *rp;
543{
544
545 return (rp->r_rdidx == rp->r_wrtidx);
6013a59e
SL
546}
547
548static
bc2cef1e
SL
549ringput(rp, v)
550 register RING *rp;
9d61b7ff 551 BCB *v;
6013a59e
SL
552{
553 register int idx;
6013a59e
SL
554
555 idx = (rp->r_wrtidx + 1) & (rp->r_size-1);
bc2cef1e 556 if (idx != rp->r_rdidx) {
7779e59b 557 ENPSETLONG(&rp->r_slot[rp->r_wrtidx], v);
6013a59e 558 rp->r_wrtidx = idx;
bc2cef1e 559 if ((idx -= rp->r_rdidx) < 0)
6013a59e 560 idx += rp->r_size;
bc2cef1e 561 return (idx); /* num ring entries */
6013a59e 562 }
bc2cef1e 563 return (0);
6013a59e
SL
564}
565
566static
bc2cef1e
SL
567ringget(rp)
568 register RING *rp;
6013a59e
SL
569{
570 register int i = 0;
bc2cef1e
SL
571
572 if (rp->r_rdidx != rp->r_wrtidx) {
7779e59b 573 i = ENPGETLONG(&rp->r_slot[rp->r_rdidx]);
6013a59e
SL
574 rp->r_rdidx = (++rp->r_rdidx) & (rp->r_size-1);
575 }
bc2cef1e 576 return (i);
6013a59e
SL
577}
578
bc2cef1e
SL
579/*
580 * ENP Ram device.
581 */
582enpr_open(dev)
583 dev_t dev;
6013a59e 584{
bc2cef1e
SL
585 register int unit = ENPUNIT(dev);
586 struct vba_device *ui;
587 struct enpdevice *addr;
6013a59e 588
bc2cef1e
SL
589 if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 ||
590 (addr = (struct enpdevice *)ui->ui_addr) == 0)
591 return (ENODEV);
592 if (addr->enp_state != S_ENPRESET)
593 return (EACCES); /* enp is not in reset state, don't open */
594 return (0);
6013a59e
SL
595}
596
9d61b7ff 597/*ARGSUSED*/
bc2cef1e
SL
598enpr_close(dev)
599 dev_t dev;
6013a59e 600{
6013a59e 601
bc2cef1e 602 return (0);
6013a59e
SL
603}
604
bc2cef1e
SL
605enpr_read(dev, uio)
606 dev_t dev;
607 register struct uio *uio;
6013a59e 608{
bc2cef1e
SL
609 register struct iovec *iov;
610 struct enpdevice *addr;
6013a59e 611
bc2cef1e
SL
612 if (uio->uio_offset > RAM_SIZE)
613 return (ENODEV);
9d61b7ff 614 iov = uio->uio_iov;
bc2cef1e
SL
615 if (uio->uio_offset + iov->iov_len > RAM_SIZE)
616 iov->iov_len = RAM_SIZE - uio->uio_offset;
617 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
7779e59b
SL
618 if (useracc(iov->iov_base, (unsigned)iov->iov_len, 0) == 0)
619 return (EFAULT);
9d61b7ff
SL
620 enpcopy((u_char *)&addr->enp_ram[uio->uio_offset],
621 (u_char *)iov->iov_base, (u_int)iov->iov_len);
bc2cef1e
SL
622 uio->uio_resid -= iov->iov_len;
623 iov->iov_len = 0;
624 return (0);
6013a59e
SL
625}
626
bc2cef1e
SL
627enpr_write(dev, uio)
628 dev_t dev;
629 register struct uio *uio;
630{
631 register struct enpdevice *addr;
632 register struct iovec *iov;
6013a59e 633
bc2cef1e
SL
634 addr = (struct enpdevice *)enpinfo[ENPUNIT(dev)]->ui_addr;
635 iov = uio->uio_iov;
636 if (uio->uio_offset > RAM_SIZE)
637 return (ENODEV);
638 if (uio->uio_offset + iov->iov_len > RAM_SIZE)
639 iov->iov_len = RAM_SIZE - uio->uio_offset;
7779e59b
SL
640 if (useracc(iov->iov_base, (unsigned)iov->iov_len, 1) == 0)
641 return (EFAULT);
9d61b7ff
SL
642 enpcopy((u_char *)iov->iov_base,
643 (u_char *)&addr->enp_ram[uio->uio_offset], (u_int)iov->iov_len);
bc2cef1e 644 uio->uio_resid -= iov->iov_len;
9bd54d0d 645 uio->uio_offset += iov->iov_len;
bc2cef1e
SL
646 iov->iov_len = 0;
647 return (0);
648}
649
9d61b7ff 650/*ARGSUSED*/
bc2cef1e
SL
651enpr_ioctl(dev, cmd, data)
652 dev_t dev;
653 caddr_t data;
6013a59e 654{
bc2cef1e 655 register unit = ENPUNIT(dev);
7779e59b 656 struct enpdevice *addr;
6013a59e 657
bc2cef1e
SL
658 addr = (struct enpdevice *)enpinfo[unit]->ui_addr;
659 switch(cmd) {
660
661 case ENPIOGO:
7779e59b 662 ENPSETLONG(&addr->enp_base, addr);
bc2cef1e
SL
663 addr->enp_intrvec = enp_softc[unit].es_ivec;
664 ENP_GO(addr, ENPSTART);
665 DELAY(200000);
666 enpinit(unit);
7779e59b
SL
667 /*
668 * Fetch Ethernet address after link level
669 * is booted (firmware copies manufacturer's
670 * address from on-board ROM).
671 */
672 enpgetaddr(unit, addr);
673 addr->enp_state = S_ENPRUN;
bc2cef1e
SL
674 break;
675
676 case ENPIORESET:
677 RESET_ENP(addr);
7779e59b 678 addr->enp_state = S_ENPRESET;
bc2cef1e
SL
679 DELAY(100000);
680 break;
7779e59b
SL
681 default:
682 return (EINVAL);
6013a59e 683 }
bc2cef1e 684 return (0);
6013a59e
SL
685}
686#endif