static void dbusy_timer_handler(struct dchannel *dch) { struct w6692_hw *card = dch->hw; int rbch, star; u_long flags; if (test_bit(FLG_BUSY_TIMER, &dch->Flags)) { spin_lock_irqsave(&card->lock, flags); rbch = ReadW6692(card, W_D_RBCH); star = ReadW6692(card, W_D_STAR); pr_debug("%s: D-Channel Busy RBCH %02x STAR %02x\n", card->name, rbch, star); if (star & W_D_STAR_XBZ) test_and_set_bit(FLG_L1_BUSY, &dch->Flags); else { test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags); if (dch->tx_idx) dch->tx_idx = 0; else pr_info("%s: W6692 D-Channel Busy no tx_idx\n", card->name); WriteW6692(card, W_D_CMDR, W_D_CMDR_XRST); } spin_unlock_irqrestore(&card->lock, flags); } }
static int setup_w6692(struct w6692_hw *card) { u32 val; if (!request_region(card->addr, 256, card->name)) { pr_info("%s: config port %x-%x already in use\n", card->name, card->addr, card->addr + 255); return -EIO; } W6692Version(card); card->bc[0].addr = card->addr; card->bc[1].addr = card->addr + 0x40; val = ReadW6692(card, W_ISTA); if (debug & DEBUG_HW) pr_notice("%s ISTA=%02x\n", card->name, val); val = ReadW6692(card, W_IMASK); if (debug & DEBUG_HW) pr_notice("%s IMASK=%02x\n", card->name, val); val = ReadW6692(card, W_D_EXIR); if (debug & DEBUG_HW) pr_notice("%s D_EXIR=%02x\n", card->name, val); val = ReadW6692(card, W_D_EXIM); if (debug & DEBUG_HW) pr_notice("%s D_EXIM=%02x\n", card->name, val); val = ReadW6692(card, W_D_RSTA); if (debug & DEBUG_HW) pr_notice("%s D_RSTA=%02x\n", card->name, val); return 0; }
static void handle_statusD(struct w6692_hw *card) { struct dchannel *dch = &card->dch; u8 exval, v1, cir; exval = ReadW6692(card, W_D_EXIR); pr_debug("%s: D_EXIR %02x\n", card->name, exval); if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { pr_debug("%s: D-channel underrun/collision\n", card->name); #ifdef ERROR_STATISTIC dch->err_tx++; #endif d_retransmit(card); } if (exval & W_D_EXI_RDOV) { pr_debug("%s: D-channel RDOV\n", card->name); WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST); } if (exval & W_D_EXI_TIN2) pr_debug("%s: spurious TIN2 interrupt\n", card->name); if (exval & W_D_EXI_MOC) { v1 = ReadW6692(card, W_MOSR); pr_debug("%s: spurious MOC interrupt MOSR %02x\n", card->name, v1); } if (exval & W_D_EXI_ISC) { cir = ReadW6692(card, W_CIR); pr_debug("%s: ISC CIR %02X\n", card->name, cir); if (cir & W_CIR_ICC) { v1 = cir & W_CIR_COD_MASK; pr_debug("%s: ph_state_change %x -> %x\n", card->name, dch->state, v1); card->state = v1; if (card->fmask & led) { switch (v1) { case W_L1IND_AI8: case W_L1IND_AI10: w6692_led_handler(card, 1); break; default: w6692_led_handler(card, 0); break; } } W6692_new_ph(card); } if (cir & W_CIR_SCC) { v1 = ReadW6692(card, W_SQR); pr_debug("%s: SCC SQR %02X\n", card->name, v1); } } if (exval & W_D_EXI_WEXP) pr_debug("%s: spurious WEXP interrupt!\n", card->name); if (exval & W_D_EXI_TEXP) pr_debug("%s: spurious TEXP interrupt!\n", card->name); }
static irqreturn_t w6692_irq(int intno, void *dev_id) { struct w6692_hw *card = dev_id; u8 ista; spin_lock(&card->lock); ista = ReadW6692(card, W_ISTA); if ((ista | card->imask) == card->imask) { spin_unlock(&card->lock); return IRQ_NONE; } card->irqcnt++; pr_debug("%s: ista %02x\n", card->name, ista); ista &= ~card->imask; if (ista & W_INT_B1_EXI) W6692B_interrupt(card, 0); if (ista & W_INT_B2_EXI) W6692B_interrupt(card, 1); if (ista & W_INT_D_RME) handle_rxD(card); if (ista & W_INT_D_RMR) W6692_empty_Dfifo(card, W_D_FIFO_THRESH); if (ista & W_INT_D_XFR) handle_txD(card); if (ista & W_INT_D_EXI) handle_statusD(card); if (ista & (W_INT_XINT0 | W_INT_XINT1)) pr_debug("%s: W6692 spurious XINT!\n", card->name); spin_unlock(&card->lock); return IRQ_HANDLED; }
static void W6692Version(struct w6692_hw *card) { int val; val = ReadW6692(card, W_D_RBCH); pr_notice("%s: Winbond W6692 version: %s\n", card->name, W6692Ver[(val >> 6) & 3]); }
void initW6692(struct w6692_hw *card) { u8 val; card->dch.timer.function = (void *)dbusy_timer_handler; card->dch.timer.data = (u_long)&card->dch; init_timer(&card->dch.timer); w6692_mode(&card->bc[0], ISDN_P_NONE); w6692_mode(&card->bc[1], ISDN_P_NONE); WriteW6692(card, W_D_CTL, 0x00); disable_hwirq(card); WriteW6692(card, W_D_SAM, 0xff); WriteW6692(card, W_D_TAM, 0xff); WriteW6692(card, W_D_MODE, W_D_MODE_RACT); card->state = W_L1CMD_RST; ph_command(card, W_L1CMD_RST); ph_command(card, W_L1CMD_ECK); /* enable all IRQ but extern */ card->imask = 0x18; WriteW6692(card, W_D_EXIM, 0x00); WriteW6692B(&card->bc[0], W_B_EXIM, 0); WriteW6692B(&card->bc[1], W_B_EXIM, 0); /* Reset D-chan receiver and transmitter */ WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); /* Reset B-chan receiver and transmitter */ WriteW6692B(&card->bc[0], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); WriteW6692B(&card->bc[1], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); /* enable peripheral */ if (card->subtype == W6692_USR) { /* seems that USR implemented some power control features * Pin 79 is connected to the oscilator circuit so we * have to handle it here */ card->pctl = 0x80; card->xdata = 0; WriteW6692(card, W_PCTL, card->pctl); WriteW6692(card, W_XDATA, card->xdata); } else { card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0; card->xaddr = 0x00;/* all sw off */ if (card->fmask & pots) card->xdata |= 0x06; /* POWER UP/ LED OFF / ALAW */ if (card->fmask & led) card->xdata |= 0x04; /* LED OFF */ if ((card->fmask & pots) || (card->fmask & led)) { WriteW6692(card, W_PCTL, card->pctl); WriteW6692(card, W_XADDR, card->xaddr); WriteW6692(card, W_XDATA, card->xdata); val = ReadW6692(card, W_XADDR); if (debug & DEBUG_HW) pr_notice("%s: W_XADDR=%02x\n", card->name, val); } } }
void initW6692(struct w6692_hw *card) { u8 val; card->dch.timer.function = (void *)dbusy_timer_handler; card->dch.timer.data = (u_long)&card->dch; init_timer(&card->dch.timer); w6692_mode(&card->bc[0], ISDN_P_NONE); w6692_mode(&card->bc[1], ISDN_P_NONE); WriteW6692(card, W_D_CTL, 0x00); disable_hwirq(card); WriteW6692(card, W_D_SAM, 0xff); WriteW6692(card, W_D_TAM, 0xff); WriteW6692(card, W_D_MODE, W_D_MODE_RACT); card->state = W_L1CMD_RST; ph_command(card, W_L1CMD_RST); ph_command(card, W_L1CMD_ECK); card->imask = 0x18; WriteW6692(card, W_D_EXIM, 0x00); WriteW6692B(&card->bc[0], W_B_EXIM, 0); WriteW6692B(&card->bc[1], W_B_EXIM, 0); WriteW6692(card, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); WriteW6692B(&card->bc[0], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); WriteW6692B(&card->bc[1], W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST); if (card->subtype == W6692_USR) { card->pctl = 0x80; card->xdata = 0; WriteW6692(card, W_PCTL, card->pctl); WriteW6692(card, W_XDATA, card->xdata); } else { card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0; card->xaddr = 0x00; if (card->fmask & pots) card->xdata |= 0x06; if (card->fmask & led) card->xdata |= 0x04; if ((card->fmask & pots) || (card->fmask & led)) { WriteW6692(card, W_PCTL, card->pctl); WriteW6692(card, W_XADDR, card->xaddr); WriteW6692(card, W_XDATA, card->xdata); val = ReadW6692(card, W_XADDR); if (debug & DEBUG_HW) pr_notice("%s: W_XADDR=%02x\n", card->name, val); } } }
static void handle_rxD(struct w6692_hw *card) { u8 stat; int count; stat = ReadW6692(card, W_D_RSTA); if (stat & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { if (stat & W_D_RSTA_RDOV) { pr_debug("%s: D-channel RDOV\n", card->name); #ifdef ERROR_STATISTIC card->dch.err_rx++; #endif } if (stat & W_D_RSTA_CRCE) { pr_debug("%s: D-channel CRC error\n", card->name); #ifdef ERROR_STATISTIC card->dch.err_crc++; #endif } if (stat & W_D_RSTA_RMB) { pr_debug("%s: D-channel ABORT\n", card->name); #ifdef ERROR_STATISTIC card->dch.err_rx++; #endif } if (card->dch.rx_skb) dev_kfree_skb(card->dch.rx_skb); card->dch.rx_skb = NULL; WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); } else { count = ReadW6692(card, W_D_RBCL) & (W_D_FIFO_THRESH - 1); if (count == 0) count = W_D_FIFO_THRESH; W6692_empty_Dfifo(card, count); recv_Dchannel(&card->dch); } }
int __init setup_w6692(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; u_char found = 0; u_char pci_irq = 0; u_int pci_ioaddr = 0; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, w6692_revision); printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_W6692) return (0); #if CONFIG_PCI if (!pci_present()) { printk(KERN_ERR "W6692: no PCI bus present\n"); return (0); } while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { if (pci_enable_device(dev_w6692)) continue; cs->subtyp = id_idx; break; } id_idx++; } if (dev_w6692) { found = 1; pci_irq = dev_w6692->irq; /* I think address 0 is allways the configuration area */ /* and address 1 is the real IO space KKe 03.09.99 */ pci_ioaddr = pci_resource_start(dev_w6692, 1); /* USR ISDN PCI card TA need some special handling */ if (cs->subtyp == W6692_WINBOND) { if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && (W6692_SD_USR == dev_w6692->subsystem_device)) { cs->subtyp = W6692_USR; } } } if (!found) { printk(KERN_WARNING "W6692: No PCI card found\n"); return (0); } cs->irq = pci_irq; if (!cs->irq) { printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); return (0); } if (!pci_ioaddr) { printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); return (0); } cs->hw.w6692.iobase = pci_ioaddr; printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, pci_ioaddr, pci_irq); if (check_region((cs->hw.w6692.iobase), 256)) { printk(KERN_WARNING "HiSax: %s I/O ports %x-%x already in use\n", id_list[cs->subtyp].card_name, cs->hw.w6692.iobase, cs->hw.w6692.iobase + 255); return (0); } else { request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name); } #else printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); printk(KERN_WARNING "HiSax: W6692 unable to config\n"); return (0); #endif /* CONFIG_PCI */ printk(KERN_INFO "HiSax: %s config irq:%d I/O:%x\n", id_list[cs->subtyp].card_name, cs->irq, cs->hw.w6692.iobase); cs->readW6692 = &ReadW6692; cs->writeW6692 = &WriteW6692; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadW6692B; cs->BC_Write_Reg = &WriteW6692B; cs->BC_Send_Data = &W6692B_fill_fifo; cs->cardmsg = &w6692_card_msg; cs->irq_func = &W6692_interrupt; cs->irq_flags |= SA_SHIRQ; W6692Version(cs, "W6692:"); printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); return (1); }
__initfunc(int setup_w6692(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; u_char found = 0; u_char pci_irq = 0; u_int pci_ioaddr = 0; strcpy(tmp, w6692_revision); printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_W6692) return (0); #if CONFIG_PCI if (!pci_present()) { printk(KERN_ERR "W6692: no PCI bus present\n"); return (0); } while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); if (dev_w6692) break; id_idx++; } if (dev_w6692) { found = 1; pci_irq = dev_w6692->irq; /* I think address 0 is allways the configuration area */ /* and address 1 is the real IO space KKe 03.09.99 */ pci_ioaddr = dev_w6692->base_address[ 1]; } if (!found) { printk(KERN_WARNING "W6692: No PCI card found\n"); return (0); } cs->irq = pci_irq; if (!cs->irq) { printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); return (0); } pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; if (!pci_ioaddr) { printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); return (0); } cs->hw.w6692.iobase = pci_ioaddr; printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", id_list[id_idx].vendor_name, id_list[id_idx].card_name, pci_ioaddr, dev_w6692->irq); if (check_region((cs->hw.w6692.iobase), 256)) { printk(KERN_WARNING "HiSax: %s I/O ports %x-%x already in use\n", id_list[id_idx].card_name, cs->hw.w6692.iobase, cs->hw.w6692.iobase + 255); return (0); } else { request_region(cs->hw.w6692.iobase, 256, id_list[id_idx].card_name); } #else printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); printk(KERN_WARNING "HiSax: W6692 unable to config\n"); return (0); #endif /* CONFIG_PCI */ printk(KERN_INFO "HiSax: %s config irq:%d I/O:%x\n", id_list[id_idx].card_name, cs->irq, cs->hw.w6692.iobase); cs->readW6692 = &ReadW6692; cs->writeW6692 = &WriteW6692; cs->readisacfifo = &ReadISACfifo; cs->writeisacfifo = &WriteISACfifo; cs->BC_Read_Reg = &ReadW6692B; cs->BC_Write_Reg = &WriteW6692B; cs->BC_Send_Data = &W6692B_fill_fifo; cs->cardmsg = &w6692_card_msg; cs->irq_func = &W6692_interrupt; W6692Version(cs, "W6692:"); printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); return (1); }