This source file includes following definitions.
- sbt_match
- sbt_attach
- sbt_detach
- sbt_write_packet
- sbt_read_packet
- sbt_intr
- sbt_enable
- sbt_disable
- sbt_start
- sbt_start_cmd
- sbt_start_acl
- sbt_start_sco
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <sys/param.h>
22 #include <sys/device.h>
23 #include <sys/malloc.h>
24 #include <sys/mbuf.h>
25 #include <sys/proc.h>
26 #include <sys/queue.h>
27 #include <sys/socket.h>
28 #include <sys/systm.h>
29
30 #include <netbt/hci.h>
31
32 #include <dev/sdmmc/sdmmcdevs.h>
33 #include <dev/sdmmc/sdmmcvar.h>
34
35 #define CSR_READ_1(sc, reg) sdmmc_io_read_1((sc)->sc_sf, (reg))
36 #define CSR_WRITE_1(sc, reg, val) sdmmc_io_write_1((sc)->sc_sf, (reg), (val))
37
38 #define SBT_REG_DAT 0x00
39 #define SBT_REG_RPC 0x10
40 #define RPC_PCRRT (1<<0)
41 #define SBT_REG_WPC 0x11
42 #define WPC_PCWRT (1<<0)
43 #define SBT_REG_RC 0x12
44 #define SBT_REG_ISTAT 0x13
45 #define ISTAT_INTRD (1<<0)
46 #define SBT_REG_ICLR 0x13
47 #define SBT_REG_IENA 0x14
48 #define SBT_REG_BTMODE 0x20
49 #define BTMODE_TYPEB (1<<0)
50
51 #define SBT_PKT_BUFSIZ 65540
52 #define SBT_RXTRY_MAX 5
53
54 struct sbt_softc {
55 struct device sc_dev;
56 struct hci_unit sc_unit;
57 struct sdmmc_function *sc_sf;
58 struct proc *sc_thread;
59 int sc_dying;
60 void *sc_ih;
61 u_char *sc_buf;
62 int sc_rxtry;
63 };
64
65 int sbt_match(struct device *, void *, void *);
66 void sbt_attach(struct device *, struct device *, void *);
67 int sbt_detach(struct device *, int);
68
69 int sbt_write_packet(struct sbt_softc *, u_char *, size_t);
70 int sbt_read_packet(struct sbt_softc *, u_char *, size_t *);
71
72 int sbt_intr(void *);
73
74 int sbt_enable(struct hci_unit *);
75 void sbt_disable(struct hci_unit *);
76 void sbt_start(struct hci_unit *, struct ifqueue *, int);
77 void sbt_start_cmd(struct hci_unit *);
78 void sbt_start_acl(struct hci_unit *);
79 void sbt_start_sco(struct hci_unit *);
80
81 #undef DPRINTF
82 #define SBT_DEBUG
83 #ifdef SBT_DEBUG
84 int sbt_debug = 1;
85 #define DPRINTF(s) printf s
86 #define DNPRINTF(n, s) do { if ((n) <= sbt_debug) printf s; } while (0)
87 #else
88 #define DPRINTF(s) do {} while (0)
89 #define DNPRINTF(n, s) do {} while (0)
90 #endif
91
92 #define DEVNAME(sc) ((sc)->sc_dev.dv_xname)
93
94 struct cfattach sbt_ca = {
95 sizeof(struct sbt_softc), sbt_match, sbt_attach, sbt_detach
96 };
97
98 struct cfdriver sbt_cd = {
99 NULL, "sbt", DV_DULL
100 };
101
102
103
104
105
106
107 static const struct sbt_product {
108 u_int16_t sp_vendor;
109 u_int16_t sp_product;
110 const char *sp_cisinfo[4];
111 } sbt_products[] = {
112 { SDMMC_VENDOR_SOCKETCOM,
113 SDMMC_PRODUCT_SOCKETCOM_BTCARD,
114 SDMMC_CIS_SOCKETCOM_BTCARD }
115 };
116
117 int
118 sbt_match(struct device *parent, void *match, void *aux)
119 {
120 struct sdmmc_attach_args *sa = aux;
121 const struct sbt_product *sp;
122 struct sdmmc_function *sf;
123 int i;
124
125 if (sa->sf == NULL)
126 return 0;
127
128 sf = sa->sf->sc->sc_fn0;
129 sp = &sbt_products[0];
130
131 for (i = 0; i < sizeof(sbt_products) / sizeof(sbt_products[0]);
132 i++, sp = &sbt_products[i])
133 if (sp->sp_vendor == sf->cis.manufacturer &&
134 sp->sp_product == sf->cis.product)
135 return 1;
136 return 0;
137 }
138
139 void
140 sbt_attach(struct device *parent, struct device *self, void *aux)
141 {
142 struct sbt_softc *sc = (struct sbt_softc *)self;
143 struct sdmmc_attach_args *sa = aux;
144
145 printf("\n");
146
147 sc->sc_sf = sa->sf;
148
149 (void)sdmmc_io_function_disable(sc->sc_sf);
150 if (sdmmc_io_function_enable(sc->sc_sf)) {
151 printf("%s: function not ready\n", DEVNAME(sc));
152 return;
153 }
154
155
156 printf("%s: SDIO Bluetooth Type-A\n", DEVNAME(sc));
157
158 sc->sc_buf = malloc(SBT_PKT_BUFSIZ, M_DEVBUF,
159 M_NOWAIT | M_CANFAIL);
160 if (sc->sc_buf == NULL) {
161 printf("%s: can't allocate cmd buffer\n", DEVNAME(sc));
162 return;
163 }
164
165
166 CSR_WRITE_1(sc, SBT_REG_IENA, ISTAT_INTRD);
167
168
169 sc->sc_ih = sdmmc_intr_establish(parent, sbt_intr, sc, DEVNAME(sc));
170 if (sc->sc_ih == NULL) {
171 printf("%s: can't establish interrupt\n", DEVNAME(sc));
172 return;
173 }
174 sdmmc_intr_enable(sc->sc_sf);
175
176
177
178
179 sc->sc_unit.hci_softc = self;
180 sc->sc_unit.hci_devname = DEVNAME(sc);
181 sc->sc_unit.hci_enable = sbt_enable;
182 sc->sc_unit.hci_disable = sbt_disable;
183 sc->sc_unit.hci_start_cmd = sbt_start_cmd;
184 sc->sc_unit.hci_start_acl = sbt_start_acl;
185 sc->sc_unit.hci_start_sco = sbt_start_sco;
186 sc->sc_unit.hci_ipl = IPL_TTY;
187 hci_attach(&sc->sc_unit);
188 }
189
190 int
191 sbt_detach(struct device *self, int flags)
192 {
193 struct sbt_softc *sc = (struct sbt_softc *)self;
194
195 sc->sc_dying = 1;
196 while (sc->sc_thread != NULL)
197 tsleep(sc, PWAIT, "dying", 0);
198
199 hci_detach(&sc->sc_unit);
200
201 if (sc->sc_ih != NULL)
202 sdmmc_intr_disestablish(sc->sc_ih);
203
204 return 0;
205 }
206
207
208
209
210
211
212 int
213 sbt_write_packet(struct sbt_softc *sc, u_char *buf, size_t len)
214 {
215 u_char hdr[3];
216 size_t pktlen;
217 int error = EIO;
218 int retry = 3;
219
220 again:
221 if (retry-- == 0) {
222 DPRINTF(("%s: sbt_write_cmd: giving up\n", DEVNAME(sc)));
223 return error;
224 }
225
226
227 sdmmc_io_write_1(sc->sc_sf, SBT_REG_WPC, WPC_PCWRT);
228
229
230 pktlen = len + 3;
231 hdr[0] = pktlen & 0xff;
232 hdr[1] = (pktlen >> 8) & 0xff;
233 hdr[2] = (pktlen >> 16) & 0xff;
234 error = sdmmc_io_write_multi_1(sc->sc_sf, SBT_REG_DAT, hdr, 3);
235 if (error) {
236 DPRINTF(("%s: sbt_write_packet: failed to send length\n",
237 DEVNAME(sc)));
238 goto again;
239 }
240
241 error = sdmmc_io_write_multi_1(sc->sc_sf, SBT_REG_DAT, buf, len);
242 if (error) {
243 DPRINTF(("%s: sbt_write_packet: failed to send packet data\n",
244 DEVNAME(sc)));
245 goto again;
246 }
247 return 0;
248 }
249
250 int
251 sbt_read_packet(struct sbt_softc *sc, u_char *buf, size_t *lenp)
252 {
253 u_char hdr[3];
254 size_t len;
255 int error;
256
257 error = sdmmc_io_read_multi_1(sc->sc_sf, SBT_REG_DAT, hdr, 3);
258 if (error) {
259 DPRINTF(("%s: sbt_read_packet: failed to read length\n",
260 DEVNAME(sc)));
261 goto out;
262 }
263 len = (hdr[0] | (hdr[1] << 8) | (hdr[2] << 16)) - 3;
264 if (len > *lenp) {
265 DPRINTF(("%s: sbt_read_packet: len %u > %u\n",
266 DEVNAME(sc), len, *lenp));
267 error = ENOBUFS;
268 goto out;
269 }
270
271 DNPRINTF(2,("%s: sbt_read_packet: reading len %u bytes\n",
272 DEVNAME(sc), len));
273 error = sdmmc_io_read_multi_1(sc->sc_sf, SBT_REG_DAT, buf, len);
274 if (error) {
275 DPRINTF(("%s: sbt_read_packet: failed to read packet data\n",
276 DEVNAME(sc)));
277 goto out;
278 }
279
280 out:
281 if (error) {
282 if (sc->sc_rxtry >= SBT_RXTRY_MAX) {
283
284 sc->sc_rxtry = 0;
285 CSR_WRITE_1(sc, SBT_REG_RPC, 0);
286 } else {
287
288 sc->sc_rxtry++;
289 CSR_WRITE_1(sc, SBT_REG_RPC, RPC_PCRRT);
290 }
291 return error;
292 }
293
294
295 CSR_WRITE_1(sc, SBT_REG_RPC, 0);
296
297 *lenp = len;
298 return 0;
299 }
300
301
302
303
304
305 int
306 sbt_intr(void *arg)
307 {
308 struct sbt_softc *sc = arg;
309 struct mbuf *m = NULL;
310 u_int8_t status;
311 size_t len;
312 int s;
313
314 s = splsdmmc();
315
316 status = CSR_READ_1(sc, SBT_REG_ISTAT);
317 CSR_WRITE_1(sc, SBT_REG_ICLR, status);
318
319 if ((status & ISTAT_INTRD) == 0)
320 return 0;
321
322 len = SBT_PKT_BUFSIZ;
323 if (sbt_read_packet(sc, sc->sc_buf, &len) != 0 || len == 0) {
324 DPRINTF(("%s: sbt_intr: read failed\n", DEVNAME(sc)));
325 goto eoi;
326 }
327
328 MGETHDR(m, M_DONTWAIT, MT_DATA);
329 if (m == NULL) {
330 DPRINTF(("%s: sbt_intr: MGETHDR failed\n", DEVNAME(sc)));
331 goto eoi;
332 }
333
334 m->m_pkthdr.len = m->m_len = MHLEN;
335 m_copyback(m, 0, len, sc->sc_buf);
336 if (m->m_pkthdr.len == MAX(MHLEN, len)) {
337 m->m_pkthdr.len = len;
338 m->m_len = MIN(MHLEN, m->m_pkthdr.len);
339 } else {
340 DPRINTF(("%s: sbt_intr: m_copyback failed\n", DEVNAME(sc)));
341 m_free(m);
342 m = NULL;
343 }
344
345 eoi:
346 if (m != NULL) {
347 switch (sc->sc_buf[0]) {
348 case HCI_ACL_DATA_PKT:
349 DNPRINTF(1,("%s: recv ACL packet (%d bytes)\n",
350 DEVNAME(sc), m->m_pkthdr.len));
351 hci_input_acl(&sc->sc_unit, m);
352 break;
353 case HCI_SCO_DATA_PKT:
354 DNPRINTF(1,("%s: recv SCO packet (%d bytes)\n",
355 DEVNAME(sc), m->m_pkthdr.len));
356 hci_input_sco(&sc->sc_unit, m);
357 break;
358 case HCI_EVENT_PKT:
359 DNPRINTF(1,("%s: recv EVENT packet (%d bytes)\n",
360 DEVNAME(sc), m->m_pkthdr.len));
361 hci_input_event(&sc->sc_unit, m);
362 break;
363 default:
364 DPRINTF(("%s: recv 0x%x packet (%d bytes)\n",
365 DEVNAME(sc), sc->sc_buf[0], m->m_pkthdr.len));
366 sc->sc_unit.hci_stats.err_rx++;
367 m_free(m);
368 break;
369 }
370 } else
371 sc->sc_unit.hci_stats.err_rx++;
372
373 splx(s);
374
375
376 return 1;
377 }
378
379
380
381
382
383
384 int
385 sbt_enable(struct hci_unit *unit)
386 {
387 if (unit->hci_flags & BTF_RUNNING)
388 return 0;
389
390 unit->hci_flags |= BTF_RUNNING;
391 unit->hci_flags &= ~BTF_XMIT;
392 return 0;
393 }
394
395 void
396 sbt_disable(struct hci_unit *unit)
397 {
398 if (!(unit->hci_flags & BTF_RUNNING))
399 return;
400
401 #ifdef notyet
402 if (sc->sc_rxp) {
403 m_freem(sc->sc_rxp);
404 sc->sc_rxp = NULL;
405 }
406
407 if (sc->sc_txp) {
408 m_freem(sc->sc_txp);
409 sc->sc_txp = NULL;
410 }
411 #endif
412
413 unit->hci_flags &= ~BTF_RUNNING;
414 }
415
416 void
417 sbt_start(struct hci_unit *unit, struct ifqueue *q, int xmit)
418 {
419 struct sbt_softc *sc = (struct sbt_softc *)unit->hci_softc;
420 struct mbuf *m;
421 int len;
422 #ifdef SBT_DEBUG
423 const char *what;
424 #endif
425
426 if (sc->sc_dying || IF_IS_EMPTY(q))
427 return;
428
429 IF_DEQUEUE(q, m);
430
431 #ifdef SBT_DEBUG
432 switch (xmit) {
433 case BTF_XMIT_CMD:
434 what = "CMD";
435 break;
436 case BTF_XMIT_ACL:
437 what = "ACL";
438 break;
439 case BTF_XMIT_SCO:
440 what = "SCO";
441 break;
442 }
443 DNPRINTF(1,("%s: xmit %s packet (%d bytes)\n", DEVNAME(sc),
444 what, m->m_pkthdr.len));
445 #endif
446
447 unit->hci_flags |= xmit;
448
449 len = m->m_pkthdr.len;
450 m_copydata(m, 0, len, sc->sc_buf);
451 m_freem(m);
452
453 if (sbt_write_packet(sc, sc->sc_buf, len))
454 DPRINTF(("%s: sbt_write_packet failed\n", DEVNAME(sc)));
455
456 unit->hci_flags &= ~xmit;
457 }
458
459 void
460 sbt_start_cmd(struct hci_unit *unit)
461 {
462 sbt_start(unit, &unit->hci_cmdq, BTF_XMIT_CMD);
463 }
464
465 void
466 sbt_start_acl(struct hci_unit *unit)
467 {
468 sbt_start(unit, &unit->hci_acltxq, BTF_XMIT_ACL);
469 }
470
471 void
472 sbt_start_sco(struct hci_unit *unit)
473 {
474 sbt_start(unit, &unit->hci_scotxq, BTF_XMIT_SCO);
475 }