Exemplo n.º 1
0
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);
	}
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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]);
}
Exemplo n.º 6
0
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);
		}
	}
}
Exemplo n.º 7
0
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);
		}
	}
}
Exemplo n.º 8
0
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);
}
Exemplo n.º 10
0
__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);
}