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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/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 Nokia Connectivity Card DTL-1");
70
MODULE_LICENSE("GPL");
71
 
72
 
73
 
74
/* ======================== Local structures ======================== */
75
 
76
 
77
typedef struct dtl1_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
        unsigned long flowmask;         /* HCI flow mask */
86
        int ri_latch;
87
 
88
        struct sk_buff_head txq;
89
        unsigned long tx_state;
90
 
91
        unsigned long rx_state;
92
        unsigned long rx_count;
93
        struct sk_buff *rx_skb;
94
} dtl1_info_t;
95
 
96
 
97
void dtl1_config(dev_link_t *link);
98
void dtl1_release(u_long arg);
99
int dtl1_event(event_t event, int priority, event_callback_args_t *args);
100
 
101
static dev_info_t dev_info = "dtl1_cs";
102
 
103
dev_link_t *dtl1_attach(void);
104
void dtl1_detach(dev_link_t *);
105
 
106
static dev_link_t *dev_list = NULL;
107
 
108
 
109
/* Transmit states  */
110
#define XMIT_SENDING  1
111
#define XMIT_WAKEUP   2
112
#define XMIT_WAITING  8
113
 
114
/* Receiver States */
115
#define RECV_WAIT_NSH   0
116
#define RECV_WAIT_DATA  1
117
 
118
 
119
typedef struct {
120
        u8 type;
121
        u8 zero;
122
        u16 len;
123
} __attribute__ ((packed)) nsh_t;       /* Nokia Specific Header */
124
 
125
#define NSHL  4                         /* Nokia Specific Header Length */
126
 
127
 
128
 
129
/* ======================== Interrupt handling ======================== */
130
 
131
 
132
static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
133
{
134
        int actual = 0;
135
 
136
        /* Tx FIFO should be empty */
137
        if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
138
                return 0;
139
 
140
        /* Fill FIFO with current frame */
141
        while ((fifo_size-- > 0) && (actual < len)) {
142
                /* Transmit next byte */
143
                outb(buf[actual], iobase + UART_TX);
144
                actual++;
145
        }
146
 
147
        return actual;
148
}
149
 
150
 
151
static void dtl1_write_wakeup(dtl1_info_t *info)
152
{
153
        if (!info) {
154
                printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
155
                return;
156
        }
157
 
158
        if (test_bit(XMIT_WAITING, &(info->tx_state))) {
159
                set_bit(XMIT_WAKEUP, &(info->tx_state));
160
                return;
161
        }
162
 
163
        if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
164
                set_bit(XMIT_WAKEUP, &(info->tx_state));
165
                return;
166
        }
167
 
168
        do {
169
                register unsigned int iobase = info->link.io.BasePort1;
170
                register struct sk_buff *skb;
171
                register int len;
172
 
173
                clear_bit(XMIT_WAKEUP, &(info->tx_state));
174
 
175
                if (!(info->link.state & DEV_PRESENT))
176
                        return;
177
 
178
                if (!(skb = skb_dequeue(&(info->txq))))
179
                        break;
180
 
181
                /* Send frame */
182
                len = dtl1_write(iobase, 32, skb->data, skb->len);
183
 
184
                if (len == skb->len) {
185
                        set_bit(XMIT_WAITING, &(info->tx_state));
186
                        kfree_skb(skb);
187
                } else {
188
                        skb_pull(skb, len);
189
                        skb_queue_head(&(info->txq), skb);
190
                }
191
 
192
                info->hdev.stat.byte_tx += len;
193
 
194
        } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
195
 
196
        clear_bit(XMIT_SENDING, &(info->tx_state));
197
}
198
 
199
 
200
static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
201
{
202
        u8 flowmask = *(u8 *)skb->data;
203
        int i;
204
 
205
        printk(KERN_INFO "dtl1_cs: Nokia control data = ");
206
        for (i = 0; i < skb->len; i++) {
207
                printk("%02x ", skb->data[i]);
208
        }
209
        printk("\n");
210
 
211
        /* transition to active state */
212
        if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
213
                clear_bit(XMIT_WAITING, &(info->tx_state));
214
                dtl1_write_wakeup(info);
215
        }
