OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [bluetooth/] [btuart_cs.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/config.h>
24
#include <linux/module.h>
25
 
26
#include <linux/kernel.h>
27
#include <linux/init.h>
28
#include <linux/slab.h>
29
#include <linux/types.h>
30
#include <linux/sched.h>
31
#include <linux/timer.h>
32
#include <linux/errno.h>
33
#include <linux/ptrace.h>
34
#include <linux/ioport.h>
35
#include <linux/spinlock.h>
36
 
37
#include <linux/skbuff.h>
38
#include <linux/string.h>
39
#include <linux/serial.h>
40
#include <linux/serial_reg.h>
41
#include <asm/system.h>
42
#include <asm/bitops.h>
43
#include <asm/io.h>
44
 
45
#include <pcmcia/version.h>
46
#include <pcmcia/cs_types.h>
47
#include <pcmcia/cs.h>
48
#include <pcmcia/cistpl.h>
49
#include <pcmcia/ciscode.h>
50
#include <pcmcia/ds.h>
51
#include <pcmcia/cisreg.h>
52
 
53
#include <net/bluetooth/bluetooth.h>
54
#include <net/bluetooth/hci_core.h>
55
 
56
 
57
 
58
/* ======================== Module parameters ======================== */
59
 
60
 
61
/* Bit map of interrupts to choose from */
62
static u_int irq_mask = 0xffff;
63
static int irq_list[4] = { -1 };
64
 
65
MODULE_PARM(irq_mask, "i");
66
MODULE_PARM(irq_list, "1-4i");
67
 
68
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
69
MODULE_DESCRIPTION("BlueZ driver for Bluetooth PCMCIA cards with HCI UART interface");
70
MODULE_LICENSE("GPL");
71
 
72
 
73
 
74
/* ======================== Local structures ======================== */
75
 
76
 
77
typedef struct btuart_info_t {
78
        dev_link_t link;
79
        dev_node_t node;
80
 
81
        struct hci_dev hdev;
82
 
83
        spinlock_t lock;        /* For serializing operations */
84
 
85
        struct sk_buff_head txq;
86
        unsigned long tx_state;
87
 
88
        unsigned long rx_state;
89
        unsigned long rx_count;
90
        struct sk_buff *rx_skb;
91
} btuart_info_t;
92
 
93
 
94
void btuart_config(dev_link_t *link);
95
void btuart_release(u_long arg);
96
int btuart_event(event_t event, int priority, event_callback_args_t *args);
97
 
98
static dev_info_t dev_info = "btuart_cs";
99
 
100
dev_link_t *btuart_attach(void);
101
void btuart_detach(dev_link_t *);
102
 
103
static dev_link_t *dev_list = NULL;
104
 
105
 
106
/* Maximum baud rate */
107
#define SPEED_MAX  115200
108
 
109
/* Default baud rate: 57600, 115200, 230400 or 460800 */
110
#define DEFAULT_BAUD_RATE  115200
111
 
112
 
113
/* Transmit states  */
114
#define XMIT_SENDING    1
115
#define XMIT_WAKEUP     2
116
#define XMIT_WAITING    8
117
 
118
/* Receiver states */
119
#define RECV_WAIT_PACKET_TYPE   0
120
#define RECV_WAIT_EVENT_HEADER  1
121
#define RECV_WAIT_ACL_HEADER    2
122
#define RECV_WAIT_SCO_HEADER    3
123
#define RECV_WAIT_DATA          4
124
 
125
 
126
 
127
/* ======================== Interrupt handling ======================== */
128
 
129
 
130
static int btuart_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
131
{
132
        int actual = 0;
133
 
134
        /* Tx FIFO should be empty */
135
        if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
136
                return 0;
137
 
138
        /* Fill FIFO with current frame */
139
        while ((fifo_size-- > 0) && (actual < len)) {
140
                /* Transmit next byte */
141
                outb(buf[actual], iobase + UART_TX);
142
                actual++;
143
        }
144
 
145
        return actual;
146
}
147
 
148
 
149
static void btuart_write_wakeup(btuart_info_t *info)
150
{
151
        if (!info) {
152
                printk(KERN_WARNING "btuart_cs: Call of write_wakeup for unknown device.\n");
153
                return;
154
        }
155
 
156
        if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
157
                set_bit(XMIT_WAKEUP, &(info->tx_state));
158
                return;
159
        }
160
 
161
        do {
162
                register unsigned int iobase = info->link.io.BasePort1;
163
                register struct sk_buff *skb;
164
                register int len;
165
 
166
                clear_bit(XMIT_WAKEUP, &(info->tx_state));
167
 
168
                if (!(info->link.state & DEV_PRESENT))
169
                        return;
170
 
171
                if (!(skb = skb_dequeue(&(info->txq))))
172
                        break;
173
 
174
                /* Send frame */
175
                len = btuart_write(iobase, 16, skb->data, skb->len);
176
                set_bit(XMIT_WAKEUP, &(info->tx_state));
177
 
178
                if (len == skb->len) {
179
                        kfree_skb(skb);
180
                } else {
181
                        skb_pull(skb, len);
182
                        skb_queue_head(&(info->txq), skb);
183
                }
184
 
185
                info->hdev.stat.byte_tx += len;
186
 
187
        } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
188
 
189
        clear_bit(XMIT_SENDING, &(info->tx_state));
190
}
191
 
