1/* 2 * ng_bt3c_pccard.c 3 */ 4 5/*- 6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: ng_bt3c_pccard.c,v 1.5 2003/04/01 18:15:21 max Exp $
| 1/* 2 * ng_bt3c_pccard.c 3 */ 4 5/*- 6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 * $Id: ng_bt3c_pccard.c,v 1.5 2003/04/01 18:15:21 max Exp $
|
31 * $FreeBSD: head/sys/netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c 151700 2005-10-26 15:52:16Z jhb $
| 31 * $FreeBSD: head/sys/netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c 151726 2005-10-26 23:13:51Z emax $
|
32 * 33 * XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX 34 * 35 * Based on information obrained from: Jose Orlando Pereira <jop@di.uminho.pt> 36 * and disassembled w2k driver. 37 * 38 * XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX 39 * 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44 45#include <sys/bus.h> 46#include <machine/bus.h> 47 48#include <sys/conf.h> 49#include <sys/endian.h> 50#include <sys/interrupt.h> 51#include <sys/kernel.h> 52#include <sys/mbuf.h> 53#include <sys/module.h> 54 55#include <machine/resource.h> 56#include <sys/rman.h> 57 58#include <sys/socket.h> 59#include <net/if.h> 60#include <net/if_var.h> 61 62#include <dev/pccard/pccardreg.h> 63#include <dev/pccard/pccardvar.h> 64#include "pccarddevs.h" 65 66#include <netgraph/ng_message.h> 67#include <netgraph/netgraph.h> 68#include <netgraph/ng_parse.h> 69#include <netgraph/bluetooth/include/ng_bluetooth.h> 70#include <netgraph/bluetooth/include/ng_hci.h> 71#include <netgraph/bluetooth/include/ng_bt3c.h> 72#include <netgraph/bluetooth/drivers/bt3c/ng_bt3c_var.h> 73 74/* Netgraph methods */ 75static ng_constructor_t ng_bt3c_constructor; 76static ng_shutdown_t ng_bt3c_shutdown; 77static ng_newhook_t ng_bt3c_newhook; 78static ng_connect_t ng_bt3c_connect; 79static ng_disconnect_t ng_bt3c_disconnect; 80static ng_rcvmsg_t ng_bt3c_rcvmsg; 81static ng_rcvdata_t ng_bt3c_rcvdata; 82 83/* PCMCIA driver methods */ 84static int bt3c_pccard_probe (device_t); 85static int bt3c_pccard_attach (device_t); 86static int bt3c_pccard_detach (device_t); 87 88static void bt3c_intr (void *); 89static void bt3c_receive (bt3c_softc_p); 90 91static void bt3c_swi_intr (void *); 92static void bt3c_forward (node_p, hook_p, void *, int); 93static void bt3c_send (node_p, hook_p, void *, int); 94 95static void bt3c_download_firmware (bt3c_softc_p, char const *, int); 96 97#define bt3c_set_address(sc, address) \ 98do { \ 99 outb(rman_get_start((sc)->iobase) + BT3C_ADDR_L, ((address) & 0xff)); \ 100 outb(rman_get_start((sc)->iobase) + BT3C_ADDR_H, (((address) >> 8) & 0xff)); \ 101} while (0) 102 103#define bt3c_read_data(sc, data) \ 104do { \ 105 (data) = inb(rman_get_start((sc)->iobase) + BT3C_DATA_L); \ 106 (data) |= ((inb(rman_get_start((sc)->iobase) + BT3C_DATA_H) & 0xff) << 8); \ 107} while (0) 108 109#define bt3c_write_data(sc, data) \ 110do { \ 111 outb(rman_get_start((sc)->iobase) + BT3C_DATA_L, ((data) & 0xff)); \ 112 outb(rman_get_start((sc)->iobase) + BT3C_DATA_H, (((data) >> 8) & 0xff)); \ 113} while (0) 114 115#define bt3c_read_control(sc, data) \ 116do { \ 117 (data) = inb(rman_get_start((sc)->iobase) + BT3C_CONTROL); \ 118} while (0) 119 120#define bt3c_write_control(sc, data) \ 121do { \ 122 outb(rman_get_start((sc)->iobase) + BT3C_CONTROL, (data)); \ 123} while (0) 124 125#define bt3c_read(sc, address, data) \ 126do { \ 127 bt3c_set_address((sc), (address)); \ 128 bt3c_read_data((sc), (data)); \ 129} while(0) 130 131#define bt3c_write(sc, address, data) \ 132do { \ 133 bt3c_set_address((sc), (address)); \ 134 bt3c_write_data((sc), (data)); \ 135} while(0) 136 137static MALLOC_DEFINE(M_BT3C, "bt3c", "bt3c data structures"); 138 139/**************************************************************************** 140 **************************************************************************** 141 ** Netgraph specific 142 **************************************************************************** 143 ****************************************************************************/ 144 145/* 146 * Netgraph node type 147 */ 148 149/* Queue length */ 150static const struct ng_parse_struct_field ng_bt3c_node_qlen_type_fields[] = 151{ 152 { "queue", &ng_parse_int32_type, }, 153 { "qlen", &ng_parse_int32_type, }, 154 { NULL, } 155}; 156static const struct ng_parse_type ng_bt3c_node_qlen_type = { 157 &ng_parse_struct_type, 158 &ng_bt3c_node_qlen_type_fields 159}; 160 161/* Stat info */ 162static const struct ng_parse_struct_field ng_bt3c_node_stat_type_fields[] = 163{ 164 { "pckts_recv", &ng_parse_uint32_type, }, 165 { "bytes_recv", &ng_parse_uint32_type, }, 166 { "pckts_sent", &ng_parse_uint32_type, }, 167 { "bytes_sent", &ng_parse_uint32_type, }, 168 { "oerrors", &ng_parse_uint32_type, }, 169 { "ierrors", &ng_parse_uint32_type, }, 170 { NULL, } 171}; 172static const struct ng_parse_type ng_bt3c_node_stat_type = { 173 &ng_parse_struct_type, 174 &ng_bt3c_node_stat_type_fields 175}; 176 177static const struct ng_cmdlist ng_bt3c_cmdlist[] = { 178{ 179 NGM_BT3C_COOKIE, 180 NGM_BT3C_NODE_GET_STATE, 181 "get_state", 182 NULL, 183 &ng_parse_uint16_type 184}, 185{ 186 NGM_BT3C_COOKIE, 187 NGM_BT3C_NODE_SET_DEBUG, 188 "set_debug", 189 &ng_parse_uint16_type, 190 NULL 191}, 192{ 193 NGM_BT3C_COOKIE, 194 NGM_BT3C_NODE_GET_DEBUG, 195 "get_debug", 196 NULL, 197 &ng_parse_uint16_type 198}, 199{ 200 NGM_BT3C_COOKIE, 201 NGM_BT3C_NODE_GET_QLEN, 202 "get_qlen", 203 NULL, 204 &ng_bt3c_node_qlen_type 205}, 206{ 207 NGM_BT3C_COOKIE, 208 NGM_BT3C_NODE_SET_QLEN, 209 "set_qlen", 210 &ng_bt3c_node_qlen_type, 211 NULL 212}, 213{ 214 NGM_BT3C_COOKIE, 215 NGM_BT3C_NODE_GET_STAT, 216 "get_stat", 217 NULL, 218 &ng_bt3c_node_stat_type 219}, 220{ 221 NGM_BT3C_COOKIE, 222 NGM_BT3C_NODE_RESET_STAT, 223 "reset_stat", 224 NULL, 225 NULL 226}, 227{ 0, } 228}; 229 230static struct ng_type typestruct = { 231 .version = NG_ABI_VERSION, 232 .name = NG_BT3C_NODE_TYPE, 233 .constructor = ng_bt3c_constructor, 234 .rcvmsg = ng_bt3c_rcvmsg, 235 .shutdown = ng_bt3c_shutdown, 236 .newhook = ng_bt3c_newhook, 237 .connect = ng_bt3c_connect, 238 .rcvdata = ng_bt3c_rcvdata, 239 .disconnect = ng_bt3c_disconnect, 240 .cmdlist = ng_bt3c_cmdlist 241}; 242 243/* 244 * Netgraph node constructor. Do not allow to create node of this type. 245 */ 246 247static int 248ng_bt3c_constructor(node_p node) 249{ 250 return (EINVAL); 251} /* ng_bt3c_constructor */ 252 253/* 254 * Netgraph node destructor. Destroy node only when device has been detached 255 */ 256 257static int 258ng_bt3c_shutdown(node_p node) 259{ 260 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 261 262 /* Let old node go */ 263 NG_NODE_SET_PRIVATE(node, NULL); 264 NG_NODE_UNREF(node); 265 266 /* Create new fresh one if we are not going down */ 267 if (sc == NULL) 268 goto out; 269 270 /* Create new Netgraph node */ 271 if (ng_make_node_common(&typestruct, &sc->node) != 0) { 272 device_printf(sc->dev, "Could not create Netgraph node\n"); 273 sc->node = NULL; 274 goto out; 275 } 276 277 /* Name new Netgraph node */ 278 if (ng_name_node(sc->node, device_get_nameunit(sc->dev)) != 0) { 279 device_printf(sc->dev, "Could not name Netgraph node\n"); 280 NG_NODE_UNREF(sc->node); 281 sc->node = NULL; 282 goto out; 283 } 284 285 NG_NODE_SET_PRIVATE(sc->node, sc); 286out: 287 return (0); 288} /* ng_bt3c_shutdown */ 289 290/* 291 * Create new hook. There can only be one. 292 */ 293 294static int 295ng_bt3c_newhook(node_p node, hook_p hook, char const *name) 296{ 297 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 298 299 if (strcmp(name, NG_BT3C_HOOK) != 0) 300 return (EINVAL); 301 302 if (sc->hook != NULL) 303 return (EISCONN); 304 305 sc->hook = hook; 306 307 return (0); 308} /* ng_bt3c_newhook */ 309 310/* 311 * Connect hook. Say YEP, that's OK with me. 312 */ 313 314static int 315ng_bt3c_connect(hook_p hook) 316{ 317 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 318 319 if (hook != sc->hook) { 320 sc->hook = NULL; 321 return (EINVAL); 322 } 323 324 /* set the hook into queueing mode (for incoming (from wire) packets) */ 325 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 326 327 return (0); 328} /* ng_bt3c_connect */ 329 330/* 331 * Disconnect hook 332 */ 333 334static int 335ng_bt3c_disconnect(hook_p hook) 336{ 337 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 338 339 /* 340 * We need to check for sc != NULL because we can be called from 341 * bt3c_pccard_detach() via ng_rmnode_self() 342 */ 343 344 if (sc != NULL) { 345 if (hook != sc->hook) 346 return (EINVAL); 347 348 IF_DRAIN(&sc->inq); 349 IF_DRAIN(&sc->outq); 350 351 sc->hook = NULL; 352 } 353 354 return (0); 355} /* ng_bt3c_disconnect */ 356 357/* 358 * Process control message 359 */ 360 361static int 362ng_bt3c_rcvmsg(node_p node, item_p item, hook_p lasthook) 363{ 364 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 365 struct ng_mesg *msg = NULL, *rsp = NULL; 366 int error = 0; 367 368 if (sc == NULL) { 369 NG_FREE_ITEM(item); 370 return (EHOSTDOWN); 371 } 372 373 NGI_GET_MSG(item, msg); 374 375 switch (msg->header.typecookie) { 376 case NGM_GENERIC_COOKIE: 377 switch (msg->header.cmd) { 378 case NGM_TEXT_STATUS: 379 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT); 380 if (rsp == NULL) 381 error = ENOMEM; 382 else 383 snprintf(rsp->data, NG_TEXTRESPONSE, 384 "Hook: %s\n" \ 385 "Flags: %#x\n" \ 386 "Debug: %d\n" \ 387 "State: %d\n" \ 388 "IncmQ: [len:%d,max:%d]\n" \ 389 "OutgQ: [len:%d,max:%d]\n", 390 (sc->hook != NULL)? NG_BT3C_HOOK : "", 391 sc->flags, 392 sc->debug, 393 sc->state, 394 _IF_QLEN(&sc->inq), /* XXX */ 395 sc->inq.ifq_maxlen, /* XXX */ 396 _IF_QLEN(&sc->outq), /* XXX */ 397 sc->outq.ifq_maxlen /* XXX */ 398 ); 399 break; 400 401 default: 402 error = EINVAL; 403 break; 404 } 405 break; 406 407 case NGM_BT3C_COOKIE: 408 switch (msg->header.cmd) { 409 case NGM_BT3C_NODE_GET_STATE: 410 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_state_ep), 411 M_NOWAIT); 412 if (rsp == NULL) 413 error = ENOMEM; 414 else 415 *((ng_bt3c_node_state_ep *)(rsp->data)) = 416 sc->state; 417 break; 418 419 case NGM_BT3C_NODE_SET_DEBUG: 420 if (msg->header.arglen != sizeof(ng_bt3c_node_debug_ep)) 421 error = EMSGSIZE; 422 else 423 sc->debug = 424 *((ng_bt3c_node_debug_ep *)(msg->data)); 425 break; 426 427 case NGM_BT3C_NODE_GET_DEBUG: 428 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_debug_ep), 429 M_NOWAIT); 430 if (rsp == NULL) 431 error = ENOMEM; 432 else 433 *((ng_bt3c_node_debug_ep *)(rsp->data)) = 434 sc->debug; 435 break; 436 437 case NGM_BT3C_NODE_GET_QLEN: 438 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_qlen_ep), 439 M_NOWAIT); 440 if (rsp == NULL) { 441 error = ENOMEM; 442 break; 443 } 444 445 switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { 446 case NGM_BT3C_NODE_IN_QUEUE: 447 ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = 448 NGM_BT3C_NODE_IN_QUEUE; 449 ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = 450 sc->inq.ifq_maxlen; 451 break; 452 453 case NGM_BT3C_NODE_OUT_QUEUE: 454 ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = 455 NGM_BT3C_NODE_OUT_QUEUE; 456 ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = 457 sc->outq.ifq_maxlen; 458 break; 459 460 default: 461 NG_FREE_MSG(rsp); 462 error = EINVAL; 463 break; 464 } 465 break; 466 467 case NGM_BT3C_NODE_SET_QLEN: 468 if (msg->header.arglen != sizeof(ng_bt3c_node_qlen_ep)){ 469 error = EMSGSIZE; 470 break; 471 } 472 473 if (((ng_bt3c_node_qlen_ep *)(msg->data))->qlen <= 0) { 474 error = EINVAL; 475 break; 476 } 477 478 switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { 479 case NGM_BT3C_NODE_IN_QUEUE: 480 sc->inq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) 481 (msg->data))->qlen; /* XXX */ 482 break; 483 484 case NGM_BT3C_NODE_OUT_QUEUE: 485 sc->outq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) 486 (msg->data))->qlen; /* XXX */ 487 break; 488 489 default: 490 error = EINVAL; 491 break; 492 } 493 break; 494 495 case NGM_BT3C_NODE_GET_STAT: 496 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_stat_ep), 497 M_NOWAIT); 498 if (rsp == NULL) 499 error = ENOMEM; 500 else 501 bcopy(&sc->stat, rsp->data, 502 sizeof(ng_bt3c_node_stat_ep)); 503 break; 504 505 case NGM_BT3C_NODE_RESET_STAT: 506 NG_BT3C_STAT_RESET(sc->stat); 507 break; 508 509 case NGM_BT3C_NODE_DOWNLOAD_FIRMWARE: 510 if (msg->header.arglen < 511 sizeof(ng_bt3c_firmware_block_ep)) 512 error = EMSGSIZE; 513 else 514 bt3c_download_firmware(sc, msg->data, 515 msg->header.arglen); 516 break; 517 518 default: 519 error = EINVAL; 520 break; 521 } 522 break; 523 524 default: 525 error = EINVAL; 526 break; 527 } 528 529 NG_RESPOND_MSG(error, node, item, rsp); 530 NG_FREE_MSG(msg); 531 532 return (error); 533} /* ng_bt3c_rcvmsg */ 534 535/* 536 * Process data 537 */ 538 539static int 540ng_bt3c_rcvdata(hook_p hook, item_p item) 541{ 542 bt3c_softc_p sc = (bt3c_softc_p)NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 543 struct mbuf *m = NULL; 544 int error = 0; 545 546 if (sc == NULL) { 547 error = EHOSTDOWN; 548 goto out; 549 } 550 551 if (hook != sc->hook) { 552 error = EINVAL; 553 goto out; 554 } 555 556 NGI_GET_M(item, m); 557 558 IF_LOCK(&sc->outq); 559 if (_IF_QFULL(&sc->outq)) { 560 NG_BT3C_ERR(sc->dev, 561"Outgoing queue is full. Dropping mbuf, len=%d\n", m->m_pkthdr.len); 562 563 _IF_DROP(&sc->outq); 564 NG_BT3C_STAT_OERROR(sc->stat); 565 566 NG_FREE_M(m); 567 } else 568 _IF_ENQUEUE(&sc->outq, m); 569 IF_UNLOCK(&sc->outq); 570 571 error = ng_send_fn(sc->node, NULL, bt3c_send, NULL, 0 /* new send */); 572out: 573 NG_FREE_ITEM(item); 574 575 return (error); 576} /* ng_bt3c_rcvdata */ 577 578/**************************************************************************** 579 **************************************************************************** 580 ** PCMCIA driver specific 581 **************************************************************************** 582 ****************************************************************************/ 583 584/* 585 * PC Card (PCMCIA) probe routine 586 */ 587 588static int 589bt3c_pccard_probe(device_t dev) 590{ 591 static struct pccard_product const bt3c_pccard_products[] = { 592 PCMCIA_CARD(3COM, 3CRWB609), 593 { NULL, } 594 }; 595 596 struct pccard_product const *pp = NULL; 597 598 pp = pccard_product_lookup(dev, bt3c_pccard_products, 599 sizeof(bt3c_pccard_products[0]), NULL); 600 if (pp == NULL) 601 return (ENXIO); 602 603 device_set_desc(dev, pp->pp_name); 604 605 return (0); 606} /* bt3c_pccard_probe */ 607 608/* 609 * PC Card (PCMCIA) attach routine 610 */ 611 612static int 613bt3c_pccard_attach(device_t dev) 614{
| 32 * 33 * XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX 34 * 35 * Based on information obrained from: Jose Orlando Pereira <jop@di.uminho.pt> 36 * and disassembled w2k driver. 37 * 38 * XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX 39 * 40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44 45#include <sys/bus.h> 46#include <machine/bus.h> 47 48#include <sys/conf.h> 49#include <sys/endian.h> 50#include <sys/interrupt.h> 51#include <sys/kernel.h> 52#include <sys/mbuf.h> 53#include <sys/module.h> 54 55#include <machine/resource.h> 56#include <sys/rman.h> 57 58#include <sys/socket.h> 59#include <net/if.h> 60#include <net/if_var.h> 61 62#include <dev/pccard/pccardreg.h> 63#include <dev/pccard/pccardvar.h> 64#include "pccarddevs.h" 65 66#include <netgraph/ng_message.h> 67#include <netgraph/netgraph.h> 68#include <netgraph/ng_parse.h> 69#include <netgraph/bluetooth/include/ng_bluetooth.h> 70#include <netgraph/bluetooth/include/ng_hci.h> 71#include <netgraph/bluetooth/include/ng_bt3c.h> 72#include <netgraph/bluetooth/drivers/bt3c/ng_bt3c_var.h> 73 74/* Netgraph methods */ 75static ng_constructor_t ng_bt3c_constructor; 76static ng_shutdown_t ng_bt3c_shutdown; 77static ng_newhook_t ng_bt3c_newhook; 78static ng_connect_t ng_bt3c_connect; 79static ng_disconnect_t ng_bt3c_disconnect; 80static ng_rcvmsg_t ng_bt3c_rcvmsg; 81static ng_rcvdata_t ng_bt3c_rcvdata; 82 83/* PCMCIA driver methods */ 84static int bt3c_pccard_probe (device_t); 85static int bt3c_pccard_attach (device_t); 86static int bt3c_pccard_detach (device_t); 87 88static void bt3c_intr (void *); 89static void bt3c_receive (bt3c_softc_p); 90 91static void bt3c_swi_intr (void *); 92static void bt3c_forward (node_p, hook_p, void *, int); 93static void bt3c_send (node_p, hook_p, void *, int); 94 95static void bt3c_download_firmware (bt3c_softc_p, char const *, int); 96 97#define bt3c_set_address(sc, address) \ 98do { \ 99 outb(rman_get_start((sc)->iobase) + BT3C_ADDR_L, ((address) & 0xff)); \ 100 outb(rman_get_start((sc)->iobase) + BT3C_ADDR_H, (((address) >> 8) & 0xff)); \ 101} while (0) 102 103#define bt3c_read_data(sc, data) \ 104do { \ 105 (data) = inb(rman_get_start((sc)->iobase) + BT3C_DATA_L); \ 106 (data) |= ((inb(rman_get_start((sc)->iobase) + BT3C_DATA_H) & 0xff) << 8); \ 107} while (0) 108 109#define bt3c_write_data(sc, data) \ 110do { \ 111 outb(rman_get_start((sc)->iobase) + BT3C_DATA_L, ((data) & 0xff)); \ 112 outb(rman_get_start((sc)->iobase) + BT3C_DATA_H, (((data) >> 8) & 0xff)); \ 113} while (0) 114 115#define bt3c_read_control(sc, data) \ 116do { \ 117 (data) = inb(rman_get_start((sc)->iobase) + BT3C_CONTROL); \ 118} while (0) 119 120#define bt3c_write_control(sc, data) \ 121do { \ 122 outb(rman_get_start((sc)->iobase) + BT3C_CONTROL, (data)); \ 123} while (0) 124 125#define bt3c_read(sc, address, data) \ 126do { \ 127 bt3c_set_address((sc), (address)); \ 128 bt3c_read_data((sc), (data)); \ 129} while(0) 130 131#define bt3c_write(sc, address, data) \ 132do { \ 133 bt3c_set_address((sc), (address)); \ 134 bt3c_write_data((sc), (data)); \ 135} while(0) 136 137static MALLOC_DEFINE(M_BT3C, "bt3c", "bt3c data structures"); 138 139/**************************************************************************** 140 **************************************************************************** 141 ** Netgraph specific 142 **************************************************************************** 143 ****************************************************************************/ 144 145/* 146 * Netgraph node type 147 */ 148 149/* Queue length */ 150static const struct ng_parse_struct_field ng_bt3c_node_qlen_type_fields[] = 151{ 152 { "queue", &ng_parse_int32_type, }, 153 { "qlen", &ng_parse_int32_type, }, 154 { NULL, } 155}; 156static const struct ng_parse_type ng_bt3c_node_qlen_type = { 157 &ng_parse_struct_type, 158 &ng_bt3c_node_qlen_type_fields 159}; 160 161/* Stat info */ 162static const struct ng_parse_struct_field ng_bt3c_node_stat_type_fields[] = 163{ 164 { "pckts_recv", &ng_parse_uint32_type, }, 165 { "bytes_recv", &ng_parse_uint32_type, }, 166 { "pckts_sent", &ng_parse_uint32_type, }, 167 { "bytes_sent", &ng_parse_uint32_type, }, 168 { "oerrors", &ng_parse_uint32_type, }, 169 { "ierrors", &ng_parse_uint32_type, }, 170 { NULL, } 171}; 172static const struct ng_parse_type ng_bt3c_node_stat_type = { 173 &ng_parse_struct_type, 174 &ng_bt3c_node_stat_type_fields 175}; 176 177static const struct ng_cmdlist ng_bt3c_cmdlist[] = { 178{ 179 NGM_BT3C_COOKIE, 180 NGM_BT3C_NODE_GET_STATE, 181 "get_state", 182 NULL, 183 &ng_parse_uint16_type 184}, 185{ 186 NGM_BT3C_COOKIE, 187 NGM_BT3C_NODE_SET_DEBUG, 188 "set_debug", 189 &ng_parse_uint16_type, 190 NULL 191}, 192{ 193 NGM_BT3C_COOKIE, 194 NGM_BT3C_NODE_GET_DEBUG, 195 "get_debug", 196 NULL, 197 &ng_parse_uint16_type 198}, 199{ 200 NGM_BT3C_COOKIE, 201 NGM_BT3C_NODE_GET_QLEN, 202 "get_qlen", 203 NULL, 204 &ng_bt3c_node_qlen_type 205}, 206{ 207 NGM_BT3C_COOKIE, 208 NGM_BT3C_NODE_SET_QLEN, 209 "set_qlen", 210 &ng_bt3c_node_qlen_type, 211 NULL 212}, 213{ 214 NGM_BT3C_COOKIE, 215 NGM_BT3C_NODE_GET_STAT, 216 "get_stat", 217 NULL, 218 &ng_bt3c_node_stat_type 219}, 220{ 221 NGM_BT3C_COOKIE, 222 NGM_BT3C_NODE_RESET_STAT, 223 "reset_stat", 224 NULL, 225 NULL 226}, 227{ 0, } 228}; 229 230static struct ng_type typestruct = { 231 .version = NG_ABI_VERSION, 232 .name = NG_BT3C_NODE_TYPE, 233 .constructor = ng_bt3c_constructor, 234 .rcvmsg = ng_bt3c_rcvmsg, 235 .shutdown = ng_bt3c_shutdown, 236 .newhook = ng_bt3c_newhook, 237 .connect = ng_bt3c_connect, 238 .rcvdata = ng_bt3c_rcvdata, 239 .disconnect = ng_bt3c_disconnect, 240 .cmdlist = ng_bt3c_cmdlist 241}; 242 243/* 244 * Netgraph node constructor. Do not allow to create node of this type. 245 */ 246 247static int 248ng_bt3c_constructor(node_p node) 249{ 250 return (EINVAL); 251} /* ng_bt3c_constructor */ 252 253/* 254 * Netgraph node destructor. Destroy node only when device has been detached 255 */ 256 257static int 258ng_bt3c_shutdown(node_p node) 259{ 260 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 261 262 /* Let old node go */ 263 NG_NODE_SET_PRIVATE(node, NULL); 264 NG_NODE_UNREF(node); 265 266 /* Create new fresh one if we are not going down */ 267 if (sc == NULL) 268 goto out; 269 270 /* Create new Netgraph node */ 271 if (ng_make_node_common(&typestruct, &sc->node) != 0) { 272 device_printf(sc->dev, "Could not create Netgraph node\n"); 273 sc->node = NULL; 274 goto out; 275 } 276 277 /* Name new Netgraph node */ 278 if (ng_name_node(sc->node, device_get_nameunit(sc->dev)) != 0) { 279 device_printf(sc->dev, "Could not name Netgraph node\n"); 280 NG_NODE_UNREF(sc->node); 281 sc->node = NULL; 282 goto out; 283 } 284 285 NG_NODE_SET_PRIVATE(sc->node, sc); 286out: 287 return (0); 288} /* ng_bt3c_shutdown */ 289 290/* 291 * Create new hook. There can only be one. 292 */ 293 294static int 295ng_bt3c_newhook(node_p node, hook_p hook, char const *name) 296{ 297 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 298 299 if (strcmp(name, NG_BT3C_HOOK) != 0) 300 return (EINVAL); 301 302 if (sc->hook != NULL) 303 return (EISCONN); 304 305 sc->hook = hook; 306 307 return (0); 308} /* ng_bt3c_newhook */ 309 310/* 311 * Connect hook. Say YEP, that's OK with me. 312 */ 313 314static int 315ng_bt3c_connect(hook_p hook) 316{ 317 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 318 319 if (hook != sc->hook) { 320 sc->hook = NULL; 321 return (EINVAL); 322 } 323 324 /* set the hook into queueing mode (for incoming (from wire) packets) */ 325 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook)); 326 327 return (0); 328} /* ng_bt3c_connect */ 329 330/* 331 * Disconnect hook 332 */ 333 334static int 335ng_bt3c_disconnect(hook_p hook) 336{ 337 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 338 339 /* 340 * We need to check for sc != NULL because we can be called from 341 * bt3c_pccard_detach() via ng_rmnode_self() 342 */ 343 344 if (sc != NULL) { 345 if (hook != sc->hook) 346 return (EINVAL); 347 348 IF_DRAIN(&sc->inq); 349 IF_DRAIN(&sc->outq); 350 351 sc->hook = NULL; 352 } 353 354 return (0); 355} /* ng_bt3c_disconnect */ 356 357/* 358 * Process control message 359 */ 360 361static int 362ng_bt3c_rcvmsg(node_p node, item_p item, hook_p lasthook) 363{ 364 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 365 struct ng_mesg *msg = NULL, *rsp = NULL; 366 int error = 0; 367 368 if (sc == NULL) { 369 NG_FREE_ITEM(item); 370 return (EHOSTDOWN); 371 } 372 373 NGI_GET_MSG(item, msg); 374 375 switch (msg->header.typecookie) { 376 case NGM_GENERIC_COOKIE: 377 switch (msg->header.cmd) { 378 case NGM_TEXT_STATUS: 379 NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT); 380 if (rsp == NULL) 381 error = ENOMEM; 382 else 383 snprintf(rsp->data, NG_TEXTRESPONSE, 384 "Hook: %s\n" \ 385 "Flags: %#x\n" \ 386 "Debug: %d\n" \ 387 "State: %d\n" \ 388 "IncmQ: [len:%d,max:%d]\n" \ 389 "OutgQ: [len:%d,max:%d]\n", 390 (sc->hook != NULL)? NG_BT3C_HOOK : "", 391 sc->flags, 392 sc->debug, 393 sc->state, 394 _IF_QLEN(&sc->inq), /* XXX */ 395 sc->inq.ifq_maxlen, /* XXX */ 396 _IF_QLEN(&sc->outq), /* XXX */ 397 sc->outq.ifq_maxlen /* XXX */ 398 ); 399 break; 400 401 default: 402 error = EINVAL; 403 break; 404 } 405 break; 406 407 case NGM_BT3C_COOKIE: 408 switch (msg->header.cmd) { 409 case NGM_BT3C_NODE_GET_STATE: 410 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_state_ep), 411 M_NOWAIT); 412 if (rsp == NULL) 413 error = ENOMEM; 414 else 415 *((ng_bt3c_node_state_ep *)(rsp->data)) = 416 sc->state; 417 break; 418 419 case NGM_BT3C_NODE_SET_DEBUG: 420 if (msg->header.arglen != sizeof(ng_bt3c_node_debug_ep)) 421 error = EMSGSIZE; 422 else 423 sc->debug = 424 *((ng_bt3c_node_debug_ep *)(msg->data)); 425 break; 426 427 case NGM_BT3C_NODE_GET_DEBUG: 428 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_debug_ep), 429 M_NOWAIT); 430 if (rsp == NULL) 431 error = ENOMEM; 432 else 433 *((ng_bt3c_node_debug_ep *)(rsp->data)) = 434 sc->debug; 435 break; 436 437 case NGM_BT3C_NODE_GET_QLEN: 438 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_qlen_ep), 439 M_NOWAIT); 440 if (rsp == NULL) { 441 error = ENOMEM; 442 break; 443 } 444 445 switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { 446 case NGM_BT3C_NODE_IN_QUEUE: 447 ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = 448 NGM_BT3C_NODE_IN_QUEUE; 449 ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = 450 sc->inq.ifq_maxlen; 451 break; 452 453 case NGM_BT3C_NODE_OUT_QUEUE: 454 ((ng_bt3c_node_qlen_ep *)(rsp->data))->queue = 455 NGM_BT3C_NODE_OUT_QUEUE; 456 ((ng_bt3c_node_qlen_ep *)(rsp->data))->qlen = 457 sc->outq.ifq_maxlen; 458 break; 459 460 default: 461 NG_FREE_MSG(rsp); 462 error = EINVAL; 463 break; 464 } 465 break; 466 467 case NGM_BT3C_NODE_SET_QLEN: 468 if (msg->header.arglen != sizeof(ng_bt3c_node_qlen_ep)){ 469 error = EMSGSIZE; 470 break; 471 } 472 473 if (((ng_bt3c_node_qlen_ep *)(msg->data))->qlen <= 0) { 474 error = EINVAL; 475 break; 476 } 477 478 switch (((ng_bt3c_node_qlen_ep *)(msg->data))->queue) { 479 case NGM_BT3C_NODE_IN_QUEUE: 480 sc->inq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) 481 (msg->data))->qlen; /* XXX */ 482 break; 483 484 case NGM_BT3C_NODE_OUT_QUEUE: 485 sc->outq.ifq_maxlen = ((ng_bt3c_node_qlen_ep *) 486 (msg->data))->qlen; /* XXX */ 487 break; 488 489 default: 490 error = EINVAL; 491 break; 492 } 493 break; 494 495 case NGM_BT3C_NODE_GET_STAT: 496 NG_MKRESPONSE(rsp, msg, sizeof(ng_bt3c_node_stat_ep), 497 M_NOWAIT); 498 if (rsp == NULL) 499 error = ENOMEM; 500 else 501 bcopy(&sc->stat, rsp->data, 502 sizeof(ng_bt3c_node_stat_ep)); 503 break; 504 505 case NGM_BT3C_NODE_RESET_STAT: 506 NG_BT3C_STAT_RESET(sc->stat); 507 break; 508 509 case NGM_BT3C_NODE_DOWNLOAD_FIRMWARE: 510 if (msg->header.arglen < 511 sizeof(ng_bt3c_firmware_block_ep)) 512 error = EMSGSIZE; 513 else 514 bt3c_download_firmware(sc, msg->data, 515 msg->header.arglen); 516 break; 517 518 default: 519 error = EINVAL; 520 break; 521 } 522 break; 523 524 default: 525 error = EINVAL; 526 break; 527 } 528 529 NG_RESPOND_MSG(error, node, item, rsp); 530 NG_FREE_MSG(msg); 531 532 return (error); 533} /* ng_bt3c_rcvmsg */ 534 535/* 536 * Process data 537 */ 538 539static int 540ng_bt3c_rcvdata(hook_p hook, item_p item) 541{ 542 bt3c_softc_p sc = (bt3c_softc_p)NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 543 struct mbuf *m = NULL; 544 int error = 0; 545 546 if (sc == NULL) { 547 error = EHOSTDOWN; 548 goto out; 549 } 550 551 if (hook != sc->hook) { 552 error = EINVAL; 553 goto out; 554 } 555 556 NGI_GET_M(item, m); 557 558 IF_LOCK(&sc->outq); 559 if (_IF_QFULL(&sc->outq)) { 560 NG_BT3C_ERR(sc->dev, 561"Outgoing queue is full. Dropping mbuf, len=%d\n", m->m_pkthdr.len); 562 563 _IF_DROP(&sc->outq); 564 NG_BT3C_STAT_OERROR(sc->stat); 565 566 NG_FREE_M(m); 567 } else 568 _IF_ENQUEUE(&sc->outq, m); 569 IF_UNLOCK(&sc->outq); 570 571 error = ng_send_fn(sc->node, NULL, bt3c_send, NULL, 0 /* new send */); 572out: 573 NG_FREE_ITEM(item); 574 575 return (error); 576} /* ng_bt3c_rcvdata */ 577 578/**************************************************************************** 579 **************************************************************************** 580 ** PCMCIA driver specific 581 **************************************************************************** 582 ****************************************************************************/ 583 584/* 585 * PC Card (PCMCIA) probe routine 586 */ 587 588static int 589bt3c_pccard_probe(device_t dev) 590{ 591 static struct pccard_product const bt3c_pccard_products[] = { 592 PCMCIA_CARD(3COM, 3CRWB609), 593 { NULL, } 594 }; 595 596 struct pccard_product const *pp = NULL; 597 598 pp = pccard_product_lookup(dev, bt3c_pccard_products, 599 sizeof(bt3c_pccard_products[0]), NULL); 600 if (pp == NULL) 601 return (ENXIO); 602 603 device_set_desc(dev, pp->pp_name); 604 605 return (0); 606} /* bt3c_pccard_probe */ 607 608/* 609 * PC Card (PCMCIA) attach routine 610 */ 611 612static int 613bt3c_pccard_attach(device_t dev) 614{
|
615 bt3c_softc_p sc = NULL;
| 615 bt3c_softc_p sc = (bt3c_softc_p) device_get_softc(dev);
|
616
| 616
|
617 sc = (bt3c_softc_p) malloc(sizeof(*sc), M_BT3C, M_NOWAIT|M_ZERO); 618 if (sc == NULL) 619 return (ENOMEM); 620
| |
621 /* Allocate I/O ports */ 622 sc->iobase_rid = 0; 623 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iobase_rid, 624 0, ~0, 8, RF_ACTIVE); 625 if (sc->iobase == NULL) { 626 device_printf(dev, "Could not allocate I/O ports\n"); 627 goto bad; 628 } 629 630 /* Allocate IRQ */ 631 sc->irq_rid = 0; 632 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 633 RF_ACTIVE); 634 if (sc->irq == NULL) { 635 device_printf(dev, "Could not allocate IRQ\n"); 636 goto bad; 637 } 638 639 sc->irq_cookie = NULL; 640 if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, bt3c_intr, sc, 641 &sc->irq_cookie) != 0) { 642 device_printf(dev, "Could not setup ISR\n"); 643 goto bad; 644 } 645 646 /* Attach handler to TTY SWI thread */ 647 sc->ith = NULL; 648 if (swi_add(&tty_intr_event, device_get_nameunit(dev), 649 bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) { 650 device_printf(dev, "Could not setup SWI ISR\n"); 651 goto bad; 652 } 653 654 /* Create Netgraph node */ 655 if (ng_make_node_common(&typestruct, &sc->node) != 0) { 656 device_printf(dev, "Could not create Netgraph node\n"); 657 sc->node = NULL; 658 goto bad; 659 } 660 661 /* Name Netgraph node */ 662 if (ng_name_node(sc->node, device_get_nameunit(dev)) != 0) { 663 device_printf(dev, "Could not name Netgraph node\n"); 664 NG_NODE_UNREF(sc->node); 665 sc->node = NULL; 666 goto bad; 667 } 668 669 sc->dev = dev; 670 sc->debug = NG_BT3C_WARN_LEVEL; 671 672 sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = BT3C_DEFAULTQLEN; 673 mtx_init(&sc->inq.ifq_mtx, "BT3C inq", NULL, MTX_DEF); 674 mtx_init(&sc->outq.ifq_mtx, "BT3C outq", NULL, MTX_DEF); 675 676 sc->state = NG_BT3C_W4_PKT_IND; 677 sc->want = 1; 678 679 NG_NODE_SET_PRIVATE(sc->node, sc);
| 617 /* Allocate I/O ports */ 618 sc->iobase_rid = 0; 619 sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->iobase_rid, 620 0, ~0, 8, RF_ACTIVE); 621 if (sc->iobase == NULL) { 622 device_printf(dev, "Could not allocate I/O ports\n"); 623 goto bad; 624 } 625 626 /* Allocate IRQ */ 627 sc->irq_rid = 0; 628 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, 629 RF_ACTIVE); 630 if (sc->irq == NULL) { 631 device_printf(dev, "Could not allocate IRQ\n"); 632 goto bad; 633 } 634 635 sc->irq_cookie = NULL; 636 if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, bt3c_intr, sc, 637 &sc->irq_cookie) != 0) { 638 device_printf(dev, "Could not setup ISR\n"); 639 goto bad; 640 } 641 642 /* Attach handler to TTY SWI thread */ 643 sc->ith = NULL; 644 if (swi_add(&tty_intr_event, device_get_nameunit(dev), 645 bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) { 646 device_printf(dev, "Could not setup SWI ISR\n"); 647 goto bad; 648 } 649 650 /* Create Netgraph node */ 651 if (ng_make_node_common(&typestruct, &sc->node) != 0) { 652 device_printf(dev, "Could not create Netgraph node\n"); 653 sc->node = NULL; 654 goto bad; 655 } 656 657 /* Name Netgraph node */ 658 if (ng_name_node(sc->node, device_get_nameunit(dev)) != 0) { 659 device_printf(dev, "Could not name Netgraph node\n"); 660 NG_NODE_UNREF(sc->node); 661 sc->node = NULL; 662 goto bad; 663 } 664 665 sc->dev = dev; 666 sc->debug = NG_BT3C_WARN_LEVEL; 667 668 sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = BT3C_DEFAULTQLEN; 669 mtx_init(&sc->inq.ifq_mtx, "BT3C inq", NULL, MTX_DEF); 670 mtx_init(&sc->outq.ifq_mtx, "BT3C outq", NULL, MTX_DEF); 671 672 sc->state = NG_BT3C_W4_PKT_IND; 673 sc->want = 1; 674 675 NG_NODE_SET_PRIVATE(sc->node, sc);
|
680 device_set_softc(dev, sc);
| |
681 682 return (0); 683bad: 684 if (sc->ith != NULL) { 685 swi_remove(sc->ith); 686 sc->ith = NULL; 687 } 688 689 if (sc->irq != NULL) { 690 if (sc->irq_cookie != NULL) 691 bus_teardown_intr(dev, sc->irq, sc->irq_cookie); 692 693 bus_release_resource(dev, SYS_RES_IRQ, 694 sc->irq_rid, sc->irq); 695 696 sc->irq = NULL; 697 sc->irq_rid = 0; 698 } 699 700 if (sc->iobase != NULL) { 701 bus_release_resource(dev, SYS_RES_IOPORT, 702 sc->iobase_rid, sc->iobase); 703 704 sc->iobase = NULL; 705 sc->iobase_rid = 0; 706 } 707
| 676 677 return (0); 678bad: 679 if (sc->ith != NULL) { 680 swi_remove(sc->ith); 681 sc->ith = NULL; 682 } 683 684 if (sc->irq != NULL) { 685 if (sc->irq_cookie != NULL) 686 bus_teardown_intr(dev, sc->irq, sc->irq_cookie); 687 688 bus_release_resource(dev, SYS_RES_IRQ, 689 sc->irq_rid, sc->irq); 690 691 sc->irq = NULL; 692 sc->irq_rid = 0; 693 } 694 695 if (sc->iobase != NULL) { 696 bus_release_resource(dev, SYS_RES_IOPORT, 697 sc->iobase_rid, sc->iobase); 698 699 sc->iobase = NULL; 700 sc->iobase_rid = 0; 701 } 702
|
708 free(sc, M_BT3C); 709
| |
710 return (ENXIO); 711} /* bt3c_pccacd_attach */ 712 713/* 714 * PC Card (PCMCIA) detach routine 715 */ 716 717static int 718bt3c_pccard_detach(device_t dev) 719{ 720 bt3c_softc_p sc = (bt3c_softc_p) device_get_softc(dev); 721 722 if (sc == NULL) 723 return (0); 724
| 703 return (ENXIO); 704} /* bt3c_pccacd_attach */ 705 706/* 707 * PC Card (PCMCIA) detach routine 708 */ 709 710static int 711bt3c_pccard_detach(device_t dev) 712{ 713 bt3c_softc_p sc = (bt3c_softc_p) device_get_softc(dev); 714 715 if (sc == NULL) 716 return (0); 717
|
725 device_set_softc(dev, NULL); 726
| |
727 swi_remove(sc->ith); 728 sc->ith = NULL; 729 730 bus_teardown_intr(dev, sc->irq, sc->irq_cookie); 731 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); 732 sc->irq_cookie = NULL; 733 sc->irq = NULL; 734 sc->irq_rid = 0; 735 736 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase); 737 sc->iobase = NULL; 738 sc->iobase_rid = 0; 739 740 if (sc->node != NULL) { 741 NG_NODE_SET_PRIVATE(sc->node, NULL); 742 ng_rmnode_self(sc->node); 743 sc->node = NULL; 744 } 745 746 NG_FREE_M(sc->m); 747 IF_DRAIN(&sc->inq); 748 IF_DRAIN(&sc->outq); 749 750 mtx_destroy(&sc->inq.ifq_mtx); 751 mtx_destroy(&sc->outq.ifq_mtx); 752
| 718 swi_remove(sc->ith); 719 sc->ith = NULL; 720 721 bus_teardown_intr(dev, sc->irq, sc->irq_cookie); 722 bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); 723 sc->irq_cookie = NULL; 724 sc->irq = NULL; 725 sc->irq_rid = 0; 726 727 bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase); 728 sc->iobase = NULL; 729 sc->iobase_rid = 0; 730 731 if (sc->node != NULL) { 732 NG_NODE_SET_PRIVATE(sc->node, NULL); 733 ng_rmnode_self(sc->node); 734 sc->node = NULL; 735 } 736 737 NG_FREE_M(sc->m); 738 IF_DRAIN(&sc->inq); 739 IF_DRAIN(&sc->outq); 740 741 mtx_destroy(&sc->inq.ifq_mtx); 742 mtx_destroy(&sc->outq.ifq_mtx); 743
|
753 bzero(sc, sizeof(*sc)); 754 free(sc, M_BT3C); 755
| |
756 return (0); 757} /* bt3c_pccacd_detach */ 758 759/* 760 * Interrupt service routine's 761 */ 762 763static void 764bt3c_intr(void *context) 765{ 766 bt3c_softc_p sc = (bt3c_softc_p) context; 767 u_int16_t control, status; 768 769 if (sc == NULL || sc->ith == NULL) { 770 printf("%s: bogus interrupt\n", NG_BT3C_NODE_TYPE); 771 return; 772 } 773 774 bt3c_read_control(sc, control); 775 if ((control & 0x80) == 0) 776 return; 777 778 bt3c_read(sc, 0x7001, status); 779 NG_BT3C_INFO(sc->dev, "control=%#x, status=%#x\n", control, status); 780 781 if ((status & 0xff) == 0x7f || (status & 0xff) == 0xff) { 782 NG_BT3C_WARN(sc->dev, "Strange status=%#x\n", status); 783 return; 784 } 785 786 /* Receive complete */ 787 if (status & 0x0001) 788 bt3c_receive(sc); 789 790 /* Record status and schedule SWI */ 791 sc->status |= status; 792 swi_sched(sc->ith, 0); 793 794 /* Complete interrupt */ 795 bt3c_write(sc, 0x7001, 0x0000); 796 bt3c_write_control(sc, control); 797} /* bt3c_intr */ 798 799/* 800 * Receive data 801 */ 802 803static void 804bt3c_receive(bt3c_softc_p sc) 805{ 806 u_int16_t i, count, c; 807 808 /* Receive data from the card */ 809 bt3c_read(sc, 0x7006, count); 810 NG_BT3C_INFO(sc->dev, "The card has %d characters\n", count); 811 812 bt3c_set_address(sc, 0x7480); 813 814 for (i = 0; i < count; i++) { 815 /* Allocate new mbuf if needed */ 816 if (sc->m == NULL) { 817 sc->state = NG_BT3C_W4_PKT_IND; 818 sc->want = 1; 819 820 MGETHDR(sc->m, M_DONTWAIT, MT_DATA); 821 if (sc->m == NULL) { 822 NG_BT3C_ERR(sc->dev, "Could not get mbuf\n"); 823 NG_BT3C_STAT_IERROR(sc->stat); 824 825 break; /* XXX lost of sync */ 826 } 827 828 MCLGET(sc->m, M_DONTWAIT); 829 if (!(sc->m->m_flags & M_EXT)) { 830 NG_FREE_M(sc->m); 831 832 NG_BT3C_ERR(sc->dev, "Could not get cluster\n"); 833 NG_BT3C_STAT_IERROR(sc->stat); 834 835 break; /* XXX lost of sync */ 836 } 837 838 sc->m->m_len = sc->m->m_pkthdr.len = 0; 839 } 840 841 /* Read and append character to mbuf */ 842 bt3c_read_data(sc, c); 843 if (sc->m->m_pkthdr.len >= MCLBYTES) { 844 NG_BT3C_ERR(sc->dev, "Oversized frame\n"); 845 846 NG_FREE_M(sc->m); 847 sc->state = NG_BT3C_W4_PKT_IND; 848 sc->want = 1; 849 850 break; /* XXX lost of sync */ 851 } 852 853 mtod(sc->m, u_int8_t *)[sc->m->m_len ++] = (u_int8_t) c; 854 sc->m->m_pkthdr.len ++; 855 856 NG_BT3C_INFO(sc->dev, 857"Got char %#x, want=%d, got=%d\n", c, sc->want, sc->m->m_pkthdr.len); 858 859 if (sc->m->m_pkthdr.len < sc->want) 860 continue; /* wait for more */ 861 862 switch (sc->state) { 863 /* Got packet indicator */ 864 case NG_BT3C_W4_PKT_IND: 865 NG_BT3C_INFO(sc->dev, 866"Got packet indicator %#x\n", *mtod(sc->m, u_int8_t *)); 867 868 sc->state = NG_BT3C_W4_PKT_HDR; 869 870 /* 871 * Since packet indicator included in the packet 872 * header just set sc->want to sizeof(packet header). 873 */ 874 875 switch (*mtod(sc->m, u_int8_t *)) { 876 case NG_HCI_ACL_DATA_PKT: 877 sc->want = sizeof(ng_hci_acldata_pkt_t); 878 break; 879 880 case NG_HCI_SCO_DATA_PKT: 881 sc->want = sizeof(ng_hci_scodata_pkt_t); 882 break; 883 884 case NG_HCI_EVENT_PKT: 885 sc->want = sizeof(ng_hci_event_pkt_t); 886 break; 887 888 default: 889 NG_BT3C_ERR(sc->dev, 890"Ignoring unknown packet type=%#x\n", *mtod(sc->m, u_int8_t *)); 891 892 NG_BT3C_STAT_IERROR(sc->stat); 893 894 NG_FREE_M(sc->m); 895 sc->state = NG_BT3C_W4_PKT_IND; 896 sc->want = 1; 897 break; 898 } 899 break; 900 901 /* Got packet header */ 902 case NG_BT3C_W4_PKT_HDR: 903 sc->state = NG_BT3C_W4_PKT_DATA; 904 905 switch (*mtod(sc->m, u_int8_t *)) { 906 case NG_HCI_ACL_DATA_PKT: 907 c = le16toh(mtod(sc->m, 908 ng_hci_acldata_pkt_t *)->length); 909 break; 910 911 case NG_HCI_SCO_DATA_PKT: 912 c = mtod(sc->m, ng_hci_scodata_pkt_t*)->length; 913 break; 914 915 case NG_HCI_EVENT_PKT: 916 c = mtod(sc->m, ng_hci_event_pkt_t *)->length; 917 break; 918 919 default: 920 KASSERT(0, 921("Invalid packet type=%#x\n", *mtod(sc->m, u_int8_t *))); 922 break; 923 } 924 925 NG_BT3C_INFO(sc->dev, 926"Got packet header, packet type=%#x, got so far %d, payload size=%d\n", 927 *mtod(sc->m, u_int8_t *), sc->m->m_pkthdr.len, 928 c); 929 930 if (c > 0) { 931 sc->want += c; 932 break; 933 } 934 935 /* else FALLTHROUGH and deliver frame */ 936 /* XXX is this true? should we deliver empty frame? */ 937 938 /* Got packet data */ 939 case NG_BT3C_W4_PKT_DATA: 940 NG_BT3C_INFO(sc->dev, 941"Got full packet, packet type=%#x, packet size=%d\n", 942 *mtod(sc->m, u_int8_t *), sc->m->m_pkthdr.len); 943 944 NG_BT3C_STAT_BYTES_RECV(sc->stat, sc->m->m_pkthdr.len); 945 NG_BT3C_STAT_PCKTS_RECV(sc->stat); 946 947 IF_LOCK(&sc->inq); 948 if (_IF_QFULL(&sc->inq)) { 949 NG_BT3C_ERR(sc->dev, 950"Incoming queue is full. Dropping mbuf, len=%d\n", sc->m->m_pkthdr.len); 951 952 _IF_DROP(&sc->inq); 953 NG_BT3C_STAT_IERROR(sc->stat); 954 955 NG_FREE_M(sc->m); 956 } else { 957 _IF_ENQUEUE(&sc->inq, sc->m); 958 sc->m = NULL; 959 } 960 IF_UNLOCK(&sc->inq); 961 962 sc->state = NG_BT3C_W4_PKT_IND; 963 sc->want = 1; 964 break; 965 966 default: 967 KASSERT(0, 968("Invalid node state=%d", sc->state)); 969 break; 970 } 971 } 972 973 bt3c_write(sc, 0x7006, 0x0000); 974} /* bt3c_receive */ 975 976/* 977 * SWI interrupt handler 978 * Netgraph part is handled via ng_send_fn() to avoid race with hook 979 * connection/disconnection 980 */ 981 982static void 983bt3c_swi_intr(void *context) 984{ 985 bt3c_softc_p sc = (bt3c_softc_p) context; 986 u_int16_t data; 987 988 /* Receive complete */ 989 if (sc->status & 0x0001) { 990 sc->status &= ~0x0001; /* XXX is it safe? */ 991 992 if (ng_send_fn(sc->node, NULL, &bt3c_forward, NULL, 0) != 0) 993 NG_BT3C_ALERT(sc->dev, "Could not forward frames!\n"); 994 } 995 996 /* Send complete */ 997 if (sc->status & 0x0002) { 998 sc->status &= ~0x0002; /* XXX is it safe */ 999 1000 if (ng_send_fn(sc->node, NULL, &bt3c_send, NULL, 1) != 0) 1001 NG_BT3C_ALERT(sc->dev, "Could not send frames!\n"); 1002 } 1003 1004 /* Antenna position */ 1005 if (sc->status & 0x0020) { 1006 sc->status &= ~0x0020; /* XXX is it safe */ 1007 1008 bt3c_read(sc, 0x7002, data); 1009 data &= 0x10; 1010 1011 if (data) 1012 sc->flags |= BT3C_ANTENNA_OUT; 1013 else 1014 sc->flags &= ~BT3C_ANTENNA_OUT; 1015 1016 NG_BT3C_INFO(sc->dev, "Antenna %s\n", data? "OUT" : "IN"); 1017 } 1018} /* bt3c_swi_intr */ 1019 1020/* 1021 * Send all incoming frames to the upper layer 1022 */ 1023 1024static void 1025bt3c_forward(node_p node, hook_p hook, void *arg1, int arg2) 1026{ 1027 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 1028 struct mbuf *m = NULL; 1029 int error; 1030 1031 if (sc == NULL) 1032 return; 1033 1034 if (sc->hook != NULL && NG_HOOK_IS_VALID(sc->hook)) { 1035 for (;;) { 1036 IF_DEQUEUE(&sc->inq, m); 1037 if (m == NULL) 1038 break; 1039 1040 NG_SEND_DATA_ONLY(error, sc->hook, m); 1041 if (error != 0) 1042 NG_BT3C_STAT_IERROR(sc->stat); 1043 } 1044 } else { 1045 IF_LOCK(&sc->inq); 1046 for (;;) { 1047 _IF_DEQUEUE(&sc->inq, m); 1048 if (m == NULL) 1049 break; 1050 1051 NG_BT3C_STAT_IERROR(sc->stat); 1052 NG_FREE_M(m); 1053 } 1054 IF_UNLOCK(&sc->inq); 1055 } 1056} /* bt3c_forward */ 1057 1058/* 1059 * Send more data to the device. Must be called when node is locked 1060 */ 1061 1062static void 1063bt3c_send(node_p node, hook_p hook, void *arg, int completed) 1064{ 1065 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 1066 struct mbuf *m = NULL; 1067 int i, wrote, len; 1068 1069 if (sc == NULL) 1070 return; 1071 1072 if (completed) 1073 sc->flags &= ~BT3C_XMIT; 1074 1075 if (sc->flags & BT3C_XMIT) 1076 return; 1077 1078 bt3c_set_address(sc, 0x7080); 1079 1080 for (wrote = 0; wrote < BT3C_FIFO_SIZE; ) { 1081 IF_DEQUEUE(&sc->outq, m); 1082 if (m == NULL) 1083 break; 1084 1085 while (m != NULL) { 1086 len = min((BT3C_FIFO_SIZE - wrote), m->m_len); 1087 1088 for (i = 0; i < len; i++) 1089 bt3c_write_data(sc, m->m_data[i]); 1090 1091 wrote += len; 1092 m->m_data += len; 1093 m->m_len -= len; 1094 1095 if (m->m_len > 0) 1096 break; 1097 1098 m = m_free(m); 1099 } 1100 1101 if (m != NULL) { 1102 IF_PREPEND(&sc->outq, m); 1103 break; 1104 } 1105 1106 NG_BT3C_STAT_PCKTS_SENT(sc->stat); 1107 } 1108 1109 if (wrote > 0) { 1110 NG_BT3C_INFO(sc->dev, "Wrote %d bytes\n", wrote); 1111 NG_BT3C_STAT_BYTES_SENT(sc->stat, wrote); 1112 1113 bt3c_write(sc, 0x7005, wrote); 1114 sc->flags |= BT3C_XMIT; 1115 } 1116} /* bt3c_send */ 1117 1118/* 1119 * Download chip firmware 1120 */ 1121 1122static void 1123bt3c_download_firmware(bt3c_softc_p sc, char const *firmware, int firmware_size) 1124{ 1125 ng_bt3c_firmware_block_ep const *block = NULL; 1126 u_int16_t const *data = NULL; 1127 int i, size; 1128 u_int8_t c; 1129 1130 /* Reset */ 1131 device_printf(sc->dev, "Reseting the card...\n"); 1132 bt3c_write(sc, 0x8040, 0x0404); 1133 bt3c_write(sc, 0x8040, 0x0400); 1134 DELAY(1); 1135 1136 bt3c_write(sc, 0x8040, 0x0404); 1137 DELAY(17); 1138 1139 /* Download firmware */ 1140 device_printf(sc->dev, "Starting firmware download process...\n"); 1141 1142 for (size = 0; size < firmware_size; ) { 1143 block = (ng_bt3c_firmware_block_ep const *)(firmware + size); 1144 data = (u_int16_t const *)(block + 1); 1145 1146 if (bootverbose) 1147 device_printf(sc->dev, "Download firmware block, " \ 1148 "address=%#08x, size=%d words, aligment=%d\n", 1149 block->block_address, block->block_size, 1150 block->block_alignment); 1151 1152 bt3c_set_address(sc, block->block_address); 1153 for (i = 0; i < block->block_size; i++) 1154 bt3c_write_data(sc, data[i]); 1155 1156 size += (sizeof(*block) + (block->block_size * 2) + 1157 block->block_alignment); 1158 } 1159 1160 DELAY(17); 1161 device_printf(sc->dev, "Firmware download process complete\n"); 1162 1163 /* Boot */ 1164 device_printf(sc->dev, "Starting the card...\n"); 1165 bt3c_set_address(sc, 0x3000); 1166 bt3c_read_control(sc, c); 1167 bt3c_write_control(sc, (c | 0x40)); 1168 DELAY(17); 1169 1170 /* Clear registers */ 1171 device_printf(sc->dev, "Clearing card registers...\n"); 1172 bt3c_write(sc, 0x7006, 0x0000); 1173 bt3c_write(sc, 0x7005, 0x0000); 1174 bt3c_write(sc, 0x7001, 0x0000); 1175 DELAY(1000); 1176} /* bt3c_download_firmware */ 1177 1178/**************************************************************************** 1179 **************************************************************************** 1180 ** Driver module 1181 **************************************************************************** 1182 ****************************************************************************/ 1183 1184/* 1185 * PC Card (PCMCIA) driver 1186 */ 1187 1188static device_method_t bt3c_pccard_methods[] = { 1189 /* Device interface */ 1190 DEVMETHOD(device_probe, bt3c_pccard_probe), 1191 DEVMETHOD(device_attach, bt3c_pccard_attach), 1192 DEVMETHOD(device_detach, bt3c_pccard_detach), 1193 1194 { 0, 0 } 1195}; 1196 1197static driver_t bt3c_pccard_driver = { 1198 NG_BT3C_NODE_TYPE, 1199 bt3c_pccard_methods,
| 744 return (0); 745} /* bt3c_pccacd_detach */ 746 747/* 748 * Interrupt service routine's 749 */ 750 751static void 752bt3c_intr(void *context) 753{ 754 bt3c_softc_p sc = (bt3c_softc_p) context; 755 u_int16_t control, status; 756 757 if (sc == NULL || sc->ith == NULL) { 758 printf("%s: bogus interrupt\n", NG_BT3C_NODE_TYPE); 759 return; 760 } 761 762 bt3c_read_control(sc, control); 763 if ((control & 0x80) == 0) 764 return; 765 766 bt3c_read(sc, 0x7001, status); 767 NG_BT3C_INFO(sc->dev, "control=%#x, status=%#x\n", control, status); 768 769 if ((status & 0xff) == 0x7f || (status & 0xff) == 0xff) { 770 NG_BT3C_WARN(sc->dev, "Strange status=%#x\n", status); 771 return; 772 } 773 774 /* Receive complete */ 775 if (status & 0x0001) 776 bt3c_receive(sc); 777 778 /* Record status and schedule SWI */ 779 sc->status |= status; 780 swi_sched(sc->ith, 0); 781 782 /* Complete interrupt */ 783 bt3c_write(sc, 0x7001, 0x0000); 784 bt3c_write_control(sc, control); 785} /* bt3c_intr */ 786 787/* 788 * Receive data 789 */ 790 791static void 792bt3c_receive(bt3c_softc_p sc) 793{ 794 u_int16_t i, count, c; 795 796 /* Receive data from the card */ 797 bt3c_read(sc, 0x7006, count); 798 NG_BT3C_INFO(sc->dev, "The card has %d characters\n", count); 799 800 bt3c_set_address(sc, 0x7480); 801 802 for (i = 0; i < count; i++) { 803 /* Allocate new mbuf if needed */ 804 if (sc->m == NULL) { 805 sc->state = NG_BT3C_W4_PKT_IND; 806 sc->want = 1; 807 808 MGETHDR(sc->m, M_DONTWAIT, MT_DATA); 809 if (sc->m == NULL) { 810 NG_BT3C_ERR(sc->dev, "Could not get mbuf\n"); 811 NG_BT3C_STAT_IERROR(sc->stat); 812 813 break; /* XXX lost of sync */ 814 } 815 816 MCLGET(sc->m, M_DONTWAIT); 817 if (!(sc->m->m_flags & M_EXT)) { 818 NG_FREE_M(sc->m); 819 820 NG_BT3C_ERR(sc->dev, "Could not get cluster\n"); 821 NG_BT3C_STAT_IERROR(sc->stat); 822 823 break; /* XXX lost of sync */ 824 } 825 826 sc->m->m_len = sc->m->m_pkthdr.len = 0; 827 } 828 829 /* Read and append character to mbuf */ 830 bt3c_read_data(sc, c); 831 if (sc->m->m_pkthdr.len >= MCLBYTES) { 832 NG_BT3C_ERR(sc->dev, "Oversized frame\n"); 833 834 NG_FREE_M(sc->m); 835 sc->state = NG_BT3C_W4_PKT_IND; 836 sc->want = 1; 837 838 break; /* XXX lost of sync */ 839 } 840 841 mtod(sc->m, u_int8_t *)[sc->m->m_len ++] = (u_int8_t) c; 842 sc->m->m_pkthdr.len ++; 843 844 NG_BT3C_INFO(sc->dev, 845"Got char %#x, want=%d, got=%d\n", c, sc->want, sc->m->m_pkthdr.len); 846 847 if (sc->m->m_pkthdr.len < sc->want) 848 continue; /* wait for more */ 849 850 switch (sc->state) { 851 /* Got packet indicator */ 852 case NG_BT3C_W4_PKT_IND: 853 NG_BT3C_INFO(sc->dev, 854"Got packet indicator %#x\n", *mtod(sc->m, u_int8_t *)); 855 856 sc->state = NG_BT3C_W4_PKT_HDR; 857 858 /* 859 * Since packet indicator included in the packet 860 * header just set sc->want to sizeof(packet header). 861 */ 862 863 switch (*mtod(sc->m, u_int8_t *)) { 864 case NG_HCI_ACL_DATA_PKT: 865 sc->want = sizeof(ng_hci_acldata_pkt_t); 866 break; 867 868 case NG_HCI_SCO_DATA_PKT: 869 sc->want = sizeof(ng_hci_scodata_pkt_t); 870 break; 871 872 case NG_HCI_EVENT_PKT: 873 sc->want = sizeof(ng_hci_event_pkt_t); 874 break; 875 876 default: 877 NG_BT3C_ERR(sc->dev, 878"Ignoring unknown packet type=%#x\n", *mtod(sc->m, u_int8_t *)); 879 880 NG_BT3C_STAT_IERROR(sc->stat); 881 882 NG_FREE_M(sc->m); 883 sc->state = NG_BT3C_W4_PKT_IND; 884 sc->want = 1; 885 break; 886 } 887 break; 888 889 /* Got packet header */ 890 case NG_BT3C_W4_PKT_HDR: 891 sc->state = NG_BT3C_W4_PKT_DATA; 892 893 switch (*mtod(sc->m, u_int8_t *)) { 894 case NG_HCI_ACL_DATA_PKT: 895 c = le16toh(mtod(sc->m, 896 ng_hci_acldata_pkt_t *)->length); 897 break; 898 899 case NG_HCI_SCO_DATA_PKT: 900 c = mtod(sc->m, ng_hci_scodata_pkt_t*)->length; 901 break; 902 903 case NG_HCI_EVENT_PKT: 904 c = mtod(sc->m, ng_hci_event_pkt_t *)->length; 905 break; 906 907 default: 908 KASSERT(0, 909("Invalid packet type=%#x\n", *mtod(sc->m, u_int8_t *))); 910 break; 911 } 912 913 NG_BT3C_INFO(sc->dev, 914"Got packet header, packet type=%#x, got so far %d, payload size=%d\n", 915 *mtod(sc->m, u_int8_t *), sc->m->m_pkthdr.len, 916 c); 917 918 if (c > 0) { 919 sc->want += c; 920 break; 921 } 922 923 /* else FALLTHROUGH and deliver frame */ 924 /* XXX is this true? should we deliver empty frame? */ 925 926 /* Got packet data */ 927 case NG_BT3C_W4_PKT_DATA: 928 NG_BT3C_INFO(sc->dev, 929"Got full packet, packet type=%#x, packet size=%d\n", 930 *mtod(sc->m, u_int8_t *), sc->m->m_pkthdr.len); 931 932 NG_BT3C_STAT_BYTES_RECV(sc->stat, sc->m->m_pkthdr.len); 933 NG_BT3C_STAT_PCKTS_RECV(sc->stat); 934 935 IF_LOCK(&sc->inq); 936 if (_IF_QFULL(&sc->inq)) { 937 NG_BT3C_ERR(sc->dev, 938"Incoming queue is full. Dropping mbuf, len=%d\n", sc->m->m_pkthdr.len); 939 940 _IF_DROP(&sc->inq); 941 NG_BT3C_STAT_IERROR(sc->stat); 942 943 NG_FREE_M(sc->m); 944 } else { 945 _IF_ENQUEUE(&sc->inq, sc->m); 946 sc->m = NULL; 947 } 948 IF_UNLOCK(&sc->inq); 949 950 sc->state = NG_BT3C_W4_PKT_IND; 951 sc->want = 1; 952 break; 953 954 default: 955 KASSERT(0, 956("Invalid node state=%d", sc->state)); 957 break; 958 } 959 } 960 961 bt3c_write(sc, 0x7006, 0x0000); 962} /* bt3c_receive */ 963 964/* 965 * SWI interrupt handler 966 * Netgraph part is handled via ng_send_fn() to avoid race with hook 967 * connection/disconnection 968 */ 969 970static void 971bt3c_swi_intr(void *context) 972{ 973 bt3c_softc_p sc = (bt3c_softc_p) context; 974 u_int16_t data; 975 976 /* Receive complete */ 977 if (sc->status & 0x0001) { 978 sc->status &= ~0x0001; /* XXX is it safe? */ 979 980 if (ng_send_fn(sc->node, NULL, &bt3c_forward, NULL, 0) != 0) 981 NG_BT3C_ALERT(sc->dev, "Could not forward frames!\n"); 982 } 983 984 /* Send complete */ 985 if (sc->status & 0x0002) { 986 sc->status &= ~0x0002; /* XXX is it safe */ 987 988 if (ng_send_fn(sc->node, NULL, &bt3c_send, NULL, 1) != 0) 989 NG_BT3C_ALERT(sc->dev, "Could not send frames!\n"); 990 } 991 992 /* Antenna position */ 993 if (sc->status & 0x0020) { 994 sc->status &= ~0x0020; /* XXX is it safe */ 995 996 bt3c_read(sc, 0x7002, data); 997 data &= 0x10; 998 999 if (data) 1000 sc->flags |= BT3C_ANTENNA_OUT; 1001 else 1002 sc->flags &= ~BT3C_ANTENNA_OUT; 1003 1004 NG_BT3C_INFO(sc->dev, "Antenna %s\n", data? "OUT" : "IN"); 1005 } 1006} /* bt3c_swi_intr */ 1007 1008/* 1009 * Send all incoming frames to the upper layer 1010 */ 1011 1012static void 1013bt3c_forward(node_p node, hook_p hook, void *arg1, int arg2) 1014{ 1015 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 1016 struct mbuf *m = NULL; 1017 int error; 1018 1019 if (sc == NULL) 1020 return; 1021 1022 if (sc->hook != NULL && NG_HOOK_IS_VALID(sc->hook)) { 1023 for (;;) { 1024 IF_DEQUEUE(&sc->inq, m); 1025 if (m == NULL) 1026 break; 1027 1028 NG_SEND_DATA_ONLY(error, sc->hook, m); 1029 if (error != 0) 1030 NG_BT3C_STAT_IERROR(sc->stat); 1031 } 1032 } else { 1033 IF_LOCK(&sc->inq); 1034 for (;;) { 1035 _IF_DEQUEUE(&sc->inq, m); 1036 if (m == NULL) 1037 break; 1038 1039 NG_BT3C_STAT_IERROR(sc->stat); 1040 NG_FREE_M(m); 1041 } 1042 IF_UNLOCK(&sc->inq); 1043 } 1044} /* bt3c_forward */ 1045 1046/* 1047 * Send more data to the device. Must be called when node is locked 1048 */ 1049 1050static void 1051bt3c_send(node_p node, hook_p hook, void *arg, int completed) 1052{ 1053 bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); 1054 struct mbuf *m = NULL; 1055 int i, wrote, len; 1056 1057 if (sc == NULL) 1058 return; 1059 1060 if (completed) 1061 sc->flags &= ~BT3C_XMIT; 1062 1063 if (sc->flags & BT3C_XMIT) 1064 return; 1065 1066 bt3c_set_address(sc, 0x7080); 1067 1068 for (wrote = 0; wrote < BT3C_FIFO_SIZE; ) { 1069 IF_DEQUEUE(&sc->outq, m); 1070 if (m == NULL) 1071 break; 1072 1073 while (m != NULL) { 1074 len = min((BT3C_FIFO_SIZE - wrote), m->m_len); 1075 1076 for (i = 0; i < len; i++) 1077 bt3c_write_data(sc, m->m_data[i]); 1078 1079 wrote += len; 1080 m->m_data += len; 1081 m->m_len -= len; 1082 1083 if (m->m_len > 0) 1084 break; 1085 1086 m = m_free(m); 1087 } 1088 1089 if (m != NULL) { 1090 IF_PREPEND(&sc->outq, m); 1091 break; 1092 } 1093 1094 NG_BT3C_STAT_PCKTS_SENT(sc->stat); 1095 } 1096 1097 if (wrote > 0) { 1098 NG_BT3C_INFO(sc->dev, "Wrote %d bytes\n", wrote); 1099 NG_BT3C_STAT_BYTES_SENT(sc->stat, wrote); 1100 1101 bt3c_write(sc, 0x7005, wrote); 1102 sc->flags |= BT3C_XMIT; 1103 } 1104} /* bt3c_send */ 1105 1106/* 1107 * Download chip firmware 1108 */ 1109 1110static void 1111bt3c_download_firmware(bt3c_softc_p sc, char const *firmware, int firmware_size) 1112{ 1113 ng_bt3c_firmware_block_ep const *block = NULL; 1114 u_int16_t const *data = NULL; 1115 int i, size; 1116 u_int8_t c; 1117 1118 /* Reset */ 1119 device_printf(sc->dev, "Reseting the card...\n"); 1120 bt3c_write(sc, 0x8040, 0x0404); 1121 bt3c_write(sc, 0x8040, 0x0400); 1122 DELAY(1); 1123 1124 bt3c_write(sc, 0x8040, 0x0404); 1125 DELAY(17); 1126 1127 /* Download firmware */ 1128 device_printf(sc->dev, "Starting firmware download process...\n"); 1129 1130 for (size = 0; size < firmware_size; ) { 1131 block = (ng_bt3c_firmware_block_ep const *)(firmware + size); 1132 data = (u_int16_t const *)(block + 1); 1133 1134 if (bootverbose) 1135 device_printf(sc->dev, "Download firmware block, " \ 1136 "address=%#08x, size=%d words, aligment=%d\n", 1137 block->block_address, block->block_size, 1138 block->block_alignment); 1139 1140 bt3c_set_address(sc, block->block_address); 1141 for (i = 0; i < block->block_size; i++) 1142 bt3c_write_data(sc, data[i]); 1143 1144 size += (sizeof(*block) + (block->block_size * 2) + 1145 block->block_alignment); 1146 } 1147 1148 DELAY(17); 1149 device_printf(sc->dev, "Firmware download process complete\n"); 1150 1151 /* Boot */ 1152 device_printf(sc->dev, "Starting the card...\n"); 1153 bt3c_set_address(sc, 0x3000); 1154 bt3c_read_control(sc, c); 1155 bt3c_write_control(sc, (c | 0x40)); 1156 DELAY(17); 1157 1158 /* Clear registers */ 1159 device_printf(sc->dev, "Clearing card registers...\n"); 1160 bt3c_write(sc, 0x7006, 0x0000); 1161 bt3c_write(sc, 0x7005, 0x0000); 1162 bt3c_write(sc, 0x7001, 0x0000); 1163 DELAY(1000); 1164} /* bt3c_download_firmware */ 1165 1166/**************************************************************************** 1167 **************************************************************************** 1168 ** Driver module 1169 **************************************************************************** 1170 ****************************************************************************/ 1171 1172/* 1173 * PC Card (PCMCIA) driver 1174 */ 1175 1176static device_method_t bt3c_pccard_methods[] = { 1177 /* Device interface */ 1178 DEVMETHOD(device_probe, bt3c_pccard_probe), 1179 DEVMETHOD(device_attach, bt3c_pccard_attach), 1180 DEVMETHOD(device_detach, bt3c_pccard_detach), 1181 1182 { 0, 0 } 1183}; 1184 1185static driver_t bt3c_pccard_driver = { 1186 NG_BT3C_NODE_TYPE, 1187 bt3c_pccard_methods,
|
1200 0
| 1188 sizeof(bt3c_softc_t)
|
1201}; 1202 1203static devclass_t bt3c_devclass; 1204 1205 1206/* 1207 * Load/Unload the driver module 1208 */ 1209 1210static int 1211bt3c_modevent(module_t mod, int event, void *data) 1212{ 1213 int error; 1214 1215 switch (event) { 1216 case MOD_LOAD: 1217 error = ng_newtype(&typestruct); 1218 if (error != 0) 1219 printf("%s: Could not register Netgraph node type, " \ 1220 "error=%d\n", NG_BT3C_NODE_TYPE, error); 1221 break; 1222 1223 case MOD_UNLOAD: 1224 error = ng_rmtype(&typestruct); 1225 break; 1226 1227 default: 1228 error = EOPNOTSUPP; 1229 break; 1230 } 1231 1232 return (error); 1233} /* bt3c_modevent */ 1234 1235DRIVER_MODULE(bt3c, pccard, bt3c_pccard_driver, bt3c_devclass, bt3c_modevent,0); 1236MODULE_VERSION(ng_bt3c, NG_BLUETOOTH_VERSION); 1237MODULE_DEPEND(ng_bt3c, netgraph, NG_ABI_VERSION, NG_ABI_VERSION,NG_ABI_VERSION); 1238
| 1189}; 1190 1191static devclass_t bt3c_devclass; 1192 1193 1194/* 1195 * Load/Unload the driver module 1196 */ 1197 1198static int 1199bt3c_modevent(module_t mod, int event, void *data) 1200{ 1201 int error; 1202 1203 switch (event) { 1204 case MOD_LOAD: 1205 error = ng_newtype(&typestruct); 1206 if (error != 0) 1207 printf("%s: Could not register Netgraph node type, " \ 1208 "error=%d\n", NG_BT3C_NODE_TYPE, error); 1209 break; 1210 1211 case MOD_UNLOAD: 1212 error = ng_rmtype(&typestruct); 1213 break; 1214 1215 default: 1216 error = EOPNOTSUPP; 1217 break; 1218 } 1219 1220 return (error); 1221} /* bt3c_modevent */ 1222 1223DRIVER_MODULE(bt3c, pccard, bt3c_pccard_driver, bt3c_devclass, bt3c_modevent,0); 1224MODULE_VERSION(ng_bt3c, NG_BLUETOOTH_VERSION); 1225MODULE_DEPEND(ng_bt3c, netgraph, NG_ABI_VERSION, NG_ABI_VERSION,NG_ABI_VERSION); 1226
|