The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/drivers/dp8390/dp8390.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  * dp8390.c
    3  *
    4  * This file contains a ethernet device driver for NS dp8390 based ethernet
    5  * cards.
    6  *
    7  * The valid messages and their parameters are:
    8  *
    9  *   m_type       DL_PORT    DL_PROC   DL_COUNT   DL_MODE   DL_ADDR
   10  * |------------+----------+---------+----------+---------+---------|
   11  * | 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:     before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
   41  *
   42  * Modified Mar 10 1994 by Philip Homburg
   43  *      Become a generic dp8390 driver.
   44  *
   45  * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
   46  *      Added support for 3c503 boards.
   47  */
   48 
   49 #include "../drivers.h"
   50 
   51 #include <stdlib.h>
   52 #include <minix/com.h>
   53 #include <net/hton.h>
   54 #include <net/gen/ether.h>
   55 #include <net/gen/eth_io.h>
   56 #include "assert.h"
   57 
   58 #include "local.h"
   59 #include "dp8390.h"
   60 
   61 #define DE_PORT_NR      3
   62 
   63 static dpeth_t de_table[DE_PORT_NR];
   64 static u16_t eth_ign_proto;
   65 static char *progname;
   66 
   67 /* Configuration */
   68 typedef struct dp_conf
   69 {
   70         port_t dpc_port;
   71         int dpc_irq;
   72         phys_bytes dpc_mem;
   73         char *dpc_envvar;
   74 } dp_conf_t;
   75 
   76 dp_conf_t dp_conf[]=    /* Card addresses */
   77 {
   78         /* I/O port, IRQ,  Buffer address,  Env. var. */
   79         {  0x280,     3,    0xD0000,        "DPETH0"    },
   80         {  0x300,     5,    0xC8000,        "DPETH1"    },
   81         {  0x380,    10,    0xD8000,        "DPETH2"    },
   82 };
   83 
   84 /* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
   85  * the error: "array size is negative".
   86  */
   87 extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
   88 
   89 /* Card inits configured out? */
   90 #if !ENABLE_WDETH
   91 #define wdeth_probe(dep)        (0)
   92 #endif
   93 #if !ENABLE_NE2000
   94 #define ne_probe(dep)           (0)
   95 #endif
   96 #if !ENABLE_3C503
   97 #define el2_probe(dep)          (0)
   98 #endif
   99 
  100 /* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
  101  * on writes to the CR register. Additional CR_STAs do not appear to hurt
  102  * genuine dp8390s
  103  */
  104 #define CR_EXTRA        CR_STA
  105 
  106 #if ENABLE_PCI
  107 _PROTOTYPE( static void pci_conf, (void)                                );
  108 #endif
  109 _PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
  110                                                         int vectored)   );
  111 _PROTOTYPE( static void do_vread, (message *mp, int vectored)           );
  112 _PROTOTYPE( static void do_init, (message *mp)                          );
  113 _PROTOTYPE( static void do_int, (dpeth_t *dep)                          );
  114 _PROTOTYPE( static void do_getstat, (message *mp)                       );
  115 _PROTOTYPE( static void do_getname, (message *mp)                       );
  116 _PROTOTYPE( static void do_stop, (message *mp)                          );
  117 _PROTOTYPE( static void dp_init, (dpeth_t *dep)                         );
  118 _PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)                     );
  119 _PROTOTYPE( static void dp_reinit, (dpeth_t *dep)                       );
  120 _PROTOTYPE( static void dp_reset, (dpeth_t *dep)                        );
  121 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)                   );
  122 _PROTOTYPE( static void dp_recv, (dpeth_t *dep)                         );
  123 _PROTOTYPE( static void dp_send, (dpeth_t *dep)                         );
  124 _PROTOTYPE( static void dp8390_stop, (void)                             );
  125 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
  126                                 size_t offset, size_t size, void *dst)  );
  127 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
  128                                 size_t offset, size_t size, void *dst)  );
  129 _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
  130                                 size_t offset, size_t size, void *dst)  );
  131 _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
  132                                                         int length)     );
  133 _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 
  134                 vir_bytes offset, int nic_addr, vir_bytes count)        );
  135 _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
  136                                 iovec_dat_t *iovp, vir_bytes offset,
  137                                 int nic_addr, vir_bytes count)          );
  138 _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
  139                                 iovec_dat_t *iovp, vir_bytes offset,
  140                                 int nic_addr, vir_bytes count)          );
  141 _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, 
  142                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  143 _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 
  144                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  145 _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 
  146                 iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  147 _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)              );
  148 _PROTOTYPE( static void conf_hw, (dpeth_t *dep)                         );
  149 _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)     );
  150 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)             );
  151 _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)   );
  152 _PROTOTYPE( static void mess_reply, (message *req, message *reply)      );
  153 _PROTOTYPE( static void get_userdata, (int user_proc,
  154                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  155 _PROTOTYPE( static void put_userdata, (int user_proc,
  156                 vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  157 _PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)                             );
  158 _PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)                             );
  159 _PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
  160                                         vir_bytes buf, size_t size)     );
  161 _PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
  162                                         vir_bytes buf, size_t size)     );
  163 _PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
  164                                         vir_bytes buf, size_t size)     );
  165 _PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
  166                                         vir_bytes buf, size_t size)     );
  167 
  168 /*===========================================================================*
  169  *                              dpeth_task                                   *
  170  *===========================================================================*/
  171 int main(int argc, char *argv[])
  172 {
  173         message m;
  174         int i, irq, r, tasknr;
  175         dpeth_t *dep;
  176         long v;
  177 
  178         if (argc < 1)
  179         {
  180                 panic("DP8390",
  181                         "A head which at this time has no name", NO_NUM);
  182         }
  183         (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
  184 
  185         env_setargs(argc, argv);
  186 
  187         for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
  188         {
  189                 strcpy(dep->de_name, "dp8390#0");
  190                 dep->de_name[7] += i;
  191         }
  192 
  193         v= 0;
  194         (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
  195         eth_ign_proto= htons((u16_t) v);
  196 
  197         /* Try to notify inet that we are present (again) */
  198         r = findproc("inet", &tasknr);
  199         if (r == OK)
  200                 notify(tasknr);
  201 
  202         while (TRUE)
  203         {
  204                 if ((r= receive(ANY, &m)) != OK)
  205                         panic("", "dp8390: receive failed", r);
  206 
  207                 switch (m.m_type)
  208                 {
  209                 case DEV_PING:  notify(m.m_source);             continue;
  210                 case DL_WRITE:  do_vwrite(&m, FALSE, FALSE);    break;
  211                 case DL_WRITEV: do_vwrite(&m, FALSE, TRUE);     break;
  212                 case DL_READ:   do_vread(&m, FALSE);            break;
  213                 case DL_READV:  do_vread(&m, TRUE);             break;
  214                 case DL_INIT:   do_init(&m);                    break;
  215                 case DL_GETSTAT: do_getstat(&m);                break;
  216                 case DL_GETNAME: do_getname(&m);                break;
  217                 case DL_STOP:   do_stop(&m);                    break;
  218                 case HARD_INT:
  219                         for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
  220                         {
  221                                 if (dep->de_mode != DEM_ENABLED)
  222                                         continue;
  223                                 assert(dep->de_flags & DEF_ENABLED);
  224                                 irq= dep->de_irq;
  225                                 assert(irq >= 0 && irq < NR_IRQ_VECTORS);
  226                                 if (dep->de_int_pending || 1)
  227                                 {
  228                                         dep->de_int_pending= 0;
  229                                         dp_check_ints(dep);
  230                                         do_int(dep);
  231                                         r= sys_irqenable(&dep->de_hook);
  232                                         if (r != OK)
  233                                         {
  234                                                 panic("DP8390", 
  235                                                 "unable enable interrupts", r);
  236                                         }
  237                                 }
  238                         }
  239                         break;
  240                 case SYS_SIG:   {
  241                         sigset_t sigset = m.NOTIFY_ARG;
  242                         if (sigismember(&sigset, SIGKSTOP)) dp8390_stop();
  243                         break;
  244                 }
  245                 case SYN_ALARM:
  246                         printf("dp8390: strange, got SYN_ALARM\n");
  247                         break;
  248                 default:
  249                         panic("", "dp8390: illegal message", m.m_type);
  250                 }
  251         }
  252 }
  253 
  254 #if 0
  255 /*===========================================================================*
  256  *                              dp8390_dump                                  *
  257  *===========================================================================*/
  258 void dp8390_dump()
  259 {
  260         dpeth_t *dep;
  261         int i, isr;
  262 
  263         printf("\n");
  264         for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
  265         {
  266 #if XXX
  267                 if (dep->de_mode == DEM_DISABLED)
  268                         printf("dp8390 port %d is disabled\n", i);
  269                 else if (dep->de_mode == DEM_SINK)
  270                         printf("dp8390 port %d is in sink mode\n", i);
  271 #endif
  272 
  273                 if (dep->de_mode != DEM_ENABLED)
  274                         continue;
  275 
  276                 printf("dp8390 statistics of port %d:\n", i);
  277 
  278                 printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
  279                 printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
  280                 printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
  281 
  282                 printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
  283                 printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
  284                 printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
  285 
  286                 printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
  287                 printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
  288                 printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
  289 
  290                 printf("collision  :%8ld\t", dep->de_stat.ets_collision);
  291                 printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
  292                 printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
  293 
  294                 printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
  295                 printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
  296                 printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
  297 
  298                 printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
  299 
  300                 isr= inb_reg0(dep, DP_ISR);
  301                 printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
  302                                         inb_reg0(dep, DP_ISR), dep->de_flags);
  303         }
  304 }
  305 #endif
  306 
  307 /*===========================================================================*
  308  *                              dp8390_stop                                  *
  309  *===========================================================================*/
  310 static void dp8390_stop()
  311 {
  312         message mess;
  313         int i;
  314 
  315         for (i= 0; i<DE_PORT_NR; i++)
  316         {
  317                 if (de_table[i].de_mode != DEM_ENABLED)
  318                         continue;
  319                 mess.m_type= DL_STOP;
  320                 mess.DL_PORT= i;
  321                 do_stop(&mess);
  322         }
  323 }
  324 
  325 #if ENABLE_PCI
  326 /*===========================================================================*
  327  *                              pci_conf                                     *
  328  *===========================================================================*/
  329 static void pci_conf()
  330 {
  331         int i, h;
  332         char *envvar;
  333         struct dpeth *dep;
  334         static char envfmt[] = "*:d.d.d";
  335         long v;
  336         static int first_time= 1;
  337 
  338         if (!first_time)
  339                 return;
  340         first_time= 0;
  341 
  342         for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
  343         {
  344                 envvar= dp_conf[i].dpc_envvar;
  345                 if (!(dep->de_pci= env_prefix(envvar, "pci")))
  346                         continue;       /* no PCI config */
  347                 v= 0;
  348                 (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
  349                 dep->de_pcibus= v;
  350                 v= 0;
  351                 (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
  352                 dep->de_pcidev= v;
  353                 v= 0;
  354                 (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
  355                 dep->de_pcifunc= v;
  356         }
  357 
  358         for (h= 1; h >= 0; h--) {
  359                 for (i= 0, dep= de_table; i<DE_PORT_NR; i++, dep++)
  360                 {
  361                         if (!dep->de_pci)
  362                                 continue;
  363                         if (((dep->de_pcibus | dep->de_pcidev |
  364                                 dep->de_pcifunc) != 0) != h)
  365                         {
  366                                 continue;
  367                         }
  368                         if (!rtl_probe(dep))
  369                                 dep->de_pci= -1;
  370                 }
  371         }
  372 }
  373 #endif /* ENABLE_PCI */
  374 
  375 /*===========================================================================*
  376  *                              do_vwrite                                    *
  377  *===========================================================================*/
  378 static void do_vwrite(mp, from_int, vectored)
  379 message *mp;
  380 int from_int;
  381 int vectored;
  382 {
  383         int port, count, size;
  384         int sendq_head;
  385         dpeth_t *dep;
  386 
  387         port = mp->DL_PORT;
  388         count = mp->DL_COUNT;
  389         if (port < 0 || port >= DE_PORT_NR)
  390                 panic("", "dp8390: illegal port", port);
  391         dep= &de_table[port];
  392         dep->de_client= mp->DL_PROC;
  393 
  394         if (dep->de_mode == DEM_SINK)
  395         {
  396                 assert(!from_int);
  397                 dep->de_flags |= DEF_PACK_SEND;
  398                 reply(dep, OK, FALSE);
  399                 return;
  400         }
  401         assert(dep->de_mode == DEM_ENABLED);
  402         assert(dep->de_flags & DEF_ENABLED);
  403         if (dep->de_flags & DEF_SEND_AVAIL)
  404                 panic("", "dp8390: send already in progress", NO_NUM);
  405 
  406         sendq_head= dep->de_sendq_head;
  407         if (dep->de_sendq[sendq_head].sq_filled)
  408         {
  409                 if (from_int)
  410                         panic("", "dp8390: should not be sending\n", NO_NUM);
  411                 dep->de_sendmsg= *mp;
  412                 dep->de_flags |= DEF_SEND_AVAIL;
  413                 reply(dep, OK, FALSE);
  414                 return;
  415         }
  416         assert(!(dep->de_flags & DEF_PACK_SEND));
  417 
  418         if (vectored)
  419         {
  420                 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
  421                         (count > IOVEC_NR ? IOVEC_NR : count) *
  422                         sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
  423                 dep->de_write_iovec.iod_iovec_s = count;
  424                 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
  425                 dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
  426 
  427                 dep->de_tmp_iovec = dep->de_write_iovec;
  428                 size = calc_iovec_size(&dep->de_tmp_iovec);
  429         }
  430         else
  431         {  
  432                 dep->de_write_iovec.iod_iovec[0].iov_addr =
  433                         (vir_bytes) mp->DL_ADDR;
  434                 dep->de_write_iovec.iod_iovec[0].iov_size =
  435                         mp->DL_COUNT;
  436                 dep->de_write_iovec.iod_iovec_s = 1;
  437                 dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
  438                 dep->de_write_iovec.iod_iovec_addr = 0;
  439                 size= mp->DL_COUNT;
  440         }
  441         if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
  442         {
  443                 panic("", "dp8390: invalid packet size", size);
  444         }
  445         (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
  446                 dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
  447                 size);
  448         dep->de_sendq[sendq_head].sq_filled= TRUE;
  449         if (dep->de_sendq_tail == sendq_head)
  450         {
  451                 outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
  452                 outb_reg0(dep, DP_TBCR1, size >> 8);
  453                 outb_reg0(dep, DP_TBCR0, size & 0xff);
  454                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
  455         }
  456         else
  457                 dep->de_sendq[sendq_head].sq_size= size;
  458         
  459         if (++sendq_head == dep->de_sendq_nr)
  460                 sendq_head= 0;
  461         assert(sendq_head < SENDQ_NR);
  462         dep->de_sendq_head= sendq_head;
  463 
  464         dep->de_flags |= DEF_PACK_SEND;
  465 
  466         /* If the interrupt handler called, don't send a reply. The reply
  467          * will be sent after all interrupts are handled. 
  468          */
  469         if (from_int)
  470                 return;
  471         reply(dep, OK, FALSE);
  472 
  473         assert(dep->de_mode == DEM_ENABLED);
  474         assert(dep->de_flags & DEF_ENABLED);
  475 }
  476 
  477 /*===========================================================================*
  478  *                              do_vread                                     *
  479  *===========================================================================*/
  480 static void do_vread(mp, vectored)
  481 message *mp;
  482 int vectored;
  483 {
  484         int port, count;
  485         int size;
  486         dpeth_t *dep;
  487 
  488         port = mp->DL_PORT;
  489         count = mp->DL_COUNT;
  490         if (port < 0 || port >= DE_PORT_NR)
  491                 panic("", "dp8390: illegal port", port);
  492         dep= &de_table[port];
  493         dep->de_client= mp->DL_PROC;
  494         if (dep->de_mode == DEM_SINK)
  495         {
  496                 reply(dep, OK, FALSE);
  497                 return;
  498         }
  499         assert(dep->de_mode == DEM_ENABLED);
  500         assert(dep->de_flags & DEF_ENABLED);
  501 
  502         if(dep->de_flags & DEF_READING)
  503                 panic("", "dp8390: read already in progress", NO_NUM);
  504 
  505         if (vectored)
  506         {
  507                 get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
  508                         (count > IOVEC_NR ? IOVEC_NR : count) *
  509                         sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
  510                 dep->de_read_iovec.iod_iovec_s = count;
  511                 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
  512                 dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
  513 
  514                 dep->de_tmp_iovec = dep->de_read_iovec;
  515                 size= calc_iovec_size(&dep->de_tmp_iovec);
  516         }
  517         else
  518         {
  519                 dep->de_read_iovec.iod_iovec[0].iov_addr =
  520                         (vir_bytes) mp->DL_ADDR;
  521                 dep->de_read_iovec.iod_iovec[0].iov_size =
  522                         mp->DL_COUNT;
  523                 dep->de_read_iovec.iod_iovec_s = 1;
  524                 dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
  525                 dep->de_read_iovec.iod_iovec_addr = 0;
  526                 size= count;
  527         }
  528         if (size < ETH_MAX_PACK_SIZE_TAGGED)
  529                 panic("", "dp8390: wrong packet size", size);
  530         dep->de_flags |= DEF_READING;
  531 
  532         dp_recv(dep);
  533 
  534         if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
  535                 (DEF_READING|DEF_STOPPED))
  536         {
  537                 /* The chip is stopped, and all arrived packets are 
  538                  * delivered.
  539                  */
  540                 dp_reset(dep);
  541         }
  542         reply(dep, OK, FALSE);
  543 }
  544 
  545 /*===========================================================================*
  546  *                              do_init                                      *
  547  *===========================================================================*/
  548 static void do_init(mp)
  549 message *mp;
  550 {
  551         int port;
  552         dpeth_t *dep;
  553         message reply_mess;
  554 
  555 #if ENABLE_PCI
  556         pci_conf(); /* Configure PCI devices. */
  557 #endif
  558 
  559         port = mp->DL_PORT;
  560         if (port < 0 || port >= DE_PORT_NR)
  561         {
  562                 reply_mess.m_type= DL_INIT_REPLY;
  563                 reply_mess.m3_i1= ENXIO;
  564                 mess_reply(mp, &reply_mess);
  565                 return;
  566         }
  567         dep= &de_table[port];
  568         if (dep->de_mode == DEM_DISABLED)
  569         {
  570                 /* This is the default, try to (re)locate the device. */
  571                 conf_hw(dep);
  572                 if (dep->de_mode == DEM_DISABLED)
  573                 {
  574                         /* Probe failed, or the device is configured off. */
  575                         reply_mess.m_type= DL_INIT_REPLY;
  576                         reply_mess.m3_i1= ENXIO;
  577                         mess_reply(mp, &reply_mess);
  578                         return;
  579                 }
  580                 if (dep->de_mode == DEM_ENABLED)
  581                         dp_init(dep);
  582         }
  583 
  584         if (dep->de_mode == DEM_SINK)
  585         {
  586                 strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
  587                 dep->de_address.ea_addr[5] = port;
  588                 dp_confaddr(dep);
  589                 reply_mess.m_type = DL_INIT_REPLY;
  590                 reply_mess.m3_i1 = mp->DL_PORT;
  591                 reply_mess.m3_i2 = DE_PORT_NR;
  592                 *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
  593                 mess_reply(mp, &reply_mess);
  594                 return;
  595         }
  596         assert(dep->de_mode == DEM_ENABLED);
  597         assert(dep->de_flags & DEF_ENABLED);
  598 
  599         dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
  600 
  601         if (mp->DL_MODE & DL_PROMISC_REQ)
  602                 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
  603         if (mp->DL_MODE & DL_MULTI_REQ)
  604                 dep->de_flags |= DEF_MULTI;
  605         if (mp->DL_MODE & DL_BROAD_REQ)
  606                 dep->de_flags |= DEF_BROAD;
  607 
  608         dep->de_client = mp->m_source;
  609         dp_reinit(dep);
  610 
  611         reply_mess.m_type = DL_INIT_REPLY;
  612         reply_mess.m3_i1 = mp->DL_PORT;
  613         reply_mess.m3_i2 = DE_PORT_NR;
  614         *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
  615 
  616         mess_reply(mp, &reply_mess);
  617 }
  618 
  619 /*===========================================================================*
  620  *                              do_int                                       *
  621  *===========================================================================*/
  622 static void do_int(dep)
  623 dpeth_t *dep;
  624 {
  625         if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
  626                 reply(dep, OK, TRUE);
  627 }
  628 
  629 /*===========================================================================*
  630  *                              do_getstat                                   *
  631  *===========================================================================*/
  632 static void do_getstat(mp)
  633 message *mp;
  634 {
  635         int port;
  636         dpeth_t *dep;
  637 
  638         port = mp->DL_PORT;
  639         if (port < 0 || port >= DE_PORT_NR)
  640                 panic("", "dp8390: illegal port", port);
  641         dep= &de_table[port];
  642         dep->de_client= mp->DL_PROC;
  643         if (dep->de_mode == DEM_SINK)
  644         {
  645                 put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
  646                         (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
  647                 reply(dep, OK, FALSE);
  648                 return;
  649         }
  650         assert(dep->de_mode == DEM_ENABLED);
  651         assert(dep->de_flags & DEF_ENABLED);
  652 
  653         dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
  654         dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
  655         dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
  656 
  657         put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
  658                 (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
  659         reply(dep, OK, FALSE);
  660 }
  661 
  662 /*===========================================================================*
  663  *                              do_getname                                   *
  664  *===========================================================================*/
  665 static void do_getname(mp)
  666 message *mp;
  667 {
  668         int r;
  669 
  670         strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
  671         mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
  672         mp->m_type= DL_NAME_REPLY;
  673         r= send(mp->m_source, mp);
  674         if (r != OK)
  675                 panic("dp8390", "do_getname: send failed: %d\n", r);
  676 }
  677 
  678 /*===========================================================================*
  679  *                              do_stop                                      *
  680  *===========================================================================*/
  681 static void do_stop(mp)
  682 message *mp;
  683 {
  684         int port;
  685         dpeth_t *dep;
  686 
  687         port = mp->DL_PORT;
  688 
  689         if (port < 0 || port >= DE_PORT_NR)
  690                 panic("", "dp8390: illegal port", port);
  691         dep= &de_table[port];
  692         if (dep->de_mode == DEM_SINK)
  693                 return;
  694         assert(dep->de_mode == DEM_ENABLED);
  695 
  696         if (!(dep->de_flags & DEF_ENABLED))
  697                 return;
  698 
  699         outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
  700         (dep->de_stopf)(dep);
  701 
  702         dep->de_flags= DEF_EMPTY;
  703 }
  704 
  705 /*===========================================================================*
  706  *                              dp_init                                      *
  707  *===========================================================================*/
  708 static void dp_init(dep)
  709 dpeth_t *dep;
  710 {
  711         int dp_rcr_reg;
  712         int i, r;
  713 
  714         /* General initialization */
  715         dep->de_flags = DEF_EMPTY;
  716         (*dep->de_initf)(dep);
  717 
  718         dp_confaddr(dep);
  719 
  720         if (debug)
  721         {
  722                 printf("%s: Ethernet address ", dep->de_name);
  723                 for (i= 0; i < 6; i++)
  724                         printf("%x%c", dep->de_address.ea_addr[i],
  725                                                         i < 5 ? ':' : '\n');
  726         }
  727 
  728         /* Initialization of the dp8390 following the mandatory procedure
  729          * in reference manual ("DP8390D/NS32490D NIC Network Interface
  730          * Controller", National Semiconductor, July 1995, Page 29).
  731          */
  732         /* Step 1: */
  733         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
  734         /* Step 2: */
  735         if (dep->de_16bit)
  736                 outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
  737         else
  738                 outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
  739         /* Step 3: */
  740         outb_reg0(dep, DP_RBCR0, 0);
  741         outb_reg0(dep, DP_RBCR1, 0);
  742         /* Step 4: */
  743         dp_rcr_reg = 0;
  744         if (dep->de_flags & DEF_PROMISC)
  745                 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
  746         if (dep->de_flags & DEF_BROAD)
  747                 dp_rcr_reg |= RCR_AB;
  748         if (dep->de_flags & DEF_MULTI)
  749                 dp_rcr_reg |= RCR_AM;
  750         outb_reg0(dep, DP_RCR, dp_rcr_reg);
  751         /* Step 5: */
  752         outb_reg0(dep, DP_TCR, TCR_INTERNAL);
  753         /* Step 6: */
  754         outb_reg0(dep, DP_BNRY, dep->de_startpage);
  755         outb_reg0(dep, DP_PSTART, dep->de_startpage);
  756         outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
  757         /* Step 7: */
  758         outb_reg0(dep, DP_ISR, 0xFF);
  759         /* Step 8: */
  760         outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
  761                 IMR_OVWE | IMR_CNTE);
  762         /* Step 9: */
  763         outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
  764 
  765         outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
  766         outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
  767         outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
  768         outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
  769         outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
  770         outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
  771 
  772         outb_reg1(dep, DP_MAR0, 0xff);
  773         outb_reg1(dep, DP_MAR1, 0xff);
  774         outb_reg1(dep, DP_MAR2, 0xff);
  775         outb_reg1(dep, DP_MAR3, 0xff);
  776         outb_reg1(dep, DP_MAR4, 0xff);
  777         outb_reg1(dep, DP_MAR5, 0xff);
  778         outb_reg1(dep, DP_MAR6, 0xff);
  779         outb_reg1(dep, DP_MAR7, 0xff);
  780 
  781         outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
  782         /* Step 10: */
  783         outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
  784         /* Step 11: */
  785         outb_reg0(dep, DP_TCR, TCR_NORMAL);
  786 
  787         inb_reg0(dep, DP_CNTR0);                /* reset counters by reading */
  788         inb_reg0(dep, DP_CNTR1);
  789         inb_reg0(dep, DP_CNTR2);
  790 
  791         /* Finish the initialization. */
  792         dep->de_flags |= DEF_ENABLED;
  793         for (i= 0; i<dep->de_sendq_nr; i++)
  794                 dep->de_sendq[i].sq_filled= 0;
  795         dep->de_sendq_head= 0;
  796         dep->de_sendq_tail= 0;
  797         if (!dep->de_prog_IO)
  798         {
  799                 dep->de_user2nicf= dp_user2nic;
  800                 dep->de_nic2userf= dp_nic2user;
  801                 dep->de_getblockf= dp_getblock;
  802         }
  803         else if (dep->de_16bit)
  804         {
  805                 dep->de_user2nicf= dp_pio16_user2nic;
  806                 dep->de_nic2userf= dp_pio16_nic2user;
  807                 dep->de_getblockf= dp_pio16_getblock;
  808         }
  809         else
  810         {
  811                 dep->de_user2nicf= dp_pio8_user2nic;
  812                 dep->de_nic2userf= dp_pio8_nic2user;
  813                 dep->de_getblockf= dp_pio8_getblock;
  814         }
  815 
  816         /* Set the interrupt handler and policy. Do not automatically 
  817          * reenable interrupts. Return the IRQ line number on interrupts.
  818          */
  819         dep->de_hook = dep->de_irq;
  820         r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
  821         if (r != OK)
  822                 panic("DP8390", "sys_irqsetpolicy failed", r);
  823 
  824         r= sys_irqenable(&dep->de_hook);
  825         if (r != OK)
  826         {
  827                 panic("DP8390", "unable enable interrupts", r);
  828         }
  829 }
  830 
  831 /*===========================================================================*
  832  *                              dp_confaddr                                  *
  833  *===========================================================================*/
  834 static void dp_confaddr(dep)
  835 dpeth_t *dep;
  836 {
  837         int i;
  838         char eakey[16];
  839         static char eafmt[]= "x:x:x:x:x:x";
  840         long v;
  841 
  842         /* User defined ethernet address? */
  843         strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
  844         strcat(eakey, "_EA");
  845 
  846         for (i= 0; i < 6; i++)
  847         {
  848                 v= dep->de_address.ea_addr[i];
  849                 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
  850                 {
  851                         break;
  852                 }
  853                 dep->de_address.ea_addr[i]= v;
  854         }
  855 
  856         if (i != 0 && i != 6) env_panic(eakey); /* It's all or nothing */
  857 }
  858 
  859 /*===========================================================================*
  860  *                              dp_reinit                                    *
  861  *===========================================================================*/
  862 static void dp_reinit(dep)
  863 dpeth_t *dep;
  864 {
  865         int dp_rcr_reg;
  866 
  867         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
  868 
  869         dp_rcr_reg = 0;
  870         if (dep->de_flags & DEF_PROMISC)
  871                 dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
  872         if (dep->de_flags & DEF_BROAD)
  873                 dp_rcr_reg |= RCR_AB;
  874         if (dep->de_flags & DEF_MULTI)
  875                 dp_rcr_reg |= RCR_AM;
  876         outb_reg0(dep, DP_RCR, dp_rcr_reg);
  877 }
  878 
  879 /*===========================================================================*
  880  *                              dp_reset                                     *
  881  *===========================================================================*/
  882 static void dp_reset(dep)
  883 dpeth_t *dep;
  884 {
  885         int i;
  886 
  887         /* Stop chip */
  888         outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
  889         outb_reg0(dep, DP_RBCR0, 0);
  890         outb_reg0(dep, DP_RBCR1, 0);
  891         for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
  892                 ; /* Do nothing */
  893         outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
  894         outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
  895         outb_reg0(dep, DP_TCR, TCR_NORMAL);
  896 
  897         /* Acknowledge the ISR_RDC (remote dma) interrupt. */
  898         for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
  899                 ; /* Do nothing */
  900         outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
  901 
  902         /* Reset the transmit ring. If we were transmitting a packet, we
  903          * pretend that the packet is processed. Higher layers will
  904          * retransmit if the packet wasn't actually sent.
  905          */
  906         dep->de_sendq_head= dep->de_sendq_tail= 0;
  907         for (i= 0; i<dep->de_sendq_nr; i++)
  908                 dep->de_sendq[i].sq_filled= 0;
  909         dp_send(dep);
  910         dep->de_flags &= ~DEF_STOPPED;
  911 }
  912 
  913 /*===========================================================================*
  914  *                              dp_check_ints                                *
  915  *===========================================================================*/
  916 static void dp_check_ints(dep)
  917 dpeth_t *dep;
  918 {
  919         int isr, tsr;
  920         int size, sendq_tail;
  921 
  922         if (!(dep->de_flags & DEF_ENABLED))
  923                 panic("", "dp8390: got premature interrupt", NO_NUM);
  924 
  925         for(;;)
  926         {
  927                 isr = inb_reg0(dep, DP_ISR);
  928                 if (!isr)
  929                         break;
  930                 outb_reg0(dep, DP_ISR, isr);
  931                 if (isr & (ISR_PTX|ISR_TXE))
  932                 {
  933                         if (isr & ISR_TXE)
  934                         {
  935 #if DEBUG
  936  { printf("%s: got send Error\n", dep->de_name); }
  937 #endif
  938                                 dep->de_stat.ets_sendErr++;
  939                         }
  940                         else
  941                         {
  942                                 tsr = inb_reg0(dep, DP_TSR);
  943 
  944                                 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
  945 #if 0   /* Reserved in later manuals, should be ignored */
  946                                 if (!(tsr & TSR_DFR))
  947                                 {
  948                                         /* In most (all?) implementations of
  949                                          * the dp8390, this bit is set
  950                                          * when the packet is not deferred
  951                                          */
  952                                         dep->de_stat.ets_transDef++;
  953                                 }
  954 #endif
  955                                 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
  956                                 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
  957                                 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
  958                                 if (tsr & TSR_FU
  959                                         && ++dep->de_stat.ets_fifoUnder <= 10)
  960                                 {
  961                                         printf("%s: fifo underrun\n",
  962                                                 dep->de_name);
  963                                 }
  964                                 if (tsr & TSR_CDH
  965                                         && ++dep->de_stat.ets_CDheartbeat <= 10)
  966                                 {
  967                                         printf("%s: CD heart beat failure\n",
  968                                                 dep->de_name);
  969                                 }
  970                                 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
  971                         }
  972                         sendq_tail= dep->de_sendq_tail;
  973 
  974                         if (!(dep->de_sendq[sendq_tail].sq_filled))
  975                         {
  976                                 /* Software bug? */
  977                                 assert(!debug);
  978 
  979                                 /* Or hardware bug? */
  980                                 printf(
  981                                 "%s: transmit interrupt, but not sending\n",
  982                                         dep->de_name);
  983                                 continue;
  984                         }
  985                         dep->de_sendq[sendq_tail].sq_filled= 0;
  986                         if (++sendq_tail == dep->de_sendq_nr)
  987                                 sendq_tail= 0;
  988                         dep->de_sendq_tail= sendq_tail;
  989                         if (dep->de_sendq[sendq_tail].sq_filled)
  990                         {
  991                                 size= dep->de_sendq[sendq_tail].sq_size;
  992                                 outb_reg0(dep, DP_TPSR,
  993                                         dep->de_sendq[sendq_tail].sq_sendpage);
  994                                 outb_reg0(dep, DP_TBCR1, size >> 8);
  995                                 outb_reg0(dep, DP_TBCR0, size & 0xff);
  996                                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
  997                         }
  998                         if (dep->de_flags & DEF_SEND_AVAIL)
  999                                 dp_send(dep);
 1000                 }
 1001 
 1002                 if (isr & ISR_PRX)
 1003                 {
 1004                         /* Only call dp_recv if there is a read request */
 1005                         if (dep->de_flags & DEF_READING)
 1006                                 dp_recv(dep);
 1007                 }
 1008                 
 1009                 if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
 1010                 if (isr & ISR_CNT)
 1011                 {
 1012                         dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
 1013                         dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
 1014                         dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
 1015                 }
 1016                 if (isr & ISR_OVW)
 1017                 {
 1018                         dep->de_stat.ets_OVW++;
 1019 #if 0
 1020                         { printW(); printf(
 1021                                 "%s: got overwrite warning\n", dep->de_name); }
 1022 #endif
 1023                         if (dep->de_flags & DEF_READING)
 1024                         {
 1025                                 printf(
 1026 "dp_check_ints: strange: overwrite warning and pending read request\n");
 1027                                 dp_recv(dep);
 1028                         }
 1029                 }
 1030                 if (isr & ISR_RDC)
 1031                 {
 1032                         /* Nothing to do */
 1033                 }
 1034                 if (isr & ISR_RST)
 1035                 {
 1036                         /* this means we got an interrupt but the ethernet 
 1037                          * chip is shutdown. We set the flag DEF_STOPPED,
 1038                          * and continue processing arrived packets. When the
 1039                          * receive buffer is empty, we reset the dp8390.
 1040                          */
 1041 #if 0
 1042                          { printW(); printf(
 1043                                 "%s: NIC stopped\n", dep->de_name); }
 1044 #endif
 1045                         dep->de_flags |= DEF_STOPPED;
 1046                         break;
 1047                 }
 1048         }
 1049         if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == 
 1050                                                 (DEF_READING|DEF_STOPPED))
 1051         {
 1052                 /* The chip is stopped, and all arrived packets are 
 1053                  * delivered.
 1054                  */
 1055                 dp_reset(dep);
 1056         }
 1057 }
 1058 
 1059 /*===========================================================================*
 1060  *                              dp_recv                                      *
 1061  *===========================================================================*/
 1062 static void dp_recv(dep)
 1063 dpeth_t *dep;
 1064 {
 1065         dp_rcvhdr_t header;
 1066         unsigned pageno, curr, next;
 1067         vir_bytes length;
 1068         int packet_processed, r;
 1069         u16_t eth_type;
 1070 
 1071         packet_processed = FALSE;
 1072         pageno = inb_reg0(dep, DP_BNRY) + 1;
 1073         if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
 1074 
 1075         do
 1076         {
 1077                 outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
 1078                 curr = inb_reg1(dep, DP_CURR);
 1079                 outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
 1080 
 1081                 if (curr == pageno) break;
 1082 
 1083                 (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
 1084                         &header);
 1085                 (dep->de_getblockf)(dep, pageno, sizeof(header) +
 1086                         2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
 1087 
 1088                 length = (header.dr_rbcl | (header.dr_rbch << 8)) -
 1089                         sizeof(dp_rcvhdr_t);
 1090                 next = header.dr_next;
 1091                 if (length < ETH_MIN_PACK_SIZE ||
 1092                         length > ETH_MAX_PACK_SIZE_TAGGED)
 1093                 {
 1094                         printf("%s: packet with strange length arrived: %d\n",
 1095                                 dep->de_name, (int) length);
 1096                         next= curr;
 1097                 }
 1098                 else if (next < dep->de_startpage || next >= dep->de_stoppage)
 1099                 {
 1100                         printf("%s: strange next page\n", dep->de_name);
 1101                         next= curr;
 1102                 }
 1103                 else if (eth_type == eth_ign_proto)
 1104                 {
 1105                         /* Hack: ignore packets of a given protocol, useful
 1106                          * if you share a net with 80 computers sending
 1107                          * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
 1108                          */
 1109                         static int first= 1;
 1110                         if (first)
 1111                         {
 1112                                 first= 0;
 1113                                 printf("%s: dropping proto 0x%04x packets\n",
 1114                                         dep->de_name,
 1115                                         ntohs(eth_ign_proto));
 1116                         }
 1117                         dep->de_stat.ets_packetR++;
 1118                 }
 1119                 else if (header.dr_status & RSR_FO)
 1120                 {
 1121                         /* This is very serious, so we issue a warning and
 1122                          * reset the buffers */
 1123                         printf("%s: fifo overrun, resetting receive buffer\n",
 1124                                 dep->de_name);
 1125                         dep->de_stat.ets_fifoOver++;
 1126                         next = curr;
 1127                 }
 1128                 else if ((header.dr_status & RSR_PRX) &&
 1129                                            (dep->de_flags & DEF_ENABLED))
 1130                 {
 1131                         r = dp_pkt2user(dep, pageno, length);
 1132                         if (r != OK)
 1133                                 return;
 1134 
 1135                         packet_processed = TRUE;
 1136                         dep->de_stat.ets_packetR++;
 1137                 }
 1138                 if (next == dep->de_startpage)
 1139                         outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
 1140                 else
 1141                         outb_reg0(dep, DP_BNRY, next - 1);
 1142 
 1143                 pageno = next;
 1144         }
 1145         while (!packet_processed);
 1146 }
 1147 
 1148 /*===========================================================================*
 1149  *                              dp_send                                      *
 1150  *===========================================================================*/
 1151 static void dp_send(dep)
 1152 dpeth_t *dep;
 1153 {
 1154         if (!(dep->de_flags & DEF_SEND_AVAIL))
 1155                 return;
 1156 
 1157         dep->de_flags &= ~DEF_SEND_AVAIL;
 1158         switch(dep->de_sendmsg.m_type)
 1159         {
 1160         case DL_WRITE:  do_vwrite(&dep->de_sendmsg, TRUE, FALSE);       break;
 1161         case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE);        break;
 1162         default:
 1163                 panic("", "dp8390: wrong type:", dep->de_sendmsg.m_type);
 1164                 break;
 1165         }
 1166 }
 1167 
 1168 /*===========================================================================*
 1169  *                              dp_getblock                                  *
 1170  *===========================================================================*/
 1171 static void dp_getblock(dep, page, offset, size, dst)
 1172 dpeth_t *dep;
 1173 int page;
 1174 size_t offset;
 1175 size_t size;
 1176 void *dst;
 1177 {
 1178         int r;
 1179 
 1180         offset = page * DP_PAGESIZE + offset;
 1181 
 1182         r = sys_vircopy(SELF, BIOS_SEG, dep->de_linmem + offset,
 1183                 SELF, D, (vir_bytes)dst, size);
 1184 
 1185         if (r != OK)
 1186                 panic("DP8390", "dp_getblock: sys_vircopy failed", r);
 1187 }
 1188 
 1189 /*===========================================================================*
 1190  *                              dp_pio8_getblock                             *
 1191  *===========================================================================*/
 1192 static void dp_pio8_getblock(dep, page, offset, size, dst)
 1193 dpeth_t *dep;
 1194 int page;
 1195 size_t offset;
 1196 size_t size;
 1197 void *dst;
 1198 {
 1199         offset = page * DP_PAGESIZE + offset;
 1200         outb_reg0(dep, DP_RBCR0, size & 0xFF);
 1201         outb_reg0(dep, DP_RBCR1, size >> 8);
 1202         outb_reg0(dep, DP_RSAR0, offset & 0xFF);
 1203         outb_reg0(dep, DP_RSAR1, offset >> 8);
 1204         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 1205 
 1206         insb(dep->de_data_port, dst, size);
 1207 }
 1208 
 1209 /*===========================================================================*
 1210  *                              dp_pio16_getblock                            *
 1211  *===========================================================================*/
 1212 static void dp_pio16_getblock(dep, page, offset, size, dst)
 1213 dpeth_t *dep;
 1214 int page;
 1215 size_t offset;
 1216 size_t size;
 1217 void *dst;
 1218 {
 1219         offset = page * DP_PAGESIZE + offset;
 1220         outb_reg0(dep, DP_RBCR0, size & 0xFF);
 1221         outb_reg0(dep, DP_RBCR1, size >> 8);
 1222         outb_reg0(dep, DP_RSAR0, offset & 0xFF);
 1223         outb_reg0(dep, DP_RSAR1, offset >> 8);
 1224         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 1225 
 1226         assert (!(size & 1));
 1227         insw(dep->de_data_port, dst, size);
 1228 }
 1229 
 1230 /*===========================================================================*
 1231  *                              dp_pkt2user                                  *
 1232  *===========================================================================*/
 1233 static int dp_pkt2user(dep, page, length)
 1234 dpeth_t *dep;
 1235 int page, length;
 1236 {
 1237         int last, count;
 1238 
 1239         if (!(dep->de_flags & DEF_READING))
 1240                 return EGENERIC;
 1241 
 1242         last = page + (length - 1) / DP_PAGESIZE;
 1243         if (last >= dep->de_stoppage)
 1244         {
 1245                 count = (dep->de_stoppage - page) * DP_PAGESIZE -
 1246                         sizeof(dp_rcvhdr_t);
 1247 
 1248                 /* Save read_iovec since we need it twice. */
 1249                 dep->de_tmp_iovec = dep->de_read_iovec;
 1250                 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
 1251                         sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
 1252                 (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 
 1253                                 &dep->de_read_iovec, count, length - count);
 1254         }
 1255         else
 1256         {
 1257                 (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
 1258                         sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
 1259         }
 1260 
 1261         dep->de_read_s = length;
 1262         dep->de_flags |= DEF_PACK_RECV;
 1263         dep->de_flags &= ~DEF_READING;
 1264 
 1265         return OK;
 1266 }
 1267 
 1268 /*===========================================================================*
 1269  *                              dp_user2nic                                  *
 1270  *===========================================================================*/
 1271 static void dp_user2nic(dep, iovp, offset, nic_addr, count)
 1272 dpeth_t *dep;
 1273 iovec_dat_t *iovp;
 1274 vir_bytes offset;
 1275 int nic_addr;
 1276 vir_bytes count;
 1277 {
 1278         vir_bytes vir_hw, vir_user;
 1279         int bytes, i, r;
 1280 
 1281         vir_hw = dep->de_linmem + nic_addr;
 1282 
 1283         i= 0;
 1284         while (count > 0)
 1285         {
 1286                 if (i >= IOVEC_NR)
 1287                 {
 1288                         dp_next_iovec(iovp);
 1289                         i= 0;
 1290                         continue;
 1291                 }
 1292                 assert(i < iovp->iod_iovec_s);
 1293                 if (offset >= iovp->iod_iovec[i].iov_size)
 1294                 {
 1295                         offset -= iovp->iod_iovec[i].iov_size;
 1296                         i++;
 1297                         continue;
 1298                 }
 1299                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1300                 if (bytes > count)
 1301                         bytes = count;
 1302 
 1303                 r= sys_vircopy(iovp->iod_proc_nr, D,
 1304                         iovp->iod_iovec[i].iov_addr + offset,
 1305                         SELF, BIOS_SEG, vir_hw, bytes);
 1306                 if (r != OK)
 1307                         panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
 1308 
 1309                 count -= bytes;
 1310                 vir_hw += bytes;
 1311                 offset += bytes;
 1312         }
 1313         assert(count == 0);
 1314 }
 1315 
 1316 /*===========================================================================*
 1317  *                              dp_pio8_user2nic                             *
 1318  *===========================================================================*/
 1319 static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
 1320 dpeth_t *dep;
 1321 iovec_dat_t *iovp;
 1322 vir_bytes offset;
 1323 int nic_addr;
 1324 vir_bytes count;
 1325 {
 1326         phys_bytes phys_user;
 1327         int bytes, i;
 1328 
 1329         outb_reg0(dep, DP_ISR, ISR_RDC);
 1330 
 1331         outb_reg0(dep, DP_RBCR0, count & 0xFF);
 1332         outb_reg0(dep, DP_RBCR1, count >> 8);
 1333         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
 1334         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
 1335         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
 1336 
 1337         i= 0;
 1338         while (count > 0)
 1339         {
 1340                 if (i >= IOVEC_NR)
 1341                 {
 1342                         dp_next_iovec(iovp);
 1343                         i= 0;
 1344                         continue;
 1345                 }
 1346                 assert(i < iovp->iod_iovec_s);
 1347                 if (offset >= iovp->iod_iovec[i].iov_size)
 1348                 {
 1349                         offset -= iovp->iod_iovec[i].iov_size;
 1350                         i++;
 1351                         continue;
 1352                 }
 1353                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1354                 if (bytes > count)
 1355                         bytes = count;
 1356 
 1357                 do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
 1358                         iovp->iod_iovec[i].iov_addr + offset, bytes);
 1359                 count -= bytes;
 1360                 offset += bytes;
 1361         }
 1362         assert(count == 0);
 1363 
 1364         for (i= 0; i<100; i++)
 1365         {
 1366                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
 1367                         break;
 1368         }
 1369         if (i == 100)
 1370         {
 1371                 panic("", "dp8390: remote dma failed to complete", NO_NUM);
 1372         }
 1373 }
 1374 
 1375 /*===========================================================================*
 1376  *                              dp_pio16_user2nic                            *
 1377  *===========================================================================*/
 1378 static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
 1379 dpeth_t *dep;
 1380 iovec_dat_t *iovp;
 1381 vir_bytes offset;
 1382 int nic_addr;
 1383 vir_bytes count;
 1384 {
 1385         vir_bytes vir_user;
 1386         vir_bytes ecount;
 1387         int i, r, bytes, user_proc;
 1388         u8_t two_bytes[2];
 1389         int odd_byte;
 1390 
 1391         ecount= (count+1) & ~1;
 1392         odd_byte= 0;
 1393 
 1394         outb_reg0(dep, DP_ISR, ISR_RDC);
 1395         outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
 1396         outb_reg0(dep, DP_RBCR1, ecount >> 8);
 1397         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
 1398         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
 1399         outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
 1400 
 1401         i= 0;
 1402         while (count > 0)
 1403         {
 1404                 if (i >= IOVEC_NR)
 1405                 {
 1406                         dp_next_iovec(iovp);
 1407                         i= 0;
 1408                         continue;
 1409                 }
 1410                 assert(i < iovp->iod_iovec_s);
 1411                 if (offset >= iovp->iod_iovec[i].iov_size)
 1412                 {
 1413                         offset -= iovp->iod_iovec[i].iov_size;
 1414                         i++;
 1415                         continue;
 1416                 }
 1417                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1418                 if (bytes > count)
 1419                         bytes = count;
 1420 
 1421                 user_proc= iovp->iod_proc_nr;
 1422                 vir_user= iovp->iod_iovec[i].iov_addr + offset;
 1423                 if (odd_byte)
 1424                 {
 1425                         r= sys_vircopy(user_proc, D, vir_user, 
 1426                                 SELF, D, (vir_bytes)&two_bytes[1], 1);
 1427                         if (r != OK)
 1428                         {
 1429                                 panic("DP8390",
 1430                                         "dp_pio16_user2nic: sys_vircopy failed",
 1431                                         r);
 1432                         }
 1433                         outw(dep->de_data_port, *(u16_t *)two_bytes);
 1434                         count--;
 1435                         offset++;
 1436                         bytes--;
 1437                         vir_user++;
 1438                         odd_byte= 0;
 1439                         if (!bytes)
 1440                                 continue;
 1441                 }
 1442                 ecount= bytes & ~1;
 1443                 if (ecount != 0)
 1444                 {
 1445                         do_vir_outsw(dep->de_data_port, user_proc, vir_user,
 1446                                 ecount);
 1447                         count -= ecount;
 1448                         offset += ecount;
 1449                         bytes -= ecount;
 1450                         vir_user += ecount;
 1451                 }
 1452                 if (bytes)
 1453                 {
 1454                         assert(bytes == 1);
 1455                         r= sys_vircopy(user_proc, D, vir_user, 
 1456                                 SELF, D, (vir_bytes)&two_bytes[0], 1);
 1457                         if (r != OK)
 1458                         {
 1459                                 panic("DP8390",
 1460                                         "dp_pio16_user2nic: sys_vircopy failed",
 1461                                         r);
 1462                         }
 1463                         count--;
 1464                         offset++;
 1465                         bytes--;
 1466                         vir_user++;
 1467                         odd_byte= 1;
 1468                 }
 1469         }
 1470         assert(count == 0);
 1471 
 1472         if (odd_byte)
 1473                 outw(dep->de_data_port, *(u16_t *)two_bytes);
 1474 
 1475         for (i= 0; i<100; i++)
 1476         {
 1477                 if (inb_reg0(dep, DP_ISR) & ISR_RDC)
 1478                         break;
 1479         }
 1480         if (i == 100)
 1481         {
 1482                 panic("", "dp8390: remote dma failed to complete", NO_NUM);
 1483         }
 1484 }
 1485 
 1486 /*===========================================================================*
 1487  *                              dp_nic2user                                  *
 1488  *===========================================================================*/
 1489 static void dp_nic2user(dep, nic_addr, iovp, offset, count)
 1490 dpeth_t *dep;
 1491 int nic_addr;
 1492 iovec_dat_t *iovp;
 1493 vir_bytes offset;
 1494 vir_bytes count;
 1495 {
 1496         vir_bytes vir_hw, vir_user;
 1497         int bytes, i, r;
 1498 
 1499         vir_hw = dep->de_linmem + nic_addr;
 1500 
 1501         i= 0;
 1502         while (count > 0)
 1503         {
 1504                 if (i >= IOVEC_NR)
 1505                 {
 1506                         dp_next_iovec(iovp);
 1507                         i= 0;
 1508                         continue;
 1509                 }
 1510                 assert(i < iovp->iod_iovec_s);
 1511                 if (offset >= iovp->iod_iovec[i].iov_size)
 1512                 {
 1513                         offset -= iovp->iod_iovec[i].iov_size;
 1514                         i++;
 1515                         continue;
 1516                 }
 1517                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1518                 if (bytes > count)
 1519                         bytes = count;
 1520 
 1521                 r= sys_vircopy(SELF, BIOS_SEG, vir_hw,
 1522                         iovp->iod_proc_nr, D,
 1523                         iovp->iod_iovec[i].iov_addr + offset, bytes);
 1524                 if (r != OK)
 1525                         panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
 1526 
 1527                 count -= bytes;
 1528                 vir_hw += bytes;
 1529                 offset += bytes;
 1530         }
 1531         assert(count == 0);
 1532 }
 1533 
 1534 /*===========================================================================*
 1535  *                              dp_pio8_nic2user                             *
 1536  *===========================================================================*/
 1537 static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
 1538 dpeth_t *dep;
 1539 int nic_addr;
 1540 iovec_dat_t *iovp;
 1541 vir_bytes offset;
 1542 vir_bytes count;
 1543 {
 1544         phys_bytes phys_user;
 1545         int bytes, i;
 1546 
 1547         outb_reg0(dep, DP_RBCR0, count & 0xFF);
 1548         outb_reg0(dep, DP_RBCR1, count >> 8);
 1549         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
 1550         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
 1551         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 1552 
 1553         i= 0;
 1554         while (count > 0)
 1555         {
 1556                 if (i >= IOVEC_NR)
 1557                 {
 1558                         dp_next_iovec(iovp);
 1559                         i= 0;
 1560                         continue;
 1561                 }
 1562                 assert(i < iovp->iod_iovec_s);
 1563                 if (offset >= iovp->iod_iovec[i].iov_size)
 1564                 {
 1565                         offset -= iovp->iod_iovec[i].iov_size;
 1566                         i++;
 1567                         continue;
 1568                 }
 1569                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1570                 if (bytes > count)
 1571                         bytes = count;
 1572 
 1573                 do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
 1574                         iovp->iod_iovec[i].iov_addr + offset, bytes);
 1575                 count -= bytes;
 1576                 offset += bytes;
 1577         }
 1578         assert(count == 0);
 1579 }
 1580 
 1581 /*===========================================================================*
 1582  *                              dp_pio16_nic2user                            *
 1583  *===========================================================================*/
 1584 static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
 1585 dpeth_t *dep;
 1586 int nic_addr;
 1587 iovec_dat_t *iovp;
 1588 vir_bytes offset;
 1589 vir_bytes count;
 1590 {
 1591         vir_bytes vir_user;
 1592         vir_bytes ecount;
 1593         int i, r, bytes, user_proc;
 1594         u8_t two_bytes[2];
 1595         int odd_byte;
 1596 
 1597         ecount= (count+1) & ~1;
 1598         odd_byte= 0;
 1599 
 1600         outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
 1601         outb_reg0(dep, DP_RBCR1, ecount >> 8);
 1602         outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
 1603         outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
 1604         outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
 1605 
 1606         i= 0;
 1607         while (count > 0)
 1608         {
 1609                 if (i >= IOVEC_NR)
 1610                 {
 1611                         dp_next_iovec(iovp);
 1612                         i= 0;
 1613                         continue;
 1614                 }
 1615                 assert(i < iovp->iod_iovec_s);
 1616                 if (offset >= iovp->iod_iovec[i].iov_size)
 1617                 {
 1618                         offset -= iovp->iod_iovec[i].iov_size;
 1619                         i++;
 1620                         continue;
 1621                 }
 1622                 bytes = iovp->iod_iovec[i].iov_size - offset;
 1623                 if (bytes > count)
 1624                         bytes = count;
 1625 
 1626                 user_proc= iovp->iod_proc_nr;
 1627                 vir_user= iovp->iod_iovec[i].iov_addr + offset;
 1628                 if (odd_byte)
 1629                 {
 1630                         r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
 1631                                 user_proc, D, vir_user,  1);
 1632                         if (r != OK)
 1633                         {
 1634                                 panic("DP8390",
 1635                                         "dp_pio16_nic2user: sys_vircopy failed",
 1636                                         r);
 1637                         }
 1638                         count--;
 1639                         offset++;
 1640                         bytes--;
 1641                         vir_user++;
 1642                         odd_byte= 0;
 1643                         if (!bytes)
 1644                                 continue;
 1645                 }
 1646                 ecount= bytes & ~1;
 1647                 if (ecount != 0)
 1648                 {
 1649                         do_vir_insw(dep->de_data_port, user_proc, vir_user,
 1650                                 ecount);
 1651                         count -= ecount;
 1652                         offset += ecount;
 1653                         bytes -= ecount;
 1654                         vir_user += ecount;
 1655                 }
 1656                 if (bytes)
 1657                 {
 1658                         assert(bytes == 1);
 1659                         *(u16_t *)two_bytes= inw(dep->de_data_port);
 1660                         r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
 1661                                 user_proc, D, vir_user,  1);
 1662                         if (r != OK)
 1663                         {
 1664                                 panic("DP8390",
 1665                                         "dp_pio16_nic2user: sys_vircopy failed",
 1666                                         r);
 1667                         }
 1668                         count--;
 1669                         offset++;
 1670                         bytes--;
 1671                         vir_user++;
 1672                         odd_byte= 1;
 1673                 }
 1674         }
 1675         assert(count == 0);
 1676 }
 1677 
 1678 /*===========================================================================*
 1679  *                              dp_next_iovec                                        *
 1680  *===========================================================================*/
 1681 static void dp_next_iovec(iovp)
 1682 iovec_dat_t *iovp;
 1683 {
 1684         assert(iovp->iod_iovec_s > IOVEC_NR);
 1685 
 1686         iovp->iod_iovec_s -= IOVEC_NR;
 1687 
 1688         iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
 1689 
 1690         get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
 1691                 (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
 1692                 sizeof(iovec_t), iovp->iod_iovec); 
 1693 }
 1694 
 1695 /*===========================================================================*
 1696  *                              conf_hw                                      *
 1697  *===========================================================================*/
 1698 static void conf_hw(dep)
 1699 dpeth_t *dep;
 1700 {
 1701         static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
 1702 
 1703         int ifnr;
 1704         dp_conf_t *dcp;
 1705 
 1706         dep->de_mode= DEM_DISABLED;     /* Superfluous */
 1707         ifnr= dep-de_table;
 1708 
 1709         dcp= &dp_conf[ifnr];
 1710         update_conf(dep, dcp);
 1711         if (dep->de_mode != DEM_ENABLED)
 1712                 return;
 1713         if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
 1714         {
 1715                 printf("%s: No ethernet card found at 0x%x\n", 
 1716                         dep->de_name, dep->de_base_port);
 1717                 dep->de_mode= DEM_DISABLED;
 1718                 return;
 1719         }
 1720 
 1721 /* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
 1722 
 1723         dep->de_flags = DEF_EMPTY;
 1724         dep->de_stat = empty_stat;
 1725 }
 1726 
 1727 /*===========================================================================*
 1728  *                              update_conf                                  *
 1729  *===========================================================================*/
 1730 static void update_conf(dep, dcp)
 1731 dpeth_t *dep;
 1732 dp_conf_t *dcp;
 1733 {
 1734         long v;
 1735         static char dpc_fmt[] = "x:d:x:x";
 1736 
 1737 #if ENABLE_PCI
 1738         if (dep->de_pci)
 1739         {
 1740                 if (dep->de_pci == 1)
 1741                 {
 1742                         /* PCI device is present */
 1743                         dep->de_mode= DEM_ENABLED;
 1744                 }
 1745                 return;         /* Already configured */
 1746         }
 1747 #endif
 1748 
 1749         /* Get the default settings and modify them from the environment. */
 1750         dep->de_mode= DEM_SINK;
 1751         v= dcp->dpc_port;
 1752         switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
 1753         case EP_OFF:
 1754                 dep->de_mode= DEM_DISABLED;
 1755                 break;
 1756         case EP_ON:
 1757         case EP_SET:
 1758                 dep->de_mode= DEM_ENABLED;      /* Might become disabled if 
 1759                                                  * all probes fail */
 1760                 break;
 1761         }
 1762         dep->de_base_port= v;
 1763 
 1764         v= dcp->dpc_irq | DEI_DEFAULT;
 1765         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
 1766                                                 (long) NR_IRQ_VECTORS - 1);
 1767         dep->de_irq= v;
 1768 
 1769         v= dcp->dpc_mem;
 1770         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
 1771         dep->de_linmem= v;
 1772 
 1773         v= 0;
 1774         (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
 1775         dep->de_ramsize= v;
 1776 }
 1777 
 1778 /*===========================================================================*
 1779  *                              calc_iovec_size                              *
 1780  *===========================================================================*/
 1781 static int calc_iovec_size(iovp)
 1782 iovec_dat_t *iovp;
 1783 {
 1784         /* Calculate the size of a request. Note that the iovec_dat
 1785          * structure will be unusable after calc_iovec_size.
 1786          */
 1787         int size;
 1788         int i;
 1789 
 1790         size= 0;
 1791         i= 0;
 1792         while (i < iovp->iod_iovec_s)
 1793         {
 1794                 if (i >= IOVEC_NR)
 1795                 {
 1796                         dp_next_iovec(iovp);
 1797                         i= 0;
 1798                         continue;
 1799                 }
 1800                 size += iovp->iod_iovec[i].iov_size;
 1801                 i++;
 1802         }
 1803         return size;
 1804 }
 1805 
 1806 /*===========================================================================*
 1807  *                              reply                                        *
 1808  *===========================================================================*/
 1809 static void reply(dep, err, may_block)
 1810 dpeth_t *dep;
 1811 int err;
 1812 int may_block;
 1813 {
 1814         message reply;
 1815         int status;
 1816         int r;
 1817 
 1818         status = 0;
 1819         if (dep->de_flags & DEF_PACK_SEND)
 1820                 status |= DL_PACK_SEND;
 1821         if (dep->de_flags & DEF_PACK_RECV)
 1822                 status |= DL_PACK_RECV;
 1823 
 1824         reply.m_type = DL_TASK_REPLY;
 1825         reply.DL_PORT = dep - de_table;
 1826         reply.DL_PROC = dep->de_client;
 1827         reply.DL_STAT = status | ((u32_t) err << 16);
 1828         reply.DL_COUNT = dep->de_read_s;
 1829         reply.DL_CLCK = 0;      /* Don't know */
 1830         r= send(dep->de_client, &reply);
 1831 
 1832         if (r == ELOCKED && may_block)
 1833         {
 1834 #if 0
 1835                 printf("send locked\n");
 1836 #endif
 1837                 return;
 1838         }
 1839 
 1840         if (r < 0)
 1841                 panic("", "dp8390: send failed:", r);
 1842         
 1843         dep->de_read_s = 0;
 1844         dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
 1845 }
 1846 
 1847 /*===========================================================================*
 1848  *                              mess_reply                                   *
 1849  *===========================================================================*/
 1850 static void mess_reply(req, reply_mess)
 1851 message *req;
 1852 message *reply_mess;
 1853 {
 1854         if (send(req->m_source, reply_mess) != OK)
 1855                 panic("", "dp8390: unable to mess_reply", NO_NUM);
 1856 }
 1857 
 1858 /*===========================================================================*
 1859  *                              get_userdata                                 *
 1860  *===========================================================================*/
 1861 static void get_userdata(user_proc, user_addr, count, loc_addr)
 1862 int user_proc;
 1863 vir_bytes user_addr;
 1864 vir_bytes count;
 1865 void *loc_addr;
 1866 {
 1867         int r;
 1868 
 1869         r= sys_vircopy(user_proc, D, user_addr,
 1870                 SELF, D, (vir_bytes)loc_addr, count);
 1871         if (r != OK)
 1872                 panic("DP8390", "get_userdata: sys_vircopy failed", r);
 1873 }
 1874 
 1875 /*===========================================================================*
 1876  *                              put_userdata                                 *
 1877  *===========================================================================*/
 1878 static void put_userdata(user_proc, user_addr, count, loc_addr)
 1879 int user_proc;
 1880 vir_bytes user_addr;
 1881 vir_bytes count;
 1882 void *loc_addr;
 1883 {
 1884         int r;
 1885 
 1886         r= sys_vircopy(SELF, D, (vir_bytes)loc_addr, 
 1887                 user_proc, D, user_addr, count);
 1888         if (r != OK)
 1889                 panic("DP8390", "put_userdata: sys_vircopy failed", r);
 1890 }
 1891 
 1892 u8_t inb(port_t port)
 1893 {
 1894         int r;
 1895         u32_t value;
 1896 
 1897         r= sys_inb(port, &value);
 1898         if (r != OK)
 1899                 panic("DP8390","sys_inb failed", r);
 1900         return value;
 1901 }
 1902 
 1903 u16_t inw(port_t port)
 1904 {
 1905         int r;
 1906         u16_t value;
 1907 
 1908         r= sys_inw(port, &value);
 1909         if (r != OK)
 1910                 panic("DP8390", "sys_inw failed", r);
 1911         return value;
 1912 }
 1913 
 1914 void outb(port_t port, u8_t value)
 1915 {
 1916         int r;
 1917 
 1918         r= sys_outb(port, value);
 1919         if (r != OK)
 1920                 panic("DP8390", "sys_outb failed", r);
 1921 }
 1922 
 1923 void outw(port_t port, u16_t value)
 1924 {
 1925         int r;
 1926 
 1927         r= sys_outw(port, value);
 1928         if (r != OK)
 1929                 panic("DP8390", "sys_outw failed", r);
 1930 }
 1931 
 1932 static void insb(port_t port, void *buf, size_t size)
 1933 {
 1934         do_vir_insb(port, SELF, (vir_bytes)buf, size);
 1935 }
 1936 
 1937 static void insw(port_t port, void *buf, size_t size)
 1938 {
 1939         do_vir_insw(port, SELF, (vir_bytes)buf, size);
 1940 }
 1941 
 1942 static void do_vir_insb(port_t port, int proc, vir_bytes buf, size_t size)
 1943 {
 1944         int r;
 1945 
 1946         r= sys_sdevio(DIO_INPUT, port, DIO_BYTE, proc, (void *)buf, size);
 1947         if (r != OK)
 1948                 panic("DP8390", "sys_sdevio failed", r);
 1949 }
 1950 
 1951 static void do_vir_insw(port_t port, int proc, vir_bytes buf, size_t size)
 1952 {
 1953         int r;
 1954 
 1955         r= sys_sdevio(DIO_INPUT, port, DIO_WORD, proc, (void *)buf, size);
 1956         if (r != OK)
 1957                 panic("DP8390", "sys_sdevio failed", r);
 1958 }
 1959 
 1960 static void do_vir_outsb(port_t port, int proc, vir_bytes buf, size_t size)
 1961 {
 1962         int r;
 1963 
 1964         r= sys_sdevio(DIO_OUTPUT, port, DIO_BYTE, proc, (void *)buf, size);
 1965         if (r != OK)
 1966                 panic("DP8390", "sys_sdevio failed", r);
 1967 }
 1968 
 1969 static void do_vir_outsw(port_t port, int proc, vir_bytes buf, size_t size)
 1970 {
 1971         int r;
 1972 
 1973         r= sys_sdevio(DIO_OUTPUT, port, DIO_WORD, proc, (void *)buf, size);
 1974         if (r != OK)
 1975                 panic("DP8390", "sys_sdevio failed", r);
 1976 }
 1977 
 1978 /*
 1979  * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
 1980  */

Cache object: fc5888001bcb2291d6c1c7c6db917e97


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