Subversion Repositories HelenOS

Rev

Rev 4743 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  3.  *
  4.  * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  5.  * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  6.  * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
  7.  * * Any deviations from these conditions require written permission from the copyright holder in advance
  8.  *
  9.  *
  10.  * Disclaimer
  11.  *
  12.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
  13.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  14.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  15.  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  16.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  17.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  18.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  19.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  21.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22.  *
  23.  * Changes:
  24.  *  2009 ported to HelenOS, Lukas Mejdrech
  25.  */
  26.  
  27. /** @addtogroup dp8390
  28.  *  @{
  29.  */
  30.  
  31. /** @file
  32.  *  DP8390 network interface core implementation.
  33.  */
  34.  
  35. #include <assert.h>
  36. #include <errno.h>
  37.  
  38. #include "../../include/byteorder.h"
  39.  
  40. #include "../../structures/packet/packet.h"
  41. #include "../../structures/packet/packet_client.h"
  42.  
  43. #include "../netif.h"
  44.  
  45. #include "dp8390_drv.h"
  46. #include "dp8390_port.h"
  47.  
  48. /*
  49.  * dp8390.c
  50.  *
  51.  * Created: before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
  52.  *
  53.  * Modified Mar 10 1994 by Philip Homburg
  54.  *  Become a generic dp8390 driver.
  55.  *
  56.  * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
  57.  *  Added support for 3c503 boards.
  58.  */
  59.  
  60. #include "local.h"
  61. #include "dp8390.h"
  62.  
  63. /** Queues the outgoing packet.
  64.  *  @param[in] dep The network interface structure.
  65.  *  @param[in] packet The outgoing packet.
  66.  *  @returns EOK on success.
  67.  *  @returns EINVAL
  68.  */
  69. int queue_packet( dpeth_t * dep, packet_t packet );
  70.  
  71. /** Reads a memory block byte by byte.
  72.  *  @param[in] port The source address.
  73.  *  @param[out] buf The destination buffer.
  74.  *  @param[in] size The memory block size in bytes.
  75.  */
  76. static void outsb( port_t port, void * buf, size_t size );
  77.  
  78. /** Reads a memory block word by word.
  79.  *  @param[in] port The source address.
  80.  *  @param[out] buf The destination buffer.
  81.  *  @param[in] size The memory block size in bytes.
  82.  */
  83. static void outsw( port_t port, void * buf, size_t size );
  84.  
  85. //static u16_t eth_ign_proto;
  86. //static char *progname;
  87.  
  88. /* Configuration */
  89. /*typedef struct dp_conf
  90. {
  91.     port_t dpc_port;
  92.     int dpc_irq;
  93.     phys_bytes dpc_mem;
  94.     char *dpc_envvar;
  95. } dp_conf_t;
  96. */
  97. //dp_conf_t dp_conf[]=  /* Card addresses */
  98. //{
  99.     /* I/O port, IRQ,  Buffer address,  Env. var. */
  100. /*  {  0x280,     3,    0xD0000,        "DPETH0"    },
  101.     {  0x300,     5,    0xC8000,        "DPETH1"    },
  102.     {  0x380,    10,    0xD8000,        "DPETH2"    },
  103. };
  104. */
  105. /* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
  106.  * the error: "array size is negative".
  107.  */
  108. //extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
  109.  
  110. /* Card inits configured out? */
  111. #if !ENABLE_WDETH
  112. #define wdeth_probe(dep)    (0)
  113. #endif
  114. #if !ENABLE_NE2000
  115. #define ne_probe(dep)       (0)
  116. #endif
  117. #if !ENABLE_3C503
  118. #define el2_probe(dep)      (0)
  119. #endif
  120.  
  121. /* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
  122.  * on writes to the CR register. Additional CR_STAs do not appear to hurt
  123.  * genuine dp8390s
  124.  */
  125. #define CR_EXTRA    CR_STA
  126.  
  127. //#if ENABLE_PCI
  128. //_PROTOTYPE( static void pci_conf, (void)              );
  129. //#endif
  130. //_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
  131. //                          int vectored)   );
  132. //_PROTOTYPE( static void do_vwrite_s, (message *mp, int from_int)  );
  133. //_PROTOTYPE( static void do_vread, (message *mp, int vectored)     );
  134. //_PROTOTYPE( static void do_vread_s, (message *mp)         );
  135. //_PROTOTYPE( static void do_init, (message *mp)                );
  136. //_PROTOTYPE( static void do_int, (dpeth_t *dep)                );
  137. //_PROTOTYPE( static void do_getstat, (message *mp)         );
  138. //_PROTOTYPE( static void do_getstat_s, (message *mp)           );
  139. //_PROTOTYPE( static void do_getname, (message *mp)         );
  140. //_PROTOTYPE( static void do_stop, (message *mp)                );
  141. _PROTOTYPE( static void dp_init, (dpeth_t *dep)             );
  142. //_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)           );
  143. _PROTOTYPE( static void dp_reinit, (dpeth_t *dep)           );
  144. _PROTOTYPE( static void dp_reset, (dpeth_t *dep)            );
  145. //_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)         );
  146. _PROTOTYPE( static void dp_recv, (dpeth_t *dep)             );
  147. _PROTOTYPE( static void dp_send, (dpeth_t *dep)             );
  148. //_PROTOTYPE( static void dp8390_stop, (void)               );
  149. _PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
  150.                 size_t offset, size_t size, void *dst)  );
  151. _PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
  152.                 size_t offset, size_t size, void *dst)  );
  153. _PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
  154.                 size_t offset, size_t size, void *dst)  );
  155. _PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
  156.                             int length) );
  157. //_PROTOTYPE( static int dp_pkt2user_s, (dpeth_t *dep, int page,
  158. //                          int length) );
  159. _PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp,
  160.         vir_bytes offset, int nic_addr, vir_bytes count)    );
  161. //_PROTOTYPE( static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp,
  162. //      vir_bytes offset, int nic_addr, vir_bytes count)    );
  163. _PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
  164.                 iovec_dat_t *iovp, vir_bytes offset,
  165.                 int nic_addr, vir_bytes count)      );
  166. //_PROTOTYPE( static void dp_pio8_user2nic_s, (dpeth_t *dep,
  167. //              iovec_dat_s_t *iovp, vir_bytes offset,
  168. //              int nic_addr, vir_bytes count)      );
  169. _PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
  170.                 iovec_dat_t *iovp, vir_bytes offset,
  171.                 int nic_addr, vir_bytes count)      );
  172. //_PROTOTYPE( static void dp_pio16_user2nic_s, (dpeth_t *dep,
  173. //              iovec_dat_s_t *iovp, vir_bytes offset,
  174. //              int nic_addr, vir_bytes count)      );
  175. _PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr,
  176.         iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  177. //_PROTOTYPE( static void dp_nic2user_s, (dpeth_t *dep, int nic_addr,
  178. //      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
  179. _PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr,
  180.         iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  181. //_PROTOTYPE( static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr,
  182. //      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
  183. _PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr,
  184.         iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)   );
  185. //_PROTOTYPE( static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr,
  186. //      iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count) );
  187. _PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)      );
  188. //_PROTOTYPE( static void dp_next_iovec_s, (iovec_dat_s_t *iovp)        );
  189. _PROTOTYPE( static void conf_hw, (dpeth_t *dep)             );
  190. //_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)   );
  191. _PROTOTYPE( static void map_hw_buffer, (dpeth_t *dep)           );
  192. //_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)       );
  193. //_PROTOTYPE( static int calc_iovec_size_s, (iovec_dat_s_t *iovp)       );
  194. _PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)   );
  195. //_PROTOTYPE( static void mess_reply, (message *req, message *reply)    );
  196. _PROTOTYPE( static void get_userdata, (int user_proc,
  197.         vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  198. //_PROTOTYPE( static void get_userdata_s, (int user_proc,
  199. //      cp_grant_id_t grant, vir_bytes offset, vir_bytes count,
  200. //      void *loc_addr) );
  201. //_PROTOTYPE( static void put_userdata, (int user_proc,
  202. //      vir_bytes user_addr, vir_bytes count, void *loc_addr)   );
  203. //_PROTOTYPE( static void put_userdata_s, (int user_proc,
  204. //      cp_grant_id_t grant, size_t count, void *loc_addr)  );
  205. _PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)             );
  206. _PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)             );
  207. //_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
  208. //                  vir_bytes buf, size_t size) );
  209. //_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
  210. //                  vir_bytes buf, size_t size) );
  211. //_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
  212. //                  vir_bytes buf, size_t size) );
  213. //_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
  214. //                  vir_bytes buf, size_t size) );
  215.  
  216. int do_probe( dpeth_t * dep ){
  217.     /* This is the default, try to (re)locate the device. */
  218.     conf_hw(dep);
  219.     if (dep->de_mode == DEM_DISABLED)
  220.     {
  221.         /* Probe failed, or the device is configured off. */
  222.         return EXDEV;//ENXIO;
  223.     }
  224.     if (dep->de_mode == DEM_ENABLED)
  225.         dp_init(dep);
  226.     return EOK;
  227. }
  228.  
  229. /*===========================================================================*
  230.  *              dp8390_dump                  *
  231.  *===========================================================================*/
  232. void dp8390_dump( dpeth_t * dep )
  233. {
  234. //  dpeth_t *dep;
  235.     int /*i,*/ isr;
  236.  
  237. //  printf("\n");
  238. //  for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
  239. //  {
  240. #if XXX
  241.         if (dep->de_mode == DEM_DISABLED)
  242.             printf("dp8390 port %d is disabled\n", i);
  243.         else if (dep->de_mode == DEM_SINK)
  244.             printf("dp8390 port %d is in sink mode\n", i);
  245. #endif
  246.  
  247.         if (dep->de_mode != DEM_ENABLED)
  248. //          continue;
  249.             return;
  250.  
  251. //      printf("dp8390 statistics of port %d:\n", i);
  252.  
  253.         printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
  254.         printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
  255.         printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
  256.  
  257.         printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
  258.         printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
  259.         printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
  260.  
  261.         printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
  262.         printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
  263.         printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
  264.  
  265.         printf("collision  :%8ld\t", dep->de_stat.ets_collision);
  266.         printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
  267.         printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
  268.  
  269.         printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
  270.         printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
  271.         printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
  272.  
  273.         printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
  274.  
  275.         isr= inb_reg0(dep, DP_ISR);
  276.         printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
  277.                     inb_reg0(dep, DP_ISR), dep->de_flags);
  278. //  }
  279. }
  280.  
  281. /*===========================================================================*
  282.  *              do_init                      *
  283.  *===========================================================================*/
  284. int do_init( dpeth_t * dep, int mode ){
  285.     if (dep->de_mode == DEM_DISABLED)
  286.     {
  287.         // might call do_probe()
  288.         return EXDEV;
  289.     }
  290.  
  291.     if (dep->de_mode == DEM_SINK)
  292.     {
  293. //      strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
  294. //      dep->de_address.ea_addr[5] = port;
  295. //      dp_confaddr(dep);
  296. //      reply_mess.m_type = DL_CONF_REPLY;
  297. //      reply_mess.m3_i1 = mp->DL_PORT;
  298. //      reply_mess.m3_i2 = DE_PORT_NR;
  299. //      *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
  300. //      mess_reply(mp, &reply_mess);
  301. //      return;
  302.         return EOK;
  303.     }
  304.     assert(dep->de_mode == DEM_ENABLED);
  305.     assert(dep->de_flags & DEF_ENABLED);
  306.  
  307.     dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
  308.  
  309.     if (mode & DL_PROMISC_REQ)
  310.         dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
  311.     if (mode & DL_MULTI_REQ)
  312.         dep->de_flags |= DEF_MULTI;
  313.     if (mode & DL_BROAD_REQ)
  314.         dep->de_flags |= DEF_BROAD;
  315.  
  316. //  dep->de_client = mp->m_source;
  317.     dp_reinit(dep);
  318.  
  319. //  reply_mess.m_type = DL_CONF_REPLY;
  320. //  reply_mess.m3_i1 = mp->DL_PORT;
  321. //  reply_mess.m3_i2 = DE_PORT_NR;
  322. //  *(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
  323.  
  324. //  mess_reply(mp, &reply_mess);
  325.     return EOK;
  326. }
  327.  
  328. /*===========================================================================*
  329.  *              do_stop                      *
  330.  *===========================================================================*/
  331. void do_stop( dpeth_t * dep ){
  332.     if(( dep->de_mode != DEM_SINK ) && ( dep->de_mode == DEM_ENABLED ) && ( dep->de_flags & DEF_ENABLED )){
  333.         outb_reg0( dep, DP_CR, CR_STP | CR_DM_ABORT );
  334.         ( dep->de_stopf )( dep );
  335.  
  336.         dep->de_flags = DEF_EMPTY;
  337.     }
  338. }
  339.  
  340. int queue_packet( dpeth_t * dep, packet_t packet ){
  341.     packet_t    tmp;
  342.  
  343.     if( dep->packet_count >= MAX_PACKETS ){
  344.         netif_pq_release( packet_get_id( packet ));
  345.         return ELIMIT;
  346.     }
  347.  
  348.     tmp = dep->packet_queue;
  349.     while( pq_next( tmp )){
  350.         tmp = pq_next( tmp );
  351.     }
  352.     if( ! pq_add( tmp, packet, 0, 0 )){
  353.         return EINVAL;
  354.     }
  355.     if( ! dep->packet_count ){
  356.         dep->packet_queue = packet;
  357.     }
  358.     ++ dep->packet_count;
  359.     return EBUSY;
  360. }
  361.  
  362. /*===========================================================================*
  363.  *          based on    do_vwrite                    *
  364.  *===========================================================================*/
  365. int do_pwrite( dpeth_t * dep, packet_t packet, int from_int )
  366. {
  367. //  int port, count, size;
  368.     int size;
  369.     int sendq_head;
  370. /*  dpeth_t *dep;
  371.  
  372.     port = mp->DL_PORT;
  373.     count = mp->DL_COUNT;
  374.     if (port < 0 || port >= DE_PORT_NR)
  375.         panic("", "dp8390: illegal port", port);
  376.     dep= &de_table[port];
  377.     dep->de_client= mp->DL_PROC;
  378. */
  379.     if (dep->de_mode == DEM_SINK)
  380.     {
  381.         assert(!from_int);
  382. //      dep->de_flags |= DEF_PACK_SEND;
  383.         reply(dep, OK, FALSE);
  384. //      return;
  385.         return EOK;
  386.     }
  387.     assert(dep->de_mode == DEM_ENABLED);
  388.     assert(dep->de_flags & DEF_ENABLED);
  389.     if( dep->packet_queue && ( ! from_int )){
  390. //  if (dep->de_flags & DEF_SEND_AVAIL){
  391. //      panic("", "dp8390: send already in progress", NO_NUM);
  392.         return queue_packet( dep, packet );
  393.     }
  394.  
  395.     sendq_head= dep->de_sendq_head;
  396. //  if (dep->de_sendq[sendq_head].sq_filled)
  397. //  {
  398. //      if (from_int)
  399. //          panic("", "dp8390: should not be sending\n", NO_NUM);
  400. //      dep->de_sendmsg= *mp;
  401. //      dep->de_flags |= DEF_SEND_AVAIL;
  402. //      reply(dep, OK, FALSE);
  403. //      return;
  404. //      return queue_packet( dep, packet );
  405. //  }
  406. //  assert(!(dep->de_flags & DEF_PACK_SEND));
  407.  
  408. /*  if (vectored)
  409.     {
  410.         get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
  411.             (count > IOVEC_NR ? IOVEC_NR : count) *
  412.             sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
  413.         dep->de_write_iovec.iod_iovec_s = count;
  414.         dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
  415.         dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
  416.  
  417.         dep->de_tmp_iovec = dep->de_write_iovec;
  418.         size = calc_iovec_size(&dep->de_tmp_iovec);
  419.     }
  420.     else
  421.     {  
  422.         dep->de_write_iovec.iod_iovec[0].iov_addr =
  423.             (vir_bytes) mp->DL_ADDR;
  424.         dep->de_write_iovec.iod_iovec[0].iov_size =
  425.             mp->DL_COUNT;
  426.         dep->de_write_iovec.iod_iovec_s = 1;
  427.         dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
  428.         dep->de_write_iovec.iod_iovec_addr = 0;
  429.         size= mp->DL_COUNT;
  430.     }
  431. */
  432.     size = packet_get_data_length( packet );
  433.     dep->de_write_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_get_data( packet );
  434.     dep->de_write_iovec.iod_iovec[0].iov_size = size;
  435.     dep->de_write_iovec.iod_iovec_s = 1;
  436.     dep->de_write_iovec.iod_iovec_addr = NULL;
  437.  
  438.     if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
  439.     {
  440.         panic("", "dp8390: invalid packet size", size);
  441.         return EINVAL;
  442.     }
  443.     (dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
  444.         dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
  445.         size);
  446.     dep->de_sendq[sendq_head].sq_filled= TRUE;
  447.     if (dep->de_sendq_tail == sendq_head)
  448.     {
  449.         outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
  450.         outb_reg0(dep, DP_TBCR1, size >> 8);
  451.         outb_reg0(dep, DP_TBCR0, size & 0xff);
  452.         outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
  453.     }
  454.     else
  455.         dep->de_sendq[sendq_head].sq_size= size;
  456.    
  457.     if (++sendq_head == dep->de_sendq_nr)
  458.         sendq_head= 0;
  459.     assert(sendq_head < SENDQ_NR);
  460.     dep->de_sendq_head= sendq_head;
  461.  
  462. //  dep->de_flags |= DEF_PACK_SEND;
  463.  
  464.     /* If the interrupt handler called, don't send a reply. The reply
  465.      * will be sent after all interrupts are handled.
  466.      */
  467.     if (from_int)
  468.         return EOK;
  469.     reply(dep, OK, FALSE);
  470.  
  471.     assert(dep->de_mode == DEM_ENABLED);
  472.     assert(dep->de_flags & DEF_ENABLED);
  473.     return EOK;
  474. }
  475.  
  476. /*===========================================================================*
  477.  *              dp_init                      *
  478.  *===========================================================================*/
  479. void dp_init(dep)
  480. dpeth_t *dep;
  481. {
  482.     int dp_rcr_reg;
  483.     int i;//, r;
  484.  
  485.     /* General initialization */
  486.     dep->de_flags = DEF_EMPTY;
  487.     (*dep->de_initf)(dep);
  488.  
  489. //  dp_confaddr(dep);
  490.  
  491.     if (debug)
  492.     {
  493.         printf("%s: Ethernet address ", dep->de_name);
  494.         for (i= 0; i < 6; i++)
  495.             printf("%x%c", dep->de_address.ea_addr[i],
  496.                             i < 5 ? ':' : '\n');
  497.     }
  498.  
  499.     /* Map buffer */
  500.     map_hw_buffer(dep);
  501.  
  502.     /* Initialization of the dp8390 following the mandatory procedure
  503.      * in reference manual ("DP8390D/NS32490D NIC Network Interface
  504.      * Controller", National Semiconductor, July 1995, Page 29).
  505.      */
  506.     /* Step 1: */
  507.     outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
  508.     /* Step 2: */
  509.     if (dep->de_16bit)
  510.         outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
  511.     else
  512.         outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
  513.     /* Step 3: */
  514.     outb_reg0(dep, DP_RBCR0, 0);
  515.     outb_reg0(dep, DP_RBCR1, 0);
  516.     /* Step 4: */
  517.     dp_rcr_reg = 0;
  518.     if (dep->de_flags & DEF_PROMISC)
  519.         dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
  520.     if (dep->de_flags & DEF_BROAD)
  521.         dp_rcr_reg |= RCR_AB;
  522.     if (dep->de_flags & DEF_MULTI)
  523.         dp_rcr_reg |= RCR_AM;
  524.     outb_reg0(dep, DP_RCR, dp_rcr_reg);
  525.     /* Step 5: */
  526.     outb_reg0(dep, DP_TCR, TCR_INTERNAL);
  527.     /* Step 6: */
  528.     outb_reg0(dep, DP_BNRY, dep->de_startpage);
  529.     outb_reg0(dep, DP_PSTART, dep->de_startpage);
  530.     outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
  531.     /* Step 7: */
  532.     outb_reg0(dep, DP_ISR, 0xFF);
  533.     /* Step 8: */
  534.     outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
  535.         IMR_OVWE | IMR_CNTE);
  536.     /* Step 9: */
  537.     outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
  538.  
  539.     outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
  540.     outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
  541.     outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
  542.     outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
  543.     outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
  544.     outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
  545.  
  546.     outb_reg1(dep, DP_MAR0, 0xff);
  547.     outb_reg1(dep, DP_MAR1, 0xff);
  548.     outb_reg1(dep, DP_MAR2, 0xff);
  549.     outb_reg1(dep, DP_MAR3, 0xff);
  550.     outb_reg1(dep, DP_MAR4, 0xff);
  551.     outb_reg1(dep, DP_MAR5, 0xff);
  552.     outb_reg1(dep, DP_MAR6, 0xff);
  553.     outb_reg1(dep, DP_MAR7, 0xff);
  554.  
  555.     outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
  556.     /* Step 10: */
  557.     outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
  558.     /* Step 11: */
  559.     outb_reg0(dep, DP_TCR, TCR_NORMAL);
  560.  
  561.     inb_reg0(dep, DP_CNTR0);        /* reset counters by reading */
  562.     inb_reg0(dep, DP_CNTR1);
  563.     inb_reg0(dep, DP_CNTR2);
  564.  
  565.     /* Finish the initialization. */
  566.     dep->de_flags |= DEF_ENABLED;
  567.     for (i= 0; i<dep->de_sendq_nr; i++)
  568.         dep->de_sendq[i].sq_filled= 0;
  569.     dep->de_sendq_head= 0;
  570.     dep->de_sendq_tail= 0;
  571.     if (!dep->de_prog_IO)
  572.     {
  573.         dep->de_user2nicf= dp_user2nic;
  574. //      dep->de_user2nicf_s= dp_user2nic_s;
  575.         dep->de_nic2userf= dp_nic2user;
  576. //      dep->de_nic2userf_s= dp_nic2user_s;
  577.         dep->de_getblockf= dp_getblock;
  578.     }
  579.     else if (dep->de_16bit)
  580.     {
  581.         dep->de_user2nicf= dp_pio16_user2nic;
  582. //      dep->de_user2nicf_s= dp_pio16_user2nic_s;
  583.         dep->de_nic2userf= dp_pio16_nic2user;
  584. //      dep->de_nic2userf_s= dp_pio16_nic2user_s;
  585.         dep->de_getblockf= dp_pio16_getblock;
  586.     }
  587.     else
  588.     {
  589.         dep->de_user2nicf= dp_pio8_user2nic;
  590. //      dep->de_user2nicf_s= dp_pio8_user2nic_s;
  591.         dep->de_nic2userf= dp_pio8_nic2user;
  592. //      dep->de_nic2userf_s= dp_pio8_nic2user_s;
  593.         dep->de_getblockf= dp_pio8_getblock;
  594.     }
  595.  
  596.     /* Set the interrupt handler and policy. Do not automatically
  597.      * reenable interrupts. Return the IRQ line number on interrupts.
  598.      */
  599. /*  dep->de_hook = dep->de_irq;
  600.     r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
  601.     if (r != OK)
  602.         panic("DP8390", "sys_irqsetpolicy failed", r);
  603.  
  604.     r= sys_irqenable(&dep->de_hook);
  605.     if (r != OK)
  606.     {
  607.         panic("DP8390", "unable enable interrupts", r);
  608.     }
  609. */
  610. }
  611.  
  612. /*===========================================================================*
  613.  *              dp_reinit                    *
  614.  *===========================================================================*/
  615. static void dp_reinit(dep)
  616. dpeth_t *dep;
  617. {
  618.     int dp_rcr_reg;
  619.  
  620.     outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
  621.  
  622.     dp_rcr_reg = 0;
  623.     if (dep->de_flags & DEF_PROMISC)
  624.         dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
  625.     if (dep->de_flags & DEF_BROAD)
  626.         dp_rcr_reg |= RCR_AB;
  627.     if (dep->de_flags & DEF_MULTI)
  628.         dp_rcr_reg |= RCR_AM;
  629.     outb_reg0(dep, DP_RCR, dp_rcr_reg);
  630. }
  631.  
  632. /*===========================================================================*
  633.  *              dp_reset                     *
  634.  *===========================================================================*/
  635. static void dp_reset(dep)
  636. dpeth_t *dep;
  637. {
  638.     int i;
  639.  
  640.     /* Stop chip */
  641.     outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
  642.     outb_reg0(dep, DP_RBCR0, 0);
  643.     outb_reg0(dep, DP_RBCR1, 0);
  644.     for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
  645.         ; /* Do nothing */
  646.     outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
  647.     outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
  648.     outb_reg0(dep, DP_TCR, TCR_NORMAL);
  649.  
  650.     /* Acknowledge the ISR_RDC (remote dma) interrupt. */
  651.     for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
  652.         ; /* Do nothing */
  653.     outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
  654.  
  655.     /* Reset the transmit ring. If we were transmitting a packet, we
  656.      * pretend that the packet is processed. Higher layers will
  657.      * retransmit if the packet wasn't actually sent.
  658.      */
  659.     dep->de_sendq_head= dep->de_sendq_tail= 0;
  660.     for (i= 0; i<dep->de_sendq_nr; i++)
  661.         dep->de_sendq[i].sq_filled= 0;
  662.     dp_send(dep);
  663.     dep->de_flags &= ~DEF_STOPPED;
  664. }
  665.  
  666. /*===========================================================================*
  667.  *              dp_check_ints                    *
  668.  *===========================================================================*/
  669. void dp_check_ints(dep, isr)
  670. dpeth_t *dep;
  671. int isr;
  672. {
  673.     int /*isr,*/ tsr;
  674.     int size, sendq_tail;
  675.  
  676.     if (!(dep->de_flags & DEF_ENABLED))
  677.         panic("", "dp8390: got premature interrupt", NO_NUM);
  678.  
  679.     for(;;)
  680.     {
  681. //      isr = inb_reg0(dep, DP_ISR);
  682.         if (!isr)
  683.             break;
  684.         outb_reg0(dep, DP_ISR, isr);
  685.         if (isr & (ISR_PTX|ISR_TXE))
  686.         {
  687.             if (isr & ISR_TXE)
  688.             {
  689. #if DEBUG
  690.  { printf("%s: got send Error\n", dep->de_name); }
  691. #endif
  692.                 dep->de_stat.ets_sendErr++;
  693.             }
  694.             else
  695.             {
  696.                 tsr = inb_reg0(dep, DP_TSR);
  697.  
  698.                 if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
  699. #if 0   /* Reserved in later manuals, should be ignored */
  700.                 if (!(tsr & TSR_DFR))
  701.                 {
  702.                     /* In most (all?) implementations of
  703.                      * the dp8390, this bit is set
  704.                      * when the packet is not deferred
  705.                      */
  706.                     dep->de_stat.ets_transDef++;
  707.                 }
  708. #endif
  709.                 if (tsr & TSR_COL) dep->de_stat.ets_collision++;
  710.                 if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
  711.                 if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
  712.                 if (tsr & TSR_FU
  713.                     && ++dep->de_stat.ets_fifoUnder <= 10)
  714.                 {
  715.                     printf("%s: fifo underrun\n",
  716.                         dep->de_name);
  717.                 }
  718.                 if (tsr & TSR_CDH
  719.                     && ++dep->de_stat.ets_CDheartbeat <= 10)
  720.                 {
  721.                     printf("%s: CD heart beat failure\n",
  722.                         dep->de_name);
  723.                 }
  724.                 if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
  725.             }
  726.             sendq_tail= dep->de_sendq_tail;
  727.  
  728.             if (!(dep->de_sendq[sendq_tail].sq_filled))
  729.             {
  730.                 /* Software bug? */
  731.                 assert(!debug);
  732.  
  733.                 /* Or hardware bug? */
  734.                 printf(
  735.                 "%s: transmit interrupt, but not sending\n",
  736.                     dep->de_name);
  737.                 continue;
  738.             }
  739.             dep->de_sendq[sendq_tail].sq_filled= 0;
  740.             if (++sendq_tail == dep->de_sendq_nr)
  741.                 sendq_tail= 0;
  742.             dep->de_sendq_tail= sendq_tail;
  743.             if (dep->de_sendq[sendq_tail].sq_filled)
  744.             {
  745.                 size= dep->de_sendq[sendq_tail].sq_size;
  746.                 outb_reg0(dep, DP_TPSR,
  747.                     dep->de_sendq[sendq_tail].sq_sendpage);
  748.                 outb_reg0(dep, DP_TBCR1, size >> 8);
  749.                 outb_reg0(dep, DP_TBCR0, size & 0xff);
  750.                 outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
  751.             }
  752. //          if (dep->de_flags & DEF_SEND_AVAIL)
  753.                 dp_send(dep);
  754.         }
  755.  
  756.         if (isr & ISR_PRX)
  757.         {
  758.             /* Only call dp_recv if there is a read request */
  759. //          if (dep->de_flags) & DEF_READING)
  760.                 dp_recv(dep);
  761.         }
  762.        
  763.         if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
  764.         if (isr & ISR_CNT)
  765.         {
  766.             dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
  767.             dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
  768.             dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
  769.         }
  770.         if (isr & ISR_OVW)
  771.         {
  772.             dep->de_stat.ets_OVW++;
  773. #if 0
  774.             { printW(); printf(
  775.                 "%s: got overwrite warning\n", dep->de_name); }
  776. #endif
  777. /*          if (dep->de_flags & DEF_READING)
  778.             {
  779.                 printf(
  780. "dp_check_ints: strange: overwrite warning and pending read request\n");
  781.                 dp_recv(dep);
  782.             }
  783. */      }
  784.         if (isr & ISR_RDC)
  785.         {
  786.             /* Nothing to do */
  787.         }
  788.         if (isr & ISR_RST)
  789.         {
  790.             /* this means we got an interrupt but the ethernet
  791.              * chip is shutdown. We set the flag DEF_STOPPED,
  792.              * and continue processing arrived packets. When the
  793.              * receive buffer is empty, we reset the dp8390.
  794.              */
  795. #if 0
  796.              { printW(); printf(
  797.                 "%s: NIC stopped\n", dep->de_name); }
  798. #endif
  799.             dep->de_flags |= DEF_STOPPED;
  800.             break;
  801.         }
  802.         isr = inb_reg0(dep, DP_ISR);
  803.     }
  804. //  if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) ==
  805. //                      (DEF_READING|DEF_STOPPED))
  806.     if ((dep->de_flags & DEF_STOPPED) == DEF_STOPPED )
  807.     {
  808.         /* The chip is stopped, and all arrived packets are
  809.          * delivered.
  810.          */
  811.         dp_reset(dep);
  812.     }
  813. }
  814.  
  815. /*===========================================================================*
  816.  *              dp_recv                      *
  817.  *===========================================================================*/
  818. static void dp_recv(dep)
  819. dpeth_t *dep;
  820. {
  821.     dp_rcvhdr_t header;
  822.     unsigned pageno, curr, next;
  823.     vir_bytes length;
  824.     int packet_processed, r;
  825.     u16_t eth_type;
  826.  
  827.     packet_processed = FALSE;
  828.     pageno = inb_reg0(dep, DP_BNRY) + 1;
  829.     if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
  830.  
  831.     do
  832.     {
  833.         outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
  834.         curr = inb_reg1(dep, DP_CURR);
  835.         outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
  836.  
  837.         if (curr == pageno) break;
  838.  
  839.         (dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
  840.             &header);
  841.         (dep->de_getblockf)(dep, pageno, sizeof(header) +
  842.             2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
  843.  
  844.         length = (header.dr_rbcl | (header.dr_rbch << 8)) -
  845.             sizeof(dp_rcvhdr_t);
  846.         next = header.dr_next;
  847.         if (length < ETH_MIN_PACK_SIZE ||
  848.             length > ETH_MAX_PACK_SIZE_TAGGED)
  849.         {
  850.             printf("%s: packet with strange length arrived: %d\n",
  851.                 dep->de_name, (int) length);
  852.             next= curr;
  853.         }
  854.         else if (next < dep->de_startpage || next >= dep->de_stoppage)
  855.         {
  856.             printf("%s: strange next page\n", dep->de_name);
  857.             next= curr;
  858.         }
  859. /*      else if (eth_type == eth_ign_proto)
  860.         {
  861. */          /* Hack: ignore packets of a given protocol, useful
  862.              * if you share a net with 80 computers sending
  863.              * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
  864.              */
  865. /*          static int first= 1;
  866.             if (first)
  867.             {
  868.                 first= 0;
  869.                 printf("%s: dropping proto 0x%04x packets\n",
  870.                     dep->de_name,
  871.                     ntohs(eth_ign_proto));
  872.             }
  873.             dep->de_stat.ets_packetR++;
  874.         }
  875. */      else if (header.dr_status & RSR_FO)
  876.         {
  877.             /* This is very serious, so we issue a warning and
  878.              * reset the buffers */
  879.             printf("%s: fifo overrun, resetting receive buffer\n",
  880.                 dep->de_name);
  881.             dep->de_stat.ets_fifoOver++;
  882.             next = curr;
  883.         }
  884.         else if ((header.dr_status & RSR_PRX) &&
  885.                        (dep->de_flags & DEF_ENABLED))
  886.         {
  887. //          if (dep->de_safecopy_read)
  888. //              r = dp_pkt2user_s(dep, pageno, length);
  889. //          else
  890.                 r = dp_pkt2user(dep, pageno, length);
  891.             if (r != OK)
  892.                 return;
  893.  
  894.             packet_processed = TRUE;
  895.             dep->de_stat.ets_packetR++;
  896.         }
  897.         if (next == dep->de_startpage)
  898.             outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
  899.         else
  900.             outb_reg0(dep, DP_BNRY, next - 1);
  901.  
  902.         pageno = next;
  903.     }
  904.     while (!packet_processed);
  905. }
  906.  
  907. /*===========================================================================*
  908.  *              dp_send                      *
  909.  *===========================================================================*/
  910. static void dp_send(dep)
  911. dpeth_t *dep;
  912. {
  913.     packet_t packet;
  914.  
  915. //  if (!(dep->de_flags & DEF_SEND_AVAIL))
  916. //      return;
  917.  
  918.     if( dep->packet_queue ){
  919.         packet = dep->packet_queue;
  920.         dep->packet_queue = pq_detach( packet );
  921.         do_pwrite( dep, packet, TRUE );
  922.         netif_pq_release( packet_get_id( packet ));
  923.         -- dep->packet_count;
  924.     }
  925. //  if( ! dep->packet_queue ){
  926. //      dep->de_flags &= ~DEF_SEND_AVAIL;
  927. //  }
  928. /*  switch(dep->de_sendmsg.m_type)
  929.     {
  930.     case DL_WRITE:  do_vwrite(&dep->de_sendmsg, TRUE, FALSE);   break;
  931.     case DL_WRITEV: do_vwrite(&dep->de_sendmsg, TRUE, TRUE);    break;
  932.     case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE);  break;
  933.     default:
  934.         panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
  935.         break;
  936.     }
  937. */
  938. }
  939.  
  940. /*===========================================================================*
  941.  *              dp_getblock                  *
  942.  *===========================================================================*/
  943. static void dp_getblock(dep, page, offset, size, dst)
  944. dpeth_t *dep;
  945. int page;
  946. size_t offset;
  947. size_t size;
  948. void *dst;
  949. {
  950. //  int r;
  951.  
  952.     offset = page * DP_PAGESIZE + offset;
  953.  
  954.     memcpy(dst, dep->de_locmem + offset, size);
  955. }
  956.  
  957. /*===========================================================================*
  958.  *              dp_pio8_getblock                 *
  959.  *===========================================================================*/
  960. static void dp_pio8_getblock(dep, page, offset, size, dst)
  961. dpeth_t *dep;
  962. int page;
  963. size_t offset;
  964. size_t size;
  965. void *dst;
  966. {
  967.     offset = page * DP_PAGESIZE + offset;
  968.     outb_reg0(dep, DP_RBCR0, size & 0xFF);
  969.     outb_reg0(dep, DP_RBCR1, size >> 8);
  970.     outb_reg0(dep, DP_RSAR0, offset & 0xFF);
  971.     outb_reg0(dep, DP_RSAR1, offset >> 8);
  972.     outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  973.  
  974.     insb(dep->de_data_port, dst, size);
  975. }
  976.  
  977. /*===========================================================================*
  978.  *              dp_pio16_getblock                *
  979.  *===========================================================================*/
  980. static void dp_pio16_getblock(dep, page, offset, size, dst)
  981. dpeth_t *dep;
  982. int page;
  983. size_t offset;
  984. size_t size;
  985. void *dst;
  986. {
  987.     offset = page * DP_PAGESIZE + offset;
  988.     outb_reg0(dep, DP_RBCR0, size & 0xFF);
  989.     outb_reg0(dep, DP_RBCR1, size >> 8);
  990.     outb_reg0(dep, DP_RSAR0, offset & 0xFF);
  991.     outb_reg0(dep, DP_RSAR1, offset >> 8);
  992.     outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  993.  
  994.     assert (!(size & 1));
  995.     insw(dep->de_data_port, dst, size);
  996. }
  997.  
  998. /*===========================================================================*
  999.  *              dp_pkt2user                  *
  1000.  *===========================================================================*/
  1001. static int dp_pkt2user(dep, page, length)
  1002. dpeth_t *dep;
  1003. int page, length;
  1004. {
  1005.     int last, count;
  1006.     packet_t    packet;
  1007.     packet_t    queue;
  1008.  
  1009. //  if (!(dep->de_flags & DEF_READING))
  1010. //      return EGENERIC;
  1011.  
  1012.     packet = netif_packet_get_1( length );
  1013.     if( ! packet ) return ENOMEM;
  1014.     dep->de_read_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_suffix( packet, length );
  1015.     dep->de_read_iovec.iod_iovec[0].iov_size = length;
  1016.     dep->de_read_iovec.iod_iovec_s = 1;
  1017.     dep->de_read_iovec.iod_iovec_addr = NULL;
  1018.  
  1019.     last = page + (length - 1) / DP_PAGESIZE;
  1020.     if (last >= dep->de_stoppage)
  1021.     {
  1022.         count = (dep->de_stoppage - page) * DP_PAGESIZE -
  1023.             sizeof(dp_rcvhdr_t);
  1024.  
  1025.         /* Save read_iovec since we need it twice. */
  1026.         dep->de_tmp_iovec = dep->de_read_iovec;
  1027.         (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
  1028.             sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
  1029.         (dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE,
  1030.                 &dep->de_read_iovec, count, length - count);
  1031.     }
  1032.     else
  1033.     {
  1034.         (dep->de_nic2userf)(dep, page * DP_PAGESIZE +
  1035.             sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
  1036.     }
  1037.  
  1038.     dep->de_read_s = length;
  1039.     dep->de_flags |= DEF_PACK_RECV;
  1040. //  dep->de_flags &= ~DEF_READING;
  1041.  
  1042.     if( dep->received_count >= MAX_PACKETS ){
  1043.         netif_pq_release( packet_get_id( packet ));
  1044.         return ELIMIT;
  1045.     }else{
  1046.         queue = pq_add( dep->received_queue, packet, 0, 0 );
  1047.         if( queue ){
  1048.             dep->received_queue = queue;
  1049.             ++ dep->received_count;
  1050.         }else{
  1051.             netif_pq_release( packet_get_id( packet ));
  1052.         }
  1053.     }
  1054.     return OK;
  1055. }
  1056.  
  1057. /*===========================================================================*
  1058.  *              dp_user2nic                  *
  1059.  *===========================================================================*/
  1060. static void dp_user2nic(dep, iovp, offset, nic_addr, count)
  1061. dpeth_t *dep;
  1062. iovec_dat_t *iovp;
  1063. vir_bytes offset;
  1064. int nic_addr;
  1065. vir_bytes count;
  1066. {
  1067.     vir_bytes vir_hw;//, vir_user;
  1068.     int bytes, i, r;
  1069.  
  1070.     vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
  1071.  
  1072.     i= 0;
  1073.     while (count > 0)
  1074.     {
  1075.         if (i >= IOVEC_NR)
  1076.         {
  1077.             dp_next_iovec(iovp);
  1078.             i= 0;
  1079.             continue;
  1080.         }
  1081.         assert(i < iovp->iod_iovec_s);
  1082.         if (offset >= iovp->iod_iovec[i].iov_size)
  1083.         {
  1084.             offset -= iovp->iod_iovec[i].iov_size;
  1085.             i++;
  1086.             continue;
  1087.         }
  1088.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1089.         if (bytes > count)
  1090.             bytes = count;
  1091.  
  1092.         r= sys_vircopy(iovp->iod_proc_nr, D,
  1093.             iovp->iod_iovec[i].iov_addr + offset,
  1094.             SELF, D, vir_hw, bytes);
  1095.         if (r != OK)
  1096.             panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
  1097.  
  1098.         count -= bytes;
  1099.         vir_hw += bytes;
  1100.         offset += bytes;
  1101.     }
  1102.     assert(count == 0);
  1103. }
  1104.  
  1105. /*===========================================================================*
  1106.  *              dp_pio8_user2nic                 *
  1107.  *===========================================================================*/
  1108. static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
  1109. dpeth_t *dep;
  1110. iovec_dat_t *iovp;
  1111. vir_bytes offset;
  1112. int nic_addr;
  1113. vir_bytes count;
  1114. {
  1115. //  phys_bytes phys_user;
  1116.     int bytes, i;
  1117.  
  1118.     outb_reg0(dep, DP_ISR, ISR_RDC);
  1119.  
  1120.     outb_reg0(dep, DP_RBCR0, count & 0xFF);
  1121.     outb_reg0(dep, DP_RBCR1, count >> 8);
  1122.     outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
  1123.     outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
  1124.     outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  1125.  
  1126.     i= 0;
  1127.     while (count > 0)
  1128.     {
  1129.         if (i >= IOVEC_NR)
  1130.         {
  1131.             dp_next_iovec(iovp);
  1132.             i= 0;
  1133.             continue;
  1134.         }
  1135.         assert(i < iovp->iod_iovec_s);
  1136.         if (offset >= iovp->iod_iovec[i].iov_size)
  1137.         {
  1138.             offset -= iovp->iod_iovec[i].iov_size;
  1139.             i++;
  1140.             continue;
  1141.         }
  1142.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1143.         if (bytes > count)
  1144.             bytes = count;
  1145.  
  1146.         do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
  1147.             iovp->iod_iovec[i].iov_addr + offset, bytes);
  1148.         count -= bytes;
  1149.         offset += bytes;
  1150.     }
  1151.     assert(count == 0);
  1152.  
  1153.     for (i= 0; i<100; i++)
  1154.     {
  1155.         if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  1156.             break;
  1157.     }
  1158.     if (i == 100)
  1159.     {
  1160.         panic("", "dp8390: remote dma failed to complete", NO_NUM);
  1161.     }
  1162. }
  1163.  
  1164. /*===========================================================================*
  1165.  *              dp_pio16_user2nic                *
  1166.  *===========================================================================*/
  1167. static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
  1168. dpeth_t *dep;
  1169. iovec_dat_t *iovp;
  1170. vir_bytes offset;
  1171. int nic_addr;
  1172. vir_bytes count;
  1173. {
  1174.     vir_bytes vir_user;
  1175.     vir_bytes ecount;
  1176.     int i, r, bytes, user_proc;
  1177.     u8_t two_bytes[2];
  1178.     int odd_byte;
  1179.  
  1180.     ecount= (count+1) & ~1;
  1181.     odd_byte= 0;
  1182.  
  1183.     outb_reg0(dep, DP_ISR, ISR_RDC);
  1184.     outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
  1185.     outb_reg0(dep, DP_RBCR1, ecount >> 8);
  1186.     outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
  1187.     outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
  1188.     outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
  1189.  
  1190.     i= 0;
  1191.     while (count > 0)
  1192.     {
  1193.         if (i >= IOVEC_NR)
  1194.         {
  1195.             dp_next_iovec(iovp);
  1196.             i= 0;
  1197.             continue;
  1198.         }
  1199.         assert(i < iovp->iod_iovec_s);
  1200.         if (offset >= iovp->iod_iovec[i].iov_size)
  1201.         {
  1202.             offset -= iovp->iod_iovec[i].iov_size;
  1203.             i++;
  1204.             continue;
  1205.         }
  1206.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1207.         if (bytes > count)
  1208.             bytes = count;
  1209.  
  1210.         user_proc= iovp->iod_proc_nr;
  1211.         vir_user= iovp->iod_iovec[i].iov_addr + offset;
  1212.         if (odd_byte)
  1213.         {
  1214.             r= sys_vircopy(user_proc, D, vir_user,
  1215.                 SELF, D, (vir_bytes)&two_bytes[1], 1);
  1216.             if (r != OK)
  1217.             {
  1218.                 panic("DP8390",
  1219.                     "dp_pio16_user2nic: sys_vircopy failed",
  1220.                     r);
  1221.             }
  1222.             outw(dep->de_data_port, *(u16_t *)two_bytes);
  1223.             count--;
  1224.             offset++;
  1225.             bytes--;
  1226.             vir_user++;
  1227.             odd_byte= 0;
  1228.             if (!bytes)
  1229.                 continue;
  1230.         }
  1231.         ecount= bytes & ~1;
  1232.         if (ecount != 0)
  1233.         {
  1234.             do_vir_outsw(dep->de_data_port, user_proc, vir_user,
  1235.                 ecount);
  1236.             count -= ecount;
  1237.             offset += ecount;
  1238.             bytes -= ecount;
  1239.             vir_user += ecount;
  1240.         }
  1241.         if (bytes)
  1242.         {
  1243.             assert(bytes == 1);
  1244.             r= sys_vircopy(user_proc, D, vir_user,
  1245.                 SELF, D, (vir_bytes)&two_bytes[0], 1);
  1246.             if (r != OK)
  1247.             {
  1248.                 panic("DP8390",
  1249.                     "dp_pio16_user2nic: sys_vircopy failed",
  1250.                     r);
  1251.             }
  1252.             count--;
  1253.             offset++;
  1254.             bytes--;
  1255.             vir_user++;
  1256.             odd_byte= 1;
  1257.         }
  1258.     }
  1259.     assert(count == 0);
  1260.  
  1261.     if (odd_byte)
  1262.         outw(dep->de_data_port, *(u16_t *)two_bytes);
  1263.  
  1264.     for (i= 0; i<100; i++)
  1265.     {
  1266.         if (inb_reg0(dep, DP_ISR) & ISR_RDC)
  1267.             break;
  1268.     }
  1269.     if (i == 100)
  1270.     {
  1271.         panic("", "dp8390: remote dma failed to complete", NO_NUM);
  1272.     }
  1273. }
  1274.  
  1275. /*===========================================================================*
  1276.  *              dp_nic2user                  *
  1277.  *===========================================================================*/
  1278. static void dp_nic2user(dep, nic_addr, iovp, offset, count)
  1279. dpeth_t *dep;
  1280. int nic_addr;
  1281. iovec_dat_t *iovp;
  1282. vir_bytes offset;
  1283. vir_bytes count;
  1284. {
  1285.     vir_bytes vir_hw;//, vir_user;
  1286.     int bytes, i, r;
  1287.  
  1288.     vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
  1289.  
  1290.     i= 0;
  1291.     while (count > 0)
  1292.     {
  1293.         if (i >= IOVEC_NR)
  1294.         {
  1295.             dp_next_iovec(iovp);
  1296.             i= 0;
  1297.             continue;
  1298.         }
  1299.         assert(i < iovp->iod_iovec_s);
  1300.         if (offset >= iovp->iod_iovec[i].iov_size)
  1301.         {
  1302.             offset -= iovp->iod_iovec[i].iov_size;
  1303.             i++;
  1304.             continue;
  1305.         }
  1306.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1307.         if (bytes > count)
  1308.             bytes = count;
  1309.  
  1310.         r= sys_vircopy(SELF, D, vir_hw,
  1311.             iovp->iod_proc_nr, D,
  1312.             iovp->iod_iovec[i].iov_addr + offset, bytes);
  1313.         if (r != OK)
  1314.             panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
  1315.  
  1316.         count -= bytes;
  1317.         vir_hw += bytes;
  1318.         offset += bytes;
  1319.     }
  1320.     assert(count == 0);
  1321. }
  1322.  
  1323. /*===========================================================================*
  1324.  *              dp_pio8_nic2user                 *
  1325.  *===========================================================================*/
  1326. static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
  1327. dpeth_t *dep;
  1328. int nic_addr;
  1329. iovec_dat_t *iovp;
  1330. vir_bytes offset;
  1331. vir_bytes count;
  1332. {
  1333. //  phys_bytes phys_user;
  1334.     int bytes, i;
  1335.  
  1336.     outb_reg0(dep, DP_RBCR0, count & 0xFF);
  1337.     outb_reg0(dep, DP_RBCR1, count >> 8);
  1338.     outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
  1339.     outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
  1340.     outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  1341.  
  1342.     i= 0;
  1343.     while (count > 0)
  1344.     {
  1345.         if (i >= IOVEC_NR)
  1346.         {
  1347.             dp_next_iovec(iovp);
  1348.             i= 0;
  1349.             continue;
  1350.         }
  1351.         assert(i < iovp->iod_iovec_s);
  1352.         if (offset >= iovp->iod_iovec[i].iov_size)
  1353.         {
  1354.             offset -= iovp->iod_iovec[i].iov_size;
  1355.             i++;
  1356.             continue;
  1357.         }
  1358.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1359.         if (bytes > count)
  1360.             bytes = count;
  1361.  
  1362.         do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
  1363.             iovp->iod_iovec[i].iov_addr + offset, bytes);
  1364.         count -= bytes;
  1365.         offset += bytes;
  1366.     }
  1367.     assert(count == 0);
  1368. }
  1369.  
  1370. /*===========================================================================*
  1371.  *              dp_pio16_nic2user                *
  1372.  *===========================================================================*/
  1373. static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
  1374. dpeth_t *dep;
  1375. int nic_addr;
  1376. iovec_dat_t *iovp;
  1377. vir_bytes offset;
  1378. vir_bytes count;
  1379. {
  1380.     vir_bytes vir_user;
  1381.     vir_bytes ecount;
  1382.     int i, r, bytes, user_proc;
  1383.     u8_t two_bytes[2];
  1384.     int odd_byte;
  1385.  
  1386.     ecount= (count+1) & ~1;
  1387.     odd_byte= 0;
  1388.  
  1389.     outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
  1390.     outb_reg0(dep, DP_RBCR1, ecount >> 8);
  1391.     outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
  1392.     outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
  1393.     outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
  1394.  
  1395.     i= 0;
  1396.     while (count > 0)
  1397.     {
  1398.         if (i >= IOVEC_NR)
  1399.         {
  1400.             dp_next_iovec(iovp);
  1401.             i= 0;
  1402.             continue;
  1403.         }
  1404.         assert(i < iovp->iod_iovec_s);
  1405.         if (offset >= iovp->iod_iovec[i].iov_size)
  1406.         {
  1407.             offset -= iovp->iod_iovec[i].iov_size;
  1408.             i++;
  1409.             continue;
  1410.         }
  1411.         bytes = iovp->iod_iovec[i].iov_size - offset;
  1412.         if (bytes > count)
  1413.             bytes = count;
  1414.  
  1415.         user_proc= iovp->iod_proc_nr;
  1416.         vir_user= iovp->iod_iovec[i].iov_addr + offset;
  1417.         if (odd_byte)
  1418.         {
  1419.             r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
  1420.                 user_proc, D, vir_user,  1);
  1421.             if (r != OK)
  1422.             {
  1423.                 panic("DP8390",
  1424.                     "dp_pio16_nic2user: sys_vircopy failed",
  1425.                     r);
  1426.             }
  1427.             count--;
  1428.             offset++;
  1429.             bytes--;
  1430.             vir_user++;
  1431.             odd_byte= 0;
  1432.             if (!bytes)
  1433.                 continue;
  1434.         }
  1435.         ecount= bytes & ~1;
  1436.         if (ecount != 0)
  1437.         {
  1438.             do_vir_insw(dep->de_data_port, user_proc, vir_user,
  1439.                 ecount);
  1440.             count -= ecount;
  1441.             offset += ecount;
  1442.             bytes -= ecount;
  1443.             vir_user += ecount;
  1444.         }
  1445.         if (bytes)
  1446.         {
  1447.             assert(bytes == 1);
  1448.             *(u16_t *)two_bytes= inw(dep->de_data_port);
  1449.             r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
  1450.                 user_proc, D, vir_user,  1);
  1451.             if (r != OK)
  1452.             {
  1453.                 panic("DP8390",
  1454.                     "dp_pio16_nic2user: sys_vircopy failed",
  1455.                     r);
  1456.             }
  1457.             count--;
  1458.             offset++;
  1459.             bytes--;
  1460.             vir_user++;
  1461.             odd_byte= 1;
  1462.         }
  1463.     }
  1464.     assert(count == 0);
  1465. }
  1466.  
  1467. /*===========================================================================*
  1468.  *              dp_next_iovec                    *
  1469.  *===========================================================================*/
  1470. static void dp_next_iovec(iovp)
  1471. iovec_dat_t *iovp;
  1472. {
  1473.     assert(iovp->iod_iovec_s > IOVEC_NR);
  1474.  
  1475.     iovp->iod_iovec_s -= IOVEC_NR;
  1476.  
  1477.     iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
  1478.  
  1479.     get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr,
  1480.         (iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
  1481.         sizeof(iovec_t), iovp->iod_iovec);
  1482. }
  1483.  
  1484. /*===========================================================================*
  1485.  *              conf_hw                      *
  1486.  *===========================================================================*/
  1487. static void conf_hw(dep)
  1488. dpeth_t *dep;
  1489. {
  1490. //  static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0    /* ,... */ };
  1491.  
  1492. //  int ifnr;
  1493. //  dp_conf_t *dcp;
  1494.  
  1495. //  dep->de_mode= DEM_DISABLED; /* Superfluous */
  1496. //  ifnr= dep-de_table;
  1497.  
  1498. //  dcp= &dp_conf[ifnr];
  1499. //  update_conf(dep, dcp);
  1500. //  if (dep->de_mode != DEM_ENABLED)
  1501. //      return;
  1502.     if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
  1503.     {
  1504.         printf("%s: No ethernet card found at 0x%x\n",
  1505.             dep->de_name, dep->de_base_port);
  1506.         dep->de_mode= DEM_DISABLED;
  1507.         return;
  1508.     }
  1509.  
  1510. /* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
  1511.  
  1512.     dep->de_mode = DEM_ENABLED;
  1513.  
  1514.     dep->de_flags = DEF_EMPTY;
  1515. //  dep->de_stat = empty_stat;
  1516. }
  1517.  
  1518. /*===========================================================================*
  1519.  *              map_hw_buffer                    *
  1520.  *===========================================================================*/
  1521. static void map_hw_buffer(dep)
  1522. dpeth_t *dep;
  1523. {
  1524. //  int r;
  1525. //  size_t o, size;
  1526. //  char *buf, *abuf;
  1527.  
  1528.     if (dep->de_prog_IO)
  1529.     {
  1530. #if 0
  1531.         if(debug){
  1532.             printf(
  1533.             "map_hw_buffer: programmed I/O, no need to map buffer\n");
  1534.         }
  1535. #endif
  1536.         dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
  1537.         return;
  1538.     }else{
  1539.         printf( "map_hw_buffer: no buffer!\n" );
  1540.     }
  1541.  
  1542. //  size = dep->de_ramsize + PAGE_SIZE; /* Add PAGE_SIZE for
  1543. //                       * alignment
  1544. //                       */
  1545. //  buf= malloc(size);
  1546. //  if (buf == NULL)
  1547. //      panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
  1548. //  o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
  1549. //  abuf= buf + o;
  1550. //  printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
  1551.  
  1552. //  r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
  1553. //          dep->de_ramsize, (phys_bytes)dep->de_linmem);
  1554. //  if (r != OK)
  1555. //      panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
  1556. //  dep->de_locmem = abuf;
  1557. }
  1558.  
  1559. /*===========================================================================*
  1560.  *              reply                        *
  1561.  *===========================================================================*/
  1562. static void reply(dep, err, may_block)
  1563. dpeth_t *dep;
  1564. int err;
  1565. int may_block;
  1566. {
  1567. /*  message reply;
  1568.     int status;
  1569.     int r;
  1570.  
  1571.     status = 0;
  1572.     if (dep->de_flags & DEF_PACK_SEND)
  1573.         status |= DL_PACK_SEND;
  1574.     if (dep->de_flags & DEF_PACK_RECV)
  1575.         status |= DL_PACK_RECV;
  1576.  
  1577.     reply.m_type = DL_TASK_REPLY;
  1578.     reply.DL_PORT = dep - de_table;
  1579.     reply.DL_PROC = dep->de_client;
  1580.     reply.DL_STAT = status | ((u32_t) err << 16);
  1581.     reply.DL_COUNT = dep->de_read_s;
  1582.     reply.DL_CLCK = 0;  *//* Don't know */
  1583. /*  r= send(dep->de_client, &reply);
  1584.  
  1585.     if (r == ELOCKED && may_block)
  1586.     {
  1587. #if 0
  1588.         printf("send locked\n");
  1589. #endif
  1590.         return;
  1591.     }
  1592.  
  1593.     if (r < 0)
  1594.         panic("", "dp8390: send failed:", r);
  1595.    
  1596. */  dep->de_read_s = 0;
  1597. //  dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
  1598. }
  1599.  
  1600. /*===========================================================================*
  1601.  *              get_userdata                     *
  1602.  *===========================================================================*/
  1603. static void get_userdata(user_proc, user_addr, count, loc_addr)
  1604. int user_proc;
  1605. vir_bytes user_addr;
  1606. vir_bytes count;
  1607. void *loc_addr;
  1608. {
  1609.     int r;
  1610.  
  1611.     r= sys_vircopy(user_proc, D, user_addr,
  1612.         SELF, D, (vir_bytes)loc_addr, count);
  1613.     if (r != OK)
  1614.         panic("DP8390", "get_userdata: sys_vircopy failed", r);
  1615. }
  1616.  
  1617. static void insb(port_t port, void *buf, size_t size)
  1618. {
  1619.     size_t i;
  1620.  
  1621.     for( i = 0; i < size; ++ i ){
  1622.         *(( uint8_t * ) buf + i ) = inb( port );
  1623.     }
  1624. }
  1625.  
  1626. static void insw(port_t port, void *buf, size_t size)
  1627. {
  1628.     size_t i;
  1629.  
  1630.     for( i = 0; i * 2 < size; ++ i ){
  1631.         *(( uint16_t * ) buf + i ) = inw( port );
  1632.     }
  1633. }
  1634.  
  1635. static void outsb(port_t port, void *buf, size_t size)
  1636. {
  1637.     size_t i;
  1638.  
  1639.     for( i = 0; i < size; ++ i ){
  1640.         outb( port, *(( uint8_t * ) buf + i ));
  1641.     }
  1642. }
  1643.  
  1644. static void outsw(port_t port, void *buf, size_t size)
  1645. {
  1646.     size_t i;
  1647.  
  1648.     for( i = 0; i * 2 < size; ++ i ){
  1649.         outw( port, *(( uint16_t * ) buf + i ));
  1650.     }
  1651. }
  1652.  
  1653. /*
  1654.  * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
  1655.  */
  1656.  
  1657. /** @}
  1658.  */
  1659.