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