216
 
217
        info->flowmask = flowmask;
218
 
219
        kfree_skb(skb);
220
}
221
 
222
 
223
static void dtl1_receive(dtl1_info_t *info)
224
{
225
        unsigned int iobase;
226
        nsh_t *nsh;
227
        int boguscount = 0;
228
 
229
        if (!info) {
230
                printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
231
                return;
232
        }
233
 
234
        iobase = info->link.io.BasePort1;
235
 
236
        do {
237
                info->hdev.stat.byte_rx++;
238
 
239
                /* Allocate packet */
240
                if (info->rx_skb == NULL)
241
                        if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
242
                                printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
243
                                info->rx_state = RECV_WAIT_NSH;
244
                                info->rx_count = NSHL;
245
                                return;
246
                        }
247
 
248
                *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
249
                nsh = (nsh_t *)info->rx_skb->data;
250
 
251
                info->rx_count--;
252
 
253
                if (info->rx_count == 0) {
254
 
255
                        switch (info->rx_state) {
256
                        case RECV_WAIT_NSH:
257
                                info->rx_state = RECV_WAIT_DATA;
258
                                info->rx_count = nsh->len + (nsh->len & 0x0001);
259
                                break;
260
                        case RECV_WAIT_DATA:
261
                                info->rx_skb->pkt_type = nsh->type;
262
 
263
                                /* remove PAD byte if it exists */
264
                                if (nsh->len & 0x0001) {
265
                                        info->rx_skb->tail--;
266
                                        info->rx_skb->len--;
267
                                }
268
 
269
                                /* remove NSH */
270
                                skb_pull(info->rx_skb, NSHL);
271
 
272
                                switch (info->rx_skb->pkt_type) {
273
                                case 0x80:
274
                                        /* control data for the Nokia Card */
275
                                        dtl1_control(info, info->rx_skb);
276
                                        break;
277
                                case 0x82:
278
                                case 0x83:
279
                                case 0x84:
280
                                        /* send frame to the HCI layer */
281
                                        info->rx_skb->dev = (void *)&(info->hdev);
282
                                        info->rx_skb->pkt_type &= 0x0f;
283
                                        hci_recv_frame(info->rx_skb);
284
                                        break;
285
                                default:
286
                                        /* unknown packet */
287
                                        printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
288
                                        kfree_skb(info->rx_skb);
289
                                        break;
290
                                }
291
 
292
                                info->rx_state = RECV_WAIT_NSH;
293
                                info->rx_count = NSHL;
294
                                info->rx_skb = NULL;
295
                                break;
296
                        }
297
 
298
                }
299
 
300
                /* Make sure we don't stay here to long */
301
                if (boguscount++ > 32)
302
                        break;
303
 
304
        } while (inb(iobase + UART_LSR) & UART_LSR_DR);
305
}
306
 
307
 
308
void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
309
{
310
        dtl1_info_t *info = dev_inst;
311
        unsigned int iobase;
312
        unsigned char msr;
313
        int boguscount = 0;
314
        int iir, lsr;
315
 
316
        if (!info) {
317
                printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
318
                return;
319
        }
320
 
321
        iobase = info->link.io.BasePort1;
322
 
323
        spin_lock(&(info->lock));
324
 
325
        iir = inb(iobase + UART_IIR) & UART_IIR_ID;
326
        while (iir) {
327
 
328
                /* Clear interrupt */
329
                lsr = inb(iobase + UART_LSR);
330
 
331
                switch (iir) {
332
                case UART_IIR_RLSI:
333
                        printk(KERN_NOTICE "dtl1_cs: RLSI\n");
334
                        break;
335
                case UART_IIR_RDI:
336
                        /* Receive interrupt */
337
                        dtl1_receive(info);
338
                        break;
339
                case UART_IIR_THRI:
340
                        if (lsr & UART_LSR_THRE) {
341
                                /* Transmitter ready for data */
342
                                dtl1_write_wakeup(info);
343
                        }
344
                        break;
345
                default:
346
                        printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
347
                        break;
348
                }
349
 
350
                /* Make sure we don't stay here to long */
351
                if (boguscount++ > 100)
352
                        break;
353
 
354
                iir = inb(iobase + UART_IIR) & UART_IIR_ID;
355
 
356
        }
357
 
358
        msr = inb(iobase + UART_MSR);
359
 
360
        if (info->ri_latch ^ (msr & UART_MSR_RI)) {
361
                info->ri_latch = msr & UART_MSR_RI;
362
                clear_bit(XMIT_WAITING, &(info->tx_state));
363
                dtl1_write_wakeup(info);
364
        }
365
 
366
        spin_unlock(&(info->lock));
367
}
368
 
