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

📄 elsa.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	int icnt=5;	if (!cs) {		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");		return;	}	if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) {		val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */		if (!(val & ELSA_PCI_IRQ_MASK))			return;	}#if ARCOFI_USE	if (cs->hw.elsa.MFlag) {		val = serial_inp(cs, UART_IIR);		if (!(val & UART_IIR_NO_INT)) {			debugl1(cs,"IIR %02x", val);			rs_interrupt_elsa(intno, cs);		}	}#endif	ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);Start_IPAC:	if (cs->debug & L1_DEB_IPAC)		debugl1(cs, "IPAC ISTA %02X", ista);	if (ista & 0x0f) {		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);		if (ista & 0x01)			val |= 0x01;		if (ista & 0x04)			val |= 0x02;		if (ista & 0x08)			val |= 0x04;		if (val)			hscx_int_main(cs, val);	}	if (ista & 0x20) {		val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80);		if (val) {			isac_interrupt(cs, val);		}	}	if (ista & 0x10) {		val = 0x01;		isac_interrupt(cs, val);	}	ista  = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);	if ((ista & 0x3f) && icnt) {		icnt--;		goto Start_IPAC;	}	if (!icnt)		printk(KERN_WARNING "ELSA IRQ LOOP\n");	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF);	writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0);}voidrelease_io_elsa(struct IsdnCardState *cs){	int bytecnt = 8;	del_timer(&cs->hw.elsa.tl);#if ARCOFI_USE	clear_arcofi(cs);#endif	if (cs->hw.elsa.ctrl)		byteout(cs->hw.elsa.ctrl, 0);	/* LEDs Out */	if (cs->subtyp == ELSA_QS1000PCI) {		byteout(cs->hw.elsa.cfg + 0x4c, 0x01);  /* disable IRQ */		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);		bytecnt = 2;		release_region(cs->hw.elsa.cfg, 0x80);	}	if (cs->subtyp == ELSA_QS3000PCI) {		byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);		release_region(cs->hw.elsa.cfg, 0x80);	} 	if (cs->subtyp == ELSA_PCMCIA_IPAC) {		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); 	}	if ((cs->subtyp == ELSA_PCFPRO) ||		(cs->subtyp == ELSA_QS3000) ||		(cs->subtyp == ELSA_PCF) ||		(cs->subtyp == ELSA_QS3000PCI)) {		bytecnt = 16;#if ARCOFI_USE		release_modem(cs);#endif	}	if (cs->hw.elsa.base)		release_region(cs->hw.elsa.base, bytecnt);}static voidreset_elsa(struct IsdnCardState *cs){	long flags;	if (cs->hw.elsa.timer) {		/* Wait 1 Timer */		byteout(cs->hw.elsa.timer, 0);		while (TimerRun(cs));		cs->hw.elsa.ctrl_reg |= 0x50;		cs->hw.elsa.ctrl_reg &= ~ELSA_ISDN_RESET;	/* Reset On */		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);		/* Wait 1 Timer */		byteout(cs->hw.elsa.timer, 0);		while (TimerRun(cs));		cs->hw.elsa.ctrl_reg |= ELSA_ISDN_RESET;	/* Reset Off */		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);		/* Wait 1 Timer */		byteout(cs->hw.elsa.timer, 0);		while (TimerRun(cs));		if (cs->hw.elsa.trig)			byteout(cs->hw.elsa.trig, 0xff);	}	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) {		save_flags(flags);		sti();		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);		set_current_state(TASK_UNINTERRUPTIBLE);		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);		set_current_state(TASK_UNINTERRUPTIBLE);		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */		restore_flags(flags);		if (cs->subtyp != ELSA_PCMCIA_IPAC) {			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);		} else {			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10);			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4);			writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8);		}		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);		if (cs->subtyp == ELSA_QS1000PCI)			byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */		else if (cs->subtyp == ELSA_QS3000PCI)			byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */	}}#if ARCOFI_USEstatic voidset_arcofi(struct IsdnCardState *cs, int bc) {	cs->dc.isac.arcofi_bc = bc;	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);}static intcheck_arcofi(struct IsdnCardState *cs){	int arcofi_present = 0;	char tmp[40];	char *t;	u_char *p;	if (!cs->dc.isac.mon_tx)		if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {			if (cs->debug & L1_DEB_WARN)				debugl1(cs, "ISAC MON TX out of buffers!");			return(0);		}	cs->dc.isac.arcofi_bc = 0;	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);	if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {			debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);			p = cs->dc.isac.mon_rx;			t = tmp;			t += sprintf(tmp, "Arcofi data");			QuickHex(t, p, cs->dc.isac.mon_rxp);			debugl1(cs, tmp);			if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {				switch(cs->dc.isac.mon_rx[1]) {					case 0x80:						debugl1(cs, "Arcofi 2160 detected");						arcofi_present = 1;						break;					case 0x82:						debugl1(cs, "Arcofi 2165 detected");						arcofi_present = 2;						break;					case 0x84:						debugl1(cs, "Arcofi 2163 detected");						arcofi_present = 3;						break;					default:						debugl1(cs, "unknown Arcofi response");						break;				}			} else				debugl1(cs, "undefined Monitor response");			cs->dc.isac.mon_rxp = 0;	} else if (cs->dc.isac.mon_tx) {		debugl1(cs, "Arcofi not detected");	}	if (arcofi_present) {		if (cs->subtyp==ELSA_QS1000) {			cs->subtyp = ELSA_QS3000;			printk(KERN_INFO				"Elsa: %s detected modem at 0x%x\n",				Elsa_Types[cs->subtyp],				cs->hw.elsa.base+8);			release_region(cs->hw.elsa.base, 8);			if (check_region(cs->hw.elsa.base, 16)) {				printk(KERN_WARNING				"HiSax: %s config port %x-%x already in use\n",				Elsa_Types[cs->subtyp],				cs->hw.elsa.base + 8,				cs->hw.elsa.base + 16);			} else				request_region(cs->hw.elsa.base, 16,					"elsa isdn modem");		} else if (cs->subtyp==ELSA_PCC16) {			cs->subtyp = ELSA_PCF;			printk(KERN_INFO				"Elsa: %s detected modem at 0x%x\n",				Elsa_Types[cs->subtyp],				cs->hw.elsa.base+8);			release_region(cs->hw.elsa.base, 8);			if (check_region(cs->hw.elsa.base, 16)) {				printk(KERN_WARNING				"HiSax: %s config port %x-%x already in use\n",				Elsa_Types[cs->subtyp],				cs->hw.elsa.base + 8,				cs->hw.elsa.base + 16);			} else				request_region(cs->hw.elsa.base, 16,					"elsa isdn modem");		} else			printk(KERN_INFO				"Elsa: %s detected modem at 0x%x\n",				Elsa_Types[cs->subtyp],				cs->hw.elsa.base+8);		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);		interruptible_sleep_on(&cs->dc.isac.arcofi_wait);		return(1);	}	return(0);}#endif /* ARCOFI_USE */static voidelsa_led_handler(struct IsdnCardState *cs){	int blink = 0;	if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC)		return;	del_timer(&cs->hw.elsa.tl);	if (cs->hw.elsa.status & ELSA_ASSIGN)		cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED;	else if (cs->hw.elsa.status & ELSA_BAD_PWR)		cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED;	else {		cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED;		blink = 250;	}	if (cs->hw.elsa.status & 0xf000)		cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED;	else if (cs->hw.elsa.status & 0x0f00) {		cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED;		blink = 500;	} else		cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED;	if ((cs->subtyp == ELSA_QS1000PCI) ||		(cs->subtyp == ELSA_QS3000PCI)) {		u_char led = 0xff;		if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED)			led ^= ELSA_IPAC_LINE_LED;		if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED)			led ^= ELSA_IPAC_STAT_LED;		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led);	} else		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);	if (blink) {		init_timer(&cs->hw.elsa.tl);		cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);		add_timer(&cs->hw.elsa.tl);	}}static intElsa_card_msg(struct IsdnCardState *cs, int mt, void *arg){	int ret = 0;	long flags;	switch (mt) {		case CARD_RESET:			reset_elsa(cs);			return(0);		case CARD_RELEASE:			release_io_elsa(cs);			return(0);		case CARD_INIT:			cs->debug |= L1_DEB_IPAC;			inithscxisac(cs, 1);			if ((cs->subtyp == ELSA_QS1000) ||			    (cs->subtyp == ELSA_QS3000))			{				byteout(cs->hw.elsa.timer, 0);			}			if (cs->hw.elsa.trig)				byteout(cs->hw.elsa.trig, 0xff);			inithscxisac(cs, 2);			return(0);		case CARD_TEST:			if ((cs->subtyp == ELSA_PCMCIA) ||				(cs->subtyp == ELSA_PCMCIA_IPAC) ||				(cs->subtyp == ELSA_QS1000PCI)) {				return(0);			} else if (cs->subtyp == ELSA_QS3000PCI) {				ret = 0;			} else {				save_flags(flags);				cs->hw.elsa.counter = 0;				sti();				cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT;				cs->hw.elsa.status |= ELSA_TIMER_AKTIV;				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);				byteout(cs->hw.elsa.timer, 0);				set_current_state(TASK_UNINTERRUPTIBLE);				schedule_timeout((110*HZ)/1000);				restore_flags(flags);				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);				cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;				printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",				       cs->hw.elsa.counter);				if ((cs->hw.elsa.counter > 10) &&					(cs->hw.elsa.counter < 16)) {					printk(KERN_INFO "Elsa: timer and irq OK\n");					ret = 0;				} else {					printk(KERN_WARNING					       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",					       cs->hw.elsa.counter, cs->irq);					ret = 1;				}			}#if ARCOFI_USE			if (check_arcofi(cs)) {				init_modem(cs);			}#endif			elsa_led_handler(cs);			return(ret);		case (MDL_REMOVE | REQUEST):			cs->hw.elsa.status &= 0;			break;		case (MDL_ASSIGN | REQUEST):			cs->hw.elsa.status |= ELSA_ASSIGN;			break;		case MDL_INFO_SETUP:			if ((long) arg)				cs->hw.elsa.status |= 0x0200;			else				cs->hw.elsa.status |= 0x0100;			break;		case MDL_INFO_CONN:			if ((long) arg)				cs->hw.elsa.status |= 0x2000;			else				cs->hw.elsa.status |= 0x1000;			break;		case MDL_INFO_REL:			if ((long) arg) {				cs->hw.elsa.status &= ~0x2000;				cs->hw.elsa.status &= ~0x0200;			} else {				cs->hw.elsa.status &= ~0x1000;				cs->hw.elsa.status &= ~0x0100;			}			break;#if ARCOFI_USE		case CARD_AUX_IND:			if (cs->hw.elsa.MFlag) {				int len;				u_char *msg;

⌨️ 快捷键说明

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