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 = &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
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