linux/drivers/bluetooth/dtl1_cs.c
<<
>>
Prefs
   1/*
   2 *
   3 *  A driver for Nokia Connectivity Card DTL-1 devices
   4 *
   5 *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
   6 *
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License version 2 as
  10 *  published by the Free Software Foundation;
  11 *
  12 *  Software distributed under the License is distributed on an "AS
  13 *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  14 *  implied. See the License for the specific language governing
  15 *  rights and limitations under the License.
  16 *
  17 *  The initial developer of the original code is David A. Hinds
  18 *  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  19 *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  20 *
  21 */
  22
  23#include <linux/module.h>
  24
  25#include <linux/kernel.h>
  26#include <linux/init.h>
  27#include <linux/slab.h>
  28#include <linux/types.h>
  29#include <linux/delay.h>
  30#include <linux/errno.h>
  31#include <linux/ptrace.h>
  32#include <linux/ioport.h>
  33#include <linux/spinlock.h>
  34#include <linux/moduleparam.h>
  35
  36#include <linux/skbuff.h>
  37#include <linux/string.h>
  38#include <linux/serial.h>
  39#include <linux/serial_reg.h>
  40#include <linux/bitops.h>
  41#include <asm/system.h>
  42#include <asm/io.h>
  43
  44#include <pcmcia/cs_types.h>
  45#include <pcmcia/cs.h>
  46#include <pcmcia/cistpl.h>
  47#include <pcmcia/ciscode.h>
  48#include <pcmcia/ds.h>
  49#include <pcmcia/cisreg.h>
  50
  51#include <net/bluetooth/bluetooth.h>
  52#include <net/bluetooth/hci_core.h>
  53
  54
  55
  56/* ======================== Module parameters ======================== */
  57
  58
  59MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
  60MODULE_DESCRIPTION("Bluetooth driver for Nokia Connectivity Card DTL-1");
  61MODULE_LICENSE("GPL");
  62
  63
  64
  65/* ======================== Local structures ======================== */
  66
  67
  68typedef struct dtl1_info_t {
  69        struct pcmcia_device *p_dev;
  70
  71        struct hci_dev *hdev;
  72
  73        spinlock_t lock;                /* For serializing operations */
  74
  75        unsigned long flowmask;         /* HCI flow mask */
  76        int ri_latch;
  77
  78        struct sk_buff_head txq;
  79        unsigned long tx_state;
  80
  81        unsigned long rx_state;
  82        unsigned long rx_count;
  83        struct sk_buff *rx_skb;
  84} dtl1_info_t;
  85
  86
  87static int dtl1_config(struct pcmcia_device *link);
  88static void dtl1_release(struct pcmcia_device *link);
  89
  90static void dtl1_detach(struct pcmcia_device *p_dev);
  91
  92
  93/* Transmit states  */
  94#define XMIT_SENDING  1
  95#define XMIT_WAKEUP   2
  96#define XMIT_WAITING  8
  97
  98/* Receiver States */
  99#define RECV_WAIT_NSH   0
 100#define RECV_WAIT_DATA  1
 101
 102
 103typedef struct {
 104        u8 type;
 105        u8 zero;
 106        u16 len;
 107} __attribute__ ((packed)) nsh_t;       /* Nokia Specific Header */
 108
 109#define NSHL  4                         /* Nokia Specific Header Length */
 110
 111
 112
 113/* ======================== Interrupt handling ======================== */
 114
 115
 116static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 117{
 118        int actual = 0;
 119
 120        /* Tx FIFO should be empty */
 121        if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
 122                return 0;
 123
 124        /* Fill FIFO with current frame */
 125        while ((fifo_size-- > 0) && (actual < len)) {
 126                /* Transmit next byte */
 127                outb(buf[actual], iobase + UART_TX);
 128                actual++;
 129        }
 130
 131        return actual;
 132}
 133
 134
 135static void dtl1_write_wakeup(dtl1_info_t *info)
 136{
 137        if (!info) {
 138                BT_ERR("Unknown device");
 139                return;
 140        }
 141
 142        if (test_bit(XMIT_WAITING, &(info->tx_state))) {
 143                set_bit(XMIT_WAKEUP, &(info->tx_state));
 144                return;
 145        }
 146
 147        if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
 148                set_bit(XMIT_WAKEUP, &(info->tx_state));
 149                return;
 150        }
 151
 152        do {
 153                register unsigned int iobase = info->p_dev->io.BasePort1;
 154                register struct sk_buff *skb;
 155                register int len;
 156
 157                clear_bit(XMIT_WAKEUP, &(info->tx_state));
 158
 159                if (!pcmcia_dev_present(info->p_dev))
 160                        return;
 161
 162                if (!(skb = skb_dequeue(&(info->txq))))
 163                        break;
 164
 165                /* Send frame */
 166                len = dtl1_write(iobase, 32, skb->data, skb->len);
 167
 168                if (len == skb->len) {
 169                        set_bit(XMIT_WAITING, &(info->tx_state));
 170                        kfree_skb(skb);
 171                } else {
 172                        skb_pull(skb, len);
 173                        skb_queue_head(&(info->txq), skb);
 174                }
 175
 176                info->hdev->stat.byte_tx += len;
 177
 178        } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
 179
 180        clear_bit(XMIT_SENDING, &(info->tx_state));
 181}
 182
 183
 184static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
 185{
 186        u8 flowmask = *(u8 *)skb->data;
 187        int i;
 188
 189        printk(KERN_INFO "Bluetooth: Nokia control data =");
 190        for (i = 0; i < skb->len; i++) {
 191                printk(" %02x", skb->data[i]);
 192        }
 193        printk("\n");
 194
 195        /* transition to active state */
 196        if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
 197                clear_bit(XMIT_WAITING, &(info->tx_state));
 198                dtl1_write_wakeup(info);
 199        }
 200
 201        info->flowmask = flowmask;
 202
 203        kfree_skb(skb);
 204}
 205
 206
 207static void dtl1_receive(dtl1_info_t *info)
 208{
 209        unsigned int iobase;
 210        nsh_t *nsh;
 211        int boguscount = 0;
 212
 213        if (!info) {
 214                BT_ERR("Unknown device");
 215                return;
 216        }
 217
 218        iobase = info->p_dev->io.BasePort1;
 219
 220        do {
 221                info->hdev->stat.byte_rx++;
 222
 223                /* Allocate packet */
 224                if (info->rx_skb == NULL)
 225                        if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
 226                                BT_ERR("Can't allocate mem for new packet");
 227                                info->rx_state = RECV_WAIT_NSH;
 228                                info->rx_count = NSHL;
 229                                return;
 230                        }
 231
 232                *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
 233                nsh = (nsh_t *)info->rx_skb->data;
 234
 235                info->rx_count--;
 236
 237                if (info->rx_count == 0) {
 238
 239                        switch (info->rx_state) {
 240                        case RECV_WAIT_NSH:
 241                                info->rx_state = RECV_WAIT_DATA;
 242                                info->rx_count = nsh->len + (nsh->len & 0x0001);
 243                                break;
 244                        case RECV_WAIT_DATA:
 245                                bt_cb(info->rx_skb)->pkt_type = nsh->type;
 246
 247                                /* remove PAD byte if it exists */
 248                                if (nsh->len & 0x0001) {
 249                                        info->rx_skb->tail--;
 250                                        info->rx_skb->len--;
 251                                }
 252
 253                                /* remove NSH */
 254                                skb_pull(info->rx_skb, NSHL);
 255
 256                                switch (bt_cb(info->rx_skb)->pkt_type) {
 257                                case 0x80:
 258                                        /* control data for the Nokia Card */
 259                                        dtl1_control(info, info->rx_skb);
 260                                        break;
 261                                case 0x82:
 262                                case 0x83:
 263                                case 0x84:
 264                                        /* send frame to the HCI layer */
 265                                        info->rx_skb->dev = (void *) info->hdev;
 266                                        bt_cb(info->rx_skb)->pkt_type &= 0x0f;
 267                                        hci_recv_frame(info->rx_skb);
 268                                        break;
 269                                default:
 270                                        /* unknown packet */
 271                                        BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
 272                                        kfree_skb(info->rx_skb);
 273                                        break;
 274                                }
 275
 276                                info->rx_state = RECV_WAIT_NSH;
 277                                info->rx_count = NSHL;
 278                                info->rx_skb = NULL;
 279                                break;
 280                        }
 281
 282                }
 283
 284                /* Make sure we don't stay here too long */
 285                if (boguscount++ > 32)
 286                        break;
 287
 288        } while (inb(iobase + UART_LSR) & UART_LSR_DR);
 289}
 290
 291
 292static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
 293{
 294        dtl1_info_t *info = dev_inst;
 295        unsigned int iobase;
 296        unsigned char msr;
 297        int boguscount = 0;
 298        int iir, lsr;
 299        irqreturn_t r = IRQ_NONE;
 300
 301        if (!info || !info->hdev)
 302                /* our irq handler is shared */
 303                return IRQ_NONE;
 304
 305        iobase = info->p_dev->io.BasePort1;
 306
 307        spin_lock(&(info->lock));
 308
 309        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 310        while (iir) {
 311
 312                r = IRQ_HANDLED;
 313                /* Clear interrupt */
 314                lsr = inb(iobase + UART_LSR);
 315
 316                switch (iir) {
 317                case UART_IIR_RLSI:
 318                        BT_ERR("RLSI");
 319                        break;
 320                case UART_IIR_RDI:
 321                        /* Receive interrupt */
 322                        dtl1_receive(info);
 323                        break;
 324                case UART_IIR_THRI:
 325                        if (lsr & UART_LSR_THRE) {
 326                                /* Transmitter ready for data */
 327                                dtl1_write_wakeup(info);
 328                        }
 329                        break;
 330                default:
 331                        BT_ERR("Unhandled IIR=%#x", iir);
 332                        break;
 333                }
 334
 335                /* Make sure we don't stay here too long */
 336                if (boguscount++ > 100)
 337                        break;
 338
 339                iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 340
 341        }
 342
 343        msr = inb(iobase + UART_MSR);
 344
 345        if (info->ri_latch ^ (msr & UART_MSR_RI)) {
 346                info->ri_latch = msr & UART_MSR_RI;
 347                clear_bit(XMIT_WAITING, &(info->tx_state));
 348                dtl1_write_wakeup(info);
 349                r = IRQ_HANDLED;
 350        }
 351
 352        spin_unlock(&(info->lock));
 353
 354        return r;
 355}
 356
 357
 358
 359/* ======================== HCI interface ======================== */
 360
 361
 362static int dtl1_hci_open(struct hci_dev *hdev)
 363{
 364        set_bit(HCI_RUNNING, &(hdev->flags));
 365
 366        return 0;
 367}
 368
 369
 370static int dtl1_hci_flush(struct hci_dev *hdev)
 371{
 372        dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
 373
 374        /* Drop TX queue */
 375        skb_queue_purge(&(info->txq));
 376
 377        return 0;
 378}
 379
 380
 381static int dtl1_hci_close(struct hci_dev *hdev)
 382{
 383        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
 384                return 0;
 385
 386        dtl1_hci_flush(hdev);
 387
 388        return 0;
 389}
 390
 391
 392static int dtl1_hci_send_frame(struct sk_buff *skb)
 393{
 394        dtl1_info_t *info;
 395        struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
 396        struct sk_buff *s;
 397        nsh_t nsh;
 398
 399        if (!hdev) {
 400                BT_ERR("Frame for unknown HCI device (hdev=NULL)");
 401                return -ENODEV;
 402        }
 403
 404        info = (dtl1_info_t *)(hdev->driver_data);
 405
 406        switch (bt_cb(skb)->pkt_type) {
 407        case HCI_COMMAND_PKT:
 408                hdev->stat.cmd_tx++;
 409                nsh.type = 0x81;
 410                break;
 411        case HCI_ACLDATA_PKT:
 412                hdev->stat.acl_tx++;
 413                nsh.type = 0x82;
 414                break;
 415        case HCI_SCODATA_PKT:
 416                hdev->stat.sco_tx++;
 417                nsh.type = 0x83;
 418                break;
 419        default:
 420                return -EILSEQ;
 421        };
 422
 423        nsh.zero = 0;
 424        nsh.len = skb->len;
 425
 426        s = bt_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
 427        if (!s)
 428                return -ENOMEM;
 429
 430        skb_reserve(s, NSHL);
 431        skb_copy_from_linear_data(skb, skb_put(s, skb->len), skb->len);
 432        if (skb->len & 0x0001)
 433                *skb_put(s, 1) = 0;     /* PAD */
 434
 435        /* Prepend skb with Nokia frame header and queue */
 436        memcpy(skb_push(s, NSHL), &nsh, NSHL);
 437        skb_queue_tail(&(info->txq), s);
 438
 439        dtl1_write_wakeup(info);
 440
 441        kfree_skb(skb);
 442
 443        return 0;
 444}
 445
 446
 447static void dtl1_hci_destruct(struct hci_dev *hdev)
 448{
 449}
 450
 451
 452static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long arg)
 453{
 454        return -ENOIOCTLCMD;
 455}
 456
 457
 458
 459/* ======================== Card services HCI interaction ======================== */
 460
 461
 462static int dtl1_open(dtl1_info_t *info)
 463{
 464        unsigned long flags;
 465        unsigned int iobase = info->p_dev->io.BasePort1;
 466        struct hci_dev *hdev;
 467
 468        spin_lock_init(&(info->lock));
 469
 470        skb_queue_head_init(&(info->txq));
 471
 472        info->rx_state = RECV_WAIT_NSH;
 473        info->rx_count = NSHL;
 474        info->rx_skb = NULL;
 475
 476        set_bit(XMIT_WAITING, &(info->tx_state));
 477
 478        /* Initialize HCI device */
 479        hdev = hci_alloc_dev();
 480        if (!hdev) {
 481                BT_ERR("Can't allocate HCI device");
 482                return -ENOMEM;
 483        }
 484
 485        info->hdev = hdev;
 486
 487        hdev->bus = HCI_PCCARD;
 488        hdev->driver_data = info;
 489        SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 490
 491        hdev->open     = dtl1_hci_open;
 492        hdev->close    = dtl1_hci_close;
 493        hdev->flush    = dtl1_hci_flush;
 494        hdev->send     = dtl1_hci_send_frame;
 495        hdev->destruct = dtl1_hci_destruct;
 496        hdev->ioctl    = dtl1_hci_ioctl;
 497
 498        hdev->owner = THIS_MODULE;
 499
 500        spin_lock_irqsave(&(info->lock), flags);
 501
 502        /* Reset UART */
 503        outb(0, iobase + UART_MCR);
 504
 505        /* Turn off interrupts */
 506        outb(0, iobase + UART_IER);
 507
 508        /* Initialize UART */
 509        outb(UART_LCR_WLEN8, iobase + UART_LCR);        /* Reset DLAB */
 510        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 511
 512        info->ri_latch = inb(info->p_dev->io.BasePort1 + UART_MSR) & UART_MSR_RI;
 513
 514        /* Turn on interrupts */
 515        outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 516
 517        spin_unlock_irqrestore(&(info->lock), flags);
 518
 519        /* Timeout before it is safe to send the first HCI packet */
 520        msleep(2000);
 521
 522        /* Register HCI device */
 523        if (hci_register_dev(hdev) < 0) {
 524                BT_ERR("Can't register HCI device");
 525                info->hdev = NULL;
 526                hci_free_dev(hdev);
 527                return -ENODEV;
 528        }
 529
 530        return 0;
 531}
 532
 533
 534static int dtl1_close(dtl1_info_t *info)
 535{
 536        unsigned long flags;
 537        unsigned int iobase = info->p_dev->io.BasePort1;
 538        struct hci_dev *hdev = info->hdev;
 539
 540        if (!hdev)
 541                return -ENODEV;
 542
 543        dtl1_hci_close(hdev);
 544
 545        spin_lock_irqsave(&(info->lock), flags);
 546
 547        /* Reset UART */
 548        outb(0, iobase + UART_MCR);
 549
 550        /* Turn off interrupts */
 551        outb(0, iobase + UART_IER);
 552
 553        spin_unlock_irqrestore(&(info->lock), flags);
 554
 555        if (hci_unregister_dev(hdev) < 0)
 556                BT_ERR("Can't unregister HCI device %s", hdev->name);
 557
 558        hci_free_dev(hdev);
 559
 560        return 0;
 561}
 562
 563static int dtl1_probe(struct pcmcia_device *link)
 564{
 565        dtl1_info_t *info;
 566
 567        /* Create new info device */
 568        info = kzalloc(sizeof(*info), GFP_KERNEL);
 569        if (!info)
 570                return -ENOMEM;
 571
 572        info->p_dev = link;
 573        link->priv = info;
 574
 575        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 576        link->io.NumPorts1 = 8;
 577
 578        link->conf.Attributes = CONF_ENABLE_IRQ;
 579        link->conf.IntType = INT_MEMORY_AND_IO;
 580
 581        return dtl1_config(link);
 582}
 583
 584
 585static void dtl1_detach(struct pcmcia_device *link)
 586{
 587        dtl1_info_t *info = link->priv;
 588
 589        dtl1_release(link);
 590
 591        kfree(info);
 592}
 593
 594static int dtl1_confcheck(struct pcmcia_device *p_dev,
 595                          cistpl_cftable_entry_t *cf,
 596                          cistpl_cftable_entry_t *dflt,
 597                          unsigned int vcc,
 598                          void *priv_data)
 599{
 600        if ((cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
 601                p_dev->io.BasePort1 = cf->io.win[0].base;
 602                p_dev->io.NumPorts1 = cf->io.win[0].len;        /*yo */
 603                p_dev->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
 604                if (!pcmcia_request_io(p_dev, &p_dev->io))
 605                        return 0;
 606        }
 607        return -ENODEV;
 608}
 609
 610static int dtl1_config(struct pcmcia_device *link)
 611{
 612        dtl1_info_t *info = link->priv;
 613        int i;
 614
 615        /* Look for a generic full-sized window */
 616        link->io.NumPorts1 = 8;
 617        if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0)
 618                goto failed;
 619
 620        i = pcmcia_request_irq(link, dtl1_interrupt);
 621        if (i != 0)
 622                goto failed;
 623
 624        i = pcmcia_request_configuration(link, &link->conf);
 625        if (i != 0)
 626                goto failed;
 627
 628        if (dtl1_open(info) != 0)
 629                goto failed;
 630
 631        return 0;
 632
 633failed:
 634        dtl1_release(link);
 635        return -ENODEV;
 636}
 637
 638
 639static void dtl1_release(struct pcmcia_device *link)
 640{
 641        dtl1_info_t *info = link->priv;
 642
 643        dtl1_close(info);
 644
 645        pcmcia_disable_device(link);
 646}
 647
 648
 649static struct pcmcia_device_id dtl1_ids[] = {
 650        PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
 651        PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82),
 652        PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
 653        PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
 654        PCMCIA_DEVICE_NULL
 655};
 656MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
 657
 658static struct pcmcia_driver dtl1_driver = {
 659        .owner          = THIS_MODULE,
 660        .drv            = {
 661                .name   = "dtl1_cs",
 662        },
 663        .probe          = dtl1_probe,
 664        .remove         = dtl1_detach,
 665        .id_table       = dtl1_ids,
 666};
 667
 668static int __init init_dtl1_cs(void)
 669{
 670        return pcmcia_register_driver(&dtl1_driver);
 671}
 672
 673
 674static void __exit exit_dtl1_cs(void)
 675{
 676        pcmcia_unregister_driver(&dtl1_driver);
 677}
 678
 679module_init(init_dtl1_cs);
 680module_exit(exit_dtl1_cs);
 681
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.