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
37 static usb_proc_callback_t ue_attach_post_task;
38 static usb_proc_callback_t ue_tick_task;
39 static usb_proc_callback_t ue_start_task;
40 static usb_proc_callback_t ue_stop_task;
41
42 struct netif *pnetif_usb0 = NULL;
43
44 #define IFQ_MAXLEN 50
45 int ifqmaxlen = IFQ_MAXLEN;
46
47 static void ue_init(struct los_eth_driver *sc,
48 unsigned char *enaddr,
49 int flags);
50 static 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);
55 static void ue_watchdog(void *);
56 static void ue_start_task(struct usb_proc_msg *_task);
57
58 /*
59 * Return values:
60 * 0: success
61 * Else: device has been detached
62 */
63 uint8_t
uether_pause(struct usb_ether * ue,unsigned int _ticks)64 uether_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
74 static void
ue_queue_command(struct usb_ether * ue,usb_proc_callback_t * fn,struct usb_proc_msg * t0,struct usb_proc_msg * t1)75 ue_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
105 void *
uether_getsc(struct usb_ether * ue)106 uether_getsc(struct usb_ether *ue)
107 {
108 return (ue->ue_sc);
109 }
110
111 int
uether_ifattach(struct usb_ether * ue)112 uether_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
144 error:
145 return (ret);
146 }
147
148 void
uether_ifattach_wait(struct usb_ether * ue)149 uether_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 */
160 static struct los_eth_driver *
if_alloc(void)161 if_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
189 static void
if_free(struct los_eth_driver * sc)190 if_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
209 void
ue_recv(struct los_eth_driver * sc,struct eth_drv_sg * sg_list,int sg_len)210 ue_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
265 END:
266 uether_freebuf(m);
267 }
268
269 int
ue_can_send(struct los_eth_driver * sc)270 ue_can_send(struct los_eth_driver *sc)
271 {
272 (void)sc;
273 return (true);
274 }
275
276 static const char usb_eth_name[3] = "ue";
277
278 static void
ue_attach_post_task(struct usb_proc_msg * _task)279 ue_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
331 fail:
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
341 void
uether_ifdetach(struct usb_ether * ue)342 uether_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
396 uint8_t
uether_is_gone(struct usb_ether * ue)397 uether_is_gone(struct usb_ether *ue)
398 {
399 return (usb_proc_is_gone(&ue->ue_tq));
400 }
401
402 static void
ue_init(struct los_eth_driver * sc,unsigned char * enaddr,int flags)403 ue_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
415 static void
ue_start_task(struct usb_proc_msg * _task)416 ue_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
435 static void
ue_stop_task(struct usb_proc_msg * _task)436 ue_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
449 static void
ue_start(struct los_eth_driver * sc,struct eth_drv_sg * sg_list,int sg_len,int total_len,UINTPTR key)450 ue_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
490 static void
ue_watchdog(void * arg)491 ue_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
507 static void
ue_tick_task(struct usb_proc_msg * _task)508 ue_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
523 struct pbuf *
uether_newbuf(int length)524 uether_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
540 struct pbuf *
uether_newbuf(int length)541 uether_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
561 void
uether_freebuf(struct pbuf * buf)562 uether_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
573 int
uether_rxmbuf(struct usb_ether * ue,struct pbuf * m,unsigned int len)574 uether_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
587 void
uether_rxflush(struct usb_ether * ue)588 uether_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
616 void
uether_rxflush(struct usb_ether * ue)617 uether_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