1/*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2009 Andrew Thompson (thompsa@FreeBSD.org) 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> 29 30#include <lwip/netifapi.h> 31 32#include "implementation/global_implementation.h" 33#include "net/usb_ethernet.h" 34 35#define USE_LWIP_BUFFER 0 36 37static usb_proc_callback_t ue_attach_post_task; 38static usb_proc_callback_t ue_tick_task; 39static usb_proc_callback_t ue_start_task; 40static usb_proc_callback_t ue_stop_task; 41 42struct netif *pnetif_usb0 = NULL; 43 44#define IFQ_MAXLEN 50 45int ifqmaxlen = IFQ_MAXLEN; 46 47static void ue_init(struct los_eth_driver *sc, 48 unsigned char *enaddr, 49 int flags); 50static void ue_start(struct los_eth_driver *sc, 51 struct eth_drv_sg *sg_list, 52 int sg_len, 53 int total_len, 54 UINTPTR key); 55static void ue_watchdog(void *); 56static void ue_start_task(struct usb_proc_msg *_task); 57 58/* 59 * Return values: 60 * 0: success 61 * Else: device has been detached 62 */ 63uint8_t 64uether_pause(struct usb_ether *ue, unsigned int _ticks) 65{ 66 if (usb_proc_is_gone(&ue->ue_tq)) { 67 /* nothing to do */ 68 return (1); 69 } 70 usb_pause_mtx(ue->ue_mtx, _ticks); 71 return (0); 72} 73 74static void 75ue_queue_command(struct usb_ether *ue, 76 usb_proc_callback_t *fn, 77 struct usb_proc_msg *t0, struct usb_proc_msg *t1) 78{ 79 struct usb_ether_cfg_task *task; 80 81 UE_LOCK_ASSERT(ue, MA_OWNED); 82 83 if (usb_proc_is_gone(&ue->ue_tq)) { 84 return; /* nothing to do */ 85 } 86 /* 87 * NOTE: The task cannot get executed before we drop the 88 * "sc_mtx" mutex. It is safe to update fields in the message 89 * structure after that the message got queued. 90 */ 91 task = (struct usb_ether_cfg_task *) 92 usb_proc_msignal(&ue->ue_tq, t0, t1); 93 94 /* Setup callback and self pointers */ 95 task->hdr.pm_callback = fn; 96 task->ue = ue; 97 98 /* 99 * Start and stop must be synchronous! 100 */ 101 if ((fn == ue_start_task) || (fn == ue_stop_task)) 102 usb_proc_mwait(&ue->ue_tq, t0, t1); 103} 104 105void * 106uether_getsc(struct usb_ether *ue) 107{ 108 return (ue->ue_sc); 109} 110 111int 112uether_ifattach(struct usb_ether *ue) 113{ 114 int ret = EFAULT; 115 116 /* check some critical parameters */ 117 if ((ue->ue_dev == NULL) || 118 (ue->ue_udev == NULL) || 119 (ue->ue_mtx == NULL) || 120 (ue->ue_methods == NULL)) 121 return (EINVAL); 122 123 if (LOS_EventInit(&ue->ue_event) != LOS_OK) { 124 device_printf(ue->ue_dev, "event init fail\n"); 125 goto error; 126 } 127 128 ret = usb_proc_create(&ue->ue_tq, ue->ue_mtx, 129 device_get_nameunit(ue->ue_dev), USB_PRI_MED); 130 if (ret) 131 { 132 device_printf(ue->ue_dev, "could not setup taskqueue\n"); 133 (void)LOS_EventDestroy(&ue->ue_event); 134 goto error; 135 } 136 137 /* fork rest of the attach code */ 138 UE_LOCK(ue); 139 ue_queue_command(ue, ue_attach_post_task, 140 &ue->ue_sync_task[0].hdr, 141 &ue->ue_sync_task[1].hdr); 142 UE_UNLOCK(ue); 143 144error: 145 return (ret); 146} 147 148void 149uether_ifattach_wait(struct usb_ether *ue) 150{ 151 152 UE_LOCK(ue); 153 usb_proc_mwait(&ue->ue_tq, 154 &ue->ue_sync_task[0].hdr, 155 &ue->ue_sync_task[1].hdr); 156 UE_UNLOCK(ue); 157} 158 159/* allocating space for eth_driver */ 160static struct los_eth_driver * 161if_alloc(void) 162{ 163 struct los_eth_driver *sc; 164 struct eth_drv_sc *drv_sc; 165 166 sc = (struct los_eth_driver *)zalloc(sizeof(struct los_eth_driver)); 167 if (sc == NULL) { 168 return (NULL); 169 } 170 171 drv_sc = (struct eth_drv_sc *)zalloc(sizeof(struct eth_drv_sc)); 172 if (drv_sc == NULL) { 173 free(sc); 174 return (NULL); 175 } 176 177 drv_sc->funs = (struct eth_hwr_funs*)zalloc(sizeof(struct eth_hwr_funs)); 178 if (drv_sc->funs == NULL) { 179 PRINTK("could not allocate eth_hwr_funs\n"); 180 free(sc); 181 free(drv_sc); 182 return (NULL); 183 } 184 sc->driver_context = drv_sc; 185 186 return (sc); 187} 188 189static void 190if_free(struct los_eth_driver * sc) 191{ 192 struct eth_drv_sc *drv_sc; 193 if (sc == NULL) { 194 return; 195 } 196 197 drv_sc = (struct eth_drv_sc *)sc->driver_context; 198 if (drv_sc != NULL) { 199 if (drv_sc->funs) { 200 free(drv_sc->funs); 201 drv_sc->funs = NULL; 202 } 203 free(drv_sc); 204 sc->driver_context = NULL; 205 free(sc); 206 } 207} 208 209void 210ue_recv(struct los_eth_driver *sc,struct eth_drv_sg *sg_list,int sg_len) 211{ 212 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 213 struct usb_ether *ue = (struct usb_ether *)drv_sc->driver_private; 214 struct pbuf *m; 215 UINT32 bytes_in_buffer; 216 UINT32 bytes_in_list; 217 UINT32 bytes_needed_list; 218 UINT32 buffer_pos = 0; 219 UINT8 *sg_buf; 220 UINT8 *hw_rxbuf; 221 int i; 222 int ret; 223 224 IF_DEQUEUE(&ue->ue_rxq, m); 225 if (m == NULL) { 226 PRINTK("no buffer! can not happen!\n"); 227 /* Delete the space */ 228 return; 229 } 230 231 for(i = 0; i < sg_len; ++i) { 232 bytes_in_list = 0; 233 while (bytes_in_list < sg_list[i].len) { 234 bytes_needed_list = sg_list[i].len - bytes_in_list; 235 bytes_in_buffer = m->len; 236 bytes_in_buffer -= buffer_pos; 237 238 sg_buf = (UINT8 *)(sg_list[i].buf); 239 hw_rxbuf = (UINT8 *)(m->payload); 240 if (bytes_needed_list < bytes_in_buffer) { 241 if (sg_buf != NULL) { 242 ret = memcpy_s(&sg_buf[bytes_in_list], bytes_needed_list, 243 (UINT8 *)&hw_rxbuf[buffer_pos], bytes_needed_list); 244 if (ret != EOK) { 245 goto END; 246 } 247 } 248 bytes_in_list += bytes_needed_list; 249 buffer_pos += bytes_needed_list; 250 } else { 251 if (sg_buf != NULL) { 252 ret = memcpy_s(&sg_buf[bytes_in_list], bytes_needed_list, 253 (UINT8 *)&hw_rxbuf[buffer_pos], bytes_in_buffer); 254 if (ret != EOK) { 255 goto END; 256 } 257 } 258 259 bytes_in_list += bytes_in_buffer; 260 buffer_pos = 0; 261 } 262 } 263 } 264 265END: 266 uether_freebuf(m); 267} 268 269int 270ue_can_send(struct los_eth_driver *sc) 271{ 272 (void)sc; 273 return (true); 274} 275 276static const char usb_eth_name[3] = "ue"; 277 278static void 279ue_attach_post_task(struct usb_proc_msg *_task) 280{ 281 struct usb_ether_cfg_task *task = 282 (struct usb_ether_cfg_task *)_task; 283 struct usb_ether *ue = task->ue; 284 struct los_eth_driver *sc; 285 struct eth_drv_sc *drv_sc; 286 int error; 287 288 UE_UNLOCK(ue); 289 290 usb_callout_init_mtx(&ue->ue_watchdog, ue->ue_mtx, 0); 291 292 error = 0; 293 sc = if_alloc(); 294 if (sc == NULL) { 295 device_printf(ue->ue_dev, "could not allocate eth_drv_sc\n"); 296 goto fail; 297 } 298 299 drv_sc = (struct eth_drv_sc *)sc->driver_context; 300 drv_sc->driver_private = ue; 301 drv_sc->dev_name = usb_eth_name; 302 if (ue->ue_methods->ue_attach_post_sub != NULL) { 303 ue->ue_drv_sc = sc; 304 error = ue->ue_methods->ue_attach_post_sub(ue); 305 } else { 306 drv_sc->funs->send = ue_start; 307 drv_sc->funs->can_send = ue_can_send; 308 drv_sc->funs->start = ue_init; 309 drv_sc->funs->recv = ue_recv; 310 drv_sc->funs->eth_drv = ð_drv_funs_usb; 311 ue->ue_drv_sc = sc; 312 } 313 314 if (error) { 315 device_printf(ue->ue_dev, "attaching PHYs failed\n"); 316 goto fail; 317 } 318 319 (drv_sc->funs->eth_drv->init)(sc, ue->ue_eaddr); 320 321 if (LOS_EventWrite(&ue->ue_event, 0x01) != LOS_OK) { 322 device_printf(ue->ue_dev, "event write fail\n"); 323 goto fail; 324 } 325 326 pnetif_usb0 = &sc->ac_if; 327 328 UE_LOCK(ue); 329 return; 330 331fail: 332 333 if (ue->ue_drv_sc != NULL) { 334 if_free(sc); 335 ue->ue_drv_sc = NULL; 336 } 337 UE_LOCK(ue); 338 return; 339} 340 341void 342uether_ifdetach(struct usb_ether *ue) 343{ 344 struct los_eth_driver *sc; 345 struct eth_drv_sc *drv_sc; 346 struct pbuf *m; 347 348 /* wait for any post attach or other command to complete */ 349 usb_proc_drain(&ue->ue_tq); 350 351 /* read "ifnet" pointer after taskqueue drain */ 352 sc = ue->ue_drv_sc; 353 if (sc != NULL) { 354 drv_sc = ( struct eth_drv_sc *)sc->driver_context; 355 /* we are not running any more */ 356 UE_LOCK(ue); 357 drv_sc->state &= ~IFF_DRV_RUNNING; 358 UE_UNLOCK(ue); 359 360 /* drain any callouts */ 361 usb_callout_drain(&ue->ue_watchdog); 362 363 /* detach ethernet */ 364 for (;;) { 365 UE_LOCK(ue); 366 IF_DEQUEUE(&(ue->ue_txq), m); 367 UE_UNLOCK(ue); 368 if (m == NULL) 369 break; 370 uether_freebuf(m); 371 } 372 for (;;) { 373 UE_LOCK(ue); 374 IF_DEQUEUE(&(ue->ue_rxq), m); 375 UE_UNLOCK(ue); 376 if (m == NULL) 377 break; 378 uether_freebuf(m); 379 } 380 381 (void)netifapi_dhcp_stop(&sc->ac_if); 382 (void)netifapi_dhcp_cleanup(&sc->ac_if); 383 (void)netifapi_netif_remove(&sc->ac_if); 384 385 /* free interface instance */ 386 if_free(sc); 387 ue->ue_drv_sc = NULL; 388 } 389 390 /* free taskqueue, if any */ 391 usb_proc_free(&ue->ue_tq); 392 393 (void)LOS_EventDestroy(&ue->ue_event); 394} 395 396uint8_t 397uether_is_gone(struct usb_ether *ue) 398{ 399 return (usb_proc_is_gone(&ue->ue_tq)); 400} 401 402static void 403ue_init(struct los_eth_driver *sc, 404 unsigned char *enaddr, 405 int flags) 406{ 407 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 408 struct usb_ether *ue = (struct usb_ether *)drv_sc->driver_private; 409 410 UE_LOCK(ue); 411 ue_start_task(&ue->ue_sync_task[0].hdr); 412 UE_UNLOCK(ue); 413} 414 415static void 416ue_start_task(struct usb_proc_msg *_task) 417{ 418 struct usb_ether_cfg_task *task = 419 (struct usb_ether_cfg_task *)_task; 420 struct usb_ether *ue = task->ue; 421 struct los_eth_driver *sc = ue->ue_drv_sc; 422 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 423 424 UE_LOCK_ASSERT(ue, MA_OWNED); 425 426 ue->ue_methods->ue_init(ue); 427 428 if ((drv_sc->state & IFF_DRV_RUNNING) == 0) 429 return; 430 431 if (ue->ue_methods->ue_tick != NULL) 432 usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue); 433} 434 435static void 436ue_stop_task(struct usb_proc_msg *_task) 437{ 438 struct usb_ether_cfg_task *task = 439 (struct usb_ether_cfg_task *)_task; 440 struct usb_ether *ue = task->ue; 441 442 UE_LOCK_ASSERT(ue, MA_OWNED); 443 444 usb_callout_stop(&ue->ue_watchdog); 445 446 ue->ue_methods->ue_stop(ue); 447} 448 449static void 450ue_start(struct los_eth_driver *sc, 451 struct eth_drv_sg *sg_list, 452 int sg_len, 453 int total_len, 454 UINTPTR key) 455{ 456 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 457 struct usb_ether *ue = (struct usb_ether *)drv_sc->driver_private; 458 struct pbuf *m; 459 int len = 0; 460 int i; 461 int ret; 462 463 m = uether_newbuf(total_len); 464 if (m == NULL) { 465 return; 466 } 467 468 for (i = 0; i < sg_len; i++) { 469 ret = memcpy_s((void *)((char *)m->payload + len), (size_t)(total_len - len), 470 (const void *)(sg_list[i].buf), sg_list[i].len); 471 if (ret != EOK) { 472 uether_freebuf(m); 473 return; 474 } 475 len += sg_list[i].len; 476 } 477 478 UE_LOCK(ue); 479 if ((drv_sc->state & IFF_DRV_RUNNING) == 0) { 480 UE_UNLOCK(ue); 481 uether_freebuf(m); 482 return; 483 } 484 IF_ENQUEUE(&(ue->ue_txq), m); 485 486 ue->ue_methods->ue_start(ue); 487 UE_UNLOCK(ue); 488} 489 490static void 491ue_watchdog(void *arg) 492{ 493 struct usb_ether *ue = (struct usb_ether *)arg; 494 struct los_eth_driver *sc = ue->ue_drv_sc; 495 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 496 497 if ((drv_sc->state & IFF_DRV_RUNNING) == 0) 498 return; 499 500 ue_queue_command(ue, ue_tick_task, 501 &ue->ue_tick_task[0].hdr, 502 &ue->ue_tick_task[1].hdr); 503 504 usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue); 505} 506 507static void 508ue_tick_task(struct usb_proc_msg *_task) 509{ 510 struct usb_ether_cfg_task *task = 511 (struct usb_ether_cfg_task *)_task; 512 struct usb_ether *ue = task->ue; 513 struct los_eth_driver *sc = ue->ue_drv_sc; 514 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 515 516 if ((drv_sc->state & IFF_DRV_RUNNING) == 0) 517 return; 518 519 ue->ue_methods->ue_tick(ue); 520} 521 522#if USE_LWIP_BUFFER 523struct pbuf * 524uether_newbuf(int length) 525{ 526 struct pbuf *m_new; 527 m_new = pbuf_alloc(PBUF_RAW, length, PBUF_RAM); 528 529 if (m_new == NULL) { 530 PRINTK("pbuf_alloc fail\n"); 531 return (NULL); 532 } 533#if ETH_PAD_SIZE 534 pbuf_header(m_new, -ETH_PAD_SIZE); /* drop the padding word */ 535#endif 536 537 return (m_new); 538} 539#else 540struct pbuf * 541uether_newbuf(int length) 542{ 543 struct pbuf *m_new = (struct pbuf *)zalloc(sizeof(struct pbuf)); 544 if (m_new == NULL) { 545 PRINTK("pbuf_alloc fail\n"); 546 return (NULL); 547 } 548 m_new->payload = memalign(USB_CACHE_ALIGN_SIZE, SKB_DATA_ALIGN(length)); 549 if (m_new->payload == NULL) { 550 PRINTK("pbuf_alloc fail\n"); 551 free(m_new); 552 return (NULL); 553 } 554 (void)memset_s(m_new->payload, SKB_DATA_ALIGN(length), 0, SKB_DATA_ALIGN(length)); 555 556 m_new->len = length; 557 558 return (m_new); 559} 560 561void 562uether_freebuf(struct pbuf *buf) 563{ 564 if(buf != NULL) { 565 if(buf->payload) { 566 free(buf->payload); 567 buf->payload = NULL; 568 } 569 free(buf); 570 } 571} 572#endif 573int 574uether_rxmbuf(struct usb_ether *ue, struct pbuf *m, unsigned int len) 575{ 576 UE_LOCK_ASSERT(ue, MA_OWNED); 577 578 m->len = len; 579 580 /* enqueue for later when the lock can be released */ 581 IF_ENQUEUE(&(ue->ue_rxq), m); 582 ue->ue_rxq.ifq_head->tot_len += len; 583 return (0); 584} 585 586#if USE_LWIP_BUFFER 587void 588uether_rxflush(struct usb_ether *ue) 589{ 590 struct netif *netif = &(ue->ue_drv_sc->ac_if); 591 struct pbuf *m = ue->ue_rxq.ifq_head; 592 int tot_len = 0; 593 struct pbuf *q; 594 595 UE_LOCK_ASSERT(ue, MA_OWNED); 596 597 PRINTK("uether_rxflush \n"); 598 for (q = m; q != NULL; q = q->next) { 599 tot_len += q->len; 600 } 601 m->tot_len = tot_len; 602 603#if ETH_PAD_SIZE 604 pbuf_header(m, ETH_PAD_SIZE); /* drop the padding word */ 605#endif 606 607 /* 608 * The USB xfer has been resubmitted so its safe to unlock now. 609 */ 610 UE_UNLOCK(ue); 611 612 driverif_input(netif, m); 613 UE_LOCK(ue); 614} 615#else 616void 617uether_rxflush(struct usb_ether *ue) 618{ 619 struct los_eth_driver *sc = ue->ue_drv_sc; 620 struct eth_drv_sc *drv_sc = (struct eth_drv_sc *)sc->driver_context; 621 struct pbuf *m; 622 623 UE_LOCK_ASSERT(ue, MA_OWNED); 624 for (;;) { 625 m = ue->ue_rxq.ifq_head; 626 if (m == NULL) 627 break; 628 629 (drv_sc->funs->eth_drv->recv)(sc, m->len); 630 } 631} 632#endif 633