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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [wan/] [pci200syn.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Goramo PCI200SYN synchronous serial card driver for Linux
3
 *
4
 * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl>
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of version 2 of the GNU General Public License
8
 * as published by the Free Software Foundation.
9
 *
10
 * For information see <http://www.kernel.org/pub/linux/utils/net/hdlc/>
11
 *
12
 * Sources of information:
13
 *    Hitachi HD64572 SCA-II User's Manual
14
 *    PLX Technology Inc. PCI9052 Data Book
15
 */
16
 
17
#include <linux/module.h>
18
#include <linux/kernel.h>
19
#include <linux/slab.h>
20
#include <linux/types.h>
21
#include <linux/fcntl.h>
22
#include <linux/in.h>
23
#include <linux/string.h>
24
#include <linux/errno.h>
25
#include <linux/init.h>
26
#include <linux/ioport.h>
27
#include <linux/moduleparam.h>
28
#include <linux/netdevice.h>
29
#include <linux/hdlc.h>
30
#include <linux/pci.h>
31
#include <linux/delay.h>
32
#include <asm/io.h>
33
 
34
#include "hd64572.h"
35
 
36
static const char* version = "Goramo PCI200SYN driver version: 1.16";
37
static const char* devname = "PCI200SYN";
38
 
39
#undef DEBUG_PKT
40
#define DEBUG_RINGS
41
 
42
#define PCI200SYN_PLX_SIZE      0x80    /* PLX control window size (128b) */
43
#define PCI200SYN_SCA_SIZE      0x400   /* SCA window size (1Kb) */
44
#define ALL_PAGES_ALWAYS_MAPPED
45
#define NEED_DETECT_RAM
46
#define NEED_SCA_MSCI_INTR
47
#define MAX_TX_BUFFERS          10
48
 
49
static int pci_clock_freq = 33000000;
50
#define CLOCK_BASE pci_clock_freq
51
 
52
/*
53
 *      PLX PCI9052 local configuration and shared runtime registers.
54
 *      This structure can be used to access 9052 registers (memory mapped).
55
 */
56
typedef struct {
57
        u32 loc_addr_range[4];  /* 00-0Ch : Local Address Ranges */
58
        u32 loc_rom_range;      /* 10h : Local ROM Range */
59
        u32 loc_addr_base[4];   /* 14-20h : Local Address Base Addrs */
60
        u32 loc_rom_base;       /* 24h : Local ROM Base */
61
        u32 loc_bus_descr[4];   /* 28-34h : Local Bus Descriptors */
62
        u32 rom_bus_descr;      /* 38h : ROM Bus Descriptor */
63
        u32 cs_base[4];         /* 3C-48h : Chip Select Base Addrs */
64
        u32 intr_ctrl_stat;     /* 4Ch : Interrupt Control/Status */
65
        u32 init_ctrl;          /* 50h : EEPROM ctrl, Init Ctrl, etc */
66
}plx9052;
67
 
68
 
69
 
70
typedef struct port_s {
71
        struct net_device *dev;
72
        struct card_s *card;
73
        spinlock_t lock;        /* TX lock */
74
        sync_serial_settings settings;
75
        int rxpart;             /* partial frame received, next frame invalid*/
76
        unsigned short encoding;
77
        unsigned short parity;
78
        u16 rxin;               /* rx ring buffer 'in' pointer */
79
        u16 txin;               /* tx ring buffer 'in' and 'last' pointers */
80
        u16 txlast;
81
        u8 rxs, txs, tmc;       /* SCA registers */
82
        u8 phy_node;            /* physical port # - 0 or 1 */
83
}port_t;
84
 
85
 
86
 
87
typedef struct card_s {
88
        u8 __iomem *rambase;    /* buffer memory base (virtual) */
89
        u8 __iomem *scabase;    /* SCA memory base (virtual) */
90
        plx9052 __iomem *plxbase;/* PLX registers memory base (virtual) */
91
        u16 rx_ring_buffers;    /* number of buffers in a ring */
92
        u16 tx_ring_buffers;
93
        u16 buff_offset;        /* offset of first buffer of first channel */
94
        u8 irq;                 /* interrupt request level */
95
 
96
        port_t ports[2];
97
}card_t;
98
 
99
 
100
#define sca_in(reg, card)            readb(card->scabase + (reg))
101
#define sca_out(value, reg, card)    writeb(value, card->scabase + (reg))
102
#define sca_inw(reg, card)           readw(card->scabase + (reg))
103
#define sca_outw(value, reg, card)   writew(value, card->scabase + (reg))
104
#define sca_inl(reg, card)           readl(card->scabase + (reg))
105
#define sca_outl(value, reg, card)   writel(value, card->scabase + (reg))
106
 
107
#define port_to_card(port)           (port->card)
108
#define log_node(port)               (port->phy_node)
109
#define phy_node(port)               (port->phy_node)
110
#define winbase(card)                (card->rambase)
111
#define get_port(card, port)         (&card->ports[port])
112
#define sca_flush(card)              (sca_in(IER0, card));
113
 
114
static inline void new_memcpy_toio(char __iomem *dest, char *src, int length)
115
{
116
        int len;
117
        do {
118
                len = length > 256 ? 256 : length;
119
                memcpy_toio(dest, src, len);
120
                dest += len;
121
                src += len;
122
                length -= len;
123
                readb(dest);
124
        } while (len);
125
}
126
 
127
#undef memcpy_toio
128
#define memcpy_toio new_memcpy_toio
129
 
130
#include "hd6457x.c"
131
 
132
 
133
static void pci200_set_iface(port_t *port)
134
{
135
        card_t *card = port->card;
136
        u16 msci = get_msci(port);
137
        u8 rxs = port->rxs & CLK_BRG_MASK;
138
        u8 txs = port->txs & CLK_BRG_MASK;
139
 
140
        sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS,
141
                port_to_card(port));
142
        switch(port->settings.clock_type) {
143
        case CLOCK_INT:
144
                rxs |= CLK_BRG; /* BRG output */
145
                txs |= CLK_PIN_OUT | CLK_TX_RXCLK; /* RX clock */
146
                break;
147
 
148
        case CLOCK_TXINT:
149
                rxs |= CLK_LINE; /* RXC input */
150
                txs |= CLK_PIN_OUT | CLK_BRG; /* BRG output */
151
                break;
152
 
153
        case CLOCK_TXFROMRX:
154
                rxs |= CLK_LINE; /* RXC input */
155
                txs |= CLK_PIN_OUT | CLK_TX_RXCLK; /* RX clock */
156
                break;
157
 
158
        default:                /* EXTernal clock */
159
                rxs |= CLK_LINE; /* RXC input */
160
                txs |= CLK_PIN_OUT | CLK_LINE; /* TXC input */
161
                break;
162
        }
163
 
164
        port->rxs = rxs;
165
        port->txs = txs;
166
        sca_out(rxs, msci + RXS, card);
167
        sca_out(txs, msci + TXS, card);
168
        sca_set_port(port);
169
}
170
 
