Annotation of Gnu-Mach/i386/i386at/if_par.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Mach Operating System
        !             3:  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
        !             4:  * All Rights Reserved.
        !             5:  * 
        !             6:  * Permission to use, copy, modify and distribute this software and its
        !             7:  * documentation is hereby granted, provided that both the copyright
        !             8:  * notice and this permission notice appear in all copies of the
        !             9:  * software, derivative works or modified versions, and any portions
        !            10:  * thereof, and that both notices appear in supporting documentation.
        !            11:  * 
        !            12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
        !            14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            15:  * 
        !            16:  * Carnegie Mellon requests users of this software to return to
        !            17:  * 
        !            18:  *  Software Distribution Coordinator  or  [email protected]
        !            19:  *  School of Computer Science
        !            20:  *  Carnegie Mellon University
        !            21:  *  Pittsburgh PA 15213-3890
        !            22:  * 
        !            23:  * any improvements or extensions that they make and grant Carnegie Mellon
        !            24:  * the rights to redistribute these changes.
        !            25:  */
        !            26: /* 
        !            27:  *     Parallel port network driver v1.1
        !            28:  *     All rights reserved.
        !            29:  */ 
        !            30: 
        !            31: /*
        !            32:  Subject: parallel network interface
        !            33: 
        !            34:  The printer network driver has the following hardware requirements for the
        !            35:  interconnection cable:
        !            36: 
        !            37:  Connections:
        !            38:  Side1         Side2           Function        Side1    / Side2
        !            39:  Pin 5         Pin 10  Interrupt strobe: send status (w)/send status (r)
        !            40:  Pin 2         Pin 15  Data bits       :       write    / read
        !            41:  Pin 3         Pin 13  Data bits       :       write    / read
        !            42:  Pin 4         Pin 12  Data bits       :       write    / read
        !            43:  Pin 6         Pin 11  Data bits       :       write    / read
        !            44:  Pin 10                Pin 5
        !            45:  Pin 11                Pin 6
        !            46:  Pin 12                Pin 4
        !            47:  Pin 13                Pin 3
        !            48:  Pin 15                Pin 2
        !            49:  Pins 18-25    Pins 18-25 (ground interconnections)
        !            50: 
        !            51:  The cable is "symmetric" in that either side can be plugged into either of the
        !            52:  computers.  
        !            53: 
        !            54:  The hardware requirements are as follows:
        !            55:  Port 0x378 must be writable with the following specifications:
        !            56:        Bit 4 -> pin 6
        !            57:        Bit 3 -> pin 5
        !            58:        Bit 2 -> pin 4
        !            59:        Bit 1 -> pin 3
        !            60:        Bit 0 -> pin 2
        !            61:  Port 0x379 must be readable with the following specifications:
        !            62:        Bit 7 <- pin 11
        !            63:        Bit 6 <- pin 10
        !            64:        Bit 5 <- pin 12
        !            65:        Bit 4 <- pin 13
        !            66:        Bit 3 <- pin 15
        !            67:  Port 0x37a must be readable and writable with the following specifications:
        !            68:        Bit 4 -> interrupt enable
        !            69:  So Port 0x378 connects to  Port 0x379 as
        !            70:        Bit 3 -> pin 5  :  pin 10 -> Bit 6      0x08 -> 0x40
        !            71: 
        !            72:        Bit 4 -> pin 6  :  pin 11 -> Bit 7      0x08<<1 -> ~ 0x80
        !            73:        Bit 2 -> pin 4  :  pin 12 -> Bit 5      0x07 -> 0x38
        !            74:        Bit 1 -> pin 3  :  pin 13 -> Bit 4      0x07 -> 0x38
        !            75:        Bit 0 -> pin 2  :  pin 15 -> Bit 3      0x07 -> 0x38
        !            76:  [note: bit 0 is considered the least significant bit, pins on the connector
        !            77:  are numbered starting with 1, -> represents sending data out on the bus, <-
        !            78:  represents reading data from the bus]
        !            79: 
        !            80:  Pins 1,7,8,9, and 16 are currently unused, and may be allowed to "float".
        !            81: 
        !            82:  The data is sent in 4 bit "nybbles", with the highest 4 bits being sent first.
        !            83: 
        !            84:  To bring up the interface, all that should be required is 
        !            85:        ifconfig par0 <your ip address> <connected machine's ip address> up
        !            86:  and to bring down the interface
        !            87:        ifconfig par0 down
        !            88:  You may get a warning message (such as printer out of paper) once you down
        !            89:  the interface, as the port is monitored for both printer and network activity
        !            90:  depending on whether par0 is up or down, and when you down the interface the
        !            91:  printer driver will then read whatever is on the port (which will be the last
        !            92:  message from the other computer).
        !            93:  */
        !            94: 
        !            95: #include <par.h>
        !            96: #if NPAR > 0
        !            97: 
        !            98: #include       <kern/time_out.h>
        !            99: #include       <device/device_types.h>
        !           100: #include       <device/errno.h>
        !           101: #include       <device/io_req.h>
        !           102: #include       <device/if_hdr.h>
        !           103: #include       <device/if_ether.h>
        !           104: #include       <device/net_status.h>
        !           105: #include       <device/net_io.h>
        !           106: 
        !           107: #include <i386/ipl.h>
        !           108: #include <i386/pio.h>
        !           109: #include <chips/busses.h>
        !           110: #include <i386at/if_par.h>
        !           111: 
        !           112: 
        !           113: int parintr();
        !           114: int parioctl();
        !           115: int parattach();
        !           116: int paroutput();
        !           117: 
        !           118: int (*oldvect)();
        !           119: int oldunit;
        !           120: 
        !           121: extern struct bus_device *lprinfo[];
        !           122: 
        !           123: int par_watch = 0;
        !           124: 
        !           125: struct par_softc {
        !           126:        struct ifnet ds_if;
        !           127:        u_char  ds_addr[6];             /* Ethernet hardware address */
        !           128:        u_char  address[6];
        !           129:        char    sc_buf[PARMTU+sizeof(struct ifnet *)];
        !           130: } par_softc[NPAR];
        !           131: 
        !           132: void parintoff(unit)
        !           133: int unit;
        !           134: {
        !           135: struct bus_device *lpdev = lprinfo[unit];
        !           136: 
        !           137:        outb(INTR(lpdev->address), 0x07);
        !           138:        par_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
        !           139:        ivect[lpdev->sysdep1] = oldvect;
        !           140:        iunit[lpdev->sysdep1] = oldunit;
        !           141: }
        !           142: 
        !           143: void parinit(unit)
        !           144: int unit;
        !           145: {
        !           146: struct bus_device *lpdev = lprinfo[unit];
        !           147: 
        !           148:        if (ivect[lpdev->sysdep1] != parintr) {
        !           149:                oldvect = ivect[lpdev->sysdep1];
        !           150:                oldunit = iunit[lpdev->sysdep1];
        !           151:                ivect[lpdev->sysdep1] = parintr;
        !           152:                iunit[lpdev->sysdep1] = unit;
        !           153:        }
        !           154:        outb(INTR(lpdev->address),0x11);
        !           155:        par_softc[unit].ds_if.if_flags |= IFF_RUNNING;
        !           156:        *(struct ifnet **)par_softc[unit].sc_buf = &par_softc[unit].ds_if;
        !           157: }
        !           158: 
        !           159: struct ether_header    par_eh;
        !           160: 
        !           161: int parattach(dev)
        !           162: struct bus_device *dev;
        !           163: {
        !           164:        u_char          unit = (u_char)dev->unit;
        !           165:        struct ifnet    *ifp;
        !           166:        struct par_softc*sp;
        !           167: 
        !           168:        if ((unit < 0) || (unit >= NPAR))
        !           169:                return(0);
        !           170:        printf("\n  par%d: at lpr%d, port = %x, spl = %d, pic = %d. ",
        !           171:                unit, unit, dev->address, dev->sysdep, dev->sysdep1);
        !           172: 
        !           173:        sp = &par_softc[unit];
        !           174:        ifp = &(sp->ds_if);
        !           175: 
        !           176:        *(sp->ds_addr)      = *(sp->address)     = 0x11;
        !           177:        *(sp->ds_addr + 1)  = *(sp->address + 1) = 0x22;
        !           178:        *(sp->ds_addr + 2)  = *(sp->address + 2) = 0x33;
        !           179:        *(sp->ds_addr + 3)  = *(sp->address + 3) = 0x44;
        !           180:        *(sp->ds_addr + 4)  = *(sp->address + 4) = 0x55;
        !           181:        *(sp->ds_addr + 5)  = *(sp->address + 5) = 0x66;
        !           182: 
        !           183:        par_eh.ether_dhost[5] = par_eh.ether_shost[0] = 0x11;
        !           184:        par_eh.ether_dhost[4] = par_eh.ether_shost[1] = 0x22;
        !           185:        par_eh.ether_dhost[3] = par_eh.ether_shost[2] = 0x33;
        !           186:        par_eh.ether_dhost[2] = par_eh.ether_shost[3] = 0x44;
        !           187:        par_eh.ether_dhost[1] = par_eh.ether_shost[4] = 0x55;
        !           188:        par_eh.ether_dhost[0] = par_eh.ether_shost[5] = 0x66;
        !           189:        par_eh.ether_type = htons(0x0800);
        !           190: 
        !           191:        printf("ethernet id [%x:%x:%x:%x:%x:%x]",
        !           192:                sp->address[0],sp->address[1],sp->address[2],
        !           193:                sp->address[3],sp->address[4],sp->address[5]);
        !           194: 
        !           195:        ifp->if_unit = unit;
        !           196:        ifp->if_mtu = ETHERMTU;
        !           197:        ifp->if_flags = IFF_POINTOPOINT;
        !           198:        ifp->if_header_size = sizeof(struct ether_header);
        !           199:        ifp->if_header_format = HDR_ETHERNET;
        !           200:        ifp->if_address_size = 6;
        !           201:        ifp->if_address = (char *)&par_softc[unit].address[0];
        !           202:        if_init_queues(ifp);
        !           203:        return(0);
        !           204: }
        !           205: 
        !           206: int parstart();        /* forward */
        !           207: 
        !           208: /*ARGSUSED*/
        !           209: paropen(dev, flag)
        !           210:        dev_t   dev;
        !           211:        int     flag;
        !           212: {
        !           213:        register int    unit = minor(dev);
        !           214: 
        !           215:        if (unit < 0 || unit >= NPAR)
        !           216:            return (ENXIO);
        !           217: 
        !           218:        par_softc[unit].ds_if.if_flags |= IFF_UP;
        !           219:        parinit(unit);
        !           220:        return(0);
        !           221: }
        !           222: 
        !           223: paroutput(dev, ior)
        !           224:        dev_t           dev;
        !           225:        io_req_t        ior;
        !           226: {
        !           227:        register int    unit = minor(dev);
        !           228: 
        !           229:        if (unit < 0 || unit >= NPAR)
        !           230:            return (ENXIO);
        !           231:        return (net_write(&par_softc[unit].ds_if, parstart, ior));
        !           232: }
        !           233: 
        !           234: parsetinput(dev, receive_port, priority, filter, filter_count)
        !           235:        dev_t           dev;
        !           236:        mach_port_t     receive_port;
        !           237:        int             priority;
        !           238:        filter_t        filter[];
        !           239:        unsigned int    filter_count;
        !           240: {
        !           241:        register int unit = minor(dev);
        !           242: 
        !           243:        if (unit < 0 || unit >= NPAR)
        !           244:            return (ENXIO);
        !           245: 
        !           246:        return (net_set_filter(&par_softc[unit].ds_if,
        !           247:                        receive_port, priority,
        !           248:                        filter, filter_count));
        !           249: }
        !           250: 
        !           251: int parstart(unit)
        !           252: {
        !           253:        struct ifnet    *ifp = &(par_softc[unit].ds_if);
        !           254:        u_short         addr = lprinfo[unit]->address;
        !           255:        struct sockaddr *dst;
        !           256:        int             len, i;
        !           257:        spl_t           s;
        !           258:        u_char          *mcp, c;
        !           259:        io_req_t        m;
        !           260: 
        !           261:        if (!(ifp->if_flags & IFF_RUNNING)) {
        !           262: #ifdef WHY
        !           263:                m_free(m);
        !           264:                parintoff(unit);
        !           265:                return(ENETDOWN);
        !           266: #else  WHY
        !           267:                parintoff(unit);
        !           268:                return(-1);
        !           269: #endif WHY
        !           270:        }
        !           271:        s = SPLNET();
        !           272: 
        !           273:        IF_DEQUEUE(&ifp->if_snd, m);
        !           274:        if (m == 0) {
        !           275:                splx(s);
        !           276:                return 0;
        !           277:        }
        !           278:        len = m->io_count;
        !           279:        if (par_watch)
        !           280:                printf("O%d\n",len);
        !           281:        len -= 14 /* XXX */;
        !           282:        mcp = (u_char *)m->io_data + 14 /* XXX */;
        !           283:        while (len--) {
        !           284:                c=*mcp++;
        !           285:                outb(OUTPUT(addr),((c&0x80)>>3) | ((c&0x70)>>4) | 0x08);
        !           286:                i=MAXSPIN;
        !           287:                while (!(inb(INPUT(addr))&0x40) && --i);
        !           288:                outb(OUTPUT(addr),((c&0x08)<<1) | (c&0x07));
        !           289:                i=MAXSPIN;
        !           290:                while ((inb(INPUT(addr))&0x40) && --i);
        !           291:        }
        !           292:        outb(OUTPUT(addr),(((c&0x08)<<1) | (c&0x07))^0x17);
        !           293:        iodone(m);
        !           294:        splx(s);
        !           295:        return (0);
        !           296: }
        !           297: 
        !           298: /*ARGSUSED*/
        !           299: pargetstat(dev, flavor, status, count)
        !           300:        dev_t           dev;
        !           301:        int             flavor;
        !           302:        dev_status_t    status;         /* pointer to OUT array */
        !           303:        unsigned int    *count;         /* out */
        !           304: {
        !           305:        register int    unit = minor(dev);
        !           306: 
        !           307:        if (unit < 0 || unit >= NPAR)
        !           308:            return (ENXIO);
        !           309: 
        !           310: 
        !           311:        switch (flavor) {
        !           312:            case NET_DSTADDR:
        !           313:                return (D_SUCCESS);
        !           314:                break;
        !           315:        }
        !           316: 
        !           317:        return (net_getstat(&par_softc[unit].ds_if,
        !           318:                            flavor,
        !           319:                            status,
        !           320:                            count));
        !           321: }
        !           322: 
        !           323: parsetstat(dev, flavor, status, count)
        !           324:        dev_t           dev;
        !           325:        int             flavor;
        !           326:        dev_status_t    status;
        !           327:        unsigned int    count;
        !           328: {
        !           329:        register int    unit = minor(dev);
        !           330:        register struct par_softc *sp;
        !           331: 
        !           332:        if (unit < 0 || unit >= NPAR)
        !           333:            return (ENXIO);
        !           334: 
        !           335:        sp = &par_softc[unit];
        !           336: 
        !           337:        switch (flavor) {
        !           338:            case NET_STATUS:
        !           339:            {
        !           340:                /*
        !           341:                 * All we can change are flags, and not many of those.
        !           342:                 */
        !           343:                register struct net_status *ns = (struct net_status *)status;
        !           344:                int     mode = 0;
        !           345: 
        !           346:                if (count < NET_STATUS_COUNT)
        !           347:                    return (D_INVALID_SIZE);
        !           348: 
        !           349: #if    0
        !           350:                /* ha ha ha */
        !           351:                if (ns->flags & IFF_ALLMULTI)
        !           352:                    mode |= MOD_ENAL;
        !           353:                if (ns->flags & IFF_PROMISC)
        !           354:                    mode |= MOD_PROM;
        !           355:                /*
        !           356:                 * Force a complete reset if the receive mode changes
        !           357:                 * so that these take effect immediately.
        !           358:                 */
        !           359:                if (sp->mode != mode) {
        !           360:                    sp->mode = mode;
        !           361:                    if (sp->flags & DSF_RUNNING) {
        !           362:                        sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
        !           363:                        parinit(unit);
        !           364:                    }
        !           365:                }
        !           366: #endif
        !           367:                break;
        !           368:            }
        !           369:            case NET_ADDRESS:
        !           370:            {
        !           371:                register union ether_cvt {
        !           372:                    char        addr[6];
        !           373:                    int         lwd[2];
        !           374:                } *ec = (union ether_cvt *)status;
        !           375: 
        !           376:                if (count < sizeof(*ec)/sizeof(int))
        !           377:                    return (D_INVALID_SIZE);
        !           378: 
        !           379:                ec->lwd[0] = ntohl(ec->lwd[0]);
        !           380:                ec->lwd[1] = ntohl(ec->lwd[1]);
        !           381: /*             at3c501seteh(sp->base, ec->addr);*/
        !           382:                break;
        !           383:            }
        !           384: 
        !           385:            default:
        !           386:                return (D_INVALID_OPERATION);
        !           387:        }
        !           388:        return (D_SUCCESS);
        !           389: }
        !           390: 
        !           391: int parintr(unit)
        !           392: int unit;
        !           393: {
        !           394:        register struct par_softc *sp = &par_softc[unit];
        !           395:        u_short         addr = lprinfo[unit]->address;
        !           396:        char            *trav = sp->sc_buf;
        !           397:        short           len = 0;
        !           398:        u_char          c, c2;
        !           399:        int             i;
        !           400:        ipc_kmsg_t              new_kmsg;
        !           401:        struct ether_header     *ehp;
        !           402:        struct packet_header    *pkt;
        !           403:        struct ifnet *ifp = &(sp->ds_if);
        !           404: 
        !           405:        do {
        !           406:                c2=inb(INPUT(addr));
        !           407:                outb(OUTPUT(addr),0x08);
        !           408:                i=MAXSPIN;
        !           409:                while(((c=inb(INPUT(addr)))&0x40) && --i);
        !           410: 
        !           411:                c = inb(INPUT(addr));
        !           412:                outb(OUTPUT(addr),0x00);
        !           413:                if (!i)
        !           414:                        break;
        !           415: 
        !           416:                if (++len > ETHERMTU) {
        !           417:                        trav = sp->sc_buf;
        !           418:                        len = 0;
        !           419:                        continue;
        !           420:                }
        !           421:                *trav++ = ((~c2)&0x80) | ((c2&0x38)<<1) | (((~c)&0x80)>>4) | ((c&0x38)>>3);
        !           422:                i=MAXSPIN;
        !           423:                while (!((c2=inb(INPUT(addr)))&0x40) && --i)
        !           424:                        if (((c2^0xb8)&0xf8) == (c&0xf8))
        !           425:                goto end;
        !           426:        } while (i);
        !           427: end:
        !           428:        if (len < 20)           /* line noise ? */
        !           429:                return;
        !           430:        if (par_watch)
        !           431:                printf("I%d\n",len);
        !           432: 
        !           433:        new_kmsg = net_kmsg_get();
        !           434:        if (new_kmsg == IKM_NULL) {
        !           435:                /*
        !           436:                 * Drop the packet.
        !           437:                */
        !           438:                sp->ds_if.if_rcvdrops++;    
        !           439:                return;
        !           440:        }
        !           441:        ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
        !           442:        pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
        !           443:        *ehp = par_eh;
        !           444: 
        !           445:        bcopy (sp->sc_buf, (char *) (pkt + 1), len);
        !           446: 
        !           447:        pkt->type = ehp->ether_type;
        !           448:        pkt->length = len + sizeof(struct packet_header);
        !           449:        /*
        !           450:         * Hand the packet to the network module.
        !           451:         */
        !           452:        net_packet(ifp, new_kmsg, pkt->length,
        !           453:                   ethernet_priority(new_kmsg));
        !           454:        return(0);
        !           455: }
        !           456: #endif

unix.superglobalmegacorp.com

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