192
 
193
static void btuart_receive(btuart_info_t *info)
194
{
195
        unsigned int iobase;
196
        int boguscount = 0;
197
 
198
        if (!info) {
199
                printk(KERN_WARNING "btuart_cs: Call of receive for unknown device.\n");
200
                return;
201
        }
202
 
203
        iobase = info->link.io.BasePort1;
204
 
205
        do {
206
                info->hdev.stat.byte_rx++;
207
 
208
                /* Allocate packet */
209
                if (info->rx_skb == NULL) {
210
                        info->rx_state = RECV_WAIT_PACKET_TYPE;
211
                        info->rx_count = 0;
212
                        if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
213
                                printk(KERN_WARNING "btuart_cs: Can't allocate mem for new packet.\n");
214
                                return;
215
                        }
216
                }
217
 
218
                if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
219
 
220
                        info->rx_skb->dev = (void *)&(info->hdev);
221
                        info->rx_skb->pkt_type = inb(iobase + UART_RX);
222
 
223
                        switch (info->rx_skb->pkt_type) {
224
 
225
                        case HCI_EVENT_PKT:
226
                                info->rx_state = RECV_WAIT_EVENT_HEADER;
227
                                info->rx_count = HCI_EVENT_HDR_SIZE;
228
                                break;
229
 
230
                        case HCI_ACLDATA_PKT:
231
                                info->rx_state = RECV_WAIT_ACL_HEADER;
232
                                info->rx_count = HCI_ACL_HDR_SIZE;
233
                                break;
234
 
235
                        case HCI_SCODATA_PKT:
236
                                info->rx_state = RECV_WAIT_SCO_HEADER;
237
                                info->rx_count = HCI_SCO_HDR_SIZE;
238
                                break;
239
 
240
                        default:
241
                                /* Unknown packet */
242
                                printk(KERN_WARNING "btuart_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
243
                                info->hdev.stat.err_rx++;
244
                                clear_bit(HCI_RUNNING, &(info->hdev.flags));
245
 
246
                                kfree_skb(info->rx_skb);
247
                                info->rx_skb = NULL;
248
                                break;
249
 
250
                        }
251
 
252
                } else {
253
 
254
                        *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
255
                        info->rx_count--;
256
 
257
                        if (info->rx_count == 0) {
258
 
259
                                int dlen;
260
                                hci_event_hdr *eh;
261
                                hci_acl_hdr *ah;
262
                                hci_sco_hdr *sh;
263
 
264
 
265
                                switch (info->rx_state) {
266
 
267
                                case RECV_WAIT_EVENT_HEADER:
268
                                        eh = (hci_event_hdr *)(info->rx_skb->data);
269
                                        info->rx_state = RECV_WAIT_DATA;
270
                                        info->rx_count = eh->plen;
271
                                        break;
272
 
273
                                case RECV_WAIT_ACL_HEADER:
274
                                        ah = (hci_acl_hdr *)(info->rx_skb->data);
275
                                        dlen = __le16_to_cpu(ah->dlen);
276
                                        info->rx_state = RECV_WAIT_DATA;
277
                                        info->rx_count = dlen;
278
                                        break;
279
 
280
                                case RECV_WAIT_SCO_HEADER:
281
                                        sh = (hci_sco_hdr *)(info->rx_skb->data);
282
                                        info->rx_state = RECV_WAIT_DATA;
283
                                        info->rx_count = sh->dlen;
284
                                        break;
285
 
286
                                case RECV_WAIT_DATA:
287
                                        hci_recv_frame(info->rx_skb);
288
                                        info->rx_skb = NULL;
289
                                        break;
290
 
291
                                }
292
 
293
                        }
294
 
295
                }
296
 
297
                /* Make sure we don't stay here to long */
298
                if (boguscount++ > 16)
299
                        break;
300
 
301
        } while (inb(iobase + UART_LSR) & UART_LSR_DR);
