1 /* $NetBSD: sbt.c,v 1.1 2009/04/21 03:00:30 nonaka Exp $ */
2 /* $OpenBSD: sbt.c,v 1.9 2007/06/19 07:59:57 uwe Exp $ */
5 * Copyright (c) 2007 Uwe Stuehler <uwe@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 /* Driver for Type-A/B SDIO Bluetooth cards */
22 #include <sys/cdefs.h>
23 __KERNEL_RCSID(0, "$NetBSD: sbt.c,v 1.1 2009/04/21 03:00:30 nonaka Exp $");
25 #include <sys/param.h>
26 #include <sys/device.h>
27 #include <sys/malloc.h>
30 #include <sys/queue.h>
31 #include <sys/socket.h>
32 #include <sys/systm.h>
34 #include <netbt/hci.h>
36 #include <dev/sdmmc/sdmmcdevs.h>
37 #include <dev/sdmmc/sdmmcvar.h>
39 #define CSR_READ_1(sc, reg) sdmmc_io_read_1((sc)->sc_sf, (reg))
40 #define CSR_WRITE_1(sc, reg, val) sdmmc_io_write_1((sc)->sc_sf, (reg), (val))
42 #define SBT_REG_DAT 0x00 /* receiver/transmitter data */
43 #define SBT_REG_RPC 0x10 /* read packet control */
44 #define RPC_PCRRT (1<<0) /* packet read retry */
45 #define SBT_REG_WPC 0x11 /* write packet control */
46 #define WPC_PCWRT (1<<0) /* packet write retry */
47 #define SBT_REG_RC 0x12 /* retry control status/set */
48 #define SBT_REG_ISTAT 0x13 /* interrupt status */
49 #define ISTAT_INTRD (1<<0) /* packet available for read */
50 #define SBT_REG_ICLR 0x13 /* interrupt clear */
51 #define SBT_REG_IENA 0x14 /* interrupt enable */
52 #define SBT_REG_BTMODE 0x20 /* SDIO Bluetooth card mode */
53 #define BTMODE_TYPEB (1<<0) /* 1=Type-B, 0=Type-A */
55 #define SBT_PKT_BUFSIZ 65540
56 #define SBT_RXTRY_MAX 5
59 device_t sc_dev
; /* base device */
61 struct hci_unit
*sc_unit
; /* Bluetooth HCI Unit */
62 struct bt_stats sc_stats
;
63 struct sdmmc_function
*sc_sf
; /* SDIO function */
64 int sc_dying
; /* shutdown in progress */
76 #define SBT_XMIT (1 << 0) /* transmit is active */
77 #define SBT_ENABLED (1 << 1) /* device is enabled */
79 static int sbt_match(device_t
, cfdata_t
, void *);
80 static void sbt_attach(device_t
, device_t
, void *);
81 static int sbt_detach(device_t
, int);
83 CFATTACH_DECL_NEW(sbt
, sizeof(struct sbt_softc
),
84 sbt_match
, sbt_attach
, sbt_detach
, NULL
);
86 static int sbt_write_packet(struct sbt_softc
*, u_char
*, size_t);
87 static int sbt_read_packet(struct sbt_softc
*, u_char
*, size_t *);
88 static void sbt_start(struct sbt_softc
*);
90 static int sbt_intr(void *);
92 static int sbt_enable(device_t
);
93 static void sbt_disable(device_t
);
94 static void sbt_start_cmd(device_t
, struct mbuf
*);
95 static void sbt_start_acl(device_t
, struct mbuf
*);
96 static void sbt_start_sco(device_t
, struct mbuf
*);
97 static void sbt_stats(device_t
, struct bt_stats
*, int);
99 #undef DPRINTF /* avoid redefine by bluetooth.h */
102 #define DPRINTF(s) printf s
103 #define DNPRINTF(n, s) do { if ((n) <= sbt_debug) printf s; } while (0)
105 #define DPRINTF(s) do {} while (0)
106 #define DNPRINTF(n, s) do {} while (0)
109 #define DEVNAME(sc) device_xname((sc)->sc_dev)
116 static const struct sbt_product
{
119 const char *sp_cisinfo
[4];
122 SDMMC_VENDOR_SOCKETCOM
,
123 SDMMC_PRODUCT_SOCKETCOM_BTCARD
,
124 SDMMC_CIS_SOCKETCOM_BTCARD
128 static const struct hci_if sbt_hci
= {
129 .enable
= sbt_enable
,
130 .disable
= sbt_disable
,
131 .output_cmd
= sbt_start_cmd
,
132 .output_acl
= sbt_start_acl
,
133 .output_sco
= sbt_start_sco
,
134 .get_stats
= sbt_stats
,
135 .ipl
= IPL_TTY
, /* XXX */
140 sbt_match(device_t parent
, cfdata_t match
, void *aux
)
142 struct sdmmc_attach_args
*sa
= aux
;
143 const struct sbt_product
*sp
;
144 struct sdmmc_function
*sf
;
148 return 0; /* not SDIO */
150 sf
= sa
->sf
->sc
->sc_fn0
;
151 sp
= &sbt_products
[0];
153 for (i
= 0; i
< sizeof(sbt_products
) / sizeof(sbt_products
[0]);
154 i
++, sp
= &sbt_products
[i
])
155 if (sp
->sp_vendor
== sf
->cis
.manufacturer
&&
156 sp
->sp_product
== sf
->cis
.product
)
162 sbt_attach(device_t parent
, device_t self
, void *aux
)
164 struct sbt_softc
*sc
= device_private(self
);
165 struct sdmmc_attach_args
*sa
= aux
;
172 MBUFQ_INIT(&sc
->sc_cmdq
);
173 MBUFQ_INIT(&sc
->sc_aclq
);
174 MBUFQ_INIT(&sc
->sc_scoq
);
176 (void)sdmmc_io_function_disable(sc
->sc_sf
);
177 if (sdmmc_io_function_enable(sc
->sc_sf
)) {
178 printf("%s: function not ready\n", DEVNAME(sc
));
182 /* It may be Type-B, but we use it only in Type-A mode. */
183 printf("%s: SDIO Bluetooth Type-A\n", DEVNAME(sc
));
185 sc
->sc_buf
= malloc(SBT_PKT_BUFSIZ
, M_DEVBUF
, M_NOWAIT
| M_CANFAIL
);
186 if (sc
->sc_buf
== NULL
) {
187 printf("%s: can't allocate cmd buffer\n", DEVNAME(sc
));
191 /* Enable the HCI packet transport read interrupt. */
192 CSR_WRITE_1(sc
, SBT_REG_IENA
, ISTAT_INTRD
);
194 /* Enable the card interrupt for this function. */
195 sc
->sc_ih
= sdmmc_intr_establish(parent
, sbt_intr
, sc
, DEVNAME(sc
));
196 if (sc
->sc_ih
== NULL
) {
197 printf("%s: can't establish interrupt\n", DEVNAME(sc
));
200 sdmmc_intr_enable(sc
->sc_sf
);
203 * Attach Bluetooth unit (machine-independent HCI).
205 sc
->sc_unit
= hci_attach(&sbt_hci
, self
, 0);
209 sbt_detach(device_t self
, int flags
)
211 struct sbt_softc
*sc
= (struct sbt_softc
*)self
;
216 hci_detach(sc
->sc_unit
);
220 if (sc
->sc_ih
!= NULL
)
221 sdmmc_intr_disestablish(sc
->sc_ih
);
228 * Bluetooth HCI packet transport
232 sbt_write_packet(struct sbt_softc
*sc
, u_char
*buf
, size_t len
)
241 DPRINTF(("%s: sbt_write_cmd: giving up\n", DEVNAME(sc
)));
245 /* Restart the current packet. */
246 sdmmc_io_write_1(sc
->sc_sf
, SBT_REG_WPC
, WPC_PCWRT
);
248 /* Write the packet length. */
250 hdr
[0] = pktlen
& 0xff;
251 hdr
[1] = (pktlen
>> 8) & 0xff;
252 hdr
[2] = (pktlen
>> 16) & 0xff;
253 error
= sdmmc_io_write_multi_1(sc
->sc_sf
, SBT_REG_DAT
, hdr
, 3);
255 DPRINTF(("%s: sbt_write_packet: failed to send length\n",
260 error
= sdmmc_io_write_multi_1(sc
->sc_sf
, SBT_REG_DAT
, buf
, len
);
262 DPRINTF(("%s: sbt_write_packet: failed to send packet data\n",
270 sbt_read_packet(struct sbt_softc
*sc
, u_char
*buf
, size_t *lenp
)
276 error
= sdmmc_io_read_multi_1(sc
->sc_sf
, SBT_REG_DAT
, hdr
, 3);
278 DPRINTF(("%s: sbt_read_packet: failed to read length\n",
282 len
= (hdr
[0] | (hdr
[1] << 8) | (hdr
[2] << 16)) - 3;
284 DPRINTF(("%s: sbt_read_packet: len %u > %u\n",
285 DEVNAME(sc
), len
, *lenp
));
290 DNPRINTF(2,("%s: sbt_read_packet: reading len %u bytes\n",
292 error
= sdmmc_io_read_multi_1(sc
->sc_sf
, SBT_REG_DAT
, buf
, len
);
294 DPRINTF(("%s: sbt_read_packet: failed to read packet data\n",
301 if (sc
->sc_rxtry
>= SBT_RXTRY_MAX
) {
302 /* Drop and request the next packet. */
304 CSR_WRITE_1(sc
, SBT_REG_RPC
, 0);
306 /* Request the current packet again. */
308 CSR_WRITE_1(sc
, SBT_REG_RPC
, RPC_PCRRT
);
313 /* acknowledge read packet */
314 CSR_WRITE_1(sc
, SBT_REG_RPC
, 0);
327 struct sbt_softc
*sc
= arg
;
328 struct mbuf
*m
= NULL
;
335 status
= CSR_READ_1(sc
, SBT_REG_ISTAT
);
336 CSR_WRITE_1(sc
, SBT_REG_ICLR
, status
);
338 if ((status
& ISTAT_INTRD
) == 0)
339 return 0; /* shared SDIO card interrupt? */
341 len
= SBT_PKT_BUFSIZ
;
342 if (sbt_read_packet(sc
, sc
->sc_buf
, &len
) != 0 || len
== 0) {
343 DPRINTF(("%s: sbt_intr: read failed\n", DEVNAME(sc
)));
347 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
349 DPRINTF(("%s: sbt_intr: MGETHDR failed\n", DEVNAME(sc
)));
353 m
->m_pkthdr
.len
= m
->m_len
= MHLEN
;
354 m_copyback(m
, 0, len
, sc
->sc_buf
);
355 if (m
->m_pkthdr
.len
== MAX(MHLEN
, len
)) {
356 m
->m_pkthdr
.len
= len
;
357 m
->m_len
= MIN(MHLEN
, m
->m_pkthdr
.len
);
359 DPRINTF(("%s: sbt_intr: m_copyback failed\n", DEVNAME(sc
)));
366 switch (sc
->sc_buf
[0]) {
367 case HCI_ACL_DATA_PKT
:
368 DNPRINTF(1,("%s: recv ACL packet (%d bytes)\n",
369 DEVNAME(sc
), m
->m_pkthdr
.len
));
370 hci_input_acl(sc
->sc_unit
, m
);
372 case HCI_SCO_DATA_PKT
:
373 DNPRINTF(1,("%s: recv SCO packet (%d bytes)\n",
374 DEVNAME(sc
), m
->m_pkthdr
.len
));
375 hci_input_sco(sc
->sc_unit
, m
);
378 DNPRINTF(1,("%s: recv EVENT packet (%d bytes)\n",
379 DEVNAME(sc
), m
->m_pkthdr
.len
));
380 hci_input_event(sc
->sc_unit
, m
);
383 DPRINTF(("%s: recv 0x%x packet (%d bytes)\n",
384 DEVNAME(sc
), sc
->sc_buf
[0], m
->m_pkthdr
.len
));
385 sc
->sc_stats
.err_rx
++;
390 sc
->sc_stats
.err_rx
++;
394 /* Claim this interrupt. */
400 * Bluetooth HCI unit functions
404 sbt_enable(device_t self
)
406 struct sbt_softc
*sc
= device_private(self
);
409 if (sc
->sc_flags
& SBT_ENABLED
)
414 sc
->sc_flags
|= SBT_ENABLED
;
415 sc
->sc_flags
&= ~SBT_XMIT
;
423 sbt_disable(device_t self
)
425 struct sbt_softc
*sc
= device_private(self
);
428 if (!(sc
->sc_flags
& SBT_ENABLED
))
433 #ifdef notyet /* XXX */
445 MBUFQ_DRAIN(&sc
->sc_cmdq
);
446 MBUFQ_DRAIN(&sc
->sc_aclq
);
447 MBUFQ_DRAIN(&sc
->sc_scoq
);
449 sc
->sc_flags
&= ~SBT_ENABLED
;
455 sbt_start(struct sbt_softc
*sc
)
463 KASSERT((sc
->sc_flags
& SBT_XMIT
) == 0);
468 if (MBUFQ_FIRST(&sc
->sc_cmdq
)) {
469 MBUFQ_DEQUEUE(&sc
->sc_cmdq
, m
);
470 sc
->sc_stats
.cmd_tx
++;
477 if (MBUFQ_FIRST(&sc
->sc_scoq
)) {
478 MBUFQ_DEQUEUE(&sc
->sc_scoq
, m
);
479 sc
->sc_stats
.sco_tx
++;
486 if (MBUFQ_FIRST(&sc
->sc_aclq
)) {
487 MBUFQ_DEQUEUE(&sc
->sc_aclq
, m
);
488 sc
->sc_stats
.acl_tx
++;
495 /* Nothing to send */
499 DNPRINTF(1,("%s: xmit %s packet (%d bytes)\n", DEVNAME(sc
),
500 what
, m
->m_pkthdr
.len
));
502 sc
->sc_flags
|= SBT_XMIT
;
504 len
= m
->m_pkthdr
.len
;
505 m_copydata(m
, 0, len
, sc
->sc_buf
);
508 if (sbt_write_packet(sc
, sc
->sc_buf
, len
))
509 DPRINTF(("%s: sbt_write_packet failed\n", DEVNAME(sc
)));
511 sc
->sc_flags
&= ~SBT_XMIT
;
515 sbt_start_cmd(device_t self
, struct mbuf
*m
)
517 struct sbt_softc
*sc
= device_private(self
);
520 KASSERT(sc
->sc_flags
& SBT_ENABLED
);
526 MBUFQ_ENQUEUE(&sc
->sc_cmdq
, m
);
527 if ((sc
->sc_flags
& SBT_XMIT
) == 0)
534 sbt_start_acl(device_t self
, struct mbuf
*m
)
536 struct sbt_softc
*sc
= device_private(self
);
539 KASSERT(sc
->sc_flags
& SBT_ENABLED
);
545 MBUFQ_ENQUEUE(&sc
->sc_aclq
, m
);
546 if ((sc
->sc_flags
& SBT_XMIT
) == 0)
553 sbt_start_sco(device_t self
, struct mbuf
*m
)
555 struct sbt_softc
*sc
= device_private(self
);
558 KASSERT(sc
->sc_flags
& SBT_ENABLED
);
562 MBUFQ_ENQUEUE(&sc
->sc_scoq
, m
);
563 if ((sc
->sc_flags
& SBT_XMIT
) == 0)
570 sbt_stats(device_t self
, struct bt_stats
*dest
, int flush
)
572 struct sbt_softc
*sc
= device_private(self
);
577 memcpy(dest
, &sc
->sc_stats
, sizeof(struct bt_stats
));
580 memset(&sc
->sc_stats
, 0, sizeof(struct bt_stats
));