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/drivers/dp8390/ne2000.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 ne2000.c
    3 
    4 Driver for the ne2000 ethernet cards. This file contains only the ne2000
    5 specific code, the rest is in dp8390.c
    6 
    7 Created:        March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
    8 */
    9 
   10 #include "../drivers.h"
   11 
   12 #include <net/gen/ether.h>
   13 #include <net/gen/eth_io.h>
   14 #if __minix_vmd
   15 #include "config.h"
   16 #endif
   17 
   18 #include "local.h"
   19 #include "dp8390.h"
   20 #include "ne2000.h"
   21 
   22 #if ENABLE_NE2000
   23 
   24 #define N 100
   25 
   26 #define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
   27 
   28 _PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)  );
   29 
   30 u8_t    pat0[]= { 0x00, 0x00, 0x00, 0x00 };
   31 u8_t    pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
   32 u8_t    pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
   33 u8_t    pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
   34 
   35 _PROTOTYPE( static int test_8, (dpeth_t *dep, int pos, u8_t *pat)       );
   36 _PROTOTYPE( static int test_16, (dpeth_t *dep, int pos, u8_t *pat)      );
   37 _PROTOTYPE( static void ne_stop, (dpeth_t *dep)                         );
   38 _PROTOTYPE( static void milli_delay, (unsigned long millis)             );
   39 
   40 /*===========================================================================*
   41  *                              ne_probe                                     *
   42  *===========================================================================*/
   43 int ne_probe(dep)
   44 dpeth_t *dep;
   45 {
   46         int byte;
   47         int i;
   48         int loc1, loc2;
   49         testf_t f;
   50 
   51         dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
   52 
   53         /* We probe for an ne1000 or an ne2000 by testing whether the
   54          * on board is reachable through the dp8390. Note that the
   55          * ne1000 is an 8bit card and has a memory region distict from
   56          * the 16bit ne2000
   57          */
   58 
   59         for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
   60         {
   61                 /* Reset the ethernet card */
   62                 byte= inb_ne(dep, NE_RESET);
   63                 milli_delay(2);
   64                 outb_ne(dep, NE_RESET, byte);
   65                 milli_delay(2);
   66 
   67                 /* Reset the dp8390 */
   68                 outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
   69                 for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
   70                         ; /* Do nothing */
   71 
   72                 /* Check if the dp8390 is really there */
   73                 if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
   74                         (CR_STP|CR_DM_ABORT))
   75                 {
   76                         return 0;
   77                 }
   78 
   79                 /* Disable the receiver and init TCR and DCR. */
   80                 outb_reg0(dep, DP_RCR, RCR_MON);
   81                 outb_reg0(dep, DP_TCR, TCR_NORMAL);
   82                 if (dep->de_16bit)
   83                 {
   84                         outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
   85                                 DCR_BMS);
   86                 }
   87                 else
   88                 {
   89                         outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
   90                                 DCR_BMS);
   91                 }
   92 
   93                 if (dep->de_16bit)
   94                 {
   95                         loc1= NE2000_START;
   96                         loc2= NE2000_START + NE2000_SIZE - 4;
   97                         f= test_16;
   98                 }
   99                 else
  100                 {
  101                         loc1= NE1000_START;
  102                         loc2= NE1000_START + NE1000_SIZE - 4;
  103                         f= test_8;
  104                 }
  105                 if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
  106                         f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
  107                         f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
  108                         f(dep, loc2, pat2) && f(dep, loc2, pat3))
  109                 {
  110                         /* We don't need a memory segment */
  111                         dep->de_linmem= 0;
  112                         if (!dep->de_pci)
  113                                 dep->de_initf= ne_init;
  114                         dep->de_stopf= ne_stop;
  115                         dep->de_prog_IO= 1;
  116                         return 1;
  117                 }
  118         }
  119         return 0;
  120 }
  121 
  122 /*===========================================================================*
  123  *                              ne_init                                      *
  124  *===========================================================================*/
  125 void ne_init(dep)
  126 dpeth_t *dep;
  127 {
  128         int i;
  129         int word, sendq_nr;
  130 
  131         /* Setup a transfer to get the ethernet address. */
  132         if (dep->de_16bit)
  133                 outb_reg0(dep, DP_RBCR0, 6*2);
  134         else
  135                 outb_reg0(dep, DP_RBCR0, 6);
  136         outb_reg0(dep, DP_RBCR1, 0);
  137         outb_reg0(dep, DP_RSAR0, 0);
  138         outb_reg0(dep, DP_RSAR1, 0);
  139         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  140 
  141         for (i= 0; i<6; i++)
  142         {
  143                 if (dep->de_16bit)
  144                 {
  145                         word= inw_ne(dep, NE_DATA);
  146                         dep->de_address.ea_addr[i]= word;
  147                 }
  148                 else
  149                 {
  150                         dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
  151                 }
  152         }
  153         dep->de_data_port= dep->de_base_port + NE_DATA;
  154         if (dep->de_16bit)
  155         {
  156                 dep->de_ramsize= NE2000_SIZE;
  157                 dep->de_offset_page= NE2000_START / DP_PAGESIZE;
  158         }
  159         else
  160         {
  161                 dep->de_ramsize= NE1000_SIZE;
  162                 dep->de_offset_page= NE1000_START / DP_PAGESIZE;
  163         }
  164 
  165         /* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
  166         sendq_nr= dep->de_ramsize / 0x2000;
  167         if (sendq_nr < 1)
  168                 sendq_nr= 1;
  169         else if (sendq_nr > SENDQ_NR)
  170                 sendq_nr= SENDQ_NR;
  171         dep->de_sendq_nr= sendq_nr;
  172         for (i= 0; i<sendq_nr; i++)
  173         {
  174                 dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
  175                         i*SENDQ_PAGES;  
  176         }
  177 
  178         dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
  179         dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
  180 
  181         /* Can't override the default IRQ. */
  182         dep->de_irq &= ~DEI_DEFAULT;
  183 
  184         if (!debug)
  185         {
  186                 printf("%s: NE%d000 at %X:%d\n",
  187                         dep->de_name, dep->de_16bit ? 2 : 1,
  188                         dep->de_base_port, dep->de_irq);
  189         }
  190         else
  191         {
  192                 printf("%s: Novell NE%d000 ethernet card at I/O address "
  193                         "0x%X, memory size 0x%X, irq %d\n",
  194                         dep->de_name, dep->de_16bit ? 2 : 1,
  195                         dep->de_base_port, dep->de_ramsize, dep->de_irq);
  196         }
  197 }
  198 
  199 /*===========================================================================*
  200  *                              test_8                                       *
  201  *===========================================================================*/
  202 static int test_8(dep, pos, pat)
  203 dpeth_t *dep;
  204 int pos;
  205 u8_t *pat;
  206 {
  207         u8_t buf[4];
  208         int i;
  209         int r;
  210 
  211         outb_reg0(dep, DP_ISR, 0xFF);
  212 
  213         /* Setup a transfer to put the pattern. */
  214         outb_reg0(dep, DP_RBCR0, 4);
  215         outb_reg0(dep, DP_RBCR1, 0);
  216         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  217         outb_reg0(dep, DP_RSAR1, pos >> 8);
  218         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  219 
  220         for (i= 0; i<4; i++)
  221                 outb_ne(dep, NE_DATA, pat[i]);
  222 
  223         for (i= 0; i<N; i++)
  224         {
  225                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  226                         break;
  227         }
  228         if (i == N)
  229         {
  230                 if (debug)
  231                 {
  232                         printf("%s: NE1000 remote DMA test failed\n",
  233                                 dep->de_name);
  234                 }
  235                 return 0;
  236         }
  237 
  238         outb_reg0(dep, DP_RBCR0, 4);
  239         outb_reg0(dep, DP_RBCR1, 0);
  240         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  241         outb_reg0(dep, DP_RSAR1, pos >> 8);
  242         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  243 
  244         for (i= 0; i<4; i++)
  245                 buf[i]= inb_ne(dep, NE_DATA);
  246 
  247         r= (memcmp(buf, pat, 4) == 0);
  248         return r;
  249 }
  250 
  251 /*===========================================================================*
  252  *                              test_16                                      *
  253  *===========================================================================*/
  254 static int test_16(dep, pos, pat)
  255 dpeth_t *dep;
  256 int pos;
  257 u8_t *pat;
  258 {
  259         u8_t buf[4];
  260         int i;
  261         int r;
  262 
  263         outb_reg0(dep, DP_ISR, 0xFF);
  264 
  265         /* Setup a transfer to put the pattern. */
  266         outb_reg0(dep, DP_RBCR0, 4);
  267         outb_reg0(dep, DP_RBCR1, 0);
  268         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  269         outb_reg0(dep, DP_RSAR1, pos >> 8);
  270         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  271 
  272         for (i= 0; i<4; i += 2)
  273         {
  274                 outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
  275         }
  276 
  277         for (i= 0; i<N; i++)
  278         {
  279                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  280                         break;
  281         }
  282         if (i == N)
  283         {
  284                 if (debug)
  285                 {
  286                         printf("%s: NE2000 remote DMA test failed\n",
  287                                 dep->de_name);
  288                 }
  289                 return 0;
  290         }
  291 
  292         outb_reg0(dep, DP_RBCR0, 4);
  293         outb_reg0(dep, DP_RBCR1, 0);
  294         outb_reg0(dep, DP_RSAR0, pos & 0xFF);
  295         outb_reg0(dep, DP_RSAR1, pos >> 8);
  296         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  297 
  298         for (i= 0; i<4; i += 2)
  299         {
  300                 *(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
  301         }
  302 
  303         r= (memcmp(buf, pat, 4) == 0);
  304         return r;
  305 }
  306 
  307 /*===========================================================================*
  308  *                              ne_stop                                      *
  309  *===========================================================================*/
  310 static void ne_stop(dep)
  311 dpeth_t *dep;
  312 {
  313         int byte;
  314 
  315         /* Reset the ethernet card */
  316         byte= inb_ne(dep, NE_RESET);
  317         milli_delay(2);
  318         outb_ne(dep, NE_RESET, byte);
  319 }
  320 
  321 static void milli_delay(unsigned long millis)
  322 {
  323         tickdelay(MILLIS_TO_TICKS(millis));
  324 }
  325 
  326 #endif /* ENABLE_NE2000 */
  327 
  328 /*
  329  * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
  330  */

Cache object: 5a8a7f50ee3440723e625b73a88caee1


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