linux/drivers/bluetooth/btuart_cs.c
<<
>>
Prefs
   1/*
   2 *
   3 *  Driver for Bluetooth PCMCIA cards with HCI UART interface
   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 Bluetooth PCMCIA cards with HCI UART interface");
  61MODULE_LICENSE("GPL");
  62
  63
  64
  65/* ======================== Local structures ======================== */
  66
  67
  68typedef struct btuart_info_t {
  69        struct pcmcia_device *p_dev;
  70        dev_node_t node;
  71
  72        struct hci_dev *hdev;
  73
  74        spinlock_t lock;        /* For serializing operations */
  75
  76        struct sk_buff_head txq;
  77        unsigned long tx_state;
  78
  79        unsigned long rx_state;
  80        unsigned long rx_count;
  81        struct sk_buff *rx_skb;
  82} btuart_info_t;
  83
  84
  85static int btuart_config(struct pcmcia_device *link);
  86static void btuart_release(struct pcmcia_device *link);
  87
  88static void btuart_detach(struct pcmcia_device *p_dev);
  89
  90
  91/* Maximum baud rate */
  92#define SPEED_MAX  115200
  93
  94/* Default baud rate: 57600, 115200, 230400 or 460800 */
  95#define DEFAULT_BAUD_RATE  115200
  96
  97
  98/* Transmit states  */
  99#define XMIT_SENDING    1
 100#define XMIT_WAKEUP     2
 101#define XMIT_WAITING    8
 102
 103/* Receiver states */
 104#define RECV_WAIT_PACKET_TYPE   0
 105#define RECV_WAIT_EVENT_HEADER  1
 106#define RECV_WAIT_ACL_HEADER    2
 107#define RECV_WAIT_SCO_HEADER    3
 108#define RECV_WAIT_DATA          4
 109
 110
 111
 112/* ======================== Interrupt handling ======================== */
 113
 114
 115static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
 116{
 117        int actual = 0;
 118
 119        /* Tx FIFO should be empty */
 120        if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
 121                return 0;
 122
 123        /* Fill FIFO with current frame */
 124        while ((fifo_size-- > 0) && (actual < len)) {
 125                /* Transmit next byte */
 126                outb(buf[actual], iobase + UART_TX);
 127                actual++;
 128        }
 129
 130        return actual;
 131}
 132
 133
 134static void btuart_write_wakeup(btuart_info_t *info)
 135{
 136        if (!info) {
 137                BT_ERR("Unknown device");
 138                return;
 139        }
 140
 141        if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
 142                set_bit(XMIT_WAKEUP, &(info->tx_state));
 143                return;
 144        }
 145
 146        do {
 147                register unsigned int iobase = info->p_dev->io.BasePort1;
 148                register struct sk_buff *skb;
 149                register int len;
 150
 151                clear_bit(XMIT_WAKEUP, &(info->tx_state));
 152
 153                if (!pcmcia_dev_present(info->p_dev))
 154                        return;
 155
 156                if (!(skb = skb_dequeue(&(info->txq))))
 157                        break;
 158
 159                /* Send frame */
 160                len = btuart_write(iobase, 16, skb->data, skb->len);
 161                set_bit(XMIT_WAKEUP, &(info->tx_state));
 162
 163                if (len == skb->len) {
 164                        kfree_skb(skb);
 165                } else {
 166                        skb_pull(skb, len);
 167                        skb_queue_head(&(info->txq), skb);
 168                }
 169
 170                info->hdev->stat.byte_tx += len;
 171
 172        } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
 173
 174        clear_bit(XMIT_SENDING, &(info->tx_state));
 175}
 176
 177
 178static void btuart_receive(btuart_info_t *info)
 179{
 180        unsigned int iobase;
 181        int boguscount = 0;
 182
 183        if (!info) {
 184                BT_ERR("Unknown device");
 185                return;
 186        }
 187
 188        iobase = info->p_dev->io.BasePort1;
 189
 190        do {
 191                info->hdev->stat.byte_rx++;
 192
 193                /* Allocate packet */
 194                if (info->rx_skb == NULL) {
 195                        info->rx_state = RECV_WAIT_PACKET_TYPE;
 196                        info->rx_count = 0;
 197                        if (!(info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
 198                                BT_ERR("Can't allocate mem for new packet");
 199                                return;
 200                        }
 201                }
 202
 203                if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
 204
 205                        info->rx_skb->dev = (void *) info->hdev;
 206                        bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX);
 207
 208                        switch (bt_cb(info->rx_skb)->pkt_type) {
 209
 210                        case HCI_EVENT_PKT:
 211                                info->rx_state = RECV_WAIT_EVENT_HEADER;
 212                                info->rx_count = HCI_EVENT_HDR_SIZE;
 213                                break;
 214
 215                        case HCI_ACLDATA_PKT:
 216                                info->rx_state = RECV_WAIT_ACL_HEADER;
 217                                info->rx_count = HCI_ACL_HDR_SIZE;
 218                                break;
 219
 220                        case HCI_SCODATA_PKT:
 221                                info->rx_state = RECV_WAIT_SCO_HEADER;
 222                                info->rx_count = HCI_SCO_HDR_SIZE;
 223                                break;
 224
 225                        default:
 226                                /* Unknown packet */
 227                                BT_ERR("Unknown HCI packet with type 0x%02x received", bt_cb(info->rx_skb)->pkt_type);
 228                                info->hdev->stat.err_rx++;
 229                                clear_bit(HCI_RUNNING, &(info->hdev->flags));
 230
 231                                kfree_skb(info->rx_skb);
 232                                info->rx_skb = NULL;
 233                                break;
 234
 235                        }
 236
 237                } else {
 238
 239                        *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
 240                        info->rx_count--;
 241
 242                        if (info->rx_count == 0) {
 243
 244                                int dlen;
 245                                struct hci_event_hdr *eh;
 246                                struct hci_acl_hdr *ah;
 247                                struct hci_sco_hdr *sh;
 248
 249
 250                                switch (info->rx_state) {
 251
 252                                case RECV_WAIT_EVENT_HEADER:
 253                                        eh = hci_event_hdr(info->rx_skb);
 254                                        info->rx_state = RECV_WAIT_DATA;
 255                                        info->rx_count = eh->plen;
 256                                        break;
 257
 258                                case RECV_WAIT_ACL_HEADER:
 259                                        ah = hci_acl_hdr(info->rx_skb);
 260                                        dlen = __le16_to_cpu(ah->dlen);
 261                                        info->rx_state = RECV_WAIT_DATA;
 262                                        info->rx_count = dlen;
 263                                        break;
 264
 265                                case RECV_WAIT_SCO_HEADER:
 266                                        sh = hci_sco_hdr(info->rx_skb);
 267                                        info->rx_state = RECV_WAIT_DATA;
 268                                        info->rx_count = sh->dlen;
 269                                        break;
 270
 271                                case RECV_WAIT_DATA:
 272                                        hci_recv_frame(info->rx_skb);
 273                                        info->rx_skb = NULL;
 274                                        break;
 275
 276                                }
 277
 278                        }
 279
 280                }
 281
 282                /* Make sure we don't stay here too long */
 283                if (boguscount++ > 16)
 284                        break;
 285
 286        } while (inb(iobase + UART_LSR) & UART_LSR_DR);
 287}
 288
 289
 290static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
 291{
 292        btuart_info_t *info = dev_inst;
 293        unsigned int iobase;
 294        int boguscount = 0;
 295        int iir, lsr;
 296        irqreturn_t r = IRQ_NONE;
 297
 298        BUG_ON(!info->hdev);
 299
 300        iobase = info->p_dev->io.BasePort1;
 301
 302        spin_lock(&(info->lock));
 303
 304        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 305        while (iir) {
 306                r = IRQ_HANDLED;
 307
 308                /* Clear interrupt */
 309                lsr = inb(iobase + UART_LSR);
 310
 311                switch (iir) {
 312                case UART_IIR_RLSI:
 313                        BT_ERR("RLSI");
 314                        break;
 315                case UART_IIR_RDI:
 316                        /* Receive interrupt */
 317                        btuart_receive(info);
 318                        break;
 319                case UART_IIR_THRI:
 320                        if (lsr & UART_LSR_THRE) {
 321                                /* Transmitter ready for data */
 322                                btuart_write_wakeup(info);
 323                        }
 324                        break;
 325                default:
 326                        BT_ERR("Unhandled IIR=%#x", iir);
 327                        break;
 328                }
 329
 330                /* Make sure we don't stay here too long */
 331                if (boguscount++ > 100)
 332                        break;
 333
 334                iir = inb(iobase + UART_IIR) & UART_IIR_ID;
 335
 336        }
 337
 338        spin_unlock(&(info->lock));
 339
 340        return r;
 341}
 342
 343
 344static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
 345{
 346        unsigned long flags;
 347        unsigned int iobase;
 348        int fcr;                /* FIFO control reg */
 349        int lcr;                /* Line control reg */
 350        int divisor;
 351
 352        if (!info) {
 353                BT_ERR("Unknown device");
 354                return;
 355        }
 356
 357        iobase = info->p_dev->io.BasePort1;
 358
 359        spin_lock_irqsave(&(info->lock), flags);
 360
 361        /* Turn off interrupts */
 362        outb(0, iobase + UART_IER);
 363
 364        divisor = SPEED_MAX / speed;
 365
 366        fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT;
 367
 368        /* 
 369         * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
 370         * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
 371         * about this timeout since it will always be fast enough. 
 372         */
 373
 374        if (speed < 38400)
 375                fcr |= UART_FCR_TRIGGER_1;
 376        else
 377                fcr |= UART_FCR_TRIGGER_14;
 378
 379        /* Bluetooth cards use 8N1 */
 380        lcr = UART_LCR_WLEN8;
 381
 382        outb(UART_LCR_DLAB | lcr, iobase + UART_LCR);   /* Set DLAB */
 383        outb(divisor & 0xff, iobase + UART_DLL);        /* Set speed */
 384        outb(divisor >> 8, iobase + UART_DLM);
 385        outb(lcr, iobase + UART_LCR);   /* Set 8N1  */
 386        outb(fcr, iobase + UART_FCR);   /* Enable FIFO's */
 387
 388        /* Turn on interrupts */
 389        outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 390
 391        spin_unlock_irqrestore(&(info->lock), flags);
 392}
 393
 394
 395
 396/* ======================== HCI interface ======================== */
 397
 398
 399static int btuart_hci_flush(struct hci_dev *hdev)
 400{
 401        btuart_info_t *info = (btuart_info_t *)(hdev->driver_data);
 402
 403        /* Drop TX queue */
 404        skb_queue_purge(&(info->txq));
 405
 406        return 0;
 407}
 408
 409
 410static int btuart_hci_open(struct hci_dev *hdev)
 411{
 412        set_bit(HCI_RUNNING, &(hdev->flags));
 413
 414        return 0;
 415}
 416
 417
 418static int btuart_hci_close(struct hci_dev *hdev)
 419{
 420        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
 421                return 0;
 422
 423        btuart_hci_flush(hdev);
 424
 425        return 0;
 426}
 427
 428
 429static int btuart_hci_send_frame(struct sk_buff *skb)
 430{
 431        btuart_info_t *info;
 432        struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
 433
 434        if (!hdev) {
 435                BT_ERR("Frame for unknown HCI device (hdev=NULL)");
 436                return -ENODEV;
 437        }
 438
 439        info = (btuart_info_t *)(hdev->driver_data);
 440
 441        switch (bt_cb(skb)->pkt_type) {
 442        case HCI_COMMAND_PKT:
 443                hdev->stat.cmd_tx++;
 444                break;
 445        case HCI_ACLDATA_PKT:
 446                hdev->stat.acl_tx++;
 447                break;
 448        case HCI_SCODATA_PKT:
 449                hdev->stat.sco_tx++;
 450                break;
 451        };
 452
 453        /* Prepend skb with frame type */
 454        memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
 455        skb_queue_tail(&(info->txq), skb);
 456
 457        btuart_write_wakeup(info);
 458
 459        return 0;
 460}
 461
 462
 463static void btuart_hci_destruct(struct hci_dev *hdev)
 464{
 465}
 466
 467
 468static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
 469{
 470        return -ENOIOCTLCMD;
 471}
 472
 473
 474
 475/* ======================== Card services HCI interaction ======================== */
 476
 477
 478static int btuart_open(btuart_info_t *info)
 479{
 480        unsigned long flags;
 481        unsigned int iobase = info->p_dev->io.BasePort1;
 482        struct hci_dev *hdev;
 483
 484        spin_lock_init(&(info->lock));
 485
 486        skb_queue_head_init(&(info->txq));
 487
 488        info->rx_state = RECV_WAIT_PACKET_TYPE;
 489        info->rx_count = 0;
 490        info->rx_skb = NULL;
 491
 492        /* Initialize HCI device */
 493        hdev = hci_alloc_dev();
 494        if (!hdev) {
 495                BT_ERR("Can't allocate HCI device");
 496                return -ENOMEM;
 497        }
 498
 499        info->hdev = hdev;
 500
 501        hdev->type = HCI_PCCARD;
 502        hdev->driver_data = info;
 503        SET_HCIDEV_DEV(hdev, &info->p_dev->dev);
 504
 505        hdev->open     = btuart_hci_open;
 506        hdev->close    = btuart_hci_close;
 507        hdev->flush    = btuart_hci_flush;
 508        hdev->send     = btuart_hci_send_frame;
 509        hdev->destruct = btuart_hci_destruct;
 510        hdev->ioctl    = btuart_hci_ioctl;
 511
 512        hdev->owner = THIS_MODULE;
 513
 514        spin_lock_irqsave(&(info->lock), flags);
 515
 516        /* Reset UART */
 517        outb(0, iobase + UART_MCR);
 518
 519        /* Turn off interrupts */
 520        outb(0, iobase + UART_IER);
 521
 522        /* Initialize UART */
 523        outb(UART_LCR_WLEN8, iobase + UART_LCR);        /* Reset DLAB */
 524        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 525
 526        /* Turn on interrupts */
 527        // outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 528
 529        spin_unlock_irqrestore(&(info->lock), flags);
 530
 531        btuart_change_speed(info, DEFAULT_BAUD_RATE);
 532
 533        /* Timeout before it is safe to send the first HCI packet */
 534        msleep(1000);
 535
 536        /* Register HCI device */
 537        if (hci_register_dev(hdev) < 0) {
 538                BT_ERR("Can't register HCI device");
 539                info->hdev = NULL;
 540                hci_free_dev(hdev);
 541                return -ENODEV;
 542        }
 543
 544        return 0;
 545}
 546
 547
 548static int btuart_close(btuart_info_t *info)
 549{
 550        unsigned long flags;
 551        unsigned int iobase = info->p_dev->io.BasePort1;
 552        struct hci_dev *hdev = info->hdev;
 553
 554        if (!hdev)
 555                return -ENODEV;
 556
 557        btuart_hci_close(hdev);
 558
 559        spin_lock_irqsave(&(info->lock), flags);
 560
 561        /* Reset UART */
 562        outb(0, iobase + UART_MCR);
 563
 564        /* Turn off interrupts */
 565        outb(0, iobase + UART_IER);
 566
 567        spin_unlock_irqrestore(&(info->lock), flags);
 568
 569        if (hci_unregister_dev(hdev) < 0)
 570                BT_ERR("Can't unregister HCI device %s", hdev->name);
 571
 572        hci_free_dev(hdev);
 573
 574        return 0;
 575}
 576
 577static int btuart_probe(struct pcmcia_device *link)
 578{
 579        btuart_info_t *info;
 580
 581        /* Create new info device */
 582        info = kzalloc(sizeof(*info), GFP_KERNEL);
 583        if (!info)
 584                return -ENOMEM;
 585
 586        info->p_dev = link;
 587        link->priv = info;
 588
 589        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 590        link->io.NumPorts1 = 8;
 591        link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
 592        link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 593
 594        link->irq.Handler = btuart_interrupt;
 595        link->irq.Instance = info;
 596
 597        link->conf.Attributes = CONF_ENABLE_IRQ;
 598        link->conf.IntType = INT_MEMORY_AND_IO;
 599
 600        return btuart_config(link);
 601}
 602
 603
 604static void btuart_detach(struct pcmcia_device *link)
 605{
 606        btuart_info_t *info = link->priv;
 607
 608        btuart_release(link);
 609        kfree(info);
 610}
 611
 612static int btuart_check_config(struct pcmcia_device *p_dev,
 613                               cistpl_cftable_entry_t *cf,
 614                               cistpl_cftable_entry_t *dflt,
 615                               unsigned int vcc,
 616                               void *priv_data)
 617{
 618        int *try = priv_data;
 619
 620        if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
 621                p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
 622        if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
 623            (cf->io.win[0].base != 0)) {
 624                p_dev->io.BasePort1 = cf->io.win[0].base;
 625                p_dev->io.IOAddrLines = (*try == 0) ? 16 :
 626                        cf->io.flags & CISTPL_IO_LINES_MASK;
 627                if (!pcmcia_request_io(p_dev, &p_dev->io))
 628                        return 0;
 629        }
 630        return -ENODEV;
 631}
 632
 633static int btuart_check_config_notpicky(struct pcmcia_device *p_dev,
 634                                        cistpl_cftable_entry_t *cf,
 635                                        cistpl_cftable_entry_t *dflt,
 636                                        unsigned int vcc,
 637                                        void *priv_data)
 638{
 639        static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
 640        int j;
 641
 642        if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
 643                for (j = 0; j < 5; j++) {
 644                        p_dev->io.BasePort1 = base[j];
 645                        p_dev->io.IOAddrLines = base[j] ? 16 : 3;
 646                        if (!pcmcia_request_io(p_dev, &p_dev->io))
 647                                return 0;
 648                }
 649        }
 650        return -ENODEV;
 651}
 652
 653static int btuart_config(struct pcmcia_device *link)
 654{
 655        btuart_info_t *info = link->priv;
 656        int i;
 657        int try;
 658
 659        /* First pass: look for a config entry that looks normal.
 660           Two tries: without IO aliases, then with aliases */
 661        for (try = 0; try < 2; try++)
 662                if (!pcmcia_loop_config(link, btuart_check_config, &try))
 663                        goto found_port;
 664
 665        /* Second pass: try to find an entry that isn't picky about
 666           its base address, then try to grab any standard serial port
 667           address, and finally try to get any free port. */
 668        if (!pcmcia_loop_config(link, btuart_check_config_notpicky, NULL))
 669                goto found_port;
 670
 671        BT_ERR("No usable port range found");
 672        cs_error(link, RequestIO, -ENODEV);
 673        goto failed;
 674
 675found_port:
 676        i = pcmcia_request_irq(link, &link->irq);
 677        if (i != 0) {
 678                cs_error(link, RequestIRQ, i);
 679                link->irq.AssignedIRQ = 0;
 680        }
 681
 682        i = pcmcia_request_configuration(link, &link->conf);
 683        if (i != 0) {
 684                cs_error(link, RequestConfiguration, i);
 685                goto failed;
 686        }
 687
 688        if (btuart_open(info) != 0)
 689                goto failed;
 690
 691        strcpy(info->node.dev_name, info->hdev->name);
 692        link->dev_node = &info->node;
 693
 694        return 0;
 695
 696failed:
 697        btuart_release(link);
 698        return -ENODEV;
 699}
 700
 701
 702static void btuart_release(struct pcmcia_device *link)
 703{
 704        btuart_info_t *info = link->priv;
 705
 706        btuart_close(info);
 707
 708        pcmcia_disable_device(link);
 709}
 710
 711static struct pcmcia_device_id btuart_ids[] = {
 712        /* don't use this driver. Use serial_cs + hci_uart instead */
 713        PCMCIA_DEVICE_NULL
 714};
 715MODULE_DEVICE_TABLE(pcmcia, btuart_ids);
 716
 717static struct pcmcia_driver btuart_driver = {
 718        .owner          = THIS_MODULE,
 719        .drv            = {
 720                .name   = "btuart_cs",
 721        },
 722        .probe          = btuart_probe,
 723        .remove         = btuart_detach,
 724        .id_table       = btuart_ids,
 725};
 726
 727static int __init init_btuart_cs(void)
 728{
 729        return pcmcia_register_driver(&btuart_driver);
 730}
 731
 732
 733static void __exit exit_btuart_cs(void)
 734{
 735        pcmcia_unregister_driver(&btuart_driver);
 736}
 737
 738module_init(init_btuart_cs);
 739module_exit(exit_btuart_cs);
 740