302
}
303
 
304
 
305
void btuart_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
306
{
307
        btuart_info_t *info = dev_inst;
308
        unsigned int iobase;
309
        int boguscount = 0;
310
        int iir, lsr;
311
 
312
        if (!info) {
313
                printk(KERN_WARNING "btuart_cs: Call of irq %d for unknown device.\n", irq);
314
                return;
315
        }
316
 
317
        iobase = info->link.io.BasePort1;
318
 
319
        spin_lock(&(info->lock));
320
 
321
        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
322
        while (iir) {
323
 
324
                /* Clear interrupt */
325
                lsr = inb(iobase + UART_LSR);
326
 
327
                switch (iir) {
328
                case UART_IIR_RLSI:
329
                        printk(KERN_NOTICE "btuart_cs: RLSI\n");
330
                        break;
331
                case UART_IIR_RDI:
332
                        /* Receive interrupt */
333
                        btuart_receive(info);
334
                        break;
335
                case UART_IIR_THRI:
336
                        if (lsr & UART_LSR_THRE) {
337
                                /* Transmitter ready for data */
338
                                btuart_write_wakeup(info);
339
                        }
340
                        break;
341
                default:
342
                        printk(KERN_NOTICE "btuart_cs: Unhandled IIR=%#x\n", iir);
343
                        break;
344
                }
345
 
346
                /* Make sure we don't stay here to long */
347
                if (boguscount++ > 100)
348
                        break;
349
 
350
                iir = inb(iobase + UART_IIR) & UART_IIR_ID;
351
 
352
        }
353
 
354
        spin_unlock(&(info->lock));
355
}
356
 
357
 
358
static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
359
{
360
        unsigned long flags;
361
        unsigned int iobase;
362
        int fcr;                /* FIFO control reg */
363
        int lcr;                /* Line control reg */
364
        int divisor;
365
 
366
        if (!info) {
367
                printk(KERN_WARNING "btuart_cs: Call of change speed for unknown device.\n");
368
                return;
369
        }
370
 
371
        iobase = info->link.io.BasePort1;
372
 
373
        spin_lock_irqsave(&(info->lock), flags);
374
 
375
        /* Turn off interrupts */
376
        outb(0, iobase + UART_IER);
377
 
378
        divisor = SPEED_MAX / speed;
379
 
380
        fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT;
381
 
382
        /*
383
         * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
384
         * almost 1,7 ms at 19200 bps. At speeds above that we can just forget
385
         * about this timeout since it will always be fast enough.
386
         */
387
 
388
        if (speed < 38400)
389
                fcr |= UART_FCR_TRIGGER_1;
390
        else
391
                fcr |= UART_FCR_TRIGGER_14;
392
 
393
        /* Bluetooth cards use 8N1 */
394
        lcr = UART_LCR_WLEN8;
395
 
396
        outb(UART_LCR_DLAB | lcr, iobase + UART_LCR);   /* Set DLAB */
397
        outb(divisor & 0xff, iobase + UART_DLL);        /* Set speed */
398
        outb(divisor >> 8, iobase + UART_DLM);
399
        outb(lcr, iobase + UART_LCR);   /* Set 8N1  */
400
        outb(fcr, iobase + UART_FCR);   /* Enable FIFO's */
401
 
402
        /* Turn on interrups */
403
        outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
404
 
405
        spin_unlock_irqrestore(&(info->lock), flags);
406
}
407
 
