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