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
fw_net_init_iso_chunks(struct fw_xferq * xferq)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 *
fw_net_alloc_txfer(struct firewire_comm * fc,int speed,void * sc,void (* hand)(struct fw_xfer *),struct malloc_type * mtype)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
fw_net_drain_sendq(if_t ifp)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
fw_net_poll_ioctl(if_t ifp,struct ifreq * ifr,struct firewire_comm * fc,poll_handler_t * poll_fn)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