⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c4.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ *  * Module for AVM C4 & C2 card. *  * Copyright 1999 by Carsten Paeth <calle@calle.de> * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#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/kernelcapi.h>#include <linux/init.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/netdevice.h>#include <linux/isdn/capicmd.h>#include <linux/isdn/capiutil.h>#include <linux/isdn/capilli.h>#include "avmcard.h"#undef CONFIG_C4_DEBUG#undef CONFIG_C4_POLLDEBUG/* ------------------------------------------------------------- */static char *revision = "$Revision: 1.1.2.2 $";/* ------------------------------------------------------------- */static int suppress_pollack;static struct pci_device_id c4_pci_tbl[] = {	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, 0, 0, (unsigned long)4 },	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2, 0, 0, (unsigned long)2 },	{ }			/* Terminating entry */};MODULE_DEVICE_TABLE(pci, c4_pci_tbl);MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");MODULE_AUTHOR("Carsten Paeth");MODULE_LICENSE("GPL");MODULE_PARM(suppress_pollack, "0-1i");/* ------------------------------------------------------------- */static void c4_dispatch_tx(avmcard *card);/* ------------------------------------------------------------- */#define DC21285_DRAM_A0MR	0x40000000#define DC21285_DRAM_A1MR	0x40004000#define DC21285_DRAM_A2MR	0x40008000#define DC21285_DRAM_A3MR	0x4000C000#define	CAS_OFFSET	0x88#define DC21285_ARMCSR_BASE	0x42000000#define	PCI_OUT_INT_STATUS	0x30#define	PCI_OUT_INT_MASK	0x34#define	MAILBOX_0		0x50#define	MAILBOX_1		0x54#define	MAILBOX_2		0x58#define	MAILBOX_3		0x5C#define	DOORBELL		0x60#define	DOORBELL_SETUP		0x64#define CHAN_1_CONTROL		0x90#define CHAN_2_CONTROL		0xB0#define DRAM_TIMING		0x10C#define DRAM_ADDR_SIZE_0	0x110#define DRAM_ADDR_SIZE_1	0x114#define DRAM_ADDR_SIZE_2	0x118#define DRAM_ADDR_SIZE_3	0x11C#define	SA_CONTROL		0x13C#define	XBUS_CYCLE		0x148#define	XBUS_STROBE		0x14C#define	DBELL_PCI_MASK		0x150#define DBELL_SA_MASK		0x154#define SDRAM_SIZE		0x1000000/* ------------------------------------------------------------- */#define	MBOX_PEEK_POKE		MAILBOX_0#define DBELL_ADDR		0x01#define DBELL_DATA		0x02#define DBELL_RNWR		0x40#define DBELL_INIT		0x80/* ------------------------------------------------------------- */#define	MBOX_UP_ADDR		MAILBOX_0#define	MBOX_UP_LEN		MAILBOX_1#define	MBOX_DOWN_ADDR		MAILBOX_2#define	MBOX_DOWN_LEN		MAILBOX_3#define	DBELL_UP_HOST		0x00000100#define	DBELL_UP_ARM		0x00000200#define	DBELL_DOWN_HOST		0x00000400#define	DBELL_DOWN_ARM		0x00000800#define	DBELL_RESET_HOST	0x40000000#define	DBELL_RESET_ARM		0x80000000/* ------------------------------------------------------------- */#define	DRAM_TIMING_DEF		0x001A01A5#define DRAM_AD_SZ_DEF0		0x00000045#define DRAM_AD_SZ_NULL		0x00000000#define SA_CTL_ALLRIGHT		0x64AA0271#define	INIT_XBUS_CYCLE		0x100016DB#define	INIT_XBUS_STROBE	0xF1F1F1F1/* ------------------------------------------------------------- */#define	RESET_TIMEOUT		(15*HZ)	/* 15 sec */#define	PEEK_POKE_TIMEOUT	(HZ/10)	/* 0.1 sec *//* ------------------------------------------------------------- */#define c4outmeml(addr, value)	writel(value, addr)#define c4inmeml(addr)	readl(addr)#define c4outmemw(addr, value)	writew(value, addr)#define c4inmemw(addr)	readw(addr)#define c4outmemb(addr, value)	writeb(value, addr)#define c4inmemb(addr)	readb(addr)/* ------------------------------------------------------------- */static inline int wait_for_doorbell(avmcard *card, unsigned long t){	unsigned long stop;	stop = jiffies + t;	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {		if (!time_before(jiffies, stop))			return -1;		mb();	}	return 0;}static int c4_poke(avmcard *card,  unsigned long off, unsigned long value){	if (wait_for_doorbell(card, HZ/10) < 0)		return -1;		c4outmeml(card->mbase+MBOX_PEEK_POKE, off);	c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);	if (wait_for_doorbell(card, HZ/10) < 0)		return -1;	c4outmeml(card->mbase+MBOX_PEEK_POKE, value);	c4outmeml(card->mbase+DOORBELL, DBELL_DATA | DBELL_ADDR);	return 0;}static int c4_peek(avmcard *card,  unsigned long off, unsigned long *valuep){	if (wait_for_doorbell(card, HZ/10) < 0)		return -1;	c4outmeml(card->mbase+MBOX_PEEK_POKE, off);	c4outmeml(card->mbase+DOORBELL, DBELL_RNWR | DBELL_ADDR);	if (wait_for_doorbell(card, HZ/10) < 0)		return -1;	*valuep = c4inmeml(card->mbase+MBOX_PEEK_POKE);	return 0;}/* ------------------------------------------------------------- */static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file){	u32 val;	unsigned char *dp;	u_int left;	u32 loadoff = 0;	dp = t4file->data;	left = t4file->len;	while (left >= sizeof(u32)) {	        if (t4file->user) {			if (copy_from_user(&val, dp, sizeof(val)))				return -EFAULT;		} else {			memcpy(&val, dp, sizeof(val));		}		if (c4_poke(card, loadoff, val)) {			printk(KERN_ERR "%s: corrupted firmware file ?\n",					card->name);			return -EIO;		}		left -= sizeof(u32);		dp += sizeof(u32);		loadoff += sizeof(u32);	}	if (left) {		val = 0;		if (t4file->user) {			if (copy_from_user(&val, dp, left))				return -EFAULT;		} else {			memcpy(&val, dp, left);		}		if (c4_poke(card, loadoff, val)) {			printk(KERN_ERR "%s: corrupted firmware file ?\n",					card->name);			return -EIO;		}	}	return 0;}/* ------------------------------------------------------------- */static inline void _put_byte(void **pp, u8 val){	u8 *s = *pp;	*s++ = val;	*pp = s;}static inline void _put_word(void **pp, u32 val){	u8 *s = *pp;	*s++ = val & 0xff;	*s++ = (val >> 8) & 0xff;	*s++ = (val >> 16) & 0xff;	*s++ = (val >> 24) & 0xff;	*pp = s;}static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len){	unsigned i = len;	_put_word(pp, i);	while (i-- > 0)		_put_byte(pp, *dp++);}static inline u8 _get_byte(void **pp){	u8 *s = *pp;	u8 val;	val = *s++;	*pp = s;	return val;}static inline u32 _get_word(void **pp){	u8 *s = *pp;	u32 val;	val = *s++;	val |= (*s++ << 8);	val |= (*s++ << 16);	val |= (*s++ << 24);	*pp = s;	return val;}static inline u32 _get_slice(void **pp, unsigned char *dp){	unsigned int len, i;	len = i = _get_word(pp);	while (i-- > 0) *dp++ = _get_byte(pp);	return len;}/* ------------------------------------------------------------- */static void c4_reset(avmcard *card){	unsigned long stop;	c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);	stop = jiffies + HZ*10;	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {		if (!time_before(jiffies, stop))			return;		c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);		mb();	}	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);}/* ------------------------------------------------------------- */static int c4_detect(avmcard *card){	unsigned long stop, dummy;	c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);	if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c)		return	1;	c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);	stop = jiffies + HZ*10;	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {		if (!time_before(jiffies, stop))			return 2;		c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);		mb();	}	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);	c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa);	if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3;	c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55);	if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4;	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5;	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6;	if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT))		return 7;	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE))		return 8;	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE))		return 8;	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;        mdelay(1);	if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;	if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;	if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12;	if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13;	if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14;	if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15;	if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;	if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;        mdelay(1);	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))		return 18;	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0))		return 19;	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL))		return 20;	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL))		return 21;	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL))		return 22;	/* Transputer test */		if (   c4_poke(card, 0x000000, 0x11111111)	    || c4_poke(card, 0x400000, 0x22222222)	    || c4_poke(card, 0x800000, 0x33333333)	    || c4_poke(card, 0xC00000, 0x44444444))		return 23;	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444)		return 24;	if (   c4_poke(card, 0x000000, 0x55555555)	    || c4_poke(card, 0x400000, 0x66666666)	    || c4_poke(card, 0x800000, 0x77777777)	    || c4_poke(card, 0xC00000, 0x88888888))		return 25;	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888)		return 26;	return 0;}/* ------------------------------------------------------------- */static void c4_dispatch_tx(avmcard *card){	avmcard_dmainfo *dma = card->dma;	struct sk_buff *skb;	u8 cmd, subcmd;	u16 len;	u32 txlen;	void *p;	if (card->csr & DBELL_DOWN_ARM) { /* tx busy */		return;	}	skb = skb_dequeue(&dma->send_queue);	if (!skb) {#ifdef CONFIG_C4_DEBUG		printk(KERN_DEBUG "%s: tx underrun\n", card->name);#endif		return;	}	len = CAPIMSG_LEN(skb->data);	if (len) {		cmd = CAPIMSG_COMMAND(skb->data);		subcmd = CAPIMSG_SUBCOMMAND(skb->data);		p = dma->sendbuf.dmabuf;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -