Annotation of 43BSDReno/sys/tahoeif/if_enp.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.