diva.c

来自「linux 内核源代码」· C语言 代码 · 共 1,284 行 · 第 1/3 页

C
1,284
字号
				spin_unlock_irqrestore(&cs->lock, flags);				return (0);			}			if (cs->subtyp == DIVA_IPAC_PCI) {				ireg = (unsigned int *)cs->hw.diva.pci_cfg;				*ireg = PITA_INT0_ENABLE;			}			inithscxisac(cs, 3);			spin_unlock_irqrestore(&cs->lock, flags);			return(0);		case CARD_TEST:			return(0);		case (MDL_REMOVE | REQUEST):			cs->hw.diva.status = 0;			break;		case (MDL_ASSIGN | REQUEST):			cs->hw.diva.status |= DIVA_ASSIGN;			break;		case MDL_INFO_SETUP:			if ((long)arg)				cs->hw.diva.status |=  0x0200;			else				cs->hw.diva.status |=  0x0100;			break;		case MDL_INFO_CONN:			if ((long)arg)				cs->hw.diva.status |=  0x2000;			else				cs->hw.diva.status |=  0x1000;			break;		case MDL_INFO_REL:			if ((long)arg) {				cs->hw.diva.status &=  ~0x2000;				cs->hw.diva.status &=  ~0x0200;			} else {				cs->hw.diva.status &=  ~0x1000;				cs->hw.diva.status &=  ~0x0100;			}			break;	}	if ((cs->subtyp != DIVA_IPAC_ISA) && 	    (cs->subtyp != DIVA_IPAC_PCI) &&	    (cs->subtyp != DIVA_IPACX_PCI)) {	    	spin_lock_irqsave(&cs->lock, flags);		diva_led_handler(cs);		spin_unlock_irqrestore(&cs->lock, flags);	}	return(0);}static int __devinit setup_diva_common(struct IsdnCardState *cs){	int bytecnt;	u_char val;	if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))		bytecnt = 8;	else		bytecnt = 32;	printk(KERN_INFO		"Diva: %s card configured at %#lx IRQ %d\n",		(cs->subtyp == DIVA_PCI) ? "PCI" :		(cs->subtyp == DIVA_ISA) ? "ISA" : 		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :		(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",		cs->hw.diva.cfg_reg, cs->irq);	if ((cs->subtyp == DIVA_IPAC_PCI)  || 	    (cs->subtyp == DIVA_IPACX_PCI) || 	    (cs->subtyp == DIVA_PCI)         )		printk(KERN_INFO "Diva: %s space at %#lx\n",			(cs->subtyp == DIVA_PCI) ? "PCI" :			(cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",			cs->hw.diva.pci_cfg);	if ((cs->subtyp != DIVA_IPAC_PCI) &&	    (cs->subtyp != DIVA_IPACX_PCI)   ) {		if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) {			printk(KERN_WARNING			       "HiSax: %s config port %lx-%lx already in use\n",			       "diva",			       cs->hw.diva.cfg_reg,			       cs->hw.diva.cfg_reg + bytecnt);			iounmap_diva(cs);			return (0);		}	}	cs->BC_Read_Reg  = &ReadHSCX;	cs->BC_Write_Reg = &WriteHSCX;	cs->BC_Send_Data = &hscx_fill_fifo;	cs->cardmsg = &Diva_card_msg;	setup_isac(cs);	if (cs->subtyp == DIVA_IPAC_ISA) {		cs->readisac  = &ReadISAC_IPAC;		cs->writeisac = &WriteISAC_IPAC;		cs->readisacfifo  = &ReadISACfifo_IPAC;		cs->writeisacfifo = &WriteISACfifo_IPAC;		cs->irq_func = &diva_irq_ipac_isa;		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);		printk(KERN_INFO "Diva: IPAC version %x\n", val);	} else if (cs->subtyp == DIVA_IPAC_PCI) {		cs->readisac  = &MemReadISAC_IPAC;		cs->writeisac = &MemWriteISAC_IPAC;		cs->readisacfifo  = &MemReadISACfifo_IPAC;		cs->writeisacfifo = &MemWriteISACfifo_IPAC;		cs->BC_Read_Reg  = &MemReadHSCX;		cs->BC_Write_Reg = &MemWriteHSCX;		cs->BC_Send_Data = &Memhscx_fill_fifo;		cs->irq_func = &diva_irq_ipac_pci;		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);		printk(KERN_INFO "Diva: IPAC version %x\n", val);	} else if (cs->subtyp == DIVA_IPACX_PCI) {		cs->readisac  = &MemReadISAC_IPACX;		cs->writeisac = &MemWriteISAC_IPACX;		cs->readisacfifo  = &MemReadISACfifo_IPACX;		cs->writeisacfifo = &MemWriteISACfifo_IPACX;		cs->BC_Read_Reg  = &MemReadHSCX_IPACX;		cs->BC_Write_Reg = &MemWriteHSCX_IPACX;		cs->BC_Send_Data = NULL; // function located in ipacx module		cs->irq_func = &diva_irq_ipacx_pci;		printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 			MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);	} else { /* DIVA 2.0 */		cs->hw.diva.tl.function = (void *) diva_led_handler;		cs->hw.diva.tl.data = (long) cs;		init_timer(&cs->hw.diva.tl);		cs->readisac  = &ReadISAC;		cs->writeisac = &WriteISAC;		cs->readisacfifo  = &ReadISACfifo;		cs->writeisacfifo = &WriteISACfifo;		cs->irq_func = &diva_interrupt;		ISACVersion(cs, "Diva:");		if (HscxVersion(cs, "Diva:")) {			printk(KERN_WARNING		       "Diva: wrong HSCX versions check IO address\n");			release_io_diva(cs);			return (0);		}	}	return (1);}#ifdef CONFIG_ISAstatic int __devinit setup_diva_isa(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	u_char val;	if (!card->para[1])		return (-1);	/* card not found; continue search */	cs->hw.diva.ctrl_reg = 0;	cs->hw.diva.cfg_reg = card->para[1];	val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,		cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);	printk(KERN_INFO "Diva: IPAC version %x\n", val);	if ((val == 1) || (val==2)) {		cs->subtyp = DIVA_IPAC_ISA;		cs->hw.diva.ctrl = 0;		cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;		cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;		cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;		cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;		test_and_set_bit(HW_IPAC, &cs->HW_Flags);	} else {		cs->subtyp = DIVA_ISA;		cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;		cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;		cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;		cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;		cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;	}	cs->irq = card->para[0];	return (1);		/* card found */}#else	/* if !CONFIG_ISA */static int __devinit setup_diva_isa(struct IsdnCard *card){	return (-1);	/* card not found; continue search */}#endif	/* CONFIG_ISA */#ifdef __ISAPNP__static struct isapnp_device_id diva_ids[] __devinitdata = {	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),	  ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 	  (unsigned long) "Diva picola" },	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),	  ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), 	  (unsigned long) "Diva picola" },	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),	  ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 	  (unsigned long) "Diva 2.0" },	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),	  ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), 	  (unsigned long) "Diva 2.0" },	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),	  ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 	  (unsigned long) "Diva 2.01" },	{ ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),	  ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), 	  (unsigned long) "Diva 2.01" },	{ 0, }};static struct isapnp_device_id *ipid __devinitdata = &diva_ids[0];static struct pnp_card *pnp_c __devinitdata = NULL;static int __devinit setup_diva_isapnp(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	struct pnp_dev *pnp_d;	if (!isapnp_present())		return (-1);	/* card not found; continue search */	while(ipid->card_vendor) {		if ((pnp_c = pnp_find_card(ipid->card_vendor,			ipid->card_device, pnp_c))) {			pnp_d = NULL;			if ((pnp_d = pnp_find_dev(pnp_c,				ipid->vendor, ipid->function, pnp_d))) {				int err;				printk(KERN_INFO "HiSax: %s detected\n",					(char *)ipid->driver_data);				pnp_disable_dev(pnp_d);				err = pnp_activate_dev(pnp_d);				if (err<0) {					printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",						__FUNCTION__, err);					return(0);				}				card->para[1] = pnp_port_start(pnp_d, 0);				card->para[0] = pnp_irq(pnp_d, 0);				if (!card->para[0] || !card->para[1]) {					printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",						card->para[0], card->para[1]);					pnp_disable_dev(pnp_d); 					return(0);				}				cs->hw.diva.cfg_reg  = card->para[1];				cs->irq = card->para[0];				if (ipid->function == ISAPNP_FUNCTION(0xA1)) {					cs->subtyp = DIVA_IPAC_ISA;					cs->hw.diva.ctrl = 0;					cs->hw.diva.isac =						card->para[1] + DIVA_IPAC_DATA;					cs->hw.diva.hscx =						card->para[1] + DIVA_IPAC_DATA;					cs->hw.diva.isac_adr =						card->para[1] + DIVA_IPAC_ADR;					cs->hw.diva.hscx_adr =						card->para[1] + DIVA_IPAC_ADR;					test_and_set_bit(HW_IPAC, &cs->HW_Flags);				} else {					cs->subtyp = DIVA_ISA;					cs->hw.diva.ctrl =						card->para[1] + DIVA_ISA_CTRL;					cs->hw.diva.isac =						card->para[1] + DIVA_ISA_ISAC_DATA;					cs->hw.diva.hscx =						card->para[1] + DIVA_HSCX_DATA;					cs->hw.diva.isac_adr =						card->para[1] + DIVA_ISA_ISAC_ADR;					cs->hw.diva.hscx_adr =						card->para[1] + DIVA_HSCX_ADR;				}				return (1);		/* card found */			} else {				printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");				return(0);			}		}		ipid++;		pnp_c=NULL;	} 	return (-1);	/* card not found; continue search */}#else	/* if !ISAPNP */static int __devinit setup_diva_isapnp(struct IsdnCard *card){	return (-1);	/* card not found; continue search */}#endif	/* ISAPNP */#ifdef CONFIG_PCI_LEGACYstatic struct pci_dev *dev_diva __devinitdata = NULL;static struct pci_dev *dev_diva_u __devinitdata = NULL;static struct pci_dev *dev_diva201 __devinitdata = NULL;static struct pci_dev *dev_diva202 __devinitdata = NULL;static int __devinit setup_diva_pci(struct IsdnCard *card){	struct IsdnCardState *cs = card->cs;	cs->subtyp = 0;	if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON,		PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) {		if (pci_enable_device(dev_diva))			return(0);		cs->subtyp = DIVA_PCI;		cs->irq = dev_diva->irq;		cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);	} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,		PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {		if (pci_enable_device(dev_diva_u))			return(0);		cs->subtyp = DIVA_PCI;		cs->irq = dev_diva_u->irq;		cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);	} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,		PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {		if (pci_enable_device(dev_diva201))			return(0);		cs->subtyp = DIVA_IPAC_PCI;		cs->irq = dev_diva201->irq;		cs->hw.diva.pci_cfg =			(ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);		cs->hw.diva.cfg_reg =			(ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);	} else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,		PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {		if (pci_enable_device(dev_diva202))			return(0);		cs->subtyp = DIVA_IPACX_PCI;		cs->irq = dev_diva202->irq;		cs->hw.diva.pci_cfg =			(ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);		cs->hw.diva.cfg_reg =			(ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);	} else {		return (-1);	/* card not found; continue search */	}	if (!cs->irq) {		printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");		iounmap_diva(cs);		return(0);	}	if (!cs->hw.diva.cfg_reg) {		printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");		iounmap_diva(cs);		return(0);	}	cs->irq_flags |= IRQF_SHARED;	if ((cs->subtyp == DIVA_IPAC_PCI) ||	    (cs->subtyp == DIVA_IPACX_PCI)   ) {		cs->hw.diva.ctrl = 0;		cs->hw.diva.isac = 0;		cs->hw.diva.hscx = 0;		cs->hw.diva.isac_adr = 0;		cs->hw.diva.hscx_adr = 0;		test_and_set_bit(HW_IPAC, &cs->HW_Flags);	} else {		cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;		cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;		cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;		cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;		cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;	}	return (1);		/* card found */}#else	/* if !CONFIG_PCI_LEGACY */static int __devinit setup_diva_pci(struct IsdnCard *card){	return (-1);	/* card not found; continue search */}#endif	/* CONFIG_PCI_LEGACY */int __devinitsetup_diva(struct IsdnCard *card){	int rc, have_card = 0;	struct IsdnCardState *cs = card->cs;	char tmp[64];	strcpy(tmp, Diva_revision);	printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp));	if (cs->typ != ISDN_CTYPE_DIEHLDIVA)		return(0);	cs->hw.diva.status = 0;	rc = setup_diva_isa(card);	if (!rc)		return rc;	if (rc > 0) {		have_card = 1;		goto ready;	}	rc = setup_diva_isapnp(card);	if (!rc)		return rc;	if (rc > 0) {		have_card = 1;		goto ready;	}	rc = setup_diva_pci(card);	if (!rc)		return rc;	if (rc > 0)		have_card = 1;ready:	if (!have_card) {		printk(KERN_WARNING "Diva: No ISA, ISAPNP or PCI card found\n");		return(0);	}	return setup_diva_common(card->cs);}

⌨️ 快捷键说明

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