openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

eth_drv.c (10769B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  */
      7 #include "eth_drv.h"
      8 
      9 #define ETH_DRV_MAX_BUF_LEN     2048
     10 
     11 #if defined(VXWORKS) && (VX_VERSION > 54) && !defined(ICS)
     12 
     13 #ifdef ETH_DRV_SUPPORTED
     14 #error "ethernet driver redefined for VxWorks"
     15 #endif /* ETH_DRV_SUPPORTED */
     16 #define ETH_DRV_SUPPORTED       1
     17 
     18 #define ETH_DRV_THREAD_POLLING  0
     19 
     20 #include <sys/types.h>
     21 #if VX_VERSION == 69
     22 #include <types/vxWind.h>
     23 #endif
     24 #include <string.h>
     25 #include <stdlib.h>
     26 #include <signal.h>
     27 
     28 #include <vxWorks.h>
     29 #include <taskLib.h>
     30 #include <tickLib.h>
     31 #include <stdlib.h>
     32 #include <stdio.h>
     33 #include "mux_drv.h"
     34 
     35 typedef struct eth_unit_info_s {
     36     int         inited;
     37     rx_cb       rx_cb;
     38     void        *cookie;
     39     int         started;
     40 } eth_unit_info_t;
     41 
     42 #ifdef MBZ
     43 #define ETH_TX_DEVICE_NAME "et"
     44 #else
     45 #ifdef BMW
     46 #define ETH_TX_DEVICE_NAME "bc"
     47 #else
     48 #ifdef MPC8548
     49 #define ETH_TX_DEVICE_NAME "motetsec"
     50 #else
     51 #define ETH_TX_DEVICE_NAME "unknown"
     52 #endif
     53 #endif
     54 #endif
     55 
     56 static eth_unit_info_t  *eth_control[ETH_MAX_UNITS];
     57 
     58 static void _eth_drv_handle_rx(int unit, void *pkt, int pkt_len);
     59 
     60 static int _eth_drv_init(int unit)
     61 {
     62     if (eth_control[unit]) {
     63         return 0;
     64     }
     65 
     66     eth_control[unit] = malloc(sizeof(eth_unit_info_t));
     67     memset(eth_control[unit], 0, sizeof(eth_unit_info_t));
     68 
     69     if (et_drvTxRxInit(ETH_TX_DEVICE_NAME, unit)) {
     70         free(eth_control[unit]);
     71         eth_control[unit] = NULL;
     72         return -1;
     73     }
     74     eth_control[unit]->inited++;
     75     return 0;
     76 }
     77 
     78 static int
     79 _eth_drv_rx_thread(void *p)
     80 {
     81     int    unit = (int)p, plen;
     82     unsigned char * rx_pkt;
     83 
     84     if ((rx_pkt = malloc(ETH_DRV_MAX_BUF_LEN)) == NULL) {
     85         return -1;
     86     }
     87     et_drv_start(unit);
     88     while (eth_control[unit]->started) {
     89         et_drv_mii_rx(unit, rx_pkt, &plen);
     90         if (plen) {
     91             _eth_drv_handle_rx(unit, rx_pkt, plen);
     92         } else {
     93             taskDelay(10);
     94         }
     95     }
     96 
     97     if (rx_pkt) {
     98         free(rx_pkt);
     99     }
    100     return 0;
    101 }
    102 
    103 static int
    104 _eth_drv_start(int unit)
    105 {
    106     sigset_t	new_mask, orig_mask;
    107 
    108     if (eth_control[unit] == NULL) {
    109         printf("ETH DRV : Driver not initialized!!\n");
    110         return -1;
    111     }
    112 
    113     if (eth_control[unit]->started == 0) {
    114         eth_control[unit]->started++;
    115         if (ETH_DRV_THREAD_POLLING) {
    116             /* Start RX poll task */
    117             sigemptyset(&new_mask);
    118             sigaddset(&new_mask, SIGINT);
    119             sigprocmask(SIG_BLOCK, &new_mask, &orig_mask);
    120         
    121             if (taskSpawn("eth_drv_rx_thread", 50, 0,
    122                        16386, _eth_drv_rx_thread,
    123                        unit, 0, 0, 0, 0, 0, 0, 0, 0, 0) == ERROR) {
    124                 eth_control[unit]->started = 0;
    125                 printf("eth_drv : Failed to start RX task!!\n");
    126                 return -1;
    127             }
    128             sigprocmask(SIG_SETMASK, &orig_mask, NULL);
    129         }
    130     } else {
    131         eth_control[unit]->started++;
    132     }
    133 
    134     return 0;
    135 
    136 }
    137 
    138 static int
    139 _eth_drv_stop(int unit)
    140 {
    141     if ((eth_control[unit] == NULL) || (!eth_control[unit]->started)) {
    142         return 0;
    143     }
    144 
    145     if (--eth_control[unit]->started == 0) {
    146         if (ETH_DRV_THREAD_POLLING) {
    147             et_drv_stop(unit);
    148         }
    149     }
    150     return 0;
    151 }
    152 
    153 static int
    154 _eth_drv_tx(int unit, unsigned char *tx_pkt, int pkt_len, void *cookie)
    155 {
    156     return et_drvTx(unit, tx_pkt, pkt_len, cookie);
    157 }
    158 
    159 static int 
    160 _eth_drv_get_mac(int unit, unsigned char *mac)
    161 {
    162     return et_drv_mac_addr_get(unit, mac);
    163 }
    164 
    165 #endif /* defined(VXWORKS) && (VX_VERSION > 54) && !defined(ICS) */
    166 
    167 #if defined(LINUX) && !defined(KERNEL) && !defined(ICS)
    168 
    169 #ifdef ETH_DRV_SUPPORTED
    170 #error "ethernet driver redefined for Linux"
    171 #endif /* ETH_DRV_SUPPORTED */
    172 #define ETH_DRV_SUPPORTED       1
    173 
    174 #include <sys/socket.h>
    175 #include <sys/types.h>
    176 #include <features.h>    /* for the glibc version number */
    177 #include <netpacket/packet.h>
    178 #include <net/ethernet.h>     /* the L2 protocols */
    179 #include <netinet/in.h>
    180 #include <stdio.h>
    181 #include <stdlib.h>
    182 #include <errno.h>
    183 #include <sys/ioctl.h>
    184 #include <string.h>
    185 #include <net/if.h>
    186 #include <linux/if_ether.h>
    187 #include <sal/appl/sal.h>
    188 
    189 typedef struct eth_unit_info_s {
    190     int         sock_fd;
    191     struct      sockaddr_ll sl;
    192     struct ifreq ifr;
    193 
    194     int         unit;
    195     int         inited;
    196     rx_cb       rx_cb;
    197     void        *cookie;
    198     int         started;
    199 } eth_unit_info_t;
    200 
    201 #define ETH_MAX_UNITS   1
    202 static eth_unit_info_t  *eth_control[ETH_MAX_UNITS];
    203 static void _eth_drv_handle_rx(int unit, void *pkt, int pkt_len);
    204 
    205 static void
    206 _eth_drv_rx_thread(void *p)
    207 {
    208     struct sockaddr_ll sl;
    209     int    unit, pkt_len;
    210     uint32 fromlen = sizeof(struct sockaddr_ll);
    211     int    rv, sock_fd;
    212     char * rx_pkt;
    213     fd_set fds;
    214     struct timeval timeout;
    215 
    216     unit = *(int *)p;
    217     sock_fd = eth_control[unit]->sock_fd;
    218 
    219     if ((rx_pkt = malloc(ETH_DRV_MAX_BUF_LEN)) == NULL) {
    220         return;
    221     }
    222 
    223     while (1) {
    224         if (!eth_control[unit]->started) {
    225             break;
    226         }
    227         FD_ZERO(&fds);
    228         FD_SET(sock_fd, &fds);
    229 
    230         timeout.tv_sec = 3;
    231         timeout.tv_usec = 0;
    232 
    233         rv = select(sock_fd + 1, &fds, NULL, NULL, &timeout);
    234 
    235         if (rv < 0) {
    236             /* error case */
    237             break;
    238         } else if (rv == 0) {
    239             /* timeout */
    240             continue;
    241         } else {
    242             if (FD_ISSET(sock_fd, &fds)) {
    243                 pkt_len = recvfrom(sock_fd, rx_pkt, ETH_DRV_MAX_BUF_LEN, 0,
    244                                   (struct sockaddr *)&sl, &fromlen);
    245                 _eth_drv_handle_rx(unit, rx_pkt, pkt_len);
    246             }
    247         }
    248     }
    249 
    250     if (rx_pkt) {
    251         free(rx_pkt);
    252     }
    253 }
    254 
    255 static int _eth_drv_init(int unit)
    256 {
    257     eth_unit_info_t     *channel;
    258     int                  result;
    259 
    260     if (eth_control[unit]) {
    261         return 0;
    262     }
    263 
    264     eth_control[unit] = malloc(sizeof(eth_unit_info_t));
    265     memset(eth_control[unit], 0, sizeof(eth_unit_info_t));
    266     channel = eth_control[unit];
    267 
    268     channel->sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    269     if (channel->sock_fd == 0) {
    270         goto error;
    271     }
    272 
    273     sprintf(channel->ifr.ifr_name, "eth%d", unit);
    274     result = ioctl(channel->sock_fd, SIOCGIFINDEX, &channel->ifr);
    275     if (result) {
    276         goto error;
    277     }
    278 
    279     channel->sl.sll_family = AF_PACKET;
    280     channel->sl.sll_ifindex = channel->ifr.ifr_ifindex;
    281     channel->sl.sll_protocol = htons(ETH_P_ALL);
    282     channel->sl.sll_halen = 6;
    283 
    284     if (bind(channel->sock_fd, (struct sockaddr *)&channel->sl, 
    285          sizeof(struct sockaddr_ll))) {
    286         goto error;
    287     }
    288 
    289     eth_control[unit]->inited++;
    290     return 0;
    291 error:
    292     free(eth_control[unit]);
    293     eth_control[unit] = NULL;
    294     return -1;
    295 }
    296 
    297 static int
    298 _eth_drv_start(int unit)
    299 {
    300     void *ptr;
    301     
    302     if ((eth_control[unit] == NULL) || (!eth_control[unit]->rx_cb)) {
    303         return -1;
    304     }
    305 
    306     if (eth_control[unit]->started == 0) {
    307 
    308         /*
    309          * Start an RX thread to poll for packets over socket interface.
    310          */
    311         eth_control[unit]->started++;
    312         eth_control[unit]->unit = unit;
    313         ptr = (void *)&eth_control[unit]->unit;
    314         sal_thread_create("eth_drv_rx_thread", 
    315                               SAL_THREAD_STKSZ,
    316                               10,
    317                               _eth_drv_rx_thread,
    318                               ptr);
    319     } else {
    320         eth_control[unit]->started++;
    321     }
    322     return 0;
    323 }
    324 
    325 static int
    326 _eth_drv_stop(int unit)
    327 {
    328     if ((eth_control[unit] == NULL) || (!eth_control[unit]->started)) {
    329         return 0;
    330     }
    331 
    332     --eth_control[unit]->started;
    333     return 0;
    334 }
    335 
    336 static int
    337 _eth_drv_tx(int unit, unsigned char *tx_pkt, int pkt_len, void *cookie)
    338 {
    339     eth_unit_info_t * p_chan = eth_control[unit];
    340 
    341     return (send(p_chan->sock_fd, tx_pkt, pkt_len, 0)
    342             == pkt_len) ? 0 : -1;
    343  
    344 }
    345 
    346 static int 
    347 _eth_drv_get_mac(int unit, unsigned char *mac)
    348 {
    349     eth_unit_info_t     *channel;
    350     int                  result;
    351 
    352     if (!eth_control[unit]) {
    353         return -1;
    354     }
    355 
    356     channel = eth_control[unit];
    357 
    358     result = ioctl(channel->sock_fd, SIOCGIFHWADDR, &channel->ifr);
    359     if (result) {
    360         return -1;
    361     }
    362 
    363     memcpy(mac, channel->ifr.ifr_hwaddr.sa_data, ETH_ALEN);
    364     return 0;
    365 }
    366 
    367 #endif /* defined(LINUX) && !defined(KERNEL) && !defined(ICS) */
    368 
    369 /********* APIs **********/
    370 
    371 #ifdef ETH_DRV_SUPPORTED
    372 static void 
    373 _eth_drv_handle_rx(int unit, void *pkt, int pkt_len)
    374 {
    375     if (eth_control[unit] && eth_control[unit]->rx_cb) {
    376         eth_control[unit]->rx_cb(unit,
    377                                  (unsigned char*) pkt, pkt_len, 
    378                                  eth_control[unit]->cookie);
    379     }
    380     return;
    381 }
    382 
    383 int eth_drv_init(int unit)
    384 {
    385     if (unit >= ETH_MAX_UNITS) {
    386         return -1;
    387     }
    388     return _eth_drv_init(unit);
    389 }
    390 
    391 int eth_drv_register(int unit, rx_cb _rx, void *cookie)
    392 {
    393     int rv = 0;
    394 
    395     if (unit >= ETH_MAX_UNITS) {
    396         return -1;
    397     }
    398 
    399     if (eth_control[unit] == NULL) {
    400         rv =  _eth_drv_init(unit);      
    401         if (rv < 0) {
    402             printf("ETH_DRV : error (driver initialize failed!)\n");
    403             return -1;
    404         }
    405     }
    406 
    407     eth_control[unit]->rx_cb = _rx;
    408     eth_control[unit]->cookie = cookie;
    409 #if defined(VXWORKS)
    410     et_drvMIIRxHandlerRegister(unit, (cb_f)_rx, NULL, NULL, cookie);
    411 #endif
    412 
    413     if (eth_control[unit]->started == 0) {
    414         rv = _eth_drv_start(unit);
    415     }
    416 
    417     return rv;
    418 }
    419 
    420 int eth_drv_unregister(int unit, rx_cb _rx)
    421 {
    422     if (unit >= ETH_MAX_UNITS) {
    423         return -1;
    424     }
    425     if (eth_control[unit] == NULL) {
    426         printf("ETH_DRV : error (driver not initialized !!)\n");
    427         return -1;
    428     }
    429     eth_control[unit]->rx_cb = NULL;
    430 #if defined(VXWORKS)
    431     et_drvMIIRxHandlerUnRegister(unit, (cb_f)_rx);
    432 #endif
    433 
    434     if (eth_control[unit]->started) {
    435         _eth_drv_stop(unit);
    436     }
    437 
    438     return 0;
    439 }
    440 
    441 int eth_drv_start(int unit)
    442 {
    443     return _eth_drv_start(unit);
    444 }
    445 
    446 int eth_drv_stop(int unit)
    447 {
    448     return _eth_drv_stop(unit);
    449 }
    450 
    451 
    452 int eth_drv_tx(int unit, unsigned char * pkt, int len, void *cookie)
    453 {
    454     return _eth_drv_tx(unit, pkt, len, cookie);
    455 }
    456 
    457 
    458 int eth_drv_get_mac(int unit, unsigned char *mac)
    459 {
    460     return _eth_drv_get_mac(unit, mac);
    461 }
    462 
    463 #else
    464 
    465 int eth_drv_init(int unit)
    466 {
    467     return -1;
    468 }
    469 
    470 int eth_drv_register(int unit, rx_cb _rx, void *cookie)
    471 {
    472     return -1;
    473 }
    474 
    475 int eth_drv_start(int unit)
    476 {
    477     return -1;
    478 }
    479 
    480 int eth_drv_stop(int unit)
    481 {
    482     return -1;
    483 }
    484 
    485 
    486 int eth_drv_tx(int unit, unsigned char * pkt, int len, void *cookie)
    487 {
    488     return -1;
    489 }
    490 
    491 
    492 int eth_drv_get_mac(int unit, unsigned char *mac)
    493 {
    494     return -1;
    495 }
    496 
    497 #endif /* ETH_DRV_SUPPORTED */
    498