171
 
172
 
173
static int pci200_open(struct net_device *dev)
174
{
175
        port_t *port = dev_to_port(dev);
176
 
177
        int result = hdlc_open(dev);
178
        if (result)
179
                return result;
180
 
181
        sca_open(dev);
182
        pci200_set_iface(port);
183
        sca_flush(port_to_card(port));
184
        return 0;
185
}
186
 
187
 
188
 
189
static int pci200_close(struct net_device *dev)
190
{
191
        sca_close(dev);
192
        sca_flush(port_to_card(dev_to_port(dev)));
193
        hdlc_close(dev);
194
        return 0;
195
}
196
 
197
 
198
 
199
static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
200
{
201
        const size_t size = sizeof(sync_serial_settings);
202
        sync_serial_settings new_line;
203
        sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
204
        port_t *port = dev_to_port(dev);
205
 
206
#ifdef DEBUG_RINGS
207
        if (cmd == SIOCDEVPRIVATE) {
208
                sca_dump_rings(dev);
209
                return 0;
210
        }
211
#endif
212
        if (cmd != SIOCWANDEV)
213
                return hdlc_ioctl(dev, ifr, cmd);
214
 
215
        switch(ifr->ifr_settings.type) {
216
        case IF_GET_IFACE:
217
                ifr->ifr_settings.type = IF_IFACE_V35;
218
                if (ifr->ifr_settings.size < size) {
219
                        ifr->ifr_settings.size = size; /* data size wanted */
220
                        return -ENOBUFS;
221
                }
222
                if (copy_to_user(line, &port->settings, size))
223
                        return -EFAULT;
224
                return 0;
225
 
226
        case IF_IFACE_V35:
227
        case IF_IFACE_SYNC_SERIAL:
228
                if (!capable(CAP_NET_ADMIN))
229
                        return -EPERM;
230
 
231
                if (copy_from_user(&new_line, line, size))
232
                        return -EFAULT;
233
 
234
                if (new_line.clock_type != CLOCK_EXT &&
235
                    new_line.clock_type != CLOCK_TXFROMRX &&
236
                    new_line.clock_type != CLOCK_INT &&
237
                    new_line.clock_type != CLOCK_TXINT)
238
                return -EINVAL; /* No such clock setting */
239
 
240
                if (new_line.loopback != 0 && new_line.loopback != 1)
241
                        return -EINVAL;
242
 
243
                memcpy(&port->settings, &new_line, size); /* Update settings */
244
                pci200_set_iface(port);
245
                sca_flush(port_to_card(port));
246
                return 0;
247
 
248
        default:
249
                return hdlc_ioctl(dev, ifr, cmd);
250
        }
251
}
252
 
253
 
254
 
255
static void pci200_pci_remove_one(struct pci_dev *pdev)
256
{
257
        int i;
258
        card_t *card = pci_get_drvdata(pdev);
259
 
260
        for (i = 0; i < 2; i++)
261
                if (card->ports[i].card) {
262
                        struct net_device *dev = port_to_dev(&card->ports[i]);
263
                        unregister_hdlc_device(dev);
264
                }
265
 
266
        if (card->irq)
267
                free_irq(card->irq, card);
268
 
269
        if (card->rambase)
270
                iounmap(card->rambase);
271
        if (card->scabase)
272
                iounmap(card->scabase);
273
        if (card->plxbase)
274
                iounmap(card->plxbase);
275
 
276
        pci_release_regions(pdev);
277
        pci_disable_device(pdev);
278
        pci_set_drvdata(pdev, NULL);
279
        if (card->ports[0].dev)
280
                free_netdev(card->ports[0].dev);
281
        if (card->ports[1].dev)
282
                free_netdev(card->ports[1].dev);
283
        kfree(card);
284
}
285
 
286
 
287
 
288
static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
289
                                         const struct pci_device_id *ent)
290
{
291
        card_t *card;
292
        u32 __iomem *p;
293
        int i;
294
        u32 ramsize;
295
        u32 ramphys;            /* buffer memory base */
296
        u32 scaphys;            /* SCA memory base */
297
        u32 plxphys;            /* PLX registers memory base */
298
 
299
#ifndef MODULE
300
        static int printed_version;
301
        if (!printed_version++)
302
                printk(KERN_INFO "%s\n", version);
303
#endif
304
 
305
        i = pci_enable_device(pdev);
306
        if (i)
307
                return i;
308
 
309
        i = pci_request_regions(pdev, "PCI200SYN");
310
        if (i) {
311
                pci_disable_device(pdev);
312
                return i;
313
        }
314
 
315
        card = kzalloc(sizeof(card_t), GFP_KERNEL);
316
        if (card == NULL) {
317
                printk(KERN_ERR "pci200syn: unable to allocate memory\n");
318
                pci_release_regions(pdev);
319
                pci_disable_device(pdev);
320
                return -ENOBUFS;
321
        }
322
        pci_set_drvdata(pdev, card);
323
        card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
324
        card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
325
        if (!card->ports[0].dev || !card->ports[1].dev) {
326
                printk(KERN_ERR "pci200syn: unable to allocate memory\n");
327
                pci200_pci_remove_one(pdev);
328
                return -ENOMEM;
329
        }
330
 
331
        if (pci_resource_len(pdev, 0) != PCI200SYN_PLX_SIZE ||
332
            pci_resource_len(pdev, 2) != PCI200SYN_SCA_SIZE ||
333
            pci_resource_len(pdev, 3) < 16384) {
334
                printk(KERN_ERR "pci200syn: invalid card EEPROM parameters\n");
335
                pci200_pci_remove_one(pdev);
336
                return -EFAULT;
337
        }
338
 
339
        plxphys = pci_resource_start(pdev,0) & PCI_BASE_ADDRESS_MEM_MASK;
340
        card->plxbase = ioremap(plxphys, PCI200SYN_PLX_SIZE);
341
 
342
        scaphys = pci_resource_start(pdev,2) & PCI_BASE_ADDRESS_MEM_MASK;
343
        card->scabase = ioremap(scaphys, PCI200SYN_SCA_SIZE);
344
 
345
        ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK;
346
        card->rambase = ioremap(ramphys, pci_resource_len(pdev,3));
347
 
348
        if (card->plxbase == NULL ||
349
            card->scabase == NULL ||
350
            card->rambase == NULL) {
351
                printk(KERN_ERR "pci200syn: ioremap() failed\n");
352
                pci200_pci_remove_one(pdev);
353
                return -EFAULT;
354
        }
355
 
356
        /* Reset PLX */
357
        p = &card->plxbase->init_ctrl;
358
        writel(readl(p) | 0x40000000, p);
359
        readl(p);               /* Flush the write - do not use sca_flush */
360
        udelay(1);
361
 
362
        writel(readl(p) & ~0x40000000, p);
363
        readl(p);               /* Flush the write - do not use sca_flush */
364
        udelay(1);
365
 
366
        ramsize = sca_detect_ram(card, card->rambase,
367
                                 pci_resource_len(pdev, 3));
368
 
369
        /* number of TX + RX buffers for one port - this is dual port card */
370
        i = ramsize / (2 * (sizeof(pkt_desc) + HDLC_MAX_MRU));
371
        card->tx_ring_buffers = min(i / 2, MAX_TX_BUFFERS);
372
        card->rx_ring_buffers = i - card->tx_ring_buffers;
373
 
374
        card->buff_offset = 2 * sizeof(pkt_desc) * (card->tx_ring_buffers +
375
                                                    card->rx_ring_buffers);
376
 
377
        printk(KERN_INFO "pci200syn: %u KB RAM at 0x%x, IRQ%u, using %u TX +"
378
               " %u RX packets rings\n", ramsize / 1024, ramphys,
379
               pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
380
 
381
        if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) {
382
                printk(KERN_ERR "Detected PCI200SYN card with old "
383
                       "configuration data.\n");
384
                printk(KERN_ERR "See <http://www.kernel.org/pub/"
385
                       "linux/utils/net/hdlc/pci200syn/> for update.\n");
386
                printk(KERN_ERR "The card will stop working with"
387
                       " future versions of Linux if not updated.\n");
388
        }
389
 
390
        if (card->tx_ring_buffers < 1) {
391
                printk(KERN_ERR "pci200syn: RAM test failed\n");
392
                pci200_pci_remove_one(pdev);
393
                return -EFAULT;
394
        }
395
 
396
        /* Enable interrupts on the PCI bridge */
397
        p = &card->plxbase->intr_ctrl_stat;
398
        writew(readw(p) | 0x0040, p);
399
 
400
        /* Allocate IRQ */
401
        if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) {
402
                printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
403
                       pdev->irq);
404
                pci200_pci_remove_one(pdev);
405
                return -EBUSY;
406
        }
407
        card->irq = pdev->irq;
408
 
409
        sca_init(card, 0);
410
 
411
        for (i = 0; i < 2; i++) {
412
                port_t *port = &card->ports[i];
413
                struct net_device *dev = port_to_dev(port);
414
                hdlc_device *hdlc = dev_to_hdlc(dev);
415
                port->phy_node = i;
416
 
417
                spin_lock_init(&port->lock);
418
                dev->irq = card->irq;
419
                dev->mem_start = ramphys;
420
                dev->mem_end = ramphys + ramsize - 1;
421
                dev->tx_queue_len = 50;
422
                dev->do_ioctl = pci200_ioctl;
423
                dev->open = pci200_open;
424
                dev->stop = pci200_close;
425
                hdlc->attach = sca_attach;
426
                hdlc->xmit = sca_xmit;
427
                port->settings.clock_type = CLOCK_EXT;
428
                port->card = card;
429
                if (register_hdlc_device(dev)) {
430
                        printk(KERN_ERR "pci200syn: unable to register hdlc "
431
                               "device\n");
432
                        port->card = NULL;
433
                        pci200_pci_remove_one(pdev);
434
                        return -ENOBUFS;
435
                }
436
                sca_init_sync_port(port);       /* Set up SCA memory */
437
 
438
                printk(KERN_INFO "%s: PCI200SYN node %d\n",
439
                       dev->name, port->phy_node);
440
        }
441
 
442
        sca_flush(card);
443
        return 0;
444
}
445
 
446
 
447
 
448
static struct pci_device_id pci200_pci_tbl[] __devinitdata = {
449
        { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
450
          PCI_DEVICE_ID_PLX_9050, 0, 0, 0 },
451
        { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
452
          PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
453
        { 0, }
454
};
455
 
456
 
457
static struct pci_driver pci200_pci_driver = {
458
        .name           = "PCI200SYN",
459
        .id_table       = pci200_pci_tbl,
460
        .probe          = pci200_pci_init_one,
461
        .remove         = pci200_pci_remove_one,
462
};
463
 
464
 
465
static int __init pci200_init_module(void)
466
{
467
#ifdef MODULE
468
        printk(KERN_INFO "%s\n", version);
469
#endif
470
        if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
471
                printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
472
                return -EINVAL;
473
        }
474
        return pci_register_driver(&pci200_pci_driver);
475
}
476
 
477
 
478
 
479
static void __exit pci200_cleanup_module(void)
480
{
481
        pci_unregister_driver(&pci200_pci_driver);
482
}
483
 
484
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
485
MODULE_DESCRIPTION("Goramo PCI200SYN serial port driver");
486
MODULE_LICENSE("GPL v2");
487
MODULE_DEVICE_TABLE(pci, pci200_pci_tbl);
488
module_param(pci_clock_freq, int, 0444);
489
MODULE_PARM_DESC(pci_clock_freq, "System PCI clock frequency in Hz");
490
module_init(pci200_init_module);
491
module_exit(pci200_cleanup_module);

powered by: WebSVN 2.1.0

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