1 1.34 rin /* $NetBSD: bcsp.c,v 1.34 2024/07/05 04:31:50 rin 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.34 rin __KERNEL_RCSID(0, "$NetBSD: bcsp.c,v 1.34 2024/07/05 04:31:50 rin 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 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK); 391 1.1 kiyohara for (unit = 0; unit < bcsp_cd.cd_ndevs; unit++) 392 1.13 cegger if (device_lookup(&bcsp_cd, unit) == NULL) 393 1.1 kiyohara break; 394 1.1 kiyohara cfdata->cf_name = name; 395 1.1 kiyohara cfdata->cf_atname = name; 396 1.1 kiyohara cfdata->cf_unit = unit; 397 1.1 kiyohara cfdata->cf_fstate = FSTATE_STAR; 398 1.1 kiyohara 399 1.14 christos aprint_normal("%s%d at tty major %llu minor %llu", 400 1.14 christos name, unit, (unsigned long long)major(tp->t_dev), 401 1.14 christos (unsigned long long)minor(tp->t_dev)); 402 1.10 plunky dev = config_attach_pseudo(cfdata); 403 1.9 kiyohara if (dev == NULL) { 404 1.1 kiyohara splx(s); 405 1.1 kiyohara return EIO; 406 1.1 kiyohara } 407 1.9 kiyohara sc = device_private(dev); 408 1.6 ad 409 1.33 riastrad ttylock(tp); 410 1.1 kiyohara tp->t_sc = sc; 411 1.1 kiyohara sc->sc_tp = tp; 412 1.1 kiyohara ttyflush(tp, FREAD | FWRITE); 413 1.33 riastrad ttyunlock(tp); 414 1.1 kiyohara 415 1.1 kiyohara splx(s); 416 1.1 kiyohara 417 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_PKTSTART; 418 1.1 kiyohara bcsp_sequencing_reset(sc); 419 1.1 kiyohara 420 1.1 kiyohara /* start link-establishment */ 421 1.10 plunky bcsp_start_le(sc); 422 1.1 kiyohara 423 1.1 kiyohara return 0; 424 1.1 kiyohara } 425 1.1 kiyohara 426 1.1 kiyohara /* ARGSUSED */ 427 1.1 kiyohara static int 428 1.1 kiyohara bcspclose(struct tty *tp, int flag __unused) 429 1.1 kiyohara { 430 1.4 plunky struct bcsp_softc *sc = tp->t_sc; 431 1.18 cegger cfdata_t cfdata; 432 1.1 kiyohara int s; 433 1.1 kiyohara 434 1.1 kiyohara /* terminate link-establishment */ 435 1.10 plunky bcsp_terminate_le(sc); 436 1.1 kiyohara 437 1.1 kiyohara s = spltty(); 438 1.1 kiyohara 439 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_dgq); 440 1.1 kiyohara bcsp_sequencing_reset(sc); 441 1.1 kiyohara 442 1.33 riastrad ttylock(tp); 443 1.1 kiyohara ttyflush(tp, FREAD | FWRITE); 444 1.33 riastrad ttyunlock(tp); /* XXX */ 445 1.1 kiyohara ttyldisc_release(tp->t_linesw); 446 1.1 kiyohara tp->t_linesw = ttyldisc_default(); 447 1.1 kiyohara if (sc != NULL) { 448 1.1 kiyohara tp->t_sc = NULL; 449 1.1 kiyohara if (sc->sc_tp == tp) { 450 1.4 plunky cfdata = device_cfdata(sc->sc_dev); 451 1.4 plunky config_detach(sc->sc_dev, 0); 452 1.1 kiyohara free(cfdata, M_DEVBUF); 453 1.1 kiyohara } 454 1.1 kiyohara 455 1.1 kiyohara } 456 1.1 kiyohara splx(s); 457 1.1 kiyohara return 0; 458 1.1 kiyohara } 459 1.1 kiyohara 460 1.1 kiyohara /* ARGSUSED */ 461 1.1 kiyohara static int 462 1.1 kiyohara bcspioctl(struct tty *tp, u_long cmd, void *data, int flag __unused, 463 1.1 kiyohara struct lwp *l __unused) 464 1.1 kiyohara { 465 1.4 plunky struct bcsp_softc *sc = tp->t_sc; 466 1.1 kiyohara int error; 467 1.1 kiyohara 468 1.31 knakahar /* 469 1.31 knakahar * XXX 470 1.31 knakahar * This function can be called without KERNEL_LOCK when caller's 471 1.31 knakahar * struct cdevsw is set D_MPSAFE. Is KERNEL_LOCK required? 472 1.31 knakahar */ 473 1.31 knakahar 474 1.1 kiyohara if (sc == NULL || tp != sc->sc_tp) 475 1.1 kiyohara return EPASSTHROUGH; 476 1.1 kiyohara 477 1.1 kiyohara error = 0; 478 1.1 kiyohara switch (cmd) { 479 1.1 kiyohara default: 480 1.1 kiyohara error = EPASSTHROUGH; 481 1.1 kiyohara break; 482 1.1 kiyohara } 483 1.1 kiyohara 484 1.1 kiyohara return error; 485 1.1 kiyohara } 486 1.1 kiyohara 487 1.1 kiyohara 488 1.1 kiyohara /* 489 1.1 kiyohara * UART Driver Layer is supported by com-driver. 490 1.1 kiyohara */ 491 1.1 kiyohara 492 1.1 kiyohara /* 493 1.1 kiyohara * BCSP SLIP Layer functions: 494 1.1 kiyohara * Supports to transmit/receive a byte stream. 495 1.1 kiyohara * SLIP protocol described in Internet standard RFC 1055. 496 1.1 kiyohara */ 497 1.1 kiyohara static int 498 1.1 kiyohara bcsp_slip_transmit(struct tty *tp) 499 1.1 kiyohara { 500 1.4 plunky struct bcsp_softc *sc = tp->t_sc; 501 1.1 kiyohara struct mbuf *m; 502 1.1 kiyohara int count, rlen; 503 1.1 kiyohara uint8_t *rptr; 504 1.1 kiyohara 505 1.1 kiyohara m = sc->sc_txp; 506 1.1 kiyohara if (m == NULL) { 507 1.10 plunky sc->sc_flags &= ~BCSP_XMIT; 508 1.1 kiyohara bcsp_mux_transmit(sc); 509 1.1 kiyohara return 0; 510 1.1 kiyohara } 511 1.1 kiyohara 512 1.1 kiyohara count = 0; 513 1.1 kiyohara rlen = 0; 514 1.1 kiyohara rptr = mtod(m, uint8_t *); 515 1.1 kiyohara 516 1.1 kiyohara if (sc->sc_slip_txrsv != 0) { 517 1.1 kiyohara #ifdef BCSP_DEBUG 518 1.1 kiyohara if (sc->sc_slip_txrsv == BCSP_SLIP_PKTSTART) 519 1.1 kiyohara DPRINTFN(4, ("%s: slip transmit start\n", 520 1.9 kiyohara device_xname(sc->sc_dev))); 521 1.1 kiyohara else 522 1.1 kiyohara DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv)); 523 1.1 kiyohara #endif 524 1.1 kiyohara 525 1.1 kiyohara if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0) 526 1.1 kiyohara return 0; 527 1.1 kiyohara count++; 528 1.1 kiyohara 529 1.1 kiyohara if (sc->sc_slip_txrsv == BCSP_SLIP_ESCAPE_PKTEND || 530 1.1 kiyohara sc->sc_slip_txrsv == BCSP_SLIP_ESCAPE_ESCAPE) { 531 1.1 kiyohara rlen++; 532 1.1 kiyohara rptr++; 533 1.1 kiyohara } 534 1.1 kiyohara sc->sc_slip_txrsv = 0; 535 1.1 kiyohara } 536 1.1 kiyohara 537 1.1 kiyohara for(;;) { 538 1.1 kiyohara if (rlen >= m->m_len) { 539 1.1 kiyohara m = m->m_next; 540 1.1 kiyohara if (m == NULL) { 541 1.1 kiyohara if (putc(BCSP_SLIP_PKTEND, &tp->t_outq) < 0) 542 1.1 kiyohara break; 543 1.1 kiyohara 544 1.1 kiyohara DPRINTFN(4, ("\n%s: slip transmit end\n", 545 1.7 plunky device_xname(sc->sc_dev))); 546 1.1 kiyohara 547 1.1 kiyohara m = sc->sc_txp; 548 1.1 kiyohara sc->sc_txp = NULL; 549 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_PKTSTART; 550 1.1 kiyohara 551 1.1 kiyohara sc->sc_transmit_callback(sc, m); 552 1.1 kiyohara m = NULL; 553 1.1 kiyohara break; 554 1.1 kiyohara } 555 1.1 kiyohara 556 1.1 kiyohara rlen = 0; 557 1.1 kiyohara rptr = mtod(m, uint8_t *); 558 1.1 kiyohara continue; 559 1.1 kiyohara } 560 1.1 kiyohara 561 1.1 kiyohara if (*rptr == BCSP_SLIP_PKTEND) { 562 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE, &tp->t_outq) < 0) 563 1.1 kiyohara break; 564 1.1 kiyohara count++; 565 1.1 kiyohara DPRINTFN(4, (" esc ")); 566 1.1 kiyohara 567 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) { 568 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_ESCAPE_PKTEND; 569 1.1 kiyohara break; 570 1.1 kiyohara } 571 1.1 kiyohara DPRINTFN(4, ("0x%02x ", BCSP_SLIP_ESCAPE_PKTEND)); 572 1.9 kiyohara rptr++; 573 1.1 kiyohara } else if (*rptr == BCSP_SLIP_ESCAPE) { 574 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE, &tp->t_outq) < 0) 575 1.1 kiyohara break; 576 1.1 kiyohara count++; 577 1.1 kiyohara DPRINTFN(4, (" esc ")); 578 1.1 kiyohara 579 1.1 kiyohara if (putc(BCSP_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) { 580 1.1 kiyohara sc->sc_slip_txrsv = BCSP_SLIP_ESCAPE_ESCAPE; 581 1.1 kiyohara break; 582 1.1 kiyohara } 583 1.1 kiyohara DPRINTFN(4, ("0x%02x ", BCSP_SLIP_ESCAPE_ESCAPE)); 584 1.9 kiyohara rptr++; 585 1.1 kiyohara } else { 586 1.1 kiyohara if (putc(*rptr++, &tp->t_outq) < 0) 587 1.1 kiyohara break; 588 1.1 kiyohara DPRINTFN(4, ("0x%02x ", *(rptr - 1))); 589 1.1 kiyohara } 590 1.1 kiyohara rlen++; 591 1.1 kiyohara count++; 592 1.1 kiyohara } 593 1.1 kiyohara if (m != NULL) 594 1.1 kiyohara m_adj(m, rlen); 595 1.1 kiyohara 596 1.10 plunky sc->sc_stats.byte_tx += count; 597 1.1 kiyohara 598 1.32 plunky if (tp->t_outq.c_cc != 0 && tp->t_oproc != NULL) 599 1.1 kiyohara (*tp->t_oproc)(tp); 600 1.1 kiyohara 601 1.1 kiyohara return 0; 602 1.1 kiyohara } 603 1.1 kiyohara 604 1.1 kiyohara static int 605 1.1 kiyohara bcsp_slip_receive(int c, struct tty *tp) 606 1.1 kiyohara { 607 1.4 plunky struct bcsp_softc *sc = tp->t_sc; 608 1.1 kiyohara struct mbuf *m = sc->sc_rxp; 609 1.1 kiyohara int discard = 0; 610 1.1 kiyohara const char *errstr; 611 1.1 kiyohara 612 1.1 kiyohara c &= TTY_CHARMASK; 613 1.1 kiyohara 614 1.1 kiyohara /* If we already started a packet, find the trailing end of it. */ 615 1.1 kiyohara if (m) { 616 1.1 kiyohara while (m->m_next) 617 1.1 kiyohara m = m->m_next; 618 1.1 kiyohara 619 1.1 kiyohara if (M_TRAILINGSPACE(m) == 0) { 620 1.1 kiyohara /* extend mbuf */ 621 1.1 kiyohara MGET(m->m_next, M_DONTWAIT, MT_DATA); 622 1.1 kiyohara if (m->m_next == NULL) { 623 1.8 plunky aprint_error_dev(sc->sc_dev, 624 1.8 plunky "out of memory\n"); 625 1.10 plunky sc->sc_stats.err_rx++; 626 1.1 kiyohara return 0; /* (lost sync) */ 627 1.1 kiyohara } 628 1.1 kiyohara 629 1.1 kiyohara m = m->m_next; 630 1.9 kiyohara m->m_len = 0; 631 1.1 kiyohara } 632 1.1 kiyohara } else 633 1.1 kiyohara if (c != BCSP_SLIP_PKTSTART) { 634 1.1 kiyohara discard = 1; 635 1.1 kiyohara errstr = "not sync"; 636 1.1 kiyohara goto discarded; 637 1.1 kiyohara } 638 1.1 kiyohara 639 1.1 kiyohara switch (c) { 640 1.1 kiyohara case BCSP_SLIP_PKTSTART /* or _PKTEND */: 641 1.1 kiyohara if (m == NULL) { 642 1.1 kiyohara /* BCSP_SLIP_PKTSTART */ 643 1.1 kiyohara 644 1.1 kiyohara DPRINTFN(4, ("%s: slip receive start\n", 645 1.4 plunky device_xname(sc->sc_dev))); 646 1.1 kiyohara 647 1.1 kiyohara /* new packet */ 648 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA); 649 1.1 kiyohara if (m == NULL) { 650 1.8 plunky aprint_error_dev(sc->sc_dev, 651 1.8 plunky "out of memory\n"); 652 1.10 plunky sc->sc_stats.err_rx++; 653 1.1 kiyohara return 0; /* (lost sync) */ 654 1.1 kiyohara } 655 1.1 kiyohara 656 1.1 kiyohara sc->sc_rxp = m; 657 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0; 658 1.1 kiyohara sc->sc_slip_rxexp = 0; 659 1.1 kiyohara } else { 660 1.1 kiyohara /* BCSP_SLIP_PKTEND */ 661 1.1 kiyohara 662 1.1 kiyohara if (m == sc->sc_rxp && m->m_len == 0) { 663 1.1 kiyohara DPRINTFN(4, ("%s: resynchronises\n", 664 1.4 plunky device_xname(sc->sc_dev))); 665 1.1 kiyohara 666 1.10 plunky sc->sc_stats.byte_rx++; 667 1.1 kiyohara return 0; 668 1.1 kiyohara } 669 1.1 kiyohara 670 1.1 kiyohara DPRINTFN(4, ("%s%s: slip receive end\n", 671 1.1 kiyohara (m->m_len % 16 != 0) ? "\n" : "", 672 1.4 plunky device_xname(sc->sc_dev))); 673 1.1 kiyohara 674 1.1 kiyohara bcsp_pktintegrity_receive(sc, sc->sc_rxp); 675 1.1 kiyohara sc->sc_rxp = NULL; 676 1.1 kiyohara sc->sc_slip_rxexp = BCSP_SLIP_PKTSTART; 677 1.1 kiyohara } 678 1.10 plunky sc->sc_stats.byte_rx++; 679 1.1 kiyohara return 0; 680 1.1 kiyohara 681 1.1 kiyohara case BCSP_SLIP_ESCAPE: 682 1.1 kiyohara 683 1.1 kiyohara DPRINTFN(4, (" esc")); 684 1.1 kiyohara 685 1.1 kiyohara if (sc->sc_slip_rxexp == BCSP_SLIP_ESCAPE) { 686 1.1 kiyohara discard = 1; 687 1.1 kiyohara errstr = "waiting 0xdc or 0xdb"; 688 1.1 kiyohara } else 689 1.1 kiyohara sc->sc_slip_rxexp = BCSP_SLIP_ESCAPE; 690 1.1 kiyohara break; 691 1.1 kiyohara 692 1.1 kiyohara default: 693 1.1 kiyohara DPRINTFN(4, (" 0x%02x%s", 694 1.1 kiyohara c, (m->m_len % 16 == 15) ? "\n" : "")); 695 1.1 kiyohara 696 1.1 kiyohara switch (sc->sc_slip_rxexp) { 697 1.1 kiyohara case BCSP_SLIP_PKTSTART: 698 1.1 kiyohara discard = 1; 699 1.1 kiyohara errstr = "waiting 0xc0"; 700 1.1 kiyohara break; 701 1.1 kiyohara 702 1.1 kiyohara case BCSP_SLIP_ESCAPE: 703 1.1 kiyohara if (c == BCSP_SLIP_ESCAPE_PKTEND) 704 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] = 705 1.1 kiyohara BCSP_SLIP_PKTEND; 706 1.1 kiyohara else if (c == BCSP_SLIP_ESCAPE_ESCAPE) 707 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] = 708 1.1 kiyohara BCSP_SLIP_ESCAPE; 709 1.1 kiyohara else { 710 1.1 kiyohara discard = 1; 711 1.1 kiyohara errstr = "unknown escape"; 712 1.1 kiyohara } 713 1.1 kiyohara sc->sc_slip_rxexp = 0; 714 1.1 kiyohara break; 715 1.1 kiyohara 716 1.1 kiyohara default: 717 1.1 kiyohara mtod(m, uint8_t *)[m->m_len++] = c; 718 1.1 kiyohara } 719 1.3 kiyohara sc->sc_rxp->m_pkthdr.len++; 720 1.1 kiyohara } 721 1.1 kiyohara if (discard) { 722 1.1 kiyohara discarded: 723 1.22 christos #ifdef BCSP_DEBUG 724 1.1 kiyohara DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n", 725 1.4 plunky device_xname(sc->sc_dev), c, errstr)); 726 1.22 christos #else 727 1.22 christos __USE(errstr); 728 1.22 christos #endif 729 1.3 kiyohara } 730 1.10 plunky sc->sc_stats.byte_rx++; 731 1.1 kiyohara 732 1.1 kiyohara return 0; 733 1.1 kiyohara } 734 1.1 kiyohara 735 1.1 kiyohara 736 1.1 kiyohara /* 737 1.1 kiyohara * BCSP Packet Integrity Layer functions: 738 1.1 kiyohara * handling Payload Length, Checksum, CRC. 739 1.1 kiyohara */ 740 1.1 kiyohara static void 741 1.1 kiyohara bcsp_pktintegrity_transmit(struct bcsp_softc *sc) 742 1.1 kiyohara { 743 1.9 kiyohara struct mbuf *m = sc->sc_txp; 744 1.1 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *); 745 1.9 kiyohara int pldlen; 746 1.1 kiyohara 747 1.4 plunky DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev))); 748 1.1 kiyohara 749 1.9 kiyohara pldlen = m->m_pkthdr.len - sizeof(bcsp_hdr_t); 750 1.1 kiyohara 751 1.1 kiyohara if (sc->sc_pi_txcrc) 752 1.1 kiyohara hdrp->flags |= BCSP_FLAGS_CRC_PRESENT; 753 1.1 kiyohara 754 1.1 kiyohara BCSP_SET_PLEN(hdrp, pldlen); 755 1.1 kiyohara BCSP_SET_CSUM(hdrp); 756 1.1 kiyohara 757 1.1 kiyohara if (sc->sc_pi_txcrc) { 758 1.9 kiyohara struct mbuf *_m; 759 1.1 kiyohara int n = 0; 760 1.1 kiyohara uint16_t crc = 0xffff; 761 1.1 kiyohara uint8_t *buf; 762 1.1 kiyohara 763 1.1 kiyohara for (_m = m; _m != NULL; _m = _m->m_next) { 764 1.1 kiyohara buf = mtod(_m, uint8_t *); 765 1.1 kiyohara for (n = 0; n < _m->m_len; n++) 766 1.1 kiyohara bcsp_crc_update(&crc, *(buf + n)); 767 1.1 kiyohara } 768 1.1 kiyohara crc = htobe16(bcsp_crc_reverse(crc)); 769 1.9 kiyohara m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc); 770 1.1 kiyohara } 771 1.1 kiyohara 772 1.1 kiyohara #ifdef BCSP_DEBUG 773 1.1 kiyohara if (bcsp_debug == 4) 774 1.1 kiyohara bcsp_packet_print(m); 775 1.1 kiyohara #endif 776 1.1 kiyohara 777 1.1 kiyohara bcsp_slip_transmit(sc->sc_tp); 778 1.1 kiyohara } 779 1.1 kiyohara 780 1.1 kiyohara static void 781 1.1 kiyohara bcsp_pktintegrity_receive(struct bcsp_softc *sc, struct mbuf *m) 782 1.1 kiyohara { 783 1.9 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *); 784 1.9 kiyohara u_int pldlen; 785 1.1 kiyohara int discard = 0; 786 1.1 kiyohara uint16_t crc = 0xffff; 787 1.30 maxv const char *errstr; 788 1.1 kiyohara 789 1.4 plunky DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev))); 790 1.1 kiyohara #ifdef BCSP_DEBUG 791 1.1 kiyohara if (bcsp_debug == 4) 792 1.1 kiyohara bcsp_packet_print(m); 793 1.1 kiyohara #endif 794 1.1 kiyohara 795 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t)); 796 1.1 kiyohara 797 1.9 kiyohara pldlen = m->m_pkthdr.len - sizeof(bcsp_hdr_t) - 798 1.1 kiyohara ((hdrp->flags & BCSP_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0); 799 1.1 kiyohara if (pldlen > 0xfff) { 800 1.1 kiyohara discard = 1; 801 1.1 kiyohara errstr = "Payload Length"; 802 1.1 kiyohara goto discarded; 803 1.1 kiyohara } 804 1.1 kiyohara if (hdrp->csum != BCSP_GET_CSUM(hdrp)) { 805 1.1 kiyohara discard = 1; 806 1.1 kiyohara errstr = "Checksum"; 807 1.1 kiyohara goto discarded; 808 1.1 kiyohara } 809 1.1 kiyohara if (BCSP_GET_PLEN(hdrp) != pldlen) { 810 1.1 kiyohara discard = 1; 811 1.1 kiyohara errstr = "Payload Length"; 812 1.1 kiyohara goto discarded; 813 1.1 kiyohara } 814 1.1 kiyohara if (hdrp->flags & BCSP_FLAGS_CRC_PRESENT) { 815 1.9 kiyohara struct mbuf *_m; 816 1.1 kiyohara int i, n; 817 1.1 kiyohara uint16_t crc0; 818 1.1 kiyohara uint8_t *buf; 819 1.1 kiyohara 820 1.1 kiyohara i = 0; 821 1.1 kiyohara n = 0; 822 1.1 kiyohara for (_m = m; _m != NULL; _m = _m->m_next) { 823 1.1 kiyohara buf = mtod(m, uint8_t *); 824 1.1 kiyohara for (n = 0; 825 1.1 kiyohara n < _m->m_len && i < sizeof(bcsp_hdr_t) + pldlen; 826 1.1 kiyohara n++, i++) 827 1.1 kiyohara bcsp_crc_update(&crc, *(buf + n)); 828 1.1 kiyohara } 829 1.1 kiyohara 830 1.1 kiyohara m_copydata(_m, n, sizeof(crc0), &crc0); 831 1.1 kiyohara if (be16toh(crc0) != bcsp_crc_reverse(crc)) { 832 1.1 kiyohara discard = 1; 833 1.1 kiyohara errstr = "CRC"; 834 1.1 kiyohara } else 835 1.1 kiyohara /* Shaves CRC */ 836 1.2 kiyohara m_adj(m, (int)(0 - sizeof(crc))); 837 1.1 kiyohara } 838 1.1 kiyohara 839 1.1 kiyohara if (discard) { 840 1.1 kiyohara discarded: 841 1.22 christos #ifdef BCSP_DEBUG 842 1.1 kiyohara DPRINTFN(3, ("%s: receives unexpected packet: %s\n", 843 1.4 plunky device_xname(sc->sc_dev), errstr)); 844 1.22 christos #else 845 1.22 christos __USE(errstr); 846 1.22 christos #endif 847 1.1 kiyohara m_freem(m); 848 1.1 kiyohara } else 849 1.1 kiyohara bcsp_mux_receive(sc, m); 850 1.1 kiyohara } 851 1.1 kiyohara 852 1.1 kiyohara static const uint16_t crctbl[] = { 853 1.1 kiyohara 0x0000, 0x1081, 0x2102, 0x3183, 854 1.1 kiyohara 0x4204, 0x5285, 0x6306, 0x7387, 855 1.1 kiyohara 0x8408, 0x9489, 0xa50a, 0xb58b, 856 1.1 kiyohara 0xc60c, 0xd68d, 0xe70e, 0xf78f, 857 1.1 kiyohara }; 858 1.1 kiyohara 859 1.1 kiyohara static void 860 1.1 kiyohara bcsp_crc_update(uint16_t *crc, uint8_t d) 861 1.1 kiyohara { 862 1.1 kiyohara uint16_t reg = *crc; 863 1.1 kiyohara 864 1.1 kiyohara reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f]; 865 1.1 kiyohara reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f]; 866 1.1 kiyohara 867 1.1 kiyohara *crc = reg; 868 1.1 kiyohara } 869 1.1 kiyohara 870 1.1 kiyohara static uint16_t 871 1.1 kiyohara bcsp_crc_reverse(uint16_t crc) 872 1.1 kiyohara { 873 1.1 kiyohara uint16_t b, rev; 874 1.1 kiyohara 875 1.1 kiyohara for (b = 0, rev = 0; b < 16; b++) { 876 1.1 kiyohara rev = rev << 1; 877 1.1 kiyohara rev |= (crc & 1); 878 1.1 kiyohara crc = crc >> 1; 879 1.1 kiyohara } 880 1.1 kiyohara 881 1.1 kiyohara return rev; 882 1.1 kiyohara } 883 1.1 kiyohara 884 1.1 kiyohara 885 1.1 kiyohara /* 886 1.1 kiyohara * BCSP MUX Layer functions 887 1.1 kiyohara */ 888 1.1 kiyohara static void 889 1.1 kiyohara bcsp_mux_transmit(struct bcsp_softc *sc) 890 1.1 kiyohara { 891 1.1 kiyohara struct mbuf *m; 892 1.1 kiyohara bcsp_hdr_t *hdrp; 893 1.1 kiyohara 894 1.10 plunky DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d", 895 1.10 plunky device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke)); 896 1.1 kiyohara 897 1.1 kiyohara if (sc->sc_mux_choke) { 898 1.1 kiyohara struct mbuf *_m = NULL; 899 1.1 kiyohara 900 1.1 kiyohara /* In this case, send only Link Establishment packet */ 901 1.1 kiyohara for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL; 902 1.1 kiyohara _m = m, m = MBUFQ_NEXT(m)) { 903 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 904 1.1 kiyohara if (hdrp->ident == BCSP_CHANNEL_LE) { 905 1.1 kiyohara if (m == MBUFQ_FIRST(&sc->sc_dgq)) 906 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_dgq, m); 907 1.1 kiyohara else { 908 1.1 kiyohara if (m->m_nextpkt == NULL) 909 1.1 kiyohara sc->sc_dgq.mq_last = 910 1.1 kiyohara &_m->m_nextpkt; 911 1.1 kiyohara _m->m_nextpkt = m->m_nextpkt; 912 1.1 kiyohara m->m_nextpkt = NULL; 913 1.1 kiyohara } 914 1.1 kiyohara goto transmit; 915 1.1 kiyohara } 916 1.1 kiyohara } 917 1.1 kiyohara DPRINTFN(2, ("\n")); 918 1.1 kiyohara return; 919 1.1 kiyohara } 920 1.1 kiyohara 921 1.1 kiyohara /* 922 1.1 kiyohara * The MUX Layer always gives priority to packets from the Datagram 923 1.1 kiyohara * Queue Layer over the Sequencing Layer. 924 1.1 kiyohara */ 925 1.1 kiyohara if (MBUFQ_FIRST(&sc->sc_dgq)) { 926 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_dgq, m); 927 1.1 kiyohara goto transmit; 928 1.1 kiyohara } 929 1.1 kiyohara if (MBUFQ_FIRST(&sc->sc_seqq)) { 930 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_seqq, m); 931 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 932 1.1 kiyohara hdrp->flags |= BCSP_FLAGS_PROTOCOL_REL; /* Reliable */ 933 1.1 kiyohara goto transmit; 934 1.1 kiyohara } 935 1.10 plunky bcsp_start(sc); 936 1.1 kiyohara if (sc->sc_mux_send_ack == true) { 937 1.1 kiyohara m = bcsp_create_ackpkt(); 938 1.1 kiyohara if (m != NULL) 939 1.1 kiyohara goto transmit; 940 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 941 1.10 plunky sc->sc_stats.err_tx++; 942 1.1 kiyohara } 943 1.1 kiyohara 944 1.1 kiyohara /* Nothing to send */ 945 1.1 kiyohara DPRINTFN(2, ("\n")); 946 1.1 kiyohara return; 947 1.1 kiyohara 948 1.1 kiyohara transmit: 949 1.1 kiyohara DPRINTFN(2, (", txack=%d, send_ack=%d\n", 950 1.1 kiyohara bcsp_get_txack(sc), sc->sc_mux_send_ack)); 951 1.1 kiyohara 952 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 953 1.1 kiyohara hdrp->flags |= 954 1.1 kiyohara (bcsp_get_txack(sc) << BCSP_FLAGS_ACK_SHIFT) & BCSP_FLAGS_ACK_MASK; 955 1.1 kiyohara if (sc->sc_mux_send_ack == true) 956 1.1 kiyohara sc->sc_mux_send_ack = false; 957 1.1 kiyohara 958 1.1 kiyohara #ifdef BCSP_DEBUG 959 1.1 kiyohara if (bcsp_debug == 3) 960 1.1 kiyohara bcsp_packet_print(m); 961 1.1 kiyohara #endif 962 1.1 kiyohara 963 1.1 kiyohara sc->sc_txp = m; 964 1.1 kiyohara bcsp_pktintegrity_transmit(sc); 965 1.1 kiyohara } 966 1.1 kiyohara 967 1.1 kiyohara static void 968 1.1 kiyohara bcsp_mux_receive(struct bcsp_softc *sc, struct mbuf *m) 969 1.1 kiyohara { 970 1.1 kiyohara bcsp_hdr_t *hdrp = mtod(m, bcsp_hdr_t *); 971 1.1 kiyohara const u_int rxack = BCSP_FLAGS_ACK(hdrp->flags); 972 1.1 kiyohara 973 1.1 kiyohara DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n", 974 1.4 plunky device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack)); 975 1.1 kiyohara #ifdef BCSP_DEBUG 976 1.1 kiyohara if (bcsp_debug == 3) 977 1.1 kiyohara bcsp_packet_print(m); 978 1.1 kiyohara #endif 979 1.1 kiyohara 980 1.1 kiyohara bcsp_signal_rxack(sc, rxack); 981 1.1 kiyohara 982 1.1 kiyohara microtime(&sc->sc_mux_lastrx); 983 1.1 kiyohara 984 1.1 kiyohara /* if the Ack Packet received then discard */ 985 1.1 kiyohara if (BCSP_FLAGS_SEQ(hdrp->flags) == 0 && 986 1.1 kiyohara hdrp->ident == BCSP_IDENT_ACKPKT && 987 1.1 kiyohara BCSP_GET_PLEN(hdrp) == 0) { 988 1.1 kiyohara m_freem(m); 989 1.1 kiyohara return; 990 1.1 kiyohara } 991 1.1 kiyohara 992 1.1 kiyohara if (hdrp->flags & BCSP_FLAGS_PROTOCOL_REL) 993 1.1 kiyohara bcsp_sequencing_receive(sc, m); 994 1.1 kiyohara else 995 1.1 kiyohara bcsp_datagramq_receive(sc, m); 996 1.1 kiyohara } 997 1.1 kiyohara 998 1.1 kiyohara static __inline void 999 1.1 kiyohara bcsp_send_ack_command(struct bcsp_softc *sc) 1000 1.1 kiyohara { 1001 1.1 kiyohara 1002 1.4 plunky DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev))); 1003 1.1 kiyohara 1004 1.1 kiyohara sc->sc_mux_send_ack = true; 1005 1.1 kiyohara } 1006 1.1 kiyohara 1007 1.1 kiyohara static __inline struct mbuf * 1008 1.15 cegger bcsp_create_ackpkt(void) 1009 1.1 kiyohara { 1010 1.1 kiyohara struct mbuf *m; 1011 1.1 kiyohara bcsp_hdr_t *hdrp; 1012 1.1 kiyohara 1013 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA); 1014 1.1 kiyohara if (m != NULL) { 1015 1.1 kiyohara m->m_pkthdr.len = m->m_len = sizeof(bcsp_hdr_t); 1016 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 1017 1.1 kiyohara /* 1018 1.1 kiyohara * An Ack Packet has the following fields: 1019 1.1 kiyohara * Ack Field: txack (not set yet) 1020 1.1 kiyohara * Seq Field: 0 1021 1.1 kiyohara * Protocol Identifier Field: 0 1022 1.1 kiyohara * Protocol Type Field: Any value 1023 1.1 kiyohara * Payload Length Field: 0 1024 1.1 kiyohara */ 1025 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t)); 1026 1.1 kiyohara } 1027 1.1 kiyohara return m; 1028 1.1 kiyohara } 1029 1.1 kiyohara 1030 1.1 kiyohara static __inline void 1031 1.1 kiyohara bcsp_set_choke(struct bcsp_softc *sc, bool choke) 1032 1.1 kiyohara { 1033 1.1 kiyohara 1034 1.4 plunky DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke)); 1035 1.1 kiyohara 1036 1.1 kiyohara sc->sc_mux_choke = choke; 1037 1.1 kiyohara } 1038 1.1 kiyohara 1039 1.1 kiyohara 1040 1.1 kiyohara /* 1041 1.1 kiyohara * BCSP Sequencing Layer functions 1042 1.1 kiyohara */ 1043 1.1 kiyohara static void 1044 1.1 kiyohara bcsp_sequencing_receive(struct bcsp_softc *sc, struct mbuf *m) 1045 1.1 kiyohara { 1046 1.1 kiyohara bcsp_hdr_t hdr; 1047 1.1 kiyohara uint32_t rxseq; 1048 1.1 kiyohara 1049 1.1 kiyohara m_copydata(m, 0, sizeof(bcsp_hdr_t), &hdr); 1050 1.1 kiyohara rxseq = BCSP_FLAGS_SEQ(hdr.flags); 1051 1.1 kiyohara 1052 1.1 kiyohara DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n", 1053 1.4 plunky device_xname(sc->sc_dev), rxseq, sc->sc_seq_expected_rxseq)); 1054 1.1 kiyohara #ifdef BCSP_DEBUG 1055 1.1 kiyohara if (bcsp_debug == 2) 1056 1.1 kiyohara bcsp_packet_print(m); 1057 1.1 kiyohara #endif 1058 1.1 kiyohara 1059 1.3 kiyohara /* 1060 1.3 kiyohara * We remove the header of BCSP and add the 'uint8_t type' of 1061 1.3 kiyohara * hci_*_hdr_t to the head. 1062 1.3 kiyohara */ 1063 1.3 kiyohara m_adj(m, sizeof(bcsp_hdr_t) - sizeof(uint8_t)); 1064 1.3 kiyohara 1065 1.1 kiyohara if (rxseq != sc->sc_seq_expected_rxseq) { 1066 1.1 kiyohara m_freem(m); 1067 1.1 kiyohara 1068 1.1 kiyohara /* send ack packet, if needly */ 1069 1.1 kiyohara bcsp_mux_transmit(sc); 1070 1.1 kiyohara 1071 1.1 kiyohara return; 1072 1.1 kiyohara } 1073 1.1 kiyohara 1074 1.1 kiyohara switch (hdr.ident) { 1075 1.1 kiyohara case BCSP_CHANNEL_HCI_CMDEVT: 1076 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_EVENT_PKT; 1077 1.10 plunky if (!hci_input_event(sc->sc_unit, m)) 1078 1.10 plunky sc->sc_stats.err_rx++; 1079 1.10 plunky 1080 1.10 plunky sc->sc_stats.evt_rx++; 1081 1.1 kiyohara break; 1082 1.1 kiyohara 1083 1.1 kiyohara case BCSP_CHANNEL_HCI_ACL: 1084 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT; 1085 1.10 plunky if (!hci_input_acl(sc->sc_unit, m)) 1086 1.10 plunky sc->sc_stats.err_rx++; 1087 1.10 plunky 1088 1.10 plunky sc->sc_stats.acl_rx++; 1089 1.1 kiyohara break; 1090 1.1 kiyohara 1091 1.1 kiyohara case BCSP_CHANNEL_HCI_SCO: 1092 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT; 1093 1.10 plunky if (!hci_input_sco(sc->sc_unit, m)) 1094 1.10 plunky sc->sc_stats.err_rx++; 1095 1.10 plunky 1096 1.10 plunky sc->sc_stats.sco_rx++; 1097 1.1 kiyohara break; 1098 1.1 kiyohara 1099 1.1 kiyohara case BCSP_CHANNEL_HQ: 1100 1.1 kiyohara case BCSP_CHANNEL_DEVMGT: 1101 1.1 kiyohara case BCSP_CHANNEL_L2CAP: 1102 1.1 kiyohara case BCSP_CHANNEL_RFCOMM: 1103 1.1 kiyohara case BCSP_CHANNEL_SDP: 1104 1.1 kiyohara case BCSP_CHANNEL_DFU: 1105 1.1 kiyohara case BCSP_CHANNEL_VM: 1106 1.1 kiyohara default: 1107 1.8 plunky aprint_error_dev(sc->sc_dev, 1108 1.8 plunky "received reliable packet with not support channel %d\n", 1109 1.8 plunky hdr.ident); 1110 1.1 kiyohara m_freem(m); 1111 1.1 kiyohara break; 1112 1.1 kiyohara } 1113 1.1 kiyohara 1114 1.1 kiyohara sc->sc_seq_expected_rxseq = 1115 1.1 kiyohara (sc->sc_seq_expected_rxseq + 1) & BCSP_FLAGS_SEQ_MASK; 1116 1.1 kiyohara sc->sc_seq_txack = sc->sc_seq_expected_rxseq; 1117 1.1 kiyohara bcsp_send_ack_command(sc); 1118 1.1 kiyohara } 1119 1.1 kiyohara 1120 1.1 kiyohara static bool 1121 1.1 kiyohara bcsp_tx_reliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id) 1122 1.1 kiyohara { 1123 1.1 kiyohara bcsp_hdr_t *hdrp; 1124 1.1 kiyohara struct mbuf *_m; 1125 1.1 kiyohara u_int pldlen; 1126 1.1 kiyohara int s; 1127 1.1 kiyohara 1128 1.1 kiyohara DPRINTFN(1, ("%s: seq transmit:" 1129 1.4 plunky "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev), 1130 1.1 kiyohara protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq)); 1131 1.1 kiyohara 1132 1.1 kiyohara for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) { 1133 1.1 kiyohara if (_m->m_len < 0) 1134 1.28 christos goto out; 1135 1.1 kiyohara pldlen += _m->m_len; 1136 1.1 kiyohara } 1137 1.1 kiyohara if (pldlen > 0xfff) 1138 1.27 christos goto out; 1139 1.1 kiyohara if (protocol_id == BCSP_IDENT_ACKPKT || protocol_id > 15) 1140 1.27 christos goto out; 1141 1.1 kiyohara 1142 1.1 kiyohara if (sc->sc_seq_winspace == 0) 1143 1.27 christos goto out; 1144 1.1 kiyohara 1145 1.1 kiyohara M_PREPEND(m, sizeof(bcsp_hdr_t), M_DONTWAIT); 1146 1.1 kiyohara if (m == NULL) { 1147 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1148 1.1 kiyohara return false; 1149 1.1 kiyohara } 1150 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t)); 1151 1.1 kiyohara 1152 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 1153 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t)); 1154 1.1 kiyohara hdrp->flags |= sc->sc_seq_txseq; 1155 1.1 kiyohara hdrp->ident = protocol_id; 1156 1.1 kiyohara 1157 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout); 1158 1.1 kiyohara 1159 1.1 kiyohara s = splserial(); 1160 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seqq, m); 1161 1.1 kiyohara splx(s); 1162 1.1 kiyohara sc->sc_transmit_callback = bcsp_reliabletx_callback; 1163 1.1 kiyohara 1164 1.1 kiyohara #ifdef BCSP_DEBUG 1165 1.1 kiyohara if (bcsp_debug == 2) 1166 1.1 kiyohara bcsp_packet_print(m); 1167 1.1 kiyohara #endif 1168 1.1 kiyohara 1169 1.1 kiyohara sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BCSP_FLAGS_SEQ_MASK; 1170 1.1 kiyohara sc->sc_seq_winspace--; 1171 1.1 kiyohara _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 1172 1.1 kiyohara if (_m == NULL) { 1173 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1174 1.27 christos goto out; 1175 1.1 kiyohara } 1176 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _m); 1177 1.1 kiyohara bcsp_mux_transmit(sc); 1178 1.1 kiyohara 1179 1.1 kiyohara return true; 1180 1.27 christos out: 1181 1.27 christos m_freem(m); 1182 1.27 christos return false; 1183 1.1 kiyohara } 1184 1.1 kiyohara 1185 1.1 kiyohara #if 0 1186 1.1 kiyohara static bool 1187 1.1 kiyohara bcsp_rx_reliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id) 1188 1.1 kiyohara { 1189 1.1 kiyohara 1190 1.1 kiyohara return false; 1191 1.1 kiyohara } 1192 1.1 kiyohara 1193 1.1 kiyohara /* XXXX: I can't understand meaning this function... */ 1194 1.1 kiyohara static __inline void 1195 1.1 kiyohara bcsp_link_failed(struct bcsp_softc *sc) 1196 1.1 kiyohara { 1197 1.1 kiyohara 1198 1.1 kiyohara return (sc->sc_seq_retries >= sc->sc_seq_retry_limit); 1199 1.1 kiyohara } 1200 1.1 kiyohara #endif 1201 1.1 kiyohara 1202 1.1 kiyohara static __inline u_int 1203 1.1 kiyohara bcsp_get_txack(struct bcsp_softc *sc) 1204 1.1 kiyohara { 1205 1.1 kiyohara 1206 1.1 kiyohara return sc->sc_seq_txack; 1207 1.1 kiyohara } 1208 1.1 kiyohara 1209 1.1 kiyohara static void 1210 1.1 kiyohara bcsp_signal_rxack(struct bcsp_softc *sc, uint32_t rxack) 1211 1.1 kiyohara { 1212 1.1 kiyohara bcsp_hdr_t *hdrp; 1213 1.1 kiyohara struct mbuf *m; 1214 1.1 kiyohara uint32_t seqno = (rxack - 1) & BCSP_FLAGS_SEQ_MASK; 1215 1.1 kiyohara int s; 1216 1.1 kiyohara 1217 1.1 kiyohara DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n", 1218 1.4 plunky device_xname(sc->sc_dev), rxack)); 1219 1.1 kiyohara 1220 1.1 kiyohara s = splserial(); 1221 1.1 kiyohara m = MBUFQ_FIRST(&sc->sc_seq_retryq); 1222 1.1 kiyohara while (m != NULL) { 1223 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 1224 1.1 kiyohara if (BCSP_FLAGS_SEQ(hdrp->flags) == seqno) { 1225 1.1 kiyohara struct mbuf *m0; 1226 1.1 kiyohara 1227 1.1 kiyohara for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq); 1228 1.1 kiyohara m0 != MBUFQ_NEXT(m); 1229 1.1 kiyohara m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) { 1230 1.1 kiyohara MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0); 1231 1.1 kiyohara m_freem(m0); 1232 1.1 kiyohara sc->sc_seq_winspace++; 1233 1.1 kiyohara } 1234 1.1 kiyohara break; 1235 1.1 kiyohara } 1236 1.1 kiyohara m = MBUFQ_NEXT(m); 1237 1.1 kiyohara } 1238 1.1 kiyohara splx(s); 1239 1.1 kiyohara sc->sc_seq_retries = 0; 1240 1.1 kiyohara 1241 1.1 kiyohara if (sc->sc_seq_winspace == sc->sc_seq_winsize) 1242 1.1 kiyohara callout_stop(&sc->sc_seq_timer); 1243 1.1 kiyohara else 1244 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout); 1245 1.1 kiyohara } 1246 1.1 kiyohara 1247 1.1 kiyohara static void 1248 1.1 kiyohara bcsp_reliabletx_callback(struct bcsp_softc *sc, struct mbuf *m) 1249 1.1 kiyohara { 1250 1.1 kiyohara 1251 1.1 kiyohara m_freem(m); 1252 1.1 kiyohara } 1253 1.1 kiyohara 1254 1.1 kiyohara static void 1255 1.1 kiyohara bcsp_timer_timeout(void *arg) 1256 1.1 kiyohara { 1257 1.1 kiyohara struct bcsp_softc *sc = arg; 1258 1.1 kiyohara struct mbuf *m, *_m; 1259 1.1 kiyohara int s, i = 0; 1260 1.1 kiyohara 1261 1.1 kiyohara DPRINTFN(1, ("%s: seq timeout: retries=%d\n", 1262 1.4 plunky device_xname(sc->sc_dev), sc->sc_seq_retries)); 1263 1.1 kiyohara 1264 1.1 kiyohara s = splserial(); 1265 1.1 kiyohara for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL; 1266 1.1 kiyohara m = MBUFQ_NEXT(m)) { 1267 1.1 kiyohara _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT); 1268 1.1 kiyohara if (_m == NULL) { 1269 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1270 1.1 kiyohara return; 1271 1.1 kiyohara } 1272 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_seqq, _m); 1273 1.1 kiyohara i++; 1274 1.1 kiyohara } 1275 1.1 kiyohara splx(s); 1276 1.1 kiyohara 1277 1.1 kiyohara if (i != 0) { 1278 1.1 kiyohara if (++sc->sc_seq_retries < sc->sc_seq_retry_limit) 1279 1.1 kiyohara callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout); 1280 1.1 kiyohara else { 1281 1.8 plunky aprint_error_dev(sc->sc_dev, 1282 1.8 plunky "reached the retry limit." 1283 1.8 plunky " restart the link-establishment\n"); 1284 1.3 kiyohara bcsp_sequencing_reset(sc); 1285 1.10 plunky bcsp_start_le(sc); 1286 1.1 kiyohara return; 1287 1.1 kiyohara } 1288 1.1 kiyohara } 1289 1.1 kiyohara bcsp_mux_transmit(sc); 1290 1.1 kiyohara } 1291 1.1 kiyohara 1292 1.1 kiyohara static void 1293 1.1 kiyohara bcsp_sequencing_reset(struct bcsp_softc *sc) 1294 1.1 kiyohara { 1295 1.1 kiyohara int s; 1296 1.1 kiyohara 1297 1.1 kiyohara s = splserial(); 1298 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_seqq); 1299 1.1 kiyohara MBUFQ_DRAIN(&sc->sc_seq_retryq); 1300 1.1 kiyohara splx(s); 1301 1.1 kiyohara 1302 1.1 kiyohara 1303 1.1 kiyohara sc->sc_seq_txseq = 0; 1304 1.1 kiyohara sc->sc_seq_txack = 0; 1305 1.1 kiyohara sc->sc_seq_winspace = sc->sc_seq_winsize; 1306 1.1 kiyohara sc->sc_seq_retries = 0; 1307 1.1 kiyohara callout_stop(&sc->sc_seq_timer); 1308 1.1 kiyohara 1309 1.1 kiyohara sc->sc_mux_send_ack = false; 1310 1.1 kiyohara 1311 1.1 kiyohara /* XXXX: expected_rxseq should be set by MUX Layer */ 1312 1.1 kiyohara sc->sc_seq_expected_rxseq = 0; 1313 1.1 kiyohara } 1314 1.1 kiyohara 1315 1.1 kiyohara 1316 1.1 kiyohara /* 1317 1.1 kiyohara * BCSP Datagram Queue Layer functions 1318 1.1 kiyohara */ 1319 1.1 kiyohara static void 1320 1.1 kiyohara bcsp_datagramq_receive(struct bcsp_softc *sc, struct mbuf *m) 1321 1.1 kiyohara { 1322 1.1 kiyohara bcsp_hdr_t hdr; 1323 1.1 kiyohara 1324 1.4 plunky DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev))); 1325 1.1 kiyohara #ifdef BCSP_DEBUG 1326 1.1 kiyohara if (bcsp_debug == 2) 1327 1.1 kiyohara bcsp_packet_print(m); 1328 1.1 kiyohara #endif 1329 1.1 kiyohara 1330 1.1 kiyohara m_copydata(m, 0, sizeof(bcsp_hdr_t), &hdr); 1331 1.1 kiyohara 1332 1.1 kiyohara switch (hdr.ident) { 1333 1.1 kiyohara case BCSP_CHANNEL_LE: 1334 1.1 kiyohara m_adj(m, sizeof(bcsp_hdr_t)); 1335 1.10 plunky bcsp_input_le(sc, m); 1336 1.1 kiyohara break; 1337 1.1 kiyohara 1338 1.1 kiyohara case BCSP_CHANNEL_HCI_SCO: 1339 1.1 kiyohara /* 1340 1.1 kiyohara * We remove the header of BCSP and add the 'uint8_t type' of 1341 1.1 kiyohara * hci_scodata_hdr_t to the head. 1342 1.1 kiyohara */ 1343 1.1 kiyohara m_adj(m, sizeof(bcsp_hdr_t) - sizeof(uint8_t)); 1344 1.1 kiyohara *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT; 1345 1.10 plunky if (!hci_input_sco(sc->sc_unit, m)) 1346 1.10 plunky sc->sc_stats.err_rx++; 1347 1.10 plunky 1348 1.10 plunky sc->sc_stats.sco_rx++; 1349 1.1 kiyohara break; 1350 1.1 kiyohara 1351 1.1 kiyohara default: 1352 1.8 plunky aprint_error_dev(sc->sc_dev, 1353 1.8 plunky "received unreliable packet with not support channel %d\n", 1354 1.8 plunky hdr.ident); 1355 1.1 kiyohara m_freem(m); 1356 1.1 kiyohara break; 1357 1.1 kiyohara } 1358 1.1 kiyohara } 1359 1.1 kiyohara 1360 1.1 kiyohara static bool 1361 1.1 kiyohara bcsp_tx_unreliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id) 1362 1.1 kiyohara { 1363 1.1 kiyohara bcsp_hdr_t *hdrp; 1364 1.1 kiyohara struct mbuf *_m; 1365 1.1 kiyohara u_int pldlen; 1366 1.1 kiyohara int s; 1367 1.1 kiyohara 1368 1.1 kiyohara DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,", 1369 1.4 plunky device_xname(sc->sc_dev), protocol_id)); 1370 1.1 kiyohara 1371 1.1 kiyohara for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) { 1372 1.1 kiyohara if (_m->m_len < 0) 1373 1.28 christos goto out; 1374 1.1 kiyohara pldlen += _m->m_len; 1375 1.1 kiyohara } 1376 1.1 kiyohara DPRINTFN(1, (" pldlen=%d\n", pldlen)); 1377 1.1 kiyohara if (pldlen > 0xfff) 1378 1.27 christos goto out; 1379 1.1 kiyohara if (protocol_id == BCSP_IDENT_ACKPKT || protocol_id > 15) 1380 1.27 christos goto out; 1381 1.1 kiyohara 1382 1.1 kiyohara M_PREPEND(m, sizeof(bcsp_hdr_t), M_DONTWAIT); 1383 1.1 kiyohara if (m == NULL) { 1384 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1385 1.1 kiyohara return false; 1386 1.1 kiyohara } 1387 1.1 kiyohara KASSERT(m->m_len >= sizeof(bcsp_hdr_t)); 1388 1.1 kiyohara 1389 1.1 kiyohara hdrp = mtod(m, bcsp_hdr_t *); 1390 1.1 kiyohara memset(hdrp, 0, sizeof(bcsp_hdr_t)); 1391 1.1 kiyohara hdrp->ident = protocol_id; 1392 1.1 kiyohara 1393 1.1 kiyohara s = splserial(); 1394 1.1 kiyohara MBUFQ_ENQUEUE(&sc->sc_dgq, m); 1395 1.1 kiyohara splx(s); 1396 1.1 kiyohara sc->sc_transmit_callback = bcsp_unreliabletx_callback; 1397 1.1 kiyohara 1398 1.1 kiyohara #ifdef BCSP_DEBUG 1399 1.1 kiyohara if (bcsp_debug == 2) 1400 1.1 kiyohara bcsp_packet_print(m); 1401 1.1 kiyohara #endif 1402 1.1 kiyohara 1403 1.1 kiyohara bcsp_mux_transmit(sc); 1404 1.1 kiyohara 1405 1.1 kiyohara return true; 1406 1.27 christos out: 1407 1.27 christos m_freem(m); 1408 1.27 christos return false; 1409 1.1 kiyohara } 1410 1.1 kiyohara 1411 1.1 kiyohara #if 0 1412 1.1 kiyohara static bool 1413 1.1 kiyohara bcsp_rx_unreliable_pkt(struct bcsp_softc *sc, struct mbuf *m, u_int protocol_id) 1414 1.1 kiyohara { 1415 1.1 kiyohara 1416 1.1 kiyohara return false; 1417 1.1 kiyohara } 1418 1.1 kiyohara #endif 1419 1.1 kiyohara 1420 1.1 kiyohara static void 1421 1.1 kiyohara bcsp_unreliabletx_callback(struct bcsp_softc *sc, struct mbuf *m) 1422 1.1 kiyohara { 1423 1.1 kiyohara 1424 1.1 kiyohara if (M_GETCTX(m, void *) == NULL) 1425 1.1 kiyohara m_freem(m); 1426 1.10 plunky else if (!hci_complete_sco(sc->sc_unit, m)) 1427 1.10 plunky sc->sc_stats.err_tx++; 1428 1.1 kiyohara } 1429 1.1 kiyohara 1430 1.1 kiyohara 1431 1.1 kiyohara /* 1432 1.1 kiyohara * BlueCore Link Establishment Protocol functions 1433 1.1 kiyohara */ 1434 1.1 kiyohara static const uint8_t sync[] = BCSP_LE_SYNC; 1435 1.1 kiyohara static const uint8_t syncresp[] = BCSP_LE_SYNCRESP; 1436 1.1 kiyohara static const uint8_t conf[] = BCSP_LE_CONF; 1437 1.1 kiyohara static const uint8_t confresp[] = BCSP_LE_CONFRESP; 1438 1.1 kiyohara 1439 1.1 kiyohara static int 1440 1.10 plunky bcsp_start_le(struct bcsp_softc *sc) 1441 1.1 kiyohara { 1442 1.1 kiyohara 1443 1.4 plunky DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev))); 1444 1.1 kiyohara 1445 1.1 kiyohara bcsp_set_choke(sc, true); 1446 1.1 kiyohara 1447 1.1 kiyohara if (!sc->sc_le_muzzled) { 1448 1.1 kiyohara struct mbuf *m; 1449 1.1 kiyohara 1450 1.1 kiyohara m = m_gethdr(M_WAIT, MT_DATA); 1451 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0; 1452 1.1 kiyohara m_copyback(m, 0, sizeof(sync), sync); 1453 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE)) { 1454 1.8 plunky aprint_error_dev(sc->sc_dev, 1455 1.8 plunky "le-packet transmit failed\n"); 1456 1.1 kiyohara return EINVAL; 1457 1.1 kiyohara } 1458 1.1 kiyohara } 1459 1.1 kiyohara callout_schedule(&sc->sc_le_timer, BCSP_LE_TSHY_TIMEOUT); 1460 1.1 kiyohara 1461 1.1 kiyohara sc->sc_le_state = le_state_shy; 1462 1.1 kiyohara return 0; 1463 1.1 kiyohara } 1464 1.1 kiyohara 1465 1.1 kiyohara static void 1466 1.10 plunky bcsp_terminate_le(struct bcsp_softc *sc) 1467 1.1 kiyohara { 1468 1.1 kiyohara struct mbuf *m; 1469 1.1 kiyohara 1470 1.1 kiyohara /* terminate link-establishment */ 1471 1.1 kiyohara callout_stop(&sc->sc_le_timer); 1472 1.1 kiyohara bcsp_set_choke(sc, true); 1473 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA); 1474 1.1 kiyohara if (m == NULL) 1475 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1476 1.1 kiyohara else { 1477 1.1 kiyohara /* length of le packets is 4 */ 1478 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0; 1479 1.1 kiyohara m_copyback(m, 0, sizeof(sync), sync); 1480 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE)) 1481 1.8 plunky aprint_error_dev(sc->sc_dev, 1482 1.8 plunky "link-establishment terminations failed\n"); 1483 1.1 kiyohara } 1484 1.1 kiyohara } 1485 1.1 kiyohara 1486 1.1 kiyohara static void 1487 1.10 plunky bcsp_input_le(struct bcsp_softc *sc, struct mbuf *m) 1488 1.1 kiyohara { 1489 1.1 kiyohara uint32_t *rcvpkt; 1490 1.1 kiyohara int i; 1491 1.1 kiyohara const uint8_t *rplypkt; 1492 1.1 kiyohara static struct { 1493 1.1 kiyohara const char *type; 1494 1.1 kiyohara const uint8_t *datap; 1495 1.1 kiyohara } pkt[] = { 1496 1.1 kiyohara { "sync", sync }, 1497 1.1 kiyohara { "sync-resp", syncresp }, 1498 1.1 kiyohara { "conf", conf }, 1499 1.1 kiyohara { "conf-resp", confresp }, 1500 1.1 kiyohara 1501 1.2 kiyohara { NULL, 0 } 1502 1.1 kiyohara }; 1503 1.1 kiyohara 1504 1.1 kiyohara DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n", 1505 1.4 plunky device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled)); 1506 1.1 kiyohara #ifdef BCSP_DEBUG 1507 1.1 kiyohara if (bcsp_debug == 1) 1508 1.1 kiyohara bcsp_packet_print(m); 1509 1.1 kiyohara #endif 1510 1.1 kiyohara 1511 1.1 kiyohara rcvpkt = mtod(m, uint32_t *); 1512 1.11 plunky i = 0; 1513 1.1 kiyohara 1514 1.1 kiyohara /* length of le packets is 4 */ 1515 1.1 kiyohara if (m->m_len == sizeof(uint32_t)) 1516 1.1 kiyohara for (i = 0; pkt[i].type != NULL; i++) 1517 1.1 kiyohara if (*(const uint32_t *)pkt[i].datap == *rcvpkt) 1518 1.1 kiyohara break; 1519 1.1 kiyohara if (m->m_len != sizeof(uint32_t) || pkt[i].type == NULL) { 1520 1.8 plunky aprint_error_dev(sc->sc_dev, "received unknown packet\n"); 1521 1.1 kiyohara m_freem(m); 1522 1.1 kiyohara return; 1523 1.1 kiyohara } 1524 1.1 kiyohara 1525 1.1 kiyohara rplypkt = NULL; 1526 1.1 kiyohara switch (sc->sc_le_state) { 1527 1.1 kiyohara case le_state_shy: 1528 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)sync) { 1529 1.1 kiyohara sc->sc_le_muzzled = false; 1530 1.1 kiyohara rplypkt = syncresp; 1531 1.1 kiyohara } else if (*rcvpkt == *(const uint32_t *)syncresp) { 1532 1.1 kiyohara DPRINTF(("%s: state change to curious\n", 1533 1.4 plunky device_xname(sc->sc_dev))); 1534 1.1 kiyohara 1535 1.1 kiyohara rplypkt = conf; 1536 1.1 kiyohara callout_schedule(&sc->sc_le_timer, 1537 1.1 kiyohara BCSP_LE_TCONF_TIMEOUT); 1538 1.1 kiyohara sc->sc_le_state = le_state_curious; 1539 1.1 kiyohara } else 1540 1.8 plunky aprint_error_dev(sc->sc_dev, 1541 1.8 plunky "received an unknown packet at shy\n"); 1542 1.1 kiyohara break; 1543 1.1 kiyohara 1544 1.1 kiyohara case le_state_curious: 1545 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)sync) 1546 1.1 kiyohara rplypkt = syncresp; 1547 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)conf) 1548 1.1 kiyohara rplypkt = confresp; 1549 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)confresp) { 1550 1.1 kiyohara DPRINTF(("%s: state change to garrulous:\n", 1551 1.4 plunky device_xname(sc->sc_dev))); 1552 1.1 kiyohara 1553 1.1 kiyohara bcsp_set_choke(sc, false); 1554 1.1 kiyohara callout_stop(&sc->sc_le_timer); 1555 1.1 kiyohara sc->sc_le_state = le_state_garrulous; 1556 1.1 kiyohara } else 1557 1.8 plunky aprint_error_dev(sc->sc_dev, 1558 1.8 plunky "received unknown packet at curious\n"); 1559 1.1 kiyohara break; 1560 1.1 kiyohara 1561 1.1 kiyohara case le_state_garrulous: 1562 1.1 kiyohara if (*rcvpkt == *(const uint32_t *)conf) 1563 1.1 kiyohara rplypkt = confresp; 1564 1.1 kiyohara else if (*rcvpkt == *(const uint32_t *)sync) { 1565 1.1 kiyohara /* XXXXX */ 1566 1.8 plunky aprint_error_dev(sc->sc_dev, 1567 1.8 plunky "received sync! peer to reset?\n"); 1568 1.1 kiyohara 1569 1.3 kiyohara bcsp_sequencing_reset(sc); 1570 1.3 kiyohara rplypkt = sync; 1571 1.1 kiyohara sc->sc_le_state = le_state_shy; 1572 1.1 kiyohara } else 1573 1.8 plunky aprint_error_dev(sc->sc_dev, 1574 1.8 plunky "received unknown packet at garrulous\n"); 1575 1.1 kiyohara break; 1576 1.1 kiyohara } 1577 1.1 kiyohara 1578 1.1 kiyohara m_freem(m); 1579 1.1 kiyohara 1580 1.1 kiyohara if (rplypkt != NULL) { 1581 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA); 1582 1.1 kiyohara if (m == NULL) 1583 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1584 1.1 kiyohara else { 1585 1.1 kiyohara /* length of le packets is 4 */ 1586 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0; 1587 1.1 kiyohara m_copyback(m, 0, 4, rplypkt); 1588 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE)) 1589 1.8 plunky aprint_error_dev(sc->sc_dev, 1590 1.8 plunky "le-packet transmit failed\n"); 1591 1.1 kiyohara } 1592 1.1 kiyohara } 1593 1.1 kiyohara } 1594 1.1 kiyohara 1595 1.1 kiyohara static void 1596 1.1 kiyohara bcsp_le_timeout(void *arg) 1597 1.1 kiyohara { 1598 1.1 kiyohara struct bcsp_softc *sc = arg; 1599 1.1 kiyohara struct mbuf *m; 1600 1.1 kiyohara int timeout; 1601 1.1 kiyohara const uint8_t *sndpkt = NULL; 1602 1.1 kiyohara 1603 1.1 kiyohara DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n", 1604 1.4 plunky device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled)); 1605 1.1 kiyohara 1606 1.1 kiyohara switch (sc->sc_le_state) { 1607 1.1 kiyohara case le_state_shy: 1608 1.1 kiyohara if (!sc->sc_le_muzzled) 1609 1.1 kiyohara sndpkt = sync; 1610 1.1 kiyohara timeout = BCSP_LE_TSHY_TIMEOUT; 1611 1.1 kiyohara break; 1612 1.1 kiyohara 1613 1.1 kiyohara case le_state_curious: 1614 1.1 kiyohara sndpkt = conf; 1615 1.1 kiyohara timeout = BCSP_LE_TCONF_TIMEOUT; 1616 1.1 kiyohara break; 1617 1.1 kiyohara 1618 1.1 kiyohara default: 1619 1.8 plunky aprint_error_dev(sc->sc_dev, 1620 1.8 plunky "timeout happen at unknown state %d\n", sc->sc_le_state); 1621 1.1 kiyohara return; 1622 1.1 kiyohara } 1623 1.1 kiyohara 1624 1.1 kiyohara if (sndpkt != NULL) { 1625 1.1 kiyohara MGETHDR(m, M_DONTWAIT, MT_DATA); 1626 1.1 kiyohara if (m == NULL) 1627 1.8 plunky aprint_error_dev(sc->sc_dev, "out of memory\n"); 1628 1.1 kiyohara else { 1629 1.1 kiyohara /* length of le packets is 4 */ 1630 1.1 kiyohara m->m_pkthdr.len = m->m_len = 0; 1631 1.1 kiyohara m_copyback(m, 0, 4, sndpkt); 1632 1.1 kiyohara if (!bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_LE)) 1633 1.8 plunky aprint_error_dev(sc->sc_dev, 1634 1.8 plunky "le-packet transmit failed\n"); 1635 1.1 kiyohara } 1636 1.1 kiyohara } 1637 1.1 kiyohara 1638 1.1 kiyohara callout_schedule(&sc->sc_le_timer, timeout); 1639 1.1 kiyohara } 1640 1.1 kiyohara 1641 1.1 kiyohara 1642 1.1 kiyohara /* 1643 1.1 kiyohara * BlueCore Serial Protocol functions. 1644 1.1 kiyohara */ 1645 1.1 kiyohara static int 1646 1.7 plunky bcsp_enable(device_t self) 1647 1.1 kiyohara { 1648 1.7 plunky struct bcsp_softc *sc = device_private(self); 1649 1.10 plunky int s; 1650 1.1 kiyohara 1651 1.10 plunky if (sc->sc_flags & BCSP_ENABLED) 1652 1.1 kiyohara return 0; 1653 1.1 kiyohara 1654 1.10 plunky s = spltty(); 1655 1.10 plunky 1656 1.10 plunky sc->sc_flags |= BCSP_ENABLED; 1657 1.10 plunky sc->sc_flags &= ~BCSP_XMIT; 1658 1.10 plunky 1659 1.10 plunky splx(s); 1660 1.1 kiyohara 1661 1.1 kiyohara return 0; 1662 1.1 kiyohara } 1663 1.1 kiyohara 1664 1.1 kiyohara static void 1665 1.7 plunky bcsp_disable(device_t self) 1666 1.1 kiyohara { 1667 1.7 plunky struct bcsp_softc *sc = device_private(self); 1668 1.10 plunky int s; 1669 1.1 kiyohara 1670 1.10 plunky if ((sc->sc_flags & BCSP_ENABLED) == 0) 1671 1.1 kiyohara return; 1672 1.1 kiyohara 1673 1.10 plunky s = spltty(); 1674 1.10 plunky 1675 1.34 rin m_freem(sc->sc_rxp); 1676 1.34 rin sc->sc_rxp = NULL; 1677 1.1 kiyohara 1678 1.34 rin m_freem(sc->sc_txp); 1679 1.34 rin sc->sc_txp = NULL; 1680 1.1 kiyohara 1681 1.10 plunky MBUFQ_DRAIN(&sc->sc_cmdq); 1682 1.10 plunky MBUFQ_DRAIN(&sc->sc_aclq); 1683 1.10 plunky MBUFQ_DRAIN(&sc->sc_scoq); 1684 1.10 plunky 1685 1.10 plunky sc->sc_flags &= ~BCSP_ENABLED; 1686 1.10 plunky splx(s); 1687 1.1 kiyohara } 1688 1.1 kiyohara 1689 1.1 kiyohara static void 1690 1.10 plunky bcsp_start(struct bcsp_softc *sc) 1691 1.1 kiyohara { 1692 1.1 kiyohara struct mbuf *m; 1693 1.1 kiyohara 1694 1.10 plunky KASSERT((sc->sc_flags & BCSP_XMIT) == 0); 1695 1.2 kiyohara KASSERT(sc->sc_txp == NULL); 1696 1.2 kiyohara 1697 1.10 plunky if (MBUFQ_FIRST(&sc->sc_aclq)) { 1698 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_aclq, m); 1699 1.10 plunky sc->sc_stats.acl_tx++; 1700 1.10 plunky sc->sc_flags |= BCSP_XMIT; 1701 1.1 kiyohara bcsp_tx_reliable_pkt(sc, m, BCSP_CHANNEL_HCI_ACL); 1702 1.1 kiyohara } 1703 1.1 kiyohara 1704 1.10 plunky if (MBUFQ_FIRST(&sc->sc_cmdq)) { 1705 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_cmdq, m); 1706 1.10 plunky sc->sc_stats.cmd_tx++; 1707 1.10 plunky sc->sc_flags |= BCSP_XMIT; 1708 1.1 kiyohara bcsp_tx_reliable_pkt(sc, m, BCSP_CHANNEL_HCI_CMDEVT); 1709 1.1 kiyohara } 1710 1.1 kiyohara 1711 1.10 plunky if (MBUFQ_FIRST(&sc->sc_scoq)) { 1712 1.10 plunky MBUFQ_DEQUEUE(&sc->sc_scoq, m); 1713 1.10 plunky sc->sc_stats.sco_tx++; 1714 1.1 kiyohara /* XXXX: We can transmit with reliable */ 1715 1.10 plunky sc->sc_flags |= BCSP_XMIT; 1716 1.1 kiyohara bcsp_tx_unreliable_pkt(sc, m, BCSP_CHANNEL_HCI_SCO); 1717 1.1 kiyohara } 1718 1.1 kiyohara 1719 1.1 kiyohara return; 1720 1.1 kiyohara } 1721 1.1 kiyohara 1722 1.10 plunky static void 1723 1.10 plunky bcsp_output_cmd(device_t self, struct mbuf *m) 1724 1.10 plunky { 1725 1.10 plunky struct bcsp_softc *sc = device_private(self); 1726 1.10 plunky int s; 1727 1.10 plunky 1728 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED); 1729 1.10 plunky 1730 1.10 plunky m_adj(m, sizeof(uint8_t)); 1731 1.10 plunky M_SETCTX(m, NULL); 1732 1.10 plunky 1733 1.10 plunky s = spltty(); 1734 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_cmdq, m); 1735 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0) 1736 1.10 plunky bcsp_start(sc); 1737 1.10 plunky 1738 1.10 plunky splx(s); 1739 1.10 plunky } 1740 1.10 plunky 1741 1.10 plunky static void 1742 1.10 plunky bcsp_output_acl(device_t self, struct mbuf *m) 1743 1.10 plunky { 1744 1.10 plunky struct bcsp_softc *sc = device_private(self); 1745 1.10 plunky int s; 1746 1.10 plunky 1747 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED); 1748 1.10 plunky 1749 1.10 plunky m_adj(m, sizeof(uint8_t)); 1750 1.10 plunky M_SETCTX(m, NULL); 1751 1.10 plunky 1752 1.10 plunky s = spltty(); 1753 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_aclq, m); 1754 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0) 1755 1.10 plunky bcsp_start(sc); 1756 1.10 plunky 1757 1.10 plunky splx(s); 1758 1.10 plunky } 1759 1.10 plunky 1760 1.10 plunky static void 1761 1.10 plunky bcsp_output_sco(device_t self, struct mbuf *m) 1762 1.10 plunky { 1763 1.10 plunky struct bcsp_softc *sc = device_private(self); 1764 1.10 plunky int s; 1765 1.10 plunky 1766 1.10 plunky KASSERT(sc->sc_flags & BCSP_ENABLED); 1767 1.10 plunky 1768 1.10 plunky m_adj(m, sizeof(uint8_t)); 1769 1.10 plunky 1770 1.10 plunky s = spltty(); 1771 1.10 plunky MBUFQ_ENQUEUE(&sc->sc_scoq, m); 1772 1.10 plunky if ((sc->sc_flags & BCSP_XMIT) == 0) 1773 1.10 plunky bcsp_start(sc); 1774 1.10 plunky 1775 1.10 plunky splx(s); 1776 1.10 plunky } 1777 1.10 plunky 1778 1.10 plunky static void 1779 1.10 plunky bcsp_stats(device_t self, struct bt_stats *dest, int flush) 1780 1.10 plunky { 1781 1.10 plunky struct bcsp_softc *sc = device_private(self); 1782 1.10 plunky int s; 1783 1.10 plunky 1784 1.10 plunky s = spltty(); 1785 1.10 plunky memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats)); 1786 1.10 plunky 1787 1.10 plunky if (flush) 1788 1.10 plunky memset(&sc->sc_stats, 0, sizeof(struct bt_stats)); 1789 1.10 plunky 1790 1.10 plunky splx(s); 1791 1.10 plunky } 1792 1.10 plunky 1793 1.1 kiyohara 1794 1.1 kiyohara #ifdef BCSP_DEBUG 1795 1.1 kiyohara static void 1796 1.1 kiyohara bcsp_packet_print(struct mbuf *m) 1797 1.1 kiyohara { 1798 1.1 kiyohara int i; 1799 1.1 kiyohara uint8_t *p; 1800 1.1 kiyohara 1801 1.1 kiyohara for ( ; m != NULL; m = m->m_next) { 1802 1.1 kiyohara p = mtod(m, uint8_t *); 1803 1.1 kiyohara for (i = 0; i < m->m_len; i++) { 1804 1.1 kiyohara if (i % 16 == 0) 1805 1.1 kiyohara printf(" "); 1806 1.1 kiyohara printf(" %02x", *(p + i)); 1807 1.1 kiyohara if (i % 16 == 15) 1808 1.1 kiyohara printf("\n"); 1809 1.1 kiyohara } 1810 1.1 kiyohara printf("\n"); 1811 1.1 kiyohara } 1812 1.1 kiyohara } 1813 1.1 kiyohara #endif 1814