408
 
409
 
410
/* ======================== HCI interface ======================== */
411
 
412
 
413
static int btuart_hci_flush(struct hci_dev *hdev)
414
{
415
        btuart_info_t *info = (btuart_info_t *)(hdev->driver_data);
416
 
417
        /* Drop TX queue */
418
        skb_queue_purge(&(info->txq));
419
 
420
        return 0;
421
}
422
 
423
 
424
static int btuart_hci_open(struct hci_dev *hdev)
425
{
426
        set_bit(HCI_RUNNING, &(hdev->flags));
427
 
428
        return 0;
429
}
430
 
431
 
432
static int btuart_hci_close(struct hci_dev *hdev)
433
{
434
        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
435
                return 0;
436
 
437
        btuart_hci_flush(hdev);
438
 
439
        return 0;
440
}
441
 
442
 
443
static int btuart_hci_send_frame(struct sk_buff *skb)
444
{
445
        btuart_info_t *info;
446
        struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
447
 
448
        if (!hdev) {
449
                printk(KERN_WARNING "btuart_cs: Frame for unknown HCI device (hdev=NULL).");
450
                return -ENODEV;
451
        }
452
 
453
        info = (btuart_info_t *)(hdev->driver_data);
454
 
455
        switch (skb->pkt_type) {
456
        case HCI_COMMAND_PKT:
457
                hdev->stat.cmd_tx++;
458
                break;
459
        case HCI_ACLDATA_PKT:
460
                hdev->stat.acl_tx++;
461
                break;
462
        case HCI_SCODATA_PKT:
463
                hdev->stat.sco_tx++;
464
                break;
465
        };
466
 
467
        /* Prepend skb with frame type */
468
        memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
469
        skb_queue_tail(&(info->txq), skb);
470
 
471
        btuart_write_wakeup(info);
472
 
473
        return 0;
474
}
475
 
476
 
477
static void btuart_hci_destruct(struct hci_dev *hdev)
478
{
479
}
480
 
481
 
482
static int btuart_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
483
{
484
        return -ENOIOCTLCMD;
485
}
486
 
487
 
488
 
489
/* ======================== Card services HCI interaction ======================== */
490
 
491
 
492
int btuart_open(btuart_info_t *info)
493
{
494
        unsigned long flags;
495
        unsigned int iobase = info->link.io.BasePort1;
496
        struct hci_dev *hdev;
497
 
498
        spin_lock_init(&(info->lock));
499
 
500
        skb_queue_head_init(&(info->txq));
501
 
502
        info->rx_state = RECV_WAIT_PACKET_TYPE;
503
        info->rx_count = 0;
504
        info->rx_skb = NULL;
505
 
506
        spin_lock_irqsave(&(info->lock), flags);
507
 
508
        /* Reset UART */
509
        outb(0, iobase + UART_MCR);
510
 
511
        /* Turn off interrupts */
512
        outb(0, iobase + UART_IER);
513
 
514
        /* Initialize UART */
515
        outb(UART_LCR_WLEN8, iobase + UART_LCR);        /* Reset DLAB */
516
        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
517
 
518
        /* Turn on interrupts */
519
        // outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
520
 
521
        spin_unlock_irqrestore(&(info->lock), flags);
522
 
523
        btuart_change_speed(info, DEFAULT_BAUD_RATE);
524
 
525
        /* Timeout before it is safe to send the first HCI packet */
526
        set_current_state(TASK_INTERRUPTIBLE);
527
        schedule_timeout(HZ);
528
 
529
 
530
        /* Initialize and register HCI device */
531
 
532
        hdev = &(info->hdev);
533
 
534
        hdev->type = HCI_PCCARD;
535
        hdev->driver_data = info;
536
 
537
        hdev->open = btuart_hci_open;
538
        hdev->close = btuart_hci_close;
539
        hdev->flush = btuart_hci_flush;
540
        hdev->send = btuart_hci_send_frame;
541
        hdev->destruct = btuart_hci_destruct;
542
        hdev->ioctl = btuart_hci_ioctl;
543
 
544
        if (hci_register_dev(hdev) < 0) {
545
                printk(KERN_WARNING "btuart_cs: Can't register HCI device %s.\n", hdev->name);
546
                return -ENODEV;
547
        }
548
 
549
        return 0;
550
}
551
 
