📄 diva.c
字号:
goto Start_IPAC; } if (!icnt) printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);}voidrelease_io_diva(struct IsdnCardState *cs){ int bytecnt; if (cs->subtyp != DIVA_IPAC_ISA) { del_timer(&cs->hw.diva.tl); if (cs->hw.diva.cfg_reg) byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ } if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) bytecnt = 8; else bytecnt = 32; if (cs->hw.diva.cfg_reg) { release_region(cs->hw.diva.cfg_reg, bytecnt); }}static voidreset_diva(struct IsdnCardState *cs){ long flags; save_flags(flags); sti(); if (cs->subtyp == DIVA_IPAC_ISA) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); schedule(); } else { cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); current->state = TASK_INTERRUPTIBLE; current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */ schedule(); if (cs->subtyp == DIVA_ISA) cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; else cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); } restore_flags(flags);}#define DIVA_ASSIGN 1static voiddiva_led_handler(struct IsdnCardState *cs){ int blink = 0; if (cs->subtyp == DIVA_IPAC_ISA) return; del_timer(&cs->hw.diva.tl); if (cs->hw.diva.status & DIVA_ASSIGN) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_A : DIVA_PCI_LED_A; else { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_A : DIVA_PCI_LED_A; blink = 250; } if (cs->hw.diva.status & 0xf000) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; else if (cs->hw.diva.status & 0x0f00) { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; blink = 500; } else cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B); byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); if (blink) { init_timer(&cs->hw.diva.tl); cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); add_timer(&cs->hw.diva.tl); }}static intDiva_card_msg(struct IsdnCardState *cs, int mt, void *arg){ u_int irq_flag = I4L_IRQ_FLAG; switch (mt) { case CARD_RESET: reset_diva(cs); return(0); case CARD_RELEASE: release_io_diva(cs); return(0); case CARD_SETIRQ: if (cs->subtyp == DIVA_PCI) irq_flag |= SA_SHIRQ; if (cs->subtyp == DIVA_IPAC_ISA) { return(request_irq(cs->irq, &diva_interrupt_ipac, irq_flag, "HiSax", cs)); } else { return(request_irq(cs->irq, &diva_interrupt, irq_flag, "HiSax", cs)); } case CARD_INIT: inithscxisac(cs, 3); 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) diva_led_handler(cs); return(0);}static int pci_index __initdata = 0;__initfunc(intsetup_diva(struct IsdnCard *card)){ int bytecnt; u_char val; 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; if (card->para[1]) { 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) { 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]; bytecnt = 8; } else {#if CONFIG_PCI u_char pci_bus, pci_device_fn, pci_irq; u_int pci_ioaddr; cs->subtyp = 0; for (; pci_index < 0xff; pci_index++) { if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn) == PCIBIOS_SUCCESSFUL) cs->subtyp = DIVA_PCI; else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn) == PCIBIOS_SUCCESSFUL) cs->subtyp = DIVA_PCI; else break; /* get IRQ */ pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq); /* get IO address */ pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr); if (cs->subtyp) break; } if (!cs->subtyp) { printk(KERN_WARNING "Diva: No PCI card found\n"); return(0); } pci_index++; if (!pci_irq) { printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); return(0); } if (!pci_ioaddr) { printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); return(0); } pci_ioaddr &= ~3; /* remove io/mem flag */ cs->hw.diva.cfg_reg = pci_ioaddr; cs->hw.diva.ctrl = pci_ioaddr + DIVA_PCI_CTRL; cs->hw.diva.isac = pci_ioaddr + DIVA_PCI_ISAC_DATA; cs->hw.diva.hscx = pci_ioaddr + DIVA_HSCX_DATA; cs->hw.diva.isac_adr = pci_ioaddr + DIVA_PCI_ISAC_ADR; cs->hw.diva.hscx_adr = pci_ioaddr + DIVA_HSCX_ADR; cs->irq = pci_irq; bytecnt = 32;#else printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); return (0);#endif /* CONFIG_PCI */ } printk(KERN_INFO "Diva: %s card configured at 0x%x IRQ %d\n", (cs->subtyp == DIVA_PCI) ? "PCI" : (cs->subtyp == DIVA_ISA) ? "ISA" : "IPAC", cs->hw.diva.cfg_reg, cs->irq); if (check_region(cs->hw.diva.cfg_reg, bytecnt)) { printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[card->typ], cs->hw.diva.cfg_reg, cs->hw.diva.cfg_reg + bytecnt); return (0); } else { request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn"); } reset_diva(cs); cs->BC_Read_Reg = &ReadHSCX; cs->BC_Write_Reg = &WriteHSCX; cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Diva_card_msg; if (cs->subtyp == DIVA_IPAC_ISA) { cs->readisac = &ReadISAC_IPAC; cs->writeisac = &WriteISAC_IPAC; cs->readisacfifo = &ReadISACfifo_IPAC; cs->writeisacfifo = &WriteISACfifo_IPAC; val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); printk(KERN_INFO "Diva: IPAC version %x\n", val); } else { 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; 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -