Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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);