552
 
553
int btuart_close(btuart_info_t *info)
554
{
555
        unsigned long flags;
556
        unsigned int iobase = info->link.io.BasePort1;
557
        struct hci_dev *hdev = &(info->hdev);
558
 
559
        btuart_hci_close(hdev);
560
 
561
        spin_lock_irqsave(&(info->lock), flags);
562
 
563
        /* Reset UART */
564
        outb(0, iobase + UART_MCR);
565
 
566
        /* Turn off interrupts */
567
        outb(0, iobase + UART_IER);
568
 
569
        spin_unlock_irqrestore(&(info->lock), flags);
570
 
571
        if (hci_unregister_dev(hdev) < 0)
572
                printk(KERN_WARNING "btuart_cs: Can't unregister HCI device %s.\n", hdev->name);
573
 
574
        return 0;
575
}
576
 
577
 
578
 
579
/* ======================== Card services ======================== */
580
 
581
 
582
static void cs_error(client_handle_t handle, int func, int ret)
583
{
584
        error_info_t err = { func, ret };
585
 
586
        CardServices(ReportError, handle, &err);
587
}
588
 
589
 
590
dev_link_t *btuart_attach(void)
591
{
592
        btuart_info_t *info;
593
        client_reg_t client_reg;
594
        dev_link_t *link;
595
        int i, ret;
596
 
597
        /* Create new info device */
598
        info = kmalloc(sizeof(*info), GFP_KERNEL);
599
        if (!info)
600
                return NULL;
601
        memset(info, 0, sizeof(*info));
602
 
603
        link = &info->link;
604
        link->priv = info;
605
 
606
        link->release.function = &btuart_release;
607
        link->release.data = (u_long)link;
608
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
609
        link->io.NumPorts1 = 8;
610
        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
611
        link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
612
 
613
        if (irq_list[0] == -1)
614
                link->irq.IRQInfo2 = irq_mask;
615
        else
616
                for (i = 0; i < 4; i++)
617
                        link->irq.IRQInfo2 |= 1 << irq_list[i];
618
 
619
        link->irq.Handler = btuart_interrupt;
620
        link->irq.Instance = info;
621
 
622
        link->conf.Attributes = CONF_ENABLE_IRQ;
623
        link->conf.Vcc = 50;
624
        link->conf.IntType = INT_MEMORY_AND_IO;
625
 
626
        /* Register with Card Services */
627
        link->next = dev_list;
628
        dev_list = link;
629
        client_reg.dev_info = &dev_info;
630
        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
631
        client_reg.EventMask =
632
                CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
633
                CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
634
                CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
635
        client_reg.event_handler = &btuart_event;
636
        client_reg.Version = 0x0210;
637
        client_reg.event_callback_args.client_data = link;
638
 
639
        ret = CardServices(RegisterClient, &link->handle, &client_reg);
640
        if (ret != CS_SUCCESS) {
641
                cs_error(link->handle, RegisterClient, ret);
642
                btuart_detach(link);
643
                return NULL;
644
        }
645
 
646
        return link;
647
}
648
 
649
 
650
void btuart_detach(dev_link_t *link)
651
{
652
        btuart_info_t *info = link->priv;
653
        dev_link_t **linkp;
654
        int ret;
655
 
656
        /* Locate device structure */
657
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
658
                if (*linkp == link)
659
                        break;
660
 
661
        if (*linkp == NULL)
662
                return;
663
 
664
        del_timer(&link->release);
665
        if (link->state & DEV_CONFIG)
666
                btuart_release((u_long)link);
667
 
668
        if (link->handle) {
669
                ret = CardServices(DeregisterClient, link->handle);
670
                if (ret != CS_SUCCESS)
671
                        cs_error(link->handle, DeregisterClient, ret);
672
        }
673
 
674
        /* Unlink device structure, free bits */
675
        *linkp = link->next;
676
 
677
        kfree(info);
678
}
679
 
