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


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

FreeBSD/Linux Kernel Cross Reference
sys/servers/inet/mnx_eth.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2 inet/mnx_eth.c
    3 
    4 Created:        Jan 2, 1992 by Philip Homburg
    5 
    6 Copyright 1995 Philip Homburg
    7 */
    8 
    9 #include "inet.h"
   10 #include "proto.h"
   11 #include "osdep_eth.h"
   12 #include "generic/type.h"
   13 
   14 #include "generic/assert.h"
   15 #include "generic/buf.h"
   16 #include "generic/clock.h"
   17 #include "generic/eth.h"
   18 #include "generic/eth_int.h"
   19 #include "generic/sr.h"
   20 
   21 THIS_FILE
   22 
   23 static int recv_debug= 0;
   24 
   25 FORWARD _PROTOTYPE( void setup_read, (eth_port_t *eth_port) );
   26 FORWARD _PROTOTYPE( void read_int, (eth_port_t *eth_port, int count) );
   27 FORWARD _PROTOTYPE( void write_int, (eth_port_t *eth_port) );
   28 FORWARD _PROTOTYPE( void eth_recvev, (event_t *ev, ev_arg_t ev_arg) );
   29 FORWARD _PROTOTYPE( void eth_sendev, (event_t *ev, ev_arg_t ev_arg) );
   30 FORWARD _PROTOTYPE( eth_port_t *find_port, (message *m) );
   31 FORWARD _PROTOTYPE( void eth_restart, (eth_port_t *eth_port, int tasknr) );
   32 
   33 PUBLIC void osdep_eth_init()
   34 {
   35         int i, r, tasknr, rport;
   36         struct eth_conf *ecp;
   37         eth_port_t *eth_port, *rep;
   38         message mess;
   39 
   40         /* First initialize normal ethernet interfaces */
   41         for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
   42                 i<eth_conf_nr; i++, ecp++, eth_port++)
   43         {
   44                 if (eth_is_vlan(ecp))
   45                         continue;
   46 #ifdef __minix_vmd
   47                 r= sys_findproc(ecp->ec_task, &tasknr, 0);
   48 #else /* Minix 3 */
   49                 r = findproc(ecp->ec_task, &tasknr);
   50 #endif 
   51                 if (r != OK)
   52                 {
   53                         printf("eth%d: unable to find task %s: %d\n",
   54                                 i, ecp->ec_task, r);
   55                         continue;
   56                 }
   57 
   58                 eth_port->etp_osdep.etp_port= ecp->ec_port;
   59                 eth_port->etp_osdep.etp_task= tasknr;
   60                 ev_init(&eth_port->etp_osdep.etp_recvev);
   61 
   62                 mess.m_type= DL_INIT;
   63                 mess.DL_PORT= eth_port->etp_osdep.etp_port;
   64                 mess.DL_PROC= this_proc;
   65                 mess.DL_MODE= DL_NOMODE;
   66 
   67                 r= send(eth_port->etp_osdep.etp_task, &mess);
   68                 if (r<0)
   69                 {
   70                         printf(
   71                 "osdep_eth_init: unable to send to ethernet task, error= %d\n",
   72                                 r);
   73                         continue;
   74                 }
   75 
   76                 r= receive(eth_port->etp_osdep.etp_task, &mess);
   77                 if (r<0)
   78                 {
   79                         printf(
   80         "osdep_eth_init: unable to receive from ethernet task, error= %d\n",
   81                                 r);
   82                         continue;
   83                 }
   84 
   85                 if (mess.m3_i1 == ENXIO)
   86                 {
   87                         printf(
   88                 "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
   89                                 eth_port->etp_osdep.etp_task, 
   90                                 eth_port->etp_osdep.etp_port);
   91                         continue;
   92                 }
   93                 if (mess.m3_i1 < 0)
   94                         ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
   95                                 mess.m3_i1));
   96                         
   97                 if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
   98                 {
   99                         ip_panic((
  100         "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
  101                                 mess.m3_i1, eth_port->etp_osdep.etp_port));
  102                 }
  103 
  104                 eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
  105 
  106                 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
  107                         i, eth_open, eth_close, eth_read, 
  108                         eth_write, eth_ioctl, eth_cancel, eth_select);
  109 
  110                 eth_port->etp_flags |= EPF_ENABLED;
  111                 eth_port->etp_vlan= 0;
  112                 eth_port->etp_vlan_port= NULL;
  113                 eth_port->etp_wr_pack= 0;
  114                 eth_port->etp_rd_pack= 0;
  115                 setup_read (eth_port);
  116         }
  117 
  118         /* And now come the VLANs */
  119         for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
  120                 i<eth_conf_nr; i++, ecp++, eth_port++)
  121         {
  122                 if (!eth_is_vlan(ecp))
  123                         continue;
  124 
  125                 eth_port->etp_osdep.etp_port= ecp->ec_port;
  126                 eth_port->etp_osdep.etp_task= ANY;
  127                 ev_init(&eth_port->etp_osdep.etp_recvev);
  128 
  129                 rport= eth_port->etp_osdep.etp_port;
  130                 assert(rport >= 0 && rport < eth_conf_nr);
  131                 rep= &eth_port_table[rport];
  132                 if (!(rep->etp_flags & EPF_ENABLED))
  133                 {
  134                         printf(
  135                         "eth%d: underlying ethernet device %d not enabled",
  136                                 i, rport);
  137                         continue;
  138                 }
  139                 if (rep->etp_vlan != 0)
  140                 {
  141                         printf(
  142                         "eth%d: underlying ethernet device %d is a VLAN",
  143                                 i, rport);
  144                         continue;
  145                 }
  146                 
  147                 eth_port->etp_ethaddr= rep->etp_ethaddr;
  148 
  149                 sr_add_minor(if2minor(ecp->ec_ifno, ETH_DEV_OFF),
  150                         i, eth_open, eth_close, eth_read, 
  151                         eth_write, eth_ioctl, eth_cancel, eth_select);
  152 
  153                 eth_port->etp_flags |= EPF_ENABLED;
  154                 eth_port->etp_vlan= ecp->ec_vlan;
  155                 eth_port->etp_vlan_port= rep;
  156                 assert(eth_port->etp_vlan != 0);
  157                 eth_port->etp_wr_pack= 0;
  158                 eth_port->etp_rd_pack= 0;
  159                 eth_reg_vlan(rep, eth_port);
  160         }
  161 }
  162 
  163 PUBLIC void eth_write_port(eth_port, pack)
  164 eth_port_t *eth_port;
  165 acc_t *pack;
  166 {
  167         eth_port_t *loc_port;
  168         message mess1, block_msg;
  169         int i, pack_size;
  170         acc_t *pack_ptr;
  171         iovec_t *iovec;
  172         u8_t *eth_dst_ptr;
  173         int multicast, r;
  174         ev_arg_t ev_arg;
  175 
  176         assert(!no_ethWritePort);
  177         assert(!eth_port->etp_vlan);
  178 
  179         assert(eth_port->etp_wr_pack == NULL);
  180         eth_port->etp_wr_pack= pack;
  181 
  182         iovec= eth_port->etp_osdep.etp_wr_iovec;
  183         pack_size= 0;
  184         for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr; i++,
  185                 pack_ptr= pack_ptr->acc_next)
  186         {
  187                 iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
  188                 pack_size += iovec[i].iov_size= pack_ptr->acc_length;
  189         }
  190         if (i>= IOVEC_NR)
  191         {
  192                 pack= bf_pack(pack);            /* packet is too fragmented */
  193                 eth_port->etp_wr_pack= pack;
  194                 pack_size= 0;
  195                 for (i=0, pack_ptr= pack; i<IOVEC_NR && pack_ptr;
  196                         i++, pack_ptr= pack_ptr->acc_next)
  197                 {
  198                         iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
  199                         pack_size += iovec[i].iov_size= pack_ptr->acc_length;
  200                 }
  201         }
  202         assert (i< IOVEC_NR);
  203         assert (pack_size >= ETH_MIN_PACK_SIZE);
  204 
  205         if (i == 1)
  206         {
  207                 /* simple packets can be sent using DL_WRITE instead of 
  208                  * DL_WRITEV.
  209                  */
  210                 mess1.DL_COUNT= iovec[0].iov_size;
  211                 mess1.DL_ADDR= (char *)iovec[0].iov_addr;
  212                 mess1.m_type= DL_WRITE;
  213         }
  214         else
  215         {
  216                 mess1.DL_COUNT= i;
  217                 mess1.DL_ADDR= (char *)iovec;
  218                 mess1.m_type= DL_WRITEV;
  219         }
  220         mess1.DL_PORT= eth_port->etp_osdep.etp_port;
  221         mess1.DL_PROC= this_proc;
  222         mess1.DL_MODE= DL_NOMODE;
  223 
  224         for (;;)
  225         {
  226                 r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
  227                 if (r != ELOCKED)
  228                         break;
  229 
  230                 /* ethernet task is sending to this task, I hope */
  231                 r= receive(eth_port->etp_osdep.etp_task, &block_msg);
  232                 if (r < 0)
  233                         ip_panic(("unable to receive"));
  234 
  235                 loc_port= eth_port;
  236                 if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
  237                         loc_port->etp_osdep.etp_task != block_msg.m_source)
  238                 {
  239                         loc_port= find_port(&block_msg);
  240                 }
  241                 assert(block_msg.DL_STAT & (DL_PACK_SEND|DL_PACK_RECV));
  242                 if (block_msg.DL_STAT & DL_PACK_SEND)
  243                 {
  244                         assert(loc_port != eth_port);
  245                         loc_port->etp_osdep.etp_sendrepl= block_msg;
  246                         ev_arg.ev_ptr= loc_port;
  247                         ev_enqueue(&loc_port->etp_sendev, eth_sendev, ev_arg);
  248                 }
  249                 if (block_msg.DL_STAT & DL_PACK_RECV)
  250                 {
  251                         if (recv_debug)
  252                         {
  253                                 printf(
  254                         "eth_write_port(block_msg): eth%d got DL_PACK_RECV\n",
  255                                         loc_port-eth_port_table);
  256                         }
  257                         loc_port->etp_osdep.etp_recvrepl= block_msg;
  258                         ev_arg.ev_ptr= loc_port;
  259                         ev_enqueue(&loc_port->etp_osdep.etp_recvev,
  260                                 eth_recvev, ev_arg);
  261                 }
  262         }
  263 
  264         if (r < 0)
  265         {
  266                 printf("eth_write_port: sendrec to %d failed: %d\n",
  267                         eth_port->etp_osdep.etp_task, r);
  268                 return;
  269         }
  270 
  271         assert(mess1.m_type == DL_TASK_REPLY &&
  272                 mess1.DL_PORT == eth_port->etp_osdep.etp_port &&
  273                 mess1.DL_PROC == this_proc);
  274         assert((mess1.DL_STAT >> 16) == OK);
  275 
  276         if (mess1.DL_STAT & DL_PACK_RECV)
  277         {
  278                 if (recv_debug)
  279                 {
  280                         printf(
  281                         "eth_write_port(mess1): eth%d got DL_PACK_RECV\n",
  282                                 mess1.DL_PORT);
  283                 }
  284                 eth_port->etp_osdep.etp_recvrepl= mess1;
  285                 ev_arg.ev_ptr= eth_port;
  286                 ev_enqueue(&eth_port->etp_osdep.etp_recvev, eth_recvev,
  287                         ev_arg);
  288         }
  289         if (!(mess1.DL_STAT & DL_PACK_SEND))
  290         {
  291                 /* Packet is not yet sent. */
  292                 return;
  293         }
  294 
  295         /* If the port is in promiscuous mode or the packet is
  296          * broad- or multicast, enqueue the reply packet.
  297          */
  298         eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
  299         multicast= (*eth_dst_ptr & 1);  /* low order bit indicates multicast */
  300         if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
  301         {
  302                 eth_port->etp_osdep.etp_sendrepl= mess1;
  303                 ev_arg.ev_ptr= eth_port;
  304                 ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
  305 
  306                 /* Pretend that we didn't get a reply. */
  307                 return;
  308         }
  309 
  310         /* packet is sent */
  311         bf_afree(eth_port->etp_wr_pack);
  312         eth_port->etp_wr_pack= NULL;
  313 }
  314 
  315 PUBLIC void eth_rec(m)
  316 message *m;
  317 {
  318         int i;
  319         eth_port_t *loc_port;
  320         int stat;
  321 
  322         assert(m->m_type == DL_TASK_REPLY);
  323 
  324         set_time (m->DL_CLCK);
  325 
  326         for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
  327         {
  328                 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
  329                         loc_port->etp_osdep.etp_task == m->m_source)
  330                         break;
  331         }
  332         if (i == eth_conf_nr)
  333         {
  334                 ip_panic(("message from unknown source: %d:%d",
  335                         m->m_source, m->DL_PORT));
  336         }
  337 
  338         stat= m->DL_STAT & 0xffff;
  339 
  340         assert(stat & (DL_PACK_SEND|DL_PACK_RECV));
  341         if (stat & DL_PACK_SEND)
  342                 write_int(loc_port);
  343         if (stat & DL_PACK_RECV)
  344         {
  345                 if (recv_debug)
  346                 {
  347                         printf("eth_rec: eth%d got DL_PACK_RECV\n",
  348                                 m->DL_PORT);
  349                 }
  350                 read_int(loc_port, m->DL_COUNT);
  351         }
  352 }
  353 
  354 PUBLIC void eth_check_drivers(m)
  355 message *m;
  356 {
  357         int i, r, tasknr;
  358         struct eth_conf *ecp;
  359         eth_port_t *eth_port;
  360         char *drivername;
  361 
  362         tasknr= m->m_source;
  363         printf("eth_check_drivers: got a notification from %d\n", tasknr);
  364 
  365         m->m_type= DL_GETNAME;
  366         r= sendrec(tasknr, m);
  367         if (r != OK)
  368         {
  369                 printf("eth_check_drivers: sendrec to %d failed: %d\n",
  370                         tasknr, r);
  371                 return;
  372         }
  373         if (m->m_type != DL_NAME_REPLY)
  374         {
  375                 printf(
  376                 "eth_check_drivers: got bad getname reply (%d) from %d\n",
  377                         m->m_type, tasknr);
  378                 return;
  379         }
  380 
  381         drivername= m->m3_ca1;
  382         printf("eth_check_drivers: got name: %s\n", drivername);
  383 
  384         /* Re-init ethernet interfaces */
  385         for (i= 0, ecp= eth_conf, eth_port= eth_port_table;
  386                 i<eth_conf_nr; i++, ecp++, eth_port++)
  387         {
  388                 if (eth_is_vlan(ecp))
  389                         continue;
  390 
  391                 if (strcmp(ecp->ec_task, drivername) != 0)
  392                 {
  393                         /* Wrong driver */
  394                         continue;
  395                 }
  396 
  397                 eth_restart(eth_port, tasknr);
  398         }
  399 }
  400 
  401 PUBLIC int eth_get_stat(eth_port, eth_stat)
  402 eth_port_t *eth_port;
  403 eth_stat_t *eth_stat;
  404 {
  405         int r;
  406         message mess, mlocked;
  407 
  408         assert(!eth_port->etp_vlan);
  409 
  410         mess.m_type= DL_GETSTAT;
  411         mess.DL_PORT= eth_port->etp_osdep.etp_port;
  412         mess.DL_PROC= this_proc;
  413         mess.DL_ADDR= (char *)eth_stat;
  414 
  415         for (;;)
  416         {
  417                 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
  418                 if (r != ELOCKED)
  419                         break;
  420 
  421                 r= receive(eth_port->etp_osdep.etp_task, &mlocked);
  422                 assert(r == OK);
  423 
  424                 compare(mlocked.m_type, ==, DL_TASK_REPLY);
  425                 eth_rec(&mlocked);
  426         }
  427 
  428         if (r != OK)
  429         {
  430                 printf("eth_get_stat: sendrec to %d failed: %d\n",
  431                         eth_port->etp_osdep.etp_task, r);
  432                 return EIO;
  433         }
  434 
  435         assert(mess.m_type == DL_TASK_REPLY);
  436 
  437         r= mess.DL_STAT >> 16;
  438         assert (r == 0);
  439 
  440         if (mess.DL_STAT)
  441         {
  442                 eth_rec(&mess);
  443         }
  444         return OK;
  445 }
  446 
  447 PUBLIC void eth_set_rec_conf (eth_port, flags)
  448 eth_port_t *eth_port;
  449 u32_t flags;
  450 {
  451         int r;
  452         unsigned dl_flags;
  453         message mess, repl_mess;
  454 
  455         assert(!eth_port->etp_vlan);
  456 
  457         eth_port->etp_osdep.etp_recvconf= flags;
  458         dl_flags= DL_NOMODE;
  459         if (flags & NWEO_EN_BROAD)
  460                 dl_flags |= DL_BROAD_REQ;
  461         if (flags & NWEO_EN_MULTI)
  462                 dl_flags |= DL_MULTI_REQ;
  463         if (flags & NWEO_EN_PROMISC)
  464                 dl_flags |= DL_PROMISC_REQ;
  465 
  466         mess.m_type= DL_INIT;
  467         mess.DL_PORT= eth_port->etp_osdep.etp_port;
  468         mess.DL_PROC= this_proc;
  469         mess.DL_MODE= dl_flags;
  470 
  471         do
  472         {
  473                 r= sendrec(eth_port->etp_osdep.etp_task, &mess);
  474                 if (r == ELOCKED)       /* etp_task is sending to this task,
  475                                            I hope */
  476                 {
  477                         if (receive (eth_port->etp_osdep.etp_task, 
  478                                 &repl_mess)< 0)
  479                         {
  480                                 ip_panic(("unable to receive"));
  481                         }
  482 
  483                         compare(repl_mess.m_type, ==, DL_TASK_REPLY);
  484                         eth_rec(&repl_mess);
  485                 }
  486         } while (r == ELOCKED);
  487         
  488         if (r < 0)
  489         {
  490                 printf("eth_set_rec_conf: sendrec to %d failed: %d\n",
  491                         eth_port->etp_osdep.etp_task, r);
  492                 return;
  493         }
  494 
  495         assert (mess.m_type == DL_INIT_REPLY);
  496         if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
  497         {
  498                 ip_panic(("got reply for wrong port"));
  499         }
  500 }
  501 
  502 PRIVATE void write_int(eth_port)
  503 eth_port_t *eth_port;
  504 {
  505         acc_t *pack;
  506         int multicast;
  507         u8_t *eth_dst_ptr;
  508 
  509         pack= eth_port->etp_wr_pack;
  510         eth_port->etp_wr_pack= NULL;
  511 
  512         eth_dst_ptr= (u8_t *)ptr2acc_data(pack);
  513         multicast= (*eth_dst_ptr & 1);  /* low order bit indicates multicast */
  514         if (multicast || (eth_port->etp_osdep.etp_recvconf & NWEO_EN_PROMISC))
  515         {
  516                 assert(!no_ethWritePort);
  517                 no_ethWritePort= 1;
  518                 eth_arrive(eth_port, pack, bf_bufsize(pack));
  519                 assert(no_ethWritePort);
  520                 no_ethWritePort= 0;
  521         }
  522         else
  523                 bf_afree(pack);
  524 
  525         eth_restart_write(eth_port);
  526 }
  527 
  528 PRIVATE void read_int(eth_port, count)
  529 eth_port_t *eth_port;
  530 int count;
  531 {
  532         acc_t *pack, *cut_pack;
  533 
  534         pack= eth_port->etp_rd_pack;
  535         eth_port->etp_rd_pack= NULL;
  536 
  537         cut_pack= bf_cut(pack, 0, count);
  538         bf_afree(pack);
  539 
  540         assert(!no_ethWritePort);
  541         no_ethWritePort= 1;
  542         eth_arrive(eth_port, cut_pack, count);
  543         assert(no_ethWritePort);
  544         no_ethWritePort= 0;
  545         
  546         eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
  547         setup_read(eth_port);
  548 }
  549 
  550 PRIVATE void setup_read(eth_port)
  551 eth_port_t *eth_port;
  552 {
  553         eth_port_t *loc_port;
  554         acc_t *pack, *pack_ptr;
  555         message mess1, block_msg;
  556         iovec_t *iovec;
  557         ev_arg_t ev_arg;
  558         int i, r;
  559 
  560         assert(!eth_port->etp_vlan);
  561         assert(!(eth_port->etp_flags & (EPF_READ_IP|EPF_READ_SP)));
  562 
  563         do
  564         {
  565                 assert (!eth_port->etp_rd_pack);
  566 
  567                 iovec= eth_port->etp_osdep.etp_rd_iovec;
  568                 pack= bf_memreq (ETH_MAX_PACK_SIZE_TAGGED);
  569 
  570                 for (i=0, pack_ptr= pack; i<RD_IOVEC && pack_ptr;
  571                         i++, pack_ptr= pack_ptr->acc_next)
  572                 {
  573                         iovec[i].iov_addr= (vir_bytes)ptr2acc_data(pack_ptr);
  574                         iovec[i].iov_size= (vir_bytes)pack_ptr->acc_length;
  575                 }
  576                 assert (!pack_ptr);
  577 
  578                 mess1.m_type= DL_READV;
  579                 mess1.DL_PORT= eth_port->etp_osdep.etp_port;
  580                 mess1.DL_PROC= this_proc;
  581                 mess1.DL_COUNT= i;
  582                 mess1.DL_ADDR= (char *)iovec;
  583 
  584                 for (;;)
  585                 {
  586                         if (recv_debug)
  587                         {
  588                                 printf("eth%d: sending DL_READV\n",
  589                                         mess1.DL_PORT);
  590                         }
  591                         r= sendrec(eth_port->etp_osdep.etp_task, &mess1);
  592                         if (r != ELOCKED)
  593                                 break;
  594 
  595                         /* ethernet task is sending to this task, I hope */
  596                         r= receive(eth_port->etp_osdep.etp_task, &block_msg);
  597                         if (r < 0)
  598                                 ip_panic(("unable to receive"));
  599 
  600                         loc_port= eth_port;
  601                         if (loc_port->etp_osdep.etp_port != block_msg.DL_PORT ||
  602                                 loc_port->etp_osdep.etp_task !=
  603                                 block_msg.m_source)
  604                         {
  605                                 loc_port= find_port(&block_msg);
  606                         }
  607                         assert(block_msg.DL_STAT &
  608                                 (DL_PACK_SEND|DL_PACK_RECV));
  609                         if (block_msg.DL_STAT & DL_PACK_SEND)
  610                         {
  611                                 loc_port->etp_osdep.etp_sendrepl= block_msg;
  612                                 ev_arg.ev_ptr= loc_port;
  613                                 ev_enqueue(&loc_port->etp_sendev, eth_sendev,
  614                                         ev_arg);
  615                         }
  616                         if (block_msg.DL_STAT & DL_PACK_RECV)
  617                         {
  618                                 if (recv_debug)
  619                                 {
  620                                         printf(
  621                         "setup_read(block_msg): eth%d got DL_PACK_RECV\n",
  622                                                 block_msg.DL_PORT);
  623                                 }
  624                                 assert(loc_port != eth_port);
  625                                 loc_port->etp_osdep.etp_recvrepl= block_msg;
  626                                 ev_arg.ev_ptr= loc_port;
  627                                 ev_enqueue(&loc_port->etp_osdep.etp_recvev,
  628                                         eth_recvev, ev_arg);
  629                         }
  630                 }
  631 
  632                 if (r < 0)
  633                 {
  634                         printf("mnx_eth`setup_read: sendrec to %d failed: %d\n",
  635                                 eth_port->etp_osdep.etp_task, r);
  636                         eth_port->etp_rd_pack= pack;
  637                         eth_port->etp_flags |= EPF_READ_IP;
  638                         continue;
  639                 }
  640 
  641                 assert (mess1.m_type == DL_TASK_REPLY &&
  642                         mess1.DL_PORT == mess1.DL_PORT &&
  643                         mess1.DL_PROC == this_proc);
  644                 compare((mess1.DL_STAT >> 16), ==, OK);
  645 
  646                 if (mess1.DL_STAT & DL_PACK_RECV)
  647                 {
  648                         if (recv_debug)
  649                         {
  650                                 printf(
  651                         "setup_read(mess1): eth%d: got DL_PACK_RECV\n",
  652                                         mess1.DL_PORT);
  653                         }
  654                         /* packet received */
  655                         pack_ptr= bf_cut(pack, 0, mess1.DL_COUNT);
  656                         bf_afree(pack);
  657 
  658                         assert(!no_ethWritePort);
  659                         no_ethWritePort= 1;
  660                         eth_arrive(eth_port, pack_ptr, mess1.DL_COUNT);
  661                         assert(no_ethWritePort);
  662                         no_ethWritePort= 0;
  663                 }
  664                 else
  665                 {
  666                         /* no packet received */
  667                         eth_port->etp_rd_pack= pack;
  668                         eth_port->etp_flags |= EPF_READ_IP;
  669                 }
  670 
  671                 if (mess1.DL_STAT & DL_PACK_SEND)
  672                 {
  673                         eth_port->etp_osdep.etp_sendrepl= mess1;
  674                         ev_arg.ev_ptr= eth_port;
  675                         ev_enqueue(&eth_port->etp_sendev, eth_sendev, ev_arg);
  676                 }
  677         } while (!(eth_port->etp_flags & EPF_READ_IP));
  678         eth_port->etp_flags |= EPF_READ_SP;
  679 }
  680 
  681 PRIVATE void eth_recvev(ev, ev_arg)
  682 event_t *ev;
  683 ev_arg_t ev_arg;
  684 {
  685         eth_port_t *eth_port;
  686         message *m_ptr;
  687 
  688         eth_port= ev_arg.ev_ptr;
  689         assert(ev == &eth_port->etp_osdep.etp_recvev);
  690         m_ptr= &eth_port->etp_osdep.etp_recvrepl;
  691 
  692         assert(m_ptr->m_type == DL_TASK_REPLY);
  693         assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
  694                 eth_port->etp_osdep.etp_task == m_ptr->m_source);
  695 
  696         assert(m_ptr->DL_STAT & DL_PACK_RECV);
  697         m_ptr->DL_STAT &= ~DL_PACK_RECV;
  698 
  699         if (recv_debug)
  700         {
  701                 printf("eth_recvev: eth%d got DL_PACK_RECV\n", m_ptr->DL_PORT);
  702         }
  703 
  704         read_int(eth_port, m_ptr->DL_COUNT);
  705 }
  706 
  707 PRIVATE void eth_sendev(ev, ev_arg)
  708 event_t *ev;
  709 ev_arg_t ev_arg;
  710 {
  711         eth_port_t *eth_port;
  712         message *m_ptr;
  713 
  714         eth_port= ev_arg.ev_ptr;
  715         assert(ev == &eth_port->etp_sendev);
  716         m_ptr= &eth_port->etp_osdep.etp_sendrepl;
  717 
  718         assert (m_ptr->m_type == DL_TASK_REPLY);
  719         assert(eth_port->etp_osdep.etp_port == m_ptr->DL_PORT &&
  720                 eth_port->etp_osdep.etp_task == m_ptr->m_source);
  721 
  722         assert(m_ptr->DL_STAT & DL_PACK_SEND);
  723         m_ptr->DL_STAT &= ~DL_PACK_SEND;
  724 
  725         /* packet is sent */
  726         write_int(eth_port);
  727 }
  728 
  729 PRIVATE eth_port_t *find_port(m)
  730 message *m;
  731 {
  732         eth_port_t *loc_port;
  733         int i;
  734 
  735         for (i=0, loc_port= eth_port_table; i<eth_conf_nr; i++, loc_port++)
  736         {
  737                 if (loc_port->etp_osdep.etp_port == m->DL_PORT &&
  738                         loc_port->etp_osdep.etp_task == m->m_source)
  739                         break;
  740         }
  741         assert (i<eth_conf_nr);
  742         return loc_port;
  743 }
  744 
  745 static void eth_restart(eth_port, tasknr)
  746 eth_port_t *eth_port;
  747 int tasknr;
  748 {
  749         int r;
  750         unsigned flags, dl_flags;
  751         message mess;
  752 #if 0
  753         int i, r, rport;
  754         struct eth_conf *ecp;
  755         eth_port_t *rep;
  756 #endif
  757 
  758         printf("eth_restart: restarting eth%d, task %d, port %d\n",
  759                 eth_port-eth_port_table, tasknr,
  760                 eth_port->etp_osdep.etp_port);
  761 
  762         eth_port->etp_osdep.etp_task= tasknr;
  763 
  764         flags= eth_port->etp_osdep.etp_recvconf;
  765         dl_flags= DL_NOMODE;
  766         if (flags & NWEO_EN_BROAD)
  767                 dl_flags |= DL_BROAD_REQ;
  768         if (flags & NWEO_EN_MULTI)
  769                 dl_flags |= DL_MULTI_REQ;
  770         if (flags & NWEO_EN_PROMISC)
  771                 dl_flags |= DL_PROMISC_REQ;
  772         mess.m_type= DL_INIT;
  773         mess.DL_PORT= eth_port->etp_osdep.etp_port;
  774         mess.DL_PROC= this_proc;
  775         mess.DL_MODE= dl_flags;
  776 
  777         r= sendrec(eth_port->etp_osdep.etp_task, &mess);
  778         /* YYY */
  779         if (r<0)
  780         {
  781                 printf(
  782         "eth_restart: sendrec to ethernet task %d failed: %d\n",
  783                         eth_port->etp_osdep.etp_task, r);
  784                 return;
  785         }
  786 
  787         if (mess.m3_i1 == ENXIO)
  788         {
  789                 printf(
  790         "osdep_eth_init: no ethernet device at task=%d,port=%d\n",
  791                         eth_port->etp_osdep.etp_task, 
  792                         eth_port->etp_osdep.etp_port);
  793                 return;
  794         }
  795         if (mess.m3_i1 < 0)
  796                 ip_panic(("osdep_eth_init: DL_INIT returned error %d\n",
  797                         mess.m3_i1));
  798                 
  799         if (mess.m3_i1 != eth_port->etp_osdep.etp_port)
  800         {
  801                 ip_panic((
  802 "osdep_eth_init: got reply for wrong port (got %d, expected %d)\n",
  803                         mess.m3_i1, eth_port->etp_osdep.etp_port));
  804         }
  805 
  806         eth_port->etp_ethaddr= *(ether_addr_t *)mess.m3_ca1;
  807 
  808         eth_port->etp_flags |= EPF_ENABLED;
  809         if (eth_port->etp_wr_pack)
  810         {
  811                 bf_afree(eth_port->etp_wr_pack);
  812                 eth_port->etp_wr_pack= NULL;
  813                 eth_restart_write(eth_port);
  814         }
  815         if (eth_port->etp_rd_pack)
  816         {
  817                 bf_afree(eth_port->etp_rd_pack);
  818                 eth_port->etp_rd_pack= NULL;
  819                 eth_port->etp_flags &= ~(EPF_READ_IP|EPF_READ_SP);
  820         }
  821         setup_read (eth_port);
  822 }
  823 
  824 /*
  825  * $PchId: mnx_eth.c,v 1.16 2005/06/28 14:24:37 philip Exp $
  826  */

Cache object: 2bad5a9c9779eb14fd2c5c0f05710cf1


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


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.