Annotation of Gnu-Mach/i386/i386at/if_ne.c, revision 1.1.1.1

1.1       root        1: /*-
                      2:  * Copyright (c) 1990, 1991 William F. Jolitz.
                      3:  * Copyright (c) 1990 The Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *      This product includes software developed by the University of
                     17:  *      California, Berkeley and its contributors.
                     18:  * 4. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  *
                     34:  *      @(#)if_ne.c     7.4 (Berkeley) 5/21/91
                     35:  */
                     36: 
                     37: /*
                     38:  * NE2000 Ethernet driver
                     39:  *
                     40:  * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
                     41:  * insight on the ne2000 gained from Robert Clements PC/FTP driver.
                     42:  */
                     43: 
                     44: #include <ne.h>
                     45: 
                     46: 
                     47: #if NNE > 0
                     48: #ifdef  MACH_KERNEL
                     49: 
                     50: #include        <kern/time_out.h>
                     51: #include        <device/device_types.h>
                     52: #include        <device/errno.h>
                     53: #include        <device/io_req.h>
                     54: #include        <device/if_hdr.h>
                     55: #include        <device/if_ether.h>
                     56: #include        <device/net_status.h>
                     57: #include        <device/net_io.h>
                     58: #include        <i386at/ds8390.h>
                     59: #include        <i386at/if_nereg.h>
                     60: #include       <i386/ipl.h>
                     61: #include       <chips/busses.h>
                     62: #ifdef FIPC
                     63: #include       <ipc/fipc.h>
                     64: #endif /* FIPC */
                     65: 
                     66: #else  MACH_KERNEL
                     67: 
                     68: #include        <sys/param.h>
                     69: #include        <mach/vm_param.h>
                     70: #include        <sys/systm.h>
                     71: #include        <sys/mbuf.h>
                     72: #include        <sys/table.h>
                     73: #include        <sys/buf.h>
                     74: #include        <sys/protosw.h>
                     75: #include        <sys/socket.h>
                     76: #include        <sys/vmmac.h>
                     77: #include        <sys/ioctl.h>
                     78: #include        <sys/errno.h>
                     79: #include        <sys/syslog.h>
                     80: #include        <vm/vm_kern.h>
                     81: 
                     82: #include        <net/if.h>
                     83: #include        <net/if_types.h>
                     84: #include        <net/route.h>
                     85: 
                     86: #include        <netinet/in.h>
                     87: #include        <netinet/in_systm.h>
                     88: #include        <netinet/in_var.h>
                     89: #include        <netinet/ip.h>
                     90: #include        <netinet/if_ether.h>
                     91: 
                     92: #include        <netns/ns.h>
                     93: #include        <netns/ns_if.h>
                     94: 
                     95: 
                     96: #include        <i386/ipl.h>
                     97: #include        <i386at/atbus.h>
                     98: #include        <i386at/ds8390.h>
                     99: #include        <i386at/if_nereg.h>
                    100: #include        <i386/handler.h>
                    101: #include        <i386/dispatcher.h>
                    102: int    ether_output();
                    103: int    neioctl();
                    104: 
                    105: #endif
                    106: 
                    107: 
                    108: int    neprobe();
                    109: void    neattach();
                    110: int    neintr();
                    111: int    nestart();
                    112: int    neinit();
                    113: 
                    114: static vm_offset_t ne_std[NNE] = {0};
                    115: static struct bus_device *ne_info[NNE];
                    116: struct  bus_driver nedriver =
                    117:         { neprobe, 0, neattach, 0, ne_std, "ne", ne_info, 0, 0, 0 };
                    118: 
                    119: #define ETHER_MIN_LEN 64
                    120: #define ETHER_MAX_LEN 1536
                    121: #define SPLNET spl6
                    122: /*
                    123:  * Ethernet software status per interface.
                    124:  *
                    125:  * Each interface is referenced by a network interface structure,
                    126:  * ns_if, which the routing code uses to locate the interface.
                    127:  * This structure contains the output queue for the interface, its address, ...
                    128:  */
                    129: typedef struct {
                    130: 
                    131: #ifdef MACH_KERNEL
                    132:        struct  ifnet ds_if;
                    133:        u_char  ds_addr[6];
                    134: #else  MACH_KERNEL
                    135:         struct  arpcom ns_ac;           /* Ethernet common part */
                    136: #define ds_if   ns_ac.ac_if             /* network-visible interface */
                    137: #define ds_addr ns_ac.ac_enaddr         /* hardware Ethernet address */
                    138: #endif  MACH_KERNEL
                    139: 
                    140:         int     ns_flags;
                    141: #define DSF_LOCK        1               /* block re-entering enstart */
                    142: #define DSF_RUNNING    2
                    143:         int     ns_oactive ;
                    144:         int     ns_mask ;
                    145:         int     ns_ba;                  /* byte addr in buffer ram of inc pkt */
                    146:         int     ns_cur;                 /* current page being filled */
                    147:         struct  prhdr   ns_ph;          /* hardware header of incoming packet*/
                    148:         struct  ether_header ns_eh;     /* header of incoming packet */
                    149:         u_char  ns_pb[2048 /*ETHERMTU+sizeof(long)*/];
                    150:         short   ns_txstart;             /* transmitter buffer start */
                    151:         short   ns_rxend;               /* recevier buffer end */
                    152:         short   ns_rxbndry;             /* recevier buffer boundary */
                    153:         caddr_t ns_port;                /* i/o port base */
                    154:         short   ns_mode;                /* word/byte mode */
                    155:        int     mode;
                    156:        short   card_present;
                    157: #ifndef MACH_KERNEL
                    158:         ihandler_t      handler;
                    159:         ihandler_id_t   *handler_id;
                    160: #endif MACH_KERNEL
                    161: 
                    162: } ne_softc_t;
                    163: ne_softc_t ne_softc[NNE];
                    164: 
                    165: #define PAT(n)  (0xa55a + 37*(n))
                    166: 
                    167: u_short boarddata[16];
                    168:  
                    169: /*
                    170:  * Fetch from onboard ROM/RAM
                    171:  */
                    172: nefetch (ns, up, ad, len) ne_softc_t *ns; caddr_t up; {
                    173:         u_char cmd;
                    174:         caddr_t nec = ns->ns_port;
                    175:         int counter = 10000;
                    176:                int t_len;
                    177:                unsigned char last_word[2];
                    178:                char odd;
                    179: 
                    180:         cmd = inb (nec + ds_cmd);
                    181:         outb (nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    182: 
                    183:         /* Setup remote dma */
                    184:         outb (nec + ds0_isr, DSIS_RDC);
                    185: 
                    186:                t_len = len;
                    187:         if ((ns->ns_mode & DSDC_WTS) && len&1) {
                    188:                                odd=1;
                    189:                 t_len++;          /* roundup to words */
                    190:                } else odd=0;
                    191: 
                    192:         outb (nec+ds0_rbcr0, t_len);
                    193:         outb (nec+ds0_rbcr1, t_len>>8);
                    194:         outb (nec+ds0_rsar0, ad);
                    195:         outb (nec+ds0_rsar1, ad>>8);
                    196: 
                    197:         /* Execute & extract from card */
                    198:         outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);
                    199: 
                    200:         if (ns->ns_mode & DSDC_WTS)
                    201:                                if (odd) {
                    202:                        linw (nec+ne_data, up, len/2);
                    203:                                        *(last_word) = inw(nec+ne_data); /* get last word */
                    204:                                        *(up+len-1) = last_word[0]; /* last byte */
                    205:                                } else {
                    206:                        linw (nec+ne_data, up, len/2);
                    207:                                }
                    208:         else
                    209:                 linb (nec+ne_data, up, len);
                    210: 
                    211: 
                    212:         /* Wait till done, then shutdown feature */
                    213:         while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
                    214:                 ;
                    215: 
                    216:         outb (nec+ds0_isr, DSIS_RDC);
                    217:         outb (nec+ds_cmd, cmd);
                    218: }
                    219: 
                    220: /*
                    221:  * Put to onboard RAM
                    222:  */
                    223: neput (ns, up, ad, len) ne_softc_t *ns; caddr_t up; {
                    224:         u_char cmd;
                    225:         caddr_t nec = ns->ns_port;
                    226:         int counter = 10000;
                    227:                int t_len;
                    228:                int odd;
                    229:                unsigned char last_word[2];
                    230: 
                    231:         cmd = inb(nec+ds_cmd);
                    232:         outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    233: 
                    234:         /* Setup for remote dma */
                    235:         outb (nec+ds0_isr, DSIS_RDC);
                    236: 
                    237:                t_len = len;
                    238:         if ((ns->ns_mode & DSDC_WTS) && len&1) {
                    239:                                odd = 1;
                    240:                 t_len++;          /* roundup to words */
                    241:                } else odd = 0;
                    242: 
                    243:         outb (nec+ds0_rbcr0, t_len);
                    244:         outb (nec+ds0_rbcr1, t_len>>8);
                    245:         outb (nec+ds0_rsar0, ad);
                    246:         outb (nec+ds0_rsar1, ad>>8);
                    247: 
                    248:         /* Execute & stuff to card */
                    249:         outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);
                    250:         if (ns->ns_mode & DSDC_WTS) {
                    251:                                if (odd) {
                    252:                        loutw (nec+ne_data, up, len/2);
                    253:                                        last_word[0] = *(up+len-1);
                    254:                                        outw (nec+ne_data, (unsigned short) *(last_word));
                    255:                                }
                    256:                                else {
                    257:                        loutw (nec+ne_data, up, len/2);
                    258:                                }
                    259:                }
                    260:         else
                    261:                 loutb (nec+ne_data, up, len);
                    262: 
                    263: 
                    264:         /* Wait till done, then shutdown feature */
                    265:         while ((inb (nec+ds0_isr) & DSIS_RDC) == 0 && counter-- > 0)
                    266:                 ;
                    267: 
                    268:         outb (nec+ds0_isr, DSIS_RDC);
                    269:         outb (nec+ds_cmd, cmd);
                    270: }
                    271: 
                    272: int
                    273: neprobe(port, dev)
                    274: struct bus_device *dev;
                    275: {
                    276:         int val, i, sum, bytemode = 1, pat;
                    277:        int unit = dev->unit;
                    278:         ne_softc_t *ns = &ne_softc[unit];
                    279:         caddr_t nec;
                    280: 
                    281:         if ((unsigned) unit >= NNE)
                    282:                 return(0);
                    283: 
                    284:         nec = (caddr_t) ns->ns_port = dev->address;
                    285: 
                    286:        if (ns->card_present) {
                    287:                printf("ne%s : card already present in port %x\n",
                    288:                        unit, nec);
                    289:                return(0);
                    290:        }
                    291: 
                    292:         if (bytemode) {
                    293:                 /* Byte Transfers, Burst Mode Select, Fifo at 8 bytes */
                    294:                 ns->ns_mode = DSDC_BMS|DSDC_FT1;
                    295:                 ns->ns_txstart = TBUF8;
                    296:                 ns->ns_rxend = RBUFEND8;
                    297:         } else {
                    298: word:
                    299:                 /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
                    300:                 ns->ns_mode = DSDC_WTS|DSDC_BMS|DSDC_FT1;
                    301:                 ns->ns_txstart = TBUF16;
                    302:                 ns->ns_rxend = RBUFEND16;
                    303:                 bytemode = 0;
                    304:         }
                    305: 
                    306:         /* Reset the bastard */
                    307:         val = inb(nec + ne_reset);
                    308:         delay(200);
                    309:         outb(nec + ne_reset, val);
                    310:         delay(200);
                    311: 
                    312:         outb(nec + ds_cmd, DSCM_STOP|DSCM_NODMA);
                    313:         
                    314:         i = 10000;
                    315:         while ((inb(nec + ds0_isr) & DSIS_RESET) == 0 && i-- > 0);
                    316:         if (i < 0) return (0);
                    317: 
                    318:         outb(nec + ds0_isr, 0xff);
                    319:         outb(nec + ds0_dcr, ns->ns_mode);
                    320:         outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
                    321:         delay(1000);
                    322: 
                    323:         /* Check cmd reg and fail if not right */
                    324:         if ((i = inb(nec + ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))
                    325:                 return(0);
                    326: 
                    327:         outb(nec + ds0_tcr, DSTC_LB0);
                    328:         outb(nec + ds0_rcr, DSRC_MON);
                    329:         outb(nec + ds0_pstart, ns->ns_txstart+PKTSZ);
                    330:         outb(nec + ds0_pstop, ns->ns_rxend);
                    331:         outb(nec + ds0_bnry, ns->ns_rxend);
                    332:         outb(nec + ds0_imr, 0);
                    333:         outb(nec + ds0_isr, 0);
                    334:         outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
                    335:         outb(nec + ds1_curr, ns->ns_txstart+PKTSZ);
                    336:         outb(nec + ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
                    337: 
                    338: #ifdef NEDEBUG
                    339: #define RCON    37
                    340:         {       int i, rom;
                    341: 
                    342:                 rom=1;
                    343:                 printf("ne ram ");
                    344:                 
                    345:                 for (i = 0; i < 0xfff0; i+=4) {
                    346:                         pat = PAT(i);
                    347:                         neput(ns, &pat,i,4);
                    348:                         nefetch(ns, &pat,i,4);
                    349:                         if (pat == PAT(i)) {
                    350:                                 if (rom) {
                    351:                                         rom=0;
                    352:                                         printf(" %x", i);
                    353:                                 }
                    354:                         } else {
                    355:                                 if (!rom) {
                    356:                                         rom=1;
                    357:                                         printf("..%x ", i);
                    358:                                 }
                    359:                         }
                    360:                         pat=0;
                    361:                         neput(ns, &pat,i,4);
                    362:                 }
                    363:                 printf("\n");
                    364:         }
                    365: #endif
                    366: 
                    367:         /*
                    368:          * <groan> detect difference between units
                    369:          * solely by where the RAM is decoded.
                    370:          */
                    371:         pat = PAT(0);
                    372:         neput  (ns, &pat, ns->ns_txstart*DS_PGSIZE, 4);
                    373:         nefetch(ns, &pat, ns->ns_txstart*DS_PGSIZE, 4);
                    374:         if (pat != PAT(0)) {
                    375:                 if (bytemode)
                    376:                         goto word;
                    377:                 else return (0);
                    378:         }
                    379: 
                    380: 
                    381:         /* Extract board address */
                    382:         nefetch (ns, (caddr_t)boarddata, 0, sizeof(boarddata));
                    383: 
                    384:         for(i=0; i < 6; i++)
                    385:                 ns->ds_addr[i] = boarddata[i];
                    386:        ns->card_present = 1;
                    387:         return (1);
                    388: }
                    389: 
                    390: /*
                    391:  * Interface exists: make available by filling in network interface
                    392:  * record.  System will initialize the interface when it is ready
                    393:  * to accept packets.  We get the ethernet address here.
                    394:  */
                    395: void 
                    396: neattach(dev)
                    397: struct bus_device *dev;
                    398: {
                    399:         short unit = dev->unit;
                    400:         ne_softc_t *ns = &ne_softc[unit];
                    401:         register struct ifnet *ifp = &(ns->ds_if);
                    402: 
                    403:         if ((unsigned) unit >= NNE)
                    404:                 return;
                    405: 
                    406: #ifdef MACH_KERNEL
                    407:        take_dev_irq(dev);
                    408: #else  MACH_KERNEL
                    409:         /* setup intr handler */
                    410:         ns->handler.ih_level            = dev->dev_pic;
                    411:         ns->handler.ih_handler          = dev->dev_intr[0];
                    412:         ns->handler.ih_resolver         = i386_resolver;
                    413:         ns->handler.ih_rdev             = dev;
                    414:         ns->handler.ih_stats.intr_type  = INTR_DEVICE;
                    415:         ns->handler.ih_stats.intr_cnt   = 0;
                    416:         ns->handler.ih_hparam[0].intparam = unit;
                    417:         if ((ns->handler_id = handler_add(&ns->handler)) != NULL)
                    418:                 handler_enable(ns->handler_id);
                    419:         else
                    420:                 panic("Unable to add NEx000 interrupt handler");
                    421: #endif MACH_KERNEL
                    422:        printf (", port = %x, spl = %d, pic = %d, [%s].",
                    423:                dev->address, dev->sysdep, dev->sysdep1,
                    424:                ether_sprintf(ns->ds_addr));
                    425: #ifndef        MACH_KERNEL
                    426:        ns->ns_ac.ac_bcastaddr  = (u_char *)etherbroadcastaddr;
                    427:        ns->ns_ac.ac_arphrd     = ARPHRD_ETHER;
                    428: #endif MACH_KERNEL
                    429:        ns->ns_flags    = 0;
                    430:        ns->mode        = 0;
                    431:         ifp->if_unit   = unit;
                    432:         ifp->if_mtu    = ETHERMTU;
                    433:         ifp->if_flags  = IFF_BROADCAST;
                    434: #ifdef MACH_KERNEL
                    435:        ifp->if_header_size = sizeof(struct ether_header);
                    436:        ifp->if_header_format = HDR_ETHERNET;
                    437:         ifp->if_address_size = 6;
                    438:        ifp->if_address = (char *)&ns->ds_addr[0];
                    439:        if_init_queues(ifp);
                    440: #else  MACH_KERNEL
                    441:         ifp->if_name   = nedriver.driver_dname;
                    442:         ifp->if_init   = neinit;
                    443:         ifp->if_output = ether_output;
                    444:         ifp->if_start  = nestart;
                    445:         ifp->if_ioctl  = neioctl;
                    446:         ifp->if_reset  = nereset;
                    447:         ifp->if_watchdog= 0;
                    448:         if_attach(ifp);
                    449: #endif MACH_KERNEL
                    450: }
                    451: 
                    452: /*
                    453:  * Initialization of interface; set up initialization block
                    454:  * and transmit/receive descriptor rings.
                    455:  */
                    456: neinit(unit)
                    457:         int unit;
                    458: {
                    459:         ne_softc_t *ns = &ne_softc[unit];
                    460:         struct ifnet *ifp = &ns->ds_if;
                    461:         int i; char *cp;
                    462:        int oldpri;
                    463:         caddr_t nec = ns->ns_port;
                    464: 
                    465: #ifndef MACH_KERNEL
                    466:         if (ifp->if_addrlist == (struct ifaddr *)0) return;
                    467: #endif MACH_KERNEL
                    468: 
                    469:        oldpri = SPLNET();
                    470: 
                    471:        outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
                    472: 
                    473:         /* Word Transfer select, Burst Mode Select, Fifo at 8 bytes */
                    474:         outb(nec+ds0_dcr, ns->ns_mode);
                    475: 
                    476:        /* clear remote byte count resigters */
                    477:         outb (nec+ds0_rbcr0, 0);
                    478:         outb (nec+ds0_rbcr1, 0);
                    479: 
                    480:        /* don't store incoming packets into memory for now */
                    481:         outb (nec+ds0_rcr, DSRC_MON);
                    482: 
                    483:        /* place NIC in internal loopback mode */
                    484:        outb(nec+ds0_tcr, DSTC_LB0);
                    485: 
                    486:        /* initialize transmit/recieve (ring-buffer) Page Start */
                    487:        outb (nec+ds0_tpsr, 0);
                    488:         outb (nec+ds0_pstart, ns->ns_txstart+PKTSZ);
                    489: 
                    490:        /* initialize reciever (ring-buffer) Page Stop and Boundary */
                    491:         outb (nec+ds0_pstop, ns->ns_rxend);
                    492:         outb (nec+ds0_bnry, ns->ns_txstart+PKTSZ);
                    493: 
                    494:        /* clear all interrupts */
                    495:         outb (nec+ds0_isr, 0xff);
                    496: 
                    497:        /* enable the interrupts that we care about */
                    498:         outb (nec+ds0_imr, IMR_ENABLE);
                    499: 
                    500:         /* set physical address on ethernet */
                    501:         outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);
                    502:         for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ds_addr[i]);
                    503: 
                    504:        ns->ns_cur = ns->ns_txstart+PKTSZ + 1;
                    505:         outb (nec+ds1_curr, ns->ns_cur);
                    506: 
                    507:        /* XXX deal with Reciever Configuration Register */
                    508:         /* clr logical address hash filter for now */
                    509:         for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);
                    510:        
                    511:        /* set page 0 registers */
                    512:        outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);
                    513:         outb (nec+ds0_rcr, DSRC_AB);
                    514: 
                    515:        /* take unit out of loopback mode */
                    516:         outb (nec+ds0_tcr, 0);
                    517: 
                    518:         ns->ds_if.if_flags |= IFF_RUNNING;
                    519:         ns->ns_flags &= ~(DSF_LOCK|DSF_RUNNING);
                    520:         ns->ns_oactive = 0; ns->ns_mask = ~0;
                    521:         splx(oldpri);
                    522:         nestart(unit);
                    523:        return(1);
                    524: }
                    525: 
                    526: /*
                    527:  * Setup output on interface.
                    528:  * Get another datagram to send off of the interface queue,
                    529:  * and map it to the interface before starting the output.
                    530:  * called only at splimp or interrupt level.
                    531:  */
                    532: nestart(unit)
                    533: int unit;
                    534: {
                    535:         ne_softc_t *ns = &ne_softc[unit];
                    536:         struct ifnet *ifp = &ns->ds_if;
                    537:         int buffer;
                    538:         int len, i, total,t;
                    539:         caddr_t nec = ns->ns_port;
                    540: #ifdef MACH_KERNEL
                    541:        io_req_t m;
                    542: 
                    543: #else  MACH_KERNEL
                    544:         struct mbuf *m0, *m;
                    545: #endif MACH_KERNEL
                    546: 
                    547:         /*
                    548:          * The DS8390 has only one transmit buffer, if it is busy we
                    549:          * must wait until the transmit interrupt completes.
                    550:          */
                    551:         outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
                    552: 
                    553:         if (ns->ns_flags & DSF_LOCK) 
                    554:                 goto done;
                    555: 
                    556:         if (inb(nec+ds_cmd) & DSCM_TRANS) 
                    557:                 goto done;
                    558: 
                    559:         if ((ns->ds_if.if_flags & IFF_RUNNING) == 0)
                    560:                 goto done;
                    561: 
                    562:         IF_DEQUEUE(&ns->ds_if.if_snd, m);
                    563:         if (m == 0)
                    564:                 goto done;
                    565: 
                    566:         /*
                    567:          * Copy the mbuf chain into the transmit buffer
                    568:          */
                    569: 
                    570:         ns->ns_flags |= DSF_LOCK;       /* prevent entering nestart */
                    571:         buffer = ns->ns_txstart*DS_PGSIZE;
                    572: #ifdef MACH_KERNEL
                    573:        total = m->io_count;
                    574:        neput(ns, m->io_data, buffer, total);
                    575: #else  MACH_KERNEL
                    576:         t = 0; len = i = 0;
                    577:         for (m0 = m; m != 0; m = m->m_next)
                    578:                 t += m->m_len;
                    579:                 
                    580:         m = m0;
                    581:         total = t;
                    582:         for (m0 = m; m != 0; ) {
                    583:                 
                    584:                 if (m->m_len&1 && t > m->m_len) {
                    585:                         neput(ns, mtod(m, caddr_t), buffer, m->m_len - 1);
                    586:                         t -= m->m_len - 1;
                    587:                         buffer += m->m_len - 1;
                    588:                         m->m_data += m->m_len - 1;
                    589:                         m->m_len = 1;
                    590:                         m = m_pullup(m, 2);
                    591:                 } else {
                    592:                         neput(ns, mtod(m, caddr_t), buffer, m->m_len);
                    593:                         buffer += m->m_len;
                    594:                         t -= m->m_len;
                    595:                         MFREE(m, m0);
                    596:                         m = m0;
                    597:                 }
                    598:         }
                    599: #endif MACH_KERNEL
                    600:         /*
                    601:          * Init transmit length registers, and set transmit start flag.
                    602:          */
                    603: 
                    604:         len = total;
                    605:         if (len < ETHER_MIN_LEN) len = ETHER_MIN_LEN;
                    606:         outb(nec+ds0_tbcr0,len&0xff);
                    607:         outb(nec+ds0_tbcr1,(len>>8)&0xff);
                    608:         outb(nec+ds0_tpsr, ns->ns_txstart);
                    609:         outb(nec+ds_cmd, DSCM_TRANS|DSCM_NODMA|DSCM_START);
                    610: 
                    611: #ifdef MACH_KERNEL
                    612:        iodone(m);
                    613:        m = 0;
                    614: done:
                    615: #endif MACH_KERNEL
                    616: }
                    617: 
                    618: /* buffer successor/predecessor in ring? */
                    619: #define succ(n) (((n)+1 >= ns->ns_rxend) ? (ns->ns_txstart+PKTSZ) : (n)+1)
                    620: #define pred(n) (((n)-1 < (ns->ns_txstart+PKTSZ)) ? ns->ns_rxend-1 : (n)-1)
                    621: 
                    622: /*
                    623:  * Controller interrupt.
                    624:  */
                    625: neintr(unit)
                    626: {
                    627:         ne_softc_t *ns = &ne_softc[unit];
                    628:         u_char cmd,isr;
                    629:         caddr_t nec = ns->ns_port;
                    630: 
                    631:         /* Save cmd, clear interrupt */
                    632:         cmd = inb (nec+ds_cmd);
                    633:         isr = inb (nec+ds0_isr);
                    634: loop:
                    635:         outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);
                    636:         outb(nec+ds0_isr, isr);
                    637: 
                    638:         /* Receiver error */
                    639:         if (isr & DSIS_RXE) {
                    640:                (void) inb(nec+ds0_rsr);
                    641:                 /* need to read these registers to clear status */
                    642:                 ns->ds_if.if_ierrors++;
                    643:         }
                    644: 
                    645:        /* Counters overflowed, reading the registers resets them */
                    646:        if (isr & DSIS_CTRS) {
                    647:                (void) inb(nec+ds0_cntr0);
                    648:                (void) inb(nec+ds0_cntr1);
                    649:                (void) inb(nec+ds0_cntr2);
                    650:        }
                    651: 
                    652: 
                    653:         /* We received something; rummage thru tiny ring buffer */
                    654:         if (isr & (DSIS_RX|DSIS_RXE|DSIS_ROVRN)) {
                    655:                 u_char pend,lastfree;
                    656: 
                    657:                 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
                    658:                 pend = inb(nec+ds1_curr);
                    659:                 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
                    660: 
                    661:                 /* Something in the buffer? */
                    662:                 while (pend != ns->ns_cur) {
                    663:                         /* Extract header from microcephalic board */
                    664:                         nefetch(ns, &ns->ns_ph,ns->ns_cur*DS_PGSIZE,
                    665:                                 sizeof(ns->ns_ph));
                    666:                         ns->ns_ba = ns->ns_cur*DS_PGSIZE+sizeof(ns->ns_ph);
                    667: 
                    668:                         /* Incipient paranoia */
                    669:                         if (ns->ns_ph.pr_status == DSRS_RPC ||
                    670:                                 /* for dequna's */
                    671:                                 ns->ns_ph.pr_status == 0x21) {
                    672:                                 if (nerecv(ns))
                    673:                                        ns->ns_cur = ns->ns_ph.pr_nxtpg ;
                    674:                                else {
                    675:                                        outb(nec+ds0_bnry, pred(ns->ns_cur));
                    676:                                        goto short_load;
                    677:                                }
                    678:                        }
                    679: #ifdef NEDEBUG
                    680:                         else  {
                    681:                                 printf("cur %x pnd %x lfr %x ",
                    682:                                         ns->ns_cur, pend, lastfree);
                    683:                                 printf("nxt %x len %x ", ns->ns_ph.pr_nxtpg,
                    684:                                         (ns->ns_ph.pr_sz1<<8)+ ns->ns_ph.pr_sz0);
                    685:                                 printf("Bogus Sts %x\n", ns->ns_ph.pr_status);  
                    686:                                ns->ns_cur = pend;
                    687:                         }
                    688: #endif
                    689:                         outb(nec+ds0_bnry, pred(ns->ns_cur));
                    690:                         outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG1);
                    691:                         pend = inb(nec+ds1_curr);
                    692:                         outb(nec+ds_cmd, DSCM_START|DSCM_NODMA|DSCM_PG0);
                    693:                 }
                    694: short_load:
                    695:                 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
                    696:         }
                    697: 
                    698:         /* Transmit error */
                    699:         if (isr & DSIS_TXE) {
                    700:                 ns->ns_flags &= ~DSF_LOCK;
                    701:                 /* Need to read these registers to clear status */
                    702:                 ns->ds_if.if_collisions += inb(nec+ds0_tbcr0);
                    703:                 ns->ds_if.if_oerrors++;
                    704:         }
                    705: 
                    706:         /* Packet Transmitted */
                    707:         if (isr & DSIS_TX) {
                    708:                 ns->ns_flags &= ~DSF_LOCK;
                    709:                 ++ns->ds_if.if_opackets;
                    710:                 ns->ds_if.if_collisions += inb(nec+ds0_tbcr0);
                    711:         }
                    712: 
                    713:         /* Receiver ovverun? */
                    714:         if (isr & DSIS_ROVRN) {
                    715:                 outb(nec+ds0_rbcr0, 0);
                    716:                 outb(nec+ds0_rbcr1, 0);
                    717:                 outb(nec+ds0_tcr, DSTC_LB0);
                    718:                 outb(nec+ds0_rcr, DSRC_MON);
                    719:                 outb(nec+ds_cmd, DSCM_START|DSCM_NODMA);
                    720:                 outb(nec+ds0_rcr, DSRC_AB);
                    721:                 outb(nec+ds0_tcr, 0);
                    722:         }
                    723: 
                    724:         /* Any more to send? */
                    725:         outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);
                    726:         nestart(unit);
                    727:         outb (nec+ds_cmd, cmd);
                    728:         outb (nec+ds0_imr, IMR_ENABLE);
                    729: 
                    730:         /* Still more to do? */
                    731:         isr = inb (nec+ds0_isr);
                    732:         if(isr) goto loop;
                    733: 
                    734:        return 0;
                    735: }
                    736: 
                    737: /*
                    738:  * Ethernet interface receiver interface.
                    739:  * If input error just drop packet.
                    740:  * Otherwise examine packet to determine type.  If can't determine length
                    741:  * from type, then have to drop packet.  Othewise decapsulate
                    742:  * packet based on type and pass to type specific higher-level
                    743:  * input routine.
                    744:  */
                    745: nerecv(ns)
                    746:         ne_softc_t *ns;
                    747: {
                    748: #ifdef MACH_KERNEL
                    749:        ipc_kmsg_t      new_kmsg;
                    750:        struct ether_header *ehp;
                    751:        struct packet_header *pkt;
                    752:        register struct ifnet *ifp = &ns->ds_if;
                    753: #ifdef FIPC
                    754:        char *fipc_buf;
                    755: #endif
                    756: #else  MACH_KERNEL
                    757:         struct mbuf *top, **mp, *m, *p;
                    758: #endif MACH_KERNEL
                    759:         int len, l;
                    760:         int epkt;
                    761: 
                    762:         ns->ds_if.if_ipackets++;
                    763:         len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1<<8);
                    764:         if(len < ETHER_MIN_LEN || len > ETHER_MAX_LEN)
                    765:                 return 0;
                    766: 
                    767:         nefetch(ns, &ns->ns_eh, ns->ns_ba, sizeof(struct ether_header));
                    768: 
                    769: #ifndef MACH_KERNEL
                    770:         ns->ns_eh.ether_type = ntohs((u_short)ns->ns_eh.ether_type);
                    771: #endif MACH_KERNEL
                    772:        ns->ns_ba += sizeof(struct ether_header);
                    773: 
                    774:         /* don't forget checksum! */
                    775:         len -= (sizeof(struct ether_header) + sizeof(long));
                    776: #ifdef MACH_KERNEL
                    777: #ifdef  FIPC
                    778:        if (ns->ns_eh.ether_type == FIPC_MSG_TYPE)  /* fipc packet */
                    779:        {
                    780:                /* We need to hand the whole packet to the handler. */
                    781: 
                    782:                fipc_recvs++;
                    783: 
                    784:                fipc_buf = get_fipc_buffer (len, TRUE, TRUE);
                    785: 
                    786:                if (fipc_buf == NULL)
                    787:                {
                    788:                        ns->ds_if.if_rcvdrops++;
                    789:                        return(0);
                    790:                }
                    791:                nefetch (ns, fipc_buf, ns->ns_ba, len);
                    792: 
                    793:                fipc_packet (fipc_buf, ns->ns_eh);
                    794:        }
                    795:        else  /* net_kmsg */
                    796:        {
                    797: #endif /* FIPC */
                    798:                new_kmsg = net_kmsg_get();
                    799: 
                    800:                if (new_kmsg == IKM_NULL) {
                    801:                        ns->ds_if.if_rcvdrops++;
                    802:                        return(0);
                    803:                }
                    804: 
                    805:                ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
                    806:                pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]);
                    807:                *ehp = ns->ns_eh;
                    808: 
                    809:                        nefetch(ns, (char *) (pkt + 1), ns->ns_ba, len);
                    810: 
                    811:                pkt->type = ehp->ether_type;
                    812:        
                    813:                pkt->length = len + sizeof(struct packet_header);
                    814:                net_packet(ifp, new_kmsg, pkt->length, ethernet_priority(new_kmsg));
                    815: #ifdef FIPC
                    816:        }
                    817: #endif
                    818: 
                    819: #else  MACH_KERNEL
                    820: /**/
                    821:         epkt = ns->ns_ba + len;
                    822: 
                    823:         MGETHDR(m, M_DONTWAIT, MT_DATA);
                    824:         if (m == 0)
                    825:                 return (0);
                    826: 
                    827:         m->m_pkthdr.rcvif = &ns->ds_if;
                    828:         m->m_pkthdr.len = len;
                    829:         m->m_len = MHLEN;
                    830: 
                    831:         top = 0;
                    832:         mp = &top;
                    833:         while (len > 0) {
                    834:                 if (top) {
                    835:                         MGET(m, M_DONTWAIT, MT_DATA);
                    836:                         if (m == 0) {
                    837:                                 m_freem(top);
                    838:                                 return (0);
                    839:                         }
                    840:                         m->m_len = MLEN;
                    841:                 }
                    842:                 l = min(len, epkt - ns->ns_ba);
                    843:                 if (l >= MINCLSIZE) {
                    844:                         MCLGET(m, M_DONTWAIT);
                    845:                         if (m->m_flags & M_EXT)
                    846:                                 m->m_len = l = min(len, MCLBYTES);
                    847:                         else
                    848:                                 l = m->m_len;
                    849:                 } else {
                    850:                         /*
                    851:                          * Place initial small packet/header at end of mbuf.
                    852:                          */
                    853:                         if (l < m->m_len) {
                    854:                                 if (top == 0 && len + max_linkhdr <= m->m_len)
                    855:                                         m->m_data += max_linkhdr;
                    856:                                 m->m_len = l;
                    857:                         } else
                    858:                                 l = m->m_len;
                    859:                 }
                    860:                nefetch(ns, mtod(m, caddr_t), ns->ns_ba, l);
                    861:                 ns->ns_ba += l;
                    862:                 *mp = m;
                    863:                 mp = &m->m_next;
                    864:                 len -= l;
                    865:         }
                    866: /**/
                    867:         if (top == 0) return 0; /* NEED MODIFY HERE !!! */
                    868: 
                    869:         ether_input(&ns->ds_if, &ns->ns_eh, top);
                    870: #endif MACH_KERNEL
                    871:        return 1;
                    872: }
                    873: 
                    874: #ifdef MACH_KERNEL
                    875: neopen(dev, flag)
                    876: dev_t dev;
                    877: int   flag;
                    878: {
                    879:        register int unit = minor(dev);
                    880: 
                    881:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    882:                return (ENXIO);
                    883: 
                    884:        ne_softc[unit].ds_if.if_flags |= IFF_UP;
                    885:        neinit(unit);
                    886:        return(0);
                    887: }
                    888: 
                    889: #ifdef FIPC
                    890: nefoutput(dev, ior)
                    891: dev_t dev;
                    892: io_req_t ior;
                    893: {
                    894:        register int unit = minor(dev);
                    895: 
                    896:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    897:                return (ENXIO);
                    898: 
                    899:        return (net_fwrite(&ne_softc[unit].ds_if, nestart, ior));
                    900: }
                    901: #endif
                    902: 
                    903: neoutput(dev, ior)
                    904: dev_t dev;
                    905: io_req_t ior;
                    906: {
                    907:        register int unit = minor(dev);
                    908: 
                    909:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    910:                return (ENXIO);
                    911: 
                    912:        return (net_write(&ne_softc[unit].ds_if, nestart, ior));
                    913: }
                    914: 
                    915: nesetinput(dev, receive_port, priority, filter, filter_count)
                    916: dev_t          dev;
                    917: mach_port_t    receive_port;
                    918: int            priority;
                    919: filter_t       filter[];
                    920: unsigned int   filter_count;
                    921: {
                    922:        register int unit = minor(dev);
                    923: 
                    924:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    925:                return (ENXIO);
                    926: 
                    927:        return (net_set_filter(&ne_softc[unit].ds_if,
                    928:                                receive_port, priority,
                    929:                                filter, filter_count));
                    930: }
                    931: 
                    932: negetstat(dev, flavor, status, count)
                    933: dev_t          dev;
                    934: int            flavor;
                    935: dev_status_t   status;
                    936: unsigned int   *count;
                    937: {
                    938:        register int unit = minor(dev);
                    939: 
                    940:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    941:                return (ENXIO);
                    942: 
                    943:        return (net_getstat(&ne_softc[unit].ds_if,
                    944:                            flavor,
                    945:                            status,
                    946:                            count));
                    947: }
                    948: 
                    949: nesetstat(dev, flavor, status, count)
                    950: dev_t          dev;
                    951: int            flavor;
                    952: dev_status_t   status;
                    953: unsigned int   count;
                    954: {
                    955:        register int unit = minor(dev);
                    956:        register ne_softc_t *ns;
                    957: 
                    958:        if (!ne_softc[unit].card_present || unit < 0 || unit >= NNE)
                    959:                return (ENXIO);
                    960: 
                    961:        ns = &ne_softc[unit];
                    962: 
                    963:        switch(flavor) {
                    964:        case NET_STATUS: {
                    965:                register struct net_status *s = (struct net_status *)status;
                    966:                int mode = 0;
                    967:                if (count < NET_STATUS_COUNT)
                    968:                        return(D_INVALID_SIZE);
                    969: #define MOD_ENAL 1
                    970: #define MOD_PROM 2
                    971:                if (s->flags & IFF_ALLMULTI)
                    972:                        mode |= MOD_ENAL;
                    973:                if (s->flags & IFF_PROMISC)
                    974:                        mode |= MOD_PROM;
                    975: 
                    976:                if (ns->mode != mode) {
                    977:                        ns->mode = mode;
                    978:                        if (ns->ns_flags & DSF_RUNNING) {
                    979:                                ns->ns_flags &= ~(DSF_LOCK | DSF_RUNNING);
                    980:                                neinit(unit);
                    981:                        }
                    982:                }
                    983:                break;
                    984:                }
                    985:        default :
                    986:                return (D_INVALID_OPERATION);
                    987:        }
                    988:        return (D_SUCCESS);
                    989: }
                    990: 
                    991: #else  MACH_KERNEL
                    992: 
                    993: /*
                    994:  * Process an ioctl request.
                    995:  */
                    996: neioctl(ifp, cmd, data)
                    997:         register struct ifnet *ifp;
                    998:         int cmd;
                    999:         caddr_t data;
                   1000: {
                   1001:         register struct ifaddr *ifa = (struct ifaddr *)data;
                   1002:         ne_softc_t *ns = &ne_softc[ifp->if_unit];
                   1003:         struct ifreq *ifr = (struct ifreq *)data;
                   1004:         int s = splimp(), error = 0;
                   1005: 
                   1006: 
                   1007:         switch (cmd) {
                   1008: 
                   1009:         case SIOCSIFADDR:
                   1010:                 ifp->if_flags |= IFF_UP;
                   1011: 
                   1012:                 switch (ifa->ifa_addr->sa_family) {
                   1013:                 case AF_INET:
                   1014:                         neinit(ifp->if_unit);   /* before arpwhohas */
                   1015:                         ((struct arpcom *)ifp)->ac_ipaddr =
                   1016:                                 IA_SIN(ifa)->sin_addr;
                   1017:                         arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
                   1018:                         break;
                   1019:                 case AF_NS:
                   1020:                     {
                   1021:                         register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
                   1022: 
                   1023:                         if (ns_nullhost(*ina))
                   1024:                                 ina->x_host = *(union ns_host *)(ns->ds_addr);
                   1025:                         else {
                   1026:                                 /* 
                   1027:                                  * The manual says we can't change the address 
                   1028:                                  * while the receiver is armed,
                   1029:                                  * so reset everything
                   1030:                                  */
                   1031:                                 ifp->if_flags &= ~IFF_RUNNING; 
                   1032:                                 bcopy((caddr_t)ina->x_host.c_host,
                   1033:                                     (caddr_t)ns->ds_addr, sizeof(ns->ds_addr));
                   1034:                         }
                   1035:                         neinit(ifp->if_unit); /* does ne_setaddr() */
                   1036:                         break;
                   1037:                     }
                   1038:                 default:
                   1039:                         neinit(ifp->if_unit);
                   1040:                         break;
                   1041:                 }
                   1042:                 break;
                   1043: 
                   1044:         case SIOCSIFFLAGS:
                   1045:                 if ((ifp->if_flags & IFF_UP) == 0 &&
                   1046:                     ifp->if_flags & IFF_RUNNING) {
                   1047:                         ifp->if_flags &= ~IFF_RUNNING;
                   1048:                         outb(ns->ns_port + ds_cmd, DSCM_STOP|DSCM_NODMA);
                   1049:                 } else if (ifp->if_flags & IFF_UP &&
                   1050:                     (ifp->if_flags & IFF_RUNNING) == 0)
                   1051:                         neinit(ifp->if_unit);
                   1052:                 break;
                   1053: 
                   1054: #ifdef notdef
                   1055:         case SIOCGHWADDR:
                   1056:                 bcopy((caddr_t)ns->ds_addr, (caddr_t) &ifr->ifr_data,
                   1057:                         sizeof(ns->ds_addr));
                   1058:                 break;
                   1059: #endif
                   1060: 
                   1061:         default:
                   1062:                 error = EINVAL;
                   1063:         }
                   1064:         splx(s);
                   1065:         return (error);
                   1066: }
                   1067: 
                   1068: /*
                   1069:  * Reset of interface.
                   1070:  */
                   1071: nereset(unit, uban)
                   1072:         int unit, uban;
                   1073: {
                   1074:         if (unit >= NNE)
                   1075:                 return;
                   1076:         printf("ne%d: reset\n", unit);
                   1077:         ne_softc[unit].ns_flags &= ~DSF_LOCK;
                   1078:         neinit(unit);
                   1079: }
                   1080: #endif MACH_KERNEL
                   1081: #endif

unix.superglobalmegacorp.com

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