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 
check_leds(unsigned long arg)23 static 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 
t3e3_remove_channel(struct channel * channel)37 static 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 
t3e3_init_channel(struct channel * channel,struct pci_dev * pdev,struct card * card)53 static 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 
103 free_regions:
104 	pci_release_regions(pdev);
105 disable:
106 	pci_disable_device(pdev);
107 	return err;
108 }
109 
t3e3_remove_card(struct pci_dev * pdev)110 static 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 
t3e3_init_card(struct pci_dev * pdev,const struct pci_device_id * ent)124 static 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 
176 free_card:
177 	kfree(card);
178 	return err;
179 }
180 
181 static 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 
190 static 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 
t3e3_init_module(void)197 static int __init t3e3_init_module(void)
198 {
199 	return pci_register_driver(&t3e3_pci_driver);
200 }
201 
t3e3_cleanup_module(void)202 static void __exit t3e3_cleanup_module(void)
203 {
204 	pci_unregister_driver(&t3e3_pci_driver);
205 }
206 
207 module_init(t3e3_init_module);
208 module_exit(t3e3_cleanup_module);
209 MODULE_LICENSE("GPL");
210 MODULE_DEVICE_TABLE(pci, t3e3_pci_tbl);
211