• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &eth_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