Loading...
1/*
2 * SBE 2T3E3 synchronous serial card driver for Linux
3 *
4 * Copyright (C) 2009-2010 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 * This code is based on a driver written by SBE Inc.
11 */
12
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15#include <linux/module.h>
16#include <linux/slab.h>
17#include <linux/delay.h>
18#include <linux/netdevice.h>
19#include <linux/pci.h>
20#include <linux/hdlc.h>
21#include <linux/if_arp.h>
22#include <linux/interrupt.h>
23#include "2t3e3.h"
24
25static void check_leds(unsigned long arg)
26{
27 struct card *card = (struct card *)arg;
28 struct channel *channel0 = &card->channels[0];
29 static int blinker;
30
31 update_led(channel0, ++blinker);
32 if (has_two_ports(channel0->pdev))
33 update_led(&card->channels[1], blinker);
34
35 card->timer.expires = jiffies + HZ / 10;
36 add_timer(&card->timer);
37}
38
39static void t3e3_remove_channel(struct channel *channel)
40{
41 struct pci_dev *pdev = channel->pdev;
42 struct net_device *dev = channel->dev;
43
44 /* system hangs if board asserts irq while module is unloaded */
45 cpld_stop_intr(channel);
46 free_irq(dev->irq, dev);
47 dc_drop_descriptor_list(channel);
48 unregister_hdlc_device(dev);
49 free_netdev(dev);
50 pci_release_regions(pdev);
51 pci_disable_device(pdev);
52 pci_set_drvdata(pdev, NULL);
53}
54
55static int t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
56{
57 struct net_device *dev;
58 unsigned int val;
59 int err;
60
61 err = pci_enable_device(pdev);
62 if (err)
63 return err;
64
65 err = pci_request_regions(pdev, "SBE 2T3E3");
66 if (err)
67 goto disable;
68
69 dev = alloc_hdlcdev(channel);
70 if (!dev) {
71 pr_err("Out of memory\n");
72 err = -ENOMEM;
73 goto free_regions;
74 }
75
76 t3e3_sc_init(channel);
77 dev_to_priv(dev) = channel;
78
79 channel->pdev = pdev;
80 channel->dev = dev;
81 channel->card = card;
82 channel->addr = pci_resource_start(pdev, 0);
83 if (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)
84 channel->h.slot = 1;
85 else
86 channel->h.slot = 0;
87
88 err = setup_device(dev, channel);
89 if (err)
90 goto free_dev;
91
92 pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */
93 pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF);
94
95 pci_read_config_byte(channel->pdev, PCI_CACHE_LINE_SIZE, &channel->h.cache_size);
96 pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command);
97 t3e3_init(channel);
98
99 err = request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev);
100 if (err) {
101 netdev_warn(channel->dev, "%s: could not get irq: %d\n",
102 dev->name, dev->irq);
103 goto unregister_dev;
104 }
105
106 pci_set_drvdata(pdev, channel);
107 return 0;
108
109unregister_dev:
110 unregister_hdlc_device(dev);
111free_dev:
112 free_netdev(dev);
113free_regions:
114 pci_release_regions(pdev);
115disable:
116 pci_disable_device(pdev);
117 return err;
118}
119
120static void t3e3_remove_card(struct pci_dev *pdev)
121{
122 struct channel *channel0 = pci_get_drvdata(pdev);
123 struct card *card = channel0->card;
124
125 del_timer_sync(&card->timer);
126 if (has_two_ports(channel0->pdev)) {
127 t3e3_remove_channel(&card->channels[1]);
128 pci_dev_put(card->channels[1].pdev);
129 }
130 t3e3_remove_channel(channel0);
131 kfree(card);
132}
133
134static int t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
135{
136 /* pdev points to channel #0 */
137 struct pci_dev *pdev1 = NULL;
138 struct card *card;
139 int channels = 1, err;
140
141 if (has_two_ports(pdev)) {
142 while ((pdev1 = pci_get_subsys(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
143 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P1,
144 pdev1)))
145 if (pdev1->bus == pdev->bus &&
146 pdev1->devfn == pdev->devfn + 8 /* next device on the same bus */)
147 break; /* found the second channel */
148
149 if (!pdev1) {
150 dev_err(&pdev->dev, "Can't find the second channel\n");
151 return -EFAULT;
152 }
153 channels = 2;
154 /* holds the reference for pdev1 */
155 }
156
157 card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel),
158 GFP_KERNEL);
159 if (!card)
160 return -ENOBUFS;
161
162 spin_lock_init(&card->bootrom_lock);
163 card->bootrom_addr = pci_resource_start(pdev, 0);
164
165 err = t3e3_init_channel(&card->channels[0], pdev, card);
166 if (err)
167 goto free_card;
168
169 if (channels == 2) {
170 err = t3e3_init_channel(&card->channels[1], pdev1, card);
171 if (err) {
172 t3e3_remove_channel(&card->channels[0]);
173 goto free_card;
174 }
175 }
176
177 /* start LED timer */
178 init_timer(&card->timer);
179 card->timer.function = check_leds;
180 card->timer.expires = jiffies + HZ / 10;
181 card->timer.data = (unsigned long)card;
182 add_timer(&card->timer);
183 return 0;
184
185free_card:
186 kfree(card);
187 return err;
188}
189
190static struct pci_device_id t3e3_pci_tbl[] = {
191 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
192 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
193 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
194 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P0, 0, 0, 0 },
195 /* channel 1 will be initialized after channel 0 */
196 { 0, }
197};
198
199static struct pci_driver t3e3_pci_driver = {
200 .name = "SBE T3E3",
201 .id_table = t3e3_pci_tbl,
202 .probe = t3e3_init_card,
203 .remove = t3e3_remove_card,
204};
205
206module_pci_driver(t3e3_pci_driver);
207MODULE_LICENSE("GPL");
208MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);
1/*
2 * SBE 2T3E3 synchronous serial card driver for Linux
3 *
4 * Copyright (C) 2009-2010 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 * This code is based on a driver written by SBE Inc.
11 */
12
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/delay.h>
16#include <linux/netdevice.h>
17#include <linux/pci.h>
18#include <linux/hdlc.h>
19#include <linux/if_arp.h>
20#include <linux/interrupt.h>
21#include "2t3e3.h"
22
23static void check_leds(unsigned long arg)
24{
25 struct card *card = (struct card *)arg;
26 struct channel *channel0 = &card->channels[0];
27 static int blinker;
28
29 update_led(channel0, ++blinker);
30 if (has_two_ports(channel0->pdev))
31 update_led(&card->channels[1], blinker);
32
33 card->timer.expires = jiffies + HZ / 10;
34 add_timer(&card->timer);
35}
36
37static void t3e3_remove_channel(struct channel *channel)
38{
39 struct pci_dev *pdev = channel->pdev;
40 struct net_device *dev = channel->dev;
41
42 /* system hangs if board asserts irq while module is unloaded */
43 cpld_stop_intr(channel);
44 free_irq(dev->irq, dev);
45 dc_drop_descriptor_list(channel);
46 unregister_hdlc_device(dev);
47 free_netdev(dev);
48 pci_release_regions(pdev);
49 pci_disable_device(pdev);
50 pci_set_drvdata(pdev, NULL);
51}
52
53static int __devinit t3e3_init_channel(struct channel *channel, struct pci_dev *pdev, struct card *card)
54{
55 struct net_device *dev;
56 unsigned int val;
57 int err;
58
59 err = pci_enable_device(pdev);
60 if (err)
61 return err;
62
63 err = pci_request_regions(pdev, "SBE 2T3E3");
64 if (err)
65 goto disable;
66
67 dev = alloc_hdlcdev(channel);
68 if (!dev) {
69 printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
70 goto free_regions;
71 }
72
73 t3e3_sc_init(channel);
74 dev_to_priv(dev) = channel;
75
76 channel->pdev = pdev;
77 channel->dev = dev;
78 channel->card = card;
79 channel->addr = pci_resource_start(pdev, 0);
80 if (pdev->subsystem_device == PCI_SUBDEVICE_ID_SBE_2T3E3_P1)
81 channel->h.slot = 1;
82 else
83 channel->h.slot = 0;
84
85 if (setup_device(dev, channel))
86 goto free_regions;
87
88 pci_read_config_dword(channel->pdev, 0x40, &val); /* mask sleep mode */
89 pci_write_config_dword(channel->pdev, 0x40, val & 0x3FFFFFFF);
90
91 pci_read_config_byte(channel->pdev, PCI_CACHE_LINE_SIZE, &channel->h.cache_size);
92 pci_read_config_dword(channel->pdev, PCI_COMMAND, &channel->h.command);
93 t3e3_init(channel);
94
95 if (request_irq(dev->irq, &t3e3_intr, IRQF_SHARED, dev->name, dev)) {
96 printk(KERN_WARNING "%s: could not get irq: %d\n", dev->name, dev->irq);
97 goto free_regions;
98 }
99
100 pci_set_drvdata(pdev, channel);
101 return 0;
102
103free_regions:
104 pci_release_regions(pdev);
105disable:
106 pci_disable_device(pdev);
107 return err;
108}
109
110static void __devexit t3e3_remove_card(struct pci_dev *pdev)
111{
112 struct channel *channel0 = pci_get_drvdata(pdev);
113 struct card *card = channel0->card;
114
115 del_timer(&card->timer);
116 if (has_two_ports(channel0->pdev)) {
117 t3e3_remove_channel(&card->channels[1]);
118 pci_dev_put(card->channels[1].pdev);
119 }
120 t3e3_remove_channel(channel0);
121 kfree(card);
122}
123
124static int __devinit t3e3_init_card(struct pci_dev *pdev, const struct pci_device_id *ent)
125{
126 /* pdev points to channel #0 */
127 struct pci_dev *pdev1 = NULL;
128 struct card *card;
129 int channels = 1, err;
130
131 if (has_two_ports(pdev)) {
132 while ((pdev1 = pci_get_subsys(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
133 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P1,
134 pdev1)))
135 if (pdev1->bus == pdev->bus &&
136 pdev1->devfn == pdev->devfn + 8 /* next device on the same bus */)
137 break; /* found the second channel */
138
139 if (!pdev1) {
140 printk(KERN_ERR "SBE 2T3E3" ": Can't find the second channel\n");
141 return -EFAULT;
142 }
143 channels = 2;
144 /* holds the reference for pdev1 */
145 }
146
147 card = kzalloc(sizeof(struct card) + channels * sizeof(struct channel), GFP_KERNEL);
148 if (!card) {
149 printk(KERN_ERR "SBE 2T3E3" ": Out of memory\n");
150 return -ENOBUFS;
151 }
152
153 spin_lock_init(&card->bootrom_lock);
154 card->bootrom_addr = pci_resource_start(pdev, 0);
155
156 err = t3e3_init_channel(&card->channels[0], pdev, card);
157 if (err)
158 goto free_card;
159
160 if (channels == 2) {
161 err = t3e3_init_channel(&card->channels[1], pdev1, card);
162 if (err) {
163 t3e3_remove_channel(&card->channels[0]);
164 goto free_card;
165 }
166 }
167
168 /* start LED timer */
169 init_timer(&card->timer);
170 card->timer.function = check_leds;
171 card->timer.expires = jiffies + HZ / 10;
172 card->timer.data = (unsigned long)card;
173 add_timer(&card->timer);
174 return 0;
175
176free_card:
177 kfree(card);
178 return err;
179}
180
181static struct pci_device_id t3e3_pci_tbl[] __devinitdata = {
182 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
183 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_T3E3, 0, 0, 0 },
184 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
185 PCI_VENDOR_ID_SBE, PCI_SUBDEVICE_ID_SBE_2T3E3_P0, 0, 0, 0 },
186 /* channel 1 will be initialized after channel 0 */
187 { 0, }
188};
189
190static struct pci_driver t3e3_pci_driver = {
191 .name = "SBE T3E3",
192 .id_table = t3e3_pci_tbl,
193 .probe = t3e3_init_card,
194 .remove = t3e3_remove_card,
195};
196
197static int __init t3e3_init_module(void)
198{
199 return pci_register_driver(&t3e3_pci_driver);
200}
201
202static void __exit t3e3_cleanup_module(void)
203{
204 pci_unregister_driver(&t3e3_pci_driver);
205}
206
207module_init(t3e3_init_module);
208module_exit(t3e3_cleanup_module);
209MODULE_LICENSE("GPL");
210MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);