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) 1993,1992,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.23  93/11/17  16:47:47  dbg
   30  *      Changed HZ to hz.  Removed non-MACH_KERNEL code.
   31  *      [93/05/24            dbg]
   32  * 
   33  * Revision 2.22  93/05/10  23:24:07  rvb
   34  *      Added TTD teledebug code to use the ns8390 as a remote ethernet
   35  *      debugging device.
   36  *      [93/03/01            grm]
   37  * 
   38  * Revision 2.21  93/05/10  21:19:20  rvb
   39  *      Lint.
   40  *      [93/05/08  11:20:50  af]
   41  * 
   42  * Revision 2.20  93/01/24  13:17:18  danner
   43  *      Sigh! Sometimes the reported length of the packet is zero.  But
   44  *      the rest of the chain looked OK.  So we'll just skip the packet.
   45  *      [92/10/27            rvb]
   46  * 
   47  * Revision 2.19  93/01/14  17:30:37  danner
   48  *      Proper spl typing.
   49  *      [92/11/30            af]
   50  * 
   51  * Revision 2.18  92/08/03  17:17:43  jfriedl
   52  *      Fixed bug in wd80xxget_board_id, that made the machine hang on
   53  *      reboot when using wd8013EP boards.
   54  *      [92/07/13            kivinen]
   55  * 
   56  * Revision 2.17  92/07/09  22:54:18  rvb
   57  *      Say whether EtherLink II is thick or thin.
   58  *      [92/06/18            rvb]
   59  * 
   60  * Revision 2.16  92/04/03  12:15:19  rpd
   61  *      Use port 0x250, 0x350 for irq 5 bnc, thick respectively.
   62  *      [92/04/02            rvb]
   63  * 
   64  * Revision 2.15  92/02/19  15:08:22  elf
   65  *      Made wd driver work with 16 bit cards. Better recognize different
   66  *      cards. Print card name when probing. Tested on wd8003, wd8013EP,
   67  *      wd8003EP.
   68  *      Add IFWD_ prefix to defines.
   69  *      [92/01/20            kivinen]
   70  * 
   71  * Revision 2.14  91/11/12  11:09:39  rvb
   72  *      Undo "strict" wrong change to probe()
   73  *      [91/10/25            rvb]
   74  * 
   75  * Revision 2.13  91/10/09  16:07:43  af
   76  *      Fixes from 2.5 (from rvb), made sure two WD boards work (with
   77  *      help from jeffreyh).
   78  * 
   79  * Revision 2.12  91/08/24  11:58:01  af
   80  *      New MI autoconf.
   81  *      [91/08/02  02:55:17  af]
   82  * 
   83  * Revision 2.11  91/05/14  16:24:56  mrt
   84  *      Correcting copyright
   85  * 
   86  * Revision 2.10  91/05/13  06:02:41  af
   87  *      Made code under CMUCS standard.
   88  *      [91/05/12  15:50:35  af]
   89  * 
   90  * Revision 2.9  91/03/16  14:46:23  rpd
   91  *      Changed net_filter to net_packet.
   92  *      [91/01/15            rpd]
   93  * 
   94  * Revision 2.8  91/02/14  14:42:44  mrt
   95  *      Distinguish EtherLinkII vs WD8003 on open.  Get packet
   96  *      size right for statistics.  Fix 3.0 buf that sometimes
   97  *      reported packets too large.
   98  *      [91/01/28  15:31:22  rvb]
   99  * 
  100  * Revision 2.7  91/02/05  17:17:52  mrt
  101  *      Changed to new Mach copyright
  102  *      [91/02/01  17:44:04  mrt]
  103  * 
  104  * Revision 2.6  91/01/09  16:07:19  rpd
  105  *      Fixed typo in ns8390probe.
  106  *      [91/01/09            rpd]
  107  * 
  108  * Revision 2.5  91/01/08  17:35:46  rpd
  109  *      Changed NET_KMSG_GET to net_kmsg_get.
  110  *      [91/01/08            rpd]
  111  * 
  112  * Revision 2.4  91/01/08  17:33:05  rpd
  113  *      A few bug fixes.
  114  *      [91/01/08  16:41:04  rvb]
  115  * 
  116  *      Make this a generic driver for ns8390 from wd8003 because
  117  *      we now will also support etherlink ii.
  118  *      [91/01/04  12:25:21  rvb]
  119  * 
  120  * Revision 2.1.1.7  90/11/27  13:43:18  rvb
  121  *      Synched 2.5 & 3.0 at I386q (r2.1.1.7) & XMK35 (r2.3)
  122  *      [90/11/15            rvb]
  123  * 
  124  * Revision 2.2  90/10/01  14:23:09  jeffreyh
  125  *      Changes for MACH_KERNEL. 
  126  *      initial checkin.
  127  *      [90/09/27  18:22:09  jeffreyh]
  128  *
  129  * Revision 2.1.1.6  90/09/18  08:38:39  rvb
  130  *      Unfortunately, the switches to bank 0 seem necessary so are back
  131  *      in.
  132  *      [90/09/08            rvb]
  133  * 
  134  * Revision 2.1.1.5  90/08/25  15:42:58  rvb
  135  *      Use take_<>_irq() vs direct manipulations of ivect and friends.
  136  *      [90/08/20            rvb]
  137  * 
  138  *      Flush unnecessary switches to bank 0. Use error counters
  139  *      vs printouts.  Fix DSF_RUNNING.  Some more cleanup.
  140  *      [90/08/14            rvb]
  141  * 
  142  * Revision 2.1.1.4  90/07/28  10:00:40  rvb
  143  *      Get correct counter offsets
  144  * 
  145  * Revision 2.1.1.3  90/07/27  17:16:05  rvb
  146  *      No multicast for now.
  147  * 
  148  * Revision 2.1.1.2  90/07/27  11:25:11  rvb
  149  *      Add boardID support for wd80xxyyy family of boards.     [rweiss]
  150  *      Bunch of cleanup and ...                [rweiss&rvb]
  151  * 
  152  * Revision 2.1.1.1  90/07/10  11:44:46  rvb
  153  *      Added to system.
  154  *      [90/07/06            rvb]
  155  *
  156  *
  157  *   Author: Ron Weiss (rweiss)
  158  *
  159  */
  160  
  161 /* NOTE:
  162  *      There are three outstanding bug/features in this implementation.
  163  * They may even be hardware misfeatures.  The conditions are registered
  164  * by counters maintained by the software.
  165  *      1: over_write is a condition that means that the board wants to store
  166  * packets, but there is no room.  So new packets are lost.  What seems to
  167  * be happening is that we get an over_write condition, but there are no
  168  * or just a few packets in the board's ram.  Also it seems that we get
  169  * several over_writes in a row.
  170  *      2: Since there is only one transmit buffer, we need a lock to indicate
  171  * whether it is in use.  We clear this lock when we get a transmit interrupt.
  172  * Sometimes we go to transmit and although there is no transmit in progress,
  173  * the lock is set.  (In this case, we just ignore the lock.)  It would look
  174  * like we can miss transmit interrupts?
  175  *      3: We tried to clean up the unnecessary switches to bank 0.  
  176  * Unfortunately, when you do an ifconfig "down", the system tend to lock up
  177  * a few seconds later (this was when DSF_RUNNING) was not being set before.
  178  * But even with DSF_RUNNING, on an EISA bus machine we ALWAYS lock up after
  179  * a few seconds. 
  180  */
  181 
  182 /*
  183  * Western Digital 8003E Mach Ethernet driver (for intel 80386)
  184  * Copyright (c) 1990 by Open Software Foundation (OSF).
  185  */
  186 
  187 /*
  188   Copyright 1990 by Open Software Foundation,
  189 Cambridge, MA.
  190 
  191                 All Rights Reserved
  192 
  193   Permission to use, copy, modify, and distribute this software and
  194 its documentation for any purpose and without fee is hereby granted,
  195 provided that the above copyright notice appears in all copies and
  196 that both the copyright notice and this permission notice appear in
  197 supporting documentation, and that the name of OSF or Open Software
  198 Foundation not be used in advertising or publicity pertaining to
  199 distribution of the software without specific, written prior
  200 permission.
  201 
  202   OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  203 <INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  204 IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  205 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  206 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  207 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  208 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  209 */
  210 
  211 #define IF_CNTRS        MACH
  212 #include        <ns8390.h>
  213 
  214 #include        <mach_ttd.h>
  215 #include        <kern/kern_io.h>
  216 #include        <kern/memory.h>
  217 #include        <kern/time_out.h>
  218 #include        <device/device_types.h>
  219 #include        <device/errno.h>
  220 #include        <device/io_req.h>
  221 #include        <device/if_hdr.h>
  222 #include        <device/if_ether.h>
  223 #include        <device/net_status.h>
  224 #include        <device/net_io.h>
  225 
  226 #include        <i386/ipl.h>
  227 #include        <i386/pio.h>
  228 #include        <chips/busses.h>
  229 #include        <i386at/if_ns8390.h>
  230 #include        <i386at/if_wd8003.h>
  231 #include        <i386at/if_3c503.h>
  232 
  233 #if     MACH_TTD
  234 #include <ttd/ttd_stub.h>
  235 #endif  /* MACH_TTD */
  236 
  237 
  238 #define SPLNET  spl6
  239 
  240 int wd_debug = 0;
  241   
  242 boolean_t ns8390probe(
  243         vm_offset_t     port,
  244         struct bus_device       *dev);
  245 void    ns8390attach();
  246 int     ns8390intr();
  247 int     ns8390init();
  248 int     ns8390output();
  249 int     ns8390ioctl();
  250 int     ns8390reset();
  251 int     ns8390rcv(int unit);
  252 void    ns8390watch(void *b_ptr);
  253 int     ns8390get_CURR();
  254 int     ns8390over_write();
  255 
  256 struct  bus_device      *ns8390info[NNS8390];   /* ???? */
  257 
  258 static vm_offset_t ns8390_std[NNS8390] = { 0 };
  259 static struct bus_device *ns8390_info[NNS8390];
  260 struct  bus_driver      ns8390driver =
  261         {ns8390probe, 0, ns8390attach, 0, ns8390_std, "ns8390", ns8390_info, 0, 0, 0};
  262 
  263 int     watchdog_id;
  264 
  265 char *wd8003_card = "wd";
  266 char *elii_card = "el";
  267 /*                2e0, 2a0, 280,  250,   350,   330,   310, 300*/
  268 int elii_irq[8] = {5,   2,   2,     5,     5, 0x711, 0x711,  5};
  269 int elii_bnc[8] = {1,   0,   1,     1,     0, 0x711, 0x711,  0};
  270 /*int elii_bnc[8] = {0, 1,   1,     1,     1,     1,     0,  1}; */
  271 
  272 typedef struct {
  273         struct  ifnet   ds_if;          /* generic interface header */
  274         u_char  ds_addr[6];             /* Ethernet hardware address */
  275         int     flags;
  276         int     timer;
  277         int     interrupt;
  278         vm_offset_t nic;                /* address of IO ports */
  279         u_char   address[ETHER_ADDR_SIZE];
  280         short   mode;
  281         int     tbusy;
  282         char    *sram;          /* beginning of the shared memory RAM buffer */
  283         int     read_nxtpkt_ptr;/* pointer to next packet available */
  284         int     pstart;         /* page start hold */
  285         int     pstop;          /* page stop hold */
  286         int     tpsr;           /* transmit page start hold */
  287         int     fifo_depth;     /* NIC fifo threshold */
  288         char    *card;
  289         int     board_id;
  290 }
  291 ns8390_softc_t;
  292 
  293 ns8390_softc_t  ns8390_softc[NNS8390];
  294 
  295 struct ns8390_cntrs {
  296 u_int   ovw,
  297         jabber,
  298         crc,
  299         frame,
  300         miss,
  301         fifo,
  302         rcv;
  303 u_int   xmt,
  304         xmti,
  305         busy,
  306         heart;
  307 } ns8390_cntrs[NNS8390];
  308 
  309 #if     MACH_TTD        
  310 boolean_t ttd_poll_loop;
  311 
  312 int ns8390poll_receive();
  313 int ns8390transmit_ttd();
  314 #endif  /* MACH_TTD */
  315 
  316 #ifdef  IF_CNTRS
  317 int ns_narp = 1, ns_arp = 0;
  318 int ns_ein[32], ns_eout[32]; 
  319 int ns_lin[128/8], ns_lout[128/8]; 
  320 static
  321 log_2(no)
  322 unsigned long no;
  323 {
  324         return ({ unsigned long _temp__;
  325                 asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" :
  326                     "=r" (_temp__) : "a" (no));
  327                 _temp__;});
  328 }
  329 #endif  /* IF_CNTRS */
  330 
  331 int  imr_hold = PRXE|PTXE|RXEE|TXEE|OVWE|CNTE;  /* Interrupts mask bits */
  332 
  333 /*
  334  * ns8390probe:
  335  *
  336  *      This function "probes" or checks for the wd8003 board on the bus to see
  337  *      if it is there.  As far as I can tell, the best break between this
  338  *      routine and the attach code is to simply determine whether the board
  339  *      is configured in properly. Currently my approach to this is to test the
  340  *      base I/O special offset for the Western Digital unique byte sequence
  341  *      identifier.  If the bytes match we assume board is there.
  342  *      The config code expects to see a successful return from the probe
  343  *      routine before attach will be called.
  344  *
  345  * input        : address device is mapped to, and unit # being checked
  346  * output       : a '1' is returned if the board exists, and a 0 otherwise
  347  *
  348  */
  349 
  350 boolean_t ns8390probe(
  351         vm_offset_t     port,
  352         struct bus_device       *dev)
  353 {
  354         vm_offset_t     hdwbase = dev->address;
  355         int             unit = dev->unit;
  356         ns8390_softc_t  *sp = &ns8390_softc[unit];
  357         int             tmp;
  358 
  359         if ((unit < 0) || (unit > NNS8390)) {
  360                 printf("ns8390 ethernet unit %d out of range\n", unit);
  361                 return(0);
  362         }
  363         if (((u_char) inb(hdwbase+IFWD_LAR_0) == (u_char) WD_NODE_ADDR_0) &&
  364             ((u_char) inb(hdwbase+IFWD_LAR_1) == (u_char) WD_NODE_ADDR_1) &&
  365             ((u_char) inb(hdwbase+IFWD_LAR_2) == (u_char) WD_NODE_ADDR_2)) {
  366                         ns8390info[unit] = dev;
  367                         sp->card = wd8003_card;
  368                         dev->name = wd8003_card;
  369                         sp->nic = hdwbase + OFF_8390;
  370                                 /* enable mem access to board */
  371                         sp->board_id = wd80xxget_board_id(dev);
  372 
  373                         *(sp->address)      = inb(hdwbase+IFWD_LAR_0);
  374                         *(sp->address + 1)  = inb(hdwbase+IFWD_LAR_1);
  375                         *(sp->address + 2)  = inb(hdwbase+IFWD_LAR_2);
  376                         *(sp->address + 3)  = inb(hdwbase+IFWD_LAR_3);
  377                         *(sp->address + 4)  = inb(hdwbase+IFWD_LAR_4);
  378                         *(sp->address + 5)  = inb(hdwbase+IFWD_LAR_5);
  379                         return (1);
  380                 }  /* checks the address of the board to verify that it is a WD */
  381         if (tmp = inb(hdwbase+BCFR)) {
  382                 switch(tmp) {
  383                 case (1<<7):    sp->board_id = 7; break;        /*irq5 xvcr*/
  384 #ifdef  not_currently_possible
  385                 case (1<<6):    sp->board_id = 6; break;
  386                 case (1<<5):    sp->board_id = 5; break;
  387 #endif  /* not_currently_possible */
  388                 case (1<<4):    sp->board_id = 4; break;
  389                 case (1<<3):    sp->board_id = 3; break;
  390                 case (1<<2):    sp->board_id = 2; break;        /*irq2 bnc*/
  391                 case (1<<1):    sp->board_id = 1; break;        /*irq2 xvcr*/
  392                 case (1<<0):    sp->board_id = 0; break;        /*irq5 bnc*/
  393                 default:        return 0;
  394                 }
  395                 switch (inb(hdwbase+PCFR)) {
  396                 case (1<<7):    dev->phys_address = 0xDC000; break;
  397                 case (1<<6):    dev->phys_address = 0xD8000; break;
  398 #ifdef  not_currently_possible
  399                 case (1<<5):    dev->phys_address = 0xCC000; break;
  400                 case (1<<4):    dev->phys_address = 0xC8000; break;
  401 #endif  /* not_currently_possible */
  402                 default:
  403                         printf("EtherLink II with NO memory configured\n");
  404                         return 0;
  405                 }
  406                 ns8390info[unit] = dev;
  407                 dev->sysdep1 = elii_irq[sp->board_id];
  408                 if (dev->sysdep1 == 2)
  409                         dev->sysdep1 = 9;
  410                 sp->card = elii_card;
  411                 dev->name = elii_card;
  412                 sp->nic = hdwbase;
  413                 return 1;
  414         }
  415         return(0);
  416 }
  417 
  418 /*
  419  * ns8390attach:
  420  *
  421  *      This function attaches a ns8390 board to the "system".  The rest of
  422  *      runtime structures are initialized here (this routine is called after
  423  *      a successful probe of the board).  Once the ethernet address is read
  424  *      and stored, the board's ifnet structure is attached and readied.
  425  *
  426  * input        : bus_device structure setup in autoconfig
  427  * output       : board structs and ifnet is setup
  428  *
  429  */
  430 
  431 void ns8390attach(dev)
  432 struct bus_device       *dev;
  433 {
  434         ns8390_softc_t  *sp;
  435         struct  ifnet   *ifp;
  436         u_char          unit;
  437 
  438         take_dev_irq(dev);
  439         unit = (u_char)dev->unit;
  440         sp = &ns8390_softc[unit];
  441         printf(", port = %x, spl = %d, pic = %d. ",
  442                 dev->address, dev->sysdep, dev->sysdep1);
  443 
  444         if (sp->card == elii_card) {
  445                 if (elii_bnc[sp->board_id])
  446                         printf("cheapernet ");
  447                 else
  448                         printf("ethernet ");
  449         } else
  450                 printf("ethernet ");
  451 
  452         (volatile char *)sp->sram =
  453             (volatile char *) phystokv(dev->phys_address);
  454         dev->address = (vm_offset_t) phystokv(dev->address);
  455         sp->timer = -1;
  456         sp->flags = 0;
  457         sp->mode  = 0;
  458 
  459         if (!ns8390hwrst(unit)) {
  460                 printf("%s%d: attach(): reset failed.\n",
  461                         sp->card, unit);
  462                 return;
  463         }
  464                 /* N.B. sp->address is not determined till
  465                  * hwrst time. */
  466         *(sp->ds_addr)      = *(sp->address);
  467         *(sp->ds_addr + 1)  = *(sp->address + 1);
  468         *(sp->ds_addr + 2)  = *(sp->address + 2);
  469         *(sp->ds_addr + 3)  = *(sp->address + 3);
  470         *(sp->ds_addr + 4)  = *(sp->address + 4);
  471         *(sp->ds_addr + 5)  = *(sp->address + 5);
  472 
  473         printf("id [%x:%x:%x:%x:%x:%x]",
  474                 sp->address[0],sp->address[1],sp->address[2],
  475                 sp->address[3],sp->address[4],sp->address[5]);
  476         ifp = &(sp->ds_if);
  477         ifp->if_unit = unit;
  478         ifp->if_mtu = ETHERMTU;
  479         ifp->if_flags = IFF_BROADCAST;
  480         ifp->if_header_size = sizeof(struct ether_header);
  481         ifp->if_header_format = HDR_ETHERNET;
  482         ifp->if_address_size = 6;
  483         ifp->if_address = (char *)&sp->address[0];
  484         if_init_queues(ifp);
  485 
  486 #if     MACH_TTD
  487         if (!ttd_get_packet) {
  488                 ttd_device_unit = unit;
  489                 ttd_get_packet = ns8390poll_receive;
  490                 ttd_send_packet = ns8390transmit_ttd;
  491                 ttd_host_ether_id.array[0] = *(sp->address);
  492                 ttd_host_ether_id.array[1] = *(sp->address + 1);
  493                 ttd_host_ether_id.array[2] = *(sp->address + 2);
  494                 ttd_host_ether_id.array[3] = *(sp->address + 3);
  495                 ttd_host_ether_id.array[4] = *(sp->address + 4);
  496                 ttd_host_ether_id.array[5] = *(sp->address + 5);
  497         }
  498 #endif  /* MACH_TTD */
  499 }
  500 
  501 /*
  502  * ns8390watch():
  503  *
  504  */
  505 
  506 void
  507 ns8390watch(void *b_ptr)
  508 {
  509         int     unit;
  510         int     temp_cr;
  511         vm_offset_t nic;
  512 
  513         unit = *(char *)b_ptr;
  514         timeout(ns8390watch,b_ptr,20*hz);
  515         nic = ns8390_softc[unit].nic;
  516         temp_cr = inb(nic+CR);
  517         outb(nic + CR, (temp_cr & 0x3f) | PS0);
  518         printf("<<< ISR=%x CURR=%x rdnxt=%x BNDY=%x>>> ",
  519                 inb(nic + ISR),
  520                 ns8390get_CURR(unit), ns8390_softc[unit].read_nxtpkt_ptr,
  521                 inb(nic+BNDY));
  522         outb(nic+CR,temp_cr);
  523 }
  524 
  525 void ns8390start(
  526         int     unit);  /* forward */
  527 
  528 /*ARGSUSED*/
  529 wd8003open(dev, flag)
  530         dev_t   dev;
  531         int     flag;
  532 {
  533         register int    unit = minor(dev);
  534 
  535         if (ns8390_softc[unit].card != wd8003_card)
  536                 return (ENXIO);
  537         if (unit < 0 || unit >= NNS8390 ||
  538                 ns8390_softc[unit].nic == 0)
  539             return (ENXIO);
  540 
  541         ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
  542         ns8390init(unit);
  543         return(0);
  544 }
  545 
  546 eliiopen(dev, flag)
  547         dev_t   dev;
  548         int     flag;
  549 {
  550         register int    unit = minor(dev);
  551 
  552         if (ns8390_softc[unit].card != elii_card)
  553                 return (ENXIO);
  554         if (unit < 0 || unit >= NNS8390 ||
  555                 ns8390_softc[unit].nic == 0)
  556             return (ENXIO);
  557 
  558         ns8390_softc[unit].ds_if.if_flags |= IFF_UP;
  559         ns8390init(unit);
  560         return(0);
  561 }
  562 
  563 ns8390output(dev, ior)
  564         dev_t           dev;
  565         io_req_t        ior;
  566 {
  567         register int    unit = minor(dev);
  568 
  569         if (unit < 0 || unit >= NNS8390 ||
  570                 ns8390_softc[unit].nic == 0)
  571             return (ENXIO);
  572         return (net_write(&ns8390_softc[unit].ds_if, ns8390start, ior));
  573 }
  574 
  575 ns8390setinput(dev, receive_port, priority, filter, filter_count)
  576         dev_t           dev;
  577         mach_port_t     receive_port;
  578         int             priority;
  579         filter_t        filter[];
  580         unsigned int    filter_count;
  581 {
  582         register int unit = minor(dev);
  583 
  584         if (unit < 0 || unit >= NNS8390 ||
  585                 ns8390_softc[unit].nic == 0)
  586             return (ENXIO);
  587 
  588         return (net_set_filter(&ns8390_softc[unit].ds_if,
  589                         receive_port, priority,
  590                         filter, filter_count));
  591 }
  592 
  593 
  594 /*
  595  * ns8390reset:
  596  *
  597  *      This routine is in part an entry point for the "if" code.  Since most
  598  *      of the actual initialization has already (we hope already) been done
  599  *      by calling ns8390attach().
  600  *
  601  * input        : unit number or board number to reset
  602  * output       : board is reset
  603  *
  604  */
  605 
  606 int
  607 ns8390reset(unit)
  608 int     unit;
  609 {
  610 
  611         ns8390_softc[unit].ds_if.if_flags &= ~IFF_RUNNING;
  612         return(ns8390init(unit));
  613 }
  614 
  615 /*
  616  * ns8390init:
  617  *
  618  *      Another routine that interfaces the "if" layer to this driver.
  619  *      Simply resets the structures that are used by "upper layers".
  620  *      As well as calling ns8390hwrst that does reset the ns8390 board.
  621  *
  622  * input        : board number
  623  * output       : structures (if structs) and board are reset
  624  *
  625  */
  626 
  627 int
  628 ns8390init(unit)
  629 int     unit;
  630 {
  631         struct  ifnet   *ifp;
  632         int             stat;
  633         spl_t           oldpri;
  634 
  635         ifp = &(ns8390_softc[unit].ds_if);
  636         oldpri = SPLNET();
  637         if ((stat = ns8390hwrst(unit)) == TRUE) {
  638                 ns8390_softc[unit].ds_if.if_flags |= IFF_RUNNING;
  639                 ns8390_softc[unit].flags |= DSF_RUNNING;
  640                 ns8390_softc[unit].tbusy = 0;
  641                 ns8390start(unit);
  642         } else
  643                 printf("%s%d init(): trouble resetting board %d\n",
  644                         ns8390_softc[unit].card, unit);
  645         ns8390_softc[unit].timer = 5;
  646         splx(oldpri);
  647         return(stat);
  648 }
  649 
  650 /*
  651  * ns8390start:
  652  *
  653  *      This is yet another interface routine that simply tries to output a
  654  *      in an mbuf after a reset.
  655  *
  656  * input        : board number
  657  * output       : stuff sent to board if any there
  658  *
  659  */
  660 
  661 void ns8390start(
  662         int     unit)
  663 {
  664         register ns8390_softc_t *is = &ns8390_softc[unit];
  665         struct  ifnet           *ifp;
  666         io_req_t        m;
  667 
  668         if (is->tbusy) {
  669                 vm_offset_t nic = ns8390_softc[unit].nic;
  670                 if (!(inb(nic+CR) & TXP)) {
  671                         is->tbusy = 0;
  672                         ns8390_cntrs[unit].busy++;
  673                 } else
  674                         return;
  675         }
  676 
  677         ifp = &(ns8390_softc[unit].ds_if);
  678 
  679         IF_DEQUEUE(&ifp->if_snd, m);
  680         if (m != 0) {
  681                 is->tbusy++;
  682                 ns8390_cntrs[unit].xmt++;
  683                 ns8390xmt(unit, m);
  684         }
  685 }
  686 
  687 /*ARGSUSED*/
  688 ns8390getstat(dev, flavor, status, count)
  689         dev_t           dev;
  690         int             flavor;
  691         dev_status_t    status;         /* pointer to OUT array */
  692         unsigned int    *count;         /* out */
  693 {
  694         register int    unit = minor(dev);
  695 
  696         if (unit < 0 || unit >= NNS8390 ||
  697                 ns8390_softc[unit].nic == 0)
  698             return (ENXIO);
  699 
  700         return (net_getstat(&ns8390_softc[unit].ds_if,
  701                             flavor,
  702                             status,
  703                             count));
  704 }
  705 ns8390setstat(dev, flavor, status, count)
  706         dev_t           dev;
  707         int             flavor;
  708         dev_status_t    status;
  709         unsigned int    count;
  710 {
  711         register int    unit = minor(dev);
  712         register ns8390_softc_t *sp;
  713 
  714         if (unit < 0 || unit >= NNS8390 ||
  715                 ns8390_softc[unit].nic == 0)
  716             return (ENXIO);
  717 
  718         sp = &ns8390_softc[unit];
  719 
  720         switch (flavor) {
  721             case NET_STATUS:
  722             {
  723                 /*
  724                  * All we can change are flags, and not many of those.
  725                  */
  726                 register struct net_status *ns = (struct net_status *)status;
  727                 int     mode = 0;
  728 
  729                 if (count < NET_STATUS_COUNT)
  730                     return (D_INVALID_SIZE);
  731 
  732                 if (ns->flags & IFF_ALLMULTI)
  733                     mode |= MOD_ENAL;
  734                 if (ns->flags & IFF_PROMISC)
  735                     mode |= MOD_PROM;
  736 
  737                 /*
  738                  * Force a complete reset if the receive mode changes
  739                  * so that these take effect immediately.
  740                  */
  741                 if (sp->mode != mode) {
  742                     sp->mode = mode;
  743                     if (sp->flags & DSF_RUNNING) {
  744                         sp->flags &= ~(DSF_LOCK | DSF_RUNNING);
  745                         ns8390init(unit);
  746                     }
  747                 }
  748                 break;
  749             }
  750 
  751             default:
  752                 return (D_INVALID_OPERATION);
  753         }
  754         return (D_SUCCESS);
  755 }
  756 
  757 /*
  758  * ns8390hwrst:
  759  *
  760  *      This routine resets the ns8390 board that corresponds to the
  761  *      board number passed in.
  762  *
  763  * input        : board number to do a hardware reset
  764  * output       : board is reset
  765  *
  766  */
  767 
  768 int
  769 ns8390hwrst(unit)
  770 int unit;
  771 {
  772         spl_t   spl = SPLNET();
  773 
  774         if (ns8390_softc[unit].card == wd8003_card && 
  775             config_wd8003(unit) == FALSE) {
  776                 printf("%s%d hwrst(): config_wd8003 failed.\n",
  777                         ns8390_softc[unit].card, unit);
  778                 splx(spl);
  779                 return(FALSE);
  780         }
  781         if (ns8390_softc[unit].card == elii_card && 
  782             config_3c503(unit) == FALSE) {
  783                 printf("%s%d hwrst(): config_3c503 failed.\n",
  784                         ns8390_softc[unit].card, unit);
  785                 splx(spl);
  786                 return(FALSE);
  787         }
  788         if (config_nic(unit) == FALSE) {
  789                 printf("%s%d hwrst(): config_nic failed.\n",
  790                         ns8390_softc[unit].card, unit);
  791                 splx(spl);
  792                 return(FALSE);
  793         }
  794         splx(spl);
  795         return(TRUE);
  796 }
  797 
  798 /*
  799  * ns8390intr:
  800  *
  801  *      This function is the interrupt handler for the ns8390 ethernet
  802  *      board.  This routine will be called whenever either a packet
  803  *      is received, or a packet has successfully been transfered and
  804  *      the unit is ready to transmit another packet.
  805  *
  806  * input        : board number that interrupted
  807  * output       : either a packet is received, or a packet is transfered
  808  *
  809  */
  810 int
  811 ns8390intr(unit)
  812 {
  813         int     isr_status;
  814         int     temp_cr;
  815         vm_offset_t nic = ns8390_softc[unit].nic;
  816 
  817         temp_cr = inb(nic+CR);
  818         outb(nic+CR, (temp_cr & 0x3f) | PS0);
  819         outb(nic+IMR, 0);                   /* stop board interrupts */
  820         outb(nic+CR, temp_cr);
  821         while (isr_status = inb(nic+ISR)) {
  822                 outb(nic+ISR, isr_status);          /* clear interrupt status */
  823 
  824                 if ((isr_status & (OVW|RXE)) == RXE) {
  825                         int rsr = inb(nic+RSR);
  826                         if (rsr & DFR) ns8390_cntrs[unit].jabber++;
  827                         if (rsr & ~(DFR|PHY|FAE|CRC|PRX))
  828                                 printf("%s%d intr(): isr = %x, RSR = %x\n",
  829                                         ns8390_softc[unit].card, unit,
  830                                         isr_status, rsr);
  831                 } else if (isr_status & OVW) {
  832                         ns8390_cntrs[unit].ovw++;
  833                         ns8390over_write(unit);
  834                 }
  835                 if (isr_status & PRX) {                 /* DFR & PRX is possible */
  836                         (void) ns8390rcv(unit);
  837 
  838 #if     MACH_TTD
  839                         if (kttd_active)
  840                                 ttd_poll_loop = FALSE;
  841 #endif  /* MACH_TTD */
  842                 }
  843 
  844                 if (isr_status & TXE) {
  845                         int tsr = inb(nic+TSR);
  846                         tsr &= ~0x2;            /* unadvertised special */
  847 #if     MACH_TTD
  848                         if (!kttd_active)
  849 #endif  /* MACH_TTD */
  850                         {
  851                                 if (tsr == (CDH|ABT))
  852                                         ns8390_cntrs[unit].heart++;
  853                                 else
  854                                         printf("%s%d intr(): isr = %x, TSR = %x\n",
  855                                                ns8390_softc[unit].card, unit,
  856                                                isr_status, tsr);
  857                                 ns8390_softc[unit].tbusy = 0;
  858                                 ns8390start(unit);
  859                         }
  860                 } else if (isr_status & PTX) {
  861 #if     MACH_TTD
  862                         if (!kttd_active)
  863 #endif  /* MACH_TTD */
  864                         {
  865                                 ns8390_cntrs[unit].xmti++;
  866                                 ns8390_softc[unit].tbusy = 0;
  867                                 ns8390start(unit);
  868                         }
  869                 }
  870 
  871                 if (isr_status & CNT) {
  872                         int c0 = inb(nic+CNTR0);
  873                         int c1 = inb(nic+CNTR1);
  874                         int c2 = inb(nic+CNTR2);
  875                         ns8390_cntrs[unit].frame += c0;
  876                         ns8390_cntrs[unit].crc += c1;
  877                         ns8390_cntrs[unit].miss += c2;
  878 #ifdef  COUNTERS
  879                         printf("%s%d intr(): isr = %x, FRAME %x, CRC %x, MISS %x\n",
  880                                 ns8390_softc[unit].card, unit,
  881                                 isr_status, c0, c1, c2);
  882                         printf("%s%d intr(): TOTAL   , FRAME %x, CRC %x, MISS %x\n",
  883                                 ns8390_softc[unit].card, unit,
  884                                 ns8390_cntrs[unit].frame,
  885                                 ns8390_cntrs[unit].crc,
  886                                 ns8390_cntrs[unit].miss);
  887 #endif  /* COUNTERS */
  888                         outb(nic+ISR, isr_status);      /* clear interrupt status again */
  889                 }
  890         }
  891         temp_cr=inb(nic+CR);
  892         outb(nic+CR, (temp_cr & 0x3f) | PS0);
  893         outb(nic+IMR, imr_hold);
  894         outb(nic+CR, temp_cr);
  895         return(0);
  896 }
  897 
  898 /*
  899  *  Called if on board buffer has been completely filled by ns8390intr.  It stops
  900  *  the board, reads in all the buffers that are currently in the buffer, and
  901  *  then restart board.
  902  */
  903 ns8390over_write(unit)
  904 int unit;
  905 {
  906         vm_offset_t nic = ns8390_softc[unit].nic;
  907         int     no;
  908         int     count = 0;
  909 
  910         outb(nic+CR, ABR|STP|PS0);        /* clear the receive buffer */
  911         outb(nic+RBCR0, 0);
  912         outb(nic+RBCR1, 0);  
  913         while ((!(inb (nic + ISR) & RST)) && (count < 10000))
  914                 count++;
  915         if (count == 10000) {
  916                 printf("%s%d: over_write(): would not reset.\n",
  917                         ns8390_softc[unit].card, unit);
  918         }
  919         no = ns8390rcv(unit);
  920 #ifdef  OVWBUG
  921         printf("%s%d over_write(): ns8390 OVW ... %d.\n",
  922                 ns8390_softc[unit].card, unit, no);
  923 #endif  /* OVWBUG */
  924         outb(nic+TCR, LB1);               /* External loopback mode */
  925         outb(nic+CR, ABR|STA|PS0);
  926         outb(nic+TCR, 0);
  927         return;
  928 }
  929 
  930 /*
  931  * ns8390rcv:
  932  *
  933  *      This routine is called by the interrupt handler to initiate a
  934  *      packet transfer from the board to the "if" layer above this
  935  *      driver.  This routine checks if a buffer has been successfully
  936  *      received by the ns8390.  If so, it does the actual transfer of the
  937  *      board data (including the ethernet header) into a packet (consisting
  938  *      of an mbuf chain) and enqueues it to a higher level.
  939  *      Then check again whether there are any packets in the receive ring,
  940  *      if so, read the next packet, until there are no more.
  941  *
  942  * input        : number of the board to check
  943  * output       : if a packet is available, it is "sent up"
  944  */
  945 int ns8390rcv(
  946         int unit)
  947 {
  948         register ns8390_softc_t *is = &ns8390_softc[unit];
  949         register struct ifnet   *ifp = &is->ds_if;
  950         vm_offset_t             nic = is->nic;
  951         int                     packets = 0;
  952         struct ether_header     eh;
  953         u_short                 len;
  954         int                     temp_cr;
  955         int                     board_id = is->board_id;
  956         vm_offset_t             hdwbase = ns8390info[unit]->address;
  957         spl_t                   s;
  958 
  959         /* calculation of pkt size */
  960         int nic_overcount;         /* NIC says 1 or 2 more than we need */
  961         int pkt_size;              /* calculated size of received data */
  962         int wrap_size;             /* size of data before wrapping it */
  963         int header_nxtpkt_ptr;     /* NIC's next pkt ptr in rcv header */
  964         int low_byte_count;        /* low byte count of read from rcv header */
  965         int high_byte_count;       /* calculated high byte count */
  966 
  967 
  968         volatile char *sram_nxtpkt_ptr;   /* mem location of next packet */
  969         volatile char *sram_getdata_ptr;  /* next location to be read */
  970         ipc_kmsg_t      new_kmsg;
  971         struct ether_header *ehp;
  972         struct packet_header *pkt;
  973 
  974 
  975 #if     MACH_TTD
  976         if (((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) &&
  977             !kttd_active) {
  978 #else
  979         if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
  980 #endif  /* MACH_TTD */
  981                 temp_cr = inb(nic+CR); /* get current CR value */
  982                 outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
  983                 outb(nic+IMR, 0);      /* Interrupt Mask Register  */
  984                 outb(nic+CR, temp_cr);
  985                 return -1;
  986         }
  987 
  988         while(is->read_nxtpkt_ptr != ns8390get_CURR(unit))   {
  989 
  990                 /* while there is a packet to read from the buffer */
  991 
  992                 if ((is->read_nxtpkt_ptr < is->pstart) ||
  993                     (is->read_nxtpkt_ptr >= is->pstop)) {
  994                         ns8390hwrst(unit);
  995                         return -1;
  996                 }    /* if next packet pointer is out of receive ring bounds */
  997 
  998 #if     MACH_TTD
  999                 if (!kttd_active)
 1000 #endif  /* MACH_TTD */
 1001                 {
 1002                         packets++;
 1003                         ns8390_cntrs[unit].rcv++;
 1004                 }
 1005 
 1006                 sram_nxtpkt_ptr = (char *) (is->sram + (is->read_nxtpkt_ptr << 8));
 1007 
 1008                 /* get packet size and location of next packet */
 1009                 header_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1010                 header_nxtpkt_ptr &= 0xFF;
 1011                 low_byte_count = *(sram_nxtpkt_ptr + 2);
 1012                 low_byte_count &= 0xFF;
 1013 
 1014                 if ((low_byte_count + NIC_HEADER_SIZE) > NIC_PAGE_SIZE)
 1015                         nic_overcount = 2;
 1016                 else
 1017                         nic_overcount = 1;
 1018                 if (header_nxtpkt_ptr > is->read_nxtpkt_ptr) {
 1019                         wrap_size = 0;
 1020                         high_byte_count = header_nxtpkt_ptr - is->read_nxtpkt_ptr -
 1021                             nic_overcount;
 1022                 } else {
 1023                         wrap_size = (int) (is->pstop - is->read_nxtpkt_ptr - nic_overcount);
 1024                         high_byte_count = is->pstop - is->read_nxtpkt_ptr +
 1025                             header_nxtpkt_ptr - is->pstart - nic_overcount;
 1026                 }
 1027                 pkt_size = (high_byte_count << 8) | (low_byte_count & 0xFF);
 1028                 /* does not seem to include NIC_HEADER_SIZE */
 1029                 if (!pkt_size) {
 1030                         printf("%s%d rcv(): zero length.\n",
 1031                                 ns8390_softc[unit].card, unit);
 1032                         goto next_pkt;
 1033                 }
 1034                 len = pkt_size;
 1035 
 1036                 sram_getdata_ptr = sram_nxtpkt_ptr + NIC_HEADER_SIZE;
 1037                 if (board_id & IFWD_SLOT_16BIT) {
 1038 #if     MACH_TTD
 1039                         if (!kttd_active)
 1040 #endif  /* MACH_TTD */
 1041                         { s = splhi(); }
 1042 
 1043                         en_16bit_access(hdwbase, board_id);
 1044                         bcopy16 (sram_getdata_ptr,
 1045                                  &eh,
 1046                                  sizeof(struct ether_header));
 1047                         dis_16bit_access (hdwbase, board_id);
 1048 #if     MACH_TTD
 1049                         if (!kttd_active)
 1050 #endif  /* MACH_TTD */
 1051                         { splx(s); }
 1052 
 1053                 } else {
 1054                         bcopy16 (sram_getdata_ptr,
 1055                                  &eh,
 1056                                  sizeof(struct ether_header));
 1057                 }                   
 1058                 sram_getdata_ptr += sizeof(struct ether_header);
 1059                 len -= (sizeof(struct ether_header) + 4);       /* crc size */
 1060 #if     MACH_TTD
 1061                 if (kttd_active) {
 1062                         new_kmsg = (ipc_kmsg_t)ttd_request_msg;
 1063                 }else
 1064 #endif  /* MACH_TTD */
 1065                 {
 1066                         new_kmsg = net_kmsg_get();
 1067                         if (new_kmsg == IKM_NULL) {
 1068                                 /*
 1069                                  * Drop the packet.
 1070                                  */
 1071                                 is->ds_if.if_rcvdrops++;    
 1072                                 /*
 1073                                  * not only do we want to return, we need to drop
 1074                                  * the packet on the floor to clear the interrupt.
 1075                                  */
 1076                                 ns8390lost_frame(unit);
 1077                                 return packets;
 1078                         }
 1079                 }
 1080 
 1081 #if     DEBUG_TTD
 1082                 dump_ether_header("ns8390wire",&eh);
 1083 #endif  /* DEBUG_TTD */
 1084 
 1085                 ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]);
 1086                 pkt = (struct packet_header *) (&net_kmsg(new_kmsg)->packet[0]);
 1087 
 1088 #if     DEBUG_TTD
 1089                 printf("!ehp = 0x%x, pkt = 0x%x!",ehp, pkt);
 1090 #endif  /* DEBUG_TTD */
 1091 
 1092                 *ehp = eh;
 1093                 if (len >
 1094                     (wrap_size = (is->sram + (is->pstop << 8) - sram_getdata_ptr))) {
 1095                         /* if needs to wrap */
 1096                         if (board_id & IFWD_SLOT_16BIT) {
 1097 #if     MACH_TTD
 1098                                 if (!kttd_active)
 1099 #endif  /* MACH_TTD */
 1100                                 { s = splhi(); }
 1101 
 1102                                 en_16bit_access(hdwbase, board_id);
 1103                                 bcopy16 (sram_getdata_ptr, (char *) (pkt + 1),
 1104                                          wrap_size);
 1105                                 dis_16bit_access (hdwbase, board_id);
 1106 #if     MACH_TTD
 1107                                 if (!kttd_active)
 1108 #endif  /* MACH_TTD */
 1109                                 { splx(s); }
 1110                         } else {
 1111                                 bcopy (sram_getdata_ptr, (char *) (pkt + 1),
 1112                                        wrap_size);
 1113                         }
 1114                         sram_getdata_ptr = (volatile char *)
 1115                             (is->sram + (is->pstart << 8));
 1116                 } else {   /* normal getting data from buffer */
 1117                         wrap_size = 0;
 1118                 }
 1119                 if (board_id & IFWD_SLOT_16BIT) {
 1120 #if     MACH_TTD
 1121                         if (!kttd_active)
 1122 #endif  /* MACH_TTD */
 1123                         { s = splhi(); }
 1124                         en_16bit_access(hdwbase, board_id);
 1125                         bcopy16 (sram_getdata_ptr,
 1126                                  (char *) (pkt + 1) + wrap_size,
 1127                                  len - wrap_size);
 1128                         dis_16bit_access (hdwbase, board_id);
 1129 #if     MACH_TTD
 1130                         if (!kttd_active)
 1131 #endif  /* MACH_TTD */
 1132                         { splx(s); }
 1133                 } else {
 1134                         bcopy (sram_getdata_ptr,
 1135                                (char *) (pkt + 1) + wrap_size,
 1136                                len - wrap_size);
 1137                 }
 1138 
 1139                 pkt->type = ehp->ether_type;
 1140                 pkt->length = len + sizeof(struct packet_header);
 1141 
 1142 #if     MACH_TTD
 1143                 /*
 1144                  * Don't want to call net_packet if we are polling
 1145                  * for a packet.
 1146                  */
 1147                 if (!kttd_active)
 1148 #endif  /* MACH_TTD */
 1149                 {
 1150                         /*
 1151                          * Hand the packet to the network module.
 1152                          */
 1153                         net_packet(ifp, new_kmsg, pkt->length,
 1154                                    ethernet_priority(new_kmsg));
 1155                 }
 1156 
 1157 
 1158 next_pkt:
 1159                 is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1160                 is->read_nxtpkt_ptr &= 0xFF;
 1161 
 1162 #if     MACH_TTD
 1163                 if (!kttd_active)
 1164 #endif  /* MACH_TTD */
 1165                 {
 1166                         temp_cr = inb(nic+CR);
 1167                         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1168                 }
 1169 
 1170                 if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
 1171                         if (is->read_nxtpkt_ptr == is->pstart)
 1172                                 outb(nic+BNDY, is->pstop - 1);
 1173                         else
 1174                                 outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
 1175                 else
 1176                         outb(nic+BNDY, is->read_nxtpkt_ptr);
 1177 
 1178 #if     MACH_TTD
 1179                 if (!kttd_active)
 1180 #endif  /* MACH_TTD */
 1181                 { outb(nic+CR, temp_cr); }
 1182 
 1183 #if     MACH_TTD
 1184                 /*
 1185                  * Hand the packet back to the TTD server, if active.
 1186                  */
 1187                 if (kttd_active && pkt_size)
 1188                         return 1;
 1189 #endif  /* MACH_TTD */
 1190 
 1191 
 1192         }
 1193         return packets;
 1194 
 1195 }
 1196 
 1197 #if     MACH_TTD
 1198 /*
 1199  * Polling routines for the TTD debugger.
 1200  */
 1201 int ns8390poll_receive(unit)
 1202         int     unit;
 1203 {
 1204         int s;
 1205         int orig_cr;
 1206         int orig_imr;
 1207         int isr_status;
 1208         int pkts;
 1209         
 1210         ttd_poll_loop = TRUE;
 1211 
 1212         
 1213         /*
 1214          * Should already in at splhigh.  Is this necessary? XXX
 1215          */
 1216         s = splhigh();
 1217 
 1218 #if     0
 1219         if (kttd_debug)
 1220                 printf("ns8390poll_receive: beginning polling loop\n");
 1221 #endif  /* DEBUG_TTD */
 1222 
 1223         /*
 1224          * Loop until packet arrives.
 1225          */
 1226         while(ttd_poll_loop) {
 1227 
 1228                 /*
 1229                  * Call intr routine
 1230                  */
 1231 
 1232                 ns8390intr(unit);
 1233         }
 1234 
 1235 #if     0
 1236         if (kttd_debug)
 1237                 printf("ns8390poll_receive: got packet exiting loop\n");
 1238 #endif  /* DEBUG_TTD */
 1239 
 1240         splx(s);
 1241 }
 1242 
 1243 int ns8390transmit_ttd(unit, packet, len)
 1244         int unit;
 1245         char * packet;
 1246         int len;
 1247 {
 1248         ns8390_softc_t  *is = &ns8390_softc[unit];
 1249         vm_offset_t     nic = is->nic;
 1250         u_short         count = 0;      /* amount of data already copied */
 1251         volatile char   *sram_write_pkt;
 1252         int             board_id = is->board_id;
 1253         caddr_t         hdwbase = ns8390info[unit]->address;
 1254         int             s;
 1255         int             orig_cr;
 1256         int             orig_imr;
 1257         int             isr_status;
 1258         boolean_t       loop = TRUE;
 1259 
 1260 #if     0
 1261         dump_ipudpbootp("Beg of xmit",packet);
 1262 #endif
 1263 
 1264         s = splhigh();
 1265 
 1266         /* begining of physical address of transmition buffer */
 1267 
 1268         sram_write_pkt = is->sram + is->tpsr * 0x100; 
 1269 
 1270         count = len;
 1271         if (board_id & IFWD_SLOT_16BIT) {
 1272                 en_16bit_access(hdwbase, board_id);
 1273                 bcopy16 (packet, sram_write_pkt,  count);
 1274                 dis_16bit_access (hdwbase, board_id);
 1275         } else {
 1276                 bcopy (packet, sram_write_pkt,  count);
 1277         }
 1278 
 1279         while (count < ETHERMIN+sizeof(struct ether_header)) {
 1280                 *(sram_write_pkt + count) = 0;
 1281                 count++;
 1282         }
 1283         outb(nic+CR, ABR|STA|PS0);              /* select page 0 */
 1284         outb(nic+TPSR, is->tpsr);               /* xmt page start at 0 of RAM */
 1285         outb(nic+TBCR1, count >> 8);            /* upper byte of count */
 1286         outb(nic+TBCR0, count & 0xFF);          /* lower byte of count */
 1287         outb(nic+CR, TXP|ABR|STA);              /* start transmission */
 1288 
 1289         ns8390intr(unit);
 1290 
 1291         splx(s);
 1292 }
 1293 #endif  /* MACH_TTD */
 1294 
 1295 
 1296 /*
 1297  *  ns8390lost_frame:
 1298  *  this routine called by ns8390read after memory for mbufs could not be
 1299  *  allocated.  It sets the boundary pointers and registers to the next
 1300  *  packet location.
 1301  */
 1302 
 1303 ns8390lost_frame(unit)
 1304 int unit;
 1305 {
 1306         ns8390_softc_t  *is = &ns8390_softc[unit];
 1307         vm_offset_t     nic = is->nic;
 1308         volatile char   *sram_nxtpkt_ptr;
 1309         int             temp_cr;
 1310 
 1311         sram_nxtpkt_ptr = (volatile char *) (is->sram +
 1312             (is->read_nxtpkt_ptr << 8));
 1313 
 1314         is->read_nxtpkt_ptr = *(sram_nxtpkt_ptr + 1);
 1315         is->read_nxtpkt_ptr &= 0xFF;
 1316 
 1317         temp_cr = inb(nic+CR);
 1318         outb(nic+CR, (temp_cr & 0x3f) | PS0);
 1319 
 1320         /* update boundary register */
 1321         if (is->read_nxtpkt_ptr == ns8390get_CURR(unit))
 1322                 if (is->read_nxtpkt_ptr == is->pstart)
 1323                         outb(nic+BNDY, is->pstop - 1);
 1324                 else
 1325                         outb(nic+BNDY, is->read_nxtpkt_ptr - 1);
 1326         else
 1327                 outb(nic+BNDY, is->read_nxtpkt_ptr);
 1328 
 1329         outb(nic+CR, temp_cr);
 1330 
 1331         return;
 1332 }
 1333 
 1334 /*
 1335  * ns8390get_CURR():
 1336  *
 1337  * Returns the value of the register CURR, which points to the next
 1338  * available space for NIC to receive from network unto receive ring.
 1339  *
 1340  */
 1341 
 1342 int
 1343 ns8390get_CURR(unit)
 1344 int unit;
 1345 {
 1346         vm_offset_t nic = ns8390_softc[unit].nic;
 1347         int     temp_cr;
 1348         int     ret_val;
 1349         spl_t   s;
 1350   
 1351         s = SPLNET();
 1352 
 1353         temp_cr = inb(nic+CR);                  /* get current CR value */
 1354         outb(nic+CR, ((temp_cr & 0x3F) | PS1)); /* select page 1 registers */
 1355         ret_val = inb(nic+CURR);                /* read CURR value */
 1356         outb(nic+CR, temp_cr);
 1357         splx(s);
 1358         return (ret_val & 0xFF);
 1359 }
 1360 
 1361 /*
 1362  * ns8390xmt:
 1363  *
 1364  *      This routine fills in the appropriate registers and memory
 1365  *      locations on the ns8390 board and starts the board off on
 1366  *      the transmit.
 1367  *
 1368  * input        : board number of interest, and a pointer to the mbuf
 1369  * output       : board memory and registers are set for xfer and attention
 1370  *
 1371  */
 1372 
 1373 ns8390xmt(unit, m)
 1374 int     unit;
 1375 io_req_t        m;
 1376 {
 1377         ns8390_softc_t          *is = &ns8390_softc[unit];
 1378         vm_offset_t             nic = is->nic;
 1379         u_short                 count = 0;      /* amount of data already copied */
 1380         volatile char           *sram_write_pkt;
 1381         int                     board_id = is->board_id;
 1382         vm_offset_t             hdwbase = ns8390info[unit]->address;
 1383         spl_t     s;
 1384 
 1385         /* begining of physical address of transmition buffer */
 1386 
 1387         sram_write_pkt = is->sram + is->tpsr * 0x100; 
 1388 
 1389         count = m->io_count;
 1390         if (board_id & IFWD_SLOT_16BIT) {
 1391                 s = splhi();
 1392                 en_16bit_access(hdwbase, board_id);
 1393                 bcopy16 (m->io_data, sram_write_pkt,  count);
 1394                 dis_16bit_access (hdwbase, board_id);
 1395                 splx(s);
 1396         } else {
 1397                 bcopy (m->io_data, sram_write_pkt,  count);
 1398         }
 1399         while (count < ETHERMIN+sizeof(struct ether_header)) {
 1400                 *(sram_write_pkt + count) = 0;
 1401                 count++;
 1402         }
 1403         outb(nic+CR, ABR|STA|PS0);              /* select page 0 */
 1404         outb(nic+TPSR, is->tpsr);               /* xmt page start at 0 of RAM */
 1405         outb(nic+TBCR1, count >> 8);            /* upper byte of count */
 1406         outb(nic+TBCR0, count & 0xFF);          /* lower byte of count */
 1407         outb(nic+CR, TXP|ABR|STA);              /* start transmission */
 1408 
 1409         iodone(m);
 1410 }
 1411 
 1412 config_nic(unit)
 1413 int unit;
 1414 {
 1415         ns8390_softc_t *is = &ns8390_softc[unit];
 1416         vm_offset_t nic = is->nic;
 1417         int       i;
 1418         int       temp;
 1419         int       count = 0;
 1420         spl_t     s;
 1421 
 1422         outb (nic+CR, PS0|ABR|STP);             /* soft reset and page 0 */
 1423         while ((!(inb (nic + ISR) & RST)) && (count < 10000))
 1424                 count++;
 1425         if (count == 10000) {
 1426                 printf("%s%d: config_nic(): would not reset.\n",
 1427                         ns8390_softc[unit].card, unit);
 1428         }
 1429 
 1430         temp = ((is->fifo_depth & 0x0c) << 3) | BMS;    /* fifo depth | not loopback */
 1431         if (is->board_id & IFWD_SLOT_16BIT)
 1432                 temp |= WTS;                    /* word xfer select (16 bit cards ) */
 1433         outb (nic+DCR, temp);
 1434         outb (nic+TCR, 0);
 1435         outb (nic+RCR, MON);                    /* receive configuration register */
 1436         outb (nic+PSTART, is->pstart);          /* recieve ring starts 2k into RAM */
 1437         outb (nic+PSTOP, is->pstop);            /* stop at last RAM buffer rcv location */
 1438         outb (nic+BNDY, is->pstart);            /* boundary pointer for page 0 */
 1439         s = SPLNET();
 1440 
 1441         outb (nic+CR, PS1|ABR|STP);             /* maintain rst | sel page 1 */
 1442         is->read_nxtpkt_ptr = is->pstart + 1;   /* internal next packet pointer */
 1443         outb (nic+CURR, is->read_nxtpkt_ptr);   /* Current page register */
 1444         for(i=0; i<ETHER_ADDR_SIZE; i++)
 1445                 outb (nic+PAR0+i, is->address[i]);
 1446         for(i=0; i<8; i++)
 1447                 outb (nic+MAR0+i, 0);
 1448 
 1449         outb (nic+CR, PS0|STP|ABR);
 1450         splx(s);
 1451         outb (nic+ISR, 0xff);                   /* clear all interrupt status bits */
 1452         outb (nic+IMR, imr_hold);               /* Enable interrupts */
 1453         outb (nic+RBCR0, 0);                    /* clear remote byte count */
 1454         outb (nic+RBCR1, 0);
 1455 
 1456         outb (nic+CR, PS0|STA|ABR);             /* start NIC | select page 0 */
 1457         outb (nic+RCR, AB);                     /* receive configuration register */
 1458 
 1459         return TRUE;
 1460 }
 1461 
 1462 /*
 1463  * config_ns8390:
 1464  *
 1465  *      This routine does a standard config of a wd8003 family board, with
 1466  *      the proper modifications to different boards within this family.
 1467  *
 1468  */
 1469 config_wd8003(unit)
 1470 int     unit;
 1471 {
 1472         ns8390_softc_t *is = &ns8390_softc[unit];
 1473         vm_offset_t   hdwbase = ns8390info[unit]->address;
 1474         int       RAMsize;
 1475         volatile char  *RAMbase;
 1476         int       addr_temp;
 1477 
 1478         is->tpsr = 0;                   /* transmit page start hold */
 1479         is->pstart = 0x06;              /* receive page start hold */
 1480         is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
 1481         is->fifo_depth = 0x08;          /* NIC fifo threshold */
 1482         switch (is->board_id & IFWD_RAM_SIZE_MASK) {
 1483               case IFWD_RAM_SIZE_8K:  
 1484                 RAMsize =  0x2000;      break;
 1485               case IFWD_RAM_SIZE_16K: 
 1486                 RAMsize =  0x4000;      break;
 1487               case IFWD_RAM_SIZE_32K: 
 1488                 RAMsize =  0x8000;      break;
 1489               case IFWD_RAM_SIZE_64K: 
 1490                 RAMsize = 0x10000;      break;
 1491               default:           
 1492                 RAMsize =  0x2000;      break;
 1493         }
 1494         is->pstop = (((int)RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
 1495         RAMbase = (volatile char *)ns8390info[unit]->phys_address;
 1496         addr_temp = ((int)(RAMbase) >> 13) & 0x3f; /* convert to be written to MSR */
 1497         outb(hdwbase+IFWD_MSR, addr_temp | IFWD_MENB); /* initialize MSR */
 1498         /* enable 16 bit access from lan controller */
 1499         if (is->board_id & IFWD_SLOT_16BIT) {
 1500                 if (is->board_id & IFWD_INTERFACE_CHIP) {
 1501                         outb(hdwbase+IFWD_REG_5,
 1502                              (inb(hdwbase + IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
 1503                              IFWD_LAN16ENB);
 1504                 } else {
 1505                         outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
 1506                 }
 1507         }
 1508         /*
 1509           outb(hdwbase+LAAR, LAN16ENB | LA19| MEM16ENB | SOFTINT);
 1510           */
 1511         
 1512         return TRUE;
 1513 }
 1514 
 1515 /*
 1516  * config_ns8390:
 1517  *
 1518  *      This routine does a standard config of a 3 com etherlink II board.
 1519  *
 1520  */
 1521 config_3c503(unit)
 1522 int     unit;
 1523 {
 1524         ns8390_softc_t  *is = &ns8390_softc[unit];
 1525         struct bus_device       *dev = ns8390info[unit];
 1526         vm_offset_t             hdwbase = dev->address;
 1527         int             RAMsize = dev->am;
 1528         int             i;
 1529 
 1530         is->tpsr =   0x20;              /* transmit page start hold */
 1531         is->sram = (char *)phystokv(dev->phys_address) - is->tpsr * 0x100;
 1532                                         /* When NIC says page 20, this means go to
 1533                                            the beginning of the sram range */
 1534         is->pstart = 0x26;              /* receive page start hold */
 1535         is->read_nxtpkt_ptr = is->pstart + 1; /* internal next packet pointer */
 1536         is->fifo_depth = 0x08;          /* NIC fifo threshold */
 1537         is->pstop = is->tpsr + ((RAMsize >> 8) & 0x0ff);      /* rcv page stop hold */
 1538 
 1539         outb(hdwbase+CTLR, CTLR_RST|CTLR_THIN);
 1540         outb(hdwbase+CTLR, CTLR_THIN);
 1541         outb(hdwbase+CTLR, CTLR_STA_ADDR|CTLR_THIN);
 1542         for (i = 0; i < 6; i++)
 1543                 is->address[i] = inb(hdwbase+i);
 1544         outb(hdwbase+CTLR, elii_bnc[is->board_id]?CTLR_THIN:CTLR_THICK);
 1545         outb(hdwbase+PSTR, is->pstart);
 1546         outb(hdwbase+PSPR, is->pstop);
 1547         outb(hdwbase+IDCFR, IDCFR_IRQ2 << (elii_irq[is->board_id] - 2));
 1548         outb(hdwbase+GACFR, GACFR_TCM|GACFR_8K);
 1549         /* BCFR & PCRFR ro */
 1550         /* STREG ro & dma */
 1551         outb(hdwbase+DQTR, 0);
 1552         outb(hdwbase+DAMSB, 0);
 1553         outb(hdwbase+DALSB, 0);
 1554         outb(hdwbase+VPTR2, 0);
 1555         outb(hdwbase+VPTR1, 0);
 1556         outb(hdwbase+VPTR0, 0);
 1557         outb(hdwbase+RFMSB, 0);
 1558         outb(hdwbase+RFLSB, 0);
 1559         return TRUE;
 1560 }
 1561 
 1562 /*
 1563  * ns8390intoff:
 1564  *
 1565  *      This function turns interrupts off for the ns8390 board indicated.
 1566  *
 1567  */
 1568 
 1569 ns8390intoff(unit)
 1570 int unit;
 1571 {
 1572         vm_offset_t nic = ns8390_softc[unit].nic;
 1573         int     temp_cr = inb(nic+CR);                  /* get current CR value */
 1574 
 1575         outb(nic+CR,((temp_cr & 0x3F)|PS0|STP));
 1576         outb(nic+IMR, 0);                       /* Interrupt Mask Register  */
 1577         outb(nic+CR, temp_cr|STP);
 1578 
 1579 }
 1580 
 1581 /*
 1582  *   wd80xxget_board_id:
 1583  *
 1584  *   determine which board is being used.
 1585  *   Currently supports:
 1586  *    wd8003E (tested)
 1587  *    wd8003EBT
 1588  *    wd8003EP (tested)
 1589  *    wd8013EP (tested)
 1590  *
 1591  */
 1592 wd80xxget_board_id(dev)
 1593 struct bus_device       *dev;
 1594 {
 1595         vm_offset_t    hdwbase = dev->address;
 1596         long           unit = dev->unit;
 1597         long           board_id = 0;
 1598         int            reg_temp;
 1599         int            rev_num;                 /* revision number */
 1600         int            ram_flag;
 1601         int            i;
 1602         boolean_t      register_aliasing;
 1603 
 1604         rev_num = (inb(hdwbase + IFWD_BOARD_ID) & IFWD_BOARD_REV_MASK) >> 1;
 1605         printf("%s%d: ", ns8390_softc[unit].card, unit);
 1606         
 1607         if (rev_num == 0) {
 1608                 printf("rev 0x00\n");
 1609                 /* It must be 8000 board */
 1610                 return 0;
 1611         }
 1612         
 1613         /* Check if register aliasing is true, that is reading from register
 1614            offsets 0-7 will return the contents of register offsets 8-f */
 1615         
 1616         register_aliasing = TRUE;
 1617         for (i = 1; i < 5; i++) {
 1618                 if (inb(hdwbase + IFWD_REG_0 + i) !=
 1619                     inb(hdwbase + IFWD_LAR_0 + i))
 1620                     register_aliasing = FALSE;
 1621         }
 1622         if (inb(hdwbase + IFWD_REG_7) != inb(hdwbase + IFWD_CHKSUM))
 1623             register_aliasing = FALSE;
 1624         
 1625         
 1626         if (register_aliasing == FALSE) {
 1627                 /* Check if board has interface chip */
 1628                 
 1629                 reg_temp = inb(hdwbase + IFWD_REG_7);   /* save old */
 1630                 outb(hdwbase + IFWD_REG_7, 0x35);       /* write value */
 1631                 inb(hdwbase + IFWD_REG_0);              /* dummy read */
 1632                 if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x35) {
 1633                         outb(hdwbase + IFWD_REG_7, 0x3a);/* Try another value*/
 1634                         inb(hdwbase + IFWD_REG_0);      /* dummy read */
 1635                         if ((inb(hdwbase + IFWD_REG_7) & 0xff) == 0x3a) {
 1636                                 board_id |= IFWD_INTERFACE_CHIP;
 1637                                 outb(hdwbase + IFWD_REG_7, reg_temp);
 1638                                 /* restore old value */
 1639                         }
 1640                 }
 1641                 
 1642                 /* Check if board is 16 bit by testing if bit zero in
 1643                    register 1 is unchangeable by software. If so then
 1644                    card has 16 bit capability */
 1645                 reg_temp = inb(hdwbase + IFWD_REG_1);
 1646                 outb(hdwbase + IFWD_REG_1, reg_temp ^ IFWD_16BIT);
 1647                 inb(hdwbase + IFWD_REG_0);                   /* dummy read */
 1648                 if ((inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) ==
 1649                     (reg_temp & IFWD_16BIT)) {        /* Is bit unchanged */
 1650                         board_id |= IFWD_BOARD_16BIT; /* Yes == 16 bit */
 1651                         reg_temp &= 0xfe;             /* For 16 bit board
 1652                                                          always reset bit 0 */
 1653                 }
 1654                 outb(hdwbase + IFWD_REG_1, reg_temp);    /* write value back */
 1655                 
 1656                 /* Test if 16 bit card is in 16 bit slot by reading bit zero in
 1657                    register 1. */
 1658                 if (board_id & IFWD_BOARD_16BIT) {
 1659                         if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
 1660                                 board_id |= IFWD_SLOT_16BIT;
 1661                         }
 1662                 }
 1663         }
 1664         
 1665         /* Get media type */
 1666         
 1667         if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEDIA_TYPE) {
 1668                 board_id |= IFWD_ETHERNET_MEDIA;
 1669         } else if (rev_num == 1) {
 1670                 board_id |= IFWD_STARLAN_MEDIA;
 1671         } else {
 1672                 board_id |= IFWD_TWISTED_PAIR_MEDIA;
 1673         }
 1674 
 1675         if (rev_num == 2) {
 1676                 if (inb(hdwbase + IFWD_BOARD_ID) & IFWD_SOFT_CONFIG) {
 1677                         if ((board_id & IFWD_STATIC_ID_MASK) == WD8003EB ||
 1678                             (board_id & IFWD_STATIC_ID_MASK) == WD8003W) {
 1679                                 board_id |= IFWD_ALTERNATE_IRQ_BIT;
 1680                         }
 1681                 }
 1682                 /* Check for memory size */
 1683                 
 1684                 ram_flag = inb(hdwbase + IFWD_BOARD_ID) & IFWD_MEMSIZE;
 1685             
 1686                 switch (board_id & IFWD_STATIC_ID_MASK) {
 1687                       case WD8003E: /* same as WD8003EBT */
 1688                       case WD8003S: /* same as WD8003SH */
 1689                       case WD8003WT:
 1690                       case WD8003W:
 1691                       case WD8003EB: /* same as WD8003EP */
 1692                         if (ram_flag)
 1693                             board_id |= IFWD_RAM_SIZE_32K;
 1694                         else
 1695                             board_id |= IFWD_RAM_SIZE_8K;
 1696                         break;
 1697                       case WD8003ETA:
 1698                       case WD8003STA:
 1699                       case WD8003EA:
 1700                       case WD8003SHA:
 1701                       case WD8003WA:
 1702                         board_id |= IFWD_RAM_SIZE_16K;
 1703                         break;
 1704                       case WD8013EBT:
 1705                         if (board_id & IFWD_SLOT_16BIT) {
 1706                                 if (ram_flag)
 1707                                     board_id |= IFWD_RAM_SIZE_64K;
 1708                                 else
 1709                                     board_id |= IFWD_RAM_SIZE_16K;
 1710                         } else {
 1711                                 if (ram_flag)
 1712                                     board_id |= IFWD_RAM_SIZE_32K;
 1713                                 else
 1714                                     board_id |= IFWD_RAM_SIZE_8K;
 1715                         }
 1716                         break;
 1717                       default:
 1718                         board_id |= IFWD_RAM_SIZE_UNKNOWN;
 1719                         break;
 1720                 }
 1721         } else if (rev_num >= 3) {
 1722                 board_id &= (long) ~IFWD_MEDIA_MASK;   /* remove media info */
 1723                 board_id |= IFWD_INTERFACE_584_CHIP;
 1724                 board_id |= wd80xxget_eeprom_info(hdwbase, board_id);
 1725         } else {
 1726                 /* Check for memory size */
 1727                 if (board_id & IFWD_BOARD_16BIT) {
 1728                         if (board_id & IFWD_SLOT_16BIT)
 1729                             board_id |= IFWD_RAM_SIZE_16K;
 1730                         else
 1731                             board_id |= IFWD_RAM_SIZE_8K;
 1732                 } else if (board_id & IFWD_MICROCHANNEL)
 1733                     board_id |= IFWD_RAM_SIZE_16K;
 1734                 else if (board_id & IFWD_INTERFACE_CHIP) {
 1735                         if (inb(hdwbase + IFWD_REG_1) & IFWD_MEMSIZE)
 1736                             board_id |= IFWD_RAM_SIZE_32K;
 1737                         else
 1738                             board_id |= IFWD_RAM_SIZE_8K;
 1739                 } else
 1740                     board_id |= IFWD_RAM_SIZE_UNKNOWN;
 1741                 
 1742                 /* No support for 690 chip yet. It should be checked here */
 1743         }
 1744         
 1745         switch (board_id & IFWD_STATIC_ID_MASK) {
 1746               case WD8003E: printf("WD8003E or WD8003EBT"); break;
 1747               case WD8003S: printf("WD8003S or WD8003SH"); break;
 1748               case WD8003WT: printf("WD8003WT"); break;
 1749               case WD8003W: printf("WD8003W"); break;
 1750               case WD8003EB:
 1751                 if (board_id & IFWD_INTERFACE_584_CHIP)
 1752                     printf("WD8003EP");
 1753                 else
 1754                     printf("WD8003EB");
 1755                 break;
 1756               case WD8003EW: printf("WD8003EW"); break;
 1757               case WD8003ETA: printf("WD8003ETA"); break;
 1758               case WD8003STA: printf("WD8003STA"); break;
 1759               case WD8003EA: printf("WD8003EA"); break;
 1760               case WD8003SHA: printf("WD8003SHA"); break;
 1761               case WD8003WA: printf("WD8003WA"); break;
 1762               case WD8013EBT: printf("WD8013EBT"); break;
 1763               case WD8013EB:
 1764                 if (board_id & IFWD_INTERFACE_584_CHIP)
 1765                     printf("WD8013EP");
 1766                 else
 1767                     printf("WD8013EB");
 1768                 break;
 1769               case WD8013W: printf("WD8013W"); break;
 1770               case WD8013EW: printf("WD8013EW"); break;
 1771               default: printf("unknown"); break;
 1772         }
 1773         printf(" rev 0x%02x", rev_num);
 1774         switch(board_id & IFWD_RAM_SIZE_RES_7) {
 1775               case IFWD_RAM_SIZE_UNKNOWN:
 1776                 break;
 1777               case IFWD_RAM_SIZE_8K:
 1778                 printf(" 8 kB ram");
 1779                 break;
 1780               case IFWD_RAM_SIZE_16K:
 1781                 printf(" 16 kB ram");
 1782                 break;
 1783               case IFWD_RAM_SIZE_32K:
 1784                 printf(" 32 kB ram");
 1785                 break;
 1786               case IFWD_RAM_SIZE_64K:
 1787                 printf(" 64 kB ram");
 1788                 break;
 1789               default:
 1790                 printf("wd: Internal error ram size value invalid %d\n",
 1791                        (board_id & IFWD_RAM_SIZE_RES_7)>>16);
 1792         }
 1793         
 1794         if (board_id & IFWD_BOARD_16BIT) {
 1795                 if (board_id & IFWD_SLOT_16BIT) {
 1796                         printf(", in 16 bit slot");
 1797                 } else {
 1798                         printf(", 16 bit board in 8 bit slot");
 1799                 }
 1800         }
 1801         if (board_id & IFWD_INTERFACE_CHIP) {
 1802                 if (board_id & IFWD_INTERFACE_584_CHIP) {
 1803                         printf(", 584 chip");
 1804                 } else {
 1805                         printf(", 583 chip");
 1806                 }
 1807         }
 1808         if ((board_id & IFWD_INTERFACE_CHIP) == IFWD_INTERFACE_CHIP) {
 1809                 /* program the WD83C583 EEPROM registers */
 1810                 int irr_temp, icr_temp;
 1811                 
 1812                 icr_temp = inb(hdwbase + IFWD_ICR);
 1813                 irr_temp = inb(hdwbase + IFWD_IRR);
 1814                 
 1815                 irr_temp &= ~(IFWD_IR0 | IFWD_IR1);
 1816                 irr_temp |= IFWD_IEN;
 1817                 
 1818                 icr_temp &= IFWD_WTS;
 1819                 
 1820                 if (!(board_id & IFWD_INTERFACE_584_CHIP)) {
 1821                         icr_temp |= IFWD_DMAE | IFWD_IOPE;
 1822                         if (ram_flag)
 1823                             icr_temp |= IFWD_MSZ;
 1824                 }
 1825                 
 1826                 if (board_id & IFWD_INTERFACE_584_CHIP) {
 1827                         switch(ns8390info[unit]->sysdep1) {
 1828                               case 10:
 1829                                 icr_temp |= IFWD_DMAE;
 1830                                 break;
 1831                               case 2:
 1832                               case 9: /* Same as 2 */
 1833                                 break;
 1834                               case 11:
 1835                                 icr_temp |= IFWD_DMAE;
 1836                                 /*FALLTHROUGH*/
 1837                               case 3:
 1838                                 irr_temp |= IFWD_IR0;
 1839                                 break;
 1840                               case 15:
 1841                                 icr_temp |= IFWD_DMAE;
 1842                                 /*FALLTHROUGH*/
 1843                               case 5:
 1844                                 irr_temp |= IFWD_IR1;
 1845                                 break;
 1846                               case 4:
 1847                                 icr_temp |= IFWD_DMAE;
 1848                                 /*FALLTHROUGH*/
 1849                               case 7:
 1850                                 irr_temp |= IFWD_IR0 | IFWD_IR1;
 1851                                 break;
 1852                               default:
 1853                                 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
 1854                                        ns8390_softc[unit].card, unit,
 1855                                        ns8390info[unit]->sysdep1);
 1856                                 break;
 1857                         }
 1858                 } else {
 1859                         switch(ns8390info[unit]->sysdep1) {
 1860                                 /* attempt to set interrupt according to assigned pic */
 1861                               case 2:
 1862                               case 9: /* Same as 2 */
 1863                                 break;
 1864                               case 3:
 1865                                 irr_temp |= IFWD_IR0;
 1866                                 break;
 1867                               case 4:
 1868                                 irr_temp |= IFWD_IR1;
 1869                                 break;
 1870                               case 5:
 1871                                 irr_temp |= IFWD_IR1 | IFWD_AINT;
 1872                                 break;
 1873                               case 7: 
 1874                                 irr_temp |= IFWD_IR0 | IFWD_IR1;
 1875                                 break;
 1876                               default: 
 1877                                 printf("%s%d: wd80xx_get_board_id(): Could not set Interrupt Request Register according to pic(%d).\n",
 1878                                        ns8390_softc[unit].card, unit,
 1879                                        ns8390info[unit]->sysdep1);
 1880                         }
 1881                 }
 1882                 outb(hdwbase + IFWD_IRR, irr_temp);
 1883                 outb(hdwbase + IFWD_ICR, icr_temp);
 1884         }
 1885         printf("\n");
 1886         return (board_id);
 1887 }
 1888 
 1889 wd80xxget_eeprom_info(hdwbase, board_id)
 1890      caddr_t    hdwbase;
 1891      long       board_id;
 1892 {
 1893   unsigned long new_bits = 0;
 1894   int           reg_temp;
 1895   
 1896   outb(hdwbase + IFWD_REG_1,
 1897        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
 1898   outb(hdwbase + IFWD_REG_3,
 1899        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_ENGR_PAGE));
 1900   outb(hdwbase + IFWD_REG_1,
 1901        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) |
 1902         (IFWD_RLA | IFWD_OTHER_BIT)));
 1903   while (inb(hdwbase + IFWD_REG_1) & IFWD_RECALL_DONE_MASK)
 1904       ;
 1905   
 1906   reg_temp = inb(hdwbase + IFWD_EEPROM_1);
 1907   switch (reg_temp & IFWD_EEPROM_BUS_TYPE_MASK) {
 1908         case IFWD_EEPROM_BUS_TYPE_AT:
 1909           if (wd_debug & 1) printf("wd: AT bus, ");
 1910           break;
 1911         case IFWD_EEPROM_BUS_TYPE_MCA:
 1912           if (wd_debug & 1) printf("wd: MICROCHANNEL, ");
 1913           new_bits |= IFWD_MICROCHANNEL;
 1914           break;
 1915         default:
 1916           break;
 1917   }
 1918   switch (reg_temp & IFWD_EEPROM_BUS_SIZE_MASK) {
 1919         case IFWD_EEPROM_BUS_SIZE_8BIT:
 1920           if (wd_debug & 1) printf("8 bit bus size, ");
 1921           break;
 1922         case IFWD_EEPROM_BUS_SIZE_16BIT:
 1923           if (wd_debug & 1) printf("16 bit bus size ");
 1924           new_bits |= IFWD_BOARD_16BIT;
 1925           if (inb(hdwbase + IFWD_REG_1) & IFWD_16BIT) {
 1926                   new_bits |= IFWD_SLOT_16BIT;
 1927                   if (wd_debug & 1)
 1928                       printf("in 16 bit slot, ");
 1929           } else {
 1930                   if (wd_debug & 1)
 1931                       printf("in 8 bit slot (why?), ");
 1932           }
 1933           break;
 1934         default:
 1935           if (wd_debug & 1) printf("bus size other than 8 or 16 bit, ");
 1936           break;
 1937   }
 1938   reg_temp = inb(hdwbase + IFWD_EEPROM_0);
 1939   switch (reg_temp & IFWD_EEPROM_MEDIA_MASK) {
 1940         case IFWD_STARLAN_TYPE:
 1941           if (wd_debug & 1) printf("Starlan media, ");
 1942           new_bits |= IFWD_STARLAN_MEDIA;
 1943           break;
 1944         case IFWD_TP_TYPE:
 1945           if (wd_debug & 1) printf("Twisted pair media, ");
 1946           new_bits |= IFWD_TWISTED_PAIR_MEDIA;
 1947           break;
 1948         case IFWD_EW_TYPE:
 1949           if (wd_debug & 1) printf("Ethernet and twisted pair media, ");
 1950           new_bits |= IFWD_EW_MEDIA;
 1951           break;
 1952         case IFWD_ETHERNET_TYPE: /*FALLTHROUGH*/
 1953         default:
 1954           if (wd_debug & 1) printf("ethernet media, ");
 1955           new_bits |= IFWD_ETHERNET_MEDIA;
 1956           break;
 1957   }
 1958   switch (reg_temp & IFWD_EEPROM_IRQ_MASK) {
 1959         case IFWD_ALTERNATE_IRQ_1:
 1960           if (wd_debug & 1) printf("Alternate irq 1\n");
 1961           new_bits |= IFWD_ALTERNATE_IRQ_BIT;
 1962           break;
 1963         default:
 1964           if (wd_debug & 1) printf("\n");
 1965           break;
 1966   }
 1967   switch (reg_temp & IFWD_EEPROM_RAM_SIZE_MASK) {
 1968         case IFWD_EEPROM_RAM_SIZE_8K:
 1969           new_bits |= IFWD_RAM_SIZE_8K;
 1970           break;
 1971         case IFWD_EEPROM_RAM_SIZE_16K:
 1972           if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
 1973               new_bits |= IFWD_RAM_SIZE_16K;
 1974           else
 1975               new_bits |= IFWD_RAM_SIZE_8K;
 1976           break;
 1977         case IFWD_EEPROM_RAM_SIZE_32K:
 1978           new_bits |= IFWD_RAM_SIZE_32K;
 1979           break;
 1980         case IFWD_EEPROM_RAM_SIZE_64K:
 1981           if ((new_bits & IFWD_BOARD_16BIT) && (new_bits & IFWD_SLOT_16BIT))
 1982               new_bits |= IFWD_RAM_SIZE_64K;
 1983           else
 1984               new_bits |= IFWD_RAM_SIZE_32K;
 1985           break;
 1986         default:
 1987           new_bits |= IFWD_RAM_SIZE_UNKNOWN;
 1988           break;
 1989   }
 1990   outb(hdwbase + IFWD_REG_1,
 1991        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_OTHER_BIT));
 1992   outb(hdwbase + IFWD_REG_3,
 1993        ((inb(hdwbase + IFWD_REG_3) & IFWD_EAR_MASK) | IFWD_EA6));
 1994   outb(hdwbase + IFWD_REG_1,
 1995        ((inb(hdwbase + IFWD_REG_1) & IFWD_ICR_MASK) | IFWD_RLA));
 1996   return (new_bits);
 1997 }
 1998 
 1999 wdpr(unit)
 2000 {
 2001         vm_offset_t nic = ns8390_softc[unit].nic;
 2002         spl_t   s;
 2003         int     temp_cr;
 2004 
 2005         s = SPLNET();
 2006         temp_cr = inb(nic);             /* get current CR value */
 2007 
 2008         printf("CR %x, BNDRY %x, TSR %x, NCR %x, FIFO %x, ISR %x, RSR %x\n",
 2009                 inb(nic+0x0), inb(nic+0x3), inb(nic+0x4), inb(nic+0x5),
 2010                 inb(nic+0x6), inb(nic+0x7), inb(nic+0xc));
 2011         printf("CLD %x:%x, CRD %x:%x, FR %x, CRC %x, Miss %x\n",
 2012                 inb(nic+0x1), inb(nic+0x2),
 2013                 inb(nic+0x8), inb(nic+0x9),
 2014                 inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
 2015 
 2016         
 2017         outb(nic, (temp_cr&0x3f)|PS1);          /* page 1 CR value */
 2018         printf("PHYS %x:%x:%x:%x:%x CUR %x\n",
 2019                 inb(nic+0x1), inb(nic+0x2), inb(nic+0x3),
 2020                 inb(nic+0x4), inb(nic+0x5), inb(nic+0x6),
 2021                 inb(nic+0x7));
 2022         printf("MAR %x:%x:%x:%x:%x:%x:%x:%x\n",
 2023                 inb(nic+0x8), inb(nic+0x9), inb(nic+0xa), inb(nic+0xb),
 2024                 inb(nic+0xc), inb(nic+0xd), inb(nic+0xe), inb(nic+0xf));
 2025         outb(nic, temp_cr);                     /* restore current CR value */
 2026         splx(s);
 2027 }
 2028 
 2029 
 2030 /*
 2031   This sets bit 7 (0 justified) of register offset 0x05. It will enable
 2032   the host to access shared RAM 16 bits at a time. It will also maintain
 2033   the LAN16BIT bit high in addition, this routine maintains address bit 19
 2034   (previous cards assumed this bit high...we must do it manually)
 2035   
 2036   note 1: this is a write only register
 2037   note 2: this routine should be called only after interrupts are disabled
 2038     and they should remain disabled until after the routine 'dis_16bit_access'
 2039     is called
 2040 */
 2041 
 2042 en_16bit_access (hdwbase, board_id)
 2043         caddr_t hdwbase;
 2044         long    board_id;
 2045 {
 2046         if (board_id & IFWD_INTERFACE_CHIP)
 2047             outb(hdwbase+IFWD_REG_5,
 2048                  (inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK)
 2049                  | IFWD_MEM16ENB | IFWD_LAN16ENB);
 2050         else
 2051             outb(hdwbase+IFWD_REG_5, (IFWD_MEM16ENB | IFWD_LAN16ENB |
 2052                                       IFWD_LA19));
 2053 }
 2054 
 2055 /*
 2056   This resets bit 7 (0 justified) of register offset 0x05. It will disable
 2057   the host from accessing shared RAM 16 bits at a time. It will maintain the
 2058   LAN16BIT bit high in addition, this routine maintains address bit 19
 2059   (previous cards assumed this bit high...we must do it manually)
 2060 
 2061   note: this is a write only register
 2062 */
 2063 
 2064 dis_16bit_access (hdwbase, board_id)
 2065         caddr_t hdwbase;
 2066         long board_id;
 2067 {
 2068         if (board_id & IFWD_INTERFACE_CHIP)
 2069             outb(hdwbase+IFWD_REG_5,
 2070                  ((inb(hdwbase+IFWD_REG_5) & IFWD_REG5_MEM_MASK) |
 2071                   IFWD_LAN16ENB));
 2072         else
 2073             outb(hdwbase+IFWD_REG_5, (IFWD_LAN16ENB | IFWD_LA19));
 2074 }
 2075 

Cache object: 338c6e9ddb7d83f3a2627f93da32a4ab


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