Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.

0108000 /*
0108001  * dp8390.c
0108002  *
0108003  * This file contains a ethernet device driver for NS dp8390 based ethernet
0108004  * cards.
0108005  *
0108006  * The valid messages and their parameters are:
0108007  *
0108008  * m_type        DL_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR
0108009  * |------------+----------+---------+----------+---------+---------|
0108010  * | HARDINT       | | | | | |
0108011  * |------------|----------|---------|----------|---------|---------|
0108012  * | DL_WRITE       | port nr | proc nr | count | mode | address |
0108013  * |------------|----------|---------|----------|---------|---------|
0108014  * | DL_WRITEV       | port nr | proc nr | count | mode | address |
0108015  * |------------|----------|---------|----------|---------|---------|
0108016  * | DL_READ       | port nr | proc nr | count | | address |
0108017  * |------------|----------|---------|----------|---------|---------|
0108018  * | DL_READV       | port nr | proc nr | count | | address |
0108019  * |------------|----------|---------|----------|---------|---------|
0108020  * | DL_INIT       | port nr | proc nr | mode | | address |
0108021  * |------------|----------|---------|----------|---------|---------|
0108022  * | DL_GETSTAT       | port nr | proc nr | | | address |
0108023  * |------------|----------|---------|----------|---------|---------|
0108024  * | DL_STOP       | port_nr | | | |        |
0108025  * |------------|----------|---------|----------|---------|---------|
0108026  *
0108027  * The messages sent are:
0108028  *
0108029  * m-type        DL_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK
0108030  * |------------|----------|---------|----------|---------|---------|
0108031  * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
0108032  * |------------|----------|---------|----------|---------|---------|
0108033  *
0108034  * m_type        m3_i1 m3_i2 m3_ca1
0108035  * |------------+---------+-----------+---------------|
0108036  * |DL_INIT_REPL| port nr | last port | ethernet addr |
0108037  * |------------|---------|-----------|---------------|
0108038  *
0108039  * Created:       before Dec 28, 1992 by Philip Homburg <philip@cs.vu.nl>
0108040  *
0108041  * Modified Mar 10 1994 by Philip Homburg
0108042  *       Become a generic dp8390 driver.
0108043  *
0108044  * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
0108045  *       Added support for 3c503 boards.
0108046  */
0108047 
0108048 #include "kernel.h"
0108049 #include <stdlib.h>
0108050 #include <minix/com.h>
0108051 #include <net/hton.h>
0108052 #include <net/gen/ether.h>
0108053 #include <net/gen/eth_io.h>
0108054 #include "assert.h"
0108055 INIT_ASSERT
0108056 #if __minix_vmd
0108057 #include "i386/protect.h"
0108058 #else
0108059 #include "protect.h"
0108060 #endif
0108061 #include "dp8390.h"
0108062 #include "proc.h"
0108063 #if __minix_vmd
0108064 #include "config.h"
0108065 #endif
0108066 
0108067 #if ENABLE_DP8390 || __minix_vmd
0108068 
0108069 #define DE_PORT_NR       2
0108070 
0108071 static dpeth_t de_table[DE_PORT_NR];
0108072 static int int_pending[NR_IRQ_VECTORS];
0108073 static int dpeth_tasknr= ANY;
0108074 static u16_t eth_ign_proto;
0108075 
0108076 /* Configuration */
0108077 typedef struct dp_conf
0108078 {
0108079          port_t dpc_port;
0108080          int dpc_irq;
0108081          phys_bytes dpc_mem;
0108082          char *dpc_envvar;
0108083 } dp_conf_t;
0108084 
0108085 dp_conf_t dp_conf[]=       /* Card addresses */
0108086 {
0108087          /* I/O port, IRQ, Buffer address, Env. var. */
0108088          { 0x280, 3, 0xD0000, "DPETH0"       },
0108089          { 0x300, 5, 0xC8000, "DPETH1"       },
0108090 };
0108091 
0108092 /* Test if dp_conf has exactly DE_PORT_NR entries. If not then you will see
0108093  * the error: "array size is negative".
0108094  */
0108095 extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
0108096 
0108097 
0108098 /* Card inits configured out? */
0108099 #if !ENABLE_WDETH
0108100 #define wdeth_probe(dep)       (0)
0108101 #endif
0108102 #if !ENABLE_NE2000
0108103 #define ne_probe(dep)              (0)
0108104 #endif
0108105 #if !ENABLE_3C503
0108106 #define el2_probe(dep)              (0)
0108107 #endif
0108108 
0108109 
0108110 _PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
0108111                                                  int vectored)       );
0108112 _PROTOTYPE( static void do_vread, (message *mp, int vectored)              );
0108113 _PROTOTYPE( static void do_init, (message *mp)                            );
0108114 _PROTOTYPE( static void do_int, (dpeth_t *dep)                            );
0108115 _PROTOTYPE( static void do_getstat, (message *mp)                     );
0108116 _PROTOTYPE( static void do_stop, (message *mp)                            );
0108117 _PROTOTYPE( static void dp_init, (dpeth_t *dep)                            );
0108118 _PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)                     );
0108119 _PROTOTYPE( static void dp_reinit, (dpeth_t *dep)                     );
0108120 _PROTOTYPE( static void dp_reset, (dpeth_t *dep)                     );
0108121 _PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)                     );
0108122 _PROTOTYPE( static void dp_recv, (dpeth_t *dep)                            );
0108123 _PROTOTYPE( static void dp_send, (dpeth_t *dep)                            );
0108124 _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
0108125                                     size_t offset, size_t size, void *dst)       );
0108126 _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
0108127                                     size_t offset, size_t size, void *dst)       );
0108128 _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
0108129                                     size_t offset, size_t size, void *dst)       );
0108130 _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
0108131                                                  int length)       );
0108132 _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
0108133                   vir_bytes offset, int nic_addr, vir_bytes count)       );
0108134 _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
0108135                                     iovec_dat_t *iovp, vir_bytes offset,
0108136                                     int nic_addr, vir_bytes count)              );
0108137 _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
0108138                                     iovec_dat_t *iovp, vir_bytes offset,
0108139                                     int nic_addr, vir_bytes count)              );
0108140 _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
0108141                   iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)       );
0108142 _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
0108143                   iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)       );
0108144 _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
0108145                   iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)       );
0108146 _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)              );
0108147 _PROTOTYPE( static int dp_handler, (int irq)                            );
0108148 _PROTOTYPE( static void conf_hw, (dpeth_t *dep)                            );
0108149 _PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)       );
0108150 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)              );
0108151 _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)       );
0108152 _PROTOTYPE( static void mess_reply, (message *req, message *reply)       );
0108153 _PROTOTYPE( static void get_userdata, (int user_proc,
0108154                   vir_bytes user_addr, vir_bytes count, void *loc_addr)       );
0108155 _PROTOTYPE( static void put_userdata, (int user_proc,
0108156                   vir_bytes user_addr, vir_bytes count, void *loc_addr)       );
0108157 
0108158 /*===========================================================================*
0108159  *                            dpeth_task                             *
0108160  *===========================================================================*/
0108161 void dp8390_task()
0108162 {
0108163          message m;
0108164          int i, irq, r;
0108165          dpeth_t *dep;
0108166          long v;
0108167 
0108168          dpeth_tasknr= proc_number(proc_ptr);
0108169 
0108170          v= 0;
0108171          (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
0108172          eth_ign_proto= htons((u16_t) v);
0108173 
0108174          while (TRUE)
0108175          {
0108176                   if ((r= receive(ANY, &m)) != OK)
0108177                            panic("dp8390: receive failed", r);
0108178 
0108179                   switch (m.m_type)
0108180                   {
0108181                   case DL_WRITE:       do_vwrite(&m, FALSE, FALSE);       break;
0108182                   case DL_WRITEV:       do_vwrite(&m, FALSE, TRUE);       break;
0108183                   case DL_READ:       do_vread(&m, FALSE);              break;
0108184                   case DL_READV:       do_vread(&m, TRUE);              break;
0108185                   case DL_INIT:       do_init(&m);                     break;
0108186                   case DL_GETSTAT: do_getstat(&m);              break;
0108187                   case DL_STOP:       do_stop(&m);                     break;
0108188                   case HARD_INT:
0108189                            for (i= 0, dep= &de_table[0]; i<DE_PORT_NR; i++, dep++)
0108190                            {
0108191                                     if (dep->de_mode != DEM_ENABLED)
0108192                                              continue;
0108193                                     assert(dep->de_flags & DEF_ENABLED);
0108194                                     irq= dep->de_irq;
0108195                                     assert(irq >= 0 && irq < NR_IRQ_VECTORS);
0108196                                     if (int_pending[irq])
0108197                                     {
0108198                                              int_pending[irq]= 0;
0108199                                              dp_check_ints(dep);
0108200                                              do_int(dep);
0108201                                              enable_irq(irq);
0108202                                     }
0108203                            }
0108204                            break;
0108205                   default:
0108206                            panic("dp8390: illegal message", m.m_type);
0108207                   }
0108208          }
0108209 }
0108210 
0108211 
0108212 /*===========================================================================*
0108213  *                            dp_dump                                    *
0108214  *===========================================================================*/
0108215 void dp_dump()
0108216 {
0108217          dpeth_t *dep;
0108218          int i, isr;
0108219 
0108220          printf("\n");
0108221          for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
0108222          {
0108223                   if (dep->de_mode == DEM_DISABLED)
0108224                            printf("dp8390 port %d is disabled\n", i);
0108225                   else if (dep->de_mode == DEM_SINK)
0108226                            printf("dp8390 port %d is in sink mode\n", i);
0108227 
0108228                   if (dep->de_mode != DEM_ENABLED)
0108229                            continue;
0108230 
0108231                   printf("dp8390 statistics of port %d:\n", i);
0108232 
0108233                   printf("recvErr :%8ld\t", dep->de_stat.ets_recvErr);
0108234                   printf("sendErr :%8ld\t", dep->de_stat.ets_sendErr);
0108235                   printf("OVW :%8ld\n", dep->de_stat.ets_OVW);
0108236 
0108237                   printf("CRCerr :%8ld\t", dep->de_stat.ets_CRCerr);
0108238                   printf("frameAll :%8ld\t", dep->de_stat.ets_frameAll);
0108239                   printf("missedP :%8ld\n", dep->de_stat.ets_missedP);
0108240 
0108241                   printf("packetR :%8ld\t", dep->de_stat.ets_packetR);
0108242                   printf("packetT :%8ld\t", dep->de_stat.ets_packetT);
0108243                   printf("transDef :%8ld\n", dep->de_stat.ets_transDef);
0108244 
0108245                   printf("collision :%8ld\t", dep->de_stat.ets_collision);
0108246                   printf("transAb :%8ld\t", dep->de_stat.ets_transAb);
0108247                   printf("carrSense :%8ld\n", dep->de_stat.ets_carrSense);
0108248 
0108249                   printf("fifoUnder :%8ld\t", dep->de_stat.ets_fifoUnder);
0108250                   printf("fifoOver :%8ld\t", dep->de_stat.ets_fifoOver);
0108251                   printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
0108252 
0108253                   printf("OWC :%8ld\t", dep->de_stat.ets_OWC);
0108254 
0108255                   isr= inb_reg0(dep, DP_ISR);
0108256                   printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
0108257                                              inb_reg0(dep, DP_ISR), dep->de_flags);
0108258 
0108259                   if (debug)
0108260                   {
0108261                            int_pending[dep->de_irq]= 1;
0108262                            interrupt(dpeth_tasknr);
0108263                   }
0108264          }
0108265 }
0108266 
0108267 
0108268 /*===========================================================================*
0108269  *                            dp8390_stop                             *
0108270  *===========================================================================*/
0108271 void dp8390_stop()
0108272 {
0108273          message mess;
0108274          int i;
0108275 
0108276          for (i= 0; i<DE_PORT_NR; i++)
0108277          {
0108278                   if (de_table[i].de_mode != DEM_ENABLED)
0108279                            continue;
0108280                   mess.m_type= DL_STOP;
0108281                   mess.DL_PORT= i;
0108282                   do_stop(&mess);
0108283          }
0108284 }
0108285 
0108286 
0108287 /*===========================================================================*
0108288  *                            do_vwrite                             *
0108289  *===========================================================================*/
0108290 static void do_vwrite(mp, from_int, vectored)
0108291 message *mp;
0108292 int from_int;
0108293 int vectored;
0108294 {
0108295          int port, count, size;
0108296          int sendq_head;
0108297          dpeth_t *dep;
0108298 
0108299          port = mp->DL_PORT;
0108300          count = mp->DL_COUNT;
0108301          if (port < 0 || port >= DE_PORT_NR)
0108302                   panic("dp8390: illegal port", port);
0108303          dep= &de_table[port];
0108304          dep->de_client= mp->DL_PROC;
0108305 
0108306          if (dep->de_mode == DEM_SINK)
0108307          {
0108308                   assert(!from_int);
0108309                   dep->de_flags |= DEF_PACK_SEND;
0108310                   reply(dep, OK, FALSE);
0108311                   return;
0108312          }
0108313          assert(dep->de_mode == DEM_ENABLED);
0108314          assert(dep->de_flags & DEF_ENABLED);
0108315          if (dep->de_flags & DEF_SEND_AVAIL)
0108316                   panic("dp8390: send already in progress", NO_NUM);
0108317 
0108318          sendq_head= dep->de_sendq_head;
0108319          if (dep->de_sendq[sendq_head].sq_filled)
0108320          {
0108321                   if (from_int)
0108322                            panic("dp8390: should not be sending\n", NO_NUM);
0108323                   dep->de_sendmsg= *mp;
0108324                   dep->de_flags |= DEF_SEND_AVAIL;
0108325                   reply(dep, OK, FALSE);
0108326                   return;
0108327          }
0108328          assert(!(dep->de_flags & DEF_PACK_SEND));
0108329 
0108330          if (vectored)
0108331          {
0108332                   get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108333                            (count > IOVEC_NR ? IOVEC_NR : count) *
0108334                            sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
0108335                   dep->de_write_iovec.iod_iovec_s = count;
0108336                   dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
0108337                   dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
0108338 
0108339                   dep->de_tmp_iovec = dep->de_write_iovec;
0108340                   size = calc_iovec_size(&dep->de_tmp_iovec);
0108341          }
0108342          else
0108343          {
0108344                   dep->de_write_iovec.iod_iovec[0].iov_addr =
0108345                            (vir_bytes) mp->DL_ADDR;
0108346                   dep->de_write_iovec.iod_iovec[0].iov_size =
0108347                            mp->DL_COUNT;
0108348                   dep->de_write_iovec.iod_iovec_s = 1;
0108349                   dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
0108350                   dep->de_write_iovec.iod_iovec_addr = 0;
0108351                   size= mp->DL_COUNT;
0108352          }
0108353          if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
0108354          {
0108355                   panic("dp8390: invalid packet size", size);
0108356          }
0108357          (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
0108358                   dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
0108359                   size);
0108360          dep->de_sendq[sendq_head].sq_filled= TRUE;
0108361          if (dep->de_sendq_tail == sendq_head)
0108362          {
0108363                   outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
0108364                   outb_reg0(dep, DP_TBCR1, size >> 8);
0108365                   outb_reg0(dep, DP_TBCR0, size & 0xff);
0108366                   outb_reg0(dep, DP_CR, CR_TXP);       /* there it goes.. */
0108367          }
0108368          else
0108369                   dep->de_sendq[sendq_head].sq_size= size;
0108370          
0108371          if (++sendq_head == dep->de_sendq_nr)
0108372                   sendq_head= 0;
0108373          assert(sendq_head < SENDQ_NR);
0108374          dep->de_sendq_head= sendq_head;
0108375 
0108376          dep->de_flags |= DEF_PACK_SEND;
0108377 
0108378          /* If the interrupt handler called, don't send a reply. The reply
0108379           * will be sent after all interrupts are handled.
0108380           */
0108381          if (from_int)
0108382                   return;
0108383          reply(dep, OK, FALSE);
0108384 
0108385          assert(dep->de_mode == DEM_ENABLED);
0108386          assert(dep->de_flags & DEF_ENABLED);
0108387 }
0108388 
0108389 
0108390 /*===========================================================================*
0108391  *                            do_vread                             *
0108392  *===========================================================================*/
0108393 static void do_vread(mp, vectored)
0108394 message *mp;
0108395 int vectored;
0108396 {
0108397          int port, count;
0108398          int size;
0108399          dpeth_t *dep;
0108400 
0108401          port = mp->DL_PORT;
0108402          count = mp->DL_COUNT;
0108403          if (port < 0 || port >= DE_PORT_NR)
0108404                   panic("dp8390: illegal port", port);
0108405          dep= &de_table[port];
0108406          dep->de_client= mp->DL_PROC;
0108407          if (dep->de_mode == DEM_SINK)
0108408          {
0108409                   reply(dep, OK, FALSE);
0108410                   return;
0108411          }
0108412          assert(dep->de_mode == DEM_ENABLED);
0108413          assert(dep->de_flags & DEF_ENABLED);
0108414 
0108415          if(dep->de_flags & DEF_READING)
0108416                   panic("dp8390: read already in progress", NO_NUM);
0108417 
0108418          if (vectored)
0108419          {
0108420                   get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108421                            (count > IOVEC_NR ? IOVEC_NR : count) *
0108422                            sizeof(iovec_t), dep->de_read_iovec.iod_iovec);
0108423                   dep->de_read_iovec.iod_iovec_s = count;
0108424                   dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
0108425                   dep->de_read_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
0108426 
0108427                   dep->de_tmp_iovec = dep->de_read_iovec;
0108428                   size= calc_iovec_size(&dep->de_tmp_iovec);
0108429          }
0108430          else
0108431          {
0108432                   dep->de_read_iovec.iod_iovec[0].iov_addr =
0108433                            (vir_bytes) mp->DL_ADDR;
0108434                   dep->de_read_iovec.iod_iovec[0].iov_size =
0108435                            mp->DL_COUNT;
0108436                   dep->de_read_iovec.iod_iovec_s = 1;
0108437                   dep->de_read_iovec.iod_proc_nr = mp->DL_PROC;
0108438                   dep->de_read_iovec.iod_iovec_addr = 0;
0108439                   size= count;
0108440          }
0108441          if (size < ETH_MAX_PACK_SIZE)
0108442                   panic("dp8390: wrong packet size", size);
0108443          dep->de_flags |= DEF_READING;
0108444 
0108445          dp_recv(dep);
0108446 
0108447          if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
0108448                   (DEF_READING|DEF_STOPPED))
0108449          {
0108450                   /* The chip is stopped, and all arrived packets are
0108451                    * delivered.
0108452                    */
0108453                   dp_reset(dep);
0108454          }
0108455          reply(dep, OK, FALSE);
0108456 }
0108457 
0108458 
0108459 /*===========================================================================*
0108460  *                            do_init                                    *
0108461  *===========================================================================*/
0108462 static void do_init(mp)
0108463 message *mp;
0108464 {
0108465          int port;
0108466          dpeth_t *dep;
0108467          message reply_mess;
0108468 
0108469          port = mp->DL_PORT;
0108470          if (port < 0 || port >= DE_PORT_NR)
0108471          {
0108472                   reply_mess.m_type= DL_INIT_REPLY;
0108473                   reply_mess.m3_i1= ENXIO;
0108474                   mess_reply(mp, &reply_mess);
0108475                   return;
0108476          }
0108477          dep= &de_table[port];
0108478          strcpy(dep->de_name, "dp8390#0");
0108479          dep->de_name[7] += port;
0108480          if (dep->de_mode == DEM_DISABLED)
0108481          {
0108482                   /* This is the default, try to (re)locate the device. */
0108483                   conf_hw(dep);
0108484                   if (dep->de_mode == DEM_DISABLED)
0108485                   {
0108486                            /* Probe failed, or the device is configured off. */
0108487                            reply_mess.m_type= DL_INIT_REPLY;
0108488                            reply_mess.m3_i1= ENXIO;
0108489                            mess_reply(mp, &reply_mess);
0108490                            return;
0108491                   }
0108492                   if (dep->de_mode == DEM_ENABLED)
0108493                            dp_init(dep);
0108494          }
0108495 
0108496          if (dep->de_mode == DEM_SINK)
0108497          {
0108498                   strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
0108499                   dep->de_address.ea_addr[5] = port;
0108500                   dp_confaddr(dep);
0108501                   reply_mess.m_type = DL_INIT_REPLY;
0108502                   reply_mess.m3_i1 = mp->DL_PORT;
0108503                   reply_mess.m3_i2 = DE_PORT_NR;
0108504                   *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
0108505                   mess_reply(mp, &reply_mess);
0108506                   return;
0108507          }
0108508          assert(dep->de_mode == DEM_ENABLED);
0108509          assert(dep->de_flags & DEF_ENABLED);
0108510 
0108511          dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
0108512 
0108513          if (mp->DL_MODE & DL_PROMISC_REQ)
0108514                   dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
0108515          if (mp->DL_MODE & DL_MULTI_REQ)
0108516                   dep->de_flags |= DEF_MULTI;
0108517          if (mp->DL_MODE & DL_BROAD_REQ)
0108518                   dep->de_flags |= DEF_BROAD;
0108519 
0108520          dep->de_client = mp->m_source;
0108521          dp_reinit(dep);
0108522 
0108523          reply_mess.m_type = DL_INIT_REPLY;
0108524          reply_mess.m3_i1 = mp->DL_PORT;
0108525          reply_mess.m3_i2 = DE_PORT_NR;
0108526          *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
0108527 
0108528          mess_reply(mp, &reply_mess);
0108529 }
0108530 
0108531 /*===========================================================================*
0108532  *                            do_int                                    *
0108533  *===========================================================================*/
0108534 static void do_int(dep)
0108535 dpeth_t *dep;
0108536 {
0108537          if (dep->de_flags & (DEF_PACK_SEND | DEF_PACK_RECV))
0108538                   reply(dep, OK, TRUE);
0108539 }
0108540 
0108541 
0108542 /*===========================================================================*
0108543  *                            do_getstat                             *
0108544  *===========================================================================*/
0108545 static void do_getstat(mp)
0108546 message *mp;
0108547 {
0108548          int port;
0108549          dpeth_t *dep;
0108550 
0108551          port = mp->DL_PORT;
0108552          if (port < 0 || port >= DE_PORT_NR)
0108553                   panic("dp8390: illegal port", port);
0108554          dep= &de_table[port];
0108555          dep->de_client= mp->DL_PROC;
0108556          if (dep->de_mode == DEM_SINK)
0108557          {
0108558                   put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108559                            (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
0108560                   reply(dep, OK, FALSE);
0108561                   return;
0108562          }
0108563          assert(dep->de_mode == DEM_ENABLED);
0108564          assert(dep->de_flags & DEF_ENABLED);
0108565 
0108566          dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
0108567          dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
0108568          dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
0108569 
0108570          put_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
0108571                   (vir_bytes) sizeof(dep->de_stat), &dep->de_stat);
0108572          reply(dep, OK, FALSE);
0108573 }
0108574 
0108575 
0108576 /*===========================================================================*
0108577  *                            do_stop                                    *
0108578  *===========================================================================*/
0108579 static void do_stop(mp)
0108580 message *mp;
0108581 {
0108582          int port;
0108583          dpeth_t *dep;
0108584 
0108585          port = mp->DL_PORT;
0108586 
0108587          if (port < 0 || port >= DE_PORT_NR)
0108588                   panic("dp8390: illegal port", port);
0108589          dep= &de_table[port];
0108590          if (dep->de_mode == DEM_SINK)
0108591                   return;
0108592          assert(dep->de_mode == DEM_ENABLED);
0108593 
0108594          if (!(dep->de_flags & DEF_ENABLED))
0108595                   return;
0108596 
0108597          outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
0108598          (dep->de_stopf)(dep);
0108599 
0108600          dep->de_flags= DEF_EMPTY;
0108601 }
0108602 
0108603 
0108604 /*===========================================================================*
0108605  *                            dp_init                                    *
0108606  *===========================================================================*/
0108607 static void dp_init(dep)
0108608 dpeth_t *dep;
0108609 {
0108610          int dp_rcr_reg;
0108611          int i;
0108612 
0108613          /* General initialization */
0108614          dep->de_flags = DEF_EMPTY;
0108615          (*dep->de_initf)(dep);
0108616 
0108617          dp_confaddr(dep);
0108618 
0108619          if (debug)
0108620          {
0108621                   printf("%s: Ethernet address ", dep->de_name);
0108622                   for (i= 0; i < 6; i++)
0108623                            printf("%x%c", dep->de_address.ea_addr[i],
0108624                                                        i < 5 ? ':' : '\n');
0108625          }
0108626 
0108627          /* Initialization of the dp8390 */
0108628          outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
0108629          outb_reg0(dep, DP_IMR, 0);
0108630          outb_reg0(dep, DP_PSTART, dep->de_startpage);
0108631          outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
0108632          outb_reg0(dep, DP_BNRY, dep->de_startpage);
0108633          outb_reg0(dep, DP_RCR, RCR_MON);
0108634          outb_reg0(dep, DP_TCR, TCR_NORMAL);
0108635          if (dep->de_16bit)
0108636                   outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
0108637          else
0108638                   outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
0108639          outb_reg0(dep, DP_RBCR0, 0);
0108640          outb_reg0(dep, DP_RBCR1, 0);
0108641          outb_reg0(dep, DP_ISR, 0xFF);
0108642          outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT);
0108643 
0108644          outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
0108645          outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
0108646          outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
0108647          outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
0108648          outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
0108649          outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
0108650 
0108651          outb_reg1(dep, DP_MAR0, 0xff);
0108652          outb_reg1(dep, DP_MAR1, 0xff);
0108653          outb_reg1(dep, DP_MAR2, 0xff);
0108654          outb_reg1(dep, DP_MAR3, 0xff);
0108655          outb_reg1(dep, DP_MAR4, 0xff);
0108656          outb_reg1(dep, DP_MAR5, 0xff);
0108657          outb_reg1(dep, DP_MAR6, 0xff);
0108658          outb_reg1(dep, DP_MAR7, 0xff);
0108659 
0108660          outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
0108661          outb_reg1(dep, DP_CR, CR_PS_P0 | CR_DM_ABORT);
0108662 
0108663          dp_rcr_reg = 0;
0108664          if (dep->de_flags & DEF_PROMISC)
0108665                   dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
0108666          if (dep->de_flags & DEF_BROAD)
0108667                   dp_rcr_reg |= RCR_AB;
0108668          if (dep->de_flags & DEF_MULTI)
0108669                   dp_rcr_reg |= RCR_AM;
0108670          outb_reg0(dep, DP_RCR, dp_rcr_reg);
0108671          inb_reg0(dep, DP_CNTR0);              /* reset counters by reading */
0108672          inb_reg0(dep, DP_CNTR1);
0108673          inb_reg0(dep, DP_CNTR2);
0108674 
0108675          outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
0108676                   IMR_OVWE | IMR_CNTE);
0108677          outb_reg0(dep, DP_CR, CR_STA | CR_DM_ABORT);
0108678 
0108679          /* Finish the initialization. */
0108680          dep->de_flags |= DEF_ENABLED;
0108681          for (i= 0; i<dep->de_sendq_nr; i++)
0108682                   dep->de_sendq[i].sq_filled= 0;
0108683          dep->de_sendq_head= 0;
0108684          dep->de_sendq_tail= 0;
0108685          if (!dep->de_prog_IO)
0108686          {
0108687                   dep->de_user2nicf= dp_user2nic;
0108688                   dep->de_nic2userf= dp_nic2user;
0108689                   dep->de_getblockf= dp_getblock;
0108690          }
0108691          else if (dep->de_16bit)
0108692          {
0108693                   dep->de_user2nicf= dp_pio16_user2nic;
0108694                   dep->de_nic2userf= dp_pio16_nic2user;
0108695                   dep->de_getblockf= dp_pio16_getblock;
0108696          }
0108697          else
0108698          {
0108699                   dep->de_user2nicf= dp_pio8_user2nic;
0108700                   dep->de_nic2userf= dp_pio8_nic2user;
0108701                   dep->de_getblockf= dp_pio8_getblock;
0108702          }
0108703 
0108704          /* set the interrupt handler */
0108705          put_irq_handler(dep->de_irq, dp_handler);
0108706          enable_irq(dep->de_irq);
0108707 }
0108708 
0108709 
0108710 /*===========================================================================*
0108711  *                            dp_confaddr                             *
0108712  *===========================================================================*/
0108713 static void dp_confaddr(dep)
0108714 dpeth_t *dep;
0108715 {
0108716          int i;
0108717          char eakey[16];
0108718          static char eafmt[]= "x:x:x:x:x:x";
0108719          long v;
0108720 
0108721          /* User defined ethernet address? */
0108722          strcpy(eakey, dp_conf[dep-de_table].dpc_envvar);
0108723          strcat(eakey, "_EA");
0108724 
0108725          for (i= 0; i < 6; i++)
0108726          {
0108727                   v= dep->de_address.ea_addr[i];
0108728                   if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
0108729                            break;
0108730                   dep->de_address.ea_addr[i]= v;
0108731          }
0108732 
0108733          if (i != 0 && i != 6)
0108734          {
0108735                   /* It's all or nothing; force a panic. */
0108736                   (void) env_parse(eakey, "?", 0, &v, 0L, 0L);
0108737          }
0108738 }
0108739 
0108740 
0108741 /*===========================================================================*
0108742  *                            dp_reinit                             *
0108743  *===========================================================================*/
0108744 static void dp_reinit(dep)
0108745 dpeth_t *dep;
0108746 {
0108747          int dp_rcr_reg;
0108748 
0108749          outb_reg0(dep, DP_CR, CR_PS_P0);
0108750 
0108751          dp_rcr_reg = 0;
0108752          if (dep->de_flags & DEF_PROMISC)
0108753                   dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
0108754          if (dep->de_flags & DEF_BROAD)
0108755                   dp_rcr_reg |= RCR_AB;
0108756          if (dep->de_flags & DEF_MULTI)
0108757                   dp_rcr_reg |= RCR_AM;
0108758          outb_reg0(dep, DP_RCR, dp_rcr_reg);
0108759 }
0108760 
0108761 
0108762 /*===========================================================================*
0108763  *                            dp_reset                             *
0108764  *===========================================================================*/
0108765 static void dp_reset(dep)
0108766 dpeth_t *dep;
0108767 {
0108768          int i;
0108769 
0108770          /* Stop chip */
0108771          outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
0108772          outb_reg0(dep, DP_RBCR0, 0);
0108773          outb_reg0(dep, DP_RBCR1, 0);
0108774          for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
0108775                   ; /* Do nothing */
0108776          outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
0108777          outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
0108778          outb_reg0(dep, DP_TCR, TCR_NORMAL|TCR_OFST);
0108779 
0108780          /* Acknowledge the ISR_RDC (remote dma) interrupt. */
0108781          for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
0108782                   ; /* Do nothing */
0108783          outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
0108784 
0108785          /* Reset the transmit ring. If we were transmitting a packet, we
0108786           * pretend that the packet is processed. Higher layers will
0108787           * retransmit if the packet wasn't actually sent.
0108788           */
0108789          dep->de_sendq_head= dep->de_sendq_tail= 0;
0108790          for (i= 0; i<dep->de_sendq_nr; i++)
0108791                   dep->de_sendq[i].sq_filled= 0;
0108792          dp_send(dep);
0108793          dep->de_flags &= ~DEF_STOPPED;
0108794 }
0108795 
0108796 
0108797 /*===========================================================================*
0108798  *                            dp_check_ints                             *
0108799  *===========================================================================*/
0108800 static void dp_check_ints(dep)
0108801 dpeth_t *dep;
0108802 {
0108803          int isr, tsr;
0108804          int size, sendq_tail;
0108805 
0108806          if (!(dep->de_flags & DEF_ENABLED))
0108807                   panic("dp8390: got premature interrupt", NO_NUM);
0108808 
0108809          for(;;)
0108810          {
0108811                   isr = inb_reg0(dep, DP_ISR);
0108812                   if (!isr)
0108813                            break;
0108814                   outb_reg0(dep, DP_ISR, isr);
0108815                   if (isr & (ISR_PTX|ISR_TXE))
0108816                   {
0108817                            if (isr & ISR_TXE)
0108818                            {
0108819 #if DEBUG
0108820  { printf("%s: got send Error\n", dep->de_name); }
0108821 #endif
0108822                                     dep->de_stat.ets_sendErr++;
0108823                            }
0108824                            else
0108825                            {
0108826                                     tsr = inb_reg0(dep, DP_TSR);
0108827 
0108828                                     if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
0108829                                     if (!(tsr & TSR_DFR))
0108830                                     {
0108831                                              /* In most (all?) implementations of
0108832                                               * the dp8390, this bit is set
0108833                                               * when the packet is not deferred
0108834                                               */
0108835                                              dep->de_stat.ets_transDef++;
0108836                                     }
0108837                                     if (tsr & TSR_COL) dep->de_stat.ets_collision++;
0108838                                     if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
0108839                                     if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
0108840                                     if (tsr & TSR_FU
0108841                                              && ++dep->de_stat.ets_fifoUnder <= 10)
0108842                                     {
0108843                                              printf("%s: fifo underrun\n",
0108844                                                     dep->de_name);
0108845                                     }
0108846                                     if (tsr & TSR_CDH
0108847                                              && ++dep->de_stat.ets_CDheartbeat <= 10)
0108848                                     {
0108849                                              printf("%s: CD heart beat failure\n",
0108850                                                     dep->de_name);
0108851                                     }
0108852                                     if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
0108853                            }
0108854                            sendq_tail= dep->de_sendq_tail;
0108855 
0108856                            if (!(dep->de_sendq[sendq_tail].sq_filled))
0108857                            {
0108858                                     /* Software bug? */
0108859                                     assert(!debug);
0108860 
0108861                                     /* Or hardware bug? */
0108862                                     printf(
0108863                                     "%s: transmit interrupt, but not sending\n",
0108864                                              dep->de_name);
0108865                                     continue;
0108866                            }
0108867                            dep->de_sendq[sendq_tail].sq_filled= 0;
0108868                            if (++sendq_tail == dep->de_sendq_nr)
0108869                                     sendq_tail= 0;
0108870                            dep->de_sendq_tail= sendq_tail;
0108871                            if (dep->de_sendq[sendq_tail].sq_filled)
0108872                            {
0108873                                     size= dep->de_sendq[sendq_tail].sq_size;
0108874                                     outb_reg0(dep, DP_TPSR,
0108875                                              dep->de_sendq[sendq_tail].sq_sendpage);
0108876                                     outb_reg0(dep, DP_TBCR1, size >> 8);
0108877                                     outb_reg0(dep, DP_TBCR0, size & 0xff);
0108878                                     outb_reg0(dep, DP_CR, CR_TXP);       /* there is goes.. */
0108879                            }
0108880                            if (dep->de_flags & DEF_SEND_AVAIL)
0108881                                     dp_send(dep);
0108882                   }
0108883 
0108884                   if (isr & ISR_PRX)
0108885                   {
0108886                            /* Only call dp_recv if there is a read request */
0108887                            if (dep->de_flags & DEF_READING)
0108888                                     dp_recv(dep);
0108889                   }
0108890                   
0108891                   if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
0108892                   if (isr & ISR_CNT)
0108893                   {
0108894                            dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
0108895                            dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
0108896                            dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
0108897                   }
0108898                   if (isr & ISR_OVW)
0108899                   {
0108900                            dep->de_stat.ets_OVW++;
0108901 #if DEBUG
0108902  { printW(); printf("%s: got overwrite warning\n", dep->de_name); }
0108903 #endif
0108904                            if (dep->de_flags & DEF_READING)
0108905                            {
0108906                                     printf(
0108907 "dp_check_ints: strange: overwrite warning and pending read request\n");
0108908                                     dp_recv(dep);
0108909                            }
0108910                   }
0108911                   if (isr & ISR_RDC)
0108912                   {
0108913                            /* Nothing to do */
0108914                   }
0108915                   if (isr & ISR_RST)
0108916                   {
0108917                            /* this means we got an interrupt but the ethernet
0108918                             * chip is shutdown. We set the flag DEF_STOPPED,
0108919                             * and continue processing arrived packets. When the
0108920                             * receive buffer is empty, we reset the dp8390.
0108921                             */
0108922 #if DEBUG
0108923  { printW(); printf("%s: NIC stopped\n", dep->de_name); }
0108924 #endif
0108925                            dep->de_flags |= DEF_STOPPED;
0108926                            break;
0108927                   }
0108928          }
0108929          if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
0108930                                             (DEF_READING|DEF_STOPPED))
0108931          {
0108932                   /* The chip is stopped, and all arrived packets are
0108933                    * delivered.
0108934                    */
0108935                   dp_reset(dep);
0108936          }
0108937 }
0108938 
0108939 
0108940 /*===========================================================================*
0108941  *                            dp_recv                                    *
0108942  *===========================================================================*/
0108943 static void dp_recv(dep)
0108944 dpeth_t *dep;
0108945 {
0108946          dp_rcvhdr_t header;
0108947          unsigned pageno, curr, next;
0108948          vir_bytes length;
0108949          int packet_processed, r;
0108950          u16_t eth_type;
0108951 
0108952          packet_processed = FALSE;
0108953          pageno = inb_reg0(dep, DP_BNRY) + 1;
0108954          if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
0108955 
0108956          do
0108957          {
0108958                   outb_reg0(dep, DP_CR, CR_PS_P1);
0108959                   curr = inb_reg1(dep, DP_CURR);
0108960                   outb_reg0(dep, DP_CR, CR_PS_P0);
0108961 
0108962                   if (curr == pageno) break;
0108963 
0108964                   (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
0108965                            &header);
0108966                   (dep->de_getblockf)(dep, pageno, sizeof(header) +
0108967                            2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
0108968 
0108969                   length = (header.dr_rbcl | (header.dr_rbch << 8)) -
0108970                            sizeof(dp_rcvhdr_t);
0108971                   next = header.dr_next;
0108972                   if (length < ETH_MIN_PACK_SIZE || length > ETH_MAX_PACK_SIZE)
0108973                   {
0108974                            printf("%s: packet with strange length arrived: %d\n",
0108975                                     dep->de_name, (int) length);
0108976                            next= curr;
0108977                   }
0108978                   else if (next < dep->de_startpage || next >= dep->de_stoppage)
0108979                   {
0108980                            printf("%s: strange next page\n", dep->de_name);
0108981                            next= curr;
0108982                   }
0108983                   else if (eth_type == eth_ign_proto)
0108984                   {
0108985                            /* Hack: ignore packets of a given protocol, useful
0108986                             * if you share a net with 80 computers sending
0108987                             * Amoeba FLIP broadcasts. (Protocol 0x8146.)
0108988                             */
0108989                            static int first= 1;
0108990                            if (first)
0108991                            {
0108992                                     first= 0;
0108993                                     printf("%s: dropping proto 0x%04x packets\n",
0108994                                              dep->de_name,
0108995                                              ntohs(eth_ign_proto));
0108996                            }
0108997                            dep->de_stat.ets_packetR++;
0108998                   }
0108999                   else if (header.dr_status & RSR_FO)
0109000                   {
0109001                            /* This is very serious, so we issue a warning and
0109002                             * reset the buffers */
0109003                            printf("%s: fifo overrun, resetting receive buffer\n",
0109004                                     dep->de_name);
0109005                            dep->de_stat.ets_fifoOver++;
0109006                            next = curr;
0109007                   }
0109008                   else if ((header.dr_status & RSR_PRX) &&
0109009                                               (dep->de_flags & DEF_ENABLED))
0109010                   {
0109011                            r = dp_pkt2user(dep, pageno, length);
0109012                            if (r != OK)
0109013                                     return;
0109014 
0109015                            packet_processed = TRUE;
0109016                            dep->de_stat.ets_packetR++;
0109017                   }
0109018                   if (next == dep->de_startpage)
0109019                            outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
0109020                   else
0109021                            outb_reg0(dep, DP_BNRY, next - 1);
0109022 
0109023                   pageno = next;
0109024          }
0109025          while (!packet_processed);
0109026 }
0109027 
0109028 
0109029 /*===========================================================================*
0109030  *                            dp_send                                    *
0109031  *===========================================================================*/
0109032 static void dp_send(dep)
0109033 dpeth_t *dep;
0109034 {
0109035          if (!(dep->de_flags & DEF_SEND_AVAIL))
0109036                   return;
0109037 
0109038          dep->de_flags &= ~DEF_SEND_AVAIL;
0109039          switch(dep->de_sendmsg.m_type)
0109040          {
0109041          case DL_WRITE:       do_vwrite(&dep->de_sendmsg, TRUE, FALSE);       break;
0109042          case DL_WRITEV:       do_vwrite(&dep->de_sendmsg, TRUE, TRUE);       break;
0109043          default:
0109044                   panic("dp8390: wrong type:", dep->de_sendmsg.m_type);
0109045                   break;
0109046          }
0109047 }
0109048 
0109049 
0109050 /*===========================================================================*
0109051  *                            dp_getblock                             *
0109052  *===========================================================================*/
0109053 static void dp_getblock(dep, page, offset, size, dst)
0109054 dpeth_t *dep;
0109055 int page;
0109056 size_t offset;
0109057 size_t size;
0109058 void *dst;
0109059 {
0109060          u16_t *ha;
0109061          int i;
0109062 
0109063          ha = (u16_t *) dst;
0109064          offset = page * DP_PAGESIZE + offset;
0109065          assert(!(size & 1));
0109066          for (i= 0; i<size; i+=2)
0109067          {
0109068                   *ha = mem_rdw(dep->de_memseg, dep->de_memoff + (offset+i));
0109069                   ha++;
0109070          }
0109071 }
0109072 
0109073 
0109074 /*===========================================================================*
0109075  *                            dp_pio8_getblock                      *
0109076  *===========================================================================*/
0109077 static void dp_pio8_getblock(dep, page, offset, size, dst)
0109078 dpeth_t *dep;
0109079 int page;
0109080 size_t offset;
0109081 size_t size;
0109082 void *dst;
0109083 {
0109084          u8_t *ha;
0109085          int i;
0109086 
0109087          ha = (u8_t *) dst;
0109088          offset = page * DP_PAGESIZE + offset;
0109089          outb_reg0(dep, DP_RBCR0, size & 0xFF);
0109090          outb_reg0(dep, DP_RBCR1, size >> 8);
0109091          outb_reg0(dep, DP_RSAR0, offset & 0xFF);
0109092          outb_reg0(dep, DP_RSAR1, offset >> 8);
0109093          outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109094 
0109095          for (i= 0; i<size; i++)
0109096                   ha[i]= in_byte(dep->de_data_port);
0109097 }
0109098 
0109099 
0109100 /*===========================================================================*
0109101  *                            dp_pio16_getblock                      *
0109102  *===========================================================================*/
0109103 static void dp_pio16_getblock(dep, page, offset, size, dst)
0109104 dpeth_t *dep;
0109105 int page;
0109106 size_t offset;
0109107 size_t size;
0109108 void *dst;
0109109 {
0109110          u16_t *ha;
0109111          int i;
0109112 
0109113          ha = (u16_t *) dst;
0109114          offset = page * DP_PAGESIZE + offset;
0109115          outb_reg0(dep, DP_RBCR0, size & 0xFF);
0109116          outb_reg0(dep, DP_RBCR1, size >> 8);
0109117          outb_reg0(dep, DP_RSAR0, offset & 0xFF);
0109118          outb_reg0(dep, DP_RSAR1, offset >> 8);
0109119          outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109120 
0109121          assert (!(size & 1));
0109122          size /= 2;
0109123          for (i= 0; i<size; i++)
0109124                   ha[i]= in_word(dep->de_data_port);
0109125 }
0109126 
0109127 
0109128 /*===========================================================================*
0109129  *                            dp_pkt2user                             *
0109130  *===========================================================================*/
0109131 static int dp_pkt2user(dep, page, length)
0109132 dpeth_t *dep;
0109133 int page, length;
0109134 {
0109135          int last, count;
0109136 
0109137          if (!(dep->de_flags & DEF_READING))
0109138                   return EGENERIC;
0109139 
0109140          last = page + (length - 1) / DP_PAGESIZE;
0109141          if (last >= dep->de_stoppage)
0109142          {
0109143                   count = (dep->de_stoppage - page) * DP_PAGESIZE -
0109144                            sizeof(dp_rcvhdr_t);
0109145 
0109146                   /* Save read_iovec since we need it twice. */
0109147                   dep->de_tmp_iovec = dep->de_read_iovec;
0109148                   (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
0109149                            sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
0109150                   (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
0109151                                     &dep->de_read_iovec, count, length - count);
0109152          }
0109153          else
0109154          {
0109155                   (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
0109156                            sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
0109157          }
0109158 
0109159          dep->de_read_s = length;
0109160          dep->de_flags |= DEF_PACK_RECV;
0109161          dep->de_flags &= ~DEF_READING;
0109162 
0109163          return OK;
0109164 }
0109165 
0109166 
0109167 /*===========================================================================*
0109168  *                            dp_user2nic                             *
0109169  *===========================================================================*/
0109170 static void dp_user2nic(dep, iovp, offset, nic_addr, count)
0109171 dpeth_t *dep;
0109172 iovec_dat_t *iovp;
0109173 vir_bytes offset;
0109174 int nic_addr;
0109175 vir_bytes count;
0109176 {
0109177          phys_bytes phys_hw, phys_user;
0109178          int bytes, i;
0109179 
0109180          phys_hw = dep->de_linmem + nic_addr;
0109181 
0109182          i= 0;
0109183          while (count > 0)
0109184          {
0109185                   if (i >= IOVEC_NR)
0109186                   {
0109187                            dp_next_iovec(iovp);
0109188                            i= 0;
0109189                            continue;
0109190                   }
0109191                   assert(i < iovp->iod_iovec_s);
0109192                   if (offset >= iovp->iod_iovec[i].iov_size)
0109193                   {
0109194                            offset -= iovp->iod_iovec[i].iov_size;
0109195                            i++;
0109196                            continue;
0109197                   }
0109198                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109199                   if (bytes > count)
0109200                            bytes = count;
0109201 
0109202                   phys_user = numap(iovp->iod_proc_nr,
0109203                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109204                   if (!phys_user)
0109205                            panic("dp8390: umap failed\n", NO_NUM);
0109206                   phys_copy(phys_user, phys_hw, (phys_bytes) bytes);
0109207                   count -= bytes;
0109208                   phys_hw += bytes;
0109209                   offset += bytes;
0109210          }
0109211          assert(count == 0);
0109212 }
0109213 
0109214 
0109215 /*===========================================================================*
0109216  *                            dp_pio8_user2nic                      *
0109217  *===========================================================================*/
0109218 static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
0109219 dpeth_t *dep;
0109220 iovec_dat_t *iovp;
0109221 vir_bytes offset;
0109222 int nic_addr;
0109223 vir_bytes count;
0109224 {
0109225          phys_bytes phys_user;
0109226          int bytes, i;
0109227 
0109228          outb_reg0(dep, DP_ISR, ISR_RDC);
0109229 
0109230          outb_reg0(dep, DP_RBCR0, count & 0xFF);
0109231          outb_reg0(dep, DP_RBCR1, count >> 8);
0109232          outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109233          outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109234          outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
0109235 
0109236          i= 0;
0109237          while (count > 0)
0109238          {
0109239                   if (i >= IOVEC_NR)
0109240                   {
0109241                            dp_next_iovec(iovp);
0109242                            i= 0;
0109243                            continue;
0109244                   }
0109245                   assert(i < iovp->iod_iovec_s);
0109246                   if (offset >= iovp->iod_iovec[i].iov_size)
0109247                   {
0109248                            offset -= iovp->iod_iovec[i].iov_size;
0109249                            i++;
0109250                            continue;
0109251                   }
0109252                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109253                   if (bytes > count)
0109254                            bytes = count;
0109255 
0109256                   phys_user = numap(iovp->iod_proc_nr,
0109257                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109258                   if (!phys_user)
0109259                            panic("dp8390: umap failed\n", NO_NUM);
0109260                   port_write_byte(dep->de_data_port, phys_user, bytes);
0109261                   count -= bytes;
0109262                   offset += bytes;
0109263          }
0109264          assert(count == 0);
0109265 
0109266          for (i= 0; i<100; i++)
0109267          {
0109268                   if (inb_reg0(dep, DP_ISR) & ISR_RDC)
0109269                            break;
0109270          }
0109271          if (i == 100)
0109272          {
0109273                   panic("dp8390: remote dma failed to complete", NO_NUM);
0109274          }
0109275 }
0109276 
0109277 
0109278 /*===========================================================================*
0109279  *                            dp_pio16_user2nic                      *
0109280  *===========================================================================*/
0109281 static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
0109282 dpeth_t *dep;
0109283 iovec_dat_t *iovp;
0109284 vir_bytes offset;
0109285 int nic_addr;
0109286 vir_bytes count;
0109287 {
0109288          phys_bytes phys_user;
0109289          vir_bytes ecount;
0109290          int bytes, i;
0109291          u8_t two_bytes[2];
0109292          phys_bytes phys_2bytes;
0109293          int odd_byte;
0109294 
0109295          ecount= (count+1) & ~1;
0109296          phys_2bytes = vir2phys(two_bytes);
0109297          odd_byte= 0;
0109298 
0109299          outb_reg0(dep, DP_ISR, ISR_RDC);
0109300          outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
0109301          outb_reg0(dep, DP_RBCR1, ecount >> 8);
0109302          outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109303          outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109304          outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
0109305 
0109306          i= 0;
0109307          while (count > 0)
0109308          {
0109309                   if (i >= IOVEC_NR)
0109310                   {
0109311                            dp_next_iovec(iovp);
0109312                            i= 0;
0109313                            continue;
0109314                   }
0109315                   assert(i < iovp->iod_iovec_s);
0109316                   if (offset >= iovp->iod_iovec[i].iov_size)
0109317                   {
0109318                            offset -= iovp->iod_iovec[i].iov_size;
0109319                            i++;
0109320                            continue;
0109321                   }
0109322                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109323                   if (bytes > count)
0109324                            bytes = count;
0109325 
0109326                   phys_user = numap(iovp->iod_proc_nr,
0109327                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109328                   if (!phys_user)
0109329                            panic("dp8390: umap failed\n", NO_NUM);
0109330                   if (odd_byte)
0109331                   {
0109332                            phys_copy(phys_user, phys_2bytes+1,
0109333                                     (phys_bytes) 1);
0109334                            out_word(dep->de_data_port, *(u16_t *)two_bytes);
0109335                            count--;
0109336                            offset++;
0109337                            bytes--;
0109338                            phys_user++;
0109339                            odd_byte= 0;
0109340                            if (!bytes)
0109341                                     continue;
0109342                   }
0109343                   ecount= bytes & ~1;
0109344                   if (ecount != 0)
0109345                   {
0109346                            port_write(dep->de_data_port, phys_user, ecount);
0109347                            count -= ecount;
0109348                            offset += ecount;
0109349                            bytes -= ecount;
0109350                            phys_user += ecount;
0109351                   }
0109352                   if (bytes)
0109353                   {
0109354                            assert(bytes == 1);
0109355                            phys_copy(phys_user, phys_2bytes, (phys_bytes) 1);
0109356                            count--;
0109357                            offset++;
0109358                            bytes--;
0109359                            phys_user++;
0109360                            odd_byte= 1;
0109361                   }
0109362          }
0109363          assert(count == 0);
0109364 
0109365          if (odd_byte)
0109366                   out_word(dep->de_data_port, *(u16_t *)two_bytes);
0109367 
0109368          for (i= 0; i<100; i++)
0109369          {
0109370                   if (inb_reg0(dep, DP_ISR) & ISR_RDC)
0109371                            break;
0109372          }
0109373          if (i == 100)
0109374          {
0109375                   panic("dp8390: remote dma failed to complete", NO_NUM);
0109376          }
0109377 }
0109378 
0109379 
0109380 /*===========================================================================*
0109381  *                            dp_nic2user                             *
0109382  *===========================================================================*/
0109383 static void dp_nic2user(dep, nic_addr, iovp, offset, count)
0109384 dpeth_t *dep;
0109385 int nic_addr;
0109386 iovec_dat_t *iovp;
0109387 vir_bytes offset;
0109388 vir_bytes count;
0109389 {
0109390          phys_bytes phys_hw, phys_user;
0109391          int bytes, i;
0109392 
0109393          phys_hw = dep->de_linmem + nic_addr;
0109394 
0109395          i= 0;
0109396          while (count > 0)
0109397          {
0109398                   if (i >= IOVEC_NR)
0109399                   {
0109400                            dp_next_iovec(iovp);
0109401                            i= 0;
0109402                            continue;
0109403                   }
0109404                   assert(i < iovp->iod_iovec_s);
0109405                   if (offset >= iovp->iod_iovec[i].iov_size)
0109406                   {
0109407                            offset -= iovp->iod_iovec[i].iov_size;
0109408                            i++;
0109409                            continue;
0109410                   }
0109411                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109412                   if (bytes > count)
0109413                            bytes = count;
0109414 
0109415                   phys_user = numap(iovp->iod_proc_nr,
0109416                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109417                   if (!phys_user)
0109418                            panic("dp8390: umap failed\n", NO_NUM);
0109419                   phys_copy(phys_hw, phys_user, (phys_bytes) bytes);
0109420                   count -= bytes;
0109421                   phys_hw += bytes;
0109422                   offset += bytes;
0109423          }
0109424          assert(count == 0);
0109425 }
0109426 
0109427 
0109428 /*===========================================================================*
0109429  *                            dp_pio8_nic2user                      *
0109430  *===========================================================================*/
0109431 static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
0109432 dpeth_t *dep;
0109433 int nic_addr;
0109434 iovec_dat_t *iovp;
0109435 vir_bytes offset;
0109436 vir_bytes count;
0109437 {
0109438          phys_bytes phys_user;
0109439          int bytes, i;
0109440 
0109441          outb_reg0(dep, DP_RBCR0, count & 0xFF);
0109442          outb_reg0(dep, DP_RBCR1, count >> 8);
0109443          outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109444          outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109445          outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109446 
0109447          i= 0;
0109448          while (count > 0)
0109449          {
0109450                   if (i >= IOVEC_NR)
0109451                   {
0109452                            dp_next_iovec(iovp);
0109453                            i= 0;
0109454                            continue;
0109455                   }
0109456                   assert(i < iovp->iod_iovec_s);
0109457                   if (offset >= iovp->iod_iovec[i].iov_size)
0109458                   {
0109459                            offset -= iovp->iod_iovec[i].iov_size;
0109460                            i++;
0109461                            continue;
0109462                   }
0109463                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109464                   if (bytes > count)
0109465                            bytes = count;
0109466 
0109467                   phys_user = numap(iovp->iod_proc_nr,
0109468                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109469                   if (!phys_user)
0109470                            panic("dp8390: umap failed\n", NO_NUM);
0109471                   port_read_byte(dep->de_data_port, phys_user, bytes);
0109472                   count -= bytes;
0109473                   offset += bytes;
0109474          }
0109475          assert(count == 0);
0109476 }
0109477 
0109478 
0109479 /*===========================================================================*
0109480  *                            dp_pio16_nic2user                      *
0109481  *===========================================================================*/
0109482 static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
0109483 dpeth_t *dep;
0109484 int nic_addr;
0109485 iovec_dat_t *iovp;
0109486 vir_bytes offset;
0109487 vir_bytes count;
0109488 {
0109489          phys_bytes phys_user;
0109490          vir_bytes ecount;
0109491          int bytes, i;
0109492          u8_t two_bytes[2];
0109493          phys_bytes phys_2bytes;
0109494          int odd_byte;
0109495 
0109496          ecount= (count+1) & ~1;
0109497          phys_2bytes = vir2phys(two_bytes);
0109498          odd_byte= 0;
0109499 
0109500          outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
0109501          outb_reg0(dep, DP_RBCR1, ecount >> 8);
0109502          outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
0109503          outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
0109504          outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
0109505 
0109506          i= 0;
0109507          while (count > 0)
0109508          {
0109509                   if (i >= IOVEC_NR)
0109510                   {
0109511                            dp_next_iovec(iovp);
0109512                            i= 0;
0109513                            continue;
0109514                   }
0109515                   assert(i < iovp->iod_iovec_s);
0109516                   if (offset >= iovp->iod_iovec[i].iov_size)
0109517                   {
0109518                            offset -= iovp->iod_iovec[i].iov_size;
0109519                            i++;
0109520                            continue;
0109521                   }
0109522                   bytes = iovp->iod_iovec[i].iov_size - offset;
0109523                   if (bytes > count)
0109524                            bytes = count;
0109525 
0109526                   phys_user = numap(iovp->iod_proc_nr,
0109527                            iovp->iod_iovec[i].iov_addr + offset, bytes);
0109528                   if (!phys_user)
0109529                            panic("dp8390: umap failed\n", NO_NUM);
0109530                   if (odd_byte)
0109531                   {
0109532                            phys_copy(phys_2bytes+1, phys_user, (phys_bytes) 1);
0109533                            count--;
0109534                            offset++;
0109535                            bytes--;
0109536                            phys_user++;
0109537                            odd_byte= 0;
0109538                            if (!bytes)
0109539                                     continue;
0109540                   }
0109541                   ecount= bytes & ~1;
0109542                   if (ecount != 0)
0109543                   {
0109544                            port_read(dep->de_data_port, phys_user, ecount);
0109545                            count -= ecount;
0109546                            offset += ecount;
0109547                            bytes -= ecount;
0109548                            phys_user += ecount;
0109549                   }
0109550                   if (bytes)
0109551                   {
0109552                            assert(bytes == 1);
0109553                            *(u16_t *)two_bytes= in_word(dep->de_data_port);
0109554                            phys_copy(phys_2bytes, phys_user, (phys_bytes) 1);
0109555                            count--;
0109556                            offset++;
0109557                            bytes--;
0109558                            phys_user++;
0109559                            odd_byte= 1;
0109560                   }
0109561          }
0109562          assert(count == 0);
0109563 }
0109564 
0109565 
0109566 /*===========================================================================*
0109567  *                            dp_next_iovec                                    *
0109568  *===========================================================================*/
0109569 static void dp_next_iovec(iovp)
0109570 iovec_dat_t *iovp;
0109571 {
0109572          assert(iovp->iod_iovec_s > IOVEC_NR);
0109573 
0109574          iovp->iod_iovec_s -= IOVEC_NR;
0109575 
0109576          iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
0109577 
0109578          get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
0109579                   (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
0109580                   sizeof(iovec_t), iovp->iod_iovec);
0109581 }
0109582 
0109583 
0109584 /*===========================================================================*
0109585  *                            dp_handler                             *
0109586  *===========================================================================*/
0109587 static int dp_handler(irq)
0109588 int irq;
0109589 {
0109590 /* DP8390 interrupt, send message and keep interrupts disabled. */
0109591 
0109592          assert(irq >= 0 && irq < NR_IRQ_VECTORS);
0109593          int_pending[irq]= 1;
0109594          interrupt(dpeth_tasknr);
0109595 
0109596          return 0;
0109597 }
0109598 
0109599 /*===========================================================================*
0109600  *                            conf_hw                                    *
0109601  *===========================================================================*/
0109602 static void conf_hw(dep)
0109603 dpeth_t *dep;
0109604 {
0109605          static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
0109606 
0109607          int ifnr;
0109608          dp_conf_t *dcp;
0109609 
0109610          dep->de_mode= DEM_DISABLED;       /* Superfluous */
0109611          ifnr= dep-de_table;
0109612 
0109613          dcp= &dp_conf[ifnr];
0109614          update_conf(dep, dcp);
0109615          if (dep->de_mode != DEM_ENABLED)
0109616                   return;
0109617          if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
0109618          {
0109619                   printf("%s: No ethernet card found at 0x%x\n",
0109620                            dep->de_name, dep->de_base_port);
0109621                   dep->de_mode= DEM_DISABLED;
0109622                   return;
0109623          }
0109624 
0109625          /* Find a memory segment, programmed I/O should set the
0109626           * memory segment (linmem) to zero.
0109627           */
0109628          if (dep->de_linmem != 0)
0109629          {
0109630                   phys2seg(&dep->de_memseg, &dep->de_memoff, dep->de_linmem);
0109631          }
0109632 
0109633 /* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
0109634 
0109635          dep->de_flags = DEF_EMPTY;
0109636          dep->de_stat = empty_stat;
0109637 }
0109638 
0109639 
0109640 /*===========================================================================*
0109641  *                            update_conf                             *
0109642  *===========================================================================*/
0109643 static void update_conf(dep, dcp)
0109644 dpeth_t *dep;
0109645 dp_conf_t *dcp;
0109646 {
0109647          long v;
0109648          static char dpc_fmt[] = "x:d:x:x";
0109649 
0109650          /* Get the default settings and modify them from the environment. */
0109651          dep->de_mode= DEM_SINK;
0109652          v= dcp->dpc_port;
0109653          switch (env_parse(dcp->dpc_envvar, dpc_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
0109654          case EP_OFF:
0109655                   dep->de_mode= DEM_DISABLED;
0109656                   break;
0109657          case EP_ON:
0109658          case EP_SET:
0109659                   dep->de_mode= DEM_ENABLED;       /* Might become disabled if
0109660                                                * all probes fail */
0109661                   break;
0109662          }
0109663          dep->de_base_port= v;
0109664 
0109665          v= dcp->dpc_irq | DEI_DEFAULT;
0109666          (void) env_parse(dcp->dpc_envvar, dpc_fmt, 1, &v, 0L,
0109667                                             (long) NR_IRQ_VECTORS - 1);
0109668          dep->de_irq= v;
0109669 
0109670          v= dcp->dpc_mem;
0109671          (void) env_parse(dcp->dpc_envvar, dpc_fmt, 2, &v, 0L, 0xFFFFFL);
0109672          dep->de_linmem= v;
0109673 
0109674          v= 0;
0109675          (void) env_parse(dcp->dpc_envvar, dpc_fmt, 3, &v, 0x2000L, 0x8000L);
0109676          dep->de_ramsize= v;
0109677 }
0109678 
0109679 
0109680 /*===========================================================================*
0109681  *                            calc_iovec_size                             *
0109682  *===========================================================================*/
0109683 static int calc_iovec_size(iovp)
0109684 iovec_dat_t *iovp;
0109685 {
0109686          /* Calculate the size of a request. Note that the iovec_dat
0109687           * structure will be unusable after calc_iovec_size.
0109688           */
0109689          int size;
0109690          int i;
0109691 
0109692          size= 0;
0109693          i= 0;
0109694          while (i < iovp->iod_iovec_s)
0109695          {
0109696                   if (i >= IOVEC_NR)
0109697                   {
0109698                            dp_next_iovec(iovp);
0109699                            i= 0;
0109700                            continue;
0109701                   }
0109702                   size += iovp->iod_iovec[i].iov_size;
0109703                   i++;
0109704          }
0109705          return size;
0109706 }
0109707 
0109708 
0109709 /*===========================================================================*
0109710  *                            reply                                    *
0109711  *===========================================================================*/
0109712 static void reply(dep, err, may_block)
0109713 dpeth_t *dep;
0109714 int err;
0109715 int may_block;
0109716 {
0109717          message reply;
0109718          int status;
0109719          int r;
0109720 
0109721          status = 0;
0109722          if (dep->de_flags & DEF_PACK_SEND)
0109723                   status |= DL_PACK_SEND;
0109724          if (dep->de_flags & DEF_PACK_RECV)
0109725                   status |= DL_PACK_RECV;
0109726 
0109727          reply.m_type = DL_TASK_REPLY;
0109728          reply.DL_PORT = dep - de_table;
0109729          reply.DL_PROC = dep->de_client;
0109730          reply.DL_STAT = status | ((u32_t) err << 16);
0109731          reply.DL_COUNT = dep->de_read_s;
0109732          reply.DL_CLCK = get_uptime();
0109733          r= send(dep->de_client, &reply);
0109734 
0109735          if (r == ELOCKED && may_block)
0109736          {
0109737 #if DEBUG
0109738                   printW(); printf("send locked\n");
0109739 #endif
0109740                   return;
0109741          }
0109742 
0109743          if (r < 0)
0109744                   panic("dp8390: send failed:", r);
0109745          
0109746          dep->de_read_s = 0;
0109747          dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
0109748 }
0109749 
0109750 
0109751 /*===========================================================================*
0109752  *                            mess_reply                             *
0109753  *===========================================================================*/
0109754 static void mess_reply(req, reply_mess)
0109755 message *req;
0109756 message *reply_mess;
0109757 {
0109758          if (send(req->m_source, reply_mess) != OK)
0109759                   panic("dp8390: unable to mess_reply", NO_NUM);
0109760 }
0109761 
0109762 
0109763 /*===========================================================================*
0109764  *                            get_userdata                             *
0109765  *===========================================================================*/
0109766 static void get_userdata(user_proc, user_addr, count, loc_addr)
0109767 int user_proc;
0109768 vir_bytes user_addr;
0109769 vir_bytes count;
0109770 void *loc_addr;
0109771 {
0109772          phys_bytes src;
0109773 
0109774          src = numap(user_proc, user_addr, count);
0109775          if (!src)
0109776                   panic("dp8390: umap failed", NO_NUM);
0109777 
0109778          phys_copy(src, vir2phys(loc_addr), (phys_bytes) count);
0109779 }
0109780 
0109781 
0109782 /*===========================================================================*
0109783  *                            put_userdata                             *
0109784  *===========================================================================*/
0109785 static void put_userdata(user_proc, user_addr, count, loc_addr)
0109786 int user_proc;
0109787 vir_bytes user_addr;
0109788 vir_bytes count;
0109789 void *loc_addr;
0109790 {
0109791          phys_bytes dst;
0109792 
0109793          dst = numap(user_proc, user_addr, count);
0109794          if (!dst)
0109795                   panic("dp8390: umap failed", NO_NUM);
0109796 
0109797          phys_copy(vir2phys(loc_addr), dst, (phys_bytes) count);
0109798 }
0109799 
0109800 #endif /* ENABLE_DP8390 */
0109801 
0109802 /*
0109803  * $PchId: dp8390.c,v 1.5 1996/01/19 22:56:35 philip Exp $
0109804  */