t1pci.c 6.61 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
Linus Torvalds's avatar
Linus Torvalds committed
2 3 4
 * 
 * Module for AVM T1 PCI-card.
 * 
Linus Torvalds's avatar
Linus Torvalds committed
5
 * Copyright 1999 by Carsten Paeth <calle@calle.de>
Linus Torvalds's avatar
Linus Torvalds committed
6
 * 
Linus Torvalds's avatar
Linus Torvalds committed
7 8 9
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
Linus Torvalds's avatar
Linus Torvalds committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/capi.h>
#include <linux/init.h>
#include <asm/io.h>
24 25 26
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
#include <linux/isdn/capilli.h>
Linus Torvalds's avatar
Linus Torvalds committed
27 28
#include "avmcard.h"

Linus Torvalds's avatar
Linus Torvalds committed
29
static char *revision = "$Revision: 1.1.4.1.2.1 $";
Linus Torvalds's avatar
Linus Torvalds committed
30 31 32 33 34 35

#undef CONFIG_T1PCI_DEBUG
#undef CONFIG_T1PCI_POLLDEBUG

/* ------------------------------------------------------------- */

Linus Torvalds's avatar
Linus Torvalds committed
36
static struct pci_device_id t1pci_pci_tbl[] __devinitdata = {
Linus Torvalds's avatar
Linus Torvalds committed
37 38 39 40 41
	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
	{ }				/* Terminating entry */
};

MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
Linus Torvalds's avatar
Linus Torvalds committed
42 43 44
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
Linus Torvalds's avatar
Linus Torvalds committed
45 46 47

/* ------------------------------------------------------------- */

Linus Torvalds's avatar
Linus Torvalds committed
48 49
static int t1pci_add_card(struct capi_driver *driver,
                          struct capicardparams *p,
50
	                  struct pci_dev *pdev)
Linus Torvalds's avatar
Linus Torvalds committed
51 52 53 54 55
{
	avmcard *card;
	avmctrl_info *cinfo;
	int retval;

56
	card = b1_alloc_card(1);
Linus Torvalds's avatar
Linus Torvalds committed
57 58
	if (!card) {
		printk(KERN_WARNING "%s: no memory.\n", driver->name);
59
		retval = -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
60
		goto err;
Linus Torvalds's avatar
Linus Torvalds committed
61
	}
62

63
        card->dma = avmcard_dma_alloc(driver->name, pdev, 2048+128, 2048+128);
Linus Torvalds's avatar
Linus Torvalds committed
64 65
	if (!card->dma) {
		printk(KERN_WARNING "%s: no memory.\n", driver->name);
66 67
		retval = -ENOMEM;
		goto err_free;
Linus Torvalds's avatar
Linus Torvalds committed
68
	}
69 70

	cinfo = card->ctrlinfo;
Linus Torvalds's avatar
Linus Torvalds committed
71 72 73 74 75 76
	sprintf(card->name, "t1pci-%x", p->port);
	card->port = p->port;
	card->irq = p->irq;
	card->membase = p->membase;
	card->cardtype = avm_t1pci;

Linus Torvalds's avatar
Linus Torvalds committed
77
	if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
Linus Torvalds's avatar
Linus Torvalds committed
78 79 80
		printk(KERN_WARNING
		       "%s: ports 0x%03x-0x%03x in use.\n",
		       driver->name, card->port, card->port + AVMB1_PORTLEN);
Linus Torvalds's avatar
Linus Torvalds committed
81
		retval = -EBUSY;
82
		goto err_free_dma;
Linus Torvalds's avatar
Linus Torvalds committed
83 84
	}

Linus Torvalds's avatar
Linus Torvalds committed
85 86
	card->mbase = ioremap_nocache(card->membase, 64);
	if (!card->mbase) {
Linus Torvalds's avatar
Linus Torvalds committed
87 88
		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
					driver->name, card->membase);
Linus Torvalds's avatar
Linus Torvalds committed
89 90
		retval = -EIO;
		goto err_release_region;
Linus Torvalds's avatar
Linus Torvalds committed
91 92 93 94
	}

	b1dma_reset(card);

Linus Torvalds's avatar
Linus Torvalds committed
95 96
	retval = t1pci_detect(card);
	if (retval != 0) {
Linus Torvalds's avatar
Linus Torvalds committed
97 98 99 100 101 102
		if (retval < 6)
			printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
					driver->name, card->port, retval);
		else
			printk(KERN_NOTICE "%s: card at 0x%x, but cabel not connected or T1 has no power (%d)\n",
					driver->name, card->port, retval);
Linus Torvalds's avatar
Linus Torvalds committed
103 104
		retval = -EIO;
		goto err_unmap;
Linus Torvalds's avatar
Linus Torvalds committed
105 106 107 108 109 110 111
	}
	b1dma_reset(card);

	retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
	if (retval) {
		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
				driver->name, card->irq);
Linus Torvalds's avatar
Linus Torvalds committed
112 113
		retval = -EBUSY;
		goto err_unmap;
Linus Torvalds's avatar
Linus Torvalds committed
114 115
	}

116
	cinfo->capi_ctrl = attach_capi_ctr(driver, card->name, cinfo);