680
 
681
static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
682
{
683
        int i;
684
 
685
        i = CardServices(fn, handle, tuple);
686
        if (i != CS_SUCCESS)
687
                return CS_NO_MORE_ITEMS;
688
 
689
        i = CardServices(GetTupleData, handle, tuple);
690
        if (i != CS_SUCCESS)
691
                return i;
692
 
693
        return CardServices(ParseTuple, handle, tuple, parse);
694
}
695
 
696
 
697
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
698
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
699
 
700
void btuart_config(dev_link_t *link)
701
{
702
        static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
703
        client_handle_t handle = link->handle;
704
        btuart_info_t *info = link->priv;
705
        tuple_t tuple;
706
        u_short buf[256];
707
        cisparse_t parse;
708
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
709
        config_info_t config;
710
        int i, j, try, last_ret, last_fn;
711
 
712
        tuple.TupleData = (cisdata_t *)buf;
713
        tuple.TupleOffset = 0;
714
        tuple.TupleDataMax = 255;
715
        tuple.Attributes = 0;
716
 
717
        /* Get configuration register information */
718
        tuple.DesiredTuple = CISTPL_CONFIG;
719
        last_ret = first_tuple(handle, &tuple, &parse);
720
        if (last_ret != CS_SUCCESS) {
721
                last_fn = ParseTuple;
722
                goto cs_failed;
723
        }
724
        link->conf.ConfigBase = parse.config.base;
725
        link->conf.Present = parse.config.rmask[0];
726
 
727
        /* Configure card */
728
        link->state |= DEV_CONFIG;
729
        i = CardServices(GetConfigurationInfo, handle, &config);
730
        link->conf.Vcc = config.Vcc;
731
 
732
        /* First pass: look for a config entry that looks normal. */
733
        tuple.TupleData = (cisdata_t *) buf;
734
        tuple.TupleOffset = 0;
735
        tuple.TupleDataMax = 255;
736
        tuple.Attributes = 0;
737
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
738
        /* Two tries: without IO aliases, then with aliases */
739
        for (try = 0; try < 2; try++) {
740
                i = first_tuple(handle, &tuple, &parse);
741
                while (i != CS_NO_MORE_ITEMS) {
742
                        if (i != CS_SUCCESS)
743
                                goto next_entry;
744
                        if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
745
                                link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
746
                        if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
747
                                link->conf.ConfigIndex = cf->index;
748
                                link->io.BasePort1 = cf->io.win[0].base;
749
                                link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
750
                                i = CardServices(RequestIO, link->handle, &link->io);
751
                                if (i == CS_SUCCESS)
752
                                        goto found_port;
753
                        }
754
next_entry:
755
                        i = next_tuple(handle, &tuple, &parse);
756
                }
757
        }
758
 
759
        /* Second pass: try to find an entry that isn't picky about
760
           its base address, then try to grab any standard serial port
761
           address, and finally try to get any free port. */
762
        i = first_tuple(handle, &tuple, &parse);
763
        while (i != CS_NO_MORE_ITEMS) {
764
                if ((i == CS_SUCCESS) && (cf->io.nwin > 0)
765
                    && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
766
                        link->conf.ConfigIndex = cf->index;
767
                        for (j = 0; j < 5; j++) {
768
                                link->io.BasePort1 = base[j];
769
                                link->io.IOAddrLines = base[j] ? 16 : 3;
770
                                i = CardServices(RequestIO, link->handle, &link->io);
771
                                if (i == CS_SUCCESS)
772
                                        goto found_port;
773
                        }
774
                }
775
                i = next_tuple(handle, &tuple, &parse);
776
        }
777
 
778
found_port:
779
        if (i != CS_SUCCESS) {
780
                printk(KERN_NOTICE "btuart_cs: No usable port range found. Giving up.\n");
781
                cs_error(link->handle, RequestIO, i);
782
                goto failed;
783
        }
784
 
785
        i = CardServices(RequestIRQ, link->handle, &link->irq);
786
        if (i != CS_SUCCESS) {
787
                cs_error(link->handle, RequestIRQ, i);
788
                link->irq.AssignedIRQ = 0;
789
        }
790
 
791
        i = CardServices(RequestConfiguration, link->handle, &link->conf);
792
        if (i != CS_SUCCESS) {
793
                cs_error(link->handle, RequestConfiguration, i);
794
                goto failed;
795
        }
796
 
797
        MOD_INC_USE_COUNT;
798
 
799
        if (btuart_open(info) != 0)
800
                goto failed;
801
 
802
        strcpy(info->node.dev_name, info->hdev.name);
803
        link->dev = &info->node;
804
        link->state &= ~DEV_CONFIG_PENDING;
805
 
806
        return;
807
 
808
cs_failed:
809
        cs_error(link->handle, last_fn, last_ret);
810
 
811
failed:
812
        btuart_release((u_long) link);
813
}
814
 
815
 
816
void btuart_release(u_long arg)
817
{
818
        dev_link_t *link = (dev_link_t *)arg;
819
        btuart_info_t *info = link->priv;
820
 
821
        if (link->state & DEV_PRESENT)
822
                btuart_close(info);
823
 
824
        MOD_DEC_USE_COUNT;
825
 
826
        link->dev = NULL;
827
 
828
        CardServices(ReleaseConfiguration, link->handle);
829
        CardServices(ReleaseIO, link->handle, &link->io);
830
        CardServices(ReleaseIRQ, link->handle, &link->irq);
831
 
832
        link->state &= ~DEV_CONFIG;
833
}
834
 
835
 
836
int btuart_event(event_t event, int priority, event_callback_args_t *args)
837
{
838
        dev_link_t *link = args->client_data;
839
        btuart_info_t *info = link->priv;
840
 
841
        switch (event) {
842
        case CS_EVENT_CARD_REMOVAL:
843
                link->state &= ~DEV_PRESENT;
844
                if (link->state & DEV_CONFIG) {
845
                        btuart_close(info);
846
                        mod_timer(&link->release, jiffies + HZ / 20);
847
                }
848
                break;
849
        case CS_EVENT_CARD_INSERTION:
850
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
851
                btuart_config(link);
852
                break;
853
        case CS_EVENT_PM_SUSPEND:
854
                link->state |= DEV_SUSPEND;
855
                /* Fall through... */
856
        case CS_EVENT_RESET_PHYSICAL:
857
                if (link->state & DEV_CONFIG)
858
                        CardServices(ReleaseConfiguration, link->handle);
859
                break;
860
        case CS_EVENT_PM_RESUME:
861
                link->state &= ~DEV_SUSPEND;
862
                /* Fall through... */
863
        case CS_EVENT_CARD_RESET:
864
                if (DEV_OK(link))
865
                        CardServices(RequestConfiguration, link->handle, &link->conf);
866
                break;
867
        }
868
 
869
        return 0;
870
}
871
 
872
 
873
 
874
/* ======================== Module initialization ======================== */
875
 
876
 
877
int __init init_btuart_cs(void)
878
{
879
        servinfo_t serv;
880
        int err;
881
 
882
        CardServices(GetCardServicesInfo, &serv);
883
        if (serv.Revision != CS_RELEASE_CODE) {
884
                printk(KERN_NOTICE "btuart_cs: Card Services release does not match!\n");
885
                return -1;
886
        }
887
 
888
        err = register_pccard_driver(&dev_info, &btuart_attach, &btuart_detach);
889
 
890
        return err;
891
}
892
 
893
 
894
void __exit exit_btuart_cs(void)
895
{
896
        unregister_pccard_driver(&dev_info);
897
 
898
        while (dev_list != NULL)
899
                btuart_detach(dev_list);
900
}
901
 
902
 
903
module_init(init_btuart_cs);
904
module_exit(exit_btuart_cs);
905
 
906
EXPORT_NO_SYMBOLS;

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.