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