PageRenderTime 42ms CodeModel.GetById 11ms app.highlight 7ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/staging/sbe-2t3e3/module.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 210 lines | 160 code | 34 blank | 16 comment | 20 complexity | 650b08617375533acd88fc28f7a7a108 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  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);