The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/if_hp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_hp.c,v 1.37 2003/08/07 16:31:07 agc Exp $   */
    2 
    3 /* XXX THIS DRIVER IS BROKEN.  IT WILL NOT EVEN COMPILE. */
    4 
    5 /*-
    6  * Copyright (c) 1990 The Regents of the University of California.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*-
   35  * Copyright (c) 1990, 1991 William F. Jolitz.
   36  *
   37  * Redistribution and use in source and binary forms, with or without
   38  * modification, are permitted provided that the following conditions
   39  * are met:
   40  * 1. Redistributions of source code must retain the above copyright
   41  *    notice, this list of conditions and the following disclaimer.
   42  * 2. Redistributions in binary form must reproduce the above copyright
   43  *    notice, this list of conditions and the following disclaimer in the
   44  *    documentation and/or other materials provided with the distribution.
   45  * 3. All advertising materials mentioning features or use of this software
   46  *    must display the following acknowledgement:
   47  *      This product includes software developed by the University of
   48  *      California, Berkeley and its contributors.
   49  * 4. Neither the name of the University nor the names of its contributors
   50  *    may be used to endorse or promote products derived from this software
   51  *    without specific prior written permission.
   52  *
   53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   63  * SUCH DAMAGE.
   64  */
   65 
   66 /*
   67  * HP LAN Ethernet driver
   68  *
   69  * Parts inspired from Tim Tucker's if_wd driver for the wd8003,
   70  * insight on the ne2000 gained from Robert Clements PC/FTP driver.
   71  *
   72  * receive bottom end totally rewritten by Curt Mayer, Dec 1992.
   73  * no longer loses back to back packets.
   74  * note to driver writers: RTFM!
   75  *
   76  * hooks for packet filter added by Charles Hannum, 29DEC1992.
   77  *
   78  * Mostly rewritten for HP-labelled EISA controllers by Charles Hannum,
   79  * 18JAN1993.
   80  */
   81 
   82 #include <sys/cdefs.h>
   83 __KERNEL_RCSID(0, "$NetBSD: if_hp.c,v 1.37 2003/08/07 16:31:07 agc Exp $");
   84 
   85 #include "hp.h"
   86 #if NHP > 0
   87 
   88 #include "opt_inet.h"
   89 #include "opt_ns.h"
   90 #include "rnd.h"
   91 
   92 #include <sys/param.h>
   93 #include <sys/systm.h>
   94 #include <sys/mbuf.h>
   95 #include <sys/buf.h>
   96 #include <sys/protosw.h>
   97 #include <sys/socket.h>
   98 #include <sys/ioctl.h>
   99 #include <sys/errno.h>
  100 #include <sys/syslog.h>
  101 #if NRND > 0
  102 #include <sys/rnd.h>
  103 #endif
  104 
  105 #include <net/if.h>
  106 #include <net/if_ether.h>
  107 
  108 #ifdef INET
  109 #include <netinet/in.h>
  110 #include <netinet/in_systm.h>
  111 #include <netinet/in_var.h>
  112 #include <netinet/ip.h>
  113 #include <netinet/if_inarp.h>
  114 #endif
  115 
  116 #ifdef NS
  117 #include <netns/ns.h>
  118 #include <netns/ns_if.h>
  119 #endif
  120 
  121 #include "bpfilter.h"
  122 #if NBPFILTER > 0
  123 #include <sys/select.h>
  124 #include <net/bpf.h>
  125 #include <net/bpfdesc.h>
  126 #endif
  127 
  128 #include <machine/cpu.h>
  129 #include <machine/pio.h>
  130 
  131 #include <i386/isa/isa_device.h>        /* XXX BROKEN */
  132 #include <dev/isa/if_nereg.h>
  133 #include <i386/isa/icu.h>               /* XXX BROKEN */
  134 
  135 int     hpprobe(), hpattach(), hpintr();
  136 int     hpstart(), hpinit(), ether_output(), hpioctl();
  137 
  138 struct isa_driver hpdriver =
  139 {
  140         hpprobe, hpattach, "hp",
  141 };
  142 
  143 struct mbuf *hpget();
  144 
  145 /*
  146  * Ethernet software status per interface.
  147  *
  148  * Each interface is referenced by a network interface structure,
  149  * ns_if, which the routing code uses to locate the interface.
  150  * This structure contains the output queue for the interface, its address, ...
  151  */
  152 struct hp_softc {
  153         struct ethercom ns_ec;  /* Ethernet common part */
  154 #define ns_if           ns_ac.ac_if     /* network-visible interface */
  155         int     ns_flags;
  156 #define DSF_LOCK        1       /* block re-entering enstart */
  157         int     ns_oactive;
  158         int     ns_mask;
  159         struct prhdr ns_ph;     /* hardware header of incoming packet */
  160         u_char  ns_pb[2048];
  161         u_char  ns_txstart;     /* transmitter buffer start */
  162         u_char  ns_rxstart;     /* receiver buffer start */
  163         u_char  ns_rxend;       /* receiver buffer end */
  164         u_char  hp_type;        /* HP board type */
  165         u_char  hp_irq;         /* interrupt vector */
  166         short   ns_port;        /* i/o port base */
  167         short   ns_mode;        /* word/byte mode */
  168         short   ns_rcr;
  169 #if NBPFILTER > 0
  170         caddr_t ns_bpf;
  171 #endif
  172         u_int8_t ns_addrp[ETHER_ADDR_LEN]; /* hardware Ethernet address */
  173 
  174 #if NRND > 0
  175         rndsource_element_t rnd_source;
  176 #endif  
  177 }
  178         hp_softc[NHP];
  179 #define ENBUFSIZE       (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)
  180 
  181 #define PAT(n)  (0xa55a + 37*(n))
  182 
  183 u_short boarddata[16];
  184 
  185 #define hp_option (-8)
  186 #define hp_data (-4)
  187 #define HP_RUN (0x01)
  188 #define HP_DATA (0x10)
  189 
  190 hpprobe(dvp)
  191         struct isa_device *dvp;
  192 {
  193         int     val, i, s, sum, pat;
  194         struct hp_softc *ns = &hp_softc[0];
  195         int hpc;
  196 
  197 #ifdef lint
  198         hpintr(0);
  199 #endif
  200 
  201         hpc = (ns->ns_port = dvp->id_iobase + 0x10);
  202         s = splnet();
  203 
  204         ns->hp_irq = ffs(dvp->id_irq) - 1;
  205 
  206         /* Extract board address */
  207         for (i = 0; i < 6; i++)
  208                 ns->ns_addrp[i] = inb(hpc - 0x10 + i);
  209         ns->hp_type = inb(hpc - 0x10 + 7);
  210 
  211         if (ns->ns_addrp[0] != 0x08 ||
  212             ns->ns_addrp[1] != 0x00 ||
  213             ns->ns_addrp[2] != 0x09) {
  214                 splx(s);
  215                 return 0;
  216         }
  217         /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */
  218         /* On this board, WTS means 32-bit transfers, which is still
  219          * experimental.  - mycroft, 18JAN93 */
  220 #ifdef HP_32BIT
  221         ns->ns_mode = DSDC_WTS | DSDC_BMS | DSDC_FT1;
  222 #else
  223         ns->ns_mode = DSDC_BMS | DSDC_FT1;
  224 #endif
  225         ns->ns_txstart = 0 * 1024 / DS_PGSIZE;
  226         ns->ns_rxend = 32 * 1024 / DS_PGSIZE;
  227 
  228         ns->ns_rxstart = ns->ns_txstart + (PKTSZ / DS_PGSIZE);
  229 
  230         outb(hpc + hp_option, HP_RUN);
  231 
  232 #if 0
  233         outb(hpc + ds0_isr, 0xff);
  234         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
  235         delay(1000);
  236 
  237         /* Check cmd reg and fail if not right */
  238         if ((i = inb(hpc + ds_cmd)) != (DSCM_NODMA | DSCM_PG0 | DSCM_STOP)) {
  239                 splx(s);
  240                 return (0);
  241         }
  242 #endif
  243 
  244         outb(hpc + hp_option, 0);
  245 
  246         splx(s);
  247         return (32);
  248 }
  249 /*
  250  * Fetch from onboard ROM/RAM
  251  */
  252 hpfetch(ns, up, ad, len)
  253         struct hp_softc *ns;
  254         caddr_t up;
  255 {
  256         u_char  cmd;
  257         int     hpc = ns->ns_port;
  258         int     counter = 100000;
  259 
  260         outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA);
  261 
  262         cmd = inb(hpc + ds_cmd);
  263         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  264 
  265         /* Setup remote DMA */
  266         outb(hpc + ds0_isr, DSIS_RDC);
  267 
  268         if (ns->ns_mode & DSDC_WTS)
  269                 len = (len + 3) & ~3;
  270         else
  271                 len = (len + 1) & ~1;
  272 
  273         outb(hpc + ds0_rbcr0, len);
  274         outb(hpc + ds0_rbcr1, len >> 8);
  275         outb(hpc + ds0_rsar0, ad);
  276         outb(hpc + ds0_rsar1, ad >> 8);
  277 
  278 #ifdef HP_DEBUG
  279         printf("hpfetch: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
  280             len, hpc + hp_data, ad, inb(hpc + hp_option),
  281             ns->ns_mode & DSDC_WTS ? 32 : 16);
  282         printf("hpfetch: cmd=0x%02x isr=0x%02x ",
  283             inb(hpc + ds_cmd), inb(hpc + ds0_isr));
  284         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
  285         printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
  286             inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr),
  287             inb(hpc + ds0_dcr));
  288 #endif
  289 
  290         /* Execute & extract from card */
  291         outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
  292 
  293 #ifdef HP_32BIT
  294         if (ns->ns_mode & DSDC_WTS)
  295                 len = (caddr_t) insd(hpc + hp_data, up, len >> 2) - up;
  296         else
  297 #endif
  298                 len = (caddr_t) insw(hpc + hp_data, up, len >> 1) - up;
  299 
  300 #ifdef HP_DEBUG
  301         printf("hpfetch: done len=%d\n", len);
  302 #endif
  303 
  304         /* Wait till done, then shutdown feature */
  305         while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0);
  306         outb(hpc + ds0_isr, DSIS_RDC);
  307         outb(hpc + ds_cmd, cmd);
  308 
  309         outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA);
  310 }
  311 /*
  312  * Put to onboard RAM
  313  */
  314 hpput(ns, up, ad, len)
  315         struct hp_softc *ns;
  316         caddr_t up;
  317 {
  318         u_char  cmd;
  319         int     hpc = ns->ns_port;
  320         int     counter = 100000;
  321 
  322         outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA);
  323 
  324         cmd = inb(hpc + ds_cmd);
  325         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  326 
  327         /* Setup for remote DMA */
  328         outb(hpc + ds0_isr, DSIS_RDC);
  329 
  330         if (ns->ns_mode & DSDC_WTS)
  331                 len = (len + 3) & ~3;
  332         else
  333                 len = (len + 1) & ~1;
  334 
  335 #ifdef HP_DEBUG
  336         printf("hpput: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n",
  337             len, hpc + hp_data, ad, inb(hpc + hp_option),
  338             ns->ns_mode & DSDC_WTS ? 32 : 16);
  339         printf("hpput: cmd=0x%02x isr=0x%02x ",
  340             inb(hpc + ds_cmd), inb(hpc + ds0_isr));
  341         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START);
  342         printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n",
  343             inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr),
  344             inb(hpc + ds0_dcr));
  345         {
  346                 unsigned char *p = (unsigned char *) up;
  347                 int     n = len;
  348                 printf("hpput:");
  349                 while (n--)
  350                         printf(" %02x", *(p++));
  351                 printf("\n");
  352         }
  353 #endif
  354 
  355         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  356         outb(hpc + ds0_rbcr0, 0xff);
  357         outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START);
  358 
  359         outb(hpc + ds0_rbcr0, len);
  360         outb(hpc + ds0_rbcr1, len >> 8);
  361         outb(hpc + ds0_rsar0, ad);
  362         outb(hpc + ds0_rsar1, ad >> 8);
  363 
  364         /* Execute & stuff to card */
  365         outb(hpc + ds_cmd, DSCM_RWRITE | DSCM_PG0 | DSCM_START);
  366 
  367 #ifdef HP_32BIT
  368         if (ns->ns_mode & DSDC_WTS)
  369                 len = (caddr_t) outsd(hpc + hp_data, up, len >> 2) - up;
  370         else
  371 #endif
  372                 len = (caddr_t) outsw(hpc + hp_data, up, len >> 1) - up;
  373 
  374 #ifdef HP_DEBUG
  375         printf("hpput: done len=%d\n", len);
  376 #endif
  377 
  378         /* Wait till done, then shutdown feature */
  379         while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0);
  380         outb(hpc + ds0_isr, DSIS_RDC);
  381         outb(hpc + ds_cmd, cmd);
  382 
  383         outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA);
  384 }
  385 /*
  386  * Reset of interface.
  387  */
  388 hpreset(unit, uban)
  389         int     unit, uban;
  390 {
  391         struct hp_softc *ns = &hp_softc[unit];
  392         int     hpc = ns->ns_port;
  393         if (unit >= NHP)
  394                 return;
  395         printf("hp%d: reset\n", unit);
  396         outb(hpc + hp_option, 0);
  397         ns->ns_flags &= ~DSF_LOCK;
  398         hpinit(unit);
  399 }
  400 
  401 static char *
  402 hp_id(type)
  403         u_char  type;
  404 {
  405         static struct {
  406                 u_char  type;
  407                 char   *name;
  408         } boards[] = {
  409                 {
  410                         0x00, "hp27240"
  411                 }, {
  412                         0x10, "hp24240"
  413                 }, {
  414                         0x01, "hp27245"
  415                 }, {
  416                         0x02, "hp27250"
  417                 }, {
  418                         0x81, "hp27247"
  419                 }, {
  420                         0x91, "hp27247r1"
  421                 }
  422         };
  423         int     n = sizeof(boards) / sizeof(boards[0]);
  424 
  425         while (n)
  426                 if (boards[--n].type == type)
  427                         return boards[n].name;
  428 
  429         return "UNKNOWN";
  430 }
  431 /*
  432  * Interface exists: make available by filling in network interface
  433  * record.  System will initialize the interface when it is ready
  434  * to accept packets.  We get the ethernet address here.
  435  */
  436 hpattach(dvp)
  437         struct isa_device *dvp;
  438 {
  439         int     unit = dvp->id_unit;
  440         struct hp_softc *ns = &hp_softc[unit];
  441         struct ifnet *ifp = &ns->ns_if;
  442 
  443         ifp->if_unit = unit;
  444         ifp->if_name = hpdriver.name;
  445         ifp->if_mtu = ETHERMTU;
  446         printf("hp%d: %s %d-bit ethernet address %s\n", unit,
  447             hp_id(ns->hp_type), ns->ns_mode & DSDC_WTS ? 32 : 16,
  448             ether_sprintf(ns->ns_addrp));
  449         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
  450         ifp->if_output = ether_output;
  451         ifp->if_start = hpstart;
  452         ifp->if_ioctl = hpioctl;
  453         ifp->if_reset = hpreset;
  454         ifp->if_watchdog = 0;
  455         IFQ_SET_READY(&ifp->if_snd);
  456         if_attach(ifp);
  457 
  458 #if NBPFILTER > 0
  459         bpfattach(&ns->ns_bpf, ifp, DLT_EN10MB,
  460             sizeof(struct ether_header));
  461 #endif
  462 
  463 #if NRND > 0
  464         rnd_attach_source(&ns->rnd_source, ns->sc_dev.dv_xname,
  465                           RND_TYPE_NET, 0);
  466 #endif
  467 
  468 }
  469 /*
  470  * Initialization of interface; set up initialization block
  471  * and transmit/receive descriptor rings.
  472  */
  473 hpinit(unit)
  474         int     unit;
  475 {
  476         struct hp_softc *ns = &hp_softc[unit];
  477         struct ifnet *ifp = &ns->ns_if;
  478         int     s;
  479         int     i;
  480         char   *cp;
  481         int hpc = ns->ns_port;
  482 
  483         if (ifp->if_addrlist == (struct ifaddr *) 0)
  484                 return;
  485         if (ifp->if_flags & IFF_RUNNING)
  486                 return;
  487 
  488         s = splnet();
  489 
  490 #ifdef HP_DEBUG
  491         printf("hpinit: hp%d at 0x%x irq %d\n", unit, hpc, (int) ns->hp_irq);
  492         printf("hpinit: promiscuous mode %s\n",
  493             ns->ns_if.if_flags & IFF_PROMISC ? "on" : "off");
  494 #endif
  495 
  496         ns->ns_rcr = (ns->ns_if.if_flags & IFF_BROADCAST ? DSRC_AB : 0) |
  497             (ns->ns_if.if_flags & IFF_PROMISC ? DSRC_PRO : 0);
  498 #ifdef HP_LOG_ERRORS
  499         ns->ns_rcr |= DSRC_SEP;
  500 #endif
  501 
  502         /* set irq and turn on board */
  503         outb(hpc + hp_option, HP_RUN | (ns->hp_irq << 1));
  504 
  505         /* init regs */
  506         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP);
  507         outb(hpc + ds0_dcr, 0);
  508         outb(hpc + ds0_rbcr0, 0);
  509         outb(hpc + ds0_rbcr1, 0);
  510         outb(hpc + ds0_rcr, DSRC_MON);
  511         outb(hpc + ds0_tpsr, ns->ns_txstart);
  512         outb(hpc + ds0_imr, 0);
  513         outb(hpc + ds0_tcr, DSTC_LB0);
  514         outb(hpc + ds0_pstart, ns->ns_rxstart);
  515         outb(hpc + ds0_bnry, ns->ns_rxend - 1);
  516         outb(hpc + ds0_pstop, ns->ns_rxend);
  517         outb(hpc + ds0_isr, 0xff);
  518         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG1 | DSCM_STOP);
  519         outb(hpc + ds1_curr, ns->ns_rxstart);
  520 
  521         /* set physical address on ethernet */
  522         for (i = 0; i < 6; i++)
  523                 outb(hpc + ds1_par0 + i, ns->ns_addrp[i]);
  524 
  525         /* clr logical address hash filter for now */
  526         for (i = 0; i < 8; i++)
  527                 outb(hpc + ds1_mar0 + i, 0xff);
  528 
  529         /* fire it up */
  530         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  531         outb(hpc + ds0_dcr, ns->ns_mode);
  532         outb(hpc + ds0_rcr, ns->ns_rcr);
  533         outb(hpc + ds0_tcr, 0);
  534         outb(hpc + ds0_imr, 0xff);
  535 
  536         ns->ns_if.if_flags |= IFF_RUNNING;
  537         ns->ns_flags &= ~DSF_LOCK;
  538         ns->ns_oactive = 0;
  539         ns->ns_mask = ~0;
  540         hpstart(ifp);
  541 
  542 #ifdef HP_DEBUG
  543         printf("hpinit: done\n", unit, hpc);
  544 #endif
  545 
  546         splx(s);
  547 }
  548 /*
  549  * Setup output on interface.
  550  * Get another datagram to send off of the interface queue,
  551  * and map it to the interface before starting the output.
  552  * called only at splnet or interrupt level.
  553  */
  554 hpstart(ifp)
  555         struct ifnet *ifp;
  556 {
  557         struct hp_softc *ns = &hp_softc[ifp->if_unit];
  558         struct mbuf *m0, *m;
  559         int     buffer;
  560         int     len, i, total;
  561         int     hpc = ns->ns_port;
  562 
  563         /*
  564                * The DS8390 has only one transmit buffer, if it is busy we
  565                * must wait until the transmit interrupt completes.
  566                */
  567         if (ns->ns_flags & DSF_LOCK)
  568                 return;
  569 
  570         if (inb(hpc + ds_cmd) & DSCM_TRANS)
  571                 return;
  572 
  573         if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)
  574                 return;
  575 
  576         IFQ_DEQUEUE(&ns->ns_if.if_snd, m);
  577 
  578         if (m == 0)
  579                 return;
  580 
  581         /*
  582                * Copy the mbuf chain into the transmit buffer
  583                */
  584 
  585         ns->ns_flags |= DSF_LOCK;       /* prevent entering hpstart */
  586         buffer = ns->ns_txstart * DS_PGSIZE;
  587         i = 0;
  588         total = len = m->m_pkthdr.len;
  589 
  590 #ifdef HP_DEBUG
  591         printf("hpstart: len=%d\n", len);
  592 #endif
  593 
  594 #if NBPFILTER > 0
  595         if (ns->ns_bpf)
  596                 bpf_mtap(ns->ns_bpf, m);
  597 #endif
  598 
  599         for (m0 = m; m != 0;) {
  600                 if (m->m_len & 1 && t > m->m_len) {
  601                         m->m_len -= 1;
  602                         hpput(ns, mtod(m, caddr_t), buffer, m->m_len);
  603                         t -= m->m_len;
  604                         buffer += m->m_len;
  605                         m->m_data += m->m_len;
  606                         m->m_len = 1;
  607                         m = m_pullup(m, 2);
  608                 } else {
  609                         hpput(ns, mtod(m, caddr_t), buffer, m->m_len);
  610                         t -= m->m_len;
  611                         buffer += m->m_len;
  612                         MFREE(m, m0);
  613                         m = m0;
  614                 }
  615         }
  616 
  617         /*
  618                * Init transmit length registers, and set transmit start flag.
  619                */
  620         len = total;
  621         if (len < ETHER_MIN_LEN)
  622                 len = ETHER_MIN_LEN;
  623 #error broken here ! need to set to 0 the pad space in buffer !
  624         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  625         outb(hpc + ds0_tbcr0, len & 0xff);
  626         outb(hpc + ds0_tbcr1, (len >> 8) & 0xff);
  627         outb(hpc + ds0_tpsr, ns->ns_txstart);
  628         outb(hpc + ds_cmd, DSCM_TRANS | DSCM_NODMA | DSCM_PG0 | DSCM_START);
  629 
  630 #ifdef HP_DEBUG
  631         printf("hpstart: done\n", hpc);
  632 #endif
  633 }
  634 /*
  635  * Controller interrupt.
  636  */
  637 hpintr(unit)
  638 {
  639         struct hp_softc *ns = &hp_softc[unit];
  640         u_char  cmd, isr;
  641         int     hpc = ns->ns_port;
  642         u_char  err;
  643 
  644         /* Save cmd, clear interrupt */
  645         cmd = inb(hpc + ds_cmd);
  646 loop:
  647         isr = inb(hpc + ds0_isr);
  648         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  649         outb(hpc + ds0_isr, isr);
  650 
  651         /* Receiver error */
  652         if (isr & DSIS_RXE) {
  653                 /* need to read these registers to clear status */
  654                 err = inb(hpc + ds0_rsr);
  655                 (void) inb(hpc + 0xD);
  656                 (void) inb(hpc + 0xE);
  657                 (void) inb(hpc + 0xF);
  658                 ns->ns_if.if_ierrors++;
  659 #ifdef HP_LOG_ERRORS
  660                 isr |= DSIS_RX;
  661 #endif
  662         }
  663         /* We received something */
  664         if (isr & DSIS_RX) {
  665                 u_char  bnry;
  666                 u_char  curr;
  667                 u_short addr;
  668                 int     len;
  669                 int     i;
  670                 unsigned char c;
  671 
  672                 while (1) {
  673                         outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
  674                         bnry = inb(hpc + ds0_bnry);
  675                         outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
  676                         curr = inb(hpc + ds1_curr);
  677 
  678 #ifdef HP_DEBUG
  679                         printf("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n",
  680                             isr, bnry, curr);
  681 #endif
  682 
  683                         if (++bnry >= ns->ns_rxend)
  684                                 bnry = ns->ns_rxstart;
  685 
  686                         /* if ring empty, done! */
  687                         if (bnry == curr)
  688                                 break;
  689 
  690                         addr = bnry * DS_PGSIZE;
  691 
  692                         outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA);
  693 
  694 #if 0
  695                         /* send packet with auto packet release */
  696                         outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
  697                         outb(hpc + ds0_rbcr1, 0x0f);
  698                         outb(hpc + ds0_dcr, ns->ns_mode | DSDC_AR);
  699                         outb(hpc + ds_cmd, DSCM_SENDP | DSCM_PG0 | DSCM_START);
  700 #endif
  701 
  702                         /* get length */
  703                         hpfetch(ns, (caddr_t) & ns->ns_ph, addr, sizeof ns->ns_ph);
  704                         addr += sizeof ns->ns_ph;
  705 
  706 #ifdef HP_DEBUG
  707                         printf("hpintr: sendp packet hdr: %x %x %x %x\n",
  708                             ns->ns_ph.pr_status,
  709                             ns->ns_ph.pr_nxtpg,
  710                             ns->ns_ph.pr_sz0,
  711                             ns->ns_ph.pr_sz1);
  712 #endif
  713 
  714 #ifdef HP_LOG_ERRORS
  715                         if (ns->ns_ph.pr_status & (DSRS_CRC | DSRS_FO | DSRS_DFR)) {
  716                                 /* Get packet header */
  717                                 if (len > 14)
  718                                         len = 14;
  719                                 hpfetch(ns, (caddr_t) (ns->ns_pb), addr, len);
  720 
  721                                 /* move boundary up */
  722                                 bnry = ns->ns_ph.pr_nxtpg;
  723                                 if (--bnry < ns->ns_rxstart)
  724                                         bnry = ns->ns_rxend - 1;
  725                                 outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
  726                                 outb(hpc + ds0_bnry, bnry);
  727 
  728                                 printf("hp%d: receive error status=0x%02x\n", unit,
  729                                     ns->ns_ph.pr_status);
  730                                 printf("hp%d: packet header:", unit);
  731                                 {
  732                                         int     n;
  733                                         for (n = 0; n < len; n++)
  734                                                 printf(" %02x", ns->ns_pb[n]);
  735                                 }
  736                                 printf("\n");
  737 
  738                                 continue;
  739                         }
  740 #endif
  741 
  742                         ns->ns_if.if_ipackets++;
  743                         len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1 << 8);
  744                         if (len < ETHER_MIN_LEN || len > ETHER_MAX_LEN) {
  745                                 printf("hpintr: bnry %x curr %x\n", bnry, curr);
  746                                 printf("hpintr: packet hdr: %x %x %x %x\n",
  747                                     ns->ns_ph.pr_status,
  748                                     ns->ns_ph.pr_nxtpg,
  749                                     ns->ns_ph.pr_sz0,
  750                                     ns->ns_ph.pr_sz1);
  751                                 printf("isr = 0x%x reg_isr=0x%x\n",
  752                                     isr, inb(hpc + ds0_isr));
  753                                 outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
  754                                 bnry = inb(hpc + ds0_bnry);
  755                                 outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1);
  756                                 curr = inb(hpc + ds1_curr);
  757                                 printf("hpintr: new bnry %x curr %x\n", bnry, curr);
  758                                 printf("hpintr: bad len %d\n-hanging-\n",
  759                                     len);
  760                                 while (1);
  761                         }
  762                         /* read packet */
  763                         hpfetch(ns, (caddr_t) (ns->ns_pb), addr, len);
  764 
  765                         /* move boundary up */
  766                         bnry = ns->ns_ph.pr_nxtpg;
  767                         if (--bnry < ns->ns_rxstart)
  768                                 bnry = ns->ns_rxend - 1;
  769                         outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0);
  770                         outb(hpc + ds0_bnry, bnry);
  771 
  772 #ifdef HP_DEBUG
  773                         printf("hpintr: receive done bnry=0x%02x\n", bnry);
  774 #endif
  775 
  776                         outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA);
  777 
  778                         /* adjust for ether header and checksum */
  779                         len -= sizeof(struct ether_header) + sizeof(long);
  780 
  781                         /* process packet */
  782                         hpread(ns, (caddr_t) (ns->ns_pb), len);
  783                 }
  784         }
  785         /* Transmit error */
  786         if (isr & DSIS_TXE) {
  787                 ns->ns_flags &= ~DSF_LOCK;
  788                 /* Need to read these registers to clear status */
  789                 ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0);
  790                 ns->ns_if.if_oerrors++;
  791         }
  792         /* Packet Transmitted */
  793         if (isr & DSIS_TX) {
  794                 ns->ns_flags &= ~DSF_LOCK;
  795                 ++ns->ns_if.if_opackets;
  796                 ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0);
  797         }
  798         /* Receiver ovverun? */
  799         if (isr & DSIS_ROVRN) {
  800                 log(LOG_ERR, "hp%d: error: isr %x\n", ns - hp_softc, isr
  801                      /* , DSIS_BITS */ );
  802                 outb(hpc + ds0_rbcr0, 0);
  803                 outb(hpc + ds0_rbcr1, 0);
  804                 outb(hpc + ds0_tcr, DSTC_LB0);
  805                 outb(hpc + ds0_rcr, DSRC_MON);
  806                 outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA);
  807                 outb(hpc + ds0_rcr, ns->ns_rcr);
  808                 outb(hpc + ds0_tcr, 0);
  809         }
  810         /* Any more to send? */
  811         outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START);
  812         hpstart(&ns->ns_if);
  813         outb(hpc + ds_cmd, cmd);
  814         outb(hpc + ds0_imr, 0xff);
  815 
  816 #if NRND > 0
  817         if (irs)
  818                 rnd_add_uint32(&sc->rnd_source, isr);
  819 #endif
  820 
  821         /* Still more to do? */
  822         isr = inb(hpc + ds0_isr);
  823         if (isr)
  824                 goto loop;
  825 }
  826 /*
  827  * Pass a packet to the higher levels.
  828  * We deal with the trailer protocol here.
  829  */
  830 hpread(ns, buf, len)
  831         struct hp_softc *ns;
  832         char   *buf;
  833         int     len;
  834 {
  835         struct ether_header *eh;
  836         struct mbuf *m;
  837         int     off, resid;
  838         struct ifqueue *inq;
  839         u_short etype;
  840 
  841         /*
  842          * Deal with trailer protocol: if type is trailer type
  843          * get true type from first 16-bit word past data.
  844          * Remember that type was trailer by setting off.
  845          */
  846         eh = (struct ether_header *) buf;
  847         etype = ntohs((u_short) eh->ether_type);
  848 #define hpdataaddr(eh, off, type)       ((type)(((caddr_t)((eh)+1)+(off))))
  849         if (etype >= ETHERTYPE_TRAIL &&
  850             etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) {
  851                 off = (etype - ETHERTYPE_TRAIL) * 512;
  852                 if (off >= ETHERMTU)
  853                         return; /* sanity */
  854                 eh->ether_type = *hpdataaddr(eh, off, u_short *);
  855                 resid = ntohs(*(hpdataaddr(eh, off + 2, u_short *)));
  856                 if (off + resid > len)
  857                         return; /* sanity */
  858                 len = off + resid;
  859         } else
  860                 off = 0;
  861 
  862         if (len == 0)
  863                 return;
  864 
  865 #if NBPFILTER > 0
  866         if (ns->ns_bpf)
  867                 bpf_tap(ns->ns_bpf, buf, len + sizeof(struct ether_header));
  868 #endif
  869 
  870         if ((ns->ns_if.if_flags & IFF_PROMISC)
  871             && memcmp(eh->ether_dhost, ns->ns_addrp,
  872                 sizeof(eh->ether_dhost)) != 0
  873             && memcmp(eh->ether_dhost, etherbroadcastaddr,
  874                 sizeof(eh->ether_dhost)) != 0)
  875                 return;
  876 
  877         /*
  878                * Pull packet off interface.  Off is nonzero if packet
  879                * has trailing header; hpget will then force this header
  880                * information to be at the front, but we still have to drop
  881                * the type and length which are at the front of any trailer data.
  882                */
  883         m = hpget(buf, len, off, &ns->ns_if);
  884         if (m == 0)
  885                 return;
  886 
  887         ether_input(&ns->ns_if, eh, m);
  888 }
  889 /*
  890  * Supporting routines
  891  */
  892 
  893 /*
  894  * Pull read data off a interface.
  895  * Len is length of data, with local net header stripped.
  896  * Off is non-zero if a trailer protocol was used, and
  897  * gives the offset of the trailer information.
  898  * We copy the trailer information and then all the normal
  899  * data into mbufs.  When full cluster sized units are present
  900  * we copy into clusters.
  901  */
  902 struct mbuf *
  903 hpget(buf, totlen, off0, ifp)
  904         caddr_t buf;
  905         int     totlen, off0;
  906         struct ifnet *ifp;
  907 {
  908         struct mbuf *top, **mp, *m, *p;
  909         int     off = off0, len;
  910         caddr_t cp = buf;
  911         char   *epkt;
  912 
  913         buf += sizeof(struct ether_header);
  914         cp = buf;
  915         epkt = cp + totlen;
  916 
  917 
  918         if (off) {
  919                 cp += off + 2 * sizeof(u_short);
  920                 totlen -= 2 * sizeof(u_short);
  921         }
  922         MGETHDR(m, M_DONTWAIT, MT_DATA);
  923         if (m == 0)
  924                 return (0);
  925         m->m_pkthdr.rcvif = ifp;
  926         m->m_pkthdr.len = totlen;
  927         m->m_len = MHLEN;
  928 
  929         top = 0;
  930         mp = &top;
  931         while (totlen > 0) {
  932                 if (top) {
  933                         MGET(m, M_DONTWAIT, MT_DATA);
  934                         if (m == 0) {
  935                                 m_freem(top);
  936                                 return (0);
  937                         }
  938                         m->m_len = MLEN;
  939                 }
  940                 len = min(totlen, epkt - cp);
  941                 if (len >= MINCLSIZE) {
  942                         MCLGET(m, M_DONTWAIT);
  943                         if (m->m_flags & M_EXT)
  944                                 m->m_len = len = min(len, MCLBYTES);
  945                         else
  946                                 len = m->m_len;
  947                 } else {
  948                         /*
  949                                        * Place initial small packet/header at end of mbuf.
  950                                        */
  951                         if (len < m->m_len) {
  952                                 if (top == 0 && len + max_linkhdr <= m->m_len)
  953                                         m->m_data += max_linkhdr;
  954                                 m->m_len = len;
  955                         } else
  956                                 len = m->m_len;
  957                 }
  958                 memcpy(mtod(m, caddr_t), cp, (unsigned) len);
  959                 cp += len;
  960                 *mp = m;
  961                 mp = &m->m_next;
  962                 totlen -= len;
  963                 if (cp == epkt)
  964                         cp = buf;
  965         }
  966         return (top);
  967 }
  968 /*
  969  * Process an ioctl request.
  970  */
  971 hpioctl(ifp, cmd, data)
  972         struct ifnet *ifp;
  973         u_long  cmd;
  974         caddr_t data;
  975 {
  976         struct ifaddr *ifa = (struct ifaddr *) data;
  977         struct hp_softc *ns = &hp_softc[ifp->if_unit];
  978         struct ifreq *ifr = (struct ifreq *) data;
  979         int     s = splnet(), error = 0;
  980 
  981 
  982         switch (cmd) {
  983 
  984         case SIOCSIFADDR:
  985                 ifp->if_flags |= IFF_UP;
  986 
  987                 switch (ifa->ifa_addr->sa_family) {
  988 #ifdef INET
  989                 case AF_INET:
  990                         hpinit(ifp->if_unit);   /* before arpwhohas */
  991                         ((struct arpcom *) ifp)->ac_ipaddr =
  992                             IA_SIN(ifa)->sin_addr;
  993                         arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr);
  994                         break;
  995 #endif
  996 #ifdef NS
  997                 case AF_NS:
  998                         {
  999                                 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
 1000 
 1001                                 if (ns_nullhost(*ina))
 1002                                         ina->x_host = *(union ns_host *) (ns->ns_addrp);
 1003                                 else {
 1004                                         /*
 1005                                                          * The manual says we can't change the address
 1006                                                          * while the receiver is armed,
 1007                                                          * so reset everything
 1008                                                          */
 1009                                         ifp->if_flags &= ~IFF_RUNNING;
 1010                                         memcpy((caddr_t) ns->ns_addrp,
 1011                                             (caddr_t) ina->x_host.c_host,
 1012                                             sizeof(ns->ns_addrp));
 1013                                 }
 1014                                 hpinit(ifp->if_unit);   /* does hp_setaddr() */
 1015                                 break;
 1016                         }
 1017 #endif
 1018                 default:
 1019                         hpinit(ifp->if_unit);
 1020                         break;
 1021                 }
 1022                 break;
 1023 
 1024         case SIOCSIFFLAGS:
 1025 #ifdef HP_DEBUG
 1026                 printf("hp: setting flags, up: %s, running: %s\n",
 1027                     ifp->if_flags & IFF_UP ? "yes" : "no",
 1028                     ifp->if_flags & IFF_RUNNING ? "yes" : "no");
 1029 #endif
 1030                 if ((ifp->if_flags & IFF_UP) == 0 &&
 1031                     ifp->if_flags & IFF_RUNNING) {
 1032                         ifp->if_flags &= ~IFF_RUNNING;
 1033                         outb(ns->ns_port + ds_cmd, DSCM_STOP | DSCM_NODMA);
 1034                 } else
 1035                         if (ifp->if_flags & IFF_UP &&
 1036                             (ifp->if_flags & IFF_RUNNING) == 0)
 1037                                 hpinit(ifp->if_unit);
 1038                 break;
 1039 
 1040 #ifdef notdef
 1041         case SIOCGHWADDR:
 1042                 memcpy((caddr_t) & ifr->ifr_data, (caddr_t) ns->ns_addrp,
 1043                     sizeof(ns->ns_addrp));
 1044                 break;
 1045 #endif
 1046 
 1047         default:
 1048                 error = EINVAL;
 1049         }
 1050         splx(s);
 1051         return (error);
 1052 }
 1053 #endif

Cache object: d7f99744d3ff943c5c7a3fa76016b3e1


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.