bcsp.c revision 1.31 1 1.31 knakahar /* $NetBSD: bcsp.c,v 1.31 2019/01/24 09:33:03 knakahara Exp $ */
2 1.1 kiyohara /*
3 1.1 kiyohara * Copyright (c) 2007 KIYOHARA Takashi
4 1.1 kiyohara * All rights reserved.
5 1.1 kiyohara *
6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without
7 1.1 kiyohara * modification, are permitted provided that the following conditions
8 1.1 kiyohara * are met:
9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright
10 1.1 kiyohara * notice, this list of conditions and the following disclaimer.
11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the
13 1.1 kiyohara * documentation and/or other materials provided with the distribution.
14 1.1 kiyohara *
15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE.
26 1.1 kiyohara */
27 1.1 kiyohara
28 1.1 kiyohara #include <sys/cdefs.h>
29 1.31 knakahar __KERNEL_RCSID(0, "$NetBSD: bcsp.c,v 1.31 2019/01/24 09:33:03 knakahara Exp $");
30 1.1 kiyohara
31 1.1 kiyohara #include <sys/types.h>
32 1.1 kiyohara #include <sys/param.h>
33 1.1 kiyohara #include <sys/callout.h>
34 1.1 kiyohara #include <sys/conf.h>
35 1.1 kiyohara #include <sys/device.h>
36 1.1 kiyohara #include <sys/errno.h>
37 1.1 kiyohara #include <sys/fcntl.h>
38 1.1 kiyohara #include <sys/kauth.h>
39 1.1 kiyohara #include <sys/kernel.h>
40 1.1 kiyohara #include <sys/malloc.h>
41 1.1 kiyohara #include <sys/mbuf.h>
42 1.1 kiyohara #include <sys/proc.h>
43 1.1 kiyohara #include <sys/sysctl.h>
44 1.1 kiyohara #include <sys/syslimits.h>
45 1.1 kiyohara #include <sys/systm.h>
46 1.1 kiyohara #include <sys/tty.h>
47 1.1 kiyohara
48 1.1 kiyohara #include <netbt/bluetooth.h>
49 1.1 kiyohara #include <netbt/hci.h>
50 1.1 kiyohara
51 1.1 kiyohara #include <dev/bluetooth/bcsp.h>
52 1.1 kiyohara
53 1.20 uebayasi #include "ioconf.h"
54 1.20 uebayasi
55 1.1 kiyohara #ifdef BCSP_DEBUG
56 1.3 kiyohara #ifdef DPRINTF
57 1.1 kiyohara #undef DPRINTF
58 1.3 kiyohara #endif
59 1.3 kiyohara #ifdef DPRINTFN
60 1.1 kiyohara #undef DPRINTFN
61 1.3 kiyohara #endif
62 1.1 kiyohara
63 1.1 kiyohara #define DPRINTF(x) printf x
64 1.1 kiyohara #define DPRINTFN(n, x) do { if (bcsp_debug > (n)) printf x; } while (0)
65 1.1 kiyohara int bcsp_debug = 3;
66 1.1 kiyohara #else
67 1.1 kiyohara #undef DPRINTF
68 1.1 kiyohara #undef DPRINTFN
69 1.1 kiyohara
70 1.1 kiyohara #define DPRINTF(x)
71 1.1 kiyohara #define DPRINTFN(n, x)
72 1.1 kiyohara #endif
73 1.1 kiyohara
74 1.1 kiyohara struct bcsp_softc {
75 1.4 plunky device_t sc_dev;
76 1.1 kiyohara
77 1.1 kiyohara struct tty *sc_tp;
78 1.10 plunky struct hci_unit *sc_unit; /* Bluetooth HCI Unit */
79 1.10 plunky struct bt_stats sc_stats;
80 1.10 plunky
81 1.10 plunky int sc_flags;
82 1.10 plunky
83 1.10 plunky /* output queues */
84 1.10 plunky MBUFQ_HEAD() sc_cmdq;
85 1.10 plunky MBUFQ_HEAD() sc_aclq;
86 1.10 plunky MBUFQ_HEAD() sc_scoq;
87 1.1 kiyohara
88 1.1 kiyohara int sc_baud;
89 1.1 kiyohara int sc_init_baud;
90 1.1 kiyohara
91 1.1 kiyohara /* variables of SLIP Layer */
92 1.1 kiyohara struct mbuf *sc_txp; /* outgoing packet */
93 1.1 kiyohara struct mbuf *sc_rxp; /* incoming packet */
94 1.1 kiyohara int sc_slip_txrsv; /* reserved byte data */
95 1.1 kiyohara int sc_slip_rxexp; /* expected byte data */
96 1.1 kiyohara void (*sc_transmit_callback)(struct bcsp_softc *, struct mbuf *);
97 1.1 kiyohara
98 1.1 kiyohara /* variables of Packet Integrity Layer */
99 1.1 kiyohara int sc_pi_txcrc; /* use CRC, if true */
100 1.1 kiyohara
101 1.1 kiyohara /* variables of MUX Layer */
102 1.1 kiyohara bool sc_mux_send_ack; /* flag for send_ack */
103 1.1 kiyohara bool sc_mux_choke; /* Choke signal */
104 1.1 kiyohara struct timeval sc_mux_lastrx; /* Last Rx Pkt Time */
105 1.1 kiyohara
106 1.1 kiyohara /* variables of Sequencing Layer */
107 1.1 kiyohara MBUFQ_HEAD() sc_seqq; /* Sequencing Layer queue */
108 1.1 kiyohara MBUFQ_HEAD() sc_seq_retryq; /* retry queue */
109 1.1 kiyohara uint32_t sc_seq_txseq;
110 1.1 kiyohara uint32_t sc_seq_txack;
111 1.1 kiyohara uint32_t sc_seq_expected_rxseq;
112 1.1 kiyohara uint32_t sc_seq_winspace;
113 1.1 kiyohara uint32_t sc_seq_retries;
114 1.1 kiyohara callout_t sc_seq_timer;
115 1.1 kiyohara uint32_t sc_seq_timeout;
116 1.1 kiyohara uint32_t sc_seq_winsize;
117 1.1 kiyohara uint32_t sc_seq_retry_limit;
118 1.1 kiyohara
119 1.1 kiyohara /* variables of Datagram Queue Layer */
120 1.1 kiyohara MBUFQ_HEAD() sc_dgq; /* Datagram Queue Layer queue */
121 1.1 kiyohara
122 1.1 kiyohara /* variables of BCSP Link Establishment Protocol */
123 1.1 kiyohara bool sc_le_muzzled;
124 1.1 kiyohara bcsp_le_state_t sc_le_state;
125 1.1 kiyohara callout_t sc_le_timer;
126 1.1 kiyohara
127 1.1 kiyohara struct sysctllog *sc_log; /* sysctl log */
128 1.1 kiyohara };
129 1.1 kiyohara
130 1.10 plunky /* sc_flags */
131 1.10 plunky #define BCSP_XMIT (1 << 0) /* transmit active */
132 1.10 plunky #define BCSP_ENABLED (1 << 1) /* is enabled */
133 1.10 plunky
134 1.18 cegger static int bcsp_match(device_t, cfdata_t, void *);
135 1.9 kiyohara static void bcsp_attach(device_t, device_t, void *);
136 1.9 kiyohara static int bcsp_detach(device_t, int);
137 1.1 kiyohara
138 1.1 kiyohara /* tty functions */
139 1.1 kiyohara static int bcspopen(dev_t, struct tty *);
140 1.1 kiyohara static int bcspclose(struct tty *, int);
141 1.1 kiyohara static int bcspioctl(struct tty *, u_long, void *, int, struct lwp *);
142 1.1 kiyohara
143 1.1 kiyohara static int bcsp_slip_transmit(struct tty *);
144 1.1 kiyohara static int bcsp_slip_receive(int, struct tty *);
145 1.1 kiyohara
146 1.1 kiyohara static void bcsp_pktintegrity_transmit(struct bcsp_softc *);
147 1.1 kiyohara static void bcsp_pktintegrity_receive(struct bcsp_softc *, struct mbuf *);
148 1.1 kiyohara static void bcsp_crc_update(uint16_t *, uint8_t);
149 1.1 kiyohara static uint16_t bcsp_crc_reverse(uint16_t);
150 1.1 kiyohara
151 1.1 kiyohara static void bcsp_mux_transmit(struct bcsp_softc *sc);
152 1.1 kiyohara static void bcsp_mux_receive(struct bcsp_softc *sc, struct mbuf *m);
153 1.1 kiyohara static __inline void bcsp_send_ack_command(struct bcsp_softc *sc);
154 1.1 kiyohara static __inline struct mbuf *bcsp_create_ackpkt(void);
155 1.1 kiyohara static __inline void bcsp_set_choke(struct bcsp_softc *, bool);
156 1.1 kiyohara
157 1.1 kiyohara static void bcsp_sequencing_receive(struct bcsp_softc *, struct mbuf *);
158 1.1 kiyohara static bool bcsp_tx_reliable_pkt(struct bcsp_softc *, struct mbuf *, u_int);
159 1.1 kiyohara static __inline u_int bcsp_get_txack(struct bcsp_softc *);
160 1.1 kiyohara static void bcsp_signal_rxack(struct bcsp_softc *, uint32_t);
161 1.1 kiyohara static void bcsp_reliabletx_callback(struct bcsp_softc *, struct mbuf *);
162 1.1 kiyohara static void bcsp_timer_timeout(void *);
163 1.1 kiyohara static void bcsp_sequencing_reset(struct bcsp_softc *);
164 1.1 kiyohara
165 1.1 kiyohara static void bcsp_datagramq_receive(struct bcsp_softc *, struct mbuf *);
166 1.1 kiyohara static bool bcsp_tx_unreliable_pkt(struct bcsp_softc *, struct mbuf *, u_int);
167 1.1 kiyohara static void bcsp_unreliabletx_callback(struct bcsp_softc *, struct mbuf *);
168 1.1 kiyohara
169 1.10 plunky static int bcsp_start_le(struct bcsp_softc *);
170 1.10 plunky static void bcsp_terminate_le(struct bcsp_softc *);
171 1.10 plunky static void bcsp_input_le(struct bcsp_softc *, struct mbuf *);
172 1.1 kiyohara static void bcsp_le_timeout(void *);
173 1.1 kiyohara
174 1.10 plunky static void bcsp_start(struct bcsp_softc *);
175 1.10 plunky
176 1.1 kiyohara /* bluetooth hci functions */
177 1.7 plunky static int bcsp_enable(device_t);
178 1.7 plunky static void bcsp_disable(device_t);
179 1.10 plunky static void bcsp_output_cmd(device_t, struct mbuf *);
180 1.10 plunky static void bcsp_output_acl(device_t, struct mbuf *);
181 1.10 plunky static void bcsp_output_sco(device_t, struct mbuf *);
182 1.10 plunky static void bcsp_stats(device_t, struct bt_stats *, int);
183 1.1 kiyohara
184 1.1 kiyohara #ifdef BCSP_DEBUG
185 1.1 kiyohara static void bcsp_packet_print(struct mbuf *m);
186 1.1 kiyohara #endif
187 1.1 kiyohara
188 1.1 kiyohara
189 1.1 kiyohara /*
190 1.1 kiyohara * It doesn't need to be exported, as only bcspattach() uses it,
191 1.1 kiyohara * but there's no "official" way to make it static.
192 1.1 kiyohara */
193 1.4 plunky CFATTACH_DECL_NEW(bcsp, sizeof(struct bcsp_softc),
194 1.1 kiyohara bcsp_match, bcsp_attach, bcsp_detach, NULL);
195 1.1 kiyohara
196 1.1 kiyohara static struct linesw bcsp_disc = {
197 1.1 kiyohara .l_name = "bcsp",
198 1.1 kiyohara .l_open = bcspopen,
199 1.1 kiyohara .l_close = bcspclose,
200 1.1 kiyohara .l_read = ttyerrio,
201 1.1 kiyohara .l_write = ttyerrio,
202 1.1 kiyohara .l_ioctl = bcspioctl,
203 1.1 kiyohara .l_rint = bcsp_slip_receive,
204 1.1 kiyohara .l_start = bcsp_slip_transmit,
205 1.1 kiyohara .l_modem = ttymodem,
206 1.1 kiyohara .l_poll = ttyerrpoll
207 1.1 kiyohara };
208 1.1 kiyohara
209 1.10 plunky static const struct hci_if bcsp_hci = {
210 1.10 plunky .enable = bcsp_enable,
211 1.10 plunky .disable = bcsp_disable,
212 1.10 plunky .output_cmd = bcsp_output_cmd,
213 1.10 plunky .output_acl = bcsp_output_acl,
214 1.10 plunky .output_sco = bcsp_output_sco,
215 1.10 plunky .get_stats = bcsp_stats,
216 1.10 plunky .ipl = IPL_TTY,
217 1.10 plunky };
218 1.1 kiyohara
219 1.1 kiyohara /* ARGSUSED */
220 1.1 kiyohara void
221 1.1 kiyohara bcspattach(int num __unused)
222 1.1 kiyohara {
223 1.1 kiyohara int error;
224 1.1 kiyohara
225 1.1 kiyohara error = ttyldisc_attach(&bcsp_disc);
226 1.1 kiyohara if (error) {
227 1.1 kiyohara aprint_error("%s: unable to register line discipline, "
228 1.1 kiyohara "error = %d\n", bcsp_cd.cd_name, error);
229 1.1 kiyohara return;
230 1.1 kiyohara }
231 1.1 kiyohara
232 1.1 kiyohara error = config_cfattach_attach(bcsp_cd.cd_name, &bcsp_ca);
233 1.1 kiyohara if (error) {
234 1.1 kiyohara aprint_error("%s: unable to register cfattach, error = %d\n",
235 1.1 kiyohara bcsp_cd.cd_name, error);
236 1.1 kiyohara config_cfdriver_detach(&bcsp_cd);
237 1.1 kiyohara (void) ttyldisc_detach(&bcsp_disc);
238 1.1 kiyohara }
239 1.1 kiyohara }
240 1.1 kiyohara
241 1.1 kiyohara /*
242 1.1 kiyohara * Autoconf match routine.
243 1.1 kiyohara *
244 1.1 kiyohara * XXX: unused: config_attach_pseudo(9) does not call ca_match.
245 1.1 kiyohara */
246 1.1 kiyohara /* ARGSUSED */
247 1.1 kiyohara static int
248 1.18 cegger bcsp_match(device_t self __unused, cfdata_t cfdata __unused,
249 1.1 kiyohara void *arg __unused)
250 1.1 kiyohara {
251 1.1 kiyohara
252 1.1 kiyohara /* pseudo-device; always present */
253 1.1 kiyohara return 1;
254 1.1 kiyohara }
255 1.1 kiyohara
256 1.1 kiyohara /*
257 1.1 kiyohara * Autoconf attach routine. Called by config_attach_pseudo(9) when we
258 1.1 kiyohara * open the line discipline.
259 1.1 kiyohara */
260 1.1 kiyohara /* ARGSUSED */
261 1.1 kiyohara static void
262 1.9 kiyohara bcsp_attach(device_t parent __unused, device_t self, void *aux __unused)
263 1.1 kiyohara {
264 1.1 kiyohara struct bcsp_softc *sc = device_private(self);
265 1.1 kiyohara const struct sysctlnode *node;
266 1.1 kiyohara int rc, bcsp_node_num;
267 1.1 kiyohara
268 1.1 kiyohara aprint_normal("\n");
269 1.1 kiyohara aprint_naive("\n");
270 1.1 kiyohara
271 1.4 plunky sc->sc_dev = self;
272 1.1 kiyohara callout_init(&sc->sc_seq_timer, 0);
273 1.1 kiyohara callout_setfunc(&sc->sc_seq_timer, bcsp_timer_timeout, sc);
274 1.1 kiyohara callout_init(&sc->sc_le_timer, 0);
275 1.1 kiyohara callout_setfunc(&sc->sc_le_timer, bcsp_le_timeout, sc);
276 1.1 kiyohara sc->sc_seq_timeout = BCSP_SEQ_TX_TIMEOUT;
277 1.1 kiyohara sc->sc_seq_winsize = BCSP_SEQ_TX_WINSIZE;
278 1.1 kiyohara sc->sc_seq_retry_limit = BCSP_SEQ_TX_RETRY_LIMIT;
279 1.1 kiyohara MBUFQ_INIT(&sc->sc_seqq);
280 1.1 kiyohara MBUFQ_INIT(&sc->sc_seq_retryq);
281 1.1 kiyohara MBUFQ_INIT(&sc->sc_dgq);
282 1.10 plunky MBUFQ_INIT(&sc->sc_cmdq);
283 1.10 plunky MBUFQ_INIT(&sc->sc_aclq);
284 1.10 plunky MBUFQ_INIT(&sc->sc_scoq);
285 1.1 kiyohara
286 1.1 kiyohara /* Attach Bluetooth unit */
287 1.24 rmind sc->sc_unit = hci_attach_pcb(&bcsp_hci, self, 0);
288 1.1 kiyohara
289 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
290 1.4 plunky 0, CTLTYPE_NODE, device_xname(self),
291 1.1 kiyohara SYSCTL_DESCR("bcsp controls"),
292 1.1 kiyohara NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
293 1.1 kiyohara goto err;
294 1.1 kiyohara }
295 1.1 kiyohara bcsp_node_num = node->sysctl_num;
296 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
297 1.21 dsl CTLFLAG_READWRITE, CTLTYPE_BOOL,
298 1.1 kiyohara "muzzled", SYSCTL_DESCR("muzzled for Link-establishment Layer"),
299 1.1 kiyohara NULL, 0, &sc->sc_le_muzzled,
300 1.1 kiyohara 0, CTL_HW, bcsp_node_num, CTL_CREATE, CTL_EOL)) != 0) {
301 1.1 kiyohara goto err;
302 1.1 kiyohara }
303 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
304 1.1 kiyohara CTLFLAG_READWRITE, CTLTYPE_INT,
305 1.1 kiyohara "txcrc", SYSCTL_DESCR("txcrc for Packet Integrity Layer"),
306 1.1 kiyohara NULL, 0, &sc->sc_pi_txcrc,
307 1.1 kiyohara 0, CTL_HW, bcsp_node_num, CTL_CREATE, CTL_EOL)) != 0) {
308 1.1 kiyohara goto err;
309 1.1 kiyohara }
310 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
311 1.1 kiyohara CTLFLAG_READWRITE, CTLTYPE_INT,
312 1.1 kiyohara "timeout", SYSCTL_DESCR("timeout for Sequencing Layer"),
313 1.1 kiyohara NULL, 0, &sc->sc_seq_timeout,
314 1.1 kiyohara 0, CTL_HW, bcsp_node_num, CTL_CREATE, CTL_EOL)) != 0) {
315 1.1 kiyohara goto err;
316 1.1 kiyohara }
317 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
318 1.1 kiyohara CTLFLAG_READWRITE, CTLTYPE_INT,
319 1.1 kiyohara "winsize", SYSCTL_DESCR("winsize for Sequencing Layer"),
320 1.1 kiyohara NULL, 0, &sc->sc_seq_winsize,
321 1.1 kiyohara 0, CTL_HW, bcsp_node_num, CTL_CREATE, CTL_EOL)) != 0) {
322 1.1 kiyohara goto err;
323 1.1 kiyohara }
324 1.1 kiyohara if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
325 1.1 kiyohara CTLFLAG_READWRITE, CTLTYPE_INT,
326 1.1 kiyohara "retry_limit", SYSCTL_DESCR("retry limit for Sequencing Layer"),
327 1.1 kiyohara NULL, 0, &sc->sc_seq_retry_limit,
328 1.1 kiyohara 0, CTL_HW, bcsp_node_num, CTL_CREATE, CTL_EOL)) != 0) {
329 1.1 kiyohara goto err;
330 1.1 kiyohara }
331 1.1 kiyohara return;
332 1.1 kiyohara
333 1.1 kiyohara err:
334 1.8 plunky aprint_error_dev(self, "sysctl_createv failed (rc = %d)\n", rc);
335 1.1 kiyohara }
336 1.1 kiyohara
337 1.1 kiyohara /*
338 1.1 kiyohara * Autoconf detach routine. Called when we close the line discipline.
339 1.1 kiyohara */
340 1.1 kiyohara /* ARGSUSED */
341 1.1 kiyohara static int
342 1.10 plunky bcsp_detach(device_t self, int flags __unused)
343 1.1 kiyohara {
344 1.1 kiyohara struct bcsp_softc *sc = device_private(self);
345 1.1 kiyohara
346 1.10 plunky if (sc->sc_unit != NULL) {
347 1.24 rmind hci_detach_pcb(sc->sc_unit);
348 1.10 plunky sc->sc_unit = NULL;
349 1.10 plunky }
350 1.1 kiyohara
351 1.25 ozaki callout_halt(&sc->sc_seq_timer, NULL);
352 1.5 plunky callout_destroy(&sc->sc_seq_timer);
353 1.5 plunky
354 1.25 ozaki callout_halt(&sc->sc_le_timer, NULL);
355 1.5 plunky callout_destroy(&sc->sc_le_timer);
356 1.5 plunky
357 1.1 kiyohara return 0;
358 1.1 kiyohara }
359 1.1 kiyohara
360 1.1 kiyohara
361 1.1 kiyohara /*
362 1.1 kiyohara * Line discipline functions.
363 1.1 kiyohara */
364 1.1 kiyohara /* ARGSUSED */
365 1.1 kiyohara static int
366 1.1 kiyohara bcspopen(dev_t device __unused, struct tty *tp)
367 1.1 kiyohara {
368 1.1 kiyohara struct bcsp_softc *sc;
369 1.9 kiyohara device_t dev;
370 1.18 cegger cfdata_t cfdata;
371 1.1 kiyohara struct lwp *l = curlwp; /* XXX */
372 1.1 kiyohara int error, unit, s;
373 1.1 kiyohara static char name[] = "bcsp";
374 1.1 kiyohara
375 1.17 elad error = kauth_authorize_device(l->l_cred, KAUTH_DEVICE_BLUETOOTH_BCSP,
376 1.17 elad KAUTH_ARG(KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD), NULL, NULL, NULL);
377 1.17 elad if (error)
378 1.17 elad return (error);
379 1.1 kiyohara
380 1.1 kiyohara s = spltty();
381 1.1 kiyohara
382 1.1 kiyohara if (tp->t_linesw == &bcsp_disc) {
383 1.4 plunky sc = tp->t_sc;
384 1.1 kiyohara if (sc != NULL) {
385 1.1 kiyohara splx(s);
386 1.1 kiyohara return EBUSY;
387 1.1 kiyohara }
388 1.1 kiyohara }
389 1.1 kiyohara
390 1.1 kiyohara KASSERT(tp->t_oproc != NULL);
391 1.1 kiyohara
392 1.1 kiyohara cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
393 1.1 kiyohara for (unit = 0; unit < bcsp_cd.cd_ndevs; unit++)
394 1.13 cegger if (device_lookup(&bcsp_cd, unit) == NULL)
395 1.1 kiyohara break;
396 1.1 kiyohara cfdata->cf_name = name;
397 1.1 kiyohara cfdata->cf_atname = name;
398 1.1 kiyohara cfdata->cf_unit = unit;
399 1.1 kiyohara cfdata->cf_fstate = FSTATE_STAR;
400 1.1 kiyohara
401 1.14 christos aprint_normal("%s%d at tty major %llu minor %llu",
402 1.14 christos name, unit, (unsigned long long)major(tp->t_dev),
403 1.14 christos (unsigned long long)minor(tp->t_dev));
404 1.10 plunky dev = config_attach_pseudo(cfdata);
405 1.9 kiyohara if (dev == NULL) {
406 1.1 kiyohara splx(s);
407 1.1 kiyohara return EIO;
408 1.1 kiyohara }
409 1.9 kiyohara sc = device_private(dev);
410 1.6 ad
411 1.6 ad mutex_spin_enter(&tty_lock);
412 1.1 kiyohara tp->t_sc = sc;
413 1.1 kiyohara sc->sc_tp = tp;
414 1.1 kiyohara ttyflush(tp, FREAD | FWRITE);
415 1.6 ad mutex_spin_exit(&tty_lock);
416 1.1 kiyohara
417 1.1 kiyohara splx(s);
418 1.1 kiyohara
419 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_PKTSTART;
420 1.1 kiyohara bcsp_sequencing_reset(sc);
421 1.1 kiyohara
422 1.1 kiyohara /* start link-establishment */
423 1.10 plunky bcsp_start_le(sc);
424 1.1 kiyohara
425 1.1 kiyohara return 0;
426 1.1 kiyohara }
427 1.1 kiyohara
428 1.1 kiyohara /* ARGSUSED */
429 1.1 kiyohara static int
430 1.1 kiyohara bcspclose(struct tty *tp, int flag __unused)
431 1.1 kiyohara {
432 1.4 plunky struct bcsp_softc *sc = tp->t_sc;
433 1.18 cegger cfdata_t cfdata;
434 1.1 kiyohara int s;
435 1.1 kiyohara
436 1.1 kiyohara /* terminate link-establishment */
437 1.10 plunky bcsp_terminate_le(sc);
438 1.1 kiyohara
439 1.1 kiyohara s = spltty();
440 1.1 kiyohara
441 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_dgq);
442 1.1 kiyohara bcsp_sequencing_reset(sc);
443 1.1 kiyohara
444 1.6 ad mutex_spin_enter(&tty_lock);
445 1.1 kiyohara ttyflush(tp, FREAD | FWRITE);
446 1.6 ad mutex_spin_exit(&tty_lock); /* XXX */
447 1.1 kiyohara ttyldisc_release(tp->t_linesw);
448 1.1 kiyohara tp->t_linesw = ttyldisc_default();
449 1.1 kiyohara if (sc != NULL) {
450 1.1 kiyohara tp->t_sc = NULL;
451 1.1 kiyohara if (sc->sc_tp == tp) {
452 1.4 plunky cfdata = device_cfdata(sc->sc_dev);
453 1.4 plunky config_detach(sc->sc_dev, 0);
454 1.1 kiyohara free(cfdata, M_DEVBUF);
455 1.1 kiyohara }
456 1.1 kiyohara
457 1.1 kiyohara }
458 1.1 kiyohara splx(s);
459 1.1 kiyohara return 0;
460 1.1 kiyohara }
461 1.1 kiyohara
462 1.1 kiyohara /* ARGSUSED */
463 1.1 kiyohara static int
464 1.1 kiyohara bcspioctl(struct tty *tp, u_long cmd, void *data, int flag __unused,
465 1.1 kiyohara struct lwp *l __unused)
466 1.1 kiyohara {
467 1.4 plunky struct bcsp_softc *sc = tp->t_sc;
468 1.1 kiyohara int error;
469 1.1 kiyohara
470 1.31 knakahar /*
471 1.31 knakahar * XXX
472 1.31 knakahar * This function can be called without KERNEL_LOCK when caller's
473 1.31 knakahar * struct cdevsw is set D_MPSAFE. Is KERNEL_LOCK required?
474 1.31 knakahar */
475 1.31 knakahar
476 1.1 kiyohara if (sc == NULL || tp != sc->sc_tp)
477 1.1 kiyohara return EPASSTHROUGH;
478 1.1 kiyohara
479 1.1 kiyohara error = 0;
480 1.1 kiyohara switch (cmd) {
481 1.1 kiyohara default:
482 1.1 kiyohara error = EPASSTHROUGH;
483 1.1 kiyohara break;
484 1.1 kiyohara }
485 1.1 kiyohara
486 1.1 kiyohara return error;
487 1.1 kiyohara }
488 1.1 kiyohara
489 1.1 kiyohara
490 1.1 kiyohara /*
491 1.1 kiyohara * UART Driver Layer is supported by com-driver.
492 1.1 kiyohara */
493 1.1 kiyohara
494 1.1 kiyohara /*
495 1.1 kiyohara * BCSP SLIP Layer functions:
496 1.1 kiyohara * Supports to transmit/receive a byte stream.
497 1.1 kiyohara * SLIP protocol described in Internet standard RFC 1055.
498 1.1 kiyohara */
499 1.1 kiyohara static int
500 1.1 kiyohara bcsp_slip_transmit(struct tty *tp)
501 1.1 kiyohara {
502 1.4 plunky struct bcsp_softc *sc = tp->t_sc;
503 1.1 kiyohara struct mbuf *m;
504 1.1 kiyohara int count, rlen;
505 1.1 kiyohara uint8_t *rptr;
506 1.1 kiyohara
507 1.1 kiyohara m = sc->sc_txp;
508 1.1 kiyohara if (m == NULL) {
509 1.10 plunky sc->sc_flags &= ~BCSP_XMIT;
510 1.1 kiyohara bcsp_mux_transmit(sc);
511 1.1 kiyohara return 0;
512 1.1 kiyohara }
513 1.1 kiyohara
514 1.1 kiyohara count = 0;
515 1.1 kiyohara rlen = 0;
516 1.1 kiyohara rptr = mtod(m, uint8_t *);
517 1.1 kiyohara
518 1.1 kiyohara if (sc->sc_slip_txrsv != 0) {
519 1.1 kiyohara #ifdef BCSP_DEBUG
520 1.1 kiyohara if (sc->sc_slip_txrsv == BCSP_SLIP_PKTSTART)
521 1.1 kiyohara DPRINTFN(4, ("%s: slip transmit start\n",
522 1.9 kiyohara device_xname(sc->sc_dev)));
523 1.1 kiyohara else
524 1.1 kiyohara DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv));
525 1.1 kiyohara #endif
526 1.1 kiyohara
527 1.1 kiyohara if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0)
528 1.1 kiyohara return 0;
529 1.1 kiyohara count++;
530 1.1 kiyohara
531 1.1 kiyohara if (sc->sc_slip_txrsv == BCSP_SLIP_ESCAPE_PKTEND ||
532 1.1 kiyohara sc->sc_slip_txrsv == BCSP_SLIP_ESCAPE_ESCAPE) {
533 1.1 kiyohara rlen++;
534 1.1 kiyohara rptr++;
535 1.1 kiyohara }
536 1.1 kiyohara sc->sc_slip_txrsv = 0;
537 1.1 kiyohara }
538 1.1 kiyohara
539 1.1 kiyohara for(;;) {
540 1.1 kiyohara if (rlen >= m->m_len) {
541 1.1 kiyohara m = m->m_next;
542 1.1 kiyohara if (m == NULL) {
543 1.1 kiyohara if (putc(BCSP_SLIP_PKTEND, &tp->t_outq) < 0)
544 1.1 kiyohara break;
545 1.1 kiyohara
546 1.1 kiyohara DPRINTFN(4, ("\n%s: slip transmit end\n",
547 1.7 plunky device_xname(sc->sc_dev)));
548 1.1 kiyohara
549 1.1 kiyohara m = sc->sc_txp;
550 1.1 kiyohara sc->sc_txp = NULL;
551 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_PKTSTART;
552 1.1 kiyohara
553 1.1 kiyohara sc->sc_transmit_callback(sc, m);
554 1.1 kiyohara m = NULL;
555 1.1 kiyohara break;
556 1.1 kiyohara }
557 1.1 kiyohara
558 1.1 kiyohara rlen = 0;
559 1.1 kiyohara rptr = mtod(m, uint8_t *);
560 1.1 kiyohara continue;
561 1.1 kiyohara }
562 1.1 kiyohara
563 1.1 kiyohara if (*rptr == BCSP_SLIP_PKTEND) {
564 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE, &tp->t_outq) < 0)
565 1.1 kiyohara break;
566 1.1 kiyohara count++;
567 1.1 kiyohara DPRINTFN(4, (" esc "));
568 1.1 kiyohara
569 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) {
570 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_ESCAPE_PKTEND;
571 1.1 kiyohara break;
572 1.1 kiyohara }
573 1.1 kiyohara DPRINTFN(4, ("0x%02x ", BCSP_SLIP_ESCAPE_PKTEND));
574 1.9 kiyohara rptr++;
575 1.1 kiyohara } else if (*rptr == BCSP_SLIP_ESCAPE) {
576 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE, &tp->t_outq) < 0)
577 1.1 kiyohara break;
578 1.1 kiyohara count++;
579 1.1 kiyohara DPRINTFN(4, (" esc "));
580 1.1 kiyohara
581 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) {
582 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_ESCAPE_ESCAPE;
583 1.1 kiyohara break;
584 1.1 kiyohara }
585 1.1 kiyohara DPRINTFN(4, ("0x%02x ", BCSP_SLIP_ESCAPE_ESCAPE));
586 1.9 kiyohara rptr++;
587 1.1 kiyohara } else {
588 1.1 kiyohara if (putc(*rptr++, &tp->t_outq) < 0)
589 1.1 kiyohara break;
590 1.1 kiyohara DPRINTFN(4, ("0x%02x ", *(rptr - 1)));
591 1.1 kiyohara }
592 1.1 kiyohara rlen++;
593 1.1 kiyohara count++;
594 1.1 kiyohara }
595 1.1 kiyohara if (m != NULL)
596 1.1 kiyohara m_adj(m, rlen);
597 1.1 kiyohara
598 1.10 plunky sc->sc_stats.byte_tx += count;
599 1.1 kiyohara
600 1.1 kiyohara if (tp->t_outq.c_cc != 0)
601 1.1 kiyohara (*tp->t_oproc)(tp);
602 1.1 kiyohara
603 1.1 kiyohara return 0;
604 1.1 kiyohara }
605 1.1 kiyohara
606 1.1 kiyohara static int
607 1.1 kiyohara bcsp_slip_receive(int c, struct tty *tp)
608 1.1 kiyohara {
609 1.4 plunky struct bcsp_softc *sc = tp->t_sc;
610 1.1 kiyohara struct mbuf *m = sc->sc_rxp;
611 1.1 kiyohara int discard = 0;
612 1.1 kiyohara const char *errstr;
613 1.1 kiyohara
614 1.1 kiyohara c &= TTY_CHARMASK;
615 1.1 kiyohara
616 1.1 kiyohara /* If we already started a packet, find the trailing end of it. */
617 1.1 kiyohara if (m) {
618 1.1 kiyohara while (m->m_next)
619 1.1 kiyohara m = m->m_next;
620 1.1 kiyohara
621 1.1 kiyohara if (M_TRAILINGSPACE(m) == 0) {
622 1.1 kiyohara /* extend mbuf */
623 1.1 kiyohara MGET(m->m_next, M_DONTWAIT, MT_DATA);
624 1.1 kiyohara if (m->m_next == NULL) {
625 1.8 plunky aprint_error_dev(sc->sc_dev,
626 1.8 plunky "out of memory\n");
627 1.10 plunky sc->sc_stats.err_rx++;
628 1.1 kiyohara return 0; /* (lost sync) */
629 1.1 kiyohara }
630 1.1 kiyohara
631 1.1 kiyohara m = m->m_next;
632 1.9 kiyohara m->m_len = 0;
633 1.1 kiyohara }
634 1.1 kiyohara } else
635 1.1 kiyohara if (c != BCSP_SLIP_PKTSTART) {
636 1.1 kiyohara discard = 1;
637 1.1 kiyohara errstr = "not sync";
638 1.1 kiyohara goto discarded;
639 1.1 kiyohara }
640 1.1 kiyohara
641 1.1 kiyohara switch (c) {
642 1.1 kiyohara case BCSP_SLIP_PKTSTART /* or _PKTEND */:
643 1.1 kiyohara if (m == NULL) {
644 1.1 kiyohara /* BCSP_SLIP_PKTSTART */
645 1.1 kiyohara
646 1.1 kiyohara DPRINTFN(4, ("%s: slip receive start\n",
647 1.4 plunky device_xname(sc->sc_dev)));
648 1.1 kiyohara
649 1.1 kiyohara /* new packet */
650 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA);
651 1.1 kiyohara if (m == NULL) {
652 1.8 plunky aprint_error_dev(sc->sc_dev,
653 1.8 plunky "out of memory\n");
654 1.10 plunky sc->sc_stats.err_rx++;
655 1.1 kiyohara return 0; /* (lost sync) */
656 1.1 kiyohara }
657 1.1 kiyohara
658 1.1 kiyohara sc->sc_rxp = m;
659 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0;
660 1.1 kiyohara sc->sc_slip_rxexp = 0;
661 1.1 kiyohara } else {
662 1.1 kiyohara /* BCSP_SLIP_PKTEND */
663 1.1 kiyohara
664 1.1 kiyohara if (m == sc->sc_rxp && m->m_len == 0) {
665 1.1 kiyohara DPRINTFN(4, ("%s: resynchronises\n",
666 1.4 plunky device_xname(sc->sc_dev)));
667 1.1 kiyohara
668 1.10 plunky sc->sc_stats.byte_rx++;
669 1.1 kiyohara return 0;
670 1.1 kiyohara }
671 1.1 kiyohara
672 1.1 kiyohara DPRINTFN(4, ("%s%s: slip receive end\n",
673 1.1 kiyohara (m->m_len % 16 != 0) ? "\n" : "",
674 1.4 plunky device_xname(sc->sc_dev)));
675 1.1 kiyohara
676 1.1 kiyohara bcsp_pktintegrity_receive(sc, sc->sc_rxp);
677 1.1 kiyohara sc->sc_rxp = NULL;
678 1.1 kiyohara sc->sc_slip_rxexp = BCSP_SLIP_PKTSTART;
679 1.1 kiyohara }
680 1.10 plunky sc->sc_stats.byte_rx++;
681 1.1 kiyohara return 0;
682 1.1 kiyohara
683 1.1 kiyohara case BCSP_SLIP_ESCAPE:
684 1.1 kiyohara
685 1.1 kiyohara DPRINTFN(4, (" esc"));
686 1.1 kiyohara
687 1.1 kiyohara if (sc->sc_slip_rxexp == BCSP_SLIP_ESCAPE) {
688 1.1 kiyohara discard = 1;
689 1.1 kiyohara errstr = "waiting 0xdc or 0xdb";
690 1.1 kiyohara } else
691 1.1 kiyohara sc->sc_slip_rxexp = BCSP_SLIP_ESCAPE;
692 1.1 kiyohara break;
693 1.1 kiyohara
694 1.1 kiyohara default:
695 1.1 kiyohara DPRINTFN(4, (" 0x%02x%s",
696 1.1 kiyohara c, (m->m_len % 16 == 15) ? "\n" : ""));
697 1.1 kiyohara
698 1.1 kiyohara switch (sc->sc_slip_rxexp) {
699 1.1 kiyohara case BCSP_SLIP_PKTSTART:
700 1.1 kiyohara discard = 1;
701 1.1 kiyohara errstr = "waiting 0xc0";
702 1.1 kiyohara break;
703 1.1 kiyohara
704 1.1 kiyohara case BCSP_SLIP_ESCAPE:
705 1.1 kiyohara if (c == BCSP_SLIP_ESCAPE_PKTEND)
706 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] =
707 1.1 kiyohara BCSP_SLIP_PKTEND;
708 1.1 kiyohara else if (c == BCSP_SLIP_ESCAPE_ESCAPE)
709 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] =
710 1.1 kiyohara BCSP_SLIP_ESCAPE;
711 1.1 kiyohara else {
712 1.1 kiyohara discard = 1;
713 1.1 kiyohara errstr = "unknown escape";
714 1.1 kiyohara }
715 1.1 kiyohara sc->sc_slip_rxexp = 0;
716 1.1 kiyohara break;
717 1.1 kiyohara
718 1.1 kiyohara default:
719 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] = c;
720 1.1 kiyohara }
721 1.3 kiyohara sc->sc_rxp->m_pkthdr.len++;
722 1.1 kiyohara }
723 1.1 kiyohara if (discard) {
724 1.1 kiyohara discarded:
725 1.22 christos #ifdef BCSP_DEBUG
726 1.1 kiyohara DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n",
727 1.4 plunky device_xname(sc->sc_dev), c, errstr));
728 1.22 christos #else
729 1.22 christos __USE(errstr);
730 1.22 christos #endif
731 1.3 kiyohara }
732 1.10 plunky sc->sc_stats.byte_rx++;
733 1.1 kiyohara
734 1.1 kiyohara return 0;
735 1.1 kiyohara }
736 1.1 kiyohara
737 1.1 kiyohara
738 1.1 kiyohara /*
739 1.1 kiyohara * BCSP Packet Integrity Layer functions:
740 1.1 kiyohara * handling Payload Length, Checksum, CRC.
741 1.1 kiyohara */
742 1.1 kiyohara static void
743 1.1 kiyohara bcsp_pktintegrity_transmit(struct bcsp_softc *sc)
744 1.1 kiyohara {
745 1.9 kiyohara struct mbuf *m = sc->sc_txp;
746 1.1 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *);
747 1.9 kiyohara int pldlen;
748 1.1 kiyohara
749 1.4 plunky DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev)));
750 1.1 kiyohara
751 1.9 kiyohara pldlen = m->m_pkthdr.len - sizeof(bcsp_hdr_t);
752 1.1 kiyohara
753 1.1 kiyohara if (sc->sc_pi_txcrc)
754 1.1 kiyohara hdrp->flags |= BCSP_FLAGS_CRC_PRESENT;
755 1.1 kiyohara
756 1.1 kiyohara BCSP_SET_PLEN(hdrp, pldlen);
757 1.1 kiyohara BCSP_SET_CSUM(hdrp);
758 1.1 kiyohara
759 1.1 kiyohara if (sc->sc_pi_txcrc) {
760 1.9 kiyohara struct mbuf *_m;
761 1.1 kiyohara int n = 0;
762 1.1 kiyohara uint16_t crc = 0xffff;
763 1.1 kiyohara uint8_t *buf;
764 1.1 kiyohara
765 1.1 kiyohara for (_m = m; _m != NULL; _m = _m->m_next) {
766 1.1 kiyohara buf = mtod(_m, uint8_t *);
767 1.1 kiyohara for (n = 0; n < _m->m_len; n++)
768 1.1 kiyohara bcsp_crc_update(&crc, *(buf + n));
769 1.1 kiyohara }
770 1.1 kiyohara crc = htobe16(bcsp_crc_reverse(crc));
771 1.9 kiyohara m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc);
772 1.1 kiyohara }
773 1.1 kiyohara
774 1.1 kiyohara #ifdef BCSP_DEBUG
775 1.1 kiyohara if (bcsp_debug == 4)
776 1.1 kiyohara bcsp_packet_print(m);
777 1.1 kiyohara #endif
778 1.1 kiyohara
779 1.1 kiyohara bcsp_slip_transmit(sc->sc_tp);
780 1.1 kiyohara }
781 1.1 kiyohara
782 1.1 kiyohara static void
783 1.1 kiyohara bcsp_pktintegrity_receive(struct bcsp_softc *sc, struct mbuf *m)
784 1.1 kiyohara {
785 1.9 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *);
786 1.9 kiyohara u_int pldlen;
787 1.1 kiyohara int discard = 0;
788 1.1 kiyohara uint16_t crc = 0xffff;
789 1.30 maxv const char *errstr;
790 1.1 kiyohara
791 1.4 plunky DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev)));
792 1.1 kiyohara #ifdef BCSP_DEBUG
793 1.1 kiyohara if (bcsp_debug == 4)
794 1.1 kiyohara bcsp_packet_print(m);
795 1.1 kiyohara #endif
796 1.1 kiyohara
797 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t));
798 1.1 kiyohara
799 1.9 kiyohara pldlen = m->m_pkthdr.len - sizeof(bcsp_hdr_t) -
800 1.1 kiyohara ((hdrp->flags & BCSP_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0);
801 1.1 kiyohara if (pldlen > 0xfff) {
802 1.1 kiyohara discard = 1;
803 1.1 kiyohara errstr = "Payload Length";
804 1.1 kiyohara goto discarded;
805 1.1 kiyohara }
806 1.1 kiyohara if (hdrp->csum != BCSP_GET_CSUM(hdrp)) {
807 1.1 kiyohara discard = 1;
808 1.1 kiyohara errstr = "Checksum";
809 1.1 kiyohara goto discarded;
810 1.1 kiyohara }
811 1.1 kiyohara if (BCSP_GET_PLEN(hdrp) != pldlen) {
812 1.1 kiyohara discard = 1;
813 1.1 kiyohara errstr = "Payload Length";
814 1.1 kiyohara goto discarded;
815 1.1 kiyohara }
816 1.1 kiyohara if (hdrp->flags & BCSP_FLAGS_CRC_PRESENT) {
817 1.9 kiyohara struct mbuf *_m;
818 1.1 kiyohara int i, n;
819 1.1 kiyohara uint16_t crc0;
820 1.1 kiyohara uint8_t *buf;
821 1.1 kiyohara
822 1.1 kiyohara i = 0;
823 1.1 kiyohara n = 0;
824 1.1 kiyohara for (_m = m; _m != NULL; _m = _m->m_next) {
825 1.1 kiyohara buf = mtod(m, uint8_t *);
826 1.1 kiyohara for (n = 0;
827 1.1 kiyohara n < _m->m_len && i < sizeof(bcsp_hdr_t) + pldlen;
828 1.1 kiyohara n++, i++)
829 1.1 kiyohara bcsp_crc_update(&crc, *(buf + n));
830 1.1 kiyohara }
831 1.1 kiyohara
832 1.1 kiyohara m_copydata(_m, n, sizeof(crc0), &crc0);
833 1.1 kiyohara if (be16toh(crc0) != bcsp_crc_reverse(crc)) {
834 1.1 kiyohara discard = 1;
835 1.1 kiyohara errstr = "CRC";
836 1.1 kiyohara } else
837 1.1 kiyohara /* Shaves CRC */
838 1.2 kiyohara m_adj(m, (int)(0 - sizeof(crc)));
839 1.1 kiyohara }
840 1.1 kiyohara
841 1.1 kiyohara if (discard) {
842 1.1 kiyohara discarded:
843 1.22 christos #ifdef BCSP_DEBUG
844 1.1 kiyohara DPRINTFN(3, ("%s: receives unexpected packet: %s\n",
845 1.4 plunky device_xname(sc->sc_dev), errstr));
846 1.22 christos #else
847 1.22 christos __USE(errstr);
848 1.22 christos #endif
849 1.1 kiyohara m_freem(m);
850 1.1 kiyohara } else
851 1.1 kiyohara bcsp_mux_receive(sc, m);
852 1.1 kiyohara }
853 1.1 kiyohara
854 1.1 kiyohara static const uint16_t crctbl[] = {
855 1.1 kiyohara 0x0000, 0x1081, 0x2102, 0x3183,
856 1.1 kiyohara 0x4204, 0x5285, 0x6306, 0x7387,
857 1.1 kiyohara 0x8408, 0x9489, 0xa50a, 0xb58b,
858 1.1 kiyohara 0xc60c, 0xd68d, 0xe70e, 0xf78f,
859 1.1 kiyohara };
860 1.1 kiyohara
861 1.1 kiyohara static void
862 1.1 kiyohara bcsp_crc_update(uint16_t *crc, uint8_t d)
863 1.1 kiyohara {
864 1.1 kiyohara uint16_t reg = *crc;
865 1.1 kiyohara
866 1.1 kiyohara reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f];
867 1.1 kiyohara reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f];
868 1.1 kiyohara
869 1.1 kiyohara *crc = reg;
870 1.1 kiyohara }
871 1.1 kiyohara
872 1.1 kiyohara static uint16_t
873 1.1 kiyohara bcsp_crc_reverse(uint16_t crc)
874 1.1 kiyohara {
875 1.1 kiyohara uint16_t b, rev;
876 1.1 kiyohara
877 1.1 kiyohara for (b = 0, rev = 0; b < 16; b++) {
878 1.1 kiyohara rev = rev << 1;
879 1.1 kiyohara rev |= (crc & 1);
880 1.1 kiyohara crc = crc >> 1;
881 1.1 kiyohara }
882 1.1 kiyohara
883 1.1 kiyohara return rev;
884 1.1 kiyohara }
885 1.1 kiyohara
886 1.1 kiyohara
887 1.1 kiyohara /*
888 1.1 kiyohara * BCSP MUX Layer functions
889 1.1 kiyohara */
890 1.1 kiyohara static void
891 1.1 kiyohara bcsp_mux_transmit(struct bcsp_softc *sc)
892 1.1 kiyohara {
893 1.1 kiyohara struct mbuf *m;
894 1.1 kiyohara bcsp_hdr_t *hdrp;
895 1.1 kiyohara
896 1.10 plunky DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
897 1.10 plunky device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
898 1.1 kiyohara
899 1.1 kiyohara if (sc->sc_mux_choke) {
900 1.1 kiyohara struct mbuf *_m = NULL;
901 1.1 kiyohara
902 1.1 kiyohara /* In this case, send only Link Establishment packet */
903 1.1 kiyohara for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL;
904 1.1 kiyohara _m = m, m = MBUFQ_NEXT(m)) {
905 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
906 1.1 kiyohara if (hdrp->ident == BCSP_CHANNEL_LE) {
907 1.1 kiyohara if (m == MBUFQ_FIRST(&sc->sc_dgq))
908 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_dgq, m);
909 1.1 kiyohara else {
910 1.1 kiyohara if (m->m_nextpkt == NULL)
911 1.1 kiyohara sc->sc_dgq.mq_last =
912 1.1 kiyohara &_m->m_nextpkt;
913 1.1 kiyohara _m->m_nextpkt = m->m_nextpkt;
914 1.1 kiyohara m->m_nextpkt = NULL;
915 1.1 kiyohara }
916 1.1 kiyohara goto transmit;
917 1.1 kiyohara }
918 1.1 kiyohara }
919 1.1 kiyohara DPRINTFN(2, ("\n"));
920 1.1 kiyohara return;
921 1.1 kiyohara }
922 1.1 kiyohara
923 1.1 kiyohara /*
924 1.1 kiyohara * The MUX Layer always gives priority to packets from the Datagram
925 1.1 kiyohara * Queue Layer over the Sequencing Layer.
926 1.1 kiyohara */
927 1.1 kiyohara if (MBUFQ_FIRST(&sc->sc_dgq)) {
928 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_dgq, m);
929 1.1 kiyohara goto transmit;
930 1.1 kiyohara }
931 1.1 kiyohara if (MBUFQ_FIRST(&sc->sc_seqq)) {
932 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_seqq, m);
933 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
934 1.1 kiyohara hdrp->flags |= BCSP_FLAGS_PROTOCOL_REL; /* Reliable */
935 1.1 kiyohara goto transmit;
936 1.1 kiyohara }
937 1.10 plunky bcsp_start(sc);
938 1.1 kiyohara if (sc->sc_mux_send_ack == true) {
939 1.1 kiyohara m = bcsp_create_ackpkt();
940 1.1 kiyohara if (m != NULL)
941 1.1 kiyohara goto transmit;
942 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
943 1.10 plunky sc->sc_stats.err_tx++;
944 1.1 kiyohara }
945 1.1 kiyohara
946 1.1 kiyohara /* Nothing to send */
947 1.1 kiyohara DPRINTFN(2, ("\n"));
948 1.1 kiyohara return;
949 1.1 kiyohara
950 1.1 kiyohara transmit:
951 1.1 kiyohara DPRINTFN(2, (", txack=%d, send_ack=%d\n",
952 1.1 kiyohara bcsp_get_txack(sc), sc->sc_mux_send_ack));
953 1.1 kiyohara
954 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
955 1.1 kiyohara hdrp->flags |=
956 1.1 kiyohara (bcsp_get_txack(sc) << BCSP_FLAGS_ACK_SHIFT) & BCSP_FLAGS_ACK_MASK;
957 1.1 kiyohara if (sc->sc_mux_send_ack == true)
958 1.1 kiyohara sc->sc_mux_send_ack = false;
959 1.1 kiyohara
960 1.1 kiyohara #ifdef BCSP_DEBUG
961 1.1 kiyohara if (bcsp_debug == 3)
962 1.1 kiyohara bcsp_packet_print(m);
963 1.1 kiyohara #endif
964 1.1 kiyohara
965 1.1 kiyohara sc->sc_txp = m;
966 1.1 kiyohara bcsp_pktintegrity_transmit(sc);
967 1.1 kiyohara }
968 1.1 kiyohara
969 1.1 kiyohara static void
970 1.1 kiyohara bcsp_mux_receive(struct bcsp_softc *sc, struct mbuf *m)
971 1.1 kiyohara {
972 1.1 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *);
973 1.1 kiyohara const u_int rxack = BCSP_FLAGS_ACK(hdrp->flags);
974 1.1 kiyohara
975 1.1 kiyohara DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
976 1.4 plunky device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
977 1.1 kiyohara #ifdef BCSP_DEBUG
978 1.1 kiyohara if (bcsp_debug == 3)
979 1.1 kiyohara bcsp_packet_print(m);
980 1.1 kiyohara #endif
981 1.1 kiyohara
982 1.1 kiyohara bcsp_signal_rxack(sc, rxack);
983 1.1 kiyohara
984 1.1 kiyohara microtime(&sc->sc_mux_lastrx);
985 1.1 kiyohara
986 1.1 kiyohara /* if the Ack Packet received then discard */
987 1.1 kiyohara if (BCSP_FLAGS_SEQ(hdrp->flags) == 0 &&
988 1.1 kiyohara hdrp->ident == BCSP_IDENT_ACKPKT &&
989 1.1 kiyohara BCSP_GET_PLEN(hdrp) == 0) {
990 1.1 kiyohara m_freem(m);
991 1.1 kiyohara return;
992 1.1 kiyohara }
993 1.1 kiyohara
994 1.1 kiyohara if (hdrp->flags & BCSP_FLAGS_PROTOCOL_REL)
995 1.1 kiyohara bcsp_sequencing_receive(sc, m);
996 1.1 kiyohara else
997 1.1 kiyohara bcsp_datagramq_receive(sc, m);
998 1.1 kiyohara }
999 1.1 kiyohara
1000 1.1 kiyohara static __inline void
1001 1.1 kiyohara bcsp_send_ack_command(struct bcsp_softc *sc)
1002 1.1 kiyohara {
1003 1.1 kiyohara
1004 1.4 plunky DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
1005 1.1 kiyohara
1006 1.1 kiyohara sc->sc_mux_send_ack = true;
1007 1.1 kiyohara }
1008 1.1 kiyohara
1009 1.1 kiyohara static __inline struct mbuf *
1010 1.15 cegger bcsp_create_ackpkt(void)
1011 1.1 kiyohara {
1012 1.1 kiyohara struct mbuf *m;
1013 1.1 kiyohara bcsp_hdr_t *hdrp;
1014 1.1 kiyohara
1015 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA);
1016 1.1 kiyohara if (m != NULL) {
1017 1.1 kiyohara m->m_pkthdr.len = m->m_len = sizeof(bcsp_hdr_t);
1018 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
1019 1.1 kiyohara /*
1020 1.1 kiyohara * An Ack Packet has the following fields:
1021 1.1 kiyohara * Ack Field: txack (not set yet)
1022 1.1 kiyohara * Seq Field: 0
1023 1.1 kiyohara * Protocol Identifier Field: 0
1024 1.1 kiyohara * Protocol Type Field: Any value
1025 1.1 kiyohara * Payload Length Field: 0
1026 1.1 kiyohara */
1027 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t));
1028 1.1 kiyohara }
1029 1.1 kiyohara return m;
1030 1.1 kiyohara }
1031 1.1 kiyohara
1032 1.1 kiyohara static __inline void
1033 1.1 kiyohara bcsp_set_choke(struct bcsp_softc *sc, bool choke)
1034 1.1 kiyohara {
1035 1.1 kiyohara
1036 1.4 plunky DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
1037 1.1 kiyohara
1038 1.1 kiyohara sc->sc_mux_choke = choke;
1039 1.1 kiyohara }
1040 1.1 kiyohara
1041 1.1 kiyohara
1042 1.1 kiyohara /*
1043 1.1 kiyohara * BCSP Sequencing Layer functions
1044 1.1 kiyohara */
1045 1.1 kiyohara static void
1046 1.1 kiyohara bcsp_sequencing_receive(struct bcsp_softc *sc, struct mbuf *m)
1047 1.1 kiyohara {
1048 1.1 kiyohara bcsp_hdr_t hdr;
1049 1.1 kiyohara uint32_t rxseq;
1050 1.1 kiyohara
1051 1.1 kiyohara m_copydata(m, 0, sizeof(bcsp_hdr_t), &hdr);
1052 1.1 kiyohara rxseq = BCSP_FLAGS_SEQ(hdr.flags);
1053 1.1 kiyohara
1054 1.1 kiyohara DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
1055 1.4 plunky device_xname(sc->sc_dev), rxseq, sc->sc_seq_expected_rxseq));
1056 1.1 kiyohara #ifdef BCSP_DEBUG
1057 1.1 kiyohara if (bcsp_debug == 2)
1058 1.1 kiyohara bcsp_packet_print(m);
1059 1.1 kiyohara #endif
1060 1.1 kiyohara
1061 1.3 kiyohara /*
1062 1.3 kiyohara * We remove the header of BCSP and add the 'uint8_t type' of
1063 1.3 kiyohara * hci_*_hdr_t to the head.
1064 1.3 kiyohara */
1065 1.3 kiyohara m_adj(m, sizeof(bcsp_hdr_t) - sizeof(uint8_t));
1066 1.3 kiyohara
1067 1.1 kiyohara if (rxseq != sc->sc_seq_expected_rxseq) {
1068 1.1 kiyohara m_freem(m);
1069 1.1 kiyohara
1070 1.1 kiyohara /* send ack packet, if needly */
1071 1.1 kiyohara bcsp_mux_transmit(sc);
1072 1.1 kiyohara
1073 1.1 kiyohara return;
1074 1.1 kiyohara }
1075 1.1 kiyohara
1076 1.1 kiyohara switch (hdr.ident) {
1077 1.1 kiyohara case BCSP_CHANNEL_HCI_CMDEVT:
1078 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
1079 1.10 plunky if (!hci_input_event(sc->sc_unit, m))
1080 1.10 plunky sc->sc_stats.err_rx++;
1081 1.10 plunky
1082 1.10 plunky sc->sc_stats.evt_rx++;
1083 1.1 kiyohara break;
1084 1.1 kiyohara
1085 1.1 kiyohara case BCSP_CHANNEL_HCI_ACL:
1086 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
1087 1.10 plunky if (!hci_input_acl(sc->sc_unit, m))
1088 1.10 plunky sc->sc_stats.err_rx++;
1089 1.10 plunky
1090 1.10 plunky sc->sc_stats.acl_rx++;
1091 1.1 kiyohara break;
1092 1.1 kiyohara
1093 1.1 kiyohara case BCSP_CHANNEL_HCI_SCO:
1094 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1095 1.10 plunky if (!hci_input_sco(sc->sc_unit, m))
1096 1.10 plunky sc->sc_stats.err_rx++;
1097 1.10 plunky
1098 1.10 plunky sc->sc_stats.sco_rx++;
1099 1.1 kiyohara break;
1100 1.1 kiyohara
1101 1.1 kiyohara case BCSP_CHANNEL_HQ:
1102 1.1 kiyohara case BCSP_CHANNEL_DEVMGT:
1103 1.1 kiyohara case BCSP_CHANNEL_L2CAP:
1104 1.1 kiyohara case BCSP_CHANNEL_RFCOMM:
1105 1.1 kiyohara case BCSP_CHANNEL_SDP:
1106 1.1 kiyohara case BCSP_CHANNEL_DFU:
1107 1.1 kiyohara case BCSP_CHANNEL_VM:
1108 1.1 kiyohara default:
1109 1.8 plunky aprint_error_dev(sc->sc_dev,
1110 1.8 plunky "received reliable packet with not support channel %d\n",
1111 1.8 plunky hdr.ident);
1112 1.1 kiyohara m_freem(m);
1113 1.1 kiyohara break;
1114 1.1 kiyohara }
1115 1.1 kiyohara
1116 1.1 kiyohara sc->sc_seq_expected_rxseq =
1117 1.1 kiyohara (sc->sc_seq_expected_rxseq + 1) & BCSP_FLAGS_SEQ_MASK;
1118 1.1 kiyohara sc->sc_seq_txack = sc->sc_seq_expected_rxseq;
1119 1.1 kiyohara bcsp_send_ack_command(sc);
1120 1.1 kiyohara }
1121 1.1 kiyohara
1122 1.1 kiyohara static bool
1123 1.1 kiyohara bcsp_tx_reliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id)
1124 1.1 kiyohara {
1125 1.1 kiyohara bcsp_hdr_t *hdrp;
1126 1.1 kiyohara struct mbuf *_m;
1127 1.1 kiyohara u_int pldlen;
1128 1.1 kiyohara int s;
1129 1.1 kiyohara
1130 1.1 kiyohara DPRINTFN(1, ("%s: seq transmit:"
1131 1.4 plunky "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
1132 1.1 kiyohara protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
1133 1.1 kiyohara
1134 1.1 kiyohara for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
1135 1.1 kiyohara if (_m->m_len < 0)
1136 1.28 christos goto out;
1137 1.1 kiyohara pldlen += _m->m_len;
1138 1.1 kiyohara }
1139 1.1 kiyohara if (pldlen > 0xfff)
1140 1.27 christos goto out;
1141 1.1 kiyohara if (protocol_id == BCSP_IDENT_ACKPKT || protocol_id > 15)
1142 1.27 christos goto out;
1143 1.1 kiyohara
1144 1.1 kiyohara if (sc->sc_seq_winspace == 0)
1145 1.27 christos goto out;
1146 1.1 kiyohara
1147 1.1 kiyohara M_PREPEND(m, sizeof(bcsp_hdr_t), M_DONTWAIT);
1148 1.1 kiyohara if (m == NULL) {
1149 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1150 1.1 kiyohara return false;
1151 1.1 kiyohara }
1152 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t));
1153 1.1 kiyohara
1154 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
1155 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t));
1156 1.1 kiyohara hdrp->flags |= sc->sc_seq_txseq;
1157 1.1 kiyohara hdrp->ident = protocol_id;
1158 1.1 kiyohara
1159 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1160 1.1 kiyohara
1161 1.1 kiyohara s = splserial();
1162 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seqq, m);
1163 1.1 kiyohara splx(s);
1164 1.1 kiyohara sc->sc_transmit_callback = bcsp_reliabletx_callback;
1165 1.1 kiyohara
1166 1.1 kiyohara #ifdef BCSP_DEBUG
1167 1.1 kiyohara if (bcsp_debug == 2)
1168 1.1 kiyohara bcsp_packet_print(m);
1169 1.1 kiyohara #endif
1170 1.1 kiyohara
1171 1.1 kiyohara sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BCSP_FLAGS_SEQ_MASK;
1172 1.1 kiyohara sc->sc_seq_winspace--;
1173 1.1 kiyohara _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1174 1.1 kiyohara if (_m == NULL) {
1175 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1176 1.27 christos goto out;
1177 1.1 kiyohara }
1178 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _m);
1179 1.1 kiyohara bcsp_mux_transmit(sc);
1180 1.1 kiyohara
1181 1.1 kiyohara return true;
1182 1.27 christos out:
1183 1.27 christos m_freem(m);
1184 1.27 christos return false;
1185 1.1 kiyohara }
1186 1.1 kiyohara
1187 1.1 kiyohara #if 0
1188 1.1 kiyohara static bool
1189 1.1 kiyohara bcsp_rx_reliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id)
1190 1.1 kiyohara {
1191 1.1 kiyohara
1192 1.1 kiyohara return false;
1193 1.1 kiyohara }
1194 1.1 kiyohara
1195 1.1 kiyohara /* XXXX: I can't understand meaning this function... */
1196 1.1 kiyohara static __inline void
1197 1.1 kiyohara bcsp_link_failed(struct bcsp_softc *sc)
1198 1.1 kiyohara {
1199 1.1 kiyohara
1200 1.1 kiyohara return (sc->sc_seq_retries >= sc->sc_seq_retry_limit);
1201 1.1 kiyohara }
1202 1.1 kiyohara #endif
1203 1.1 kiyohara
1204 1.1 kiyohara static __inline u_int
1205 1.1 kiyohara bcsp_get_txack(struct bcsp_softc *sc)
1206 1.1 kiyohara {
1207 1.1 kiyohara
1208 1.1 kiyohara return sc->sc_seq_txack;
1209 1.1 kiyohara }
1210 1.1 kiyohara
1211 1.1 kiyohara static void
1212 1.1 kiyohara bcsp_signal_rxack(struct bcsp_softc *sc, uint32_t rxack)
1213 1.1 kiyohara {
1214 1.1 kiyohara bcsp_hdr_t *hdrp;
1215 1.1 kiyohara struct mbuf *m;
1216 1.1 kiyohara uint32_t seqno = (rxack - 1) & BCSP_FLAGS_SEQ_MASK;
1217 1.1 kiyohara int s;
1218 1.1 kiyohara
1219 1.1 kiyohara DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
1220 1.4 plunky device_xname(sc->sc_dev), rxack));
1221 1.1 kiyohara
1222 1.1 kiyohara s = splserial();
1223 1.1 kiyohara m = MBUFQ_FIRST(&sc->sc_seq_retryq);
1224 1.1 kiyohara while (m != NULL) {
1225 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
1226 1.1 kiyohara if (BCSP_FLAGS_SEQ(hdrp->flags) == seqno) {
1227 1.1 kiyohara struct mbuf *m0;
1228 1.1 kiyohara
1229 1.1 kiyohara for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
1230 1.1 kiyohara m0 != MBUFQ_NEXT(m);
1231 1.1 kiyohara m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
1232 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
1233 1.1 kiyohara m_freem(m0);
1234 1.1 kiyohara sc->sc_seq_winspace++;
1235 1.1 kiyohara }
1236 1.1 kiyohara break;
1237 1.1 kiyohara }
1238 1.1 kiyohara m = MBUFQ_NEXT(m);
1239 1.1 kiyohara }
1240 1.1 kiyohara splx(s);
1241 1.1 kiyohara sc->sc_seq_retries = 0;
1242 1.1 kiyohara
1243 1.1 kiyohara if (sc->sc_seq_winspace == sc->sc_seq_winsize)
1244 1.1 kiyohara callout_stop(&sc->sc_seq_timer);
1245 1.1 kiyohara else
1246 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1247 1.1 kiyohara }
1248 1.1 kiyohara
1249 1.1 kiyohara static void
1250 1.1 kiyohara bcsp_reliabletx_callback(struct bcsp_softc *sc, struct mbuf *m)
1251 1.1 kiyohara {
1252 1.1 kiyohara
1253 1.1 kiyohara m_freem(m);
1254 1.1 kiyohara }
1255 1.1 kiyohara
1256 1.1 kiyohara static void
1257 1.1 kiyohara bcsp_timer_timeout(void *arg)
1258 1.1 kiyohara {
1259 1.1 kiyohara struct bcsp_softc *sc = arg;
1260 1.1 kiyohara struct mbuf *m, *_m;
1261 1.1 kiyohara int s, i = 0;
1262 1.1 kiyohara
1263 1.1 kiyohara DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
1264 1.4 plunky device_xname(sc->sc_dev), sc->sc_seq_retries));
1265 1.1 kiyohara
1266 1.1 kiyohara s = splserial();
1267 1.1 kiyohara for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
1268 1.1 kiyohara m = MBUFQ_NEXT(m)) {
1269 1.1 kiyohara _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1270 1.1 kiyohara if (_m == NULL) {
1271 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1272 1.1 kiyohara return;
1273 1.1 kiyohara }
1274 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
1275 1.1 kiyohara i++;
1276 1.1 kiyohara }
1277 1.1 kiyohara splx(s);
1278 1.1 kiyohara
1279 1.1 kiyohara if (i != 0) {
1280 1.1 kiyohara if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
1281 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1282 1.1 kiyohara else {
1283 1.8 plunky aprint_error_dev(sc->sc_dev,
1284 1.8 plunky "reached the retry limit."
1285 1.8 plunky " restart the link-establishment\n");
1286 1.3 kiyohara bcsp_sequencing_reset(sc);
1287 1.10 plunky bcsp_start_le(sc);
1288 1.1 kiyohara return;
1289 1.1 kiyohara }
1290 1.1 kiyohara }
1291 1.1 kiyohara bcsp_mux_transmit(sc);
1292 1.1 kiyohara }
1293 1.1 kiyohara
1294 1.1 kiyohara static void
1295 1.1 kiyohara bcsp_sequencing_reset(struct bcsp_softc *sc)
1296 1.1 kiyohara {
1297 1.1 kiyohara int s;
1298 1.1 kiyohara
1299 1.1 kiyohara s = splserial();
1300 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_seqq);
1301 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_seq_retryq);
1302 1.1 kiyohara splx(s);
1303 1.1 kiyohara
1304 1.1 kiyohara
1305 1.1 kiyohara sc->sc_seq_txseq = 0;
1306 1.1 kiyohara sc->sc_seq_txack = 0;
1307 1.1 kiyohara sc->sc_seq_winspace = sc->sc_seq_winsize;
1308 1.1 kiyohara sc->sc_seq_retries = 0;
1309 1.1 kiyohara callout_stop(&sc->sc_seq_timer);
1310 1.1 kiyohara
1311 1.1 kiyohara sc->sc_mux_send_ack = false;
1312 1.1 kiyohara
1313 1.1 kiyohara /* XXXX: expected_rxseq should be set by MUX Layer */
1314 1.1 kiyohara sc->sc_seq_expected_rxseq = 0;
1315 1.1 kiyohara }
1316 1.1 kiyohara
1317 1.1 kiyohara
1318 1.1 kiyohara /*
1319 1.1 kiyohara * BCSP Datagram Queue Layer functions
1320 1.1 kiyohara */
1321 1.1 kiyohara static void
1322 1.1 kiyohara bcsp_datagramq_receive(struct bcsp_softc *sc, struct mbuf *m)
1323 1.1 kiyohara {
1324 1.1 kiyohara bcsp_hdr_t hdr;
1325 1.1 kiyohara
1326 1.4 plunky DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
1327 1.1 kiyohara #ifdef BCSP_DEBUG
1328 1.1 kiyohara if (bcsp_debug == 2)
1329 1.1 kiyohara bcsp_packet_print(m);
1330 1.1 kiyohara #endif
1331 1.1 kiyohara
1332 1.1 kiyohara m_copydata(m, 0, sizeof(bcsp_hdr_t), &hdr);
1333 1.1 kiyohara
1334 1.1 kiyohara switch (hdr.ident) {
1335 1.1 kiyohara case BCSP_CHANNEL_LE:
1336 1.1 kiyohara m_adj(m, sizeof(bcsp_hdr_t));
1337 1.10 plunky bcsp_input_le(sc, m);
1338 1.1 kiyohara break;
1339 1.1 kiyohara
1340 1.1 kiyohara case BCSP_CHANNEL_HCI_SCO:
1341 1.1 kiyohara /*
1342 1.1 kiyohara * We remove the header of BCSP and add the 'uint8_t type' of
1343 1.1 kiyohara * hci_scodata_hdr_t to the head.
1344 1.1 kiyohara */
1345 1.1 kiyohara m_adj(m, sizeof(bcsp_hdr_t) - sizeof(uint8_t));
1346 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1347 1.10 plunky if (!hci_input_sco(sc->sc_unit, m))
1348 1.10 plunky sc->sc_stats.err_rx++;
1349 1.10 plunky
1350 1.10 plunky sc->sc_stats.sco_rx++;
1351 1.1 kiyohara break;
1352 1.1 kiyohara
1353 1.1 kiyohara default:
1354 1.8 plunky aprint_error_dev(sc->sc_dev,
1355 1.8 plunky "received unreliable packet with not support channel %d\n",
1356 1.8 plunky hdr.ident);
1357 1.1 kiyohara m_freem(m);
1358 1.1 kiyohara break;
1359 1.1 kiyohara }
1360 1.1 kiyohara }
1361 1.1 kiyohara
1362 1.1 kiyohara static bool
1363 1.1 kiyohara bcsp_tx_unreliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id)
1364 1.1 kiyohara {
1365 1.1 kiyohara bcsp_hdr_t *hdrp;
1366 1.1 kiyohara struct mbuf *_m;
1367 1.1 kiyohara u_int pldlen;
1368 1.1 kiyohara int s;
1369 1.1 kiyohara
1370 1.1 kiyohara DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
1371 1.4 plunky device_xname(sc->sc_dev), protocol_id));
1372 1.1 kiyohara
1373 1.1 kiyohara for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
1374 1.1 kiyohara if (_m->m_len < 0)
1375 1.28 christos goto out;
1376 1.1 kiyohara pldlen += _m->m_len;
1377 1.1 kiyohara }
1378 1.1 kiyohara DPRINTFN(1, (" pldlen=%d\n", pldlen));
1379 1.1 kiyohara if (pldlen > 0xfff)
1380 1.27 christos goto out;
1381 1.1 kiyohara if (protocol_id == BCSP_IDENT_ACKPKT || protocol_id > 15)
1382 1.27 christos goto out;
1383 1.1 kiyohara
1384 1.1 kiyohara M_PREPEND(m, sizeof(bcsp_hdr_t), M_DONTWAIT);
1385 1.1 kiyohara if (m == NULL) {
1386 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1387 1.1 kiyohara return false;
1388 1.1 kiyohara }
1389 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t));
1390 1.1 kiyohara
1391 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *);
1392 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t));
1393 1.1 kiyohara hdrp->ident = protocol_id;
1394 1.1 kiyohara
1395 1.1 kiyohara s = splserial();
1396 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_dgq, m);
1397 1.1 kiyohara splx(s);
1398 1.1 kiyohara sc->sc_transmit_callback = bcsp_unreliabletx_callback;
1399 1.1 kiyohara
1400 1.1 kiyohara #ifdef BCSP_DEBUG
1401 1.1 kiyohara if (bcsp_debug == 2)
1402 1.1 kiyohara bcsp_packet_print(m);
1403 1.1 kiyohara #endif
1404 1.1 kiyohara
1405 1.1 kiyohara bcsp_mux_transmit(sc);
1406 1.1 kiyohara
1407 1.1 kiyohara return true;
1408 1.27 christos out:
1409 1.27 christos m_freem(m);
1410 1.27 christos return false;
1411 1.1 kiyohara }
1412 1.1 kiyohara
1413 1.1 kiyohara #if 0
1414 1.1 kiyohara static bool
1415 1.1 kiyohara bcsp_rx_unreliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id)
1416 1.1 kiyohara {
1417 1.1 kiyohara
1418 1.1 kiyohara return false;
1419 1.1 kiyohara }
1420 1.1 kiyohara #endif
1421 1.1 kiyohara
1422 1.1 kiyohara static void
1423 1.1 kiyohara bcsp_unreliabletx_callback(struct bcsp_softc *sc, struct mbuf *m)
1424 1.1 kiyohara {
1425 1.1 kiyohara
1426 1.1 kiyohara if (M_GETCTX(m, void *) == NULL)
1427 1.1 kiyohara m_freem(m);
1428 1.10 plunky else if (!hci_complete_sco(sc->sc_unit, m))
1429 1.10 plunky sc->sc_stats.err_tx++;
1430 1.1 kiyohara }
1431 1.1 kiyohara
1432 1.1 kiyohara
1433 1.1 kiyohara /*
1434 1.1 kiyohara * BlueCore Link Establishment Protocol functions
1435 1.1 kiyohara */
1436 1.1 kiyohara static const uint8_t sync[] = BCSP_LE_SYNC;
1437 1.1 kiyohara static const uint8_t syncresp[] = BCSP_LE_SYNCRESP;
1438 1.1 kiyohara static const uint8_t conf[] = BCSP_LE_CONF;
1439 1.1 kiyohara static const uint8_t confresp[] = BCSP_LE_CONFRESP;
1440 1.1 kiyohara
1441 1.1 kiyohara static int
1442 1.10 plunky bcsp_start_le(struct bcsp_softc *sc)
1443 1.1 kiyohara {
1444 1.1 kiyohara
1445 1.4 plunky DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
1446 1.1 kiyohara
1447 1.1 kiyohara bcsp_set_choke(sc, true);
1448 1.1 kiyohara
1449 1.1 kiyohara if (!sc->sc_le_muzzled) {
1450 1.1 kiyohara struct mbuf *m;
1451 1.1 kiyohara
1452 1.1 kiyohara m = m_gethdr(M_WAIT, MT_DATA);
1453 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0;
1454 1.1 kiyohara m_copyback(m, 0, sizeof(sync), sync);
1455 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE)) {
1456 1.8 plunky aprint_error_dev(sc->sc_dev,
1457 1.8 plunky "le-packet transmit failed\n");
1458 1.1 kiyohara return EINVAL;
1459 1.1 kiyohara }
1460 1.1 kiyohara }
1461 1.1 kiyohara callout_schedule(&sc->sc_le_timer, BCSP_LE_TSHY_TIMEOUT);
1462 1.1 kiyohara
1463 1.1 kiyohara sc->sc_le_state = le_state_shy;
1464 1.1 kiyohara return 0;
1465 1.1 kiyohara }
1466 1.1 kiyohara
1467 1.1 kiyohara static void
1468 1.10 plunky bcsp_terminate_le(struct bcsp_softc *sc)
1469 1.1 kiyohara {
1470 1.1 kiyohara struct mbuf *m;
1471 1.1 kiyohara
1472 1.1 kiyohara /* terminate link-establishment */
1473 1.1 kiyohara callout_stop(&sc->sc_le_timer);
1474 1.1 kiyohara bcsp_set_choke(sc, true);
1475 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA);
1476 1.1 kiyohara if (m == NULL)
1477 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1478 1.1 kiyohara else {
1479 1.1 kiyohara /* length of le packets is 4 */
1480 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0;
1481 1.1 kiyohara m_copyback(m, 0, sizeof(sync), sync);
1482 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE))
1483 1.8 plunky aprint_error_dev(sc->sc_dev,
1484 1.8 plunky "link-establishment terminations failed\n");
1485 1.1 kiyohara }
1486 1.1 kiyohara }
1487 1.1 kiyohara
1488 1.1 kiyohara static void
1489 1.10 plunky bcsp_input_le(struct bcsp_softc *sc, struct mbuf *m)
1490 1.1 kiyohara {
1491 1.1 kiyohara uint32_t *rcvpkt;
1492 1.1 kiyohara int i;
1493 1.1 kiyohara const uint8_t *rplypkt;
1494 1.1 kiyohara static struct {
1495 1.1 kiyohara const char *type;
1496 1.1 kiyohara const uint8_t *datap;
1497 1.1 kiyohara } pkt[] = {
1498 1.1 kiyohara { "sync", sync },
1499 1.1 kiyohara { "sync-resp", syncresp },
1500 1.1 kiyohara { "conf", conf },
1501 1.1 kiyohara { "conf-resp", confresp },
1502 1.1 kiyohara
1503 1.2 kiyohara { NULL, 0 }
1504 1.1 kiyohara };
1505 1.1 kiyohara
1506 1.1 kiyohara DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
1507 1.4 plunky device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1508 1.1 kiyohara #ifdef BCSP_DEBUG
1509 1.1 kiyohara if (bcsp_debug == 1)
1510 1.1 kiyohara bcsp_packet_print(m);
1511 1.1 kiyohara #endif
1512 1.1 kiyohara
1513 1.1 kiyohara rcvpkt = mtod(m, uint32_t *);
1514 1.11 plunky i = 0;
1515 1.1 kiyohara
1516 1.1 kiyohara /* length of le packets is 4 */
1517 1.1 kiyohara if (m->m_len == sizeof(uint32_t))
1518 1.1 kiyohara for (i = 0; pkt[i].type != NULL; i++)
1519 1.1 kiyohara if (*(const uint32_t *)pkt[i].datap == *rcvpkt)
1520 1.1 kiyohara break;
1521 1.1 kiyohara if (m->m_len != sizeof(uint32_t) || pkt[i].type == NULL) {
1522 1.8 plunky aprint_error_dev(sc->sc_dev, "received unknown packet\n");
1523 1.1 kiyohara m_freem(m);
1524 1.1 kiyohara return;
1525 1.1 kiyohara }
1526 1.1 kiyohara
1527 1.1 kiyohara rplypkt = NULL;
1528 1.1 kiyohara switch (sc->sc_le_state) {
1529 1.1 kiyohara case le_state_shy:
1530 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)sync) {
1531 1.1 kiyohara sc->sc_le_muzzled = false;
1532 1.1 kiyohara rplypkt = syncresp;
1533 1.1 kiyohara } else if (*rcvpkt == *(const uint32_t *)syncresp) {
1534 1.1 kiyohara DPRINTF(("%s: state change to curious\n",
1535 1.4 plunky device_xname(sc->sc_dev)));
1536 1.1 kiyohara
1537 1.1 kiyohara rplypkt = conf;
1538 1.1 kiyohara callout_schedule(&sc->sc_le_timer,
1539 1.1 kiyohara BCSP_LE_TCONF_TIMEOUT);
1540 1.1 kiyohara sc->sc_le_state = le_state_curious;
1541 1.1 kiyohara } else
1542 1.8 plunky aprint_error_dev(sc->sc_dev,
1543 1.8 plunky "received an unknown packet at shy\n");
1544 1.1 kiyohara break;
1545 1.1 kiyohara
1546 1.1 kiyohara case le_state_curious:
1547 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)sync)
1548 1.1 kiyohara rplypkt = syncresp;
1549 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)conf)
1550 1.1 kiyohara rplypkt = confresp;
1551 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)confresp) {
1552 1.1 kiyohara DPRINTF(("%s: state change to garrulous:\n",
1553 1.4 plunky device_xname(sc->sc_dev)));
1554 1.1 kiyohara
1555 1.1 kiyohara bcsp_set_choke(sc, false);
1556 1.1 kiyohara callout_stop(&sc->sc_le_timer);
1557 1.1 kiyohara sc->sc_le_state = le_state_garrulous;
1558 1.1 kiyohara } else
1559 1.8 plunky aprint_error_dev(sc->sc_dev,
1560 1.8 plunky "received unknown packet at curious\n");
1561 1.1 kiyohara break;
1562 1.1 kiyohara
1563 1.1 kiyohara case le_state_garrulous:
1564 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)conf)
1565 1.1 kiyohara rplypkt = confresp;
1566 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)sync) {
1567 1.1 kiyohara /* XXXXX */
1568 1.8 plunky aprint_error_dev(sc->sc_dev,
1569 1.8 plunky "received sync! peer to reset?\n");
1570 1.1 kiyohara
1571 1.3 kiyohara bcsp_sequencing_reset(sc);
1572 1.3 kiyohara rplypkt = sync;
1573 1.1 kiyohara sc->sc_le_state = le_state_shy;
1574 1.1 kiyohara } else
1575 1.8 plunky aprint_error_dev(sc->sc_dev,
1576 1.8 plunky "received unknown packet at garrulous\n");
1577 1.1 kiyohara break;
1578 1.1 kiyohara }
1579 1.1 kiyohara
1580 1.1 kiyohara m_freem(m);
1581 1.1 kiyohara
1582 1.1 kiyohara if (rplypkt != NULL) {
1583 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA);
1584 1.1 kiyohara if (m == NULL)
1585 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1586 1.1 kiyohara else {
1587 1.1 kiyohara /* length of le packets is 4 */
1588 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0;
1589 1.1 kiyohara m_copyback(m, 0, 4, rplypkt);
1590 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE))
1591 1.8 plunky aprint_error_dev(sc->sc_dev,
1592 1.8 plunky "le-packet transmit failed\n");
1593 1.1 kiyohara }
1594 1.1 kiyohara }
1595 1.1 kiyohara }
1596 1.1 kiyohara
1597 1.1 kiyohara static void
1598 1.1 kiyohara bcsp_le_timeout(void *arg)
1599 1.1 kiyohara {
1600 1.1 kiyohara struct bcsp_softc *sc = arg;
1601 1.1 kiyohara struct mbuf *m;
1602 1.1 kiyohara int timeout;
1603 1.1 kiyohara const uint8_t *sndpkt = NULL;
1604 1.1 kiyohara
1605 1.1 kiyohara DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
1606 1.4 plunky device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1607 1.1 kiyohara
1608 1.1 kiyohara switch (sc->sc_le_state) {
1609 1.1 kiyohara case le_state_shy:
1610 1.1 kiyohara if (!sc->sc_le_muzzled)
1611 1.1 kiyohara sndpkt = sync;
1612 1.1 kiyohara timeout = BCSP_LE_TSHY_TIMEOUT;
1613 1.1 kiyohara break;
1614 1.1 kiyohara
1615 1.1 kiyohara case le_state_curious:
1616 1.1 kiyohara sndpkt = conf;
1617 1.1 kiyohara timeout = BCSP_LE_TCONF_TIMEOUT;
1618 1.1 kiyohara break;
1619 1.1 kiyohara
1620 1.1 kiyohara default:
1621 1.8 plunky aprint_error_dev(sc->sc_dev,
1622 1.8 plunky "timeout happen at unknown state %d\n", sc->sc_le_state);
1623 1.1 kiyohara return;
1624 1.1 kiyohara }
1625 1.1 kiyohara
1626 1.1 kiyohara if (sndpkt != NULL) {
1627 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA);
1628 1.1 kiyohara if (m == NULL)
1629 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n");
1630 1.1 kiyohara else {
1631 1.1 kiyohara /* length of le packets is 4 */
1632 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0;
1633 1.1 kiyohara m_copyback(m, 0, 4, sndpkt);
1634 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE))
1635 1.8 plunky aprint_error_dev(sc->sc_dev,
1636 1.8 plunky "le-packet transmit failed\n");
1637 1.1 kiyohara }
1638 1.1 kiyohara }
1639 1.1 kiyohara
1640 1.1 kiyohara callout_schedule(&sc->sc_le_timer, timeout);
1641 1.1 kiyohara }
1642 1.1 kiyohara
1643 1.1 kiyohara
1644 1.1 kiyohara /*
1645 1.1 kiyohara * BlueCore Serial Protocol functions.
1646 1.1 kiyohara */
1647 1.1 kiyohara static int
1648 1.7 plunky bcsp_enable(device_t self)
1649 1.1 kiyohara {
1650 1.7 plunky struct bcsp_softc *sc = device_private(self);
1651 1.10 plunky int s;
1652 1.1 kiyohara
1653 1.10 plunky if (sc->sc_flags & BCSP_ENABLED)
1654 1.1 kiyohara return 0;
1655 1.1 kiyohara
1656 1.10 plunky s = spltty();
1657 1.10 plunky
1658 1.10 plunky sc->sc_flags |= BCSP_ENABLED;
1659 1.10 plunky sc->sc_flags &= ~BCSP_XMIT;
1660 1.10 plunky
1661 1.10 plunky splx(s);
1662 1.1 kiyohara
1663 1.1 kiyohara return 0;
1664 1.1 kiyohara }
1665 1.1 kiyohara
1666 1.1 kiyohara static void
1667 1.7 plunky bcsp_disable(device_t self)
1668 1.1 kiyohara {
1669 1.7 plunky struct bcsp_softc *sc = device_private(self);
1670 1.10 plunky int s;
1671 1.1 kiyohara
1672 1.10 plunky if ((sc->sc_flags & BCSP_ENABLED) == 0)
1673 1.1 kiyohara return;
1674 1.1 kiyohara
1675 1.10 plunky s = spltty();
1676 1.10 plunky
1677 1.1 kiyohara if (sc->sc_rxp) {
1678 1.1 kiyohara m_freem(sc->sc_rxp);
1679 1.1 kiyohara sc->sc_rxp = NULL;
1680 1.1 kiyohara }
1681 1.1 kiyohara
1682 1.1 kiyohara if (sc->sc_txp) {
1683 1.1 kiyohara m_freem(sc->sc_txp);
1684 1.1 kiyohara sc->sc_txp = NULL;
1685 1.1 kiyohara }
1686 1.1 kiyohara
1687 1.10 plunky MBUFQ_DRAIN(&sc->sc_cmdq);
1688 1.10 plunky MBUFQ_DRAIN(&sc->sc_aclq);
1689 1.10 plunky MBUFQ_DRAIN(&sc->sc_scoq);
1690 1.10 plunky
1691 1.10 plunky sc->sc_flags &= ~BCSP_ENABLED;
1692 1.10 plunky splx(s);
1693 1.1 kiyohara }
1694 1.1 kiyohara
1695 1.1 kiyohara static void
1696 1.10 plunky bcsp_start(struct bcsp_softc *sc)
1697 1.1 kiyohara {
1698 1.1 kiyohara struct mbuf *m;
1699 1.1 kiyohara
1700 1.10 plunky KASSERT((sc->sc_flags & BCSP_XMIT) == 0);
1701 1.2 kiyohara KASSERT(sc->sc_txp == NULL);
1702 1.2 kiyohara
1703 1.10 plunky if (MBUFQ_FIRST(&sc->sc_aclq)) {
1704 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1705 1.10 plunky sc->sc_stats.acl_tx++;
1706 1.10 plunky sc->sc_flags |= BCSP_XMIT;
1707 1.1 kiyohara bcsp_tx_reliable_pkt(sc, m, BCSP_CHANNEL_HCI_ACL);
1708 1.1 kiyohara }
1709 1.1 kiyohara
1710 1.10 plunky if (MBUFQ_FIRST(&sc->sc_cmdq)) {
1711 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
1712 1.10 plunky sc->sc_stats.cmd_tx++;
1713 1.10 plunky sc->sc_flags |= BCSP_XMIT;
1714 1.1 kiyohara bcsp_tx_reliable_pkt(sc, m, BCSP_CHANNEL_HCI_CMDEVT);
1715 1.1 kiyohara }
1716 1.1 kiyohara
1717 1.10 plunky if (MBUFQ_FIRST(&sc->sc_scoq)) {
1718 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1719 1.10 plunky sc->sc_stats.sco_tx++;
1720 1.1 kiyohara /* XXXX: We can transmit with reliable */
1721 1.10 plunky sc->sc_flags |= BCSP_XMIT;
1722 1.1 kiyohara bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_HCI_SCO);
1723 1.1 kiyohara }
1724 1.1 kiyohara
1725 1.1 kiyohara return;
1726 1.1 kiyohara }
1727 1.1 kiyohara
1728 1.10 plunky static void
1729 1.10 plunky bcsp_output_cmd(device_t self, struct mbuf *m)
1730 1.10 plunky {
1731 1.10 plunky struct bcsp_softc *sc = device_private(self);
1732 1.10 plunky int s;
1733 1.10 plunky
1734 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED);
1735 1.10 plunky
1736 1.10 plunky m_adj(m, sizeof(uint8_t));
1737 1.10 plunky M_SETCTX(m, NULL);
1738 1.10 plunky
1739 1.10 plunky s = spltty();
1740 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
1741 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0)
1742 1.10 plunky bcsp_start(sc);
1743 1.10 plunky
1744 1.10 plunky splx(s);
1745 1.10 plunky }
1746 1.10 plunky
1747 1.10 plunky static void
1748 1.10 plunky bcsp_output_acl(device_t self, struct mbuf *m)
1749 1.10 plunky {
1750 1.10 plunky struct bcsp_softc *sc = device_private(self);
1751 1.10 plunky int s;
1752 1.10 plunky
1753 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED);
1754 1.10 plunky
1755 1.10 plunky m_adj(m, sizeof(uint8_t));
1756 1.10 plunky M_SETCTX(m, NULL);
1757 1.10 plunky
1758 1.10 plunky s = spltty();
1759 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_aclq, m);
1760 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0)
1761 1.10 plunky bcsp_start(sc);
1762 1.10 plunky
1763 1.10 plunky splx(s);
1764 1.10 plunky }
1765 1.10 plunky
1766 1.10 plunky static void
1767 1.10 plunky bcsp_output_sco(device_t self, struct mbuf *m)
1768 1.10 plunky {
1769 1.10 plunky struct bcsp_softc *sc = device_private(self);
1770 1.10 plunky int s;
1771 1.10 plunky
1772 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED);
1773 1.10 plunky
1774 1.10 plunky m_adj(m, sizeof(uint8_t));
1775 1.10 plunky
1776 1.10 plunky s = spltty();
1777 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_scoq, m);
1778 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0)
1779 1.10 plunky bcsp_start(sc);
1780 1.10 plunky
1781 1.10 plunky splx(s);
1782 1.10 plunky }
1783 1.10 plunky
1784 1.10 plunky static void
1785 1.10 plunky bcsp_stats(device_t self, struct bt_stats *dest, int flush)
1786 1.10 plunky {
1787 1.10 plunky struct bcsp_softc *sc = device_private(self);
1788 1.10 plunky int s;
1789 1.10 plunky
1790 1.10 plunky s = spltty();
1791 1.10 plunky memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1792 1.10 plunky
1793 1.10 plunky if (flush)
1794 1.10 plunky memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1795 1.10 plunky
1796 1.10 plunky splx(s);
1797 1.10 plunky }
1798 1.10 plunky
1799 1.1 kiyohara
1800 1.1 kiyohara #ifdef BCSP_DEBUG
1801 1.1 kiyohara static void
1802 1.1 kiyohara bcsp_packet_print(struct mbuf *m)
1803 1.1 kiyohara {
1804 1.1 kiyohara int i;
1805 1.1 kiyohara uint8_t *p;
1806 1.1 kiyohara
1807 1.1 kiyohara for ( ; m != NULL; m = m->m_next) {
1808 1.1 kiyohara p = mtod(m, uint8_t *);
1809 1.1 kiyohara for (i = 0; i < m->m_len; i++) {
1810 1.1 kiyohara if (i % 16 == 0)
1811 1.1 kiyohara printf(" ");
1812 1.1 kiyohara printf(" %02x", *(p + i));
1813 1.1 kiyohara if (i % 16 == 15)
1814 1.1 kiyohara printf("\n");
1815 1.1 kiyohara }
1816 1.1 kiyohara printf("\n");
1817 1.1 kiyohara }
1818 1.1 kiyohara }
1819 1.1 kiyohara #endif
1820