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/rtl8139/rtl8139.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  * rtl8139.c
    3  *
    4  * This file contains a ethernet device driver for Realtek rtl8139 based
    5  * ethernet cards.
    6  *
    7  * The valid messages and their parameters are:
    8  *
    9  *   m_type       DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
   10  * |------------+----------+---------+----------+---------+---------|
   11  * | HARD_INT   |          |         |          |         |         |
   12  * |------------|----------|---------|----------|---------|---------|
   13  * | SYS_SIG    |          |         |          |         |         |
   14  * |------------|----------|---------|----------|---------|---------|
   15  * | DL_WRITE   | port nr  | proc nr | count    | mode    | address |
   16  * |------------|----------|---------|----------|---------|---------|
   17  * | DL_WRITEV  | port nr  | proc nr | count    | mode    | address |
   18  * |------------|----------|---------|----------|---------|---------|
   19  * | DL_READ    | port nr  | proc nr | count    |         | address |
   20  * |------------|----------|---------|----------|---------|---------|
   21  * | DL_READV   | port nr  | proc nr | count    |         | address |
   22  * |------------|----------|---------|----------|---------|---------|
   23  * | DL_INIT    | port nr  | proc nr | mode     |         | address |
   24  * |------------|----------|---------|----------|---------|---------|
   25  * | DL_GETSTAT | port nr  | proc nr |          |         | address |
   26  * |------------|----------|---------|----------|---------|---------|
   27  * | DL_GETNAME |          |         |          |         |         |
   28  * |------------|----------|---------|----------|---------|---------|
   29  * | DL_STOP    | port_nr  |         |          |         |         |
   30  * |------------|----------|---------|----------|---------|---------|
   31  *
   32  * The messages sent are:
   33  *
   34  *   m-type       DL_POR T   DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
   35  * |------------|----------|---------|----------|---------|---------|
   36  * |DL_TASK_REPL| port nr  | proc nr | rd-count | err|stat| clock   |
   37  * |------------|----------|---------|----------|---------|---------|
   38  *
   39  *   m_type       m3_i1     m3_i2       m3_ca1
   40  * |------------+---------+-----------+---------------|
   41  * |DL_INIT_REPL| port nr | last port | ethernet addr |
   42  * |------------|---------|-----------|---------------|
   43  *
   44  * Created:     Aug 2003 by Philip Homburg <philip@cs.vu.nl>
   45  * Changes:
   46  *   Aug 15, 2004   sync alarms replace watchdogs timers  (Jorrit N. Herder)
   47  *   May 02, 2004   flag alarms replace micro_elapsed()  (Jorrit N. Herder)
   48  *
   49  */
   50 
   51 #include "../drivers.h"
   52 
   53 #include <stdlib.h>
   54 #include <stdio.h>
   55 #include <string.h>
   56 #include <stddef.h>
   57 #include <minix/com.h>
   58 #include <minix/keymap.h>
   59 #include <minix/syslib.h>
   60 #include <minix/type.h>
   61 #include <minix/sysutil.h>
   62 #include <timers.h>
   63 #include <ibm/portio.h>
   64 #include <net/hton.h>
   65 #include <net/gen/ether.h>
   66 #include <net/gen/eth_io.h>
   67 
   68 #include <sys/types.h>
   69 #include <fcntl.h>
   70 #include <assert.h>
   71 #include <unistd.h>
   72 #include <sys/ioc_memory.h>
   73 #include "../../kernel/const.h"
   74 #include "../../kernel/config.h"
   75 #include "../../kernel/type.h"
   76 
   77 #define tmra_ut                 timer_t
   78 #define tmra_inittimer(tp)      tmr_inittimer(tp)
   79 #define Proc_number(p)          proc_number(p)
   80 #define debug                   0
   81 #define printW()                ((void)0)
   82 #define vm_1phys2bus(p)         (p)
   83 
   84 #define VERBOSE         0       /* display message during init */
   85 
   86 #include "../libpci/pci.h"
   87 #include "rtl8139.h"
   88 
   89 #define RX_BUFSIZE      RL_RCR_RBLEN_64K_SIZE
   90 #define RX_BUFBITS      RL_RCR_RBLEN_64K
   91 #define N_TX_BUF        RL_N_TX
   92 
   93 #define RE_PORT_NR      1               /* Minix */
   94 
   95 /* I/O vectors are handled IOVEC_NR entries at a time. */
   96 #define IOVEC_NR        16
   97 
   98 /* Configuration */
   99 #define RL_ENVVAR       "RTLETH"
  100 
  101 PRIVATE struct pcitab
  102 {
  103         u16_t vid;
  104         u16_t did;
  105         int checkclass;
  106 } pcitab[]=
  107 {
  108         { 0x10ec, 0x8139, 0 },          /* Realtek RTL8139 */
  109         { 0x1186, 0x1300, 0 },          /* D-Link RTL8139 */
  110 
  111         { 0x0000, 0x0000, 0 }
  112 };
  113 
  114 typedef struct re
  115 {
  116         port_t re_base_port;
  117         int re_irq;
  118         int re_mode;
  119         int re_flags;
  120         int re_client;
  121         int re_link_up;
  122         int re_got_int;
  123         int re_send_int;
  124         int re_report_link;
  125         int re_clear_rx;
  126         int re_need_reset;
  127         int re_tx_alive;
  128         char *re_model;
  129 
  130         /* Rx */
  131         phys_bytes re_rx_buf;
  132         char  *v_re_rx_buf;
  133         vir_bytes re_read_s;
  134 
  135         /* Tx */
  136         int re_tx_head;
  137         int re_tx_tail;
  138         struct
  139         {
  140                 int ret_busy;
  141                 phys_bytes ret_buf;
  142                 char * v_ret_buf;
  143         } re_tx[N_TX_BUF];
  144         u32_t re_ertxth;        /* Early Tx Threshold */
  145 
  146         /* PCI related */
  147         int re_seen;                    /* TRUE iff device available */
  148         u8_t re_pcibus; 
  149         u8_t re_pcidev; 
  150         u8_t re_pcifunc;        
  151 
  152         /* 'large' items */
  153         int re_hook_id;                 /* IRQ hook id at kernel */
  154         eth_stat_t re_stat;
  155         ether_addr_t re_address;
  156         message re_rx_mess;
  157         message re_tx_mess;
  158         char re_name[sizeof("rtl8139#n")];
  159         iovec_t re_iovec[IOVEC_NR];
  160 }
  161 re_t;
  162 
  163 #define REM_DISABLED    0x0
  164 #define REM_ENABLED     0x1
  165 
  166 #define REF_PACK_SENT   0x001
  167 #define REF_PACK_RECV   0x002
  168 #define REF_SEND_AVAIL  0x004
  169 #define REF_READING     0x010
  170 #define REF_EMPTY       0x000
  171 #define REF_PROMISC     0x040
  172 #define REF_MULTI       0x080
  173 #define REF_BROAD       0x100
  174 #define REF_ENABLED     0x200
  175 
  176 static re_t re_table[RE_PORT_NR];
  177 
  178 static u16_t eth_ign_proto;
  179 static tmra_ut rl_watchdog;
  180 
  181 FORWARD _PROTOTYPE( unsigned my_inb, (U16_t port) );
  182 FORWARD _PROTOTYPE( unsigned my_inw, (U16_t port) );
  183 FORWARD _PROTOTYPE( unsigned my_inl, (U16_t port) );
  184 static unsigned my_inb(U16_t port) {
  185         U8_t value;
  186         int s;
  187         if ((s=sys_inb(port, &value)) !=OK)
  188                 printf("RTL8139: warning, sys_inb failed: %d\n", s);
  189         return value;
  190 }
  191 static unsigned my_inw(U16_t port) {
  192         U16_t value;
  193         int s;
  194         if ((s=sys_inw(port, &value)) !=OK)
  195                 printf("RTL8139: warning, sys_inw failed: %d\n", s);
  196         return value;
  197 }
  198 static unsigned my_inl(U16_t port) {
  199         U32_t value;
  200         int s;
  201         if ((s=sys_inl(port, &value)) !=OK)
  202                 printf("RTL8139: warning, sys_inl failed: %d\n", s);
  203         return value;
  204 }
  205 #define rl_inb(port, offset)    (my_inb((port) + (offset)))
  206 #define rl_inw(port, offset)    (my_inw((port) + (offset)))
  207 #define rl_inl(port, offset)    (my_inl((port) + (offset)))
  208 
  209 FORWARD _PROTOTYPE( void my_outb, (U16_t port, U8_t value) );
  210 FORWARD _PROTOTYPE( void my_outw, (U16_t port, U16_t value) );
  211 FORWARD _PROTOTYPE( void my_outl, (U16_t port, U32_t value) );
  212 static void my_outb(U16_t port, U8_t value) {
  213         int s;
  214         if ((s=sys_outb(port, value)) !=OK)
  215                 printf("RTL8139: warning, sys_outb failed: %d\n", s);
  216 }
  217 static void my_outw(U16_t port, U16_t value) {
  218         int s;
  219         if ((s=sys_outw(port, value)) !=OK)
  220                 printf("RTL8139: warning, sys_outw failed: %d\n", s);
  221 }
  222 static void my_outl(U16_t port, U32_t value) {
  223         int s;
  224         if ((s=sys_outl(port, value)) !=OK)
  225                 printf("RTL8139: warning, sys_outl failed: %d\n", s);
  226 }
  227 #define rl_outb(port, offset, value)    (my_outb((port) + (offset), (value)))
  228 #define rl_outw(port, offset, value)    (my_outw((port) + (offset), (value)))
  229 #define rl_outl(port, offset, value)    (my_outl((port) + (offset), (value)))
  230 
  231 _PROTOTYPE( static void rl_init, (message *mp)                          );
  232 _PROTOTYPE( static void rl_pci_conf, (void)                             );
  233 _PROTOTYPE( static int rl_probe, (re_t *rep)                            );
  234 _PROTOTYPE( static void rl_conf_hw, (re_t *rep)                         );
  235 _PROTOTYPE( static void rl_init_buf, (re_t *rep)                                );
  236 _PROTOTYPE( static void rl_init_hw, (re_t *rep)                         );
  237 _PROTOTYPE( static void rl_reset_hw, (re_t *rep)                        );
  238 _PROTOTYPE( static void rl_confaddr, (re_t *rep)                        );
  239 _PROTOTYPE( static void rl_rec_mode, (re_t *rep)                        );
  240 _PROTOTYPE( static void rl_readv, (message *mp, int from_int, 
  241                                                         int vectored)   );
  242 _PROTOTYPE( static void rl_writev, (message *mp, int from_int,
  243                                                         int vectored)   );
  244 _PROTOTYPE( static void rl_check_ints, (re_t *rep)                      );
  245 _PROTOTYPE( static void rl_report_link, (re_t *rep)                     );
  246 _PROTOTYPE( static void mii_print_techab, (U16_t techab)                );
  247 _PROTOTYPE( static void mii_print_stat_speed, (U16_t stat,
  248                                                         U16_t extstat)  );
  249 _PROTOTYPE( static void rl_clear_rx, (re_t *rep)                        );
  250 _PROTOTYPE( static void rl_do_reset, (re_t *rep)                        );
  251 _PROTOTYPE( static void rl_getstat, (message *mp)                       );
  252 _PROTOTYPE( static void rl_getname, (message *mp)                       );
  253 _PROTOTYPE( static void reply, (re_t *rep, int err, int may_block)      );
  254 _PROTOTYPE( static void mess_reply, (message *req, message *reply)      );
  255 _PROTOTYPE( static void put_userdata, (int user_proc,
  256                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  257 _PROTOTYPE( static void rtl8139_stop, (void)                            );
  258 _PROTOTYPE( static void check_int_events, (void)                                );
  259 _PROTOTYPE( static int do_hard_int, (void)                              );
  260 _PROTOTYPE( static void rtl8139_dump, (message *m)                              );
  261 #if 0
  262 _PROTOTYPE( static void dump_phy, (re_t *rep)                           );
  263 #endif
  264 _PROTOTYPE( static int rl_handler, (re_t *rep)                  );
  265 _PROTOTYPE( static void rl_watchdog_f, (timer_t *tp)                    );
  266 
  267 /* The message used in the main loop is made global, so that rl_watchdog_f()
  268  * can change its message type to fake a HARD_INT message.
  269  */
  270 PRIVATE message m;
  271 PRIVATE int int_event_check;            /* set to TRUE if events arrived */
  272 
  273 static char *progname;
  274 extern int errno;
  275 
  276 /*===========================================================================*
  277  *                              main                                 *
  278  *===========================================================================*/
  279 int main(int argc, char *argv[])
  280 {
  281         int fkeys, sfkeys;
  282         int inet_proc_nr;
  283         int i, r;
  284         re_t *rep;
  285         long v;
  286 
  287         env_setargs(argc, argv);
  288 
  289         v= 0;
  290         (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
  291         eth_ign_proto= htons((u16_t) v);
  292 
  293         /* Observe some function key for debug dumps. */
  294         fkeys = sfkeys = 0; bit_set(sfkeys, 9);
  295         if ((r=fkey_map(&fkeys, &sfkeys)) != OK) 
  296             printf("Warning: RTL8139 couldn't observe Shift+F9 key: %d\n",r);
  297 
  298         /* Claim buffer memory now under Minix, before MM takes it all. */
  299         for (rep= &re_table[0]; rep < re_table+RE_PORT_NR; rep++)
  300                 rl_init_buf(rep);
  301 
  302         /* Try to notify INET that we are present (again). If INET cannot
  303          * be found, assume this is the first time we started and INET is
  304          * not yet alive.
  305          */
  306         (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
  307         r = findproc("inet", &inet_proc_nr);
  308         if (r == OK) notify(inet_proc_nr);
  309 
  310 
  311         while (TRUE)
  312         {
  313                 if ((r= receive(ANY, &m)) != OK)
  314                         panic("rtl8139","receive failed", r);
  315 
  316                 switch (m.m_type)
  317                 {
  318                 case DEV_PING: notify(m.m_source);              continue;
  319                 case DL_WRITEV: rl_writev(&m, FALSE, TRUE);     break;
  320                 case DL_WRITE:  rl_writev(&m, FALSE, FALSE);    break;
  321 #if 0
  322                 case DL_READ:   do_vread(&m, FALSE);            break;
  323 #endif
  324                 case DL_READV:  rl_readv(&m, FALSE, TRUE);      break;
  325                 case DL_INIT:   rl_init(&m);                    break;
  326                 case DL_GETSTAT: rl_getstat(&m);                break;
  327                 case DL_GETNAME: rl_getname(&m);                break;
  328 #if 0
  329                 case DL_STOP:   do_stop(&m);                    break;
  330 #endif
  331                 case SYN_ALARM:
  332                         /* Under MINIX, synchronous alarms are used instead of
  333                          * watchdog functions. The approach is very different:
  334                          * MINIX VMD timeouts are handled within the kernel 
  335                          * (the watchdog is executed by CLOCK), and notify()
  336                          * the driver in some cases.
  337                          * MINIX timeouts result in a SYN_ALARM message to the
  338                          * driver and thus are handled where they should be
  339                          * handled. Locally, watchdog functions are used again. 
  340                          */
  341                         rl_watchdog_f(NULL);     
  342                         break;           
  343                 case HARD_INT:
  344                         do_hard_int();
  345                         if (int_event_check)
  346                                 check_int_events();
  347                         break ;
  348                 case FKEY_PRESSED: rtl8139_dump(&m);            break;
  349                 case SYS_SIG: {
  350                         sigset_t sigset = m.NOTIFY_ARG;
  351                         if (sigismember(&sigset, SIGKSTOP)) rtl8139_stop();             
  352                         break;
  353                 }
  354                 default:
  355                         panic("rtl8139","illegal message", m.m_type);
  356                 }
  357         }
  358 }
  359 
  360 static void check_int_events(void) 
  361 {
  362   int i;
  363   re_t *rep;
  364                         for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
  365                         {
  366                                 if (rep->re_mode != REM_ENABLED)
  367                                         continue;
  368                                 if (!rep->re_got_int)
  369                                         continue;
  370                                 rep->re_got_int= 0;
  371                                 assert(rep->re_flags & REF_ENABLED);
  372                                 rl_check_ints(rep);
  373                         }
  374 }
  375 
  376 /*===========================================================================*
  377  *                              rtl8139_stop                                 *
  378  *===========================================================================*/
  379 static void rtl8139_stop()
  380 {
  381         int i;
  382         re_t *rep;
  383 
  384         for (i= 0, rep= &re_table[0]; i<RE_PORT_NR; i++, rep++)
  385         {
  386                 if (rep->re_mode != REM_ENABLED)
  387                         continue;
  388                 rl_outb(rep->re_base_port, RL_CR, 0);
  389         }
  390         sys_exit(0);
  391 }
  392 
  393 /*===========================================================================*
  394  *                              rtl8139_dump                                 *
  395  *===========================================================================*/
  396 static void rtl8139_dump(m)
  397 message *m;                     /* pointer to request message */
  398 {
  399         re_t *rep;
  400         int i;
  401 
  402         printf("\n");
  403         for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
  404         {
  405                 if (rep->re_mode == REM_DISABLED)
  406                         printf("Realtek RTL 8139 port %d is disabled\n", i);
  407 
  408                 if (rep->re_mode != REM_ENABLED)
  409                         continue;
  410 
  411                 printf("Realtek RTL 8139 statistics of port %d:\n", i);
  412 
  413                 printf("recvErr    :%8ld\t", rep->re_stat.ets_recvErr);
  414                 printf("sendErr    :%8ld\t", rep->re_stat.ets_sendErr);
  415                 printf("OVW        :%8ld\n", rep->re_stat.ets_OVW);
  416 
  417                 printf("CRCerr     :%8ld\t", rep->re_stat.ets_CRCerr);
  418                 printf("frameAll   :%8ld\t", rep->re_stat.ets_frameAll);
  419                 printf("missedP    :%8ld\n", rep->re_stat.ets_missedP);
  420 
  421                 printf("packetR    :%8ld\t", rep->re_stat.ets_packetR);
  422                 printf("packetT    :%8ld\t", rep->re_stat.ets_packetT);
  423                 printf("transDef   :%8ld\n", rep->re_stat.ets_transDef);
  424 
  425                 printf("collision  :%8ld\t", rep->re_stat.ets_collision);
  426                 printf("transAb    :%8ld\t", rep->re_stat.ets_transAb);
  427                 printf("carrSense  :%8ld\n", rep->re_stat.ets_carrSense);
  428 
  429                 printf("fifoUnder  :%8ld\t", rep->re_stat.ets_fifoUnder);
  430                 printf("fifoOver   :%8ld\t", rep->re_stat.ets_fifoOver);
  431                 printf("CDheartbeat:%8ld\n", rep->re_stat.ets_CDheartbeat);
  432 
  433                 printf("OWC        :%8ld\t", rep->re_stat.ets_OWC);
  434 
  435                 printf("re_flags = 0x%x\n", rep->re_flags);
  436 
  437                 printf(
  438         "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
  439                         rl_inw(rep->re_base_port, RL_TSAD),
  440                         rl_inl(rep->re_base_port, RL_TSD0+0*4),
  441                         rl_inl(rep->re_base_port, RL_TSD0+1*4),
  442                         rl_inl(rep->re_base_port, RL_TSD0+2*4),
  443                         rl_inl(rep->re_base_port, RL_TSD0+3*4));
  444                 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
  445                         rep->re_tx_head, rep->re_tx_tail,
  446                         rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
  447                         rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
  448         }
  449 }
  450 
  451 /*===========================================================================*
  452  *                              do_init                                      *
  453  *===========================================================================*/
  454 static void rl_init(mp)
  455 message *mp;
  456 {
  457         static int first_time= 1;
  458 
  459         int port;
  460         re_t *rep;
  461         message reply_mess;
  462 
  463         if (first_time)
  464         {
  465                 first_time= 0;
  466                 rl_pci_conf(); /* Configure PCI devices. */
  467 
  468                 tmra_inittimer(&rl_watchdog);
  469                 /* Use a synchronous alarm instead of a watchdog timer. */
  470                 sys_setalarm(HZ, 0);
  471         }
  472 
  473         port = mp->DL_PORT;
  474         if (port < 0 || port >= RE_PORT_NR)
  475         {
  476                 reply_mess.m_type= DL_INIT_REPLY;
  477                 reply_mess.m3_i1= ENXIO;
  478                 mess_reply(mp, &reply_mess);
  479                 return;
  480         }
  481         rep= &re_table[port];
  482         if (rep->re_mode == REM_DISABLED)
  483         {
  484                 /* This is the default, try to (re)locate the device. */
  485                 rl_conf_hw(rep);
  486                 if (rep->re_mode == REM_DISABLED)
  487                 {
  488                         /* Probe failed, or the device is configured off. */
  489                         reply_mess.m_type= DL_INIT_REPLY;
  490                         reply_mess.m3_i1= ENXIO;
  491                         mess_reply(mp, &reply_mess);
  492                         return;
  493                 }
  494                 if (rep->re_mode == REM_ENABLED)
  495                         rl_init_hw(rep);
  496 #if VERBOSE     /* load silently ... can always check status later */
  497                 rl_report_link(rep);
  498 #endif
  499         }
  500 
  501         assert(rep->re_mode == REM_ENABLED);
  502         assert(rep->re_flags & REF_ENABLED);
  503 
  504         rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
  505 
  506         if (mp->DL_MODE & DL_PROMISC_REQ)
  507                 rep->re_flags |= REF_PROMISC;
  508         if (mp->DL_MODE & DL_MULTI_REQ)
  509                 rep->re_flags |= REF_MULTI;
  510         if (mp->DL_MODE & DL_BROAD_REQ)
  511                 rep->re_flags |= REF_BROAD;
  512 
  513         rep->re_client = mp->m_source;
  514         rl_rec_mode(rep);
  515 
  516         reply_mess.m_type = DL_INIT_REPLY;
  517         reply_mess.m3_i1 = mp->DL_PORT;
  518         reply_mess.m3_i2 = RE_PORT_NR;
  519         *(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
  520 
  521         mess_reply(mp, &reply_mess);
  522 }
  523 
  524 /*===========================================================================*
  525  *                              rl_pci_conf                                  *
  526  *===========================================================================*/
  527 static void rl_pci_conf()
  528 {
  529         int i, h;
  530         re_t *rep;
  531         static char envvar[] = RL_ENVVAR "#";
  532         static char envfmt[] = "*:d.d.d";
  533         static char val[128];
  534         long v;
  535 
  536         for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
  537         {
  538                 strcpy(rep->re_name, "rtl8139#0");
  539                 rep->re_name[8] += i;
  540                 rep->re_seen= FALSE;
  541                 envvar[sizeof(RL_ENVVAR)-1]= ''+i;
  542                 if (0 == env_get_param(envvar, val, sizeof(val)) && 
  543                                 ! env_prefix(envvar, "pci")) {
  544                         env_panic(envvar);
  545                 }
  546                 v= 0;
  547                 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
  548                 rep->re_pcibus= v;
  549                 v= 0;
  550                 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
  551                 rep->re_pcidev= v;
  552                 v= 0;
  553                 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
  554                 rep->re_pcifunc= v;
  555         }
  556 
  557         pci_init();
  558 
  559         for (h= 1; h >= 0; h--) {
  560                 for (i= 0, rep= re_table; i<RE_PORT_NR; i++, rep++)
  561                 {
  562                         if (((rep->re_pcibus | rep->re_pcidev |
  563                                 rep->re_pcifunc) != 0) != h)
  564                         {
  565                                 continue;
  566                         }
  567                         if (rl_probe(rep))
  568                                 rep->re_seen= TRUE;
  569                 }
  570         }
  571 }
  572 
  573 /*===========================================================================*
  574  *                              rl_probe                                     *
  575  *===========================================================================*/
  576 static int rl_probe(rep)
  577 re_t *rep;
  578 {
  579         int i, r, devind, just_one;
  580         u16_t vid, did;
  581         u32_t bar;
  582         u8_t ilr;
  583         char *dname;
  584 
  585         if ((rep->re_pcibus | rep->re_pcidev | rep->re_pcifunc) != 0)
  586         {
  587                 /* Look for specific PCI device */
  588                 r= pci_find_dev(rep->re_pcibus, rep->re_pcidev,
  589                         rep->re_pcifunc, &devind);
  590                 if (r == 0)
  591                 {
  592                         printf("%s: no PCI found at %d.%d.%d\n",
  593                                 rep->re_name, rep->re_pcibus,
  594                                 rep->re_pcidev, rep->re_pcifunc);
  595                         return 0;
  596                 }
  597                 pci_ids(devind, &vid, &did);
  598                 just_one= TRUE;
  599         }
  600         else
  601         {
  602                 r= pci_first_dev(&devind, &vid, &did);
  603                 if (r == 0)
  604                         return 0;
  605                 just_one= FALSE;
  606         }
  607 
  608         for(;;)
  609         {
  610                 for (i= 0; pcitab[i].vid != 0; i++)
  611                 {
  612                         if (pcitab[i].vid != vid)
  613                                 continue;
  614                         if (pcitab[i].did != did)
  615                                 continue;
  616                         if (pcitab[i].checkclass)
  617                         {
  618                           panic("rtl_probe",
  619                             "class check not implemented", NO_NUM);
  620                         }
  621                         break;
  622                 }
  623                 if (pcitab[i].vid != 0)
  624                         break;
  625 
  626                 if (just_one)
  627                 {
  628                         printf(
  629                 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
  630                                 rep->re_name, vid, did,
  631                                 rep->re_pcibus,
  632                                 rep->re_pcidev, rep->re_pcifunc);
  633                         return 0;
  634                 }
  635 
  636                 r= pci_next_dev(&devind, &vid, &did);
  637                 if (!r)
  638                         return 0;
  639         }
  640 
  641 #if VERBOSE     /* stay silent at startup, can always get status later */
  642         dname= pci_dev_name(vid, did);
  643         if (!dname)
  644                 dname= "unknown device";
  645         printf("%s: ", rep->re_name);
  646         printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
  647 #endif
  648         pci_reserve(devind);
  649         /* printf("cr = 0x%x\n", pci_attr_r16(devind, PCI_CR)); */
  650         bar= pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
  651         if ((bar & 0x3ff) >= 0x100-32 || bar < 0x400)
  652           panic("rtl_probe",
  653             "base address is not properly configured", NO_NUM);
  654         rep->re_base_port= bar;
  655 
  656         ilr= pci_attr_r8(devind, PCI_ILR);
  657         rep->re_irq= ilr;
  658         if (debug)
  659         {
  660                 printf("%s: using I/O address 0x%lx, IRQ %d\n",
  661                         rep->re_name, (unsigned long)bar, ilr);
  662         }
  663 
  664         return TRUE;
  665 }
  666 
  667 /*===========================================================================*
  668  *                              rl_conf_hw                                   *
  669  *===========================================================================*/
  670 static void rl_conf_hw(rep)
  671 re_t *rep;
  672 {
  673         static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
  674 
  675         rep->re_mode= REM_DISABLED;     /* Superfluous */
  676 
  677         if (rep->re_seen)
  678         {
  679                 /* PCI device is present */
  680                 rep->re_mode= REM_ENABLED;
  681         }
  682         if (rep->re_mode != REM_ENABLED)
  683                 return;
  684 
  685         rep->re_flags= REF_EMPTY;
  686         rep->re_link_up= -1;    /* Unknown */
  687         rep->re_got_int= 0;
  688         rep->re_send_int= 0;
  689         rep->re_report_link= 0;
  690         rep->re_clear_rx= 0;
  691         rep->re_need_reset= 0;
  692         rep->re_tx_alive= 0;
  693         rep->re_read_s= 0;
  694         rep->re_tx_head= 0;
  695         rep->re_tx_tail= 0;
  696         rep->re_ertxth= RL_TSD_ERTXTH_8;
  697         rep->re_stat= empty_stat;
  698 }
  699 
  700 /*===========================================================================*
  701  *                              rl_init_buf                                  *
  702  *===========================================================================*/
  703 static void rl_init_buf(rep)
  704 re_t *rep;
  705 {
  706         size_t rx_bufsize, tx_bufsize, tot_bufsize;
  707         phys_bytes buf;
  708         char *mallocbuf;
  709         static struct memory chunk;
  710         int fd, s, i, off;
  711 
  712         /* Allocate receive and transmit buffers */
  713         tx_bufsize= ETH_MAX_PACK_SIZE_TAGGED;
  714         if (tx_bufsize % 4)
  715                 tx_bufsize += 4-(tx_bufsize % 4);       /* Align */
  716         rx_bufsize= RX_BUFSIZE;
  717         tot_bufsize= N_TX_BUF*tx_bufsize + rx_bufsize;
  718 
  719         /* Now try to allocate a kernel memory buffer. */
  720         chunk.size = tot_bufsize;
  721 
  722 #define BUF_ALIGNMENT (64*1024)
  723 
  724         if(!(mallocbuf = malloc(BUF_ALIGNMENT + tot_bufsize))) {
  725             panic("RTL8139","Couldn't allocate kernel buffer",i);
  726         }
  727 
  728         if(OK != (i = sys_umap(SELF, D, (vir_bytes) mallocbuf, tot_bufsize, &buf))) {
  729             panic("RTL8139","Couldn't re-map malloced buffer",i);
  730         }
  731 
  732         /* click-align mallocced buffer. this is what we used to get
  733          * from kmalloc() too.
  734          */
  735         if((off = buf % BUF_ALIGNMENT)) {
  736                 mallocbuf += BUF_ALIGNMENT - off;
  737                 buf += BUF_ALIGNMENT - off;
  738         }
  739 
  740         for (i= 0; i<N_TX_BUF; i++)
  741         {
  742                 rep->re_tx[i].ret_buf= buf;
  743                 rep->re_tx[i].v_ret_buf= mallocbuf;
  744                 buf += tx_bufsize;
  745                 mallocbuf += tx_bufsize;
  746         }
  747         rep->re_rx_buf= buf;
  748         rep->v_re_rx_buf= mallocbuf;
  749 }
  750 
  751 /*===========================================================================*
  752  *                              rl_init_hw                                   *
  753  *===========================================================================*/
  754 static void rl_init_hw(rep)
  755 re_t *rep;
  756 {
  757         int s, i;
  758 
  759         rep->re_flags = REF_EMPTY;
  760         rep->re_flags |= REF_ENABLED;
  761 
  762         /* Set the interrupt handler. The policy is to only send HARD_INT 
  763          * notifications. Don't reenable interrupts automatically. The id
  764          * that is passed back is the interrupt line number.
  765          */
  766         rep->re_hook_id = rep->re_irq;  
  767         if ((s=sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
  768                 printf("RTL8139: error, couldn't set IRQ policy: %d\n", s);
  769 
  770         rl_reset_hw(rep);
  771 
  772         if ((s=sys_irqenable(&rep->re_hook_id)) != OK)
  773                 printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
  774 
  775 #if VERBOSE     /* stay silent during startup, can always get status later */
  776         if (rep->re_mode) {
  777                 printf("%s: model %s\n", rep->re_name, rep->re_model);
  778         } else
  779         {
  780                 printf("%s: unknown model 0x%08x\n",
  781                         rep->re_name,
  782                         rl_inl(rep->re_base_port, RL_TCR) &
  783                         (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
  784         }
  785 #endif
  786 
  787         rl_confaddr(rep);
  788         if (debug)
  789         {
  790                 printf("%s: Ethernet address ", rep->re_name);
  791                 for (i= 0; i < 6; i++)
  792                 {
  793                         printf("%x%c", rep->re_address.ea_addr[i],
  794                                 i < 5 ? ':' : '\n');
  795                 }
  796         }
  797 }
  798 
  799 /*===========================================================================*
  800  *                              rl_reset_hw                                  *
  801  *===========================================================================*/
  802 static void rl_reset_hw(rep)
  803 re_t *rep;
  804 {
  805         port_t port;
  806         u32_t t;
  807         phys_bytes bus_buf;
  808         int i;
  809         clock_t t0,t1;
  810 
  811         port= rep->re_base_port;
  812 
  813 #if 0
  814         /* Reset the PHY */
  815         rl_outb(port, RL_BMCR, MII_CTRL_RST);
  816         getuptime(&t0);
  817         do {
  818                 if (!(rl_inb(port, RL_BMCR) & MII_CTRL_RST))
  819                         break;
  820         } while (getuptime(&t1)==OK && (t1-t0) < HZ);
  821         if (rl_inb(port, RL_BMCR) & MII_CTRL_RST)
  822                 panic("rtl8139","reset PHY failed to complete", NO_NUM);
  823 #endif
  824 
  825         /* Reset the device */
  826         rl_outb(port, RL_CR, RL_CR_RST);
  827         getuptime(&t0);
  828         do {
  829                 if (!(rl_inb(port, RL_CR) & RL_CR_RST))
  830                         break;
  831         } while (getuptime(&t1)==OK && (t1-t0) < HZ);
  832         if (rl_inb(port, RL_CR) & RL_CR_RST)
  833                 panic("rtl8139","reset failed to complete", NO_NUM);
  834 
  835         t= rl_inl(port, RL_TCR);
  836         switch(t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM))
  837         {
  838         case RL_TCR_HWVER_RTL8139: rep->re_model= "RTL8139"; break;
  839         case RL_TCR_HWVER_RTL8139A: rep->re_model= "RTL8139A"; break;
  840         case RL_TCR_HWVER_RTL8139AG:
  841                 rep->re_model= "RTL8139A-G / RTL8139C";
  842                 break;
  843         case RL_TCR_HWVER_RTL8139B:
  844                 rep->re_model= "RTL8139B / RTL8130";
  845                 break;
  846         case RL_TCR_HWVER_RTL8100: rep->re_model= "RTL8100"; break;
  847         case RL_TCR_HWVER_RTL8100B:
  848                 rep->re_model= "RTL8100B/RTL8139D";
  849                 break;
  850         case RL_TCR_HWVER_RTL8139CP: rep->re_model= "RTL8139C+"; break;
  851         case RL_TCR_HWVER_RTL8101: rep->re_model= "RTL8101"; break;
  852         default:
  853                 rep->re_model= NULL;
  854                 break;
  855         }
  856 
  857 #if 0
  858         printf("REVID: 0x%02x\n", rl_inb(port, RL_REVID));
  859 #endif
  860 
  861         /* Intialize Rx */
  862 
  863         /* Should init multicast mask */
  864 #if 0
  865 08-0f   R/W     MAR[0-7]        multicast
  866 #endif
  867         bus_buf= vm_1phys2bus(rep->re_rx_buf);
  868         rl_outl(port, RL_RBSTART, bus_buf);
  869 
  870         /* Initialize Tx */ 
  871         for (i= 0; i<N_TX_BUF; i++)
  872         {
  873                 rep->re_tx[i].ret_busy= FALSE;
  874                 bus_buf= vm_1phys2bus(rep->re_tx[i].ret_buf);
  875                 rl_outl(port, RL_TSAD0+i*4, bus_buf);
  876                 t= rl_inl(port, RL_TSD0+i*4);
  877                 assert(t & RL_TSD_OWN);
  878         }
  879 
  880 #if 0
  881         dump_phy(rep);
  882 #endif
  883 
  884         t= rl_inw(port, RL_IMR);
  885         rl_outw(port, RL_IMR, t | (RL_IMR_SERR | RL_IMR_TIMEOUT |
  886                 RL_IMR_LENCHG));
  887 
  888         t= rl_inw(port, RL_IMR);
  889         rl_outw(port, RL_IMR, t | (RL_IMR_FOVW | RL_IMR_PUN |
  890                 RL_IMR_RXOVW | RL_IMR_RER | RL_IMR_ROK));
  891 
  892         t= rl_inw(port, RL_IMR);
  893         rl_outw(port, RL_IMR, t | (RL_IMR_TER | RL_IMR_TOK));
  894 
  895         t= rl_inb(port, RL_CR);
  896         rl_outb(port, RL_CR, t | RL_CR_RE);
  897 
  898         t= rl_inb(port, RL_CR);
  899         rl_outb(port, RL_CR, t | RL_CR_TE);
  900 
  901         rl_outl(port, RL_RCR, RX_BUFBITS);
  902 
  903         t= rl_inl(port, RL_TCR);
  904         rl_outl(port, RL_TCR, t | RL_TCR_IFG_STD);
  905 }
  906 
  907 /*===========================================================================*
  908  *                              rl_confaddr                                  *
  909  *===========================================================================*/
  910 static void rl_confaddr(rep)
  911 re_t *rep;
  912 {
  913         static char eakey[]= RL_ENVVAR "#_EA";
  914         static char eafmt[]= "x:x:x:x:x:x";
  915 
  916         int i;
  917         port_t port;
  918         u32_t w;
  919         long v;
  920 
  921         /* User defined ethernet address? */
  922         eakey[sizeof(RL_ENVVAR)-1]= '' + (rep-re_table);
  923 
  924         port= rep->re_base_port;
  925 
  926         for (i= 0; i < 6; i++)
  927         {
  928                 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
  929                         break;
  930                 rep->re_address.ea_addr[i]= v;
  931         }
  932 
  933         if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
  934 
  935         /* Should update ethernet address in hardware */
  936         if (i == 6)
  937         {
  938                 port= rep->re_base_port;
  939                 rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
  940                 w= 0;
  941                 for (i= 0; i<4; i++)
  942                         w |= (rep->re_address.ea_addr[i] << (i*8));
  943                 rl_outl(port, RL_IDR, w);
  944                 w= 0;
  945                 for (i= 4; i<6; i++)
  946                         w |= (rep->re_address.ea_addr[i] << ((i-4)*8));
  947                 rl_outl(port, RL_IDR+4, w);
  948                 rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
  949         }
  950 
  951         /* Get ethernet address */
  952         for (i= 0; i<6; i++)
  953                 rep->re_address.ea_addr[i]= rl_inb(port, RL_IDR+i);
  954 }
  955 
  956 /*===========================================================================*
  957  *                              rl_rec_mode                                  *
  958  *===========================================================================*/
  959 static void rl_rec_mode(rep)
  960 re_t *rep;
  961 {
  962         port_t port;
  963         u32_t rcr;
  964 
  965         port= rep->re_base_port;
  966         rcr= rl_inl(port, RL_RCR);
  967         rcr &= ~(RL_RCR_AB|RL_RCR_AM|RL_RCR_APM|RL_RCR_AAP);
  968         if (rep->re_flags & REF_PROMISC)
  969                 rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
  970         if (rep->re_flags & REF_BROAD)
  971                 rcr |= RL_RCR_AB;
  972         if (rep->re_flags & REF_MULTI)
  973                 rcr |= RL_RCR_AM;
  974         rcr |= RL_RCR_APM;
  975 
  976         rl_outl(port, RL_RCR, rcr);
  977 }
  978 
  979 /*===========================================================================*
  980  *                              rl_readv                                     *
  981  *===========================================================================*/
  982 static void rl_readv(mp, from_int, vectored)
  983 message *mp;
  984 int from_int;
  985 int vectored;
  986 {
  987         int i, j, n, o, s, s1, dl_port, re_client, count, size;
  988         port_t port;
  989         unsigned amount, totlen, packlen;
  990         phys_bytes src_phys, dst_phys, iov_src;
  991         u16_t d_start, d_end;
  992         u32_t l, rxstat = 0x12345678;
  993         re_t *rep;
  994         iovec_t *iovp;
  995         int cps;
  996 
  997         dl_port = mp->DL_PORT;
  998         count = mp->DL_COUNT;
  999         if (dl_port < 0 || dl_port >= RE_PORT_NR)
 1000                 panic("rtl8139"," illegal port", dl_port);
 1001         rep= &re_table[dl_port];
 1002         re_client= mp->DL_PROC;
 1003         rep->re_client= re_client;
 1004 
 1005         if (rep->re_clear_rx)
 1006                 goto suspend;   /* Buffer overflow */
 1007 
 1008         assert(rep->re_mode == REM_ENABLED);
 1009         assert(rep->re_flags & REF_ENABLED);
 1010 
 1011         port= rep->re_base_port;
 1012 
 1013         /* Assume that the RL_CR_BUFE check was been done by rl_checks_ints
 1014          */
 1015         if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
 1016         {
 1017                 /* Receive buffer is empty, suspend */
 1018                 goto suspend;
 1019         }
 1020 
 1021         d_start= rl_inw(port, RL_CAPR) + RL_CAPR_DATA_OFF;
 1022         d_end= rl_inw(port, RL_CBR) % RX_BUFSIZE;
 1023 
 1024         if (d_start >= RX_BUFSIZE)
 1025         {
 1026                 printf("rl_readv: strange value in RL_CAPR: 0x%x\n",
 1027                         rl_inw(port, RL_CAPR));
 1028                 d_start %= RX_BUFSIZE;
 1029         }
 1030 
 1031         if (d_end > d_start)
 1032                 amount= d_end-d_start;
 1033         else
 1034                 amount= d_end+RX_BUFSIZE - d_start;
 1035 
 1036         rxstat = *(u32_t *) (rep->v_re_rx_buf + d_start);
 1037 
 1038 #if DEAD_CODE
 1039         src_phys= rep->re_rx_buf + d_start;
 1040         cps = sys_physcopy(
 1041                 NONE, PHYS_SEG, src_phys,
 1042                 SELF, D, (vir_bytes) &rxstat, sizeof(rxstat));
 1043         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1044 #endif
 1045 
 1046         if (rep->re_clear_rx)
 1047         {
 1048 #if 0
 1049                 printf("rl_readv: late buffer overflow\n");
 1050 #endif
 1051                 goto suspend;   /* Buffer overflow */
 1052         }
 1053 
 1054         /* Should convert from little endian to host byte order */
 1055 
 1056         if (!(rxstat & RL_RXS_ROK))
 1057         {
 1058                 printf("rxstat = 0x%08lx\n", rxstat);
 1059                 printf("d_start: 0x%x, d_end: 0x%x, rxstat: 0x%lx\n",
 1060                         d_start, d_end, rxstat);
 1061                 panic("rtl8139","received packet not OK", NO_NUM);
 1062         }
 1063         totlen= (rxstat >> RL_RXS_LEN_S);
 1064         if (totlen < 8 || totlen > 2*ETH_MAX_PACK_SIZE)
 1065         {
 1066                 /* Someting went wrong */
 1067                 printf(
 1068                 "rl_readv: bad length (%u) in status 0x%08lx at offset 0x%x\n",
 1069                         totlen, rxstat, d_start);
 1070                 printf(
 1071                 "d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%lx\n",
 1072                         d_start, d_end, totlen, rxstat);
 1073                 panic(NULL, NULL, NO_NUM);
 1074         }
 1075 
 1076 #if 0
 1077         printf("d_start: 0x%x, d_end: 0x%x, totlen: %d, rxstat: 0x%x\n",
 1078                 d_start, d_end, totlen, rxstat);
 1079 #endif
 1080 
 1081         if (totlen+4 > amount)
 1082         {
 1083                 printf("rl_readv: packet not yet ready\n");
 1084                 goto suspend;
 1085         }
 1086 
 1087         /* Should subtract the CRC */
 1088         packlen= totlen - ETH_CRC_SIZE;
 1089 
 1090         if (vectored)
 1091         {
 1092                 int iov_offset = 0;
 1093 #if 0
 1094                 if ((cps = sys_umap(re_client, D, (vir_bytes) mp->DL_ADDR,
 1095                         count * sizeof(rep->re_iovec[0]), &iov_src)) != OK)
 1096                         printf("sys_umap failed: %d\n", cps);
 1097 #endif
 1098 
 1099                 size= 0;
 1100                 o= d_start+4;
 1101                 src_phys= rep->re_rx_buf;
 1102                 for (i= 0; i<count; i += IOVEC_NR,
 1103                         iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
 1104                         iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
 1105                 {
 1106                         n= IOVEC_NR;
 1107                         if (i+n > count)
 1108                                 n= count-i;
 1109 #if 0
 1110                         cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, 
 1111                                 n * sizeof(rep->re_iovec[0]));
 1112         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1113 #else
 1114                         cps = sys_vircopy(re_client, D, (vir_bytes) mp->DL_ADDR + iov_offset,
 1115                                 SELF, D, (vir_bytes) rep->re_iovec, n * sizeof(rep->re_iovec[0]));
 1116         if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
 1117 #endif
 1118 
 1119                         for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
 1120                         {
 1121                                 s= iovp->iov_size;
 1122                                 if (size + s > packlen)
 1123                                 {
 1124                                         assert(packlen > size);
 1125                                         s= packlen-size;
 1126                                 }
 1127 
 1128 #if 0
 1129                                 if (sys_umap(re_client, D, iovp->iov_addr, s, &dst_phys) != OK)
 1130                                   panic("rtl8139","umap_local failed\n", NO_NUM);
 1131 #endif
 1132 
 1133                                 if (o >= RX_BUFSIZE)
 1134                                 {
 1135                                         o -= RX_BUFSIZE;
 1136                                         assert(o < RX_BUFSIZE);
 1137                                 }
 1138 
 1139                                 if (o+s > RX_BUFSIZE)
 1140                                 {
 1141                                         assert(o<RX_BUFSIZE);
 1142                                         s1= RX_BUFSIZE-o;
 1143 
 1144 #if 0
 1145                                         cps = sys_abscopy(src_phys+o, dst_phys, s1);
 1146         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1147                                         cps = sys_abscopy(src_phys, dst_phys+s1, s-s1);
 1148         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1149 #else
 1150                                         cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
 1151                                         re_client, D, iovp->iov_addr, s1);
 1152         if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
 1153                                         cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf,
 1154                                         re_client, D, iovp->iov_addr+s1, s-s1);
 1155         if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
 1156 #endif
 1157                                 }
 1158                                 else
 1159                                 {
 1160 #if 0
 1161                                         cps = sys_abscopy(src_phys+o, dst_phys, s);
 1162         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1163 #else
 1164                                         cps = sys_vircopy(SELF, D, (vir_bytes) rep->v_re_rx_buf+o,
 1165                                         re_client, D, iovp->iov_addr, s);
 1166         if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d (%d)\n", cps, __LINE__);
 1167 #endif
 1168                                 }
 1169 
 1170                                 size += s;
 1171                                 if (size == packlen)
 1172                                         break;
 1173                                 o += s;
 1174                         }
 1175                         if (size == packlen)
 1176                                 break;
 1177                 }
 1178                 if (size < packlen)
 1179                 {
 1180                         assert(0);
 1181                 }
 1182         }
 1183         else
 1184         {  
 1185                 assert(0);
 1186 #if 0
 1187                 size= mp->DL_COUNT;
 1188                 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
 1189                         panic("rtl8139","invalid packet size", size);
 1190                 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
 1191                         panic("rtl8139","umap_local failed", NO_NUM);
 1192 
 1193                 p= rep->re_tx[tx_head].ret_buf;
 1194                 cps = sys_abscopy(phys_user, p, size);
 1195                 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1196 #endif
 1197                 }
 1198 
 1199                 if (rep->re_clear_rx)
 1200                 {
 1201                         /* For some reason the receiver FIFO is not stopped when
 1202                          * the buffer is full.
 1203                          */
 1204         #if 0
 1205                         printf("rl_readv: later buffer overflow\n");
 1206         #endif
 1207                         goto suspend;   /* Buffer overflow */
 1208                 }
 1209 
 1210                 rep->re_stat.ets_packetR++;
 1211                 rep->re_read_s= packlen;
 1212                 rep->re_flags= (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
 1213 
 1214                 /* Avoid overflow in 16-bit computations */
 1215                 l= d_start;
 1216                 l += totlen+4;
 1217                 l= (l+3) & ~3;  /* align */
 1218                 if (l >= RX_BUFSIZE)
 1219                 {
 1220                         l -= RX_BUFSIZE;
 1221                         assert(l < RX_BUFSIZE);
 1222                 }
 1223                 rl_outw(port, RL_CAPR, l-RL_CAPR_DATA_OFF);
 1224 
 1225                 if (!from_int)
 1226                         reply(rep, OK, FALSE);
 1227 
 1228                 return;
 1229 
 1230         suspend:
 1231                 if (from_int)
 1232                 {
 1233                         assert(rep->re_flags & REF_READING);
 1234 
 1235                         /* No need to store any state */
 1236                         return;
 1237                 }
 1238 
 1239                 rep->re_rx_mess= *mp;
 1240                 assert(!(rep->re_flags & REF_READING));
 1241                 rep->re_flags |= REF_READING;
 1242 
 1243                 reply(rep, OK, FALSE);
 1244         }
 1245 
 1246         /*===========================================================================*
 1247          *                              rl_writev                                    *
 1248          *===========================================================================*/
 1249         static void rl_writev(mp, from_int, vectored)
 1250         message *mp;
 1251         int from_int;
 1252         int vectored;
 1253         {
 1254                 phys_bytes p, iov_src, phys_user;
 1255                 int i, j, n, s, port, count, size;
 1256                 int tx_head, re_client;
 1257                 re_t *rep;
 1258                 iovec_t *iovp;
 1259                 char *ret;
 1260                 int cps;
 1261 
 1262                 port = mp->DL_PORT;
 1263                 count = mp->DL_COUNT;
 1264                 if (port < 0 || port >= RE_PORT_NR)
 1265                         panic("rtl8139","illegal port", port);
 1266                 rep= &re_table[port];
 1267                 re_client= mp->DL_PROC;
 1268                 rep->re_client= re_client;
 1269 
 1270                 assert(rep->re_mode == REM_ENABLED);
 1271                 assert(rep->re_flags & REF_ENABLED);
 1272 
 1273                 if (from_int)
 1274                 {
 1275                         assert(rep->re_flags & REF_SEND_AVAIL);
 1276                         rep->re_flags &= ~REF_SEND_AVAIL;
 1277                         rep->re_send_int= FALSE;
 1278                         rep->re_tx_alive= TRUE;
 1279                 }
 1280 
 1281                 tx_head= rep->re_tx_head;
 1282                 if (rep->re_tx[tx_head].ret_busy)
 1283                 {
 1284                         assert(!(rep->re_flags & REF_SEND_AVAIL));
 1285                         rep->re_flags |= REF_SEND_AVAIL;
 1286                         if (rep->re_tx[tx_head].ret_busy)
 1287                                 goto suspend;
 1288 
 1289                         /* Race condition, the interrupt handler may clear re_busy
 1290                          * before we got a chance to set REF_SEND_AVAIL. Checking
 1291                          * ret_busy twice should be sufficient.
 1292                          */
 1293         #if 0
 1294                         printf("rl_writev: race detected\n");
 1295         #endif
 1296                         rep->re_flags &= ~REF_SEND_AVAIL;
 1297                         rep->re_send_int= FALSE;
 1298                 }
 1299 
 1300                 assert(!(rep->re_flags & REF_SEND_AVAIL));
 1301                 assert(!(rep->re_flags & REF_PACK_SENT));
 1302 
 1303                 if (vectored)
 1304                 {
 1305                         int iov_offset = 0;
 1306 
 1307 #if 0
 1308                         if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR,
 1309                                 count * sizeof(rep->re_iovec[0]), &iov_src))
 1310                                 panic("rtl8139","umap_local failed", NO_NUM);
 1311 #endif
 1312 
 1313                         size= 0;
 1314 #if 0
 1315                         p= rep->re_tx[tx_head].ret_buf;
 1316 #else
 1317                         ret = rep->re_tx[tx_head].v_ret_buf;
 1318 #endif
 1319                         for (i= 0; i<count; i += IOVEC_NR,
 1320                                 iov_src += IOVEC_NR * sizeof(rep->re_iovec[0]),
 1321                                 iov_offset += IOVEC_NR * sizeof(rep->re_iovec[0]))
 1322                         {
 1323                                 n= IOVEC_NR;
 1324                                 if (i+n > count)
 1325                                         n= count-i;
 1326 #if 0
 1327                                 cps = sys_physcopy(NONE, PHYS_SEG, iov_src, SELF, D, (vir_bytes) rep->re_iovec, 
 1328                                         n * sizeof(rep->re_iovec[0]));
 1329                 if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1330 #else
 1331                                 cps = sys_vircopy(re_client, D, ((vir_bytes) mp->DL_ADDR) + iov_offset,
 1332                                         SELF, D, (vir_bytes) rep->re_iovec, 
 1333                                         n * sizeof(rep->re_iovec[0]));
 1334         if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
 1335 #endif
 1336 
 1337                         for (j= 0, iovp= rep->re_iovec; j<n; j++, iovp++)
 1338                         {
 1339                                 s= iovp->iov_size;
 1340                                 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
 1341                                 {
 1342                                   panic("rtl8139","invalid packet size",
 1343                                     NO_NUM);
 1344                                 }
 1345 
 1346                                 if (OK != sys_umap(re_client, D, iovp->iov_addr, s, &phys_user))
 1347                                   panic("rtl8139","umap_local failed\n", NO_NUM);
 1348 
 1349 #if 0
 1350                                 cps = sys_abscopy(phys_user, p, s);
 1351         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1352 #else
 1353                                 cps = sys_vircopy(re_client, D, iovp->iov_addr,
 1354                                         SELF, D, (vir_bytes) ret, s);
 1355                 if (cps != OK) printf("RTL8139: warning, sys_vircopy failed: %d\n", cps);
 1356 #endif
 1357                                 size += s;
 1358 #if 0
 1359                                 p += s;
 1360 #endif
 1361                                 ret += s;
 1362                         }
 1363                 }
 1364                 if (size < ETH_MIN_PACK_SIZE)
 1365                         panic("rtl8139","invalid packet size", size);
 1366         }
 1367         else
 1368         {  
 1369                 size= mp->DL_COUNT;
 1370                 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
 1371                         panic("rtl8139","invalid packet size", size);
 1372 #if 0
 1373                 if (OK != sys_umap(re_client, D, (vir_bytes)mp->DL_ADDR, size, &phys_user))
 1374                         panic("rtl8139","umap_local failed\n", NO_NUM);
 1375 
 1376                 p= rep->re_tx[tx_head].ret_buf;
 1377                 cps = sys_abscopy(phys_user, p, size);
 1378         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1379 #else
 1380                 ret = rep->re_tx[tx_head].v_ret_buf;
 1381                 cps = sys_vircopy(re_client, D, (vir_bytes)mp->DL_ADDR, 
 1382                         SELF, D, (vir_bytes) ret, size);
 1383         if (cps != OK) printf("RTL8139: warning, sys_abscopy failed: %d\n", cps);
 1384 #endif
 1385         }
 1386 
 1387         rl_outl(rep->re_base_port, RL_TSD0+tx_head*4, 
 1388                 rep->re_ertxth | size);
 1389         rep->re_tx[tx_head].ret_busy= TRUE;
 1390 
 1391         if (++tx_head == N_TX_BUF)
 1392                 tx_head= 0;
 1393         assert(tx_head < RL_N_TX);
 1394         rep->re_tx_head= tx_head;
 1395 
 1396         rep->re_flags |= REF_PACK_SENT;
 1397 
 1398         /* If the interrupt handler called, don't send a reply. The reply
 1399          * will be sent after all interrupts are handled. 
 1400          */
 1401         if (from_int)
 1402                 return;
 1403         reply(rep, OK, FALSE);
 1404         return;
 1405 
 1406 suspend:
 1407 #if 0
 1408                 printf("rl_writev: head %d, tail %d, busy: %d %d %d %d\n",
 1409                         tx_head, rep->re_tx_tail,
 1410                         rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
 1411                         rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
 1412                 printf("rl_writev: TSD: 0x%x, 0x%x, 0x%x, 0x%x\n",
 1413                         rl_inl(rep->re_base_port, RL_TSD0+0*4),
 1414                         rl_inl(rep->re_base_port, RL_TSD0+1*4),
 1415                         rl_inl(rep->re_base_port, RL_TSD0+2*4),
 1416                         rl_inl(rep->re_base_port, RL_TSD0+3*4));
 1417 #endif
 1418 
 1419         if (from_int)
 1420                 panic("rtl8139","should not be sending\n", NO_NUM);
 1421 
 1422         rep->re_tx_mess= *mp;
 1423         reply(rep, OK, FALSE);
 1424 }
 1425 
 1426 /*===========================================================================*
 1427  *                              rl_check_ints                                *
 1428  *===========================================================================*/
 1429 static void rl_check_ints(rep)
 1430 re_t *rep;
 1431 {
 1432 #if 0
 1433 10-1f   R/W     TSD[0-3]        Transmit Status of Descriptor [0-3]
 1434         31      R       CRS     Carrier Sense Lost
 1435         30      R       TABT    Transmit Abort
 1436         29      R       OWC     Out of Window Collision
 1437         27-24   R       NCC[3-0] Number of Collision Count
 1438         23-22                   reserved
 1439         21-16   R/W     ERTXH[5-0] Early Tx Threshold
 1440         15      R       TOK     Transmit OK
 1441         14      R       TUN     Transmit FIFO Underrun
 1442         13      R/W     OWN     OWN
 1443         12-0    R/W     SIZE    Descriptor Size
 1444 3e-3f   R/W     ISR             Interrupt Status Register
 1445         6       R/W     FOVW    Fx FIFO Overflow Interrupt
 1446         5       R/W     PUN/LinkChg Packet Underrun / Link Change Interrupt
 1447         3       R/W     TER     Transmit Error Interrupt
 1448         2       R/W     TOK     Transmit OK Interrupt
 1449 3e-3f   R/W     ISR             Interrupt Status Register
 1450         15      R/W     SERR    System Error Interrupt
 1451         14      R/W     TimeOut Time Out Interrupt
 1452         13      R/W     LenChg  Cable Length Change Interrupt
 1453 3e-3f   R/W     ISR             Interrupt Status Register
 1454         4       R/W     RXOVW   Rx Buffer Overflow Interrupt
 1455         1       R/W     RER     Receive Error Interrupt
 1456         0       R/W     ROK     Receive OK Interrupt
 1457 4c-4f   R/W     MPC             Missed Packet Counter
 1458 60-61   R       TSAD            Transmit Status of All Descriptors
 1459         15-12   R       TOK[3-0] TOK bit of Descriptor [3-0]
 1460         11-8    R       TUN[3-0] TUN bit of Descriptor [3-0]
 1461         7-4     R       TABT[3-0] TABT bit of Descriptor [3-0]
 1462         3-0     R       OWN[3-0] OWN bit of Descriptor [3-0]
 1463 6c-6d   R       DIS             Disconnect Counter
 1464         15-0    R       DCNT    Disconnect Counter
 1465 6e-6f   R       FCSC            False Carrier Sense Counter
 1466         15-0    R       FCSCNT  False Carrier event counter
 1467 72-73   R       REC             RX_ER Counter
 1468         15-0    R       RXERCNT Received packet counter
 1469 #endif
 1470 
 1471         int re_flags;
 1472 
 1473         re_flags= rep->re_flags;
 1474 
 1475         if ((re_flags & REF_READING) &&
 1476                 !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
 1477         {
 1478                 if (rep->re_rx_mess.m_type == DL_READV)
 1479                 {
 1480                         rl_readv(&rep->re_rx_mess, TRUE /* from int */,
 1481                                 TRUE /* vectored */);
 1482                 }
 1483                 else
 1484                 {
 1485                         assert(rep->re_rx_mess.m_type == DL_READ);
 1486                         rl_readv(&rep->re_rx_mess, TRUE /* from int */,
 1487                                 FALSE /* !vectored */);
 1488                 }
 1489         }
 1490         if (rep->re_clear_rx)
 1491                 rl_clear_rx(rep);
 1492 
 1493         if (rep->re_need_reset)
 1494                 rl_do_reset(rep);
 1495 
 1496         if (rep->re_send_int)
 1497         {
 1498                 if (rep->re_tx_mess.m_type == DL_WRITEV)
 1499                 {
 1500                         rl_writev(&rep->re_tx_mess, TRUE /* from int */,
 1501                                 TRUE /* vectored */);
 1502                 }
 1503                 else
 1504                 {
 1505                         assert(rep->re_tx_mess.m_type == DL_WRITE);
 1506                         rl_writev(&rep->re_tx_mess, TRUE /* from int */,
 1507                                 FALSE /* !vectored */);
 1508                 }
 1509         }
 1510 
 1511         if (rep->re_report_link)
 1512                 rl_report_link(rep);
 1513 
 1514         if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
 1515                 reply(rep, OK, TRUE);
 1516 }
 1517 
 1518 /*===========================================================================*
 1519  *                              rl_report_link                               *
 1520  *===========================================================================*/
 1521 static void rl_report_link(rep)
 1522 re_t *rep;
 1523 {
 1524         port_t port;
 1525         u16_t mii_ctrl, mii_status, mii_ana, mii_anlpa, mii_ane, mii_extstat;
 1526         u8_t msr;
 1527         int f, link_up;
 1528 
 1529         rep->re_report_link= FALSE;
 1530         port= rep->re_base_port;
 1531         msr= rl_inb(port, RL_MSR);
 1532         link_up= !(msr & RL_MSR_LINKB);
 1533         rep->re_link_up= link_up;
 1534         if (!link_up)
 1535         {
 1536                 printf("%s: link down\n", rep->re_name);
 1537                 return;
 1538         }
 1539 
 1540         mii_ctrl= rl_inw(port, RL_BMCR);
 1541         mii_status= rl_inw(port, RL_BMSR);
 1542         mii_ana= rl_inw(port, RL_ANAR);
 1543         mii_anlpa= rl_inw(port, RL_ANLPAR);
 1544         mii_ane= rl_inw(port, RL_ANER);
 1545         mii_extstat= 0;
 1546 
 1547         if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
 1548         {
 1549                 printf("%s: PHY: ", rep->re_name);
 1550                 f= 1;
 1551                 if (mii_ctrl & MII_CTRL_LB)
 1552                 {
 1553                         printf("loopback mode");
 1554                         f= 0;
 1555                 }
 1556                 if (mii_ctrl & MII_CTRL_PD)
 1557                 {
 1558                         if (!f) printf(", ");
 1559                         f= 0;
 1560                         printf("powered down");
 1561                 }
 1562                 if (mii_ctrl & MII_CTRL_ISO)
 1563                 {
 1564                         if (!f) printf(", ");
 1565                         f= 0;
 1566                         printf("isolated");
 1567                 }
 1568                 printf("\n");
 1569                 return;
 1570         }
 1571         if (!(mii_ctrl & MII_CTRL_ANE))
 1572         {
 1573                 printf("%s: manual config: ", rep->re_name);
 1574                 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
 1575                 {
 1576                 case MII_CTRL_SP_10:    printf("10 Mbps"); break;
 1577                 case MII_CTRL_SP_100:   printf("100 Mbps"); break;
 1578                 case MII_CTRL_SP_1000:  printf("1000 Mbps"); break;
 1579                 case MII_CTRL_SP_RES:   printf("reserved speed"); break;
 1580                 }
 1581                 if (mii_ctrl & MII_CTRL_DM)
 1582                         printf(", full duplex");
 1583                 else
 1584                         printf(", half duplex");
 1585                 printf("\n");
 1586                 return;
 1587         }
 1588 
 1589         if (!debug) goto resspeed;
 1590 
 1591         printf("%s: ", rep->re_name);
 1592         mii_print_stat_speed(mii_status, mii_extstat);
 1593         printf("\n");
 1594 
 1595         if (!(mii_status & MII_STATUS_ANC))
 1596                 printf("%s: auto-negotiation not complete\n", rep->re_name);
 1597         if (mii_status & MII_STATUS_RF)
 1598                 printf("%s: remote fault detected\n", rep->re_name);
 1599         if (!(mii_status & MII_STATUS_ANA))
 1600         {
 1601                 printf("%s: local PHY has no auto-negotiation ability\n",
 1602                         rep->re_name);
 1603         }
 1604         if (!(mii_status & MII_STATUS_LS))
 1605                 printf("%s: link down\n", rep->re_name);
 1606         if (mii_status & MII_STATUS_JD)
 1607                 printf("%s: jabber condition detected\n", rep->re_name);
 1608         if (!(mii_status & MII_STATUS_EC))
 1609         {
 1610                 printf("%s: no extended register set\n", rep->re_name);
 1611                 goto resspeed;
 1612         }
 1613         if (!(mii_status & MII_STATUS_ANC))
 1614                 goto resspeed;
 1615 
 1616         printf("%s: local cap.: ", rep->re_name);
 1617         mii_print_techab(mii_ana);
 1618         printf("\n");
 1619 
 1620         if (mii_ane & MII_ANE_PDF)
 1621                 printf("%s: parallel detection fault\n", rep->re_name);
 1622         if (!(mii_ane & MII_ANE_LPANA))
 1623         {
 1624                 printf("%s: link-partner does not support auto-negotiation\n",
 1625                         rep->re_name);
 1626                 goto resspeed;
 1627         }
 1628 
 1629         printf("%s: remote cap.: ", rep->re_name);
 1630         mii_print_techab(mii_anlpa);
 1631         printf("\n");
 1632 
 1633 resspeed:
 1634         printf("%s: ", rep->re_name);
 1635         printf("link up at %d Mbps, ", (msr & RL_MSR_SPEED_10) ? 10 : 100);
 1636         printf("%s duplex\n", ((mii_ctrl & MII_CTRL_DM) ? "full" : "half"));
 1637 
 1638 }
 1639 
 1640 static void mii_print_techab(techab)
 1641 u16_t techab;
 1642 {
 1643         int fs, ft;
 1644         if ((techab & MII_ANA_SEL_M) != MII_ANA_SEL_802_3)
 1645         {
 1646                 printf("strange selector 0x%x, value 0x%x",
 1647                         techab & MII_ANA_SEL_M,
 1648                         (techab & MII_ANA_TAF_M) >> MII_ANA_TAF_S);
 1649                 return;
 1650         }
 1651         fs= 1;
 1652         if (techab & (MII_ANA_100T4 | MII_ANA_100TXFD | MII_ANA_100TXHD))
 1653         {
 1654                 printf("100 Mbps: ");
 1655                 fs= 0;
 1656                 ft= 1;
 1657                 if (techab & MII_ANA_100T4)
 1658                 {
 1659                         printf("T4");
 1660                         ft= 0;
 1661                 }
 1662                 if (techab & (MII_ANA_100TXFD | MII_ANA_100TXHD))
 1663                 {
 1664                         if (!ft)
 1665                                 printf(", ");
 1666                         ft= 0;
 1667                         printf("TX-");
 1668                         switch(techab & (MII_ANA_100TXFD|MII_ANA_100TXHD))
 1669                         {
 1670                         case MII_ANA_100TXFD:   printf("FD"); break;
 1671                         case MII_ANA_100TXHD:   printf("HD"); break;
 1672                         default:                printf("FD/HD"); break;
 1673                         }
 1674                 }
 1675         }
 1676         if (techab & (MII_ANA_10TFD | MII_ANA_10THD))
 1677         {
 1678                 if (!fs)
 1679                         printf(", ");
 1680                 printf("10 Mbps: ");
 1681                 fs= 0;
 1682                 printf("T-");
 1683                 switch(techab & (MII_ANA_10TFD|MII_ANA_10THD))
 1684                 {
 1685                 case MII_ANA_10TFD:     printf("FD"); break;
 1686                 case MII_ANA_10THD:     printf("HD"); break;
 1687                 default:                printf("FD/HD"); break;
 1688                 }
 1689         }
 1690         if (techab & MII_ANA_PAUSE_SYM)
 1691         {
 1692                 if (!fs)
 1693                         printf(", ");
 1694                 fs= 0;
 1695                 printf("pause(SYM)");
 1696         }
 1697         if (techab & MII_ANA_PAUSE_ASYM)
 1698         {
 1699                 if (!fs)
 1700                         printf(", ");
 1701                 fs= 0;
 1702                 printf("pause(ASYM)");
 1703         }
 1704         if (techab & MII_ANA_TAF_RES)
 1705         {
 1706                 if (!fs)
 1707                         printf(", ");
 1708                 fs= 0;
 1709                 printf("0x%x", (techab & MII_ANA_TAF_RES) >> MII_ANA_TAF_S);
 1710         }
 1711 }
 1712 
 1713 static void mii_print_stat_speed(stat, extstat)
 1714 u16_t stat;
 1715 u16_t extstat;
 1716 {
 1717         int fs, ft;
 1718         fs= 1;
 1719         if (stat & MII_STATUS_EXT_STAT)
 1720         {
 1721                 if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD |
 1722                         MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
 1723                 {
 1724                         printf("1000 Mbps: ");
 1725                         fs= 0;
 1726                         ft= 1;
 1727                         if (extstat & (MII_ESTAT_1000XFD | MII_ESTAT_1000XHD))
 1728                         {
 1729                                 ft= 0;
 1730                                 printf("X-");
 1731                                 switch(extstat &
 1732                                         (MII_ESTAT_1000XFD|MII_ESTAT_1000XHD))
 1733                                 {
 1734                                 case MII_ESTAT_1000XFD: printf("FD"); break;
 1735                                 case MII_ESTAT_1000XHD: printf("HD"); break;
 1736                                 default:                printf("FD/HD"); break;
 1737                                 }
 1738                         }
 1739                         if (extstat & (MII_ESTAT_1000TFD | MII_ESTAT_1000THD))
 1740                         {
 1741                                 if (!ft)
 1742                                         printf(", ");
 1743                                 ft= 0;
 1744                                 printf("T-");
 1745                                 switch(extstat &
 1746                                         (MII_ESTAT_1000TFD|MII_ESTAT_1000THD))
 1747                                 {
 1748                                 case MII_ESTAT_1000TFD: printf("FD"); break;
 1749                                 case MII_ESTAT_1000THD: printf("HD"); break;
 1750                                 default:                printf("FD/HD"); break;
 1751                                 }
 1752                         }
 1753                 }
 1754         }
 1755         if (stat & (MII_STATUS_100T4 |
 1756                 MII_STATUS_100XFD | MII_STATUS_100XHD |
 1757                 MII_STATUS_100T2FD | MII_STATUS_100T2HD))
 1758         {
 1759                 if (!fs)
 1760                         printf(", ");
 1761                 fs= 0;
 1762                 printf("100 Mbps: ");
 1763                 ft= 1;
 1764                 if (stat & MII_STATUS_100T4)
 1765                 {
 1766                         printf("T4");
 1767                         ft= 0;
 1768                 }
 1769                 if (stat & (MII_STATUS_100XFD | MII_STATUS_100XHD))
 1770                 {
 1771                         if (!ft)
 1772                                 printf(", ");
 1773                         ft= 0;
 1774                         printf("TX-");
 1775                         switch(stat & (MII_STATUS_100XFD|MII_STATUS_100XHD))
 1776                         {
 1777                         case MII_STATUS_100XFD: printf("FD"); break;
 1778                         case MII_STATUS_100XHD: printf("HD"); break;
 1779                         default:                printf("FD/HD"); break;
 1780                         }
 1781                 }
 1782                 if (stat & (MII_STATUS_100T2FD | MII_STATUS_100T2HD))
 1783                 {
 1784                         if (!ft)
 1785                                 printf(", ");
 1786                         ft= 0;
 1787                         printf("T2-");
 1788                         switch(stat & (MII_STATUS_100T2FD|MII_STATUS_100T2HD))
 1789                         {
 1790                         case MII_STATUS_100T2FD:        printf("FD"); break;
 1791                         case MII_STATUS_100T2HD:        printf("HD"); break;
 1792                         default:                printf("FD/HD"); break;
 1793                         }
 1794                 }
 1795         }
 1796         if (stat & (MII_STATUS_10FD | MII_STATUS_10HD))
 1797         {
 1798                 if (!fs)
 1799                         printf(", ");
 1800                 printf("10 Mbps: ");
 1801                 fs= 0;
 1802                 printf("T-");
 1803                 switch(stat & (MII_STATUS_10FD|MII_STATUS_10HD))
 1804                 {
 1805                 case MII_STATUS_10FD:   printf("FD"); break;
 1806                 case MII_STATUS_10HD:   printf("HD"); break;
 1807                 default:                printf("FD/HD"); break;
 1808                 }
 1809         }
 1810 }
 1811 
 1812 /*===========================================================================*
 1813  *                              rl_clear_rx                                  *
 1814  *===========================================================================*/
 1815 static void rl_clear_rx(rep)
 1816 re_t *rep;
 1817 {
 1818         port_t port;
 1819         u8_t cr;
 1820         int i;
 1821         clock_t t0,t1;
 1822 
 1823         rep->re_clear_rx= FALSE;
 1824         port= rep->re_base_port;
 1825 
 1826         /* Reset the receiver */
 1827         cr= rl_inb(port, RL_CR);
 1828         cr &= ~RL_CR_RE;
 1829         rl_outb(port, RL_CR, cr);
 1830         getuptime(&t0);
 1831         do {
 1832                 if (!(rl_inb(port, RL_CR) & RL_CR_RE))
 1833                         break;
 1834         } while (getuptime(&t1)==OK && (t1-t0) < HZ);
 1835         if (rl_inb(port, RL_CR) & RL_CR_RE)
 1836                 panic("rtl8139","cannot disable receiver", NO_NUM);
 1837 
 1838 #if 0
 1839         printf("RBSTART = 0x%08x\n", rl_inl(port, RL_RBSTART));
 1840         printf("CAPR = 0x%04x\n", rl_inw(port, RL_CAPR));
 1841         printf("CBR = 0x%04x\n", rl_inw(port, RL_CBR));
 1842         printf("RCR = 0x%08x\n", rl_inl(port, RL_RCR));
 1843 #endif
 1844 
 1845         rl_outb(port, RL_CR, cr | RL_CR_RE);
 1846 
 1847         rl_outl(port, RL_RCR, RX_BUFBITS);
 1848 
 1849         rl_rec_mode(rep);
 1850 
 1851         rep->re_stat.ets_missedP++;
 1852 }
 1853 
 1854 /*===========================================================================*
 1855  *                              rl_do_reset                                  *
 1856  *===========================================================================*/
 1857 static void rl_do_reset(rep)
 1858 re_t *rep;
 1859 {
 1860         rep->re_need_reset= FALSE;
 1861         rl_reset_hw(rep);
 1862         rl_rec_mode(rep);
 1863 
 1864         rep->re_tx_head= 0;
 1865         if (rep->re_flags & REF_SEND_AVAIL)
 1866         {
 1867                 rep->re_tx[rep->re_tx_head].ret_busy= FALSE;
 1868                 rep->re_send_int= TRUE;
 1869         }
 1870 }
 1871 
 1872 /*===========================================================================*
 1873  *                              rl_getstat                                   *
 1874  *===========================================================================*/
 1875 static void rl_getstat(mp)
 1876 message *mp;
 1877 {
 1878         int port;
 1879         eth_stat_t stats;
 1880         re_t *rep;
 1881 
 1882         port = mp->DL_PORT;
 1883         if (port < 0 || port >= RE_PORT_NR)
 1884                 panic("rtl8139","illegal port", port);
 1885         rep= &re_table[port];
 1886         rep->re_client= mp->DL_PROC;
 1887 
 1888         assert(rep->re_mode == REM_ENABLED);
 1889         assert(rep->re_flags & REF_ENABLED);
 1890 
 1891         stats= rep->re_stat;
 1892 
 1893         put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
 1894                 (vir_bytes) sizeof(stats), &stats);
 1895         reply(rep, OK, FALSE);
 1896 }
 1897 
 1898 
 1899 /*===========================================================================*
 1900  *                              rl_getname                                   *
 1901  *===========================================================================*/
 1902 static void rl_getname(mp)
 1903 message *mp;
 1904 {
 1905         int r;
 1906 
 1907         strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
 1908         mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
 1909         mp->m_type= DL_NAME_REPLY;
 1910         r= send(mp->m_source, mp);
 1911         if (r != OK)
 1912                 panic("RTL8139", "rl_getname: send failed: %d\n", r);
 1913 }
 1914 
 1915 
 1916 /*===========================================================================*
 1917  *                              reply                                        *
 1918  *===========================================================================*/
 1919 static void reply(rep, err, may_block)
 1920 re_t *rep;
 1921 int err;
 1922 int may_block;
 1923 {
 1924         message reply;
 1925         int status;
 1926         int r;
 1927         clock_t now;
 1928 
 1929         status = 0;
 1930         if (rep->re_flags & REF_PACK_SENT)
 1931                 status |= DL_PACK_SEND;
 1932         if (rep->re_flags & REF_PACK_RECV)
 1933                 status |= DL_PACK_RECV;
 1934 
 1935         reply.m_type = DL_TASK_REPLY;
 1936         reply.DL_PORT = rep - re_table;
 1937         reply.DL_PROC = rep->re_client;
 1938         reply.DL_STAT = status | ((u32_t) err << 16);
 1939         reply.DL_COUNT = rep->re_read_s;
 1940         if (OK != (r = getuptime(&now)))
 1941                 panic("rtl8139","getuptime() failed:", r);
 1942         reply.DL_CLCK = now;
 1943 
 1944         r= send(rep->re_client, &reply);
 1945 
 1946         if (r == ELOCKED && may_block)
 1947         {
 1948 #if 0
 1949                 printW(); printf("send locked\n");
 1950 #endif
 1951                 return;
 1952         }
 1953 
 1954         if (r < 0) {
 1955                 printf("RTL8139 tried sending to %d, type %d\n", rep->re_client, reply.m_type);
 1956                 panic("rtl8139","send failed:", r);
 1957         }
 1958         
 1959         rep->re_read_s = 0;
 1960         rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
 1961 }
 1962 
 1963 /*===========================================================================*
 1964  *                              mess_reply                                   *
 1965  *===========================================================================*/
 1966 static void mess_reply(req, reply_mess)
 1967 message *req;
 1968 message *reply_mess;
 1969 {
 1970         if (send(req->m_source, reply_mess) != OK)
 1971                 panic("rtl8139","unable to mess_reply", NO_NUM);
 1972 }
 1973 
 1974 /*===========================================================================*
 1975  *                              put_userdata                                 *
 1976  *===========================================================================*/
 1977 static void put_userdata(user_proc, user_addr, count, loc_addr)
 1978 int user_proc;
 1979 vir_bytes user_addr;
 1980 vir_bytes count;
 1981 void *loc_addr;
 1982 {
 1983         int cps;
 1984         cps = sys_datacopy(SELF, (vir_bytes) loc_addr, user_proc, user_addr, count);
 1985         if (cps != OK) printf("RTL8139: warning, scopy failed: %d\n", cps);
 1986 }
 1987 
 1988 #if 0
 1989 static void dump_phy(rep)
 1990 re_t *rep;
 1991 {
 1992         port_t port;
 1993         u32_t t;
 1994 
 1995         port= rep->re_base_port;
 1996 
 1997         t= rl_inb(port, RL_MSR);
 1998         printf("MSR: 0x%02lx\n", t);
 1999         if (t & RL_MSR_SPEED_10)
 2000                 printf("\t10 Mbps\n");
 2001         if (t & RL_MSR_LINKB)
 2002                 printf("\tLink failed\n");
 2003 
 2004         t= rl_inb(port, RL_CONFIG1);
 2005         printf("CONFIG1: 0x%02lx\n", t);
 2006 
 2007         t= rl_inb(port, RL_CONFIG3);
 2008         printf("CONFIG3: 0x%02lx\n", t);
 2009 
 2010         t= rl_inb(port, RL_CONFIG4);
 2011         printf("CONFIG4: 0x%02lx\n", t);
 2012 
 2013         t= rl_inw(port, RL_BMCR);
 2014         printf("BMCR (MII_CTRL): 0x%04lx\n", t);
 2015 
 2016         t= rl_inw(port, RL_BMSR);
 2017         printf("BMSR:");
 2018         if (t & MII_STATUS_100T4)
 2019                 printf(" 100Base-T4");
 2020         if (t & MII_STATUS_100XFD)
 2021                 printf(" 100Base-X-FD");
 2022         if (t & MII_STATUS_100XHD)
 2023                 printf(" 100Base-X-HD");
 2024         if (t & MII_STATUS_10FD)
 2025                 printf(" 10Mbps-FD");
 2026         if (t & MII_STATUS_10HD)
 2027                 printf(" 10Mbps-HD");
 2028         if (t & MII_STATUS_100T2FD)
 2029                 printf(" 100Base-T2-FD");
 2030         if (t & MII_STATUS_100T2HD)
 2031                 printf(" 100Base-T2-HD");
 2032         if (t & MII_STATUS_EXT_STAT)
 2033                 printf(" Ext-stat");
 2034         if (t & MII_STATUS_RES)
 2035                 printf(" res-0x%lx", t & MII_STATUS_RES);
 2036         if (t & MII_STATUS_MFPS)
 2037                 printf(" MFPS");
 2038         if (t & MII_STATUS_ANC)
 2039                 printf(" ANC");
 2040         if (t & MII_STATUS_RF)
 2041                 printf(" remote-fault");
 2042         if (t & MII_STATUS_ANA)
 2043                 printf(" ANA");
 2044         if (t & MII_STATUS_LS)
 2045                 printf(" Link");
 2046         if (t & MII_STATUS_JD)
 2047                 printf(" Jabber");
 2048         if (t & MII_STATUS_EC)
 2049                 printf(" Extended-capability");
 2050         printf("\n");
 2051 
 2052         t= rl_inw(port, RL_ANAR);
 2053         printf("ANAR (MII_ANA): 0x%04lx\n", t);
 2054 
 2055         t= rl_inw(port, RL_ANLPAR);
 2056         printf("ANLPAR: 0x%04lx\n", t);
 2057 
 2058         t= rl_inw(port, RL_ANER);
 2059         printf("ANER (MII_ANE): ");
 2060         if (t & MII_ANE_RES)
 2061                 printf(" res-0x%lx", t & MII_ANE_RES);
 2062         if (t & MII_ANE_PDF)
 2063                 printf(" Par-Detect-Fault");
 2064         if (t & MII_ANE_LPNPA)
 2065                 printf(" LP-Next-Page-Able");
 2066         if (t & MII_ANE_NPA)
 2067                 printf(" Loc-Next-Page-Able");
 2068         if (t & MII_ANE_PR)
 2069                 printf(" Page-Received");
 2070         if (t & MII_ANE_LPANA)
 2071                 printf(" LP-Auto-Neg-Able");
 2072         printf("\n");
 2073 
 2074         t= rl_inw(port, RL_NWAYTR);
 2075         printf("NWAYTR: 0x%04lx\n", t);
 2076         t= rl_inw(port, RL_CSCR);
 2077         printf("CSCR: 0x%04lx\n", t);
 2078 
 2079         t= rl_inb(port, RL_CONFIG5);
 2080         printf("CONFIG5: 0x%02lx\n", t);
 2081 }
 2082 #endif
 2083 
 2084 static int do_hard_int(void)
 2085 {
 2086         int i,s;
 2087 
 2088         for (i=0; i < RE_PORT_NR; i ++) {
 2089 
 2090                 /* Run interrupt handler at driver level. */
 2091                 rl_handler( &re_table[i]);
 2092 
 2093                 /* Reenable interrupts for this hook. */
 2094         if ((s=sys_irqenable(&re_table[i].re_hook_id)) != OK)
 2095                 printf("RTL8139: error, couldn't enable interrupts: %d\n", s);
 2096         }
 2097 }
 2098 
 2099 /*===========================================================================*
 2100  *                              rl_handler                                   *
 2101  *===========================================================================*/
 2102 static int rl_handler(rep)
 2103 re_t *rep;
 2104 {
 2105         int i, port, tx_head, tx_tail, link_up;
 2106         u16_t isr, tsad;
 2107         u32_t tsd, tcr, ertxth;
 2108 #if 0
 2109         u8_t cr;
 2110 #endif
 2111         clock_t t0,t1;
 2112         int_event_check = FALSE;        /* disable check by default */
 2113 
 2114         port= rep->re_base_port;
 2115 
 2116         /* Ack interrupt */
 2117         isr= rl_inw(port, RL_ISR);
 2118         rl_outw(port, RL_ISR, isr);
 2119 
 2120         if (isr & RL_IMR_FOVW)
 2121         {
 2122                 isr &= ~RL_IMR_FOVW;
 2123                 /* Should do anything? */
 2124 
 2125                 rep->re_stat.ets_fifoOver++;
 2126         }
 2127         if (isr & RL_IMR_PUN)
 2128         {
 2129                 isr &= ~RL_IMR_PUN;
 2130 
 2131                 /* Either the link status changed or there was a TX fifo
 2132                  * underrun.
 2133                  */
 2134                 link_up= !(rl_inb(port, RL_MSR) & RL_MSR_LINKB);
 2135                 if (link_up != rep->re_link_up)
 2136                 {
 2137                         rep->re_report_link= TRUE;
 2138                         rep->re_got_int= TRUE;
 2139                         int_event_check = TRUE;
 2140                 }
 2141         }
 2142         if (isr & RL_IMR_RXOVW)
 2143         {
 2144                 isr &= ~RL_IMR_RXOVW;
 2145 
 2146                 /* Clear the receive buffer */
 2147                 rep->re_clear_rx= TRUE;
 2148                 rep->re_got_int= TRUE;
 2149                 int_event_check = TRUE;
 2150         }
 2151 
 2152         if (isr & (RL_ISR_RER | RL_ISR_ROK))
 2153         {
 2154                 isr &= ~(RL_ISR_RER | RL_ISR_ROK);
 2155 
 2156                 if (!rep->re_got_int && (rep->re_flags & REF_READING))
 2157                 {
 2158                         rep->re_got_int= TRUE;
 2159                         int_event_check = TRUE;
 2160                 }
 2161         }
 2162 #if 0
 2163         if ((isr & (RL_ISR_TER | RL_ISR_TOK)) &&
 2164                 (rep->re_flags & REF_SEND_AVAIL) &&
 2165                 (rep->re_tx[0].ret_busy || rep->re_tx[1].ret_busy ||
 2166                 rep->re_tx[2].ret_busy || rep->re_tx[3].ret_busy))
 2167                 
 2168         {
 2169                 printf(
 2170         "rl_handler, SEND_AVAIL: tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
 2171                         rep->re_tx_head, rep->re_tx_tail,
 2172                         rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
 2173                         rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
 2174                 printf(
 2175         "rl_handler: TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
 2176                         rl_inw(port, RL_TSAD),
 2177                         rl_inl(port, RL_TSD0+0*4),
 2178                         rl_inl(port, RL_TSD0+1*4),
 2179                         rl_inl(port, RL_TSD0+2*4),
 2180                         rl_inl(port, RL_TSD0+3*4));
 2181         }
 2182 #endif
 2183         if ((isr & (RL_ISR_TER | RL_ISR_TOK)) || 1)
 2184         {
 2185                 isr &= ~(RL_ISR_TER | RL_ISR_TOK);
 2186 
 2187                 tsad= rl_inw(port, RL_TSAD);
 2188                 if (tsad & (RL_TSAD_TABT0|RL_TSAD_TABT1|
 2189                         RL_TSAD_TABT2|RL_TSAD_TABT3))
 2190                 {
 2191 #if 0
 2192                         /* Do we need a watch dog? */
 2193                         /* Just reset the whole chip */
 2194                         rep->re_need_reset= TRUE;
 2195                         rep->re_got_int= TRUE;
 2196                         int_event_check = TRUE;
 2197 #elif 0
 2198                         /* Reset transmitter */
 2199                         rep->re_stat.ets_transAb++;
 2200 
 2201                         cr= rl_inb(port, RL_CR);
 2202                         cr &= ~RL_CR_TE;
 2203                         rl_outb(port, RL_CR, cr);
 2204                         getuptime(&t0);
 2205                         do {
 2206                                 if (!(rl_inb(port, RL_CR) & RL_CR_TE))
 2207                                         break;
 2208                         } while (getuptime(&t1)==OK && (t1-t0) < HZ);
 2209                         if (rl_inb(port, RL_CR) & RL_CR_TE)
 2210                         {
 2211                           panic("rtl8139","cannot disable transmitter",
 2212                                         NO_NUM);
 2213                         }
 2214                         rl_outb(port, RL_CR, cr | RL_CR_TE);
 2215 
 2216                         tcr= rl_inl(port, RL_TCR);
 2217                         rl_outl(port, RL_TCR, tcr | RL_TCR_IFG_STD);
 2218 
 2219                         printf("rl_handler: reset after abort\n");
 2220 
 2221                         if (rep->re_flags & REF_SEND_AVAIL)
 2222                         {
 2223                                 printf("rl_handler: REF_SEND_AVAIL\n");
 2224                                 rep->re_send_int= TRUE;
 2225                                 rep->re_got_int= TRUE;
 2226                                 int_event_check = TRUE;
 2227                         }
 2228                         for (i= 0; i< N_TX_BUF; i++)
 2229                                 rep->re_tx[i].ret_busy= FALSE;
 2230                         rep->re_tx_head= 0;
 2231 #else
 2232                         printf("rl_handler, TABT, tasd = 0x%04x\n",
 2233                                 tsad);
 2234 
 2235                         /* Find the aborted transmit request */
 2236                         for (i= 0; i< N_TX_BUF; i++)
 2237                         {
 2238                                 tsd= rl_inl(port, RL_TSD0+i*4);
 2239                                 if (tsd & RL_TSD_TABT)
 2240                                         break;
 2241                         }
 2242                         if (i >= N_TX_BUF)
 2243                         {
 2244                                 printf(
 2245                                 "rl_handler: can't find aborted TX req.\n");
 2246                         }
 2247                         else
 2248                         {
 2249                                 printf("TSD%d = 0x%04lx\n", i, tsd);
 2250 
 2251                                 /* Set head and tail to this buffer */
 2252                                 rep->re_tx_head= rep->re_tx_tail= i;
 2253                         }
 2254 
 2255                         /* Aborted transmission, just kick the device
 2256                          * and be done with it.
 2257                          */
 2258                         rep->re_stat.ets_transAb++;
 2259                         tcr= rl_inl(port, RL_TCR);
 2260                         rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
 2261 #endif
 2262                 }
 2263 
 2264                 /* Transmit completed */
 2265                 tx_head= rep->re_tx_head;
 2266                 tx_tail= rep->re_tx_tail;
 2267                 for (i= 0; i< 2*N_TX_BUF; i++)
 2268                 {
 2269                         if (!rep->re_tx[tx_tail].ret_busy)
 2270                         {
 2271                                 /* Strange, this buffer is not in-use.
 2272                                  * Increment tx_tail until tx_head is
 2273                                  * reached (or until we find a buffer that
 2274                                  * is in-use.
 2275                                  */
 2276                                 if (tx_tail == tx_head)
 2277                                         break;
 2278                                 if (++tx_tail >= N_TX_BUF)
 2279                                         tx_tail= 0;
 2280                                 assert(tx_tail < RL_N_TX);
 2281                                 rep->re_tx_tail= tx_tail;
 2282                                 continue;
 2283                         }
 2284                         tsd= rl_inl(port, RL_TSD0+tx_tail*4);
 2285                         if (!(tsd & RL_TSD_OWN))
 2286                         {
 2287                                 /* Buffer is not yet ready */
 2288                                 break;
 2289                         }
 2290 
 2291                         /* Should collect statistics */
 2292                         if (tsd & RL_TSD_CRS)
 2293                                 rep->re_stat.ets_carrSense++;
 2294                         if (tsd & RL_TSD_TABT)
 2295                         {
 2296                                 printf("rl_handler, TABT, TSD%d = 0x%04lx\n",
 2297                                         tx_tail, tsd);
 2298                                 assert(0);      /* CLRABT is not all that
 2299                                                  * effective, why not?
 2300                                                  */
 2301                                 rep->re_stat.ets_transAb++;
 2302                                 tcr= rl_inl(port, RL_TCR);
 2303                                 rl_outl(port, RL_TCR, tcr | RL_TCR_CLRABT);
 2304                         }
 2305                         if (tsd & RL_TSD_OWC)
 2306                                 rep->re_stat.ets_OWC++;
 2307                         if (tsd & RL_TSD_CDH)
 2308                                 rep->re_stat.ets_CDheartbeat++;
 2309 
 2310                         /* What about collisions? */
 2311                         if (tsd & RL_TSD_TOK)
 2312                                 rep->re_stat.ets_packetT++;
 2313                         else
 2314                                 rep->re_stat.ets_sendErr++;
 2315                         if (tsd & RL_TSD_TUN)
 2316                         {
 2317                                 rep->re_stat.ets_fifoUnder++;
 2318 
 2319                                 /* Increase ERTXTH */
 2320                                 ertxth= tsd + (1 << RL_TSD_ERTXTH_S);
 2321                                 ertxth &= RL_TSD_ERTXTH_M;
 2322                                 if (debug && ertxth > rep->re_ertxth)
 2323                                 {
 2324                                         printf("%s: new ertxth: %ld bytes\n",
 2325                                                 rep->re_name,
 2326                                                 (ertxth >> RL_TSD_ERTXTH_S) *
 2327                                                 32);
 2328                                         rep->re_ertxth= ertxth;
 2329                                 }
 2330                         }
 2331                         rep->re_tx[tx_tail].ret_busy= FALSE;
 2332 
 2333 #if 0
 2334                         if (rep->re_flags & REF_SEND_AVAIL)
 2335                         {
 2336                         printf("TSD%d: %08lx\n", tx_tail, tsd);
 2337                         printf(
 2338                         "rl_handler: head %d, tail %d, busy: %d %d %d %d\n", 
 2339                                 tx_head, tx_tail,
 2340                                 rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy, 
 2341                                 rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
 2342                         }
 2343 #endif
 2344 
 2345                         if (++tx_tail >= N_TX_BUF)
 2346                                 tx_tail= 0;
 2347                         assert(tx_tail < RL_N_TX);
 2348                         rep->re_tx_tail= tx_tail;
 2349 
 2350                         if (rep->re_flags & REF_SEND_AVAIL)
 2351                         {
 2352 #if 0
 2353                                 printf("rl_handler: REF_SEND_AVAIL\n");
 2354 #endif
 2355                                 rep->re_send_int= TRUE;
 2356                                 if (!rep->re_got_int)
 2357                                 {
 2358                                         rep->re_got_int= TRUE;
 2359                                         int_event_check = TRUE;
 2360                                 }
 2361                         }
 2362                 }
 2363                 assert(i < 2*N_TX_BUF);
 2364         }
 2365         if (isr)
 2366         {
 2367                 printf("rl_handler: unhandled interrupt: isr = 0x%04x\n",
 2368                         isr);
 2369         }
 2370 
 2371         return 1;
 2372 }
 2373 
 2374 /*===========================================================================*
 2375  *                              rl_watchdog_f                                *
 2376  *===========================================================================*/
 2377 static void rl_watchdog_f(tp)
 2378 timer_t *tp;
 2379 {
 2380         int i;
 2381         re_t *rep;
 2382         /* Use a synchronous alarm instead of a watchdog timer. */
 2383         sys_setalarm(HZ, 0);
 2384 
 2385         for (i= 0, rep = &re_table[0]; i<RE_PORT_NR; i++, rep++)
 2386         {
 2387                 if (rep->re_mode != REM_ENABLED)
 2388                         continue;
 2389                 if (!(rep->re_flags & REF_SEND_AVAIL))
 2390                 {
 2391                         /* Assume that an idle system is alive */
 2392                         rep->re_tx_alive= TRUE;
 2393                         continue;
 2394                 }
 2395                 if (rep->re_tx_alive)
 2396                 {
 2397                         rep->re_tx_alive= FALSE;
 2398                         continue;
 2399                 }
 2400                 printf("rl_watchdog_f: resetting port %d\n", i);
 2401                 printf(
 2402         "TSAD: 0x%04x, TSD: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
 2403                         rl_inw(rep->re_base_port, RL_TSAD),
 2404                         rl_inl(rep->re_base_port, RL_TSD0+0*4),
 2405                         rl_inl(rep->re_base_port, RL_TSD0+1*4),
 2406                         rl_inl(rep->re_base_port, RL_TSD0+2*4),
 2407                         rl_inl(rep->re_base_port, RL_TSD0+3*4));
 2408                 printf("tx_head %d, tx_tail %d, busy: %d %d %d %d\n",
 2409                         rep->re_tx_head, rep->re_tx_tail,
 2410                         rep->re_tx[0].ret_busy, rep->re_tx[1].ret_busy,
 2411                         rep->re_tx[2].ret_busy, rep->re_tx[3].ret_busy);
 2412                 rep->re_need_reset= TRUE;
 2413                 rep->re_got_int= TRUE;
 2414                         
 2415                 check_int_events();
 2416         }
 2417 }
 2418 
 2419 #if 0
 2420 
 2421 _PROTOTYPE( static void rtl_init, (struct dpeth *dep)                   );
 2422 _PROTOTYPE( static u16_t get_ee_word, (dpeth_t *dep, int a)             );
 2423 _PROTOTYPE( static void ee_wen, (dpeth_t *dep)                          );
 2424 _PROTOTYPE( static void set_ee_word, (dpeth_t *dep, int a, U16_t w)     );
 2425 _PROTOTYPE( static void ee_wds, (dpeth_t *dep)                          );
 2426 
 2427 static void rtl_init(dep)
 2428 dpeth_t *dep;
 2429 {
 2430         u8_t reg_a, reg_b, cr, config0, config2, config3;
 2431         int i;
 2432         char val[128];
 2433 
 2434         printf("rtl_init called\n");
 2435         ne_init(dep);
 2436 
 2437         /* ID */
 2438         outb_reg0(dep, DP_CR, CR_PS_P0);
 2439         reg_a = inb_reg0(dep, DP_DUM1);
 2440         reg_b = inb_reg0(dep, DP_DUM2);
 2441 
 2442         printf("rtl_init: '%c', '%c'\n", reg_a, reg_b);
 2443 
 2444         outb_reg0(dep, DP_CR, CR_PS_P3);
 2445         config0 = inb_reg3(dep, 3);
 2446         config2 = inb_reg3(dep, 5);
 2447         config3 = inb_reg3(dep, 6);
 2448         outb_reg0(dep, DP_CR, CR_PS_P0);
 2449 
 2450         printf("rtl_init: config 0/2/3 = %x/%x/%x\n",
 2451                 config0, config2, config3);
 2452 
 2453         if (0 == sys_getkenv("RTL8029FD",9+1, val, sizeof(val)))
 2454         {
 2455                 printf("rtl_init: setting full-duplex mode\n");
 2456                 outb_reg0(dep, DP_CR, CR_PS_P3);
 2457 
 2458                 cr= inb_reg3(dep, 1);
 2459                 outb_reg3(dep, 1, cr | 0xc0);
 2460 
 2461                 outb_reg3(dep, 6, config3 | 0x40);
 2462                 config3 = inb_reg3(dep, 6);
 2463 
 2464                 config2= inb_reg3(dep, 5);
 2465                 outb_reg3(dep, 5, config2 | 0x20);
 2466                 config2= inb_reg3(dep, 5);
 2467 
 2468                 outb_reg3(dep, 1, cr);
 2469 
 2470                 outb_reg0(dep, DP_CR, CR_PS_P0);
 2471 
 2472                 printf("rtl_init: config 2 = %x\n", config2);
 2473                 printf("rtl_init: config 3 = %x\n", config3);
 2474         }
 2475 
 2476         for (i= 0; i<64; i++)
 2477                 printf("%x ", get_ee_word(dep, i));
 2478         printf("\n");
 2479 
 2480         if (0 == sys_getkenv("RTL8029MN",9+1, val, sizeof(val)))
 2481         {
 2482                 ee_wen(dep);
 2483 
 2484                 set_ee_word(dep, 0x78/2, 0x10ec);
 2485                 set_ee_word(dep, 0x7A/2, 0x8029);
 2486                 set_ee_word(dep, 0x7C/2, 0x10ec);
 2487                 set_ee_word(dep, 0x7E/2, 0x8029);
 2488 
 2489                 ee_wds(dep);
 2490 
 2491                 assert(get_ee_word(dep, 0x78/2) == 0x10ec);
 2492                 assert(get_ee_word(dep, 0x7A/2) == 0x8029);
 2493                 assert(get_ee_word(dep, 0x7C/2) == 0x10ec);
 2494                 assert(get_ee_word(dep, 0x7E/2) == 0x8029);
 2495         }
 2496 
 2497         if (0 == sys_getkenv("RTL8029XXX",10+1, val, sizeof(val)))
 2498         {
 2499                 ee_wen(dep);
 2500 
 2501                 set_ee_word(dep, 0x76/2, 0x8029);
 2502 
 2503                 ee_wds(dep);
 2504 
 2505                 assert(get_ee_word(dep, 0x76/2) == 0x8029);
 2506         }
 2507 }
 2508 
 2509 static u16_t get_ee_word(dep, a)
 2510 dpeth_t *dep;
 2511 int a;
 2512 {
 2513         int b, i, cmd;
 2514         u16_t w;
 2515 
 2516         outb_reg0(dep, DP_CR, CR_PS_P3);        /* Bank 3 */
 2517 
 2518         /* Switch to 9346 mode and enable CS */
 2519         outb_reg3(dep, 1, 0x80 | 0x8);
 2520 
 2521         cmd= 0x180 | (a & 0x3f);        /* 1 1 0 a5 a4 a3 a2 a1 a0 */
 2522         for (i= 8; i >= 0; i--)
 2523         {
 2524                 b= (cmd & (1 << i));
 2525                 b= (b ? 2 : 0);
 2526 
 2527                 /* Cmd goes out on the rising edge of the clock */
 2528                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2529                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
 2530         }
 2531         outb_reg3(dep, 1, 0x80 | 0x8);  /* End of cmd */
 2532 
 2533         w= 0;
 2534         for (i= 0; i<16; i++)
 2535         {
 2536                 w <<= 1;
 2537 
 2538                 /* Data is shifted out on the rising edge. Read at the
 2539                  * falling edge.
 2540                  */
 2541                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4);
 2542                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2543                 b= inb_reg3(dep, 1);
 2544                 w |= (b & 1);
 2545         }
 2546 
 2547         outb_reg3(dep, 1, 0x80);                /* drop CS */
 2548         outb_reg3(dep, 1, 0x00);                /* back to normal */
 2549         outb_reg0(dep, DP_CR, CR_PS_P0);        /* back to bank 0 */
 2550 
 2551         return w;
 2552 }
 2553 
 2554 static void ee_wen(dep)
 2555 dpeth_t *dep;
 2556 {
 2557         int b, i, cmd;
 2558         u16_t w;
 2559 
 2560         outb_reg0(dep, DP_CR, CR_PS_P3);        /* Bank 3 */
 2561 
 2562         /* Switch to 9346 mode and enable CS */
 2563         outb_reg3(dep, 1, 0x80 | 0x8);
 2564 
 2565         cmd= 0x130;             /* 1 0 0 1 1 x x x x */
 2566         for (i= 8; i >= 0; i--)
 2567         {
 2568                 b= (cmd & (1 << i));
 2569                 b= (b ? 2 : 0);
 2570 
 2571                 /* Cmd goes out on the rising edge of the clock */
 2572                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2573                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
 2574         }
 2575         outb_reg3(dep, 1, 0x80 | 0x8);  /* End of cmd */
 2576         outb_reg3(dep, 1, 0x80);        /* Drop CS */
 2577         /* micro_delay(1); */                   /* Is this required? */
 2578 }
 2579 
 2580 static void set_ee_word(dep, a, w)
 2581 dpeth_t *dep;
 2582 int a;
 2583 u16_t w;
 2584 {
 2585         int b, i, cmd;
 2586         clock_t t0, t1;
 2587 
 2588         outb_reg3(dep, 1, 0x80 | 0x8);          /* Set CS */
 2589 
 2590         cmd= 0x140 | (a & 0x3f);                /* 1 0 1 a5 a4 a3 a2 a1 a0 */
 2591         for (i= 8; i >= 0; i--)
 2592         {
 2593                 b= (cmd & (1 << i));
 2594                 b= (b ? 2 : 0);
 2595 
 2596                 /* Cmd goes out on the rising edge of the clock */
 2597                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2598                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
 2599         }
 2600         for (i= 15; i >= 0; i--)
 2601         {
 2602                 b= (w & (1 << i));
 2603                 b= (b ? 2 : 0);
 2604 
 2605                 /* Cmd goes out on the rising edge of the clock */
 2606                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2607                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
 2608         }
 2609         outb_reg3(dep, 1, 0x80 | 0x8);  /* End of data */
 2610         outb_reg3(dep, 1, 0x80);        /* Drop CS */
 2611         /* micro_delay(1); */                   /* Is this required? */
 2612         outb_reg3(dep, 1, 0x80 | 0x8);          /* Set CS */
 2613         getuptime(&t0);
 2614         do {
 2615                 if (inb_reg3(dep, 1) & 1)
 2616                         break;
 2617         } while (getuptime(&t1) == OK && (t1 == t0));
 2618         if (!(inb_reg3(dep, 1) & 1))
 2619                 panic("set_ee_word","device remains busy", NO_NUM);
 2620 }
 2621 
 2622 static void ee_wds(dep)
 2623 dpeth_t *dep;
 2624 {
 2625         int b, i, cmd;
 2626         u16_t w;
 2627 
 2628         outb_reg0(dep, DP_CR, CR_PS_P3);        /* Bank 3 */
 2629 
 2630         /* Switch to 9346 mode and enable CS */
 2631         outb_reg3(dep, 1, 0x80 | 0x8);
 2632 
 2633         cmd= 0x100;             /* 1 0 0 0 0 x x x x */
 2634         for (i= 8; i >= 0; i--)
 2635         {
 2636                 b= (cmd & (1 << i));
 2637                 b= (b ? 2 : 0);
 2638 
 2639                 /* Cmd goes out on the rising edge of the clock */
 2640                 outb_reg3(dep, 1, 0x80 | 0x8 | b);
 2641                 outb_reg3(dep, 1, 0x80 | 0x8 | 0x4 | b);
 2642         }
 2643         outb_reg3(dep, 1, 0x80 | 0x8);  /* End of cmd */
 2644         outb_reg3(dep, 1, 0x80);        /* Drop CS */
 2645         outb_reg3(dep, 1, 0x00);                /* back to normal */
 2646         outb_reg0(dep, DP_CR, CR_PS_P0);        /* back to bank 0 */
 2647 }
 2648 #endif
 2649 
 2650 /*
 2651  * $PchId: rtl8139.c,v 1.3 2003/09/11 14:15:15 philip Exp $
 2652  */

Cache object: 510f338e63b3b6a52bb1a475969803e0


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