📄 elsa.c
字号:
} if (!icnt) printk(KERN_WARNING"ELSA IRQ LOOP\n"); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF); if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) { if (!TimerRun(cs)) { /* Timer Restart */ byteout(cs->hw.elsa.timer, 0); cs->hw.elsa.counter++; } } if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_MCR); val ^= 0x8; serial_outp(cs, UART_MCR, val); val = serial_inp(cs, UART_MCR); val ^= 0x8; serial_outp(cs, UART_MCR, val); } if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0);}static voidelsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs){ struct IsdnCardState *cs = dev_id; u_char ista,val; int icnt=20; if (!cs) { printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); return; } 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 (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_PCFPRO) || (cs->subtyp == ELSA_QS3000) || (cs->subtyp == ELSA_PCF) || (cs->subtyp == ELSA_QS3000PCI)) { bytecnt = 16; release_modem(cs); } 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)) { save_flags(flags); sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); schedule(); restore_flags(flags); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); 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 */ }}static voidinit_arcofi(struct IsdnCardState *cs) { send_arcofi(cs, ARCOFI_XOP_0, 1, 0);/* send_arcofi(cs, ARCOFI_XOP_F, 1);*/}#define ARCDEL 500static voidset_arcofi(struct IsdnCardState *cs, int bc) { long flags; debugl1(cs,"set_arcofi bc=%d", bc); save_flags(flags); sti(); send_arcofi(cs, ARCOFI_XOP_0, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_COP_5, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_COP_6, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_COP_7, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_COP_8, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_COP_9, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_SOP_F, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_XOP_1, bc, 0); udelay(ARCDEL); send_arcofi(cs, ARCOFI_XOP_F, bc, 0); restore_flags(flags); debugl1(cs,"end set_arcofi bc=%d", bc);}static intcheck_arcofi(struct IsdnCardState *cs){#if ARCOFI_USE int arcofi_present = 0; char tmp[40]; char *t; u_char *p; if (!cs->mon_tx) if (!(cs->mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON TX out of buffers!"); return(0); } send_arcofi(cs, ARCOFI_VERSION, 0, 1); if (test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags)) { if (test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags)) { debugl1(cs, "Arcofi response received %d bytes", cs->mon_rxp); p = cs->mon_rx; t = tmp; t += sprintf(tmp, "Arcofi data"); QuickHex(t, p, cs->mon_rxp); debugl1(cs, tmp); if ((cs->mon_rxp == 2) && (cs->mon_rx[0] == 0xa0)) { switch(cs->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->mon_rxp = 0; } } else if (cs->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); init_arcofi(cs); return(1); }#endif return(0);}static voidelsa_led_handler(struct IsdnCardState *cs){ int blink = 0; if (cs->subtyp == ELSA_PCMCIA) 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 len, ret = 0; u_char *msg; long flags; switch (mt) { case CARD_RESET: reset_elsa(cs); return(0); case CARD_RELEASE: release_io_elsa(cs); return(0); case CARD_SETIRQ: if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) ret = request_irq(cs->irq, &elsa_interrupt_ipac, I4L_IRQ_FLAG | SA_SHIRQ, "HiSax", cs); else ret = request_irq(cs->irq, &elsa_interrupt, I4L_IRQ_FLAG, "HiSax", cs); return(ret); 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_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); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (110 * HZ) / 1000; /* Timeout 110ms */ schedule(); 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 (abs(cs->hw.elsa.counter - 13) < 3) { 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -