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);
		}
	}
}
Beispiel #2
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);
		}
	}
}
Beispiel #3
0
static int
disable_pots(struct w6692_ch *wch)
{
	struct w6692_hw *card = wch->bch.hw;

	if (!(card->fmask & pots))
		return -ENODEV;
	wch->b_mode &= ~(W_B_MODE_EPCM | W_B_MODE_BSW0);
	WriteW6692B(wch, W_B_MODE, wch->b_mode);
	WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
		W_B_CMDR_XRST);
	return 0;
}
Beispiel #4
0
static int
enable_pots(struct w6692_ch *wch)
{
	struct w6692_hw *card = wch->bch.hw;

	if ((!(card->fmask & pots)) ||
	    !test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
		return -ENODEV;
	wch->b_mode |= W_B_MODE_EPCM | W_B_MODE_BSW0;
	WriteW6692B(wch, W_B_MODE, wch->b_mode);
	WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
	card->pctl |= ((wch->bch.nr & 2) ? W_PCTL_PCX : 0);
	WriteW6692(card, W_PCTL, card->pctl);
	return 0;
}
Beispiel #5
0
static void
W6692_fill_Bfifo(struct w6692_ch *wch)
{
	struct w6692_hw *card = wch->bch.hw;
	int count;
	u8 *ptr, cmd = W_B_CMDR_RACT | W_B_CMDR_XMS;

	pr_debug("%s: fill Bfifo\n", card->name);
	if (!wch->bch.tx_skb)
		return;
	count = wch->bch.tx_skb->len - wch->bch.tx_idx;
	if (count <= 0)
		return;
	ptr = wch->bch.tx_skb->data + wch->bch.tx_idx;
	if (count > W_B_FIFO_THRESH)
		count = W_B_FIFO_THRESH;
	else if (test_bit(FLG_HDLC, &wch->bch.Flags))
		cmd |= W_B_CMDR_XME;

	pr_debug("%s: fill Bfifo%d/%d\n", card->name,
			count, wch->bch.tx_idx);
	wch->bch.tx_idx += count;
	outsb(wch->addr + W_B_XFIFO, ptr, count);
	WriteW6692B(wch, W_B_CMDR, cmd);
	if (debug & DEBUG_HW_DFIFO) {
		snprintf(card->log, 63, "B%1d-send %s %d ",
			wch->bch.nr, card->name, count);
		print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
	}
}
Beispiel #6
0
static int
w6692_mode(struct w6692_ch *wch, u32 pr)
{
	struct w6692_hw	*card;

	card = wch->bch.hw;
	pr_debug("%s: B%d protocol %x-->%x\n", card->name,
		wch->bch.nr, wch->bch.state, pr);
	switch (pr) {
	case ISDN_P_NONE:
		if ((card->fmask & pots) && (wch->b_mode & W_B_MODE_EPCM))
			disable_pots(wch);
		wch->b_mode = 0;
		mISDN_clear_bchannel(&wch->bch);
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
		test_and_clear_bit(FLG_HDLC, &wch->bch.Flags);
		test_and_clear_bit(FLG_TRANSPARENT, &wch->bch.Flags);
		break;
	case ISDN_P_B_RAW:
		wch->b_mode = W_B_MODE_MMS;
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_EXIM, 0);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
			W_B_CMDR_XRST);
		test_and_set_bit(FLG_TRANSPARENT, &wch->bch.Flags);
		break;
	case ISDN_P_B_HDLC:
		wch->b_mode = W_B_MODE_ITF;
		WriteW6692B(wch, W_B_MODE, wch->b_mode);
		WriteW6692B(wch, W_B_ADM1, 0xff);
		WriteW6692B(wch, W_B_ADM2, 0xff);
		WriteW6692B(wch, W_B_EXIM, 0);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT |
			W_B_CMDR_XRST);
		test_and_set_bit(FLG_HDLC, &wch->bch.Flags);
		break;
	default:
		pr_info("%s: protocol %x not known\n", card->name, pr);
		return -ENOPROTOOPT;
	}
	wch->bch.state = pr;
	return 0;
}
Beispiel #7
0
static void
W6692_empty_Bfifo(struct w6692_ch *wch, int count)
{
	struct w6692_hw *card = wch->bch.hw;
	u8 *ptr;

	pr_debug("%s: empty_Bfifo %d\n", card->name, count);
	if (unlikely(wch->bch.state == ISDN_P_NONE)) {
		pr_debug("%s: empty_Bfifo ISDN_P_NONE\n", card->name);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
		if (wch->bch.rx_skb)
			skb_trim(wch->bch.rx_skb, 0);
		return;
	}
	if (!wch->bch.rx_skb) {
		wch->bch.rx_skb = mI_alloc_skb(wch->bch.maxlen, GFP_ATOMIC);
		if (unlikely(!wch->bch.rx_skb)) {
			pr_info("%s: B receive out of memory\n", card->name);
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
				W_B_CMDR_RACT);
			return;
		}
	}
	if (wch->bch.rx_skb->len + count > wch->bch.maxlen) {
		pr_debug("%s: empty_Bfifo incoming packet too large\n",
			card->name);
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
		skb_trim(wch->bch.rx_skb, 0);
		return;
	}
	ptr = skb_put(wch->bch.rx_skb, count);
	insb(wch->addr + W_B_RFIFO, ptr, count);
	WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT);
	if (debug & DEBUG_HW_DFIFO) {
		snprintf(card->log, 63, "B%1d-recv %s %d ",
			wch->bch.nr, card->name, count);
		print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, ptr, count);
	}
}
Beispiel #8
0
static void
W6692B_interrupt(struct w6692_hw *card, int ch)
{
	struct w6692_ch	*wch = &card->bc[ch];
	int		count;
	u8		stat, star = 0;

	stat = ReadW6692B(wch, W_B_EXIR);
	pr_debug("%s: B%d EXIR %02x\n", card->name, wch->bch.nr, stat);
	if (stat & W_B_EXI_RME) {
		star = ReadW6692B(wch, W_B_STAR);
		if (star & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) {
			if ((star & W_B_STAR_RDOV) &&
			    test_bit(FLG_ACTIVE, &wch->bch.Flags)) {
				pr_debug("%s: B%d RDOV proto=%x\n", card->name,
					wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
				wch->bch.err_rdo++;
#endif
			}
			if (test_bit(FLG_HDLC, &wch->bch.Flags)) {
				if (star & W_B_STAR_CRCE) {
					pr_debug("%s: B%d CRC error\n",
						card->name, wch->bch.nr);
#ifdef ERROR_STATISTIC
					wch->bch.err_crc++;
#endif
				}
				if (star & W_B_STAR_RMB) {
					pr_debug("%s: B%d message abort\n",
						card->name, wch->bch.nr);
#ifdef ERROR_STATISTIC
					wch->bch.err_inv++;
#endif
				}
			}
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
				W_B_CMDR_RRST | W_B_CMDR_RACT);
			if (wch->bch.rx_skb)
				skb_trim(wch->bch.rx_skb, 0);
		} else {
			count = ReadW6692B(wch, W_B_RBCL) &
				(W_B_FIFO_THRESH - 1);
			if (count == 0)
				count = W_B_FIFO_THRESH;
			W6692_empty_Bfifo(wch, count);
			recv_Bchannel(&wch->bch, 0);
		}
	}
	if (stat & W_B_EXI_RMR) {
		if (!(stat & W_B_EXI_RME))
			star = ReadW6692B(wch, W_B_STAR);
		if (star & W_B_STAR_RDOV) {
			pr_debug("%s: B%d RDOV proto=%x\n", card->name,
				wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
			wch->bch.err_rdo++;
#endif
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
				W_B_CMDR_RRST | W_B_CMDR_RACT);
		} else {
			W6692_empty_Bfifo(wch, W_B_FIFO_THRESH);
			if (test_bit(FLG_TRANSPARENT, &wch->bch.Flags) &&
			    wch->bch.rx_skb && (wch->bch.rx_skb->len > 0))
				recv_Bchannel(&wch->bch, 0);
		}
	}
	if (stat & W_B_EXI_RDOV) {
		
		if (!(star & W_B_STAR_RDOV)) {
			pr_debug("%s: B%d RDOV IRQ proto=%x\n", card->name,
				wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
			wch->bch.err_rdo++;
#endif
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK |
				W_B_CMDR_RRST | W_B_CMDR_RACT);
		}
	}
	if (stat & W_B_EXI_XFR) {
		if (!(stat & (W_B_EXI_RME | W_B_EXI_RMR))) {
			star = ReadW6692B(wch, W_B_STAR);
			pr_debug("%s: B%d star %02x\n", card->name,
				wch->bch.nr, star);
		}
		if (star & W_B_STAR_XDOW) {
			pr_debug("%s: B%d XDOW proto=%x\n", card->name,
				wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
			wch->bch.err_xdu++;
#endif
			WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST |
				W_B_CMDR_RACT);
			
			if (wch->bch.tx_skb) {
				if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
					wch->bch.tx_idx = 0;
			}
		}
		send_next(wch);
		if (stat & W_B_EXI_XDUN)
			return; 
	}
	if (stat & W_B_EXI_XDUN) {
		pr_debug("%s: B%d XDUN proto=%x\n", card->name,
			wch->bch.nr, wch->bch.state);
#ifdef ERROR_STATISTIC
		wch->bch.err_xdu++;
#endif
		WriteW6692B(wch, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT);
		
		if (wch->bch.tx_skb) {
			if (!test_bit(FLG_TRANSPARENT, &wch->bch.Flags))
				wch->bch.tx_idx = 0;
		}
		send_next(wch);
	}
}