xref: /freebsd/sys/dev/firewire/fw_net.h (revision d15f2551b25f79ddcbe289faa95e655100b952da)
1 /*
2  * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  */
6 
7 #ifndef _DEV_FIREWIRE_FW_NET_H_
8 #define _DEV_FIREWIRE_FW_NET_H_
9 
10 /*
11  * Allocate mbuf clusters for isochronous receive bulk transfers
12  * and insert them into the free queue.
13  */
14 static __inline void
15 fw_net_init_iso_chunks(struct fw_xferq *xferq)
16 {
17 	struct mbuf *m;
18 	int i;
19 
20 	for (i = 0; i < xferq->bnchunk; i++) {
21 		m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR);
22 		xferq->bulkxfer[i].mbuf = m;
23 		m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;
24 		STAILQ_INSERT_TAIL(&xferq->stfree, &xferq->bulkxfer[i], link);
25 	}
26 }
27 
28 /*
29  * Allocate a single TX xfer with speed, callback, and softc pre-filled.
30  */
31 static __inline struct fw_xfer *
32 fw_net_alloc_txfer(struct firewire_comm *fc, int speed,
33     void *sc, void (*hand)(struct fw_xfer *),
34     struct malloc_type *mtype)
35 {
36 	struct fw_xfer *xfer;
37 
38 	xfer = fw_xfer_alloc(mtype);
39 	if (xfer == NULL)
40 		return (NULL);
41 	xfer->send.spd = speed;
42 	xfer->fc = fc;
43 	xfer->sc = (caddr_t)sc;
44 	xfer->hand = hand;
45 	return (xfer);
46 }
47 
48 /*
49  * Free all xfers on a STAILQ list.
50  */
51 #define	FW_NET_FREE_XFERLIST(head) do {					\
52 	struct fw_xfer *_xfer, *_next;					\
53 	for (_xfer = STAILQ_FIRST(head); _xfer != NULL;		\
54 	    _xfer = _next) {						\
55 		_next = STAILQ_NEXT(_xfer, link);			\
56 		fw_xfer_free(_xfer);					\
57 	}								\
58 } while (0)
59 
60 /*
61  * Drain the send queue, counting each dropped packet as an output error.
62  */
63 static __inline void
64 fw_net_drain_sendq(if_t ifp)
65 {
66 	struct mbuf *m;
67 
68 	do {
69 		m = if_dequeue(ifp);
70 		if (m != NULL)
71 			m_freem(m);
72 		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
73 	} while (m != NULL);
74 }
75 
76 /*
77  * Handle SIOCSIFCAP for DEVICE_POLLING.
78  * Returns 0 if handled (caller should return), -1 if not a polling request.
79  */
80 #ifdef DEVICE_POLLING
81 static __inline int
82 fw_net_poll_ioctl(if_t ifp, struct ifreq *ifr,
83     struct firewire_comm *fc, poll_handler_t *poll_fn)
84 {
85 	int error;
86 
87 	if (ifr->ifr_reqcap & IFCAP_POLLING &&
88 	    !(if_getcapenable(ifp) & IFCAP_POLLING)) {
89 		error = ether_poll_register(poll_fn, ifp);
90 		if (error)
91 			return (error);
92 		/* Disable interrupts */
93 		fc->set_intr(fc, 0);
94 		if_setcapenablebit(ifp, IFCAP_POLLING, 0);
95 		return (0);
96 	}
97 	if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
98 	    if_getcapenable(ifp) & IFCAP_POLLING) {
99 		error = ether_poll_deregister(ifp);
100 		/* Enable interrupts. */
101 		fc->set_intr(fc, 1);
102 		if_setcapenablebit(ifp, 0, IFCAP_POLLING);
103 		return (error);
104 	}
105 	return (-1);
106 }
107 #endif /* DEVICE_POLLING */
108 
109 #endif /* !_DEV_FIREWIRE_FW_NET_H_ */
110