Annotation of Gnu-Mach/i386/i386at/if_par.c, revision 1.1.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.