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

📄 eicon_mod.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: eicon_mod.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $ * * ISDN lowlevel-module for Eicon active cards. *  * Copyright 1997      by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998-2000 by Armin Schindler (mac@melware.de)  * Copyright 1999,2000 Cytronics & Melware (info@melware.de) *  * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * Thanks to    Eicon Networks for *              documents, informations and hardware. * *		Deutsche Mailbox Saar-Lor-Lux GmbH *		for sponsoring and testing fax *		capabilities with Diva Server cards. *		(dor@deutschemailbox.de) * */#define DRIVERNAME "Eicon active ISDN driver"#define DRIVERRELEASE "2.0"#define DRIVERPATCH ".16"#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#ifdef CONFIG_MCA#include <linux/mca.h>#endif /* CONFIG_MCA */#include "eicon.h"#include "../avmb1/capicmd.h"  /* this should be moved in a common place */#undef N_DATA#include "adapter.h"#include "uxio.h"#define INCLUDE_INLINE_FUNCSstatic eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains                                                     start of card-list   */static char *eicon_revision = "$Revision: 1.1.4.1 $";extern char *eicon_pci_revision;extern char *eicon_isa_revision;extern char *eicon_idi_revision;extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,			unsigned int command, unsigned long arg);extern void eicon_pci_init_conf(eicon_card *card);#ifdef MODULE#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))#endif#define EICON_CTRL_VERSION 2 ulong DebugVar;spinlock_t eicon_lock;DESCRIPTOR idi_d[32];/* Parameters to be set by insmod */#ifdef CONFIG_ISDN_DRV_EICON_ISAstatic int   membase      = -1;static int   irq          = -1;#endifstatic char *id           = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";MODULE_DESCRIPTION(             "ISDN4Linux: Driver for Eicon active ISDN cards");MODULE_AUTHOR(                  "Armin Schindler");MODULE_LICENSE(                 "GPL");MODULE_PARM_DESC(id,   		"ID-String of first card");MODULE_PARM(id,           	"s");#ifdef CONFIG_ISDN_DRV_EICON_ISAMODULE_PARM_DESC(membase,	"Base address of first ISA card");MODULE_PARM_DESC(irq,    	"IRQ of first card");MODULE_PARM(membase,    	"i");MODULE_PARM(irq,          	"i");#endifchar *eicon_ctype_name[] = {        "ISDN-S",        "ISDN-SX",        "ISDN-SCOM",        "ISDN-QUADRO",        "ISDN-S2M",        "DIVA Server BRI/PCI",        "DIVA Server 4BRI/PCI",        "DIVA Server 4BRI/PCI",        "DIVA Server PRI/PCI"};static char *eicon_getrev(const char *revision){	char *rev;	char *p;	if ((p = strchr(revision, ':'))) {		rev = p + 2;		p = strchr(rev, '$');		*--p = 0;	} else rev = "?.??";	return rev;}static eicon_chan *find_channel(eicon_card *card, int channel){	if ((channel >= 0) && (channel < card->nchannels))        	return &(card->bch[channel]);	eicon_log(card, 1, "eicon: Invalid channel %d\n", channel);	return NULL;}#ifdef CONFIG_PCI#ifdef CONFIG_ISDN_DRV_EICON_PCI/* * Find pcicard with given card number  */static inline eicon_card *eicon_findnpcicard(int driverid){        eicon_card *p = cards;        while (p) {                if ((p->regname[strlen(p->regname)-1] == (driverid + '0')) &&			(p->bus == EICON_BUS_PCI))                        return p;                p = p->next;        }        return (eicon_card *) 0;}#endif#endif /* CONFIG_PCI */static voideicon_rcv_dispatch(struct eicon_card *card){	switch (card->bus) {		case EICON_BUS_ISA:		case EICON_BUS_MCA:		case EICON_BUS_PCI:			eicon_io_rcv_dispatch(card);			break;		default:			eicon_log(card, 1,			       "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);	}}static voideicon_ack_dispatch(struct eicon_card *card){	switch (card->bus) {		case EICON_BUS_ISA:		case EICON_BUS_MCA:		case EICON_BUS_PCI:			eicon_io_ack_dispatch(card);			break;		default:			eicon_log(card, 1,		       		"eicon_ack_dispatch: Illegal bustype %d\n", card->bus);	}}static voideicon_transmit(struct eicon_card *card){	switch (card->bus) {		case EICON_BUS_ISA:		case EICON_BUS_MCA:		case EICON_BUS_PCI:			eicon_io_transmit(card);			break;		default:			eicon_log(card, 1,			       "eicon_transmit: Illegal bustype %d\n", card->bus);	}}static inteicon_command(eicon_card * card, isdn_ctrl * c){        ulong a;        eicon_chan *chan;	eicon_cdef cdef;#ifdef CONFIG_PCI#ifdef CONFIG_ISDN_DRV_EICON_PCI	dia_start_t dstart;        int idi_length = 0;#endif#endif	isdn_ctrl cmd;	int ret = 0;	unsigned long flags; 	eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",		c->command, c->arg, (ulong) *c->parm.num);        switch (c->command) {		case ISDN_CMD_IOCTL:			memcpy(&a, c->parm.num, sizeof(ulong));			switch (c->arg) {				case EICON_IOCTL_GETVER:					return(EICON_CTRL_VERSION);				case EICON_IOCTL_GETTYPE:					if (card->bus == EICON_BUS_PCI) {						copy_to_user((char *)a, &card->hwif.pci.master, sizeof(int));					}					return(card->type);				case EICON_IOCTL_GETMMIO:					switch (card->bus) {						case EICON_BUS_ISA:						case EICON_BUS_MCA:							return (int)card->hwif.isa.shmem;						default:							eicon_log(card, 1,							       "eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}#ifdef CONFIG_ISDN_DRV_EICON_ISA				case EICON_IOCTL_SETMMIO:					if (card->flags & EICON_FLAGS_LOADED)						return -EBUSY;					switch (card->bus) {						case EICON_BUS_ISA:							if (eicon_isa_find_card(a,								card->hwif.isa.irq,								card->regname) < 0)								return -EFAULT;							card->hwif.isa.shmem = (eicon_isa_shmem *)a;							return 0;						case EICON_BUS_MCA:#if CONFIG_MCA							if (eicon_mca_find_card(								0, a,								card->hwif.isa.irq,								card->regname) < 0)								return -EFAULT;							card->hwif.isa.shmem = (eicon_isa_shmem *)a;							return 0;#endif /* CONFIG_MCA */						default:							eicon_log(card, 1,						      		"eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}					#endif				case EICON_IOCTL_GETIRQ:					switch (card->bus) {						case EICON_BUS_ISA:						case EICON_BUS_MCA:							return card->hwif.isa.irq;						default:							eicon_log(card, 1,							       "eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}				case EICON_IOCTL_SETIRQ:					if (card->flags & EICON_FLAGS_LOADED)						return -EBUSY;					if ((a < 2) || (a > 15))						return -EFAULT;					switch (card->bus) {						case EICON_BUS_ISA:						case EICON_BUS_MCA:							card->hwif.isa.irq = a;							return 0;						default:							eicon_log(card, 1,						      		"eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}					#ifdef CONFIG_ISDN_DRV_EICON_ISA				case EICON_IOCTL_LOADBOOT:					if (card->flags & EICON_FLAGS_RUNNING)						return -EBUSY;  					switch (card->bus) {						case EICON_BUS_ISA:						case EICON_BUS_MCA:							ret = eicon_isa_bootload(								&(card->hwif.isa),								&(((eicon_codebuf *)a)->isa));							break;						default:							eicon_log(card, 1,							       "eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}					return ret;#endif#ifdef CONFIG_ISDN_DRV_EICON_ISA				case EICON_IOCTL_LOADISA:					if (card->flags & EICON_FLAGS_RUNNING)						return -EBUSY;  					switch (card->bus) {						case EICON_BUS_ISA:						case EICON_BUS_MCA:							ret = eicon_isa_load(								&(card->hwif.isa),								&(((eicon_codebuf *)a)->isa));							if (!ret) {                                                                card->flags |= EICON_FLAGS_LOADED;                                                                card->flags |= EICON_FLAGS_RUNNING;								if (card->hwif.isa.channels > 1) {									cmd.command = ISDN_STAT_ADDCH;									cmd.driver = card->myid;									cmd.arg = card->hwif.isa.channels - 1;									card->interface.statcallb(&cmd);								}								cmd.command = ISDN_STAT_RUN;    								cmd.driver = card->myid;        								cmd.arg = 0;                    								card->interface.statcallb(&cmd);							}							break;						default:							eicon_log(card, 1,							       "eicon: Illegal BUS type %d\n",							       card->bus);							ret = -ENODEV;					}					return ret;#endif				case EICON_IOCTL_MANIF:					if (!card->flags & EICON_FLAGS_RUNNING)						return -ENODEV;					if (!card->d)						return -ENODEV;					if (!card->d->features & DI_MANAGE)						return -ENODEV;					ret = eicon_idi_manage(						card, 						(eicon_manifbuf *)a);					return ret;				case EICON_IOCTL_GETXLOG:					return -ENODEV;				case EICON_IOCTL_ADDCARD:					if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))						return -EFAULT;					if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id, 0)))						return -EIO;					return 0;				case EICON_IOCTL_DEBUGVAR:					DebugVar = a;					eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar);					return 0;#ifdef MODULE				case EICON_IOCTL_FREEIT:					while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;					MOD_INC_USE_COUNT;					return 0;#endif				case EICON_IOCTL_LOADPCI:					eicon_log(card, 1, "Eicon: Wrong version of load-utility,\n");					eicon_log(card, 1, "Eicon: re-compile eiconctrl !\n");					eicon_log(card, 1, "Eicon: Maybe update of utility is necessary !\n");					return -EINVAL;				default:	#ifdef CONFIG_PCI#ifdef CONFIG_ISDN_DRV_EICON_PCI					if (c->arg < EICON_IOCTL_DIA_OFFSET)						return -EINVAL;					if (copy_from_user(&dstart, (char *)a, sizeof(dstart)))						return -1;					if (!(card = eicon_findnpcicard(dstart.card_id)))						return -EINVAL;					ret = do_ioctl(NULL, NULL,						c->arg - EICON_IOCTL_DIA_OFFSET,						(unsigned long) a);					if (((c->arg - EICON_IOCTL_DIA_OFFSET)==DIA_IOCTL_START) && (!ret)) {						if (card->type != EICON_CTYPE_MAESTRAQ) {							DIVA_DIDD_Read(idi_d, sizeof(idi_d));                                                        for(idi_length = 0; idi_length < 32; idi_length++) {                                                          if (idi_d[idi_length].type == 0) break;                                                        }                                                        if ((idi_length < 1) || (idi_length >= 32)) {					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");                                                          break;                                                        }							card->d = &idi_d[idi_length - 1];							card->flags |= EICON_FLAGS_LOADED;							card->flags |= EICON_FLAGS_RUNNING;							eicon_pci_init_conf(card);							if (card->d->channels > 1) {								cmd.command = ISDN_STAT_ADDCH;								cmd.driver = card->myid;								cmd.arg = card->d->channels - 1;								card->interface.statcallb(&cmd);							}							cmd.command = ISDN_STAT_RUN;    							cmd.driver = card->myid;        							cmd.arg = 0;                    							card->interface.statcallb(&cmd);							eicon_log(card, 1, "Eicon: %s started, %d channels (feat. 0x%x)\n",								(card->type == EICON_CTYPE_MAESTRA) ? "BRI" : "PRI",								card->d->channels, card->d->features);						} else {							int i;							DIVA_DIDD_Read(idi_d, sizeof(idi_d));                                                        for(idi_length = 0; idi_length < 32; idi_length++)                                                          if (idi_d[idi_length].type == 0) break;                                                        if ((idi_length < 1) || (idi_length >= 32)) {					                  eicon_log(card, 1, "eicon: invalid idi table length.\n");                                                          break;                                                        }        						for(i = 3; i >= 0; i--) {								if (!(card = eicon_findnpcicard(dstart.card_id - i)))									return -EINVAL;									card->flags |= EICON_FLAGS_LOADED;								card->flags |= EICON_FLAGS_RUNNING;								card->d = &idi_d[idi_length - (i+1)];								eicon_pci_init_conf(card);								if (card->d->channels > 1) {									cmd.command = ISDN_STAT_ADDCH;									cmd.driver = card->myid;									cmd.arg = card->d->channels - 1;									card->interface.statcallb(&cmd);								}								cmd.command = ISDN_STAT_RUN;    								cmd.driver = card->myid;        								cmd.arg = 0;                    								card->interface.statcallb(&cmd);								eicon_log(card, 1, "Eicon: %d/4BRI started, %d channels (feat. 0x%x)\n",									4-i, card->d->channels, card->d->features);							}						}					}					return ret;#else					return -EINVAL;#endif#endif /* CONFIG_PCI */			}			break;		case ISDN_CMD_DIAL:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			spin_lock_irqsave(&eicon_lock, flags);			if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {				spin_unlock_irqrestore(&eicon_lock, flags);				eicon_log(card, 1, "Dial on channel %d with state %d\n",					chan->No, chan->fsm_state);				return -EBUSY;			}			chan->fsm_state = EICON_STATE_OCALL;			spin_unlock_irqrestore(&eicon_lock, flags);						ret = idi_connect_req(card, chan, c->parm.setup.phone,						     c->parm.setup.eazmsn,						     c->parm.setup.si1,						     c->parm.setup.si2);			if (ret) {				cmd.driver = card->myid;				cmd.command = ISDN_STAT_DHUP;				cmd.arg &= 0x1f;				card->interface.statcallb(&cmd);			}			return ret;		case ISDN_CMD_ACCEPTD:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			if (chan->fsm_state == EICON_STATE_ICALL) { 				idi_connect_res(card, chan);			}			return 0;		case ISDN_CMD_ACCEPTB:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			return 0;		case ISDN_CMD_HANGUP:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			idi_hangup(card, chan);			return 0;		case ISDN_CMD_SETEAZ:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			chan->eazmask = 0x3ff;			eicon_idi_listen_req(card, chan);			return 0;		case ISDN_CMD_CLREAZ:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			chan->eazmask = 0;			eicon_idi_listen_req(card, chan);			return 0;		case ISDN_CMD_SETL2:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			chan->l2prot = (c->arg >> 8);			return 0;		case ISDN_CMD_GETL2:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			return chan->l2prot;		case ISDN_CMD_SETL3:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			chan->l3prot = (c->arg >> 8);#ifdef CONFIG_ISDN_TTY_FAX			if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) {				chan->fax = c->parm.fax;				eicon_log(card, 128, "idi_cmd: Ch%d: SETL3 struct fax=0x%x\n",chan->No, chan->fax);			}#endif			return 0;		case ISDN_CMD_GETL3:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			if (!(chan = find_channel(card, c->arg & 0x1f)))				break;			return chan->l3prot;		case ISDN_CMD_GETEAZ:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n");			return 0;		case ISDN_CMD_SETSIL:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n");			return 0;		case ISDN_CMD_GETSIL:			if (!card->flags & EICON_FLAGS_RUNNING)				return -ENODEV;			eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n");

⌨️ 快捷键说明

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