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/i386at/if_ns8390.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 /*
    2  * Mach Operating System
    3  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        if_ns8390.c,v $
   29  * Revision 2.22  93/05/10  23:24:07  rvb
   30  *      Checkin for MK80 branch.
   31  *      [93/05/10  15:13:33  grm]
   32  * 
   33  * Revision 2.20.1.2  93/04/20  11:48:30  grm
   34  *      Changed ttd variable name.
   35  * 
   36  * Revision 2.20.1.1  93/03/01  15:28:16  grm
   37  *      Added TTD teledebug code to use the ns8390 as a remote ethernet
   38  *      debugging device.
   39  *      [93/03/01            grm]
   40  * 
   41  * Revision 2.21  93/05/10  21:19:20  rvb
   42  *      Lint.
   43  *      [93/05/08  11:20:50  af]
   44  * 
   45  * Revision 2.20  93/01/24  13:17:18  danner
   46  *      Sigh! Sometimes the reported length of the packet is zero.  But
   47  *      the rest of the chain looked OK.  So we'll just skip the packet.
   48  *      [92/10/27            rvb]
   49  * 
   50  * Revision 2.19  93/01/14  17:30:37  danner
   51  *      Proper spl typing.
   52  *      [92/11/30            af]
   53  * 
   54  * Revision 2.18  92/08/03  17:17:43  jfriedl
   55  *      Fixed bug in wd80xxget_board_id, that made the machine hang on
   56  *      reboot when using wd8013EP boards.
   57  *      [92/07/13            kivinen]
   58  * 
   59  * Revision 2.17  92/07/09  22:54:18  rvb
   60  *      Say whether EtherLink II is thick or thin.
   61  *      [92/06/18            rvb]
   62  * 
   63  * Revision 2.16  92/04/03  12:15:19  rpd
   64  *      Use port 0x250, 0x350 for irq 5 bnc, thick respectively.
   65  *      [92/04/02            rvb]
   66  * 
   67  * Revision 2.15  92/02/19  15:08:22  elf
   68  *      Made wd driver work with 16 bit cards. Better recognize different
   69  *      cards. Print card name when probing. Tested on wd8003, wd8013EP,
   70  *      wd8003EP.
   71  *      Add IFWD_ prefix to defines.
   72  *      [92/01/20            kivinen]
   73  * 
   74  * Revision 2.14  91/11/12  11:09:39  rvb
   75  *      Undo "strict" wrong change to probe()
   76  *      [91/10/25            rvb]
   77  * 
   78  * Revision 2.13  91/10/09  16:07:43  af
   79  *       Revision 2.12.1.1  91/09/03  17:28:50  af
   80  *              Fixes from 2.5 (from rvb), made sure two WD boards work (with
   81  *              help from jeffreyh).
   82  * 
   83  * Revision 2.12.1.1  91/09/03  17:28:50  af
   84  *      Fixes from 2.5 (from rvb), made sure two WD boards work (with
   85  *      help from jeffreyh).
   86  * 
   87  * Revision 2.12  91/08/24  11:58:01  af
   88  *      New MI autoconf.
   89  *      [91/08/02  02:55:17  af]
   90  * 
   91  * Revision 2.11  91/05/14  16:24:56  mrt
   92  *      Correcting copyright
   93  * 
   94  * Revision 2.10  91/05/13  06:02:41  af
   95  *      Made code under CMUCS standard.
   96  *      [91/05/12  15:50:35  af]
   97  * 
   98  * Revision 2.9  91/03/16  14:46:23  rpd
   99  *      Changed net_filter to net_packet.
  100  *      [91/01/15            rpd]
  101  * 
  102  * Revision 2.8  91/02/14  14:42:44  mrt
  103  *      Distinguish EtherLinkII vs WD8003 on open.  Get packet
  104  *      size right for statistics.  Fix 3.0 buf that sometimes
  105  *      reported packets too large.
  106  *      [91/01/28  15:31:22  rvb]
  107  * 
  108  * Revision 2.7  91/02/05  17:17:52  mrt
  109  *      Changed to new Mach copyright
  110  *      [91/02/01  17:44:04  mrt]
  111  * 
  112  * Revision 2.6  91/01/09  16:07:19  rpd
  113  *      Fixed typo in ns8390probe.
  114  *      [91/01/09            rpd]
  115  * 
  116  * Revision 2.5  91/01/08  17:35:46  rpd
  117  *      Changed NET_KMSG_GET to net_kmsg_get.
  118  *      [91/01/08            rpd]
  119  * 
  120  * Revision 2.4  91/01/08  17:33:05  rpd
  121  *      A few bug fixes.
  122  *      [91/01/08  16:41:04  rvb]
  123  * 
  124  *      Make this a generic driver for ns8390 from wd8003 because
  125  *      we now will also support etherlink ii.
  126  *      [91/01/04  12:25:21  rvb]
  127  * 
  128  * Revision 2.1.1.7  90/11/27  13:43:18  rvb
  129  *      Synched 2.5 & 3.0 at I386q (r2.1.1.7) & XMK35 (r2.3)
  130  *      [90/11/15            rvb]
  131  * 
  132  * Revision 2.2  90/10/01  14:23:09  jeffreyh
  133  *      Changes for MACH_KERNEL. 
  134  *      initial checkin.
  135  *      [90/09/27  18:22:09  jeffreyh]
  136  *
  137  * Revision 2.1.1.6  90/09/18  08:38:39  rvb
  138  *      Unfortunately, the switches to bank 0 seem necessary so are back
  139  *      in.
  140  *      [90/09/08            rvb]
  141  * 
  142  * Revision 2.1.1.5  90/08/25  15:42:58  rvb
  143  *      Use take_<>_irq() vs direct manipulations of ivect and friends.
  144  *      [90/08/20            rvb]
  145  * 
  146  *      Flush unnecessary switches to bank 0. Use error counters
  147  *      vs printouts.  Fix DSF_RUNNING.  Some more cleanup.
  148  *      [90/08/14            rvb]
  149  * 
  150  * Revision 2.1.1.4  90/07/28  10:00:40  rvb
  151  *      Get correct counter offsets
  152  * 
  153  * Revision 2.1.1.3  90/07/27  17:16:05  rvb
  154  *      No multicast for now.
  155  * 
  156  * Revision 2.1.1.2  90/07/27  11:25:11  rvb
  157  *      Add boardID support for wd80xxyyy family of boards.     [rweiss]
  158  *      Bunch of cleanup and ...                [rweiss&rvb]
  159  * 
  160  * Revision 2.1.1.1  90/07/10  11:44:46  rvb
  161  *      Added to system.
  162  *      [90/07/06            rvb]
  163  *
  164  *
  165  *   Author: Ron Weiss (rweiss)
  166  *
  167  */
  168  
  169 /* NOTE:
  170  *      There are three outstanding bug/features in this implementation.
  171  * They may even be hardware misfeatures.  The conditions are registered
  172  * by counters maintained by the software.
  173  *      1: over_write is a condition that means that the board wants to store
  174  * packets, but there is no room.  So new packets are lost.  What seems to
  175  * be happening is that we get an over_write condition, but there are no
  176  * or just a few packets in the board's ram.  Also it seems that we get
  177  * several over_writes in a row.
  178  *      2: Since there is only one transmit buffer, we need a lock to indicate
  179  * whether it is in use.  We clear this lock when we get a transmit interrupt.
  180  * Sometimes we go to transmit and although there is no transmit in progress,
  181  * the lock is set.  (In this case, we just ignore the lock.)  It would look
  182  * like we can miss transmit interrupts?
  183  *      3: We tried to clean up the unnecessary switches to bank 0.  
  184  * Unfortunately, when you do an ifconfig "down", the system tend to lock up
  185  * a few seconds later (this was when DSF_RUNNING) was not being set before.
  186  * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after
  187  * a few seconds. 
  188  */
  189 
  190 /*
  191  * Western Digital 8003E Mach Ethernet driver (for intel 80386)
  192  * Copyright (c) 1990 by Open Software Foundation (OSF).
  193  */
  194 
  195 /*
  196   Copyright 1990 by Open Software Foundation,
  197 Cambridge, MA.
  198 
  199                 All Rights Reserved
  200 
  201   Permission to use, copy, modify, and distribute this software and
  202 its documentation for any purpose and without fee is hereby granted,
  203 provided that the above copyright notice appears in all copies and
  204 that both the copyright notice and this permission notice appear in
  205 supporting documentation, and that the name of OSF or Open Software
  206 Foundation not be used in advertising or publicity pertaining to
  207 distribution of the software without specific, written prior
  208 permission.
  209 
  210   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  211 <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  212 IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  213 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  214 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  215 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  216 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  217 */
  218 
  219 #define IF_CNTRS        MACH
  220 #include        <ns8390.h>
  221 
  222 #ifdef  MACH_KERNEL
  223 #include        <mach_ttd.h>
  224 #include        <kern/time_out.h>
  225 #include        <device/device_types.h>
  226 #include        <device/errno.h>
  227 #include        <device/io_req.h>
  228 #include        <device/if_hdr.h>
  229 #include        <device/if_ether.h>
  230 #include        <device/net_status.h>
  231 #include        <device/net_io.h>
  232 #else   MACH_KERNEL
  233 #include        <sys/param.h>
  234 #include        <mach/machine/vm_param.h>
  235 #include        <sys/systm.h>
  236 #include        <sys/mbuf.h>
  237 #include        <sys/buf.h>
  238 #include        <sys/protosw.h>
  239 #include        <sys/socket.h>
  240 #include        <sys/vmmac.h>
  241 #include        <sys/ioctl.h>
  242 #include        <sys/errno.h>
  243 #include        <sys/syslog.h>
  244 
  245 #include        <net/if.h>
  246 #include        <net/netisr.h>
  247 #include        <net/route.h>
  248 
  249 #ifdef  INET
  250 #include        <netinet/in.h>
  251 #include        <netinet/in_systm.h>
  252 #include        <netinet/in_var.h>
  253 #include        <netinet/ip.h>
  254 #include        <netinet/if_ether.h>
  255 #endif
  256 
  257 #ifdef  NS
  258 #include        <netns/ns.h>
  259 #include        <netns/ns_if.h>
  260 #endif
  261 #endif  MACH_KERNEL
  262 
  263 #include        <i386/ipl.h>
  264 #include        <chips/busses.h>
  265 #include        <i386at/if_ns8390.h>
  266 #include        <i386at/if_wd8003.h>
  267 #include        <i386at/if_3c503.h>
  268 
  269 #if     MACH_TTD
  270 #include <ttd/ttd_stub.h>
  271 #endif  /* MACH_TTD */
  272 
  273 
  274 #define SPLNET  spl6
  275 
  276 int wd_debug = 0;
  277   
  278 int     ns8390probe();
  279 void    ns8390attach();
  280 int     ns8390intr();
  281 int     ns8390init();
  282 int     ns8390output();
  283 int     ns8390ioctl();
  284 int     ns8390reset();
  285 int     ns8390rcv();
  286 int     ns8390watch();
  287 int     ns8390get_CURR();
  288 int     ns8390over_write();
  289 
  290 struct  bus_device      *ns8390info[NNS8390];   /* ???? */
  291 
  292 static vm_offset_t ns8390_std[NNS8390] = { 0 };
  293 static struct bus_device *ns8390_info[NNS8390];
  294 struct  bus_driver      ns8390driver =
  295         {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0};
  296 
  297 int     watchdog_id;
  298 
  299 char *wd8003_card = "wd";
  300 char *elii_card = "el";
  301 /*                2e0, 2a0, 280,  250,   350,   330,   310, 300*/
  302 int elii_irq[8] = {5,   2,   2,     5,     5, 0x711, 0x711,  5};
  303 int elii_bnc[8] = {1,   0,   1,     1,     0, 0x711, 0x711,  0};
  304 /*int elii_bnc[8] = {0, 1,   1,     1,     1,     1,     0,  1}; */
  305 
  306 typedef struct {
  307 #ifdef  MACH_KERNEL
  308         struct  ifnet   ds_if;          /* generic interface header */
  309         u_char  ds_addr[6];             /* Ethernet hardware address */
  310 #else   MACH_KERNEL
  311         struct  arpcom  ns8390_ac;
  312 #define ds_if   ns8390_ac.ac_if
  313 #define ds_addr ns8390_ac.ac_enaddr
  314 #endif  MACH_KERNEL
  315         int     flags;
  316         int     timer;
  317         int     interrupt;
  318         char    *nic;
  319         u_char   address[ETHER_ADDR_SIZE];
  320         short   mode;
  321         int     tbusy;
  322         char    *sram;          /* beginning of the shared memory RAM buffer */
  323         int     read_nxtpkt_ptr;/* pointer to next packet available */
  324         int     pstart;         /* page start hold */
  325         int     pstop;          /* page stop hold */
  326         int     tpsr;           /* transmit page start hold */
  327         int     fifo_depth;     /* NIC fifo threshold */
  328         char    *card;
  329         int     board_id;
  330 }
  331 ns8390_softc_t;
  332 
  333 ns8390_softc_t  ns8390_softc[NNS8390];
  334 
  335 struct ns8390_cntrs {
  336 u_int   ovw,
  337         jabber,
  338         crc,
  339         frame,
  340         miss,
  341         fifo,
  342         rcv;
  343 u_int   xmt,
  344         xmti,
  345         busy,
  346         heart;
  347 } ns8390_cntrs[NNS8390];
  348 
  349 #if     MACH_TTD        
  350 boolean_t ttd_poll_loop;
  351 
  352 int ns8390poll_receive();
  353 int ns8390transmit_ttd();
  354 #endif  /* MACH_TTD */
  355 
  356 #ifdef  IF_CNTRS
  357 int ns_narp = 1, ns_arp = 0;
  358 int ns_ein[32], ns_eout[32]; 
  359 int ns_lin[128/8], ns_lout[128/8]; 
  360 static
  361 log_2(no)
  362 unsigned long no;
  363 {
  364         return ({ unsigned long _temp__;
  365                 asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
  366                     "=r" (_temp__) : "a" (no));
  367                 _temp__;});
  368 }
  369 #endif  IF_CNTRS
  370 
  371 int  imr_hold = PRXE|PTXE|RXEE|TXEE|OVWE|CNTE;  /* Interrupts mask bits */
  372 
  373 /*
  374  * ns8390probe:
  375  *
  376  *      This function "probes" or checks for the wd8003 board on the bus to see
  377  *      if it is there.  As far as I can tell, the best break between this
  378  *      routine and the attach code is to simply determine whether the board
  379  *      is configured in properly. Currently my approach to this is to test the
  380  *      base I/O special offset for the Western Digital unique byte sequence
  381  *      identifier.  If the bytes match we assume board is there.
  382  *      The config code expects to see a successful return from the probe
  383  *      routine before attach will be called.
  384  *
  385  * input        : address device is mapped to, and unit # being checked
  386  * output       : a '1' is returned if the board exists, and a 0 otherwise
  387  *
  388  */
  389 
  390 ns8390probe(port, dev)
  391 struct bus_device       *dev;
  392 {
  393         caddr_t         hdwbase = (caddr_t)dev->address;
  394         int             unit = dev->unit;
  395         ns8390_softc_t  *sp = &ns8390_softc[unit];
  396         int             tmp;
  397 
  398         if ((unit < 0) || (unit > NNS8390)) {
  399                 printf("ns8390 ethernet unit %d out of range\n", unit);
  400                 return(0);
  401         }
  402         if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) &&
  403             ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) &&
  404             ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) {
  405                         ns8390info[unit] = dev;
  406                         sp->card = wd8003_card;
  407                         dev->name = wd8003_card;
  408                         sp->nic = hdwbase + OFF_8390;
  409                                 /* enable mem access to board */
  410                         sp->board_id = wd80xxget_board_id(dev);
  411 
  412                         *(sp->address)      = inb(hdwbase+IFWD_LAR_0);
  413                         *(sp->address + 1)  = inb(hdwbase+IFWD_LAR_1);
  414                         *(sp->address + 2)  = inb(hdwbase+IFWD_LAR_2);
  415                         *(sp->address + 3)  = inb(hdwbase+IFWD_LAR_3);
  416                         *(sp->address + 4)  = inb(hdwbase+IFWD_LAR_4);
  417                         *(sp->address + 5)  = inb(hdwbase+IFWD_LAR_5);
  418                         return (1);
  419                 }  /* checks the address of the board to verify that it is a WD */
  420         if (tmp = inb(hdwbase+BCFR)) {
  421                 switch(tmp) {
  422                 case (1<<7):    sp->board_id = 7; break;        /*irq5 xvcr*/
  423 #ifdef  not_currently_possible
  424                 case (1<<6):    sp->board_id = 6; break;
  425                 case (1<<5):    sp->board_id = 5; break;
  426 #endif  not_currently_possible
  427                 case (1<<4):    sp->board_id = 4; break;
  428                 case (1<<3):    sp->board_id = 3; break;
  429                 case (1<<2):    sp->board_id = 2; break;        /*irq2 bnc*/
  430                 case (1<<1):    sp->board_id = 1; break;        /*irq2 xvcr*/
  431                 case (1<<0):    sp->board_id = 0; break;        /*irq5 bnc*/
  432                 default:        return 0;
  433                 }
  434                 switch (inb(hdwbase+PCFR)) {
  435                 case (1<<7):    dev->phys_address = 0xDC000; break;
  436                 case (1<<6):    dev->phys_address = 0xD8000; break;
  437 #ifdef  not_currently_possible
  438                 case (1<<5):    dev->phys_address = 0xCC000; break;
  439                 case (1<<4):    dev->phys_address = 0xC8000; break;
  440 #endif  not_currently_possible
  441                 default:
  442                         printf("EtherLink II with NO memory configured\n");
  443                         return 0;
  444                 }
  445                 ns8390info[unit] = dev;
  446                 dev->sysdep1 = elii_irq[sp->board_id];
  447                 if (dev->sysdep1 == 2)
  448                         dev->sysdep1 = 9;
  449                 sp->card = elii_card;
  450                 dev->name = elii_card;
  451                 sp->nic = hdwbase;
  452                 return 1;
  453         }
  454         return(0);
  455 }
  456 
  457 /*
  458  * ns8390attach:
  459  *
  460  *      This function attaches a ns8390 board to the "system".  The rest of
  461  *      runtime structures are initialized here (this routine is called after
  462  *      a successful probe of the board).  Once the ethernet address is read
  463  *      and stored, the board's ifnet structure is attached and readied.
  464  *
  465  * input        : bus_device structure setup in autoconfig
  466  * output       : board structs and ifnet is setup
  467  *
  468  */
  469 
  470 void ns8390attach(dev)
  471 struct bus_device       *dev;
  472 {
  473         ns8390_softc_t  *sp;
  474         struct  ifnet   *ifp;
  475         u_char          unit;
  476         int             temp;
  477 
  478         take_dev_irq(dev);
  479         unit = (u_char)dev->unit;
  480         sp = &ns8390_softc[unit];
  481         printf(", port = %x, spl = %d, pic = %d. ",
  482                 dev->address, dev->sysdep, dev->sysdep1);
  483 
  484         if (sp->card == elii_card) {
  485                 if (elii_bnc[sp->board_id])
  486                         printf("cheapernet ");
  487                 else
  488                         printf("ethernet ");
  489         } else
  490                 printf("ethernet ");
  491 
  492         (volatile char *)sp->sram =
  493             (volatile char *) phystokv(dev->phys_address);
  494         dev->address = (vm_offset_t) phystokv(dev->address);
  495         sp->timer = -1;
  496         sp->flags = 0;
  497         sp->mode  = 0;
  498 
  499         if (!ns8390hwrst(unit)) {
  500                 printf("%s%d: attach(): reset failed.\n",
  501                         sp->card, unit);
  502                 return;
  503         }
  504                 /* N.B. sp->address is not determined till
  505                  * hwrst time. */
  506         *(sp->ds_addr)      = *(sp->address);
  507         *(sp->ds_addr + 1)  = *(sp->address + 1);
  508         *(sp->ds_addr + 2)  = *(sp->address + 2);
  509         *(sp->ds_addr + 3)  = *(sp->address + 3);
  510         *(sp->ds_addr + 4)  = *(sp->address + 4);
  511         *(sp->ds_addr + 5)  = *(sp->address + 5);
  512 
  513         printf("id [%x:%x:%x:%x:%x:%x]",
  514                 sp->address[0],sp->address[1],sp->address[2],
  515                 sp->address[3],sp->address[4],sp->address[5]);
  516         ifp = &(sp->ds_if);
  517         ifp->if_unit = unit;
  518         ifp->if_mtu = ETHERMTU;
  519         ifp->if_flags = IFF_BROADCAST;
  520 #ifdef  MACH_KERNEL
  521         ifp->if_header_size = sizeof(struct ether_header);
  522         ifp->if_header_format = HDR_ETHERNET;
  523         ifp->if_address_size = 6;
  524         ifp->if_address = (char *)&sp->address[0];
  525         if_init_queues(ifp);
  526 #else   MACH_KERNEL
  527         ifp->if_name = sp->card;
  528         ifp->if_init = ns8390init;
  529         ifp->if_output = ns8390output;
  530         ifp->if_ioctl = ns8390ioctl;
  531         ifp->if_reset = ns8390reset;
  532         ifp->if_next = NULL;
  533         if_attach(ifp);
  534 #ifdef notdef
  535         watchdog_id = timeout(ns8390watch, &(ifp->if_unit), 20*HZ);
  536 #endif
  537 #endif  MACH_KERNEL
  538 
  539 #ifdef  MACH_KERNEL
  540 #if     MACH_TTD
  541         if (!ttd_get_packet) {
  542                 ttd_device_unit = unit;
  543                 ttd_get_packet = ns8390poll_receive;
  544                 ttd_send_packet = ns8390transmit_ttd;
  545                 ttd_host_ether_id.array[0] = *(sp->address);
  546                 ttd_host_ether_id.array[1] = *(sp->address + 1);
  547                 ttd_host_ether_id.array[2] = *(sp->address + 2);
  548                 ttd_host_ether_id.array[3] = *(sp->address + 3);
  549                 ttd_host_ether_id.array[4] = *(sp->address + 4);
  550                 ttd_host_ether_id.array[5] = *(sp->address + 5);
  551         }
  552 #endif  /* MACH_TTD */
  553 #endif  /* MACH_KERNEL */
  554 }
  555 
  556 /*
  557  * ns8390watch():
  558  *
  559  */
  560 
  561 int
  562 ns8390watch(b_ptr)
  563 caddr_t b_ptr;
  564 {
  565         int     x,
  566                 y,
  567                 opri,
  568                 unit;
  569         int     temp_cr;
  570         caddr_t nic;
  571 
  572         unit = *b_ptr;
  573 #ifdef  MACH_KERNEL
  574         timeout(ns8390watch,b_ptr,20*HZ);
  575 #else   MACH_KERNEL
  576         watchdog_id = timeout(ns8390watch,b_ptr,20*HZ);
  577 #endif  MACH_KERNEL
  578         nic = ns8390_softc[unit].nic;
  579         temp_cr = inb(nic+CR);
  580         outb(nic + CR, (temp_cr & 0x3f) | PS0);
  581         printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ",
  582                 inb(nic + ISR),
  583                 ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr,
  584                 inb(nic+BNDY));
  585         outb(nic+CR,temp_cr);
  586 }
  587 
  588 #ifdef  MACH_KERNEL
  589 int ns8390start();      /* forward */
  590 
  591 /*ARGSUSED*/
  592 wd8003open(dev, flag)
  593         dev_t   dev;
  594         int     flag;
  595 {
  596         register int    unit = minor(dev);
  597 
  598         if (ns8390_softc[unit].card != wd8003_card)
  599                 return (ENXIO);
  600         if (unit < 0 || unit >= NNS8390 ||
  601                 ns8390_softc[unit].nic == 0)
  602             return (ENXIO);
  603 
  604         ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
  605         ns8390init(unit);
  606         return(0);
  607 }
  608 
  609 eliiopen(dev, flag)
  610         dev_t   dev;
  611         int     flag;
  612 {
  613         register int    unit = minor(dev);
  614 
  615         if (ns8390_softc[unit].card != elii_card)
  616                 return (ENXIO);
  617         if (unit < 0 || unit >= NNS8390 ||
  618                 ns8390_softc[unit].nic == 0)
  619             return (ENXIO);
  620 
  621         ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
  622         ns8390init(unit);
  623         return(0);
  624 }
  625 
  626 ns8390output(dev, ior)
  627         dev_t           dev;
  628         io_req_t        ior;
  629 {
  630         register int    unit = minor(dev);
  631 
  632         if (unit < 0 || unit >= NNS8390 ||
  633                 ns8390_softc[unit].nic == 0)
  634             return (ENXIO);
  635         return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior));
  636 }
  637 
  638 ns8390setinput(dev, receive_port, priority, filter, filter_count)
  639         dev_t           dev;
  640         mach_port_t     receive_port;
  641         int             priority;
  642         filter_t        filter[];
  643         unsigned int    filter_count;
  644 {
  645         register int unit = minor(dev);
  646 
  647         if (unit < 0 || unit >= NNS8390 ||
  648                 ns8390_softc[unit].nic == 0)
  649             return (ENXIO);
  650 
  651         return (net_set_filter(&ns8390_softc[unit].ds_if,
  652                         receive_port, priority,
  653                         filter, filter_count));
  654 }
  655 
  656 #else   MACH_KERNEL
  657 /*
  658  * ns8390output:
  659  *
  660  *      This routine is called by the "if" layer to output a packet to
  661  *      the network.  This code resolves the local ethernet address, and
  662  *      puts it into the mbuf if there is room.  If not, then a new mbuf
  663  *      is allocated with the header information and precedes the data
  664  *      to be transmitted.  The routine ns8390xmt() which actually
  665  *      transmits the data expects the ethernet header to precede the
  666  *      data in the mbuf.
  667  *
  668  * input:       ifnet structure pointer, an mbuf with data, and address
  669  *              to be resolved
  670  * output:      mbuf is updated to hold enet address, or a new mbuf
  671  *              with the address is added
  672  *
  673  */
  674 
  675 ns8390output(ifp, m0, dst)
  676 struct ifnet    *ifp;
  677 struct mbuf     *m0;
  678 struct sockaddr *dst;
  679 {
  680         register ns8390_softc_t         *is = &ns8390_softc[ifp->if_unit];
  681         u_char                          edst[6];
  682         struct in_addr                  idst;
  683         register struct mbuf            *m = m0;
  684         register struct ether_header    *eh;
  685         register int                    off;
  686         int                             usetrailers;
  687         int                             type, error;
  688         spl_t                           opri;
  689 
  690         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  691                 printf("%s%d output(): Turning off board %d\n",
  692                         is->card, ifp->if_unit);
  693                 ns8390intoff(ifp->if_unit);
  694                 error = ENETDOWN;
  695                 goto bad;
  696         }
  697         switch (dst->sa_family) {
  698 #ifdef INET
  699         case AF_INET:
  700                 idst = ((struct sockaddr_in *)dst)->sin_addr;
  701                 if (!arpresolve(&is->ns8390_ac, m, &idst, edst, &usetrailers)){
  702                         return (0);     /* if not yet resolved */
  703                 }
  704                 off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len;
  705                 if (usetrailers && off > 0 && (off & 0x1ff) == 0 &&
  706                     m->m_off >= MMINOFF + 2 * sizeof (u_short)) {
  707                         type = ETHERTYPE_TRAIL + (off>>9);
  708                         m->m_off -= 2 * sizeof (u_short);
  709                         m->m_len += 2 * sizeof (u_short);
  710                         *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP);
  711                         *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len);
  712                         goto gottrailertype;
  713                 }
  714                 type = ETHERTYPE_IP;
  715                 off = 0;
  716                 goto gottype;
  717 #endif
  718 #ifdef NS
  719         case AF_NS:
  720                 type = ETHERTYPE_NS;
  721                 bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
  722                       (caddr_t)edst,
  723                       sizeof (edst));
  724                 off = 0;
  725                 goto gottype;
  726 #endif
  727         case AF_UNSPEC:
  728                 eh = (struct ether_header *)dst->sa_data;
  729                 bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst));
  730                 type = eh->ether_type;
  731                 goto gottype;
  732         default:
  733                 printf("%s%d output(): can't handle af%d\n",
  734                         is->card, ifp->if_unit,
  735                         dst->sa_family);
  736                 error = EAFNOSUPPORT;
  737                 goto bad;
  738         }
  739 gottrailertype:
  740         /*
  741          * Packet to be sent as trailer: move first packet
  742          * (control information) to end of chain.
  743          */
  744         while (m->m_next)
  745                 m = m->m_next;
  746         m->m_next = m0;
  747         m = m0->m_next;
  748         m0->m_next = 0;
  749         m0 = m;
  750 gottype:
  751         /*
  752          * Add local net header.  If no space in first mbuf,
  753          * allocate another.
  754          */
  755         if (m->m_off > MMAXOFF ||
  756             MMINOFF + sizeof (struct ether_header) > m->m_off) {
  757                 m = m_get(M_DONTWAIT, MT_HEADER);
  758                 if (m == 0) {
  759                         error = ENOBUFS;
  760                         goto bad;
  761                 }
  762                 m->m_next = m0;
  763                 m->m_off = MMINOFF;
  764                 m->m_len = sizeof (struct ether_header);
  765         } else {
  766                 m->m_off -= sizeof (struct ether_header);
  767                 m->m_len += sizeof (struct ether_header);
  768         }
  769         eh = mtod(m, struct ether_header *);
  770         eh->ether_type = htons((u_short)type);
  771         bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst));
  772         bcopy((caddr_t)is->address,
  773               (caddr_t)eh->ether_shost,
  774               sizeof(edst));
  775         /*
  776          * Queue message on interface, and start output if interface
  777          * not yet active.
  778          */
  779         opri = SPLNET();
  780         if (IF_QFULL(&ifp->if_snd)) {
  781                 IF_DROP(&ifp->if_snd);
  782                 splx(opri);
  783                 m_freem(m);
  784                 return (ENOBUFS);
  785         }
  786         IF_ENQUEUE(&ifp->if_snd, m);
  787         /*
  788          * Some action needs to be added here for checking whether the
  789          * board is already transmitting.  If it is, we don't want to
  790          * start it up (ie call ns8390start()).  We will attempt to send
  791          * packets that are queued up after an interrupt occurs.  Some
  792          * flag checking action has to happen here and/or in the start
  793          * routine.  This note is here to remind me that some thought
  794          * is needed and there is a potential problem here.
  795          *
  796          */
  797         ns8390start(ifp->if_unit);
  798         splx(opri);
  799         return (0);
  800 bad:
  801         m_freem(m0);
  802         return (error);
  803 }
  804 #endif MACH_KERNEL
  805 
  806 /*
  807  * ns8390reset:
  808  *
  809  *      This routine is in part an entry point for the "if" code.  Since most
  810  *      of the actual initialization has already (we hope already) been done
  811  *      by calling ns8390attach().
  812  *
  813  * input        : unit number or board number to reset
  814  * output       : board is reset
  815  *
  816  */
  817 
  818 int
  819 ns8390reset(unit)
  820 int     unit;
  821 {
  822 
  823         ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
  824         return(ns8390init(unit));
  825 }
  826 
  827 /*
  828  * ns8390init:
  829  *
  830  *      Another routine that interfaces the "if" layer to this driver.
  831  *      Simply resets the structures that are used by "upper layers".
  832  *      As well as calling ns8390hwrst that does reset the ns8390 board.
  833  *
  834  * input        : board number
  835  * output       : structures (if structs) and board are reset
  836  *
  837  */
  838 
  839 int
  840 ns8390init(unit)
  841 int     unit;
  842 {
  843         struct  ifnet   *ifp;
  844         int             stat;
  845         spl_t           oldpri;
  846 
  847         ifp = &(ns8390_softc[unit].ds_if);
  848 #ifdef  MACH_KERNEL
  849 #else   MACH_KERNEL
  850         if (ifp->if_addrlist == (struct ifaddr *)0) {
  851                 return;
  852         }
  853 #endif  MACH_KERNEL
  854         oldpri = SPLNET();
  855         if ((stat = ns8390hwrst(unit)) == TRUE) {
  856                 ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING;
  857                 ns8390_softc[unit].flags |= DSF_RUNNING;
  858                 ns8390_softc[unit].tbusy = 0;
  859                 ns8390start(unit);
  860         } else
  861                 printf("%s%d init(): trouble resetting board %d\n",
  862                         ns8390_softc[unit].card, unit);
  863         ns8390_softc[unit].timer = 5;
  864         splx(oldpri);
  865         return(stat);
  866 }
  867 
  868 /*
  869  * ns8390start:
  870  *
  871  *      This is yet another interface routine that simply tries to output a
  872  *      in an mbuf after a reset.
  873  *
  874  * input        : board number
  875  * output       : stuff sent to board if any there
  876  *
  877  */
  878 
  879 ns8390start(unit)
  880 int     unit;
  881 {
  882         register ns8390_softc_t *is = &ns8390_softc[unit];
  883         struct  ifnet           *ifp;
  884 #ifdef  MACH_KERNEL
  885         io_req_t        m;
  886 #else   MACH_KERNEL
  887         struct  mbuf    *m;
  888 #endif  MACH_KERNEL
  889 
  890         if (is->tbusy) {
  891                 caddr_t nic = ns8390_softc[unit].nic;
  892                 if (!(inb(nic+CR) & TXP)) {
  893                         is->tbusy = 0;
  894                         ns8390_cntrs[unit].busy++;
  895                 } else
  896                         return;
  897         }
  898 
  899         ifp = &(ns8390_softc[unit].ds_if);
  900 
  901         IF_DEQUEUE(&ifp->if_snd, m);
  902 #ifdef  MACH_KERNEL
  903         if (m != 0)
  904 #else   MACH_KERNEL
  905         if (m != (struct mbuf *)0)
  906 #endif  MACH_KERNEL
  907         {
  908                 is->tbusy++;
  909                 ns8390_cntrs[unit].xmt++;
  910                 ns8390xmt(unit, m);
  911         }
  912 }
  913 
  914 #ifdef  MACH_KERNEL
  915 /*ARGSUSED*/
  916 ns8390getstat(dev, flavor, status, count)
  917         dev_t           dev;
  918         int             flavor;
  919         dev_status_t    status;         /* pointer to OUT array */
  920         unsigned int    *count;         /* out */
  921 {
  922         register int    unit = minor(dev);
  923 
  924         if (unit < 0 || unit >= NNS8390 ||
  925                 ns8390_softc[unit].nic == 0)
  926             return (ENXIO);
  927 
  928         return (net_getstat(&ns8390_softc[unit].ds_if,
  929                             flavor,
  930                             status,
  931                             count));
  932 }
  933 ns8390setstat(dev, flavor, status, count)
  934         dev_t           dev;
  935         int             flavor;
  936         dev_status_t    status;
  937         unsigned int    count;
  938 {
  939         register int    unit = minor(dev);
  940         register ns8390_softc_t *sp;
  941 
  942         if (unit < 0 || unit >= NNS8390 ||
  943                 ns8390_softc[unit].nic == 0)
  944             return (ENXIO);
  945 
  946         sp = &ns8390_softc[unit];
  947 
  948         switch (flavor) {
  949             case NET_STATUS:
  950             {
  951                 /*
  952                  * All we can change are flags, and not many of those.
  953                  */
  954                 register struct net_status *ns = (struct net_status *)status;
  955                 int     mode = 0;
  956 
  957                 if (count < NET_STATUS_COUNT)
  958                     return (D_INVALID_SIZE);
  959 
  960                 if (ns->flags & IFF_ALLMULTI)
  961                     mode |= MOD_ENAL;
  962                 if (ns->flags & IFF_PROMISC)
  963                     mode |= MOD_PROM;
  964 
  965                 /*
  966                  * Force a complete reset if the receive mode changes
  967                  * so that these take effect immediately.
  968                  */
  969                 if (sp->mode != mode) {
  970                     sp->mode = mode;
  971                     if (sp->flags & DSF_RUNNING) {
  972                         sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
  973                         ns8390init(unit);
  974                     }
  975                 }
  976                 break;
  977             }
  978 
  979             default:
  980                 return (D_INVALID_OPERATION);
  981         }
  982         return (D_SUCCESS);
  983 }
  984 #else   MACH_KERNEL
  985 /*
  986  * ns8390ioctl:
  987  *
  988  *      This routine processes an ioctl request from the "if" layer
  989  *      above.
  990  *
  991  * input        : pointer the appropriate "if" struct, command, and data
  992  * output       : based on command appropriate action is taken on the
  993  *                ns8390 board(s) or related structures
  994  * return       : error is returned containing exit conditions
  995  *
  996  */
  997 
  998 int
  999 ns8390ioctl(ifp, cmd, data)
 1000 struct ifnet    *ifp;
 1001 int     cmd;
 1002 caddr_t data;
 1003 {
 1004         register struct ifaddr  *ifa = (struct ifaddr *)data;
 1005         register ns8390_softc_t *is;
 1006         int                     error;
 1007         spl_t                   opri;
 1008         short                    mode = 0;
 1009 
 1010         is = &ns8390_softc[ifp->if_unit];
 1011         opri = SPLNET();
 1012         error = 0;
 1013         switch (cmd) {
 1014         case SIOCSIFADDR:
 1015                 ifp->if_flags |= IFF_UP;
 1016                 ns8390init(ifp->if_unit);
 1017                 switch (ifa->ifa_addr.sa_family) {
 1018 #ifdef INET
 1019                 case AF_INET:
 1020                         ((struct arpcom *)ifp)->ac_ipaddr =
 1021                             IA_SIN(ifa)->sin_addr;
 1022                         arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
 1023                         break;
 1024 #endif
 1025 #ifdef NS
 1026                 case AF_NS:
 1027                         {
 1028                                 register struct ns_addr *ina =
 1029                                     &(IA_SNS(ifa)->sns_addr);
 1030                                 if (ns_nullhost(*ina))
 1031                                         ina->x_host =
 1032                                             *(union ns_host *)(ds->ds_addr);
 1033                                 else
 1034 ????
 1035                                         ns8390seteh(ina->x_host.c_host,
 1036                                                     ns8390_softc[ifp->if_unit].base);
 1037                                 break;
 1038                         }
 1039 #endif
 1040                 }
 1041                 break;
 1042         case SIOCSIFFLAGS:
 1043                 if (ifp->if_flags & IFF_ALLMULTI)
 1044                         mode |= MOD_ENAL;
 1045                 if (ifp->if_flags & IFF_PROMISC)
 1046                         mode |= MOD_PROM;
 1047                 /*
 1048                  * force a complete reset if the receive multicast/
 1049                  * promiscuous mode changes so that these take
 1050                  * effect immediately.
 1051                  *
 1052                  */
 1053                 if (is->mode != mode) {
 1054                         is->mode = mode;
 1055                         if (is->flags & DSF_RUNNING) {
 1056                                 is->flags &=
 1057                                     ~(DSF_LOCK|DSF_RUNNING);
 1058                                 ns8390init(ifp->if_unit);
 1059                         }
 1060                 }
 1061                 if ((ifp->if_flags & IFF_UP) == 0 &&
 1062                     is->flags & DSF_RUNNING) {
 1063                         printf("%s%d ioctl(): turning off board %d\n",
 1064                                 is->card, ifp->if_unit);
 1065                         is->flags &= ~(DSF_LOCK | DSF_RUNNING);
 1066                         is->timer = -1;
 1067                         ns8390intoff(ifp->if_unit);
 1068                         ns8390over_write(ifp->if_unit);
 1069                 } else
 1070                     if (ifp->if_flags & IFF_UP &&
 1071                     (is->flags & DSF_RUNNING) == 0)
 1072                         ns8390init(ifp->if_unit);
 1073                 break;
 1074 #ifdef  IF_CNTRS
 1075         case SIOCCIFCNTRS:
 1076                 if (!suser()) {
 1077                         error = EPERM;
 1078                         break;
 1079                 }
 1080                 bzero((caddr_t)ns_ein, sizeof (ns_ein));
 1081                 bzero((caddr_t)ns_eout, sizeof (ns_eout));
 1082                 bzero((caddr_t)ns_lin, sizeof (ns_lin));
 1083                 bzero((caddr_t)ns_lout, sizeof (ns_lout));
 1084                 bzero((caddr_t)&ns_arp, sizeof (int));
 1085                 bzero((caddr_t)&ns8390_cntrs, sizeof (ns8390_cntrs));
 1086                 break;
 1087 #endif  IF_CNTRS
 1088         default:
 1089                 error = EINVAL;
 1090         }
 1091         splx(opri);
 1092         return (error);
 1093 }
 1094 #endif  MACH_KERNEL
 1095 
 1096 /*
 1097  * ns8390hwrst:
 1098  *
 1099  *      This routine resets the ns8390 board that corresponds to the
 1100  *      board number passed in.
 1101  *
 1102  * input        : board number to do a hardware reset
 1103  * output       : board is reset
 1104  *
 1105  */
 1106 
 1107 int
 1108 ns8390hwrst(unit)
 1109 int unit;
 1110 {
 1111         caddr_t nic = ns8390_softc[unit].nic;
 1112         int     count;
 1113         u_char  stat;
 1114         spl_t   spl = SPLNET();
 1115 
 1116         if (ns8390_softc[unit].card == wd8003_card && 
 1117             config_wd8003(unit) == FALSE) {
 1118                 printf("%s%d hwrst(): config_wd8003 failed.\n",
 1119                         ns8390_softc[unit].card, unit);
 1120                 splx(spl);
 1121                 return(FALSE);
 1122         }
 1123         if (ns8390_softc[unit].card == elii_card && 
 1124             config_3c503(unit) == FALSE) {
 1125                 printf("%s%d hwrst(): config_3c503 failed.\n",
 1126                         ns8390_softc[unit].card, unit);
 1127                 splx(spl);
 1128                 return(FALSE);
 1129         }
 1130         if (config_nic(unit) == FALSE) {
 1131                 printf("%s%d hwrst(): config_nic failed.\n",
 1132                         ns8390_softc[unit].card, unit);
 1133                 splx(spl);
 1134                 return(FALSE);
 1135         }
 1136         splx(spl);
 1137         return(TRUE);
 1138 }
 1139 
 1140 /*
 1141  * ns8390intr:
 1142  *
 1143  *      This function is the interrupt handler for the ns8390 ethernet
 1144  *      board.  This routine will be called whenever either a packet
 1145  *      is received, or a packet has successfully been transfered and
 1146  *      the unit is ready to transmit another packet.
 1147  *
 1148  * input        : board number that interrupted
 1149  * output       : either a packet is received, or a packet is transfered
 1150  *
 1151  */
 1152 int
 1153 ns8390intr(unit)
 1154 {
 1155         int     opri, i;
 1156         int     isr_status;
 1157         int     temp_cr;
 1158         caddr_t nic = ns8390_softc[unit].nic;
 1159 
 1160         temp_cr = inb(nic+CR);
 1161         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1162         outb(nic+IMR, 0);                   /* stop board interrupts */
 1163         outb(nic+CR, temp_cr);
 1164         while (isr_status = inb(nic+ISR)) {
 1165                 outb(nic+ISR, isr_status);          /* clear interrupt status */
 1166 
 1167                 if ((isr_status & (OVW|RXE)) == RXE) {
 1168                         int rsr = inb(nic+RSR);
 1169                         if (rsr & DFR) ns8390_cntrs[unit].jabber++;
 1170                         if (rsr & ~(DFR|PHY|FAE|CRC|PRX))
 1171                                 printf("%s%d intr(): isr = %x, RSR = %x\n",
 1172                                         ns8390_softc[unit].card, unit,
 1173                                         isr_status, rsr);
 1174                 } else if (isr_status & OVW) {
 1175                         ns8390_cntrs[unit].ovw++;
 1176                         ns8390over_write(unit);
 1177                 }
 1178                 if (isr_status & PRX) {                 /* DFR & PRX is possible */
 1179                         ns8390rcv(unit);
 1180 
 1181 #if     MACH_TTD
 1182                         if (kttd_active)
 1183                                 ttd_poll_loop = FALSE;
 1184 #endif  /* MACH_TTD */
 1185                 }
 1186 
 1187                 if (isr_status & TXE) {
 1188                         int tsr = inb(nic+TSR);
 1189                         tsr &= ~0x2;            /* unadvertised special */
 1190 #if     MACH_TTD
 1191                         if (!kttd_active)
 1192 #endif  /* MACH_TTD */
 1193                         {
 1194                                 if (tsr == (CDH|ABT))
 1195                                         ns8390_cntrs[unit].heart++;
 1196                                 else
 1197                                         printf("%s%d intr(): isr = %x, TSR = %x\n",
 1198                                                ns8390_softc[unit].card, unit,
 1199                                                isr_status, tsr);
 1200                                 ns8390_softc[unit].tbusy = 0;
 1201                                 ns8390start(unit);
 1202                         }
 1203                 } else if (isr_status & PTX) {
 1204 #if     MACH_TTD
 1205                         if (!kttd_active)
 1206 #endif  /* MACH_TTD */
 1207                         {
 1208                                 ns8390_cntrs[unit].xmti++;
 1209                                 ns8390_softc[unit].tbusy = 0;
 1210                                 ns8390start(unit);
 1211                         }
 1212                 }
 1213 
 1214                 if (isr_status & CNT) {
 1215                         int c0 = inb(nic+CNTR0);
 1216                         int c1 = inb(nic+CNTR1);
 1217                         int c2 = inb(nic+CNTR2);
 1218                         ns8390_cntrs[unit].frame += c0;
 1219                         ns8390_cntrs[unit].crc += c1;
 1220                         ns8390_cntrs[unit].miss += c2;
 1221 #ifdef  COUNTERS
 1222                         printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n",
 1223                                 ns8390_softc[unit].card, unit,
 1224                                 isr_status, c0, c1, c2);
 1225                         printf("%s%d intr(): TOTAL   , FRAME %x, CRC %x, MISS %x\n",
 1226                                 ns8390_softc[unit].card, unit,
 1227                                 ns8390_cntrs[unit].frame,
 1228                                 ns8390_cntrs[unit].crc,
 1229                                 ns8390_cntrs[unit].miss);
 1230 #endif  COUNTERS
 1231                         outb(nic+ISR, isr_status);      /* clear interrupt status again */
 1232                 }
 1233         }
 1234         temp_cr=inb(nic+CR);
 1235         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1236         outb(nic+IMR, imr_hold);
 1237         outb(nic+CR, temp_cr);
 1238         return(0);
 1239 }
 1240 
 1241 /*
 1242  *  Called if on board buffer has been completely filled by ns8390intr.  It stops
 1243  *  the board, reads in all the buffers that are currently in the buffer, and
 1244  *  then restart board.
 1245  */
 1246 ns8390over_write(unit)
 1247 int unit;
 1248 {
 1249         caddr_t nic = ns8390_softc[unit].nic;
 1250         int     no;
 1251         int     count = 0;
 1252 
 1253         outb(nic+CR, ABR|STP|PS0);        /* clear the receive buffer */
 1254         outb(nic+RBCR0, 0);
 1255         outb(nic+RBCR1, 0);  
 1256         while ((!(inb (nic + ISR) & RST)) && (count < 10000))
 1257                 count++;
 1258         if (count == 10000) {
 1259                 printf("%s%d: over_write(): would not reset.\n",
 1260                         ns8390_softc[unit].card, unit);
 1261         }
 1262         no = ns8390rcv(unit);
 1263 #ifdef  OVWBUG
 1264         printf("%s%d over_write(): ns8390 OVW ... %d.\n",
 1265                 ns8390_softc[unit].card, unit, no);
 1266 #endif  OVWBUG
 1267         outb(nic+TCR, LB1);               /* External loopback mode */
 1268         outb(nic+CR, ABR|STA|PS0);
 1269         outb(nic+TCR, 0);
 1270         return;
 1271 }
 1272 
 1273 /*
 1274  * ns8390rcv:
 1275  *
 1276  *      This routine is called by the interrupt handler to initiate a
 1277  *      packet transfer from the board to the "if" layer above this
 1278  *      driver.  This routine checks if a buffer has been successfully
 1279  *      received by the ns8390.  If so, it does the actual transfer of the
 1280  *      board data (including the ethernet header) into a packet (consisting
 1281  *      of an mbuf chain) and enqueues it to a higher level.
 1282  *      Then check again whether there are any packets in the receive ring,
 1283  *      if so, read the next packet, until there are no more.
 1284  *
 1285  * input        : number of the board to check
 1286  * output       : if a packet is available, it is "sent up"
 1287  */
 1288 ns8390rcv(unit)
 1289 int unit;
 1290 {
 1291         register ns8390_softc_t *is = &ns8390_softc[unit];
 1292         register struct ifnet   *ifp = &is->ds_if;
 1293         caddr_t                 nic = is->nic;
 1294         int                     packets = 0;
 1295         struct ether_header     eh;
 1296         u_short                 mlen, len, bytes_in_mbuf, bytes;
 1297         u_short                 remaining;
 1298         int                     temp_cr;
 1299         u_char                  *mb_p;
 1300         int                     board_id = is->board_id;
 1301         vm_offset_t             hdwbase = ns8390info[unit]->address;
 1302         spl_t                   s;
 1303 
 1304         /* calculation of pkt size */
 1305         int nic_overcount;         /* NIC says 1 or 2 more than we need */
 1306         int pkt_size;              /* calculated size of received data */
 1307         int wrap_size;             /* size of data before wrapping it */
 1308         int header_nxtpkt_ptr;     /* NIC's next pkt ptr in rcv header */
 1309         int low_byte_count;        /* low byte count of read from rcv header */
 1310         int high_byte_count;       /* calculated high byte count */
 1311 
 1312 
 1313         volatile char *sram_nxtpkt_ptr;   /* mem location of next packet */
 1314         volatile char *sram_getdata_ptr;  /* next location to be read */
 1315 #ifdef  MACH_KERNEL
 1316         ipc_kmsg_t      new_kmsg;
 1317         struct ether_header *ehp;
 1318         struct packet_header *pkt;
 1319 #else   MACH_KERNEL
 1320         struct mbuf *m, *tm;              /* initial allocation of mem; temp */
 1321 #endif  MACH_KERNEL
 1322 
 1323 
 1324 #if     MACH_TTD
 1325         if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) &&
 1326             !kttd_active) {
 1327 #else
 1328         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
 1329 #endif  /* MACH_TTD */
 1330                 temp_cr = inb(nic+CR); /* get current CR value */
 1331                 outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
 1332                 outb(nic+IMR, 0);      /* Interrupt Mask Register  */
 1333                 outb(nic+CR, temp_cr);
 1334                 return -1;
 1335         }
 1336 
 1337         while(is->read_nxtpkt_ptr != ns8390get_CURR(unit))   {
 1338 
 1339                 /* while there is a packet to read from the buffer */
 1340 
 1341                 if ((is->read_nxtpkt_ptr < is->pstart) ||
 1342                     (is->read_nxtpkt_ptr >= is->pstop)) {
 1343                         ns8390hwrst(unit);
 1344                         return -1;
 1345                 }    /* if next packet pointer is out of receive ring bounds */
 1346 
 1347 #if     MACH_TTD
 1348                 if (!kttd_active)
 1349 #endif  /* MACH_TTD */
 1350                 {
 1351                         packets++;
 1352                         ns8390_cntrs[unit].rcv++;
 1353                 }
 1354 
 1355                 sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8));
 1356 
 1357                 /* get packet size and location of next packet */
 1358                 header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1359                 header_nxtpkt_ptr &= 0xFF;
 1360                 low_byte_count = *(sram_nxtpkt_ptr + 2);
 1361                 low_byte_count &= 0xFF;
 1362 
 1363                 if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE)
 1364                         nic_overcount = 2;
 1365                 else
 1366                         nic_overcount = 1;
 1367                 if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) {
 1368                         wrap_size = 0;
 1369                         high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr -
 1370                             nic_overcount;
 1371                 } else {
 1372                         wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount);
 1373                         high_byte_count = is->pstop - is->read_nxtpkt_ptr +
 1374                             header_nxtpkt_ptr - is->pstart - nic_overcount;
 1375                 }
 1376                 pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF);
 1377                 /* does not seem to include NIC_HEADER_SIZE */
 1378                 if (!pkt_size) {
 1379                         printf("%s%d rcv(): zero length.\n",
 1380                                 ns8390_softc[unit].card, unit);
 1381                         goto next_pkt;
 1382                 }
 1383                 len = pkt_size;
 1384 
 1385                 sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE;
 1386                 if (board_id & IFWD_SLOT_16BIT) {
 1387 #if     MACH_TTD
 1388                         if (!kttd_active)
 1389 #endif  /* MACH_TTD */
 1390                         { s = splhi(); }
 1391 
 1392                         en_16bit_access(hdwbase, board_id);
 1393                         bcopy16 (sram_getdata_ptr,
 1394                                  &eh,
 1395                                  sizeof(struct ether_header));
 1396                         dis_16bit_access (hdwbase, board_id);
 1397 #if     MACH_TTD
 1398                         if (!kttd_active)
 1399 #endif  /* MACH_TTD */
 1400                         { splx(s); }
 1401 
 1402                 } else {
 1403                         bcopy16 (sram_getdata_ptr,
 1404                                  &eh,
 1405                                  sizeof(struct ether_header));
 1406                 }                   
 1407                 sram_getdata_ptr += sizeof(struct ether_header);
 1408                 len -= (sizeof(struct ether_header) + 4);       /* crc size */
 1409 #ifdef  MACH_KERNEL
 1410 #if     MACH_TTD
 1411                 if (kttd_active) {
 1412                         new_kmsg = (ipc_kmsg_t)ttd_request_msg;
 1413                 }else
 1414 #endif  /* MACH_TTD */
 1415                 {
 1416                         new_kmsg = net_kmsg_get();
 1417                         if (new_kmsg == IKM_NULL) {
 1418                                 /*
 1419                                  * Drop the packet.
 1420                                  */
 1421                                 is->ds_if.if_rcvdrops++;    
 1422                                 /*
 1423                                  * not only do we want to return, we need to drop
 1424                                  * the packet on the floor to clear the interrupt.
 1425                                  */
 1426                                 ns8390lost_frame(unit);
 1427                                 return;/* packets;*/
 1428                         }
 1429                 }
 1430 
 1431 #if     DEBUG_TTD
 1432                 dump_ether_header("ns8390wire",&eh);
 1433 #endif  /* DEBUG_TTD */
 1434 
 1435                 ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
 1436                 pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
 1437 
 1438 #if     DEBUG_TTD
 1439                 printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt);
 1440 #endif  /* DEBUG_TTD */
 1441 
 1442                 *ehp = eh;
 1443                 if (len >
 1444                     (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) {
 1445                         /* if needs to wrap */
 1446                         if (board_id & IFWD_SLOT_16BIT) {
 1447 #if     MACH_TTD
 1448                                 if (!kttd_active)
 1449 #endif  /* MACH_TTD */
 1450                                 { s = splhi(); }
 1451 
 1452                                 en_16bit_access(hdwbase, board_id);
 1453                                 bcopy16 (sram_getdata_ptr, (char *) (pkt + 1),
 1454                                          wrap_size);
 1455                                 dis_16bit_access (hdwbase, board_id);
 1456 #if     MACH_TTD
 1457                                 if (!kttd_active)
 1458 #endif  /* MACH_TTD */
 1459                                 { splx(s); }
 1460                         } else {
 1461                                 bcopy (sram_getdata_ptr, (char *) (pkt + 1),
 1462                                        wrap_size);
 1463                         }
 1464                         sram_getdata_ptr = (volatile char *)
 1465                             (is->sram + (is->pstart << 8));
 1466                 } else {   /* normal getting data from buffer */
 1467                         wrap_size = 0;
 1468                 }
 1469                 if (board_id & IFWD_SLOT_16BIT) {
 1470 #if     MACH_TTD
 1471                         if (!kttd_active)
 1472 #endif  /* MACH_TTD */
 1473                         { s = splhi(); }
 1474                         en_16bit_access(hdwbase, board_id);
 1475                         bcopy16 (sram_getdata_ptr,
 1476                                  (char *) (pkt + 1) + wrap_size,
 1477                                  len - wrap_size);
 1478                         dis_16bit_access (hdwbase, board_id);
 1479 #if     MACH_TTD
 1480                         if (!kttd_active)
 1481 #endif  /* MACH_TTD */
 1482                         { splx(s); }
 1483                 } else {
 1484                         bcopy (sram_getdata_ptr,
 1485                                (char *) (pkt + 1) + wrap_size,
 1486                                len - wrap_size);
 1487                 }
 1488 
 1489                 pkt->type = ehp->ether_type;
 1490                 pkt->length = len + sizeof(struct packet_header);
 1491 
 1492 #if     MACH_TTD
 1493                 /*
 1494                  * Don't want to call net_packet if we are polling
 1495                  * for a packet.
 1496                  */
 1497                 if (!kttd_active)
 1498 #endif  /* MACH_TTD */
 1499                 {
 1500                         /*
 1501                          * Hand the packet to the network module.
 1502                          */
 1503                         net_packet(ifp, new_kmsg, pkt->length,
 1504                                    ethernet_priority(new_kmsg));
 1505                 }
 1506 
 1507 #else   MACH_KERNEL
 1508 #define NEW
 1509 #ifdef  NEW
 1510                 m = (struct mbuf *) 0;
 1511                 eh.ether_type = ntohs(eh.ether_type);
 1512                 MGET(m, M_DONTWAIT, MT_DATA);
 1513                 if (m == (struct mbuf *) 0) {
 1514                         printf("%s%d rcv(): Lost frame\n",
 1515                                 ns8390_softc[unit].card, unit);
 1516                         ns8390lost_frame(unit); /* update NIC pointers and registers */
 1517                         return packets;
 1518                 }
 1519                 m->m_next = (struct mbuf *) 0;
 1520                 tm = m;
 1521                 m->m_len = MLEN;
 1522                 if (len > 2 * MLEN - sizeof (struct ifnet **)) {
 1523                         MCLGET(m);
 1524                 }
 1525                 *(mtod(tm, struct ifnet **)) = ifp;
 1526                 mlen = sizeof (struct ifnet **);
 1527                 bytes_in_mbuf = m->m_len - sizeof(struct ifnet **);
 1528                 mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **);
 1529                 bytes = min(bytes_in_mbuf, len);
 1530                 remaining =  (int) (is->sram + (is->pstop << 8) -
 1531                                     sram_getdata_ptr);
 1532                 bytes = min(bytes, remaining);
 1533                 do {
 1534                         if (board_id & IFWD_SLOT_16BIT) {
 1535                                 s = splhi();
 1536                                 en_16bit_access(hdwbase, board_id);
 1537                                 bcopy16 (sram_getdata_ptr, mb_p, bytes);
 1538                                 dis_16bit_access (hdwbase, board_id);
 1539                                 splx(s);
 1540                         } else {
 1541                                 bcopy16 (sram_getdata_ptr, mb_p, bytes);
 1542                         }
 1543                         
 1544                         mlen += bytes;
 1545 
 1546                         if (!(bytes_in_mbuf -= bytes)) {
 1547                                 MGET(tm->m_next, M_DONTWAIT, MT_DATA);
 1548                                 tm = tm->m_next;
 1549                                 if (tm == (struct mbuf *)0) {
 1550                                         printf("%s%d rcv(): No mbufs, lost frame\n",
 1551                                                 ns8390_softc[unit].card, unit);
 1552                                         m_freem(m);              /* free the mbuf chain */
 1553                                         ns8390lost_frame(unit);  /* update NIC pointers and registers */
 1554                                         return;
 1555                                 }
 1556                                 mlen = 0;
 1557                                 tm->m_len = MLEN;
 1558                                 bytes_in_mbuf = MLEN;
 1559                                 mb_p = mtod(tm, u_char *);
 1560                         } else
 1561                                 mb_p += bytes;
 1562 
 1563                         if (!(len  -= bytes)) {
 1564                                 tm->m_len = mlen;
 1565                                 break;
 1566                         } else if (bytes == remaining) {
 1567                                 sram_getdata_ptr = (volatile char *) (is->sram +
 1568                                     (is->pstart << 8));
 1569                                 bytes = len;
 1570                                 remaining = ETHERMTU;
 1571                         } else {
 1572                                 sram_getdata_ptr += bytes;
 1573                                 remaining -= bytes;
 1574                         }
 1575 
 1576                         bytes = min(bytes_in_mbuf, len);
 1577                         bytes = min(bytes, remaining);
 1578                 } while(1);
 1579 #else   NEW
 1580                 m = (struct mbuf *) 0;
 1581                 eh.ether_type = ntohs(eh.ether_type);
 1582 
 1583                 while ( len ) {
 1584                         if (m == (struct mbuf *) 0) {
 1585                                 m = m_get(M_DONTWAIT, MT_DATA);
 1586                                 if (m == (struct mbuf *) 0) {
 1587                                         printf("%s%d rcv(): Lost frame\n",
 1588                                         ns8390_softc[unit].card, unit);
 1589                                         ns8390lost_frame(unit); /* update NIC pointers and registers */
 1590                                         return packets;
 1591                                 }
 1592                                 tm = m;
 1593                                 tm->m_off = MMINOFF;
 1594 
 1595 
 1596                                 /*
 1597                                  * first mbuf in the packet must contain a pointer to the
 1598                                  * ifnet structure.  other mbufs that follow and make up
 1599                                  * the packet do not need this pointer in the mbuf.
 1600                                  *
 1601                                  */
 1602 
 1603                                 *(mtod(tm, struct ifnet **)) = ifp;
 1604                                 tm->m_len = sizeof(struct ifnet **);
 1605 
 1606                         /* end of first buffer of packet */
 1607                         } else {
 1608                                 tm->m_next = m_get(M_DONTWAIT, MT_DATA);
 1609                                 tm = tm->m_next;
 1610                                 if (tm == (struct mbuf *) 0) {
 1611                                         printf("%s%d rcv(): No mbufs, lost frame\n",
 1612                                                 ns8390_softc[unit].card, unit);
 1613                                         m_freem(m);              /* free the mbuf chain */
 1614                                         ns8390lost_frame(unit);  /* update NIC pointers and registers */
 1615                                         return packets;
 1616                                 }
 1617                                 tm->m_off = MMINOFF;
 1618                                 tm->m_len = 0;
 1619                         }
 1620 
 1621                         tlen = MIN( MLEN - tm->m_len, len);
 1622                         /* size of mbuf so you know how much you can copy from board */
 1623                         tm->m_next = (struct mbuf *) 0;
 1624                         if (sram_getdata_ptr + tlen >=
 1625                             (volatile char *) (is->sram + (is->pstop << 8))) {
 1626                                 /* if needs to wrap */
 1627                                 wrap_size = (int) (is->sram + (is->pstop << 8) -
 1628                                     sram_getdata_ptr);
 1629                                 if (board_id & IFWD_SLOT_16BIT) {
 1630                                         s = splhi();
 1631                                         en_16bit_access(hdwbase, board_id);
 1632                                         bcopy16 (sram_getdata_ptr,
 1633                                                  mtod(tm, char*) + tm->m_len,
 1634                                                  wrap_size);
 1635                                         dis_16bit_access (hdwbase, board_id);
 1636                                         splx(s);
 1637                                 } else {
 1638                                         bcopy16 (sram_getdata_ptr,
 1639                                                  mtod(tm, char*) + tm->m_len,
 1640                                                  wrap_size);
 1641                                 }
 1642                                 tm->m_len += wrap_size;
 1643                                 len -= wrap_size;
 1644 
 1645                                 sram_getdata_ptr = (volatile char *) (is->sram +
 1646                                     (is->pstart << 8));
 1647                         } else {   /* normal getting data from buffer */
 1648                                 if (board_id & IFWD_SLOT_16BIT) {
 1649                                         s = splhi();
 1650                                         en_16bit_access(hdwbase, board_id);
 1651                                         bcopy16 (sram_getdata_ptr,
 1652                                                  mtod(tm, char*) + tm->m_len,
 1653                                                  tlen);
 1654                                         dis_16bit_access (hdwbase, board_id);
 1655                                         splx(s);
 1656                                 } else {
 1657                                         bcopy16 (sram_getdata_ptr,
 1658                                                  mtod(tm, char*) + tm->m_len,
 1659                                                  tlen);
 1660                                 }
 1661                                 sram_getdata_ptr += tlen;
 1662                                 tm->m_len += tlen;
 1663                                 len -= tlen;
 1664 
 1665                               }
 1666                 }
 1667 
 1668 #endif  NEW
 1669                 if (!ns8390send_packet_up(m, &eh, is))
 1670                         m_freem(m);
 1671 #ifdef  IF_CNTRS
 1672                 ns_ein[log_2(pkt_size)]++;
 1673                 if (pkt_size < 128) ns_lin[(pkt_size)>>3]++;
 1674 
 1675                 if (eh.ether_type == ETHERTYPE_ARP) {
 1676                         ns_arp++;
 1677                         if (ns_narp) {
 1678                                 ns_ein[log_2(pkt_size)]--;
 1679                                 if (pkt_size < 128) ns_lin[(pkt_size)>>3]--;
 1680                         }
 1681                 }
 1682 #endif  IF_CNTRS
 1683 #endif  MACH_KERNEL
 1684 
 1685 next_pkt:
 1686                 is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1687                 is->read_nxtpkt_ptr &= 0xFF;
 1688 
 1689 #if     MACH_TTD
 1690                 if (!kttd_active)
 1691 #endif  /* MACH_TTD */
 1692                 {
 1693                         temp_cr = inb(nic+CR);
 1694                         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1695                 }
 1696 
 1697                 if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
 1698                         if (is->read_nxtpkt_ptr == is->pstart)
 1699                                 outb(nic+BNDY, is->pstop - 1);
 1700                         else
 1701                                 outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
 1702                 else
 1703                         outb(nic+BNDY, is->read_nxtpkt_ptr);
 1704 
 1705 #if     MACH_TTD
 1706                 if (!kttd_active)
 1707 #endif  /* MACH_TTD */
 1708                 { outb(nic+CR, temp_cr); }
 1709 
 1710 #if     MACH_TTD
 1711                 /*
 1712                  * Hand the packet back to the TTD server, if active.
 1713                  */
 1714                 if (kttd_active && pkt_size)
 1715                         return 1;
 1716 #endif  /* MACH_TTD */
 1717 
 1718 
 1719         }
 1720         return packets;
 1721 
 1722 }
 1723 
 1724 #ifdef  MACH_KERNEL
 1725 #if     MACH_TTD
 1726 /*
 1727  * Polling routines for the TTD debugger.
 1728  */
 1729 int ns8390poll_receive(unit)
 1730         int     unit;
 1731 {
 1732         int s;
 1733         int orig_cr;
 1734         int orig_imr;
 1735         int isr_status;
 1736         int pkts;
 1737         
 1738         ttd_poll_loop = TRUE;
 1739 
 1740         
 1741         /*
 1742          * Should already in at splhigh.  Is this necessary? XXX
 1743          */
 1744         s = splhigh();
 1745 
 1746 #if     0
 1747         if (kttd_debug)
 1748                 printf("ns8390poll_receive: beginning polling loop\n");
 1749 #endif  /* DEBUG_TTD */
 1750 
 1751         /*
 1752          * Loop until packet arrives.
 1753          */
 1754         while(ttd_poll_loop) {
 1755 
 1756                 /*
 1757                  * Call intr routine
 1758                  */
 1759 
 1760                 ns8390intr(unit);
 1761         }
 1762 
 1763 #if     0
 1764         if (kttd_debug)
 1765                 printf("ns8390poll_receive: got packet exiting loop\n");
 1766 #endif  /* DEBUG_TTD */
 1767 
 1768         splx(s);
 1769 }
 1770 
 1771 int ns8390transmit_ttd(unit, packet, len)
 1772         int unit;
 1773         char * packet;
 1774         int len;
 1775 {
 1776         ns8390_softc_t  *is = &ns8390_softc[unit];
 1777         caddr_t         nic = is->nic;
 1778         u_short         count = 0;      /* amount of data already copied */
 1779         volatile char   *sram_write_pkt;
 1780         int             board_id = is->board_id;
 1781         caddr_t         hdwbase = ns8390info[unit]->address;
 1782         int             s;
 1783         int             orig_cr;
 1784         int             orig_imr;
 1785         int             isr_status;
 1786         boolean_t       loop = TRUE;
 1787 
 1788 #if     0
 1789         dump_ipudpbootp("Beg of xmit",packet);
 1790 #endif
 1791 
 1792         s = splhigh();
 1793 
 1794         /* begining of physical address of transmition buffer */
 1795 
 1796         sram_write_pkt = is->sram + is->tpsr * 0x100; 
 1797 
 1798         count = len;
 1799         if (board_id & IFWD_SLOT_16BIT) {
 1800                 en_16bit_access(hdwbase, board_id);
 1801                 bcopy16 (packet, sram_write_pkt,  count);
 1802                 dis_16bit_access (hdwbase, board_id);
 1803         } else {
 1804                 bcopy (packet, sram_write_pkt,  count);
 1805         }
 1806 
 1807         while (count < ETHERMIN+sizeof(struct ether_header)) {
 1808                 *(sram_write_pkt + count) = 0;
 1809                 count++;
 1810         }
 1811         outb(nic+CR, ABR|STA|PS0);              /* select page 0 */
 1812         outb(nic+TPSR, is->tpsr);               /* xmt page start at 0 of RAM */
 1813         outb(nic+TBCR1, count >> 8);            /* upper byte of count */
 1814         outb(nic+TBCR0, count & 0xFF);          /* lower byte of count */
 1815         outb(nic+CR, TXP|ABR|STA);              /* start transmission */
 1816 
 1817         ns8390intr(unit);
 1818 
 1819         splx(s);
 1820 }
 1821 #endif  /* MACH_TTD */
 1822 #endif  /* MACH_KERNEL */
 1823 
 1824 #ifdef  MACH_KERNEL
 1825 #else   MACH_KERNEL
 1826 /*
 1827  * Send a packet composed of an mbuf chain to the higher levels
 1828  *
 1829  */
 1830 ns8390send_packet_up(m, eh, is)
 1831 struct mbuf *m;
 1832 struct ether_header *eh;
 1833 ns8390_softc_t *is;
 1834 {
 1835         register struct ifqueue *inq;
 1836         spl_t                   opri;
 1837 
 1838         switch (eh->ether_type) {
 1839 #ifdef INET
 1840         case ETHERTYPE_IP:
 1841                 schednetisr(NETISR_IP);
 1842                 inq = &ipintrq;
 1843                 break;
 1844         case ETHERTYPE_ARP:
 1845                 arpinput(&is->ns8390_ac, m);
 1846                 return(TRUE);
 1847 #endif
 1848 #ifdef NS
 1849         case ETHERTYPE_NS:
 1850                 schednetisr(NETISR_NS);
 1851                 inq = &nsintrq;
 1852                 break;
 1853 #endif
 1854         default:
 1855                 return(FALSE);
 1856         }
 1857         opri = SPLNET();
 1858         if (IF_QFULL(inq)) {
 1859                 IF_DROP(inq);
 1860                 splx(opri);
 1861                 return(FALSE);
 1862         }
 1863         IF_ENQUEUE(inq, m);
 1864         splx(opri);
 1865         return(TRUE);
 1866 }
 1867 #endif  MACH_KERNEL
 1868 
 1869 /*
 1870  *  ns8390lost_frame:
 1871  *  this routine called by ns8390read after memory for mbufs could not be
 1872  *  allocated.  It sets the boundary pointers and registers to the next
 1873  *  packet location.
 1874  */
 1875 
 1876 ns8390lost_frame(unit)
 1877 int unit;
 1878 {
 1879         ns8390_softc_t *is = &ns8390_softc[unit];
 1880         caddr_t        nic = is->nic;
 1881         volatile char  *sram_nxtpkt_ptr;
 1882         int            temp_cr;
 1883 
 1884 
 1885 
 1886         sram_nxtpkt_ptr = (volatile char *) (is->sram +
 1887             (is->read_nxtpkt_ptr << 8));
 1888 
 1889         is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1890         is->read_nxtpkt_ptr &= 0xFF;
 1891 
 1892         temp_cr = inb(nic+CR);
 1893         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1894 
 1895         /* update boundary register */
 1896         if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
 1897                 if (is->read_nxtpkt_ptr == is->pstart)
 1898                         outb(nic+BNDY, is->pstop - 1);
 1899                 else
 1900                         outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
 1901         else
 1902                 outb(nic+BNDY, is->read_nxtpkt_ptr);
 1903 
 1904         outb(nic+CR, temp_cr);
 1905 
 1906         return;
 1907 }
 1908 
 1909 /*
 1910  * ns8390get_CURR():
 1911  *
 1912  * Returns the value of the register CURR, which points to the next
 1913  * available space for NIC to receive from network unto receive ring.
 1914  *
 1915  */
 1916 
 1917 int
 1918 ns8390get_CURR(unit)
 1919 int unit;
 1920 {
 1921         caddr_t nic = ns8390_softc[unit].nic;
 1922         int     temp_cr;
 1923         int     ret_val;
 1924         spl_t   s;
 1925   
 1926         s = SPLNET();
 1927 
 1928         temp_cr = inb(nic+CR);                  /* get current CR value */
 1929         outb(nic+CR, ((temp_cr & 0x3F) | PS1)); /* select page 1 registers */
 1930         ret_val = inb(nic+CURR);                /* read CURR value */
 1931         outb(nic+CR, temp_cr);
 1932         splx(s);
 1933         return (ret_val & 0xFF);
 1934 }
 1935 
 1936 /*
 1937  * ns8390xmt:
 1938  *
 1939  *      This routine fills in the appropriate registers and memory
 1940  *      locations on the ns8390 board and starts the board off on
 1941  *      the transmit.
 1942  *
 1943  * input        : board number of interest, and a pointer to the mbuf
 1944  * output       : board memory and registers are set for xfer and attention
 1945  *
 1946  */
 1947 
 1948 ns8390xmt(unit, m)
 1949 int     unit;
 1950 #ifdef  MACH_KERNEL
 1951 io_req_t        m;
 1952 #else   MACH_KERNEL
 1953 struct  mbuf    *m;
 1954 #endif  MACH_KERNEL
 1955 {
 1956         ns8390_softc_t          *is = &ns8390_softc[unit];
 1957         caddr_t                 nic = is->nic;
 1958         struct ether_header     *eh;
 1959         int                     i;
 1960         int                     opri;
 1961         u_short                 count = 0;      /* amount of data already copied */
 1962         volatile char           *sram_write_pkt;
 1963         int                     board_id = is->board_id;
 1964         vm_offset_t             hdwbase = ns8390info[unit]->address;
 1965         spl_t     s;
 1966 
 1967 #ifdef  MACH_KERNEL
 1968 #else   MACH_KERNEL
 1969         register struct mbuf    *tm_p;
 1970 #endif  MACH_KERNEL
 1971         /* begining of physical address of transmition buffer */
 1972 
 1973         sram_write_pkt = is->sram + is->tpsr * 0x100; 
 1974 
 1975 #ifdef  MACH_KERNEL
 1976         count = m->io_count;
 1977         if (board_id & IFWD_SLOT_16BIT) {
 1978                 s = splhi();
 1979                 en_16bit_access(hdwbase, board_id);
 1980                 bcopy16 (m->io_data, sram_write_pkt,  count);
 1981                 dis_16bit_access (hdwbase, board_id);
 1982                 splx(s);
 1983         } else {
 1984                 bcopy (m->io_data, sram_write_pkt,  count);
 1985         }
 1986 #else   MACH_KERNEL
 1987         for(tm_p = m; tm_p != (struct mbuf *)0; tm_p = tm_p->m_next)  {
 1988                 if (count + tm_p->m_len > ETHERMTU + sizeof (struct ether_header))
 1989                         break;
 1990                 if (tm_p->m_len == 0)
 1991                         continue;
 1992                 if (board_id & IFWD_SLOT_16BIT) {
 1993                         s = splhi();
 1994                         en_16bit_access(hdwbase, board_id);
 1995                         bcopy16 (mtod(tm_p, caddr_t),
 1996                                  sram_write_pkt + count,
 1997                                  tm_p->m_len);
 1998                         dis_16bit_access (hdwbase, board_id);
 1999                         splx(s);
 2000                 } else {
 2001                         bcopy16 (mtod(tm_p, caddr_t),
 2002                                  sram_write_pkt + count,
 2003                                  tm_p->m_len);
 2004                 }
 2005                 count += tm_p->m_len;
 2006         }
 2007 #ifdef  IF_CNTRS
 2008         ns_eout[log_2(count+4/*crc*/)]++;
 2009         if (count < 128)  ns_lout[(count+4/*crc*/)>>3]++;
 2010 #endif  IF_CNTRS
 2011 #endif  MACH_KERNEL
 2012         while (count < ETHERMIN+sizeof(struct ether_header)) {
 2013                 *(sram_write_pkt + count) = 0;
 2014                 count++;
 2015         }
 2016         outb(nic+CR, ABR|STA|PS0);              /* select page 0 */
 2017         outb(nic+TPSR, is->tpsr);               /* xmt page start at 0 of RAM */
 2018         outb(nic+TBCR1, count >> 8);            /* upper byte of count */
 2019         outb(nic+TBCR0, count & 0xFF);          /* lower byte of count */
 2020         outb(nic+CR, TXP|ABR|STA);              /* start transmission */
 2021 
 2022 #ifdef  MACH_KERNEL
 2023         iodone(m);
 2024         m=0;
 2025 #else   MACH_KERNEL
 2026         /* If this is a broadcast packet, loop it back to rcv.  */
 2027         eh = mtod( m, struct ether_header *);
 2028         for (i=0; ((i < 6) && (eh->ether_dhost[i] == 0xff)); i++)  ;
 2029         if (i == 6) {
 2030                 if (!ns8390send_packet_up(m, eh, is))
 2031                         m_freem(m);
 2032         } else
 2033                 m_freem(m);
 2034 #endif  MACH_KERNEL
 2035         return;
 2036 }
 2037 
 2038 config_nic(unit)
 2039 int unit;
 2040 {
 2041         ns8390_softc_t *is = &ns8390_softc[unit];
 2042         caddr_t   nic = is->nic;
 2043         int       i;
 2044         int       temp;
 2045         int       count = 0;
 2046         spl_t     s;
 2047 
 2048         outb (nic+CR, PS0|ABR|STP);             /* soft reset and page 0 */
 2049         while ((!(inb (nic + ISR) & RST)) && (count < 10000))
 2050                 count++;
 2051         if (count == 10000) {
 2052                 printf("%s%d: config_nic(): would not reset.\n",
 2053                         ns8390_softc[unit].card, unit);
 2054         }
 2055 
 2056         temp = ((is->fifo_depth & 0x0c) << 3) | BMS;    /* fifo depth | not loopback */
 2057         if (is->board_id & IFWD_SLOT_16BIT)
 2058                 temp |= WTS;                    /* word xfer select (16 bit cards ) */
 2059         outb (nic+DCR, temp);
 2060         outb (nic+TCR, 0);
 2061         outb (nic+RCR, MON);                    /* receive configuration register */
 2062         outb (nic+PSTART, is->pstart);          /* recieve ring starts 2k into RAM */
 2063         outb (nic+PSTOP, is->pstop);            /* stop at last RAM buffer rcv location */
 2064         outb (nic+BNDY, is->pstart);            /* boundary pointer for page 0 */
 2065         s = SPLNET();
 2066 
 2067         outb (nic+CR, PS1|ABR|STP);             /* maintain rst | sel page 1 */
 2068         is->read_nxtpkt_ptr = is->pstart + 1;   /* internal next packet pointer */
 2069         outb (nic+CURR, is->read_nxtpkt_ptr);   /* Current page register */
 2070         for(i=0; i<ETHER_ADDR_SIZE; i++)
 2071                 outb (nic+PAR0+i, is->address[i]);
 2072         for(i=0; i<8; i++)
 2073                 outb (nic+MAR0+i, 0);
 2074 
 2075         outb (nic+CR, PS0|STP|ABR);
 2076         splx(s);
 2077         outb (nic+ISR, 0xff);                   /* clear all interrupt status bits */
 2078         outb (nic+IMR, imr_hold);               /* Enable interrupts */
 2079         outb (nic+RBCR0, 0);                    /* clear remote byte count */
 2080         outb (nic+RBCR1, 0);
 2081 
 2082         outb (nic+CR, PS0|STA|ABR);             /* start NIC | select page 0 */
 2083         outb (nic+RCR, AB);                     /* receive configuration register */
 2084 
 2085         return TRUE;
 2086 }
 2087 
 2088 /*
 2089  * config_ns8390:
 2090  *
 2091  *      This routine does a standard config of a wd8003 family board, with
 2092  *      the proper modifications to different boards within this family.
 2093  *
 2094  */
 2095 config_wd8003(unit)
 2096 int     unit;
 2097 {
 2098         ns8390_softc_t *is = &ns8390_softc[unit];
 2099         vm_offset_t   hdwbase = ns8390info[unit]->address;
 2100         int       i;
 2101         int       RAMsize;
 2102         volatile char  *RAMbase;
 2103         int       addr_temp;
 2104 
 2105         is->tpsr = 0;                   /* transmit page start hold */
 2106         is->pstart = 0x06;              /* receive page start hold */
 2107         is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
 2108         is->fifo_depth = 0x08;          /* NIC fifo threshold */
 2109         switch (is->board_id & IFWD_RAM_SIZE_MASK) {
 2110               case IFWD_RAM_SIZE_8K:  
 2111                 RAMsize =  0x2000;      break;
 2112               case IFWD_RAM_SIZE_16K: 
 2113                 RAMsize =  0x4000;      break;
 2114               case IFWD_RAM_SIZE_32K: 
 2115                 RAMsize =  0x8000;      break;
 2116               case IFWD_RAM_SIZE_64K: 
 2117                 RAMsize = 0x10000;      break;
 2118               default:           
 2119                 RAMsize =  0x2000;      break;
 2120         }
 2121         is->pstop = (((int)RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
 2122         RAMbase = (volatile char *)ns8390info[unit]->phys_address;
 2123         addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */
 2124         outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */
 2125         /* enable 16 bit access from lan controller */
 2126         if (is->board_id & IFWD_SLOT_16BIT) {
 2127                 if (is->board_id & IFWD_INTERFACE_CHIP) {
 2128                         outb(hdwbase+IFWD_REG_5,
 2129                              (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
 2130                              IFWD_LAN16ENB);
 2131                 } else {
 2132                         outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
 2133                 }
 2134         }
 2135         /*
 2136           outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT);
 2137           */
 2138         
 2139         return TRUE;
 2140 }
 2141 
 2142 /*
 2143  * config_ns8390:
 2144  *
 2145  *      This routine does a standard config of a 3 com etherlink II board.
 2146  *
 2147  */
 2148 config_3c503(unit)
 2149 int     unit;
 2150 {
 2151         ns8390_softc_t  *is = &ns8390_softc[unit];
 2152         struct bus_device       *dev = ns8390info[unit];
 2153         vm_offset_t             hdwbase = dev->address;
 2154         int             RAMsize = dev->am;
 2155         int             i;
 2156 
 2157         is->tpsr =   0x20;              /* transmit page start hold */
 2158         is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100;
 2159                                         /* When NIC says page 20, this means go to
 2160                                            the beginning of the sram range */
 2161         is->pstart = 0x26;              /* receive page start hold */
 2162         is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
 2163         is->fifo_depth = 0x08;          /* NIC fifo threshold */
 2164         is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
 2165 
 2166         outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN);
 2167         outb(hdwbase+CTLR, CTLR_THIN);
 2168         outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN);
 2169         for (i = 0; i < 6; i++)
 2170                 is->address[i] = inb(hdwbase+i);
 2171         outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK);
 2172         outb(hdwbase+PSTR, is->pstart);
 2173         outb(hdwbase+PSPR, is->pstop);
 2174         outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2));
 2175         outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K);
 2176         /* BCFR & PCRFR ro */
 2177         /* STREG ro & dma */
 2178         outb(hdwbase+DQTR, 0);
 2179         outb(hdwbase+DAMSB, 0);
 2180         outb(hdwbase+DALSB, 0);
 2181         outb(hdwbase+VPTR2, 0);
 2182         outb(hdwbase+VPTR1, 0);
 2183         outb(hdwbase+VPTR0, 0);
 2184         outb(hdwbase+RFMSB, 0);
 2185         outb(hdwbase+RFLSB, 0);
 2186         return TRUE;
 2187 }
 2188 
 2189 /*
 2190  * ns8390intoff:
 2191  *
 2192  *      This function turns interrupts off for the ns8390 board indicated.
 2193  *
 2194  */
 2195 
 2196 ns8390intoff(unit)
 2197 int unit;
 2198 {
 2199         caddr_t nic = ns8390_softc[unit].nic;
 2200         int     temp_cr = inb(nic+CR);                  /* get current CR value */
 2201 
 2202         outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
 2203         outb(nic+IMR, 0);                       /* Interrupt Mask Register  */
 2204         outb(nic+CR, temp_cr|STP);
 2205 
 2206 }
 2207 
 2208 /*
 2209  *   wd80xxget_board_id:
 2210  *
 2211  *   determine which board is being used.
 2212  *   Currently supports:
 2213  *    wd8003E (tested)
 2214  *    wd8003EBT
 2215  *    wd8003EP (tested)
 2216  *    wd8013EP (tested)
 2217  *
 2218  */
 2219 wd80xxget_board_id(dev)
 2220 struct bus_device       *dev;
 2221 {
 2222         vm_offset_t    hdwbase = dev->address;
 2223         long           unit = dev->unit;
 2224         long           board_id = 0;
 2225         int            reg_temp;
 2226         int            rev_num;                 /* revision number */
 2227         int            ram_flag;
 2228         int            intr_temp;
 2229         int            i;
 2230         boolean_t      register_aliasing;
 2231 
 2232         rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1;
 2233         printf("%s%d: ", ns8390_softc[unit].card, unit);
 2234         
 2235         if (rev_num == 0) {
 2236                 printf("rev 0x00\n");
 2237                 /* It must be 8000 board */
 2238                 return 0;
 2239         }
 2240         
 2241         /* Check if register aliasing is true, that is reading from register
 2242            offsets 0-7 will return the contents of register offsets 8-f */
 2243         
 2244         register_aliasing = TRUE;
 2245         for (i = 1; i < 5; i++) {
 2246                 if (inb(hdwbase + IFWD_REG_0 + i) !=
 2247                     inb(hdwbase + IFWD_LAR_0 + i))
 2248                     register_aliasing = FALSE;
 2249         }
 2250         if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM))
 2251             register_aliasing = FALSE;
 2252         
 2253         
 2254         if (register_aliasing == FALSE) {
 2255                 /* Check if board has interface chip */
 2256                 
 2257                 reg_temp = inb(hdwbase + IFWD_REG_7);   /* save old */
 2258                 outb(hdwbase + IFWD_REG_7, 0x35);       /* write value */
 2259                 inb(hdwbase + IFWD_REG_0);              /* dummy read */
 2260                 if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) {
 2261                         outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/
 2262                         inb(hdwbase + IFWD_REG_0);      /* dummy read */
 2263                         if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) {
 2264                                 board_id |= IFWD_INTERFACE_CHIP;
 2265                                 outb(hdwbase + IFWD_REG_7, reg_temp);
 2266                                 /* restore old value */
 2267                         }
 2268                 }
 2269                 
 2270                 /* Check if board is 16 bit by testing if bit zero in
 2271                    register 1 is unchangeable by software. If so then
 2272                    card has 16 bit capability */
 2273                 reg_temp = inb(hdwbase + IFWD_REG_1);
 2274                 outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT);
 2275                 inb(hdwbase + IFWD_REG_0);                   /* dummy read */
 2276                 if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) ==
 2277                     (reg_temp & IFWD_16BIT)) {        /* Is bit unchanged */
 2278                         board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */
 2279                         reg_temp &= 0xfe;             /* For 16 bit board
 2280                                                          always reset bit 0 */
 2281                 }
 2282                 outb(hdwbase + IFWD_REG_1, reg_temp);    /* write value back */
 2283                 
 2284                 /* Test if 16 bit card is in 16 bit slot by reading bit zero in
 2285                    register 1. */
 2286                 if (board_id & IFWD_BOARD_16BIT) {
 2287                         if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
 2288                                 board_id |= IFWD_SLOT_16BIT;
 2289                         }
 2290                 }
 2291         }
 2292         
 2293         /* Get media type */
 2294         
 2295         if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) {
 2296                 board_id |= IFWD_ETHERNET_MEDIA;
 2297         } else if (rev_num == 1) {
 2298                 board_id |= IFWD_STARLAN_MEDIA;
 2299         } else {
 2300                 board_id |= IFWD_TWISTED_PAIR_MEDIA;
 2301         }
 2302 
 2303         if (rev_num == 2) {
 2304                 if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) {
 2305                         if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB ||
 2306                             (board_id & IFWD_STATIC_ID_MASK) == WD8003W) {
 2307                                 board_id |= IFWD_ALTERNATE_IRQ_BIT;
 2308                         }
 2309                 }
 2310                 /* Check for memory size */
 2311                 
 2312                 ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE;
 2313             
 2314                 switch (board_id & IFWD_STATIC_ID_MASK) {
 2315                       case WD8003E: /* same as WD8003EBT */
 2316                       case WD8003S: /* same as WD8003SH */
 2317                       case WD8003WT:
 2318                       case WD8003W:
 2319                       case WD8003EB: /* same as WD8003EP */
 2320                         if (ram_flag)
 2321                             board_id |= IFWD_RAM_SIZE_32K;
 2322                         else
 2323                             board_id |= IFWD_RAM_SIZE_8K;
 2324                         break;
 2325                       case WD8003ETA:
 2326                       case WD8003STA:
 2327                       case WD8003EA:
 2328                       case WD8003SHA:
 2329                       case WD8003WA:
 2330                         board_id |= IFWD_RAM_SIZE_16K;
 2331                         break;
 2332                       case WD8013EBT:
 2333                         if (board_id & IFWD_SLOT_16BIT) {
 2334                                 if (ram_flag)
 2335                                     board_id |= IFWD_RAM_SIZE_64K;
 2336                                 else
 2337                                     board_id |= IFWD_RAM_SIZE_16K;
 2338                         } else {
 2339                                 if (ram_flag)
 2340                                     board_id |= IFWD_RAM_SIZE_32K;
 2341                                 else
 2342                                     board_id |= IFWD_RAM_SIZE_8K;
 2343                         }
 2344                         break;
 2345                       default:
 2346                         board_id |= IFWD_RAM_SIZE_UNKNOWN;
 2347                         break;
 2348                 }
 2349         } else if (rev_num >= 3) {
 2350                 board_id &= (long) ~IFWD_MEDIA_MASK;   /* remove media info */
 2351                 board_id |= IFWD_INTERFACE_584_CHIP;
 2352                 board_id |= wd80xxget_eeprom_info(hdwbase, board_id);
 2353         } else {
 2354                 /* Check for memory size */
 2355                 if (board_id & IFWD_BOARD_16BIT) {
 2356                         if (board_id & IFWD_SLOT_16BIT)
 2357                             board_id |= IFWD_RAM_SIZE_16K;
 2358                         else
 2359                             board_id |= IFWD_RAM_SIZE_8K;
 2360                 } else if (board_id & IFWD_MICROCHANNEL)
 2361                     board_id |= IFWD_RAM_SIZE_16K;
 2362                 else if (board_id & IFWD_INTERFACE_CHIP) {
 2363                         if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE)
 2364                             board_id |= IFWD_RAM_SIZE_32K;
 2365                         else
 2366                             board_id |= IFWD_RAM_SIZE_8K;
 2367                 } else
 2368                     board_id |= IFWD_RAM_SIZE_UNKNOWN;
 2369                 
 2370                 /* No support for 690 chip yet. It should be checked here */
 2371         }
 2372         
 2373         switch (board_id & IFWD_STATIC_ID_MASK) {
 2374               case WD8003E: printf("WD8003E or WD8003EBT"); break;
 2375               case WD8003S: printf("WD8003S or WD8003SH"); break;
 2376               case WD8003WT: printf("WD8003WT"); break;
 2377               case WD8003W: printf("WD8003W"); break;
 2378               case WD8003EB:
 2379                 if (board_id & IFWD_INTERFACE_584_CHIP)
 2380                     printf("WD8003EP");
 2381                 else
 2382                     printf("WD8003EB");
 2383                 break;
 2384               case WD8003EW: printf("WD8003EW"); break;
 2385               case WD8003ETA: printf("WD8003ETA"); break;
 2386               case WD8003STA: printf("WD8003STA"); break;
 2387               case WD8003EA: printf("WD8003EA"); break;
 2388               case WD8003SHA: printf("WD8003SHA"); break;
 2389               case WD8003WA: printf("WD8003WA"); break;
 2390               case WD8013EBT: printf("WD8013EBT"); break;
 2391               case WD8013EB:
 2392                 if (board_id & IFWD_INTERFACE_584_CHIP)
 2393                     printf("WD8013EP");
 2394                 else
 2395                     printf("WD8013EB");
 2396                 break;
 2397               case WD8013W: printf("WD8013W"); break;
 2398               case WD8013EW: printf("WD8013EW"); break;
 2399               default: printf("unknown"); break;
 2400         }
 2401         printf(" rev 0x%02x", rev_num);
 2402         switch(board_id & IFWD_RAM_SIZE_RES_7) {
 2403               case IFWD_RAM_SIZE_UNKNOWN:
 2404                 break;
 2405               case IFWD_RAM_SIZE_8K:
 2406                 printf(" 8 kB ram");
 2407                 break;
 2408               case IFWD_RAM_SIZE_16K:
 2409                 printf(" 16 kB ram");
 2410                 break;
 2411               case IFWD_RAM_SIZE_32K:
 2412                 printf(" 32 kB ram");
 2413                 break;
 2414               case IFWD_RAM_SIZE_64K:
 2415                 printf(" 64 kB ram");
 2416                 break;
 2417               default:
 2418                 printf("wd: Internal error ram size value invalid %d\n",
 2419                        (board_id & IFWD_RAM_SIZE_RES_7)>>16);
 2420         }
 2421         
 2422         if (board_id & IFWD_BOARD_16BIT) {
 2423                 if (board_id & IFWD_SLOT_16BIT) {
 2424                         printf(", in 16 bit slot");
 2425                 } else {
 2426                         printf(", 16 bit board in 8 bit slot");
 2427                 }
 2428         }
 2429         if (board_id & IFWD_INTERFACE_CHIP) {
 2430                 if (board_id & IFWD_INTERFACE_584_CHIP) {
 2431                         printf(", 584 chip");
 2432                 } else {
 2433                         printf(", 583 chip");
 2434                 }
 2435         }
 2436         if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) {
 2437                 /* program the WD83C583 EEPROM registers */
 2438                 int irr_temp, icr_temp;
 2439                 
 2440                 icr_temp = inb(hdwbase + IFWD_ICR);
 2441                 irr_temp = inb(hdwbase + IFWD_IRR);
 2442                 
 2443                 irr_temp &= ~(IFWD_IR0 | IFWD_IR1);
 2444                 irr_temp |= IFWD_IEN;
 2445                 
 2446                 icr_temp &= IFWD_WTS;
 2447                 
 2448                 if (!(board_id & IFWD_INTERFACE_584_CHIP)) {
 2449                         icr_temp |= IFWD_DMAE | IFWD_IOPE;
 2450                         if (ram_flag)
 2451                             icr_temp |= IFWD_MSZ;
 2452                 }
 2453                 
 2454                 if (board_id & IFWD_INTERFACE_584_CHIP) {
 2455                         switch(ns8390info[unit]->sysdep1) {
 2456                               case 10:
 2457                                 icr_temp |= IFWD_DMAE;
 2458                                 break;
 2459                               case 2:
 2460                               case 9: /* Same as 2 */
 2461                                 break;
 2462                               case 11:
 2463                                 icr_temp |= IFWD_DMAE;
 2464                                 /*FALLTHROUGH*/
 2465                               case 3:
 2466                                 irr_temp |= IFWD_IR0;
 2467                                 break;
 2468                               case 15:
 2469                                 icr_temp |= IFWD_DMAE;
 2470                                 /*FALLTHROUGH*/
 2471                               case 5:
 2472                                 irr_temp |= IFWD_IR1;
 2473                                 break;
 2474                               case 4:
 2475                                 icr_temp |= IFWD_DMAE;
 2476                                 /*FALLTHROUGH*/
 2477                               case 7:
 2478                                 irr_temp |= IFWD_IR0 | IFWD_IR1;
 2479                                 break;
 2480                               default:
 2481                                 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
 2482                                        ns8390_softc[unit].card, unit,
 2483                                        ns8390info[unit]->sysdep1);
 2484                                 break;
 2485                         }
 2486                 } else {
 2487                         switch(ns8390info[unit]->sysdep1) {
 2488                                 /* attempt to set interrupt according to assigned pic */
 2489                               case 2:
 2490                               case 9: /* Same as 2 */
 2491                                 break;
 2492                               case 3:
 2493                                 irr_temp |= IFWD_IR0;
 2494                                 break;
 2495                               case 4:
 2496                                 irr_temp |= IFWD_IR1;
 2497                                 break;
 2498                               case 5:
 2499                                 irr_temp |= IFWD_IR1 | IFWD_AINT;
 2500                                 break;
 2501                               case 7: 
 2502                                 irr_temp |= IFWD_IR0 | IFWD_IR1;
 2503                                 break;
 2504                               default: 
 2505                                 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
 2506                                        ns8390_softc[unit].card, unit,
 2507                                        ns8390info[unit]->sysdep1);
 2508                         }
 2509                 }
 2510                 outb(hdwbase + IFWD_IRR, irr_temp);
 2511                 outb(hdwbase + IFWD_ICR, icr_temp);
 2512         }
 2513         printf("\n");
 2514         return (board_id);
 2515 }
 2516 
 2517 wd80xxget_eeprom_info(hdwbase, board_id)
 2518      caddr_t    hdwbase;
 2519      long       board_id;
 2520 {
 2521   unsigned long new_bits = 0;
 2522   int           reg_temp;
 2523   
 2524   outb(hdwbase + IFWD_REG_1,
 2525        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
 2526   outb(hdwbase + IFWD_REG_3,
 2527        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE));
 2528   outb(hdwbase + IFWD_REG_1,
 2529        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) |
 2530         (IFWD_RLA | IFWD_OTHER_BIT)));
 2531   while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK)
 2532       ;
 2533   
 2534   reg_temp = inb(hdwbase + IFWD_EEPROM_1);
 2535   switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) {
 2536         case IFWD_EEPROM_BUS_TYPE_AT:
 2537           if (wd_debug & 1) printf("wd: AT bus, ");
 2538           break;
 2539         case IFWD_EEPROM_BUS_TYPE_MCA:
 2540           if (wd_debug & 1) printf("wd: MICROCHANNEL, ");
 2541           new_bits |= IFWD_MICROCHANNEL;
 2542           break;
 2543         default:
 2544           break;
 2545   }
 2546   switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) {
 2547         case IFWD_EEPROM_BUS_SIZE_8BIT:
 2548           if (wd_debug & 1) printf("8 bit bus size, ");
 2549           break;
 2550         case IFWD_EEPROM_BUS_SIZE_16BIT:
 2551           if (wd_debug & 1) printf("16 bit bus size ");
 2552           new_bits |= IFWD_BOARD_16BIT;
 2553           if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
 2554                   new_bits |= IFWD_SLOT_16BIT;
 2555                   if (wd_debug & 1)
 2556                       printf("in 16 bit slot, ");
 2557           } else {
 2558                   if (wd_debug & 1)
 2559                       printf("in 8 bit slot (why?), ");
 2560           }
 2561           break;
 2562         default:
 2563           if (wd_debug & 1) printf("bus size other than 8 or 16 bit, ");
 2564           break;
 2565   }
 2566   reg_temp = inb(hdwbase + IFWD_EEPROM_0);
 2567   switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) {
 2568         case IFWD_STARLAN_TYPE:
 2569           if (wd_debug & 1) printf("Starlan media, ");
 2570           new_bits |= IFWD_STARLAN_MEDIA;
 2571           break;
 2572         case IFWD_TP_TYPE:
 2573           if (wd_debug & 1) printf("Twisted pair media, ");
 2574           new_bits |= IFWD_TWISTED_PAIR_MEDIA;
 2575           break;
 2576         case IFWD_EW_TYPE:
 2577           if (wd_debug & 1) printf("Ethernet and twisted pair media, ");
 2578           new_bits |= IFWD_EW_MEDIA;
 2579           break;
 2580         case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/
 2581         default:
 2582           if (wd_debug & 1) printf("ethernet media, ");
 2583           new_bits |= IFWD_ETHERNET_MEDIA;
 2584           break;
 2585   }
 2586   switch (reg_temp & IFWD_EEPROM_IRQ_MASK) {
 2587         case IFWD_ALTERNATE_IRQ_1:
 2588           if (wd_debug & 1) printf("Alternate irq 1\n");
 2589           new_bits |= IFWD_ALTERNATE_IRQ_BIT;
 2590           break;
 2591         default:
 2592           if (wd_debug & 1) printf("\n");
 2593           break;
 2594   }
 2595   switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) {
 2596         case IFWD_EEPROM_RAM_SIZE_8K:
 2597           new_bits |= IFWD_RAM_SIZE_8K;
 2598           break;
 2599         case IFWD_EEPROM_RAM_SIZE_16K:
 2600           if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
 2601               new_bits |= IFWD_RAM_SIZE_16K;
 2602           else
 2603               new_bits |= IFWD_RAM_SIZE_8K;
 2604           break;
 2605         case IFWD_EEPROM_RAM_SIZE_32K:
 2606           new_bits |= IFWD_RAM_SIZE_32K;
 2607           break;
 2608         case IFWD_EEPROM_RAM_SIZE_64K:
 2609           if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
 2610               new_bits |= IFWD_RAM_SIZE_64K;
 2611           else
 2612               new_bits |= IFWD_RAM_SIZE_32K;
 2613           break;
 2614         default:
 2615           new_bits |= IFWD_RAM_SIZE_UNKNOWN;
 2616           break;
 2617   }
 2618   outb(hdwbase + IFWD_REG_1,
 2619        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
 2620   outb(hdwbase + IFWD_REG_3,
 2621        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6));
 2622   outb(hdwbase + IFWD_REG_1,
 2623        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA));
 2624   return (new_bits);
 2625 }
 2626 
 2627 wdpr(unit)
 2628 {
 2629         caddr_t nic = ns8390_softc[unit].nic;
 2630         spl_t   s;
 2631         int     temp_cr;
 2632 
 2633         s = SPLNET();
 2634         temp_cr = inb(nic);             /* get current CR value */
 2635 
 2636         printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n",
 2637                 inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5),
 2638                 inb(nic+0x6), inb(nic+0x7), inb(nic+0xc));
 2639         printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n",
 2640                 inb(nic+0x1), inb(nic+0x2),
 2641                 inb(nic+0x8), inb(nic+0x9),
 2642                 inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
 2643 
 2644         
 2645         outb(nic, (temp_cr&0x3f)|PS1);          /* page 1 CR value */
 2646         printf("PHYS %x:%x:%x:%x:%x CUR %x\n",
 2647                 inb(nic+0x1), inb(nic+0x2), inb(nic+0x3),
 2648                 inb(nic+0x4), inb(nic+0x5), inb(nic+0x6),
 2649                 inb(nic+0x7));
 2650         printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n",
 2651                 inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb),
 2652                 inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
 2653         outb(nic, temp_cr);                     /* restore current CR value */
 2654         splx(s);
 2655 }
 2656 
 2657 
 2658 /*
 2659   This sets bit 7 (0 justified) of register offset 0x05. It will enable
 2660   the host to access shared RAM 16 bits at a time. It will also maintain
 2661   the LAN16BIT bit high in addition, this routine maintains address bit 19
 2662   (previous cards assumed this bit high...we must do it manually)
 2663   
 2664   note 1: this is a write only register
 2665   note 2: this routine should be called only after interrupts are disabled
 2666     and they should remain disabled until after the routine 'dis_16bit_access'
 2667     is called
 2668 */
 2669 
 2670 en_16bit_access (hdwbase, board_id)
 2671         caddr_t hdwbase;
 2672         long    board_id;
 2673 {
 2674         if (board_id & IFWD_INTERFACE_CHIP)
 2675             outb(hdwbase+IFWD_REG_5,
 2676                  (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK)
 2677                  | IFWD_MEM16ENB | IFWD_LAN16ENB);
 2678         else
 2679             outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB |
 2680                                       IFWD_LA19));
 2681 }
 2682 
 2683 /*
 2684   This resets bit 7 (0 justified) of register offset 0x05. It will disable
 2685   the host from accessing shared RAM 16 bits at a time. It will maintain the
 2686   LAN16BIT bit high in addition, this routine maintains address bit 19
 2687   (previous cards assumed this bit high...we must do it manually)
 2688 
 2689   note: this is a write only register
 2690 */
 2691 
 2692 dis_16bit_access (hdwbase, board_id)
 2693         caddr_t hdwbase;
 2694         long board_id;
 2695 {
 2696         if (board_id & IFWD_INTERFACE_CHIP)
 2697             outb(hdwbase+IFWD_REG_5,
 2698                  ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
 2699                   IFWD_LAN16ENB));
 2700         else
 2701             outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
 2702 }
 2703 

Cache object: 83bf26b9201d1cce9ef4edd97391dfd7


[ 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.