369
 
370
 
371
/* ======================== HCI interface ======================== */
372
 
373
 
374
static int dtl1_hci_open(struct hci_dev *hdev)
375
{
376
        set_bit(HCI_RUNNING, &(hdev->flags));
377
 
378
        return 0;
379
}
380
 
381
 
382
static int dtl1_hci_flush(struct hci_dev *hdev)
383
{
384
        dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
385
 
386
        /* Drop TX queue */
387
        skb_queue_purge(&(info->txq));
388
 
389
        return 0;
390
}
391
 
392
 
393
static int dtl1_hci_close(struct hci_dev *hdev)
394
{
395
        if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
396
                return 0;
397
 
398
        dtl1_hci_flush(hdev);
399
 
400
        return 0;
401
}
402
 
403
 
404
static int dtl1_hci_send_frame(struct sk_buff *skb)
405
{
406
        dtl1_info_t *info;
407
        struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
408
        struct sk_buff *s;
409
        nsh_t nsh;
410
 
411
        if (!hdev) {
412
                printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
413
                return -ENODEV;
414
        }
415
 
416
        info = (dtl1_info_t *)(hdev->driver_data);
417
 
418
        switch (skb->pkt_type) {
419
        case HCI_COMMAND_PKT:
420
                hdev->stat.cmd_tx++;
421
                nsh.type = 0x81;
422
                break;
423
        case HCI_ACLDATA_PKT:
424
                hdev->stat.acl_tx++;
425
                nsh.type = 0x82;
426
                break;
427
        case HCI_SCODATA_PKT:
428
                hdev->stat.sco_tx++;
429
                nsh.type = 0x83;
430
                break;
431
        };
432
 
433
        nsh.zero = 0;
434
        nsh.len = skb->len;
435
 
436
        s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
437
        skb_reserve(s, NSHL);
438
        memcpy(skb_put(s, skb->len), skb->data, skb->len);
439
        if (skb->len & 0x0001)
440
                *skb_put(s, 1) = 0;      /* PAD */
441
 
442
        /* Prepend skb with Nokia frame header and queue */
443
        memcpy(skb_push(s, NSHL), &nsh, NSHL);
444
        skb_queue_tail(&(info->txq), s);
445
 
446
        dtl1_write_wakeup(info);
447
 
448
        kfree_skb(skb);
449
 
450
        return 0;
451
}
452
 
453
 
454
static void dtl1_hci_destruct(struct hci_dev *hdev)
455
{
456
}
457
 
458
 
459
static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long arg)
460
{
461
        return -ENOIOCTLCMD;
462
}
463
 
464
 
465
 
466
/* ======================== Card services HCI interaction ======================== */
467
 
468
 
469
int dtl1_open(dtl1_info_t *info)
470
{
471
        unsigned long flags;
472
        unsigned int iobase = info->link.io.BasePort1;
473
        struct hci_dev *hdev;
474
 
475
        spin_lock_init(&(info->lock));
476
 
477
        skb_queue_head_init(&(info->txq));
478
 
479
        info->rx_state = RECV_WAIT_NSH;
480
        info->rx_count = NSHL;
481
        info->rx_skb = NULL;
482
 
483
        set_bit(XMIT_WAITING, &(info->tx_state));
484
 
485
        spin_lock_irqsave(&(info->lock), flags);
486
 
487
        /* Reset UART */
488
        outb(0, iobase + UART_MCR);
489
 
490
        /* Turn off interrupts */
491
        outb(0, iobase + UART_IER);
492
 
493
        /* Initialize UART */
494
        outb(UART_LCR_WLEN8, iobase + UART_LCR);        /* Reset DLAB */
495
        outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
496
 
497
        info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
498
 
499
        /* Turn on interrupts */
500
        outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
501
 
502
        spin_unlock_irqrestore(&(info->lock), flags);
503
 
504
        /* Timeout before it is safe to send the first HCI packet */
505
        set_current_state(TASK_INTERRUPTIBLE);
506
        schedule_timeout(HZ * 2);
507
 
508
 
509
        /* Initialize and register HCI device */
510
 
511
        hdev = &(info->hdev);
512
 
513
        hdev->type = HCI_PCCARD;
514
        hdev->driver_data = info;
515
 
516
        hdev->open = dtl1_hci_open;
517
        hdev->close = dtl1_hci_close;
518
        hdev->flush = dtl1_hci_flush;
519
        hdev->send = dtl1_hci_send_frame;
520
        hdev->destruct = dtl1_hci_destruct;
521
        hdev->ioctl = dtl1_hci_ioctl;
522
 
523
        if (hci_register_dev(hdev) < 0) {
524
                printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
525
                return -ENODEV;
526
        }
527
 
528
        return 0;
529
}
530
 
531
 
532
int dtl1_close(dtl1_info_t *info)
533
{
534
        unsigned long flags;
535
        unsigned int iobase = info->link.io.BasePort1;
536
        struct hci_dev *hdev = &(info->hdev);
537
 
538
        dtl1_hci_close(hdev);
539
 
540
        spin_lock_irqsave(&(info->lock), flags);
541
 
542
        /* Reset UART */
543
        outb(0, iobase + UART_MCR);
544
 
545
        /* Turn off interrupts */
546
        outb(0, iobase + UART_IER);
547
 
548
        spin_unlock_irqrestore(&(info->lock), flags);
549
 
550
        if (hci_unregister_dev(hdev) < 0)
551
                printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
552
 
553
        return 0;
554
}
555
 
556
 
557
 
558
/* ======================== Card services ======================== */
559
 
560
 
561
static void cs_error(client_handle_t handle, int func, int ret)
562
{
563
        error_info_t err = { func, ret };
564
 
565
        CardServices(ReportError, handle, &err);
566
}
567
 
568
 
569
dev_link_t *dtl1_attach(void)
570
{
571
        dtl1_info_t *info;
572
        client_reg_t client_reg;
573
        dev_link_t *link;
574
        int i, ret;
575
 
576
        /* Create new info device */
577
        info = kmalloc(sizeof(*info), GFP_KERNEL);
578
        if (!info)
579
                return NULL;
580
        memset(info, 0, sizeof(*info));
581
 
582
        link = &info->link;
583
        link->priv = info;
584
 
585
        link->release.function = &dtl1_release;
586
        link->release.data = (u_long)link;
587
        link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
588
        link->io.NumPorts1 = 8;
589
        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
590
        link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
591
 
592
        if (irq_list[0] == -1)
593
                link->irq.IRQInfo2 = irq_mask;
594
        else
595
                for (i = 0; i < 4; i++)
596
                        link->irq.IRQInfo2 |= 1 << irq_list[i];
597
 
598
        link->irq.Handler = dtl1_interrupt;
599
        link->irq.Instance = info;
600
 
601
        link->conf.Attributes = CONF_ENABLE_IRQ;
602
        link->conf.Vcc = 50;
603
        link->conf.IntType = INT_MEMORY_AND_IO;
604
 
605
        /* Register with Card Services */
606
        link->next = dev_list;
607
        dev_list = link;
608
        client_reg.dev_info = &dev_info;
609
        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
610
        client_reg.EventMask =
611
                CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
612
                CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
613
                CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
614
        client_reg.event_handler = &dtl1_event;
615
        client_reg.Version = 0x0210;
616
        client_reg.event_callback_args.client_data = link;
617
 
618
        ret = CardServices(RegisterClient, &link->handle, &client_reg);
619
        if (ret != CS_SUCCESS) {
620
                cs_error(link->handle, RegisterClient, ret);
621
                dtl1_detach(link);
622
                return NULL;
623
        }
624
 
625
        return link;
626
}
627
 
628
 
629
void dtl1_detach(dev_link_t *link)
630
{
631
        dtl1_info_t *info = link->priv;
632
        dev_link_t **linkp;
633
        int ret;
634
 
635
        /* Locate device structure */
636
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
637
                if (*linkp == link)
638
                        break;
639
 
640
        if (*linkp == NULL)
641
                return;
642
 
643
        del_timer(&link->release);
644
        if (link->state & DEV_CONFIG)
645
                dtl1_release((u_long)link);
646
 
647
        if (link->handle) {
648
                ret = CardServices(DeregisterClient, link->handle);
649
                if (ret != CS_SUCCESS)
650
                        cs_error(link->handle, DeregisterClient, ret);
651
        }
652
 
653
        /* Unlink device structure, free bits */
654
        *linkp = link->next;
655
 
656
        kfree(info);
657
}
658
 
659
 
660
static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
661
{
662
        int i;
663
 
664
        i = CardServices(fn, handle, tuple);
665
        if (i != CS_SUCCESS)
666
                return CS_NO_MORE_ITEMS;
667
 
668
        i = CardServices(GetTupleData, handle, tuple);
669
        if (i != CS_SUCCESS)
670
                return i;
671
 
672
        return CardServices(ParseTuple, handle, tuple, parse);
673
}
674
 
675
 
676
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
677
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
678
 
679
void dtl1_config(dev_link_t *link)
680
{
681
        client_handle_t handle = link->handle;
682
        dtl1_info_t *info = link->priv;
683
        tuple_t tuple;
684
        u_short buf[256];
685
        cisparse_t parse;
686
        cistpl_cftable_entry_t *cf = &parse.cftable_entry;
687
        config_info_t config;
688
        int i, last_ret, last_fn;
689
 
690
        tuple.TupleData = (cisdata_t *)buf;
691
        tuple.TupleOffset = 0;
692
        tuple.TupleDataMax = 255;
693
        tuple.Attributes = 0;
694
 
695
        /* Get configuration register information */
696
        tuple.DesiredTuple = CISTPL_CONFIG;
697
        last_ret = first_tuple(handle, &tuple, &parse);
698
        if (last_ret != CS_SUCCESS) {
699
                last_fn = ParseTuple;
700
                goto cs_failed;
701
        }
702
        link->conf.ConfigBase = parse.config.base;
703
        link->conf.Present = parse.config.rmask[0];
704
 
705
        /* Configure card */
706
        link->state |= DEV_CONFIG;
707
        i = CardServices(GetConfigurationInfo, handle, &config);
708
        link->conf.Vcc = config.Vcc;
709
 
710
        tuple.TupleData = (cisdata_t *)buf;
711
        tuple.TupleOffset = 0;
712
        tuple.TupleDataMax = 255;
713
        tuple.Attributes = 0;
714
        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
715
 
716
        /* Look for a generic full-sized window */
717
        link->io.NumPorts1 = 8;
718
        i = first_tuple(handle, &tuple, &parse);
719
        while (i != CS_NO_MORE_ITEMS) {
720
                if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
721
                        link->conf.ConfigIndex = cf->index;
722
                        link->io.BasePort1 = cf->io.win[0].base;
723
                        link->io.NumPorts1 = cf->io.win[0].len;  /*yo */
724
                        link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
725
                        i = CardServices(RequestIO, link->handle, &link->io);
726
                        if (i == CS_SUCCESS)
727
                                break;
728
                }
729
                i = next_tuple(handle, &tuple, &parse);
730
        }
731
 
732
        if (i != CS_SUCCESS) {
733
                cs_error(link->handle, RequestIO, i);
734
                goto failed;
735
        }
736
 
737
        i = CardServices(RequestIRQ, link->handle, &link->irq);
738
        if (i != CS_SUCCESS) {
739
                cs_error(link->handle, RequestIRQ, i);
740
                link->irq.AssignedIRQ = 0;
741
        }
742
 
743
        i = CardServices(RequestConfiguration, link->handle, &link->conf);
744
        if (i != CS_SUCCESS) {
745
                cs_error(link->handle, RequestConfiguration, i);
746
                goto failed;
747
        }
748
 
749
        MOD_INC_USE_COUNT;
750
 
751
        if (dtl1_open(info) != 0)
752
                goto failed;
753
 
754
        strcpy(info->node.dev_name, info->hdev.name);
755
        link->dev = &info->node;
756
        link->state &= ~DEV_CONFIG_PENDING;
757
 
758
        return;
759
 
760
cs_failed:
761
        cs_error(link->handle, last_fn, last_ret);
762
 
763
failed:
764
        dtl1_release((u_long)link);
765
}
766
 
767
 
768
void dtl1_release(u_long arg)
769
{
770
        dev_link_t *link = (dev_link_t *)arg;
771
        dtl1_info_t *info = link->priv;
772
 
773
        if (link->state & DEV_PRESENT)
774
                dtl1_close(info);
775
 
776
        MOD_DEC_USE_COUNT;
777
 
778
        link->dev = NULL;
779
 
780
        CardServices(ReleaseConfiguration, link->handle);
781
        CardServices(ReleaseIO, link->handle, &link->io);
782
        CardServices(ReleaseIRQ, link->handle, &link->irq);
783
 
784
        link->state &= ~DEV_CONFIG;
785
}
786
 
787
 
788
int dtl1_event(event_t event, int priority, event_callback_args_t *args)
789
{
790
        dev_link_t *link = args->client_data;
791
        dtl1_info_t *info = link->priv;
792
 
793
        switch (event) {
794
        case CS_EVENT_CARD_REMOVAL:
795
                link->state &= ~DEV_PRESENT;
796
                if (link->state & DEV_CONFIG) {
797
                        dtl1_close(info);
798
                        mod_timer(&link->release, jiffies + HZ / 20);
799
                }
800
                break;
801
        case CS_EVENT_CARD_INSERTION:
802
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
803
                dtl1_config(link);
804
                break;
805
        case CS_EVENT_PM_SUSPEND:
806
                link->state |= DEV_SUSPEND;
807
                /* Fall through... */
808
        case CS_EVENT_RESET_PHYSICAL:
809
                if (link->state & DEV_CONFIG)
810
                        CardServices(ReleaseConfiguration, link->handle);
811
                break;
812
        case CS_EVENT_PM_RESUME:
813
                link->state &= ~DEV_SUSPEND;
814
                /* Fall through... */
815
        case CS_EVENT_CARD_RESET:
816
                if (DEV_OK(link))
817
                        CardServices(RequestConfiguration, link->handle, &link->conf);
818
                break;
819
        }
820
 
821
        return 0;
822
}
823
 
824
 
825
 
826
/* ======================== Module initialization ======================== */
827
 
828
 
829
int __init init_dtl1_cs(void)
830
{
831
        servinfo_t serv;
832
        int err;
833
 
834
        CardServices(GetCardServicesInfo, &serv);
835
        if (serv.Revision != CS_RELEASE_CODE) {
836
                printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
837
                return -1;
838
        }
839
 
840
        err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
841
 
842
        return err;
843
}
844
 
845
 
846
void __exit exit_dtl1_cs(void)
847
{
848
        unregister_pccard_driver(&dev_info);
849
 
850
        while (dev_list != NULL)
851
                dtl1_detach(dev_list);
852
}
853
 
854
 
855
module_init(init_dtl1_cs);
856
module_exit(exit_dtl1_cs);
857
 
858
EXPORT_NO_SYMBOLS;

powered by: WebSVN 2.1.0

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