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/fxp/fxp.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  * fxp.c
    3  *
    4  * This file contains an ethernet device driver for Intel 82557, 82558, 
    5  * 82559, 82550, and 82562 fast ethernet controllers.
    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  * | HARDINT    |          |         |          |         |         |
   12  * |------------|----------|---------|----------|---------|---------|
   13  * | DL_WRITE   | port nr  | proc nr | count    | mode    | address |
   14  * |------------|----------|---------|----------|---------|---------|
   15  * | DL_WRITEV  | port nr  | proc nr | count    | mode    | address |
   16  * |------------|----------|---------|----------|---------|---------|
   17  * | DL_READ    | port nr  | proc nr | count    |         | address |
   18  * |------------|----------|---------|----------|---------|---------|
   19  * | DL_READV   | port nr  | proc nr | count    |         | address |
   20  * |------------|----------|---------|----------|---------|---------|
   21  * | DL_INIT    | port nr  | proc nr | mode     |         | address |
   22  * |------------|----------|---------|----------|---------|---------|
   23  * | DL_GETSTAT | port nr  | proc nr |          |         | address |
   24  * |------------|----------|---------|----------|---------|---------|
   25  * | DL_STOP    | port_nr  |         |          |         |         |
   26  * |------------|----------|---------|----------|---------|---------|
   27  *
   28  * The messages sent are:
   29  *
   30  *   m-type        DL_PORT    DL_PROC   DL_COUNT   DL_STAT   DL_CLCK
   31  * |-------------+----------+---------+----------+---------+---------|
   32  * |DL_TASK_REPLY| port nr  | proc nr | rd-count | err|stat| clock   |
   33  * |-------------+----------+---------+----------+---------+---------|
   34  *
   35  *   m_type        m3_i1     m3_i2       m3_ca1
   36  * |-------------+---------+-----------+---------------|
   37  * |DL_INIT_REPLY| port nr | last port | ethernet addr |
   38  * |-------------+---------+-----------+---------------|
   39  *
   40  * Created:     Nov 2004 by Philip Homburg <philip@f-mnx.phicoh.com>
   41  */
   42 
   43 #include "../drivers.h"
   44 
   45 #include <stdlib.h>
   46 #include <net/hton.h>
   47 #include <net/gen/ether.h>
   48 #include <net/gen/eth_io.h>
   49 
   50 #include <timers.h>
   51 
   52 #define tmra_ut                 timer_t
   53 #define tmra_inittimer(tp)      tmr_inittimer(tp)
   54 #define Proc_number(p)          proc_number(p)
   55 #define debug                   0
   56 #define RAND_UPDATE             /**/
   57 #define printW()                ((void)0)
   58 #define vm_1phys2bus(p)         (p)
   59 
   60 #include "assert.h"
   61 #include "../libpci/pci.h"
   62 #include "fxp.h"
   63 #include "mii.h"
   64 
   65 /* Number of receive buffers */
   66 #define N_RX_BUF        40
   67 
   68 /* Number of transmit buffers */
   69 #define N_TX_BUF        4
   70 
   71 /* I/O vectors are handled IOVEC_NR entries at a time. */
   72 #define IOVEC_NR        16
   73 
   74 /* Configuration */
   75 #define FXP_ENVVAR      "FXPETH"
   76 
   77 struct pcitab
   78 {
   79         u16_t vid;
   80         u16_t did;
   81         int checkclass;
   82 };
   83 
   84 PRIVATE struct pcitab pcitab_fxp[]=
   85 {
   86         { 0x8086, 0x1229, 0 },          /* Intel 82557, etc. */
   87         { 0x8086, 0x2449, 0 },          /* Intel 82801BA/BAM/CA/CAM */
   88 
   89         { 0x0000, 0x0000, 0 }
   90 };
   91 
   92 #define FXP_PORT_NR     1               /* Minix */
   93 
   94 typedef int irq_hook_t;
   95 
   96 /* Translate a pointer to a field in a structure to a pointer to the structure
   97  * itself.  So it translates '&struct_ptr->field' back to 'struct_ptr'.
   98  */
   99 #define structof(type, field, ptr) \
  100         ((type *) (((char *) (ptr)) - offsetof(type, field)))
  101 
  102 #define MICROS_TO_TICKS(m)  (((m)*HZ/1000000)+1)
  103 
  104 static timer_t *fxp_timers= NULL;
  105 static clock_t fxp_next_timeout= 0;
  106 
  107 static void micro_delay(unsigned long usecs);
  108 
  109 /* ignore interrupt for the moment */
  110 #define interrupt(x)    0
  111 
  112 char buffer[70*1024];
  113 
  114 typedef struct fxp
  115 {
  116         port_t fxp_base_port;
  117         int fxp_mode;
  118         int fxp_got_int;
  119         int fxp_send_int;
  120         int fxp_flags;
  121         int fxp_client;
  122         int fxp_features;               /* Needed? */
  123         int fxp_irq;
  124         int fxp_type;                   /* What kind of hardware */
  125         int fxp_ee_addrlen;             /* #EEPROM address bits */
  126         int fxp_tx_alive;
  127         int fxp_need_reset;
  128 
  129         /* Rx */
  130         vir_bytes fxp_read_s;
  131         int fxp_rx_nbuf;
  132         int fxp_rx_bufsize;
  133         struct rfd *fxp_rx_buf;
  134         phys_bytes fxp_rx_busaddr;
  135         int fxp_rx_head;
  136         int fxp_rx_need_restart;
  137         int fxp_need_conf;              /* Re-configure after draining send
  138                                          * queue
  139                                          */
  140 
  141         /* Tx */
  142         int fxp_tx_nbuf;
  143         int fxp_tx_bufsize;
  144         struct tx *fxp_tx_buf;
  145         phys_bytes fxp_tx_busaddr;
  146         int fxp_tx_idle;
  147         int fxp_tx_head;
  148         int fxp_tx_tail;
  149         int fxp_tx_threshold;
  150 
  151         /* Link status */
  152         int fxp_report_link;
  153         int fxp_link_up;
  154         int fxp_mii_busy;
  155         u16_t fxp_mii_scr;
  156 
  157         /* PCI related */
  158         int fxp_seen;                   /* TRUE iff device available */
  159         u8_t fxp_pcibus;        
  160         u8_t fxp_pcidev;        
  161         u8_t fxp_pcifunc;       
  162 
  163         /* 'large' items */
  164         irq_hook_t fxp_hook;
  165         ether_addr_t fxp_address;
  166         message fxp_rx_mess;
  167         message fxp_tx_mess;
  168         struct sc fxp_stat;
  169         u8_t fxp_conf_bytes[CC_BYTES_NR];
  170         char fxp_name[sizeof("fxp#n")];
  171         iovec_t fxp_iovec[IOVEC_NR];
  172 }
  173 fxp_t;
  174 
  175 /* fxp_mode */
  176 #define FM_DISABLED     0x0
  177 #define FM_ENABLED      0x1
  178 
  179 /* fxp_flags */
  180 #define FF_EMPTY        0x000
  181 #define FF_PACK_SENT    0x001
  182 #define FF_PACK_RECV    0x002
  183 #define FF_SEND_AVAIL   0x004
  184 #define FF_READING      0x010
  185 #define FF_PROMISC      0x040
  186 #define FF_MULTI        0x080
  187 #define FF_BROAD        0x100
  188 #define FF_ENABLED      0x200
  189 
  190 /* fxp_features */
  191 #define FFE_NONE        0x0
  192 
  193 /* fxp_type */
  194 #define FT_UNKNOWN      0x0
  195 #define FT_82557        0x1
  196 #define FT_82558A       0x2
  197 #define FT_82559        0x4
  198 
  199 static fxp_t fxp_table[FXP_PORT_NR];
  200 
  201 static int fxp_tasknr= ANY;
  202 static u16_t eth_ign_proto;
  203 static tmra_ut fxp_watchdog;
  204 static char *progname;
  205 
  206 extern int errno;
  207 
  208 #define fxp_inb(port, offset)   (do_inb((port) + (offset)))
  209 #define fxp_inw(port, offset)   (do_inw((port) + (offset)))
  210 #define fxp_inl(port, offset)   (do_inl((port) + (offset)))
  211 #define fxp_outb(port, offset, value)   (do_outb((port) + (offset), (value)))
  212 #define fxp_outw(port, offset, value)   (do_outw((port) + (offset), (value)))
  213 #define fxp_outl(port, offset, value)   (do_outl((port) + (offset), (value)))
  214 
  215 _PROTOTYPE( static void fxp_init, (message *mp)                         );
  216 _PROTOTYPE( static void fxp_pci_conf, (void)                            );
  217 _PROTOTYPE( static int fxp_probe, (fxp_t *fp)                           );
  218 _PROTOTYPE( static void fxp_conf_hw, (fxp_t *fp)                        );
  219 _PROTOTYPE( static void fxp_init_hw, (fxp_t *fp)                        );
  220 _PROTOTYPE( static void fxp_init_buf, (fxp_t *fp)                       );
  221 _PROTOTYPE( static void fxp_reset_hw, (fxp_t *fp)                       );
  222 _PROTOTYPE( static void fxp_confaddr, (fxp_t *fp)                       );
  223 _PROTOTYPE( static void fxp_rec_mode, (fxp_t *fp)                       );
  224 _PROTOTYPE( static void fxp_writev, (message *mp, int from_int,
  225                                                         int vectored)   );
  226 _PROTOTYPE( static void fxp_readv, (message *mp, int from_int, 
  227                                                         int vectored)   );
  228 _PROTOTYPE( static void fxp_do_conf, (fxp_t *fp)                        );
  229 _PROTOTYPE( static void fxp_cu_ptr_cmd, (fxp_t *fp, int cmd,
  230                                 phys_bytes bus_addr, int check_idle)    );
  231 _PROTOTYPE( static void fxp_ru_ptr_cmd, (fxp_t *fp, int cmd,
  232                                 phys_bytes bus_addr, int check_idle)    );
  233 _PROTOTYPE( static void fxp_restart_ru, (fxp_t *fp)                     );
  234 _PROTOTYPE( static void fxp_getstat, (message *mp)                      );
  235 _PROTOTYPE( static void fxp_getname, (message *mp)                      );
  236 _PROTOTYPE( static int fxp_handler, (fxp_t *fp)                         );
  237 _PROTOTYPE( static void fxp_check_ints, (fxp_t *fp)                     );
  238 _PROTOTYPE( static void fxp_watchdog_f, (timer_t *tp)                   );
  239 _PROTOTYPE( static int fxp_link_changed, (fxp_t *fp)                    );
  240 _PROTOTYPE( static void fxp_report_link, (fxp_t *fp)                    );
  241 _PROTOTYPE( static void fxp_stop, (void));
  242 _PROTOTYPE( static void reply, (fxp_t *fp, int err, int may_block)      );
  243 _PROTOTYPE( static void mess_reply, (message *req, message *reply)      );
  244 _PROTOTYPE( static void put_userdata, (int user_proc,
  245                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  246 _PROTOTYPE( static u16_t eeprom_read, (fxp_t *fp, int reg)              );
  247 _PROTOTYPE( static void eeprom_addrsize, (fxp_t *fp)                    );
  248 _PROTOTYPE( static u16_t mii_read, (fxp_t *fp, int reg)                 );
  249 _PROTOTYPE( static void fxp_set_timer,(timer_t *tp, clock_t delta,
  250                                                 tmr_func_t watchdog)    );
  251 _PROTOTYPE( static void fxp_expire_timers,(void)                        );
  252 _PROTOTYPE( static u8_t do_inb, (port_t port)                           );
  253 _PROTOTYPE( static u32_t do_inl, (port_t port)                          );
  254 _PROTOTYPE( static void do_outb, (port_t port, u8_t v)                  );
  255 _PROTOTYPE( static void do_outl, (port_t port, u32_t v)                 );
  256 
  257 /*===========================================================================*
  258  *                              main                                         *
  259  *===========================================================================*/
  260 int main(int argc, char *argv[])
  261 {
  262         message m;
  263         int i, r, tasknr;
  264         fxp_t *fp;
  265         long v;
  266 
  267         if ((fxp_tasknr= getprocnr())<0)
  268                 panic("FXP", "couldn't get proc nr", errno);
  269 
  270         if (argc < 1)
  271                 panic("FXP", "A head which at this time has no name", NO_NUM);
  272         (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
  273 
  274         v= 0;
  275 #if 0
  276         (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
  277 #endif
  278         eth_ign_proto= htons((u16_t) v);
  279 
  280 #if 0   /* What about memory allocation? */
  281         /* Claim buffer memory now under Minix, before MM takes it all. */
  282         for (fp= &fxp_table[0]; fp < fxp_table+FXP_PORT_NR; fp++)
  283                 fxp_init_buf(fp);
  284 #endif
  285 
  286         /* Try to notify inet that we are present (again) */
  287         r = findproc("inet", &tasknr);
  288         if (r == OK)
  289                 notify(tasknr);
  290 
  291         while (TRUE)
  292         {
  293                 if ((r= receive(ANY, &m)) != OK)
  294                         panic("FXP","receive failed", r);
  295 
  296                 switch (m.m_type)
  297                 {
  298                 case DEV_PING:  notify(m.m_source);             continue;
  299                 case DL_WRITEV: fxp_writev(&m, FALSE, TRUE);    break;
  300                 case DL_WRITE:  fxp_writev(&m, FALSE, FALSE);   break;
  301 #if 0
  302                 case DL_READ:   fxp_vread(&m, FALSE);           break;
  303 #endif
  304                 case DL_READV:  fxp_readv(&m, FALSE, TRUE);     break;
  305                 case DL_INIT:   fxp_init(&m);                   break;
  306                 case DL_GETSTAT: fxp_getstat(&m);               break;
  307                 case DL_GETNAME: fxp_getname(&m);               break;
  308                 case HARD_INT:
  309                         for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
  310                         {
  311                                 if (fp->fxp_mode != FM_ENABLED)
  312                                         continue;
  313                                 fxp_handler(fp);
  314 
  315                                 r= sys_irqenable(&fp->fxp_hook);
  316                                 if (r != OK)
  317                                         panic("FXP","unable enable interrupts", r);
  318 
  319                                 if (!fp->fxp_got_int)
  320                                         continue;
  321                                 fp->fxp_got_int= 0;
  322                                 assert(fp->fxp_flags & FF_ENABLED);
  323                                 fxp_check_ints(fp);
  324                         }
  325                         break;
  326                 case SYS_SIG:   {
  327                         sigset_t sigset = m.NOTIFY_ARG;
  328                         if (sigismember(&sigset, SIGKSTOP)) fxp_stop();
  329                         break;
  330                 }
  331                 case SYN_ALARM: fxp_expire_timers();            break;
  332                 default:
  333                         panic("FXP"," illegal message", m.m_type);
  334                 }
  335         }
  336 }
  337 
  338 /*===========================================================================*
  339  *                              fxp_init                                     *
  340  *===========================================================================*/
  341 static void fxp_init(mp)
  342 message *mp;
  343 {
  344         static int first_time= 1;
  345 
  346         int port;
  347         fxp_t *fp;
  348         message reply_mess;
  349 
  350         if (first_time)
  351         {
  352                 first_time= 0;
  353                 fxp_pci_conf(); /* Configure PCI devices. */
  354 
  355                 tmra_inittimer(&fxp_watchdog);
  356                 tmr_arg(&fxp_watchdog)->ta_int= 0;
  357                 fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
  358         }
  359 
  360         port = mp->DL_PORT;
  361         if (port < 0 || port >= FXP_PORT_NR)
  362         {
  363                 reply_mess.m_type= DL_INIT_REPLY;
  364                 reply_mess.m3_i1= ENXIO;
  365                 mess_reply(mp, &reply_mess);
  366                 return;
  367         }
  368         fp= &fxp_table[port];
  369         if (fp->fxp_mode == FM_DISABLED)
  370         {
  371                 /* This is the default, try to (re)locate the device. */
  372                 fxp_conf_hw(fp);
  373                 if (fp->fxp_mode == FM_DISABLED)
  374                 {
  375                         /* Probe failed, or the device is configured off. */
  376                         reply_mess.m_type= DL_INIT_REPLY;
  377                         reply_mess.m3_i1= ENXIO;
  378                         mess_reply(mp, &reply_mess);
  379                         return;
  380                 }
  381                 if (fp->fxp_mode == FM_ENABLED)
  382                         fxp_init_hw(fp);
  383                 fxp_report_link(fp);
  384         }
  385 
  386         assert(fp->fxp_mode == FM_ENABLED);
  387         assert(fp->fxp_flags & FF_ENABLED);
  388 
  389         fp->fxp_flags &= ~(FF_PROMISC | FF_MULTI | FF_BROAD);
  390 
  391         if (mp->DL_MODE & DL_PROMISC_REQ)
  392                 fp->fxp_flags |= FF_PROMISC;
  393         if (mp->DL_MODE & DL_MULTI_REQ)
  394                 fp->fxp_flags |= FF_MULTI;
  395         if (mp->DL_MODE & DL_BROAD_REQ)
  396                 fp->fxp_flags |= FF_BROAD;
  397 
  398         fp->fxp_client = mp->m_source;
  399         fxp_rec_mode(fp);
  400 
  401         reply_mess.m_type = DL_INIT_REPLY;
  402         reply_mess.m3_i1 = mp->DL_PORT;
  403         reply_mess.m3_i2 = FXP_PORT_NR;
  404         *(ether_addr_t *) reply_mess.m3_ca1 = fp->fxp_address;
  405 
  406         mess_reply(mp, &reply_mess);
  407 }
  408 
  409 /*===========================================================================*
  410  *                              fxp_pci_conf                                 *
  411  *===========================================================================*/
  412 static void fxp_pci_conf()
  413 {
  414         static char envvar[] = FXP_ENVVAR "#";
  415         static char envfmt[] = "*:d.d.d";
  416 
  417         int i, h;
  418         fxp_t *fp;
  419         long v;
  420 
  421         for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
  422         {
  423                 strcpy(fp->fxp_name, "fxp#0");
  424                 fp->fxp_name[4] += i;
  425                 fp->fxp_seen= FALSE;
  426                 fp->fxp_features= FFE_NONE;
  427                 envvar[sizeof(FXP_ENVVAR)-1]= ''+i;
  428 #if 0
  429                 if (getenv(envvar) != NULL)
  430                 {
  431                         if (strcmp(getenv(envvar), "off") == 0)
  432                         {
  433                                 fp->fxp_pcibus= 255;
  434                                 continue;
  435                         }
  436                         if (!env_prefix(envvar, "pci"))
  437                                 env_panic(envvar);
  438                 }
  439 #endif
  440 
  441                 v= 0;
  442 #if 0
  443                 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
  444 #endif
  445                 fp->fxp_pcibus= v;
  446                 v= 0;
  447 #if 0
  448                 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
  449 #endif
  450                 fp->fxp_pcidev= v;
  451                 v= 0;
  452 #if 0
  453                 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
  454 #endif
  455                 fp->fxp_pcifunc= v;
  456         }
  457 
  458         pci_init();
  459 
  460         for (h= 1; h >= 0; h--) {
  461                 for (i= 0, fp= fxp_table; i<FXP_PORT_NR; i++, fp++)
  462                 {
  463                         if (fp->fxp_pcibus == 255)
  464                                 continue;
  465                         if (((fp->fxp_pcibus | fp->fxp_pcidev |
  466                                 fp->fxp_pcifunc) != 0) != h)
  467                         {
  468                                 continue;
  469                         }
  470                         if (fxp_probe(fp))
  471                                 fp->fxp_seen= TRUE;
  472                 }
  473         }
  474 }
  475 
  476 /*===========================================================================*
  477  *                              fxp_probe                                    *
  478  *===========================================================================*/
  479 static int fxp_probe(fp)
  480 fxp_t *fp;
  481 {
  482         int i, r, devind, just_one;
  483         u16_t vid, did;
  484         u32_t bar;
  485         u8_t ilr, rev;
  486         char *dname, *str;
  487 
  488         if ((fp->fxp_pcibus | fp->fxp_pcidev | fp->fxp_pcifunc) != 0)
  489         {
  490                 /* Look for specific PCI device */
  491                 r= pci_find_dev(fp->fxp_pcibus, fp->fxp_pcidev,
  492                         fp->fxp_pcifunc, &devind);
  493                 if (r == 0)
  494                 {
  495                         printf("%s: no PCI device found at %d.%d.%d\n",
  496                                 fp->fxp_name, fp->fxp_pcibus,
  497                                 fp->fxp_pcidev, fp->fxp_pcifunc);
  498                         return FALSE;
  499                 }
  500                 pci_ids(devind, &vid, &did);
  501                 just_one= TRUE;
  502         }
  503         else
  504         {
  505                 r= pci_first_dev(&devind, &vid, &did);
  506                 if (r == 0)
  507                         return FALSE;
  508                 just_one= FALSE;
  509         }
  510 
  511         for(;;)
  512         {
  513                 for (i= 0; pcitab_fxp[i].vid != 0; i++)
  514                 {
  515                         if (pcitab_fxp[i].vid != vid)
  516                                 continue;
  517                         if (pcitab_fxp[i].did != did)
  518                                 continue;
  519                         if (pcitab_fxp[i].checkclass)
  520                         {
  521                                 panic("FXP","fxp_probe: class check not implemented",
  522                                         NO_NUM);
  523                         }
  524                         break;
  525                 }
  526                 if (pcitab_fxp[i].vid != 0)
  527                         break;
  528 
  529                 if (just_one)
  530                 {
  531                         printf(
  532                 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
  533                                 fp->fxp_name, vid, did,
  534                                 fp->fxp_pcibus,
  535                                 fp->fxp_pcidev, fp->fxp_pcifunc);
  536                         return FALSE;
  537                 }
  538 
  539                 r= pci_next_dev(&devind, &vid, &did);
  540                 if (!r)
  541                         return FALSE;
  542         }
  543 
  544         dname= pci_dev_name(vid, did);
  545 #if VERBOSE
  546         if (!dname)
  547                 dname= "unknown device";
  548         printf("%s: %s (%04x/%04x) at %s\n",
  549                 fp->fxp_name, dname, vid, did, pci_slot_name(devind));
  550 #endif
  551         pci_reserve(devind);
  552 
  553         bar= pci_attr_r32(devind, PCI_BAR_2) & 0xffffffe0;
  554         if ((bar & 0x3ff) >= 0x100-32 || bar < 0x400)
  555         {
  556                 panic("FXP","fxp_probe: base address is not properly configured",
  557                         NO_NUM);
  558         }
  559         fp->fxp_base_port= bar;
  560 
  561         ilr= pci_attr_r8(devind, PCI_ILR);
  562         fp->fxp_irq= ilr;
  563         if (debug)
  564         {
  565                 printf("%s: using I/O address 0x%lx, IRQ %d\n",
  566                         fp->fxp_name, (unsigned long)bar, ilr);
  567         }
  568 
  569         rev= pci_attr_r8(devind, PCI_REV);
  570         str= NULL;
  571         fp->fxp_type= FT_UNKNOWN;
  572         switch(rev)
  573         {
  574         case FXP_REV_82557A:    str= "82557A";                  /* 0x01 */
  575                                 fp->fxp_type= FT_82557;
  576                                 break;
  577         case FXP_REV_82557B:    str= "82557B"; break;           /* 0x02 */
  578         case FXP_REV_82557C:    str= "82557C"; break;           /* 0x03 */
  579         case FXP_REV_82558A:    str= "82558A";                  /* 0x04 */
  580                                 fp->fxp_type= FT_82558A;
  581                                 break;
  582         case FXP_REV_82558B:    str= "82558B"; break;           /* 0x05 */
  583         case FXP_REV_82559A:    str= "82559A"; break;           /* 0x06 */
  584         case FXP_REV_82559B:    str= "82559B"; break;           /* 0x07 */
  585         case FXP_REV_82559C:    str= "82559C";                  /* 0x08 */
  586                                 fp->fxp_type= FT_82559;
  587                                 break;
  588         case FXP_REV_82559ERA:  str= "82559ER-A"; break;        /* 0x09 */
  589         case FXP_REV_82550_1:   str= "82550(1)"; break;         /* 0x0C */
  590         case FXP_REV_82550_2:   str= "82550(2)"; break;         /* 0x0D */
  591         case FXP_REV_82550_3:   str= "82550(3)"; break;         /* 0x0E */
  592         case FXP_REV_82551_1:   str= "82551(1)"; break;         /* 0x0F */
  593         case FXP_REV_82551_2:   str= "82551(2)"; break;         /* 0x10 */
  594         }
  595 
  596 #if VERBOSE
  597         if (str)
  598                 printf("%s: device revision: %s\n", fp->fxp_name, str);
  599         else
  600                 printf("%s: unknown revision: 0x%x\n", fp->fxp_name, rev);
  601 #endif
  602 
  603         if (fp->fxp_type == FT_UNKNOWN)
  604         {
  605                 printf("fxp_probe: device is not supported by this driver\n");
  606                 return FALSE;
  607         }
  608 
  609         return TRUE;
  610 }
  611 
  612 /*===========================================================================*
  613  *                              fxp_conf_hw                                  *
  614  *===========================================================================*/
  615 static void fxp_conf_hw(fp)
  616 fxp_t *fp;
  617 {
  618         int i;
  619         int mwi, ext_stat1, ext_stat2, lim_fifo, i82503, fc;
  620 
  621         fp->fxp_mode= FM_DISABLED;      /* Superfluous */
  622 
  623         if (!fp->fxp_seen)
  624                 return;
  625 
  626         /* PCI device is present */
  627         fp->fxp_mode= FM_ENABLED;
  628 
  629         fp->fxp_flags= FF_EMPTY;
  630         fp->fxp_got_int= 0;
  631         fp->fxp_send_int= 0;
  632         fp->fxp_ee_addrlen= 0;  /* Unknown */
  633         fp->fxp_need_reset= 0;
  634         fp->fxp_report_link= 0;
  635         fp->fxp_link_up= -1;    /* Unknown */
  636         fp->fxp_mii_busy= 0;
  637         fp->fxp_read_s= 0;
  638         fp->fxp_rx_need_restart= 0;
  639         fp->fxp_need_conf= 0;
  640         fp->fxp_tx_head= 0;
  641         fp->fxp_tx_tail= 0;
  642         fp->fxp_tx_alive= 0;
  643         fp->fxp_tx_threshold= TXTT_MIN;
  644 
  645         /* Try to come up with a sensible configuration for the current
  646          * device. Unfortunately every device is different, defaults are
  647          * not always zero, and some fields are re-used with a completely
  648          * different interpretation. We start out with a sensible default
  649          * for all devices and then add device specific changes.
  650          */
  651         fp->fxp_conf_bytes[0]= CC_BYTES_NR;
  652         fp->fxp_conf_bytes[1]= CTL_DEFAULT | CRL_DEFAULT;
  653         fp->fxp_conf_bytes[2]= CAI_DEFAULT;
  654         fp->fxp_conf_bytes[3]= 0;
  655         fp->fxp_conf_bytes[4]= 0;
  656         fp->fxp_conf_bytes[5]= 0;
  657         fp->fxp_conf_bytes[6]= CCB6_ESC | CCB6_ETCB | CCB6_RES;
  658         fp->fxp_conf_bytes[7]= CUR_1;
  659         fp->fxp_conf_bytes[8]= CCB8_503_MII;
  660         fp->fxp_conf_bytes[9]= 0;
  661         fp->fxp_conf_bytes[10]= CLB_NORMAL | CPAL_DEFAULT | CCB10_NSAI |
  662                                 CCB10_RES1;
  663         fp->fxp_conf_bytes[11]= 0;
  664         fp->fxp_conf_bytes[12]= CIS_DEFAULT;
  665         fp->fxp_conf_bytes[13]= CCB13_DEFAULT;
  666         fp->fxp_conf_bytes[14]= CCB14_DEFAULT;
  667         fp->fxp_conf_bytes[15]= CCB15_RES1 | CCB15_RES2;
  668         fp->fxp_conf_bytes[16]= CCB16_DEFAULT;
  669         fp->fxp_conf_bytes[17]= CCB17_DEFAULT;
  670         fp->fxp_conf_bytes[18]= CCB18_RES1 | CCB18_PFCT | CCB18_PE;
  671         fp->fxp_conf_bytes[19]= CCB19_FDPE;
  672         fp->fxp_conf_bytes[20]= CCB20_PFCL | CCB20_RES1;
  673         fp->fxp_conf_bytes[21]= CCB21_RES21;
  674 
  675 #if VERBOSE
  676         for (i= 0; i<CC_BYTES_NR; i++)
  677                 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
  678         printf("\n");
  679 #endif
  680 
  681         mwi= 0;         /* Do we want "Memory Write and Invalidate"? */
  682         ext_stat1= 0;   /* Do we want extended statistical counters? */
  683         ext_stat2= 0;   /* Do we want even more statistical counters? */
  684         lim_fifo= 0;    /* Limit number of frame in TX FIFO */
  685         i82503= 0;      /* Older 10 Mbps interface on the 82557 */
  686         fc= 0;          /* Flow control */
  687 
  688         switch(fp->fxp_type)
  689         {
  690         case FT_82557:
  691                 if (i82503)
  692                 {
  693                         fp->fxp_conf_bytes[8] &= ~CCB8_503_MII;
  694                         fp->fxp_conf_bytes[15] |= CCB15_CRSCDT;
  695                 }
  696                 break;
  697         case FT_82558A:
  698         case FT_82559:
  699                 if (mwi)
  700                         fp->fxp_conf_bytes[3] |= CCB3_MWIE;
  701                 if (ext_stat1)
  702                         fp->fxp_conf_bytes[6] &= ~CCB6_ESC;
  703                 if (ext_stat2)
  704                         fp->fxp_conf_bytes[6] &= ~CCB6_TCOSC;
  705                 if (lim_fifo)
  706                         fp->fxp_conf_bytes[7] |= CCB7_2FFIFO;
  707                 if (fc)
  708                 {
  709                         /* From FreeBSD driver */
  710                         fp->fxp_conf_bytes[16]= 0x1f;
  711                         fp->fxp_conf_bytes[17]= 0x01;
  712 
  713                         fp->fxp_conf_bytes[19] |= CCB19_FDRSTAFC |
  714                                 CCB19_FDRSTOFC;
  715                 }
  716 
  717                 fp->fxp_conf_bytes[18] |= CCB18_LROK;
  718                 break;
  719         default:
  720                 panic("FXP","fxp_conf_hw: bad device type", fp->fxp_type);
  721         }
  722 
  723 #if VERBOSE
  724         for (i= 0; i<CC_BYTES_NR; i++)
  725                 printf("%d: %0x, ", i, fp->fxp_conf_bytes[i]);
  726         printf("\n");
  727 #endif
  728 }
  729 
  730 /*===========================================================================*
  731  *                              fxp_init_hw                                  *
  732  *===========================================================================*/
  733 static void fxp_init_hw(fp)
  734 fxp_t *fp;
  735 {
  736         int i, r, isr;
  737         port_t port;
  738         u32_t bus_addr;
  739 
  740         port= fp->fxp_base_port;
  741 
  742         fxp_init_buf(fp);
  743 
  744         fp->fxp_flags = FF_EMPTY;
  745         fp->fxp_flags |= FF_ENABLED;
  746 
  747         /* Set the interrupt handler and policy. Do not automatically 
  748          * reenable interrupts. Return the IRQ line number on interrupts.
  749          */
  750         fp->fxp_hook = fp->fxp_irq;
  751         r= sys_irqsetpolicy(fp->fxp_irq, 0, &fp->fxp_hook);
  752         if (r != OK)
  753                 panic("FXP","sys_irqsetpolicy failed", r);
  754 
  755         fxp_reset_hw(fp);
  756 
  757         r= sys_irqenable(&fp->fxp_hook);
  758         if (r != OK)
  759                 panic("FXP","sys_irqenable failed", r);
  760 
  761         /* Reset PHY? */
  762 
  763         fxp_do_conf(fp);
  764 
  765         /* Set pointer to statistical counters */
  766         r= sys_umap(SELF, D, (vir_bytes)&fp->fxp_stat, sizeof(fp->fxp_stat),
  767                 &bus_addr);
  768         if (r != OK)
  769                 panic("FXP","sys_umap failed", r);
  770         fxp_cu_ptr_cmd(fp, SC_CU_LOAD_DCA, bus_addr, TRUE /* check idle */);
  771 
  772         /* Ack previous interrupts */
  773         isr= fxp_inb(port, SCB_INT_STAT);
  774         fxp_outb(port, SCB_INT_STAT, isr);
  775 
  776         /* Enable interrupts */
  777         fxp_outb(port, SCB_INT_MASK, 0);
  778 
  779         fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
  780                 TRUE /* check idle */);
  781 
  782         fxp_confaddr(fp);
  783         if (debug)
  784         {
  785                 printf("%s: Ethernet address ", fp->fxp_name);
  786                 for (i= 0; i < 6; i++)
  787                 {
  788                         printf("%x%c", fp->fxp_address.ea_addr[i],
  789                                 i < 5 ? ':' : '\n');
  790                 }
  791         }
  792 }
  793 
  794 /*===========================================================================*
  795  *                              fxp_init_buf                                 *
  796  *===========================================================================*/
  797 static void fxp_init_buf(fp)
  798 fxp_t *fp;
  799 {
  800         size_t rx_totbufsize, tx_totbufsize, tot_bufsize;
  801         phys_bytes buf;
  802         int i, r;
  803         struct rfd *rfdp;
  804         struct tx *txp;
  805 
  806         fp->fxp_rx_nbuf= N_RX_BUF;
  807         rx_totbufsize= fp->fxp_rx_nbuf * sizeof(struct rfd);
  808         fp->fxp_rx_bufsize= rx_totbufsize;
  809 
  810         fp->fxp_tx_nbuf= N_TX_BUF;
  811         tx_totbufsize= fp->fxp_tx_nbuf * sizeof(struct tx);
  812         fp->fxp_tx_bufsize= tx_totbufsize;
  813 
  814         tot_bufsize= tx_totbufsize + rx_totbufsize;
  815 
  816         /* What about memory allocation? */
  817         {
  818                 static int first_time= 1;
  819 
  820                 assert(first_time);
  821                 first_time= 0;
  822 
  823 #define BUFALIGN        4096
  824                 assert(tot_bufsize <= sizeof(buffer)-BUFALIGN); 
  825                 buf= (phys_bytes)buffer;
  826                 buf += BUFALIGN - (buf % BUFALIGN);
  827         }
  828 
  829         fp->fxp_rx_buf= (struct rfd *)buf;
  830         r= sys_umap(SELF, D, (vir_bytes)buf, rx_totbufsize,
  831                 &fp->fxp_rx_busaddr);
  832         if (r != OK)
  833                 panic("FXP","sys_umap failed", r);
  834         for (i= 0, rfdp= fp->fxp_rx_buf; i<fp->fxp_rx_nbuf; i++, rfdp++)
  835         {
  836                 rfdp->rfd_status= 0;
  837                 rfdp->rfd_command= 0;
  838                 if (i != fp->fxp_rx_nbuf-1)
  839                 {
  840                         r= sys_umap(SELF, D, (vir_bytes)&rfdp[1],
  841                                 sizeof(rfdp[1]), &rfdp->rfd_linkaddr);
  842                         if (r != OK)
  843                                 panic("FXP","sys_umap failed", r);
  844                 }
  845                 else
  846                 {
  847                         rfdp->rfd_linkaddr= fp->fxp_rx_busaddr;
  848                         rfdp->rfd_command |= RFDC_EL;
  849                 }
  850                 rfdp->rfd_reserved= 0;
  851                 rfdp->rfd_res= 0;
  852                 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
  853 
  854         }
  855         fp->fxp_rx_head= 0;
  856 
  857         fp->fxp_tx_buf= (struct tx *)(buf+rx_totbufsize);
  858         r= sys_umap(SELF, D, (vir_bytes)fp->fxp_tx_buf,
  859                 (phys_bytes)tx_totbufsize, &fp->fxp_tx_busaddr);
  860         if (r != OK)
  861                 panic("FXP","sys_umap failed", r);
  862 
  863         for (i= 0, txp= fp->fxp_tx_buf; i<fp->fxp_tx_nbuf; i++, txp++)
  864         {
  865                 txp->tx_status= 0;
  866                 txp->tx_command= TXC_EL | CBL_NOP;      /* Just in case */
  867                 if (i != fp->fxp_tx_nbuf-1)
  868                 {
  869                         r= sys_umap(SELF, D, (vir_bytes)&txp[1],
  870                                 (phys_bytes)sizeof(txp[1]),
  871                                 &txp->tx_linkaddr);
  872                         if (r != OK)
  873                                 panic("FXP","sys_umap failed", r);
  874                 }
  875                 else
  876                 {
  877                         txp->tx_linkaddr= fp->fxp_tx_busaddr;
  878                 }
  879                 txp->tx_tbda= TX_TBDA_NIL;
  880                 txp->tx_size= 0;
  881                 txp->tx_tthresh= fp->fxp_tx_threshold;
  882                 txp->tx_ntbd= 0;
  883         }
  884         fp->fxp_tx_idle= 1;
  885 }
  886 
  887 /*===========================================================================*
  888  *                              fxp_reset_hw                                 *
  889  *===========================================================================*/
  890 static void fxp_reset_hw(fp)
  891 fxp_t *fp;
  892 {
  893 /* Inline the function in init? */
  894         port_t port;
  895 
  896         port= fp->fxp_base_port;
  897 
  898         /* Reset device */
  899         fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
  900         tickdelay(MICROS_TO_TICKS(CSR_PORT_RESET_DELAY));
  901 
  902         /* Disable interrupts */
  903         fxp_outb(port, SCB_INT_MASK, SIM_M);
  904 
  905         /* Set CU base to zero */
  906         fxp_cu_ptr_cmd(fp, SC_CU_LOAD_BASE, 0, TRUE /* check idle */);
  907 
  908         /* Set RU base to zero */
  909         fxp_ru_ptr_cmd(fp, SC_RU_LOAD_BASE, 0, TRUE /* check idle */);
  910 }
  911 
  912 /*===========================================================================*
  913  *                              fxp_confaddr                                 *
  914  *===========================================================================*/
  915 static void fxp_confaddr(fp)
  916 fxp_t *fp;
  917 {
  918         static char eakey[]= FXP_ENVVAR "#_EA";
  919         static char eafmt[]= "x:x:x:x:x:x";
  920         clock_t t0,t1;
  921         int i, r;
  922         port_t port;
  923         u32_t bus_addr;
  924         long v;
  925         struct ias ias;
  926 
  927         port= fp->fxp_base_port;
  928 
  929         /* User defined ethernet address? */
  930         eakey[sizeof(FXP_ENVVAR)-1]= '' + (fp-fxp_table);
  931 
  932 #if 0
  933         for (i= 0; i < 6; i++)
  934         {
  935                 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
  936                         break;
  937                 fp->fxp_address.ea_addr[i]= v;
  938         }
  939 #else
  940         i= 0;
  941 #endif
  942 
  943 #if 0
  944         if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
  945 #endif
  946 
  947         if (i == 0)
  948         {
  949                 /* Get ethernet address from EEPROM */
  950                 for (i= 0; i<3; i++)
  951                 {
  952                         v= eeprom_read(fp, i);
  953                         fp->fxp_address.ea_addr[i*2]= (v & 0xff);
  954                         fp->fxp_address.ea_addr[i*2+1]= ((v >> 8) & 0xff);
  955                 }
  956         }
  957 
  958         /* Tell NIC about ethernet address */
  959         ias.ias_status= 0;
  960         ias.ias_command= CBL_C_EL | CBL_AIS;
  961         ias.ias_linkaddr= 0;
  962         memcpy(ias.ias_ethaddr, fp->fxp_address.ea_addr,
  963                 sizeof(ias.ias_ethaddr));
  964         r= sys_umap(SELF, D, (vir_bytes)&ias, (phys_bytes)sizeof(ias),
  965                 &bus_addr);
  966         if (r != OK)
  967                 panic("FXP","sys_umap failed", r);
  968 
  969         fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
  970 
  971         getuptime(&t0);
  972         do {
  973                 /* Wait for CU command to complete */
  974                 if (ias.ias_status & CBL_F_C)
  975                         break;
  976         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
  977 
  978         if (!(ias.ias_status & CBL_F_C))
  979                 panic("FXP","fxp_confaddr: CU command failed to complete", NO_NUM);
  980         if (!(ias.ias_status & CBL_F_OK))
  981                 panic("FXP","fxp_confaddr: CU command failed", NO_NUM);
  982 
  983 #if VERBOSE
  984         printf("%s: hardware ethernet address: ", fp->fxp_name);
  985         for (i= 0; i<6; i++)
  986         {
  987                 printf("%02x%s", fp->fxp_address.ea_addr[i], 
  988                         i < 5 ? ":" : "");
  989         }
  990         printf("\n");
  991 #endif
  992 }
  993 
  994 /*===========================================================================*
  995  *                              fxp_rec_mode                                 *
  996  *===========================================================================*/
  997 static void fxp_rec_mode(fp)
  998 fxp_t *fp;
  999 {
 1000         fp->fxp_conf_bytes[0]= CC_BYTES_NR;     /* Just to be sure */
 1001         fp->fxp_conf_bytes[15] &= ~(CCB15_BD|CCB15_PM);
 1002         fp->fxp_conf_bytes[21] &= ~CCB21_MA;
 1003 
 1004         if (fp->fxp_flags & FF_PROMISC)
 1005                 fp->fxp_conf_bytes[15] |= CCB15_PM;
 1006         if (fp->fxp_flags & FF_MULTI)
 1007                 fp->fxp_conf_bytes[21] |= CCB21_MA;
 1008 
 1009         if (!(fp->fxp_flags & (FF_BROAD|FF_MULTI|FF_PROMISC)))
 1010                 fp->fxp_conf_bytes[15] |= CCB15_BD;
 1011 
 1012         /* Queue request if not idle */
 1013         if (fp->fxp_tx_idle)
 1014         {
 1015                 fxp_do_conf(fp);
 1016         }
 1017         else
 1018         {
 1019                 printf("fxp_rec_mode: setting fxp_need_conf\n");
 1020                 fp->fxp_need_conf= TRUE;
 1021         }
 1022 }
 1023 
 1024 /*===========================================================================*
 1025  *                              fxp_writev                                   *
 1026  *===========================================================================*/
 1027 static void fxp_writev(mp, from_int, vectored)
 1028 message *mp;
 1029 int from_int;
 1030 int vectored;
 1031 {
 1032         vir_bytes iov_src;
 1033         int i, j, n, o, r, s, dl_port, count, size, prev_head;
 1034         int fxp_client, fxp_tx_nbuf, fxp_tx_head;
 1035         u16_t tx_command;
 1036         fxp_t *fp;
 1037         iovec_t *iovp;
 1038         struct tx *txp, *prev_txp;
 1039 
 1040         dl_port = mp->DL_PORT;
 1041         count = mp->DL_COUNT;
 1042         if (dl_port < 0 || dl_port >= FXP_PORT_NR)
 1043                 panic("FXP","fxp_writev: illegal port", dl_port);
 1044         fp= &fxp_table[dl_port];
 1045         fxp_client= mp->DL_PROC;
 1046         fp->fxp_client= fxp_client;
 1047 
 1048         assert(fp->fxp_mode == FM_ENABLED);
 1049         assert(fp->fxp_flags & FF_ENABLED);
 1050 
 1051         if (from_int)
 1052         {
 1053                 assert(fp->fxp_flags & FF_SEND_AVAIL);
 1054                 fp->fxp_flags &= ~FF_SEND_AVAIL;
 1055                 fp->fxp_tx_alive= TRUE;
 1056         }
 1057 
 1058         if (fp->fxp_tx_idle)
 1059         {
 1060                 txp= fp->fxp_tx_buf;
 1061                 fxp_tx_head= 0; /* lint */
 1062                 prev_txp= NULL; /* lint */
 1063         }
 1064         else
 1065         {       
 1066                 fxp_tx_nbuf= fp->fxp_tx_nbuf;
 1067                 prev_head= fp->fxp_tx_head;
 1068                 fxp_tx_head= prev_head+1;
 1069                 if (fxp_tx_head == fxp_tx_nbuf)
 1070                         fxp_tx_head= 0;
 1071                 assert(fxp_tx_head < fxp_tx_nbuf);
 1072 
 1073                 if (fxp_tx_head == fp->fxp_tx_tail)
 1074                 {
 1075                         /* Send queue is full */
 1076                         assert(!(fp->fxp_flags & FF_SEND_AVAIL));
 1077                         fp->fxp_flags |= FF_SEND_AVAIL;
 1078                         goto suspend;
 1079                 }
 1080 
 1081                 prev_txp= &fp->fxp_tx_buf[prev_head];
 1082                 txp= &fp->fxp_tx_buf[fxp_tx_head];
 1083         }
 1084 
 1085         assert(!(fp->fxp_flags & FF_SEND_AVAIL));
 1086         assert(!(fp->fxp_flags & FF_PACK_SENT));
 1087 
 1088         if (vectored)
 1089         {
 1090 
 1091                 iov_src = (vir_bytes)mp->DL_ADDR;
 1092 
 1093                 size= 0;
 1094                 o= 0;
 1095                 for (i= 0; i<count; i += IOVEC_NR,
 1096                         iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
 1097                 {
 1098                         n= IOVEC_NR;
 1099                         if (i+n > count)
 1100                                 n= count-i;
 1101                         r= sys_vircopy(fxp_client, D, iov_src, 
 1102                                 SELF, D, (vir_bytes)fp->fxp_iovec,
 1103                                 n * sizeof(fp->fxp_iovec[0]));
 1104                         if (r != OK)
 1105                                 panic("FXP","fxp_writev: sys_vircopy failed", r);
 1106 
 1107                         for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
 1108                         {
 1109                                 s= iovp->iov_size;
 1110                                 if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
 1111                                 {
 1112                                         panic("FXP","fxp_writev: invalid packet size",
 1113                                                 NO_NUM);
 1114                                 }
 1115 
 1116                                 r= sys_vircopy(fxp_client, D, iovp->iov_addr, 
 1117                                         SELF, D, (vir_bytes)(txp->tx_buf+o),
 1118                                         s);
 1119                                 if (r != OK)
 1120                                 {
 1121                                         panic("FXP","fxp_writev: sys_vircopy failed",
 1122                                                 r);
 1123                                 }
 1124                                 size += s;
 1125                                 o += s;
 1126                         }
 1127                 }
 1128                 if (size < ETH_MIN_PACK_SIZE)
 1129                         panic("FXP","fxp_writev: invalid packet size", size);
 1130         }
 1131         else
 1132         {  
 1133                 size= mp->DL_COUNT;
 1134                 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
 1135                         panic("FXP","fxp_writev: invalid packet size", size);
 1136 
 1137                 r= sys_vircopy(fxp_client, D, (vir_bytes)mp->DL_ADDR, 
 1138                         SELF, D, (vir_bytes)txp->tx_buf, size);
 1139                 if (r != OK)
 1140                         panic("FXP","fxp_writev: sys_vircopy failed", r);
 1141         }
 1142 
 1143         txp->tx_status= 0;
 1144         txp->tx_command= TXC_EL | CBL_XMIT;
 1145         txp->tx_tbda= TX_TBDA_NIL;
 1146         txp->tx_size= TXSZ_EOF | size;
 1147         txp->tx_tthresh= fp->fxp_tx_threshold;
 1148         txp->tx_ntbd= 0;
 1149         if (fp->fxp_tx_idle)
 1150         {
 1151                 fp->fxp_tx_idle= 0;
 1152                 fp->fxp_tx_head= fp->fxp_tx_tail= 0;
 1153 
 1154                 fxp_cu_ptr_cmd(fp, SC_CU_START, fp->fxp_tx_busaddr,
 1155                         TRUE /* check idle */);
 1156         }
 1157         else
 1158         {
 1159                 /* Link new request in transmit list */
 1160                 tx_command= prev_txp->tx_command;
 1161                 assert(tx_command == (TXC_EL | CBL_XMIT));
 1162                 prev_txp->tx_command= CBL_XMIT;
 1163                 fp->fxp_tx_head= fxp_tx_head;
 1164         }
 1165 
 1166         fp->fxp_flags |= FF_PACK_SENT;
 1167 
 1168         /* If the interrupt handler called, don't send a reply. The reply
 1169          * will be sent after all interrupts are handled. 
 1170          */
 1171         if (from_int)
 1172                 return;
 1173         reply(fp, OK, FALSE);
 1174         return;
 1175 
 1176 suspend:
 1177         if (from_int)
 1178                 panic("FXP","fxp: should not be sending\n", NO_NUM);
 1179 
 1180         fp->fxp_tx_mess= *mp;
 1181         reply(fp, OK, FALSE);
 1182 }
 1183 
 1184 /*===========================================================================*
 1185  *                              fxp_readv                                    *
 1186  *===========================================================================*/
 1187 static void fxp_readv(mp, from_int, vectored)
 1188 message *mp;
 1189 int from_int;
 1190 int vectored;
 1191 {
 1192         int i, j, n, o, r, s, dl_port, fxp_client, count, size,
 1193                 fxp_rx_head, fxp_rx_nbuf;
 1194         port_t port;
 1195         unsigned packlen;
 1196         vir_bytes iov_src;
 1197         u16_t rfd_status;
 1198         u16_t rfd_res;
 1199         u8_t scb_status;
 1200         fxp_t *fp;
 1201         iovec_t *iovp;
 1202         struct rfd *rfdp, *prev_rfdp;
 1203 
 1204         dl_port = mp->DL_PORT;
 1205         count = mp->DL_COUNT;
 1206         if (dl_port < 0 || dl_port >= FXP_PORT_NR)
 1207                 panic("FXP","fxp_readv: illegal port", dl_port);
 1208         fp= &fxp_table[dl_port];
 1209         fxp_client= mp->DL_PROC;
 1210         fp->fxp_client= fxp_client;
 1211 
 1212         assert(fp->fxp_mode == FM_ENABLED);
 1213         assert(fp->fxp_flags & FF_ENABLED);
 1214 
 1215         port= fp->fxp_base_port;
 1216 
 1217         fxp_rx_head= fp->fxp_rx_head;
 1218         rfdp= &fp->fxp_rx_buf[fxp_rx_head];
 1219 
 1220         rfd_status= rfdp->rfd_status;
 1221         if (!(rfd_status & RFDS_C))
 1222         {
 1223                 /* Receive buffer is empty, suspend */
 1224                 goto suspend;
 1225         }
 1226 
 1227         if (!rfd_status & RFDS_OK)
 1228         {
 1229                 /* Not OK? What happened? */
 1230                 assert(0);
 1231         }
 1232         else
 1233         {
 1234                 assert(!(rfd_status & (RFDS_CRCERR | RFDS_ALIGNERR |
 1235                         RFDS_OUTOFBUF | RFDS_DMAOVR | RFDS_TOOSHORT | 
 1236                         RFDS_RXERR)));
 1237         }
 1238         rfd_res= rfdp->rfd_res;
 1239         assert(rfd_res & RFDR_EOF);
 1240         assert(rfd_res & RFDR_F);
 1241 
 1242         packlen= rfd_res & RFDSZ_SIZE;
 1243 
 1244         if (vectored)
 1245         {
 1246                 iov_src = (vir_bytes)mp->DL_ADDR;
 1247 
 1248                 size= 0;
 1249                 o= 0;
 1250                 for (i= 0; i<count; i += IOVEC_NR,
 1251                         iov_src += IOVEC_NR * sizeof(fp->fxp_iovec[0]))
 1252                 {
 1253                         n= IOVEC_NR;
 1254                         if (i+n > count)
 1255                                 n= count-i;
 1256                         r= sys_vircopy(fxp_client, D, iov_src, 
 1257                                 SELF, D, (vir_bytes)fp->fxp_iovec,
 1258                                 n * sizeof(fp->fxp_iovec[0]));
 1259                         if (r != OK)
 1260                                 panic("FXP","fxp_readv: sys_vircopy failed", r);
 1261 
 1262                         for (j= 0, iovp= fp->fxp_iovec; j<n; j++, iovp++)
 1263                         {
 1264                                 s= iovp->iov_size;
 1265                                 if (size + s > packlen)
 1266                                 {
 1267                                         assert(packlen > size);
 1268                                         s= packlen-size;
 1269                                 }
 1270 
 1271                                 r= sys_vircopy(SELF, D,
 1272                                         (vir_bytes)(rfdp->rfd_buf+o),
 1273                                         fxp_client, D, iovp->iov_addr, s);
 1274                                 if (r != OK)
 1275                                 {
 1276                                         panic("FXP","fxp_readv: sys_vircopy failed",
 1277                                                 r);
 1278                                 }
 1279 
 1280                                 size += s;
 1281                                 if (size == packlen)
 1282                                         break;
 1283                                 o += s;
 1284                         }
 1285                         if (size == packlen)
 1286                                 break;
 1287                 }
 1288                 if (size < packlen)
 1289                 {
 1290                         assert(0);
 1291                 }
 1292         }
 1293         else
 1294         {  
 1295                 assert(0);
 1296         }
 1297 
 1298         fp->fxp_read_s= packlen;
 1299         fp->fxp_flags= (fp->fxp_flags & ~FF_READING) | FF_PACK_RECV;
 1300 
 1301         /* Re-init the current buffer */
 1302         rfdp->rfd_status= 0;
 1303         rfdp->rfd_command= RFDC_EL;
 1304         rfdp->rfd_reserved= 0;
 1305         rfdp->rfd_res= 0;
 1306         rfdp->rfd_size= sizeof(rfdp->rfd_buf);
 1307 
 1308         fxp_rx_nbuf= fp->fxp_rx_nbuf;
 1309         if (fxp_rx_head == 0)
 1310         {
 1311                 prev_rfdp= &fp->fxp_rx_buf[fxp_rx_nbuf-1];
 1312         }
 1313         else
 1314                 prev_rfdp= &rfdp[-1];
 1315 
 1316         assert(prev_rfdp->rfd_command & RFDC_EL);
 1317         prev_rfdp->rfd_command &= ~RFDC_EL;
 1318 
 1319         fxp_rx_head++;
 1320         if (fxp_rx_head == fxp_rx_nbuf)
 1321                 fxp_rx_head= 0;
 1322         assert(fxp_rx_head < fxp_rx_nbuf);
 1323         fp->fxp_rx_head= fxp_rx_head;
 1324 
 1325         if (!from_int)
 1326                 reply(fp, OK, FALSE);
 1327 
 1328         return;
 1329 
 1330 suspend:
 1331         if (fp->fxp_rx_need_restart)
 1332         {
 1333                 fp->fxp_rx_need_restart= 0;
 1334 
 1335                 /* Check the status of the RU */
 1336                 scb_status= fxp_inb(port, SCB_STATUS);
 1337                 if ((scb_status & SS_RUS_MASK) != SS_RU_NORES)
 1338                 {
 1339                         /* Race condition? */
 1340                         printf("fxp_readv: restart race: 0x%x\n",
 1341                                 scb_status);
 1342                         assert((scb_status & SS_RUS_MASK) == SS_RU_READY);
 1343                 }
 1344                 else
 1345                 {
 1346                         fxp_restart_ru(fp);
 1347                 }
 1348         }
 1349         if (from_int)
 1350         {
 1351                 assert(fp->fxp_flags & FF_READING);
 1352 
 1353                 /* No need to store any state */
 1354                 return;
 1355         }
 1356 
 1357         fp->fxp_rx_mess= *mp;
 1358         assert(!(fp->fxp_flags & FF_READING));
 1359         fp->fxp_flags |= FF_READING;
 1360 
 1361         reply(fp, OK, FALSE);
 1362 }
 1363 
 1364 /*===========================================================================*
 1365  *                              fxp_do_conf                                  *
 1366  *===========================================================================*/
 1367 static void fxp_do_conf(fp)
 1368 fxp_t *fp;
 1369 {
 1370         int r;
 1371         u32_t bus_addr;
 1372         struct cbl_conf cc;
 1373         clock_t t0,t1;
 1374 
 1375         /* Configure device */
 1376         cc.cc_status= 0;
 1377         cc.cc_command= CBL_C_EL | CBL_CONF;
 1378         cc.cc_linkaddr= 0;
 1379         memcpy(cc.cc_bytes, fp->fxp_conf_bytes, sizeof(cc.cc_bytes));
 1380 
 1381         r= sys_umap(SELF, D, (vir_bytes)&cc, (phys_bytes)sizeof(cc),
 1382                 &bus_addr);
 1383         if (r != OK)
 1384                 panic("FXP","sys_umap failed", r);
 1385 
 1386         fxp_cu_ptr_cmd(fp, SC_CU_START, bus_addr, TRUE /* check idle */);
 1387 
 1388         getuptime(&t0);
 1389         do {
 1390                 /* Wait for CU command to complete */
 1391                 if (cc.cc_status & CBL_F_C)
 1392                         break;
 1393         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
 1394 
 1395         if (!(cc.cc_status & CBL_F_C))
 1396                 panic("FXP","fxp_do_conf: CU command failed to complete", NO_NUM);
 1397         if (!(cc.cc_status & CBL_F_OK))
 1398                 panic("FXP","fxp_do_conf: CU command failed", NO_NUM);
 1399 
 1400 }
 1401 
 1402 /*===========================================================================*
 1403  *                              fxp_cu_ptr_cmd                               *
 1404  *===========================================================================*/
 1405 static void fxp_cu_ptr_cmd(fp, cmd, bus_addr, check_idle)
 1406 fxp_t *fp;
 1407 int cmd;
 1408 phys_bytes bus_addr;
 1409 int check_idle;
 1410 {
 1411         clock_t t0,t1;
 1412         port_t port;
 1413         u8_t scb_cmd;
 1414 
 1415         port= fp->fxp_base_port;
 1416 
 1417         if (check_idle)
 1418         {
 1419                 /* Consistency check. Make sure that CU is idle */
 1420                 if ((fxp_inb(port, SCB_STATUS) & SS_CUS_MASK) != SS_CU_IDLE)
 1421                         panic("FXP","fxp_cu_ptr_cmd: CU is not idle", NO_NUM);
 1422         }
 1423 
 1424         fxp_outl(port, SCB_POINTER, bus_addr);
 1425         fxp_outb(port, SCB_CMD, cmd);
 1426 
 1427         /* What is a reasonable time-out? There is nothing in the
 1428          * documentation. 1 ms should be enough.
 1429          */
 1430         getuptime(&t0);
 1431         do {
 1432                 /* Wait for CU command to be accepted */
 1433                 scb_cmd= fxp_inb(port, SCB_CMD);
 1434                 if ((scb_cmd & SC_CUC_MASK) == SC_CU_NOP)
 1435                         break;
 1436         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
 1437 
 1438         if ((scb_cmd & SC_CUC_MASK) != SC_CU_NOP)
 1439                 panic("FXP","fxp_cu_ptr_cmd: CU does not accept command", NO_NUM);
 1440 }
 1441 
 1442 /*===========================================================================*
 1443  *                              fxp_ru_ptr_cmd                               *
 1444  *===========================================================================*/
 1445 static void fxp_ru_ptr_cmd(fp, cmd, bus_addr, check_idle)
 1446 fxp_t *fp;
 1447 int cmd;
 1448 phys_bytes bus_addr;
 1449 int check_idle;
 1450 {
 1451         clock_t t0,t1;
 1452         port_t port;
 1453         u8_t scb_cmd;
 1454 
 1455         port= fp->fxp_base_port;
 1456 
 1457         if (check_idle)
 1458         {
 1459                 /* Consistency check, make sure that RU is idle */
 1460                 if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_IDLE)
 1461                         panic("FXP","fxp_ru_ptr_cmd: RU is not idle", NO_NUM);
 1462         }
 1463 
 1464         fxp_outl(port, SCB_POINTER, bus_addr);
 1465         fxp_outb(port, SCB_CMD, cmd);
 1466 
 1467         getuptime(&t0);
 1468         do {
 1469                 /* Wait for RU command to be accepted */
 1470                 scb_cmd= fxp_inb(port, SCB_CMD);
 1471                 if ((scb_cmd & SC_RUC_MASK) == SC_RU_NOP)
 1472                         break;
 1473         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
 1474 
 1475         if ((scb_cmd & SC_RUC_MASK) != SC_RU_NOP)
 1476                 panic("FXP","fxp_ru_ptr_cmd: RU does not accept command", NO_NUM);
 1477 }
 1478 
 1479 /*===========================================================================*
 1480  *                              fxp_restart_ru                               *
 1481  *===========================================================================*/
 1482 static void fxp_restart_ru(fp)
 1483 fxp_t *fp;
 1484 {
 1485         int i, fxp_rx_nbuf;
 1486         port_t port;
 1487         struct rfd *rfdp;
 1488 
 1489         port= fp->fxp_base_port;
 1490 
 1491         fxp_rx_nbuf= fp->fxp_rx_nbuf;
 1492         for (i= 0, rfdp= fp->fxp_rx_buf; i<fxp_rx_nbuf; i++, rfdp++)
 1493         {
 1494                 rfdp->rfd_status= 0;
 1495                 rfdp->rfd_command= 0;
 1496                 if (i == fp->fxp_rx_nbuf-1)
 1497                         rfdp->rfd_command= RFDC_EL;
 1498                 rfdp->rfd_reserved= 0;
 1499                 rfdp->rfd_res= 0;
 1500                 rfdp->rfd_size= sizeof(rfdp->rfd_buf);
 1501         }
 1502         fp->fxp_rx_head= 0;
 1503 
 1504         /* Make sure that RU is in the 'No resources' state */
 1505         if ((fxp_inb(port, SCB_STATUS) & SS_RUS_MASK) != SS_RU_NORES)
 1506                 panic("FXP","fxp_restart_ru: RU is in an unexpected state", NO_NUM);
 1507 
 1508         fxp_ru_ptr_cmd(fp, SC_RU_START, fp->fxp_rx_busaddr,
 1509                 FALSE /* do not check idle */);
 1510 }
 1511 
 1512 /*===========================================================================*
 1513  *                              fxp_getstat                                  *
 1514  *===========================================================================*/
 1515 static void fxp_getstat(mp)
 1516 message *mp;
 1517 {
 1518         clock_t t0,t1;
 1519         int dl_port;
 1520         port_t port;
 1521         fxp_t *fp;
 1522         u32_t *p;
 1523         eth_stat_t stats;
 1524 
 1525         dl_port = mp->DL_PORT;
 1526         if (dl_port < 0 || dl_port >= FXP_PORT_NR)
 1527                 panic("FXP","fxp_getstat: illegal port", dl_port);
 1528         fp= &fxp_table[dl_port];
 1529         fp->fxp_client= mp->DL_PROC;
 1530 
 1531         assert(fp->fxp_mode == FM_ENABLED);
 1532         assert(fp->fxp_flags & FF_ENABLED);
 1533 
 1534         port= fp->fxp_base_port;
 1535 
 1536         p= &fp->fxp_stat.sc_tx_fcp;
 1537         *p= 0;
 1538 
 1539         /* The dump commmand doesn't take a pointer. Setting a pointer
 1540          * doesn't hard though.
 1541          */
 1542         fxp_cu_ptr_cmd(fp, SC_CU_DUMP_SC, 0, FALSE /* do not check idle */);
 1543 
 1544         getuptime(&t0);
 1545         do {
 1546                 /* Wait for CU command to complete */
 1547                 if (*p != 0)
 1548                         break;
 1549         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(1000));
 1550 
 1551         if (*p == 0)
 1552                 panic("FXP","fxp_getstat: CU command failed to complete", NO_NUM);
 1553         if (*p != SCM_DSC)
 1554                 panic("FXP","fxp_getstat: bad magic", NO_NUM);
 1555 
 1556         stats.ets_recvErr=
 1557                 fp->fxp_stat.sc_rx_crc +
 1558                 fp->fxp_stat.sc_rx_align +
 1559                 fp->fxp_stat.sc_rx_resource +
 1560                 fp->fxp_stat.sc_rx_overrun +
 1561                 fp->fxp_stat.sc_rx_cd +
 1562                 fp->fxp_stat.sc_rx_short;
 1563         stats.ets_sendErr=
 1564                 fp->fxp_stat.sc_tx_maxcol +
 1565                 fp->fxp_stat.sc_tx_latecol +
 1566                 fp->fxp_stat.sc_tx_crs;
 1567         stats.ets_OVW= fp->fxp_stat.sc_rx_overrun;
 1568         stats.ets_CRCerr= fp->fxp_stat.sc_rx_crc;
 1569         stats.ets_frameAll= fp->fxp_stat.sc_rx_align;
 1570         stats.ets_missedP= fp->fxp_stat.sc_rx_resource;
 1571         stats.ets_packetR= fp->fxp_stat.sc_rx_good;
 1572         stats.ets_packetT= fp->fxp_stat.sc_tx_good;
 1573         stats.ets_transDef= fp->fxp_stat.sc_tx_defered;
 1574         stats.ets_collision= fp->fxp_stat.sc_tx_totcol;
 1575         stats.ets_transAb= fp->fxp_stat.sc_tx_maxcol;
 1576         stats.ets_carrSense= fp->fxp_stat.sc_tx_crs;
 1577         stats.ets_fifoUnder= fp->fxp_stat.sc_tx_underrun;
 1578         stats.ets_fifoOver= fp->fxp_stat.sc_rx_overrun;
 1579         stats.ets_CDheartbeat= 0;
 1580         stats.ets_OWC= fp->fxp_stat.sc_tx_latecol;
 1581 
 1582         put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
 1583                 (vir_bytes) sizeof(stats), &stats);
 1584         reply(fp, OK, FALSE);
 1585 }
 1586 
 1587 
 1588 /*===========================================================================*
 1589  *                              fxp_getname                                  *
 1590  *===========================================================================*/
 1591 static void fxp_getname(mp)
 1592 message *mp;
 1593 {
 1594         int r;
 1595 
 1596         strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
 1597         mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
 1598         mp->m_type= DL_NAME_REPLY;
 1599         r= send(mp->m_source, mp);
 1600         if (r != OK)
 1601                 panic("FXP", "fxp_getname: send failed", r);
 1602 }
 1603 
 1604 /*===========================================================================*
 1605  *                              fxp_handler                                  *
 1606  *===========================================================================*/
 1607 static int fxp_handler(fp)
 1608 fxp_t *fp;
 1609 {
 1610         int port;
 1611         u16_t isr;
 1612 
 1613         RAND_UPDATE
 1614 
 1615         port= fp->fxp_base_port;
 1616 
 1617         /* Ack interrupt */
 1618         isr= fxp_inb(port, SCB_INT_STAT);
 1619         fxp_outb(port, SCB_INT_STAT, isr);
 1620 
 1621         if (isr & SIS_FR)
 1622         {
 1623                 isr &= ~SIS_FR;
 1624 
 1625                 if (!fp->fxp_got_int && (fp->fxp_flags & FF_READING))
 1626                 {
 1627                         fp->fxp_got_int= TRUE;
 1628                         interrupt(fxp_tasknr);
 1629                 }
 1630         }
 1631         if (isr & SIS_CNA)
 1632         {
 1633                 isr &= ~SIS_CNA;
 1634                 if (!fp->fxp_tx_idle)
 1635                 {
 1636                         fp->fxp_send_int= TRUE;
 1637                         if (!fp->fxp_got_int)
 1638                         {
 1639                                 fp->fxp_got_int= TRUE;
 1640                                 interrupt(fxp_tasknr);
 1641                         }
 1642                 }
 1643         }
 1644         if (isr & SIS_RNR)
 1645         {
 1646                 isr &= ~SIS_RNR;
 1647 
 1648                 /* Assume that receive buffer is full of packets. fxp_readv
 1649                  * will restart the RU.
 1650                  */
 1651                 fp->fxp_rx_need_restart= 1;
 1652         }
 1653         if (isr)
 1654         {
 1655                 printf("fxp_handler: unhandled interrupt: isr = 0x%02x\n",
 1656                         isr);
 1657         }
 1658 
 1659         return 1;
 1660 }
 1661 
 1662 /*===========================================================================*
 1663  *                              fxp_check_ints                               *
 1664  *===========================================================================*/
 1665 static void fxp_check_ints(fp)
 1666 fxp_t *fp;
 1667 {
 1668         int n, fxp_flags, prev_tail;
 1669         int fxp_tx_tail, fxp_tx_nbuf, fxp_tx_threshold;
 1670         port_t port;
 1671         u32_t busaddr;
 1672         u16_t tx_status;
 1673         u8_t scb_status;
 1674         struct tx *txp;
 1675 
 1676         fxp_flags= fp->fxp_flags;
 1677 
 1678         if (fxp_flags & FF_READING)
 1679         {
 1680                 if (!(fp->fxp_rx_buf[fp->fxp_rx_head].rfd_status & RFDS_C))
 1681                         ; /* Nothing */
 1682                 else if (fp->fxp_rx_mess.m_type == DL_READV)
 1683                 {
 1684                         fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
 1685                                 TRUE /* vectored */);
 1686                 }
 1687                 else
 1688                 {
 1689                         assert(fp->fxp_rx_mess.m_type == DL_READ);
 1690                         fxp_readv(&fp->fxp_rx_mess, TRUE /* from int */,
 1691                                 FALSE /* !vectored */);
 1692                 }
 1693         }
 1694         if (fp->fxp_tx_idle)
 1695                 ;       /* Nothing to do */
 1696         else if (fp->fxp_send_int)
 1697         {
 1698                 fp->fxp_send_int= FALSE;
 1699                 fxp_tx_tail= fp->fxp_tx_tail;
 1700                 fxp_tx_nbuf= fp->fxp_tx_nbuf;
 1701                 n= 0;
 1702                 for (;;)
 1703                 {
 1704                         txp= &fp->fxp_tx_buf[fxp_tx_tail];
 1705                         tx_status= txp->tx_status;
 1706                         if (!(tx_status & TXS_C))
 1707                                 break;
 1708 
 1709                         n++;
 1710 
 1711                         assert(tx_status & TXS_OK);
 1712                         if (tx_status & TXS_U)
 1713                         {
 1714                                 fxp_tx_threshold= fp->fxp_tx_threshold;
 1715                                 if (fxp_tx_threshold < TXTT_MAX)
 1716                                 {
 1717                                         fxp_tx_threshold++;
 1718                                         fp->fxp_tx_threshold= fxp_tx_threshold;
 1719                                 }
 1720                                 printf(
 1721                         "fxp_check_ints: fxp_tx_threshold = 0x%x\n",
 1722                                         fxp_tx_threshold);
 1723                         }
 1724 
 1725                         if (txp->tx_command & TXC_EL)
 1726                         {
 1727                                 fp->fxp_tx_idle= 1;
 1728                                 break;
 1729                         }
 1730 
 1731                         fxp_tx_tail++;
 1732                         if (fxp_tx_tail == fxp_tx_nbuf)
 1733                                 fxp_tx_tail= 0;
 1734                         assert(fxp_tx_tail < fxp_tx_nbuf);
 1735                 }
 1736 
 1737                 if (fp->fxp_need_conf)
 1738                 {
 1739                         /* Check the status of the CU */
 1740                         port= fp->fxp_base_port;
 1741                         scb_status= fxp_inb(port, SCB_STATUS);
 1742                         if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
 1743                         {
 1744                                 /* Nothing to do */
 1745                                 printf("scb_status = 0x%x\n", scb_status);
 1746                         }
 1747                         else
 1748                         {
 1749                                 printf("fxp_check_ints: fxp_need_conf\n");
 1750                                 fp->fxp_need_conf= FALSE;
 1751                                 fxp_do_conf(fp);
 1752                         }
 1753                 }
 1754 
 1755                 if (n)
 1756                 {
 1757                         if (!fp->fxp_tx_idle)
 1758                         {
 1759                                 fp->fxp_tx_tail= fxp_tx_tail;
 1760                                 
 1761                                 /* Check the status of the CU */
 1762                                 port= fp->fxp_base_port;
 1763                                 scb_status= fxp_inb(port, SCB_STATUS);
 1764                                 if ((scb_status & SS_CUS_MASK) != SS_CU_IDLE)
 1765                                 {
 1766                                         /* Nothing to do */
 1767                                         printf("scb_status = 0x%x\n",
 1768                                                 scb_status);
 1769 
 1770                                 }
 1771                                 else
 1772                                 {
 1773                                         if (fxp_tx_tail == 0)
 1774                                                 prev_tail= fxp_tx_nbuf-1;
 1775                                         else
 1776                                                 prev_tail= fxp_tx_tail-1;
 1777                                         busaddr= fp->fxp_tx_buf[prev_tail].
 1778                                                 tx_linkaddr;
 1779 
 1780                                         fxp_cu_ptr_cmd(fp, SC_CU_START,
 1781                                                 busaddr, 1 /* check idle */);
 1782                                 }
 1783                         }
 1784 
 1785                         if (fp->fxp_flags & FF_SEND_AVAIL)
 1786                         {
 1787                                 if (fp->fxp_tx_mess.m_type == DL_WRITEV)
 1788                                 {
 1789                                         fxp_writev(&fp->fxp_tx_mess,
 1790                                                 TRUE /* from int */,
 1791                                                 TRUE /* vectored */);
 1792                                 }
 1793                                 else
 1794                                 {
 1795                                         assert(fp->fxp_tx_mess.m_type ==
 1796                                                 DL_WRITE);
 1797                                         fxp_writev(&fp->fxp_tx_mess,
 1798                                                 TRUE /* from int */,
 1799                                                 FALSE /* !vectored */);
 1800                                 }
 1801                         }
 1802                 }
 1803                 
 1804         }
 1805         if (fp->fxp_report_link)
 1806                 fxp_report_link(fp);
 1807 
 1808         if (fp->fxp_flags & (FF_PACK_SENT | FF_PACK_RECV))
 1809                 reply(fp, OK, TRUE);
 1810 }
 1811 
 1812 /*===========================================================================*
 1813  *                              fxp_watchdog_f                               *
 1814  *===========================================================================*/
 1815 static void fxp_watchdog_f(tp)
 1816 timer_t *tp;
 1817 {
 1818         int i;
 1819         fxp_t *fp;
 1820 
 1821         tmr_arg(&fxp_watchdog)->ta_int= 0;
 1822         fxp_set_timer(&fxp_watchdog, HZ, fxp_watchdog_f);
 1823 
 1824         for (i= 0, fp = &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
 1825         {
 1826                 if (fp->fxp_mode != FM_ENABLED)
 1827                         continue;
 1828 
 1829                 /* Handle race condition, MII interface mgith be busy */
 1830                 if(!fp->fxp_mii_busy)
 1831                 {
 1832                         /* Check the link status. */
 1833                         if (fxp_link_changed(fp))
 1834                         {
 1835 #if VERBOSE
 1836                                 printf("fxp_watchdog_f: link changed\n");
 1837 #endif
 1838                                 fp->fxp_report_link= TRUE;
 1839                                 fp->fxp_got_int= TRUE;
 1840                                 interrupt(fxp_tasknr);
 1841                         }
 1842                 }
 1843                 
 1844                 if (!(fp->fxp_flags & FF_SEND_AVAIL))
 1845                 {
 1846                         /* Assume that an idle system is alive */
 1847                         fp->fxp_tx_alive= TRUE;
 1848                         continue;
 1849                 }
 1850                 if (fp->fxp_tx_alive)
 1851                 {
 1852                         fp->fxp_tx_alive= FALSE;
 1853                         continue;
 1854                 }
 1855 
 1856                 fp->fxp_need_reset= TRUE;
 1857                 fp->fxp_got_int= TRUE;
 1858                 interrupt(fxp_tasknr);
 1859         }
 1860 }
 1861 
 1862 /*===========================================================================*
 1863  *                              fxp_link_changed                             *
 1864  *===========================================================================*/
 1865 static int fxp_link_changed(fp)
 1866 fxp_t *fp;
 1867 {
 1868         u16_t scr;
 1869 
 1870         scr= mii_read(fp, MII_SCR);
 1871         scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
 1872 
 1873         return (fp->fxp_mii_scr != scr);
 1874 }
 1875 
 1876 /*===========================================================================*
 1877  *                              fxp_report_link                              *
 1878  *===========================================================================*/
 1879 static void fxp_report_link(fp)
 1880 fxp_t *fp;
 1881 {
 1882         port_t port;
 1883         u16_t mii_ctrl, mii_status, mii_id1, mii_id2, 
 1884                 mii_ana, mii_anlpa, mii_ane, mii_extstat,
 1885                 mii_ms_ctrl, mii_ms_status, scr;
 1886         u32_t oui;
 1887         int model, rev;
 1888         int f, link_up, ms_regs;
 1889 
 1890         /* Assume an 82555 (compatible) PHY. The should be changed for
 1891          * 82557 NICs with different PHYs
 1892          */
 1893         ms_regs= 0;     /* No master/slave registers. */
 1894 
 1895         fp->fxp_report_link= FALSE;
 1896         port= fp->fxp_base_port;
 1897 
 1898         scr= mii_read(fp, MII_SCR);
 1899         scr &= ~(MII_SCR_RES|MII_SCR_RES_1);
 1900         fp->fxp_mii_scr= scr;
 1901 
 1902         mii_ctrl= mii_read(fp, MII_CTRL);
 1903         mii_read(fp, MII_STATUS); /* Read the status register twice, why? */
 1904         mii_status= mii_read(fp, MII_STATUS);
 1905         mii_id1= mii_read(fp, MII_PHYID_H);
 1906         mii_id2= mii_read(fp, MII_PHYID_L);
 1907         mii_ana= mii_read(fp, MII_ANA);
 1908         mii_anlpa= mii_read(fp, MII_ANLPA);
 1909         mii_ane= mii_read(fp, MII_ANE);
 1910         if (mii_status & MII_STATUS_EXT_STAT)
 1911                 mii_extstat= mii_read(fp, MII_EXT_STATUS);
 1912         else
 1913                 mii_extstat= 0;
 1914         if (ms_regs)
 1915         {
 1916                 mii_ms_ctrl= mii_read(fp, MII_MS_CTRL);
 1917                 mii_ms_status= mii_read(fp, MII_MS_STATUS);
 1918         }
 1919         else
 1920         {
 1921                 mii_ms_ctrl= 0;
 1922                 mii_ms_status= 0;
 1923         }
 1924 
 1925         /* How do we know about the link status? */
 1926         link_up= !!(mii_status & MII_STATUS_LS);
 1927 
 1928         fp->fxp_link_up= link_up;
 1929         if (!link_up)
 1930         {
 1931 #if VERBOSE
 1932                 printf("%s: link down\n", fp->fxp_name);
 1933 #endif
 1934                 return;
 1935         }
 1936 
 1937         oui= (mii_id1 << MII_PH_OUI_H_C_SHIFT) | 
 1938                 ((mii_id2 & MII_PL_OUI_L_MASK) >> MII_PL_OUI_L_SHIFT);
 1939         model= ((mii_id2 & MII_PL_MODEL_MASK) >> MII_PL_MODEL_SHIFT);
 1940         rev= (mii_id2 & MII_PL_REV_MASK);
 1941 
 1942 #if VERBOSE
 1943         printf("OUI 0x%06lx, Model 0x%02x, Revision 0x%x\n", oui, model, rev);
 1944 #endif
 1945 
 1946         if (mii_ctrl & (MII_CTRL_LB|MII_CTRL_PD|MII_CTRL_ISO))
 1947         {
 1948                 printf("%s: PHY: ", fp->fxp_name);
 1949                 f= 1;
 1950                 if (mii_ctrl & MII_CTRL_LB)
 1951                 {
 1952                         printf("loopback mode");
 1953                         f= 0;
 1954                 }
 1955                 if (mii_ctrl & MII_CTRL_PD)
 1956                 {
 1957                         if (!f) printf(", ");
 1958                         f= 0;
 1959                         printf("powered down");
 1960                 }
 1961                 if (mii_ctrl & MII_CTRL_ISO)
 1962                 {
 1963                         if (!f) printf(", ");
 1964                         f= 0;
 1965                         printf("isolated");
 1966                 }
 1967                 printf("\n");
 1968                 return;
 1969         }
 1970         if (!(mii_ctrl & MII_CTRL_ANE))
 1971         {
 1972                 printf("%s: manual config: ", fp->fxp_name);
 1973                 switch(mii_ctrl & (MII_CTRL_SP_LSB|MII_CTRL_SP_MSB))
 1974                 {
 1975                 case MII_CTRL_SP_10:    printf("10 Mbps"); break;
 1976                 case MII_CTRL_SP_100:   printf("100 Mbps"); break;
 1977                 case MII_CTRL_SP_1000:  printf("1000 Mbps"); break;
 1978                 case MII_CTRL_SP_RES:   printf("reserved speed"); break;
 1979                 }
 1980                 if (mii_ctrl & MII_CTRL_DM)
 1981                         printf(", full duplex");
 1982                 else
 1983                         printf(", half duplex");
 1984                 printf("\n");
 1985                 return;
 1986         }
 1987 
 1988         if (!debug) goto resspeed;
 1989 
 1990         printf("%s: ", fp->fxp_name);
 1991         mii_print_stat_speed(mii_status, mii_extstat);
 1992         printf("\n");
 1993 
 1994         if (!(mii_status & MII_STATUS_ANC))
 1995                 printf("%s: auto-negotiation not complete\n", fp->fxp_name);
 1996         if (mii_status & MII_STATUS_RF)
 1997                 printf("%s: remote fault detected\n", fp->fxp_name);
 1998         if (!(mii_status & MII_STATUS_ANA))
 1999         {
 2000                 printf("%s: local PHY has no auto-negotiation ability\n",
 2001                         fp->fxp_name);
 2002         }
 2003         if (!(mii_status & MII_STATUS_LS))
 2004                 printf("%s: link down\n", fp->fxp_name);
 2005         if (mii_status & MII_STATUS_JD)
 2006                 printf("%s: jabber condition detected\n", fp->fxp_name);
 2007         if (!(mii_status & MII_STATUS_EC))
 2008         {
 2009                 printf("%s: no extended register set\n", fp->fxp_name);
 2010                 goto resspeed;
 2011         }
 2012         if (!(mii_status & MII_STATUS_ANC))
 2013                 goto resspeed;
 2014 
 2015         printf("%s: local cap.: ", fp->fxp_name);
 2016         if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
 2017         {
 2018                 printf("1000 Mbps: T-");
 2019                 switch(mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
 2020                 {
 2021                 case MII_MSC_1000T_FD:  printf("FD"); break;
 2022                 case MII_MSC_1000T_HD:  printf("HD"); break;
 2023                 default:                printf("FD/HD"); break;
 2024                 }
 2025                 if (mii_ana)
 2026                         printf(", ");
 2027         }
 2028         mii_print_techab(mii_ana);
 2029         printf("\n");
 2030 
 2031         if (mii_ane & MII_ANE_PDF)
 2032                 printf("%s: parallel detection fault\n", fp->fxp_name);
 2033         if (!(mii_ane & MII_ANE_LPANA))
 2034         {
 2035                 printf("%s: link-partner does not support auto-negotiation\n",
 2036                         fp->fxp_name);
 2037                 goto resspeed;
 2038         }
 2039 
 2040         printf("%s: remote cap.: ", fp->fxp_name);
 2041         if (mii_ms_ctrl & (MII_MSC_1000T_FD | MII_MSC_1000T_HD))
 2042         if (mii_ms_status & (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
 2043         {
 2044                 printf("1000 Mbps: T-");
 2045                 switch(mii_ms_status &
 2046                         (MII_MSS_LP1000T_FD | MII_MSS_LP1000T_HD))
 2047                 {
 2048                 case MII_MSS_LP1000T_FD:        printf("FD"); break;
 2049                 case MII_MSS_LP1000T_HD:        printf("HD"); break;
 2050                 default:                        printf("FD/HD"); break;
 2051                 }
 2052                 if (mii_anlpa)
 2053                         printf(", ");
 2054         }
 2055         mii_print_techab(mii_anlpa);
 2056         printf("\n");
 2057 
 2058         if (ms_regs)
 2059         {
 2060                 printf("%s: ", fp->fxp_name);
 2061                 if (mii_ms_ctrl & MII_MSC_MS_MANUAL)
 2062                 {
 2063                         printf("manual %s",
 2064                                 (mii_ms_ctrl & MII_MSC_MS_VAL) ?
 2065                                 "MASTER" : "SLAVE");
 2066                 }
 2067                 else
 2068                 {
 2069                         printf("%s device",
 2070                                 (mii_ms_ctrl & MII_MSC_MULTIPORT) ?
 2071                                 "multiport" : "single-port");
 2072                 }
 2073                 if (mii_ms_ctrl & MII_MSC_RES)
 2074                         printf(" reserved<0x%x>", mii_ms_ctrl & MII_MSC_RES);
 2075                 printf(": ");
 2076                 if (mii_ms_status & MII_MSS_FAULT)
 2077                         printf("M/S config fault");
 2078                 else if (mii_ms_status & MII_MSS_MASTER)
 2079                         printf("MASTER");
 2080                 else
 2081                         printf("SLAVE");
 2082                 printf("\n");
 2083         }
 2084 
 2085         if (mii_ms_status & (MII_MSS_LP1000T_FD|MII_MSS_LP1000T_HD))
 2086         {
 2087                 if (!(mii_ms_status & MII_MSS_LOCREC))
 2088                 {
 2089                         printf("%s: local receiver not OK\n",
 2090                                 fp->fxp_name);
 2091                 }
 2092                 if (!(mii_ms_status & MII_MSS_REMREC))
 2093                 {
 2094                         printf("%s: remote receiver not OK\n",
 2095                                 fp->fxp_name);
 2096                 }
 2097         }
 2098         if (mii_ms_status & (MII_MSS_RES|MII_MSS_IDLE_ERR))
 2099         {
 2100                 printf("%s", fp->fxp_name);
 2101                 if (mii_ms_status & MII_MSS_RES)
 2102                         printf(" reserved<0x%x>", mii_ms_status & MII_MSS_RES);
 2103                 if (mii_ms_status & MII_MSS_IDLE_ERR)
 2104                 {
 2105                         printf(" idle error %d",
 2106                                 mii_ms_status & MII_MSS_IDLE_ERR);
 2107                 }
 2108                 printf("\n");
 2109         }
 2110 
 2111 resspeed:
 2112 #if VERBOSE
 2113         printf("%s: link up, %d Mbps, %s duplex\n",
 2114                 fp->fxp_name, (scr & MII_SCR_100) ? 100 : 10,
 2115                 (scr & MII_SCR_FD) ? "full" : "half");
 2116 #endif
 2117         ;
 2118 }
 2119 
 2120 /*===========================================================================*
 2121  *                              fxp_stop                                     *
 2122  *===========================================================================*/
 2123 static void fxp_stop()
 2124 {
 2125         int i;
 2126         port_t port;
 2127         fxp_t *fp;
 2128 
 2129         for (i= 0, fp= &fxp_table[0]; i<FXP_PORT_NR; i++, fp++)
 2130         {
 2131                 if (fp->fxp_mode != FM_ENABLED)
 2132                         continue;
 2133                 if (!(fp->fxp_flags & FF_ENABLED))
 2134                         continue;
 2135                 port= fp->fxp_base_port;
 2136 
 2137                 /* Reset device */
 2138                 if (debug)
 2139                         printf("%s: resetting device\n", fp->fxp_name);
 2140                 fxp_outl(port, CSR_PORT, CP_CMD_SOFT_RESET);
 2141         }
 2142         sys_exit(0);
 2143 }
 2144 
 2145 /*===========================================================================*
 2146  *                              reply                                        *
 2147  *===========================================================================*/
 2148 static void reply(fp, err, may_block)
 2149 fxp_t *fp;
 2150 int err;
 2151 int may_block;
 2152 {
 2153         message reply;
 2154         int status;
 2155         int r;
 2156 
 2157         status = 0;
 2158         if (fp->fxp_flags & FF_PACK_SENT)
 2159                 status |= DL_PACK_SEND;
 2160         if (fp->fxp_flags & FF_PACK_RECV)
 2161                 status |= DL_PACK_RECV;
 2162 
 2163         reply.m_type = DL_TASK_REPLY;
 2164         reply.DL_PORT = fp - fxp_table;
 2165         reply.DL_PROC = fp->fxp_client;
 2166         reply.DL_STAT = status | ((u32_t) err << 16);
 2167         reply.DL_COUNT = fp->fxp_read_s;
 2168 #if 0
 2169         reply.DL_CLCK = get_uptime();
 2170 #else
 2171         reply.DL_CLCK = 0;
 2172 #endif
 2173 
 2174         r= send(fp->fxp_client, &reply);
 2175 
 2176         if (r == ELOCKED && may_block)
 2177         {
 2178 #if 0
 2179                 printW(); printf("send locked\n");
 2180 #endif
 2181                 return;
 2182         }
 2183 
 2184         if (r < 0)
 2185                 panic("FXP","fxp: send failed:", r);
 2186         
 2187         fp->fxp_read_s = 0;
 2188         fp->fxp_flags &= ~(FF_PACK_SENT | FF_PACK_RECV);
 2189 }
 2190 
 2191 /*===========================================================================*
 2192  *                              mess_reply                                   *
 2193  *===========================================================================*/
 2194 static void mess_reply(req, reply_mess)
 2195 message *req;
 2196 message *reply_mess;
 2197 {
 2198         if (send(req->m_source, reply_mess) != OK)
 2199                 panic("FXP","fxp: unable to mess_reply", NO_NUM);
 2200 }
 2201 
 2202 /*===========================================================================*
 2203  *                              put_userdata                                 *
 2204  *===========================================================================*/
 2205 static void put_userdata(user_proc, user_addr, count, loc_addr)
 2206 int user_proc;
 2207 vir_bytes user_addr;
 2208 vir_bytes count;
 2209 void *loc_addr;
 2210 {
 2211         int r;
 2212 
 2213         r= sys_vircopy(SELF, D, (vir_bytes)loc_addr,
 2214                 user_proc, D, user_addr, count);
 2215         if (r != OK)
 2216                 panic("FXP","put_userdata: sys_vircopy failed", r);
 2217 }
 2218 
 2219 /*===========================================================================*
 2220  *                              eeprom_read                                  *
 2221  *===========================================================================*/
 2222 PRIVATE u16_t eeprom_read(fp, reg)
 2223 fxp_t *fp;
 2224 int reg;
 2225 {
 2226         port_t port;
 2227         u16_t v;
 2228         int b, i, alen;
 2229 
 2230         alen= fp->fxp_ee_addrlen;
 2231         if (!alen)
 2232         {
 2233                 eeprom_addrsize(fp);
 2234                 alen= fp->fxp_ee_addrlen;
 2235                 assert(alen == 6 || alen == 8);
 2236         }
 2237 
 2238         port= fp->fxp_base_port;
 2239 
 2240         fxp_outb(port, CSR_EEPROM, CE_EECS);    /* Enable EEPROM */
 2241         v= EEPROM_READ_PREFIX;
 2242         for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
 2243         {
 2244                 b= ((v & (1 << i)) ? CE_EEDI : 0);
 2245                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);        /* bit */
 2246                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
 2247                 micro_delay(EESK_PERIOD/2+1);
 2248                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);                
 2249                 micro_delay(EESK_PERIOD/2+1);
 2250         }
 2251         
 2252         v= reg;
 2253         for (i= alen-1; i >= 0; i--)
 2254         {
 2255                 b= ((v & (1 << i)) ? CE_EEDI : 0);
 2256                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);        /* bit */
 2257                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
 2258                 micro_delay(EESK_PERIOD/2+1);
 2259                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);                
 2260                 micro_delay(EESK_PERIOD/2+1);
 2261         }
 2262 
 2263         v= 0;
 2264         for (i= 0; i<16; i++)
 2265         {
 2266                 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
 2267                 micro_delay(EESK_PERIOD/2+1);
 2268                 b= !!(fxp_inb(port, CSR_EEPROM) & CE_EEDO);
 2269                 v= (v << 1) | b;
 2270                 fxp_outb(port, CSR_EEPROM, CE_EECS );           
 2271                 micro_delay(EESK_PERIOD/2+1);
 2272         }
 2273         fxp_outb(port, CSR_EEPROM, 0);  /* Disable EEPROM */
 2274         micro_delay(EECS_DELAY);
 2275 
 2276         return v;
 2277 }
 2278 
 2279 /*===========================================================================*
 2280  *                              eeprom_addrsize                              *
 2281  *===========================================================================*/
 2282 PRIVATE void eeprom_addrsize(fp)
 2283 fxp_t *fp;
 2284 {
 2285         port_t port;
 2286         u16_t v;
 2287         int b, i;
 2288 
 2289         port= fp->fxp_base_port;
 2290 
 2291         /* Try to find out the size of the EEPROM */
 2292         fxp_outb(port, CSR_EEPROM, CE_EECS);    /* Enable EEPROM */
 2293         v= EEPROM_READ_PREFIX;
 2294         for (i= EEPROM_PREFIX_LEN-1; i >= 0; i--)
 2295         {
 2296                 b= ((v & (1 << i)) ? CE_EEDI : 0);
 2297                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);        /* bit */
 2298                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
 2299                 micro_delay(EESK_PERIOD/2+1);
 2300                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);                
 2301                 micro_delay(EESK_PERIOD/2+1);
 2302         }
 2303 
 2304         for (i= 0; i<32; i++)
 2305         {
 2306                 b= 0;
 2307                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);        /* bit */
 2308                 fxp_outb(port, CSR_EEPROM, CE_EECS | b | CE_EESK); /* Clock */
 2309                 micro_delay(EESK_PERIOD/2+1);
 2310                 fxp_outb(port, CSR_EEPROM, CE_EECS | b);                
 2311                 micro_delay(EESK_PERIOD/2+1);
 2312                 v= fxp_inb(port, CSR_EEPROM);
 2313                 if (!(v & CE_EEDO))
 2314                         break;
 2315         }
 2316         if (i >= 32)
 2317                 panic("FXP","eeprom_addrsize: failed", NO_NUM);
 2318         fp->fxp_ee_addrlen= i+1;
 2319 
 2320         /* Discard 16 data bits */
 2321         for (i= 0; i<16; i++)
 2322         {
 2323                 fxp_outb(port, CSR_EEPROM, CE_EECS | CE_EESK); /* Clock */
 2324                 micro_delay(EESK_PERIOD/2+1);
 2325                 fxp_outb(port, CSR_EEPROM, CE_EECS );           
 2326                 micro_delay(EESK_PERIOD/2+1);
 2327         }
 2328         fxp_outb(port, CSR_EEPROM, 0);  /* Disable EEPROM */
 2329         micro_delay(EECS_DELAY);
 2330 
 2331 #if VERBOSE
 2332         printf("%s EEPROM address length: %d\n",
 2333                 fp->fxp_name, fp->fxp_ee_addrlen);
 2334 #endif
 2335 }
 2336 
 2337 /*===========================================================================*
 2338  *                              mii_read                                     *
 2339  *===========================================================================*/
 2340 PRIVATE u16_t mii_read(fp, reg)
 2341 fxp_t *fp;
 2342 int reg;
 2343 {
 2344         clock_t t0,t1;
 2345         port_t port;
 2346         u32_t v;
 2347 
 2348         port= fp->fxp_base_port;
 2349 
 2350         assert(!fp->fxp_mii_busy);
 2351         fp->fxp_mii_busy++;
 2352 
 2353         if (!(fxp_inl(port, CSR_MDI_CTL) & CM_READY))
 2354                 panic("FXP","mii_read: MDI not ready", NO_NUM);
 2355         fxp_outl(port, CSR_MDI_CTL, CM_READ | (1 << CM_PHYADDR_SHIFT) |
 2356                 (reg << CM_REG_SHIFT));
 2357 
 2358         getuptime(&t0);
 2359         do {
 2360                 v= fxp_inl(port, CSR_MDI_CTL);
 2361                 if (v & CM_READY)
 2362                         break;
 2363         } while (getuptime(&t1)==OK && (t1-t0) < MICROS_TO_TICKS(100000));
 2364 
 2365         if (!(v & CM_READY))
 2366                 panic("FXP","mii_read: MDI not ready after command", NO_NUM);
 2367 
 2368         fp->fxp_mii_busy--;
 2369         assert(!fp->fxp_mii_busy);
 2370 
 2371         return v & CM_DATA_MASK;
 2372 }
 2373 
 2374 /*===========================================================================*
 2375  *                              fxp_set_timer                                *
 2376  *===========================================================================*/
 2377 PRIVATE void fxp_set_timer(tp, delta, watchdog)
 2378 timer_t *tp;                            /* timer to be set */
 2379 clock_t delta;                          /* in how many ticks */
 2380 tmr_func_t watchdog;                    /* watchdog function to be called */
 2381 {
 2382         clock_t now;                            /* current time */
 2383         int r;
 2384 
 2385         /* Get the current time. */
 2386         r= getuptime(&now);
 2387         if (r != OK)
 2388                 panic("FXP","unable to get uptime from clock", r);
 2389 
 2390         /* Add the timer to the local timer queue. */
 2391         tmrs_settimer(&fxp_timers, tp, now + delta, watchdog, NULL);
 2392 
 2393         /* Possibly reschedule an alarm call. This happens when a new timer
 2394          * is added in front. 
 2395          */
 2396         if (fxp_next_timeout == 0 || 
 2397                 fxp_timers->tmr_exp_time < fxp_next_timeout)
 2398         {
 2399                 fxp_next_timeout= fxp_timers->tmr_exp_time; 
 2400 #if VERBOSE
 2401                 printf("fxp_set_timer: calling sys_setalarm for %d (now+%d)\n",
 2402                         fxp_next_timeout, fxp_next_timeout-now);
 2403 #endif
 2404                 r= sys_setalarm(fxp_next_timeout, 1);
 2405                 if (r != OK)
 2406                         panic("FXP","unable to set synchronous alarm", r);
 2407         }
 2408 }
 2409 
 2410 /*===========================================================================*
 2411  *                              fxp_expire_tmrs                              *
 2412  *===========================================================================*/
 2413 PRIVATE void fxp_expire_timers()
 2414 {
 2415 /* A synchronous alarm message was received. Check if there are any expired 
 2416  * timers. Possibly reschedule the next alarm.  
 2417  */
 2418   clock_t now;                          /* current time */
 2419   timer_t *tp;
 2420   int r;
 2421 
 2422   /* Get the current time to compare the timers against. */
 2423   r= getuptime(&now);
 2424   if (r != OK)
 2425         panic("FXP","Unable to get uptime from clock.", r);
 2426 
 2427   /* Scan the timers queue for expired timers. Dispatch the watchdog function
 2428    * for each expired timers. Possibly a new alarm call must be scheduled.
 2429    */
 2430   tmrs_exptimers(&fxp_timers, now, NULL);
 2431   if (fxp_timers == NULL)
 2432         fxp_next_timeout= TMR_NEVER;
 2433   else
 2434   {                                       /* set new alarm */
 2435         fxp_next_timeout = fxp_timers->tmr_exp_time;
 2436         r= sys_setalarm(fxp_next_timeout, 1);
 2437         if (r != OK)
 2438                 panic("FXP","Unable to set synchronous alarm.", r);
 2439   }
 2440 }
 2441 
 2442 static void micro_delay(unsigned long usecs)
 2443 {
 2444         tickdelay(MICROS_TO_TICKS(usecs));
 2445 }
 2446 
 2447 static u8_t do_inb(port_t port)
 2448 {
 2449         int r;
 2450         u32_t value;
 2451 
 2452         r= sys_inb(port, &value);
 2453         if (r != OK)
 2454                 panic("FXP","sys_inb failed", r);
 2455         return value;
 2456 }
 2457 
 2458 static u32_t do_inl(port_t port)
 2459 {
 2460         int r;
 2461         u32_t value;
 2462 
 2463         r= sys_inl(port, &value);
 2464         if (r != OK)
 2465                 panic("FXP","sys_inl failed", r);
 2466         return value;
 2467 }
 2468 
 2469 static void do_outb(port_t port, u8_t value)
 2470 {
 2471         int r;
 2472 
 2473         r= sys_outb(port, value);
 2474         if (r != OK)
 2475                 panic("FXP","sys_outb failed", r);
 2476 }
 2477 
 2478 static void do_outl(port_t port, u32_t value)
 2479 {
 2480         int r;
 2481 
 2482         r= sys_outl(port, value);
 2483         if (r != OK)
 2484                 panic("FXP","sys_outl failed", r);
 2485 }
 2486 
 2487 /*
 2488  * $PchId: fxp.c,v 1.4 2005/01/31 22:10:37 philip Exp $
 2489  */
 2490 

Cache object: 24ace8389ce3212bcd15546464b72cdf


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