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