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 *)ð_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