Linus Torvalds's avatar
Linus Torvalds committed
117 118
	if (!cinfo->capi_ctrl) {
		printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
Linus Torvalds's avatar
Linus Torvalds committed
119 120
		retval = -EBUSY;
		goto err_free_irq;
Linus Torvalds's avatar
Linus Torvalds committed
121 122 123 124 125 126 127
	}
	card->cardnr = cinfo->capi_ctrl->cnr;

	printk(KERN_INFO
		"%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
		driver->name, card->port, card->irq, card->membase);

128
	pci_set_drvdata(pdev, card);
Linus Torvalds's avatar
Linus Torvalds committed
129
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
130 131 132 133 134 135 136

 err_free_irq:
	free_irq(card->irq, card);
 err_unmap:
	iounmap(card->mbase);
 err_release_region:
	release_region(card->port, AVMB1_PORTLEN);
137
 err_free_dma:
Linus Torvalds's avatar
Linus Torvalds committed
138
	avmcard_dma_free(card->dma);
139 140
 err_free:
	b1_free_card(card);
Linus Torvalds's avatar
Linus Torvalds committed
141 142 143 144 145 146
 err:
	return retval;
}

/* ------------------------------------------------------------- */

147
static void t1pci_remove(struct pci_dev *pdev)
Linus Torvalds's avatar
Linus Torvalds committed
148
{
149 150
	avmcard *card = pci_get_drvdata(pdev);
	avmctrl_info *cinfo = card->ctrlinfo;
Linus Torvalds's avatar
Linus Torvalds committed
151 152 153

 	b1dma_reset(card);

154
	detach_capi_ctr(cinfo->capi_ctrl);
Linus Torvalds's avatar
Linus Torvalds committed
155 156 157 158
	free_irq(card->irq, card);
	iounmap(card->mbase);
	release_region(card->port, AVMB1_PORTLEN);
	avmcard_dma_free(card->dma);
159
	b1_free_card(card);
Linus Torvalds's avatar
Linus Torvalds committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
}

/* ------------------------------------------------------------- */

static char *t1pci_procinfo(struct capi_ctr *ctrl)
{
	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);

	if (!cinfo)
		return "";
	sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
		cinfo->cardname[0] ? cinfo->cardname : "-",
		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
		cinfo->card ? cinfo->card->port : 0x0,
		cinfo->card ? cinfo->card->irq : 0,
		cinfo->card ? cinfo->card->membase : 0
		);
	return cinfo->infobuf;
}

/* ------------------------------------------------------------- */

static struct capi_driver t1pci_driver = {
183 184 185 186 187 188 189 190 191 192 193 194
	owner: THIS_MODULE,
	name: "t1pci",
	revision: "0.0",
	load_firmware: b1dma_load_firmware,
	reset_ctr: b1dma_reset_ctr,
	register_appl: b1dma_register_appl,
	release_appl: b1dma_release_appl,
	send_message: b1dma_send_message,
	
	procinfo: t1pci_procinfo,
	ctr_read_proc: b1dmactl_read_proc,
	driver_read_proc: 0,	/* use standard driver_read_proc */
Linus Torvalds's avatar
Linus Torvalds committed
195 196
};

Linus Torvalds's avatar
Linus Torvalds committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
/* ------------------------------------------------------------- */

static int __devinit t1pci_probe(struct pci_dev *dev,
				 const struct pci_device_id *ent)
{
	struct capi_driver *driver = &t1pci_driver;
	struct capicardparams param;
	int retval;

	if (pci_enable_device(dev) < 0) {
		printk(KERN_ERR	"%s: failed to enable AVM-T1-PCI\n",
		       driver->name);
		return -ENODEV;
	}
	pci_set_master(dev);

	param.port = pci_resource_start(dev, 1);
	param.irq = dev->irq;
	param.membase = pci_resource_start(dev, 0);

	printk(KERN_INFO
	       "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
	       driver->name, param.port, param.irq, param.membase);

	retval = t1pci_add_card(driver, &param, dev);
	if (retval != 0) {
		printk(KERN_ERR
		       "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n",
		       driver->name, param.port, param.irq, param.membase);
		return -ENODEV;
	}
	return 0;
}

static struct pci_driver t1pci_pci_driver = {
       name:           "t1pci",
       id_table:       t1pci_pci_tbl,
       probe:          t1pci_probe,
235
       remove:         t1pci_remove,
Linus Torvalds's avatar
Linus Torvalds committed
236
};
Linus Torvalds's avatar
Linus Torvalds committed
237 238 239

static int __init t1pci_init(void)
{
240
	int retval;
Linus Torvalds's avatar
Linus Torvalds committed
241

242
	b1_set_revision(&t1pci_driver, revision);
243
        attach_capi_driver(&t1pci_driver);
Linus Torvalds's avatar
Linus Torvalds committed
244

245 246 247 248 249
	retval = pci_register_driver(&t1pci_pci_driver);
	if (retval < 0)
		goto err;

	printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
250
	       t1pci_driver.name, retval);
251 252 253 254
	retval = 0;
	goto out;

 err:
Linus Torvalds's avatar
Linus Torvalds committed
255
	detach_capi_driver(&t1pci_driver);
256 257
 out:
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
258 259 260 261
}

static void __exit t1pci_exit(void)
{
Linus Torvalds's avatar
Linus Torvalds committed
262 263
	pci_unregister_driver(&t1pci_pci_driver);
	detach_capi_driver(&t1pci_driver);
Linus Torvalds's avatar
Linus Torvalds committed
264 265 266 267
}

module_init(t1pci_init);
module_exit(t1pci_exit);