void __init initW6692(struct IsdnCardState *cs, int part)
{
	if (part & 1) {
		cs->tqueue.routine = (void *) (void *) W6692_bh;
		cs->setstack_d = setstack_W6692;
		cs->DC_Close = DC_Close_W6692;
		cs->dbusytimer.function = (void *) dbusy_timer_handler;
		cs->dbusytimer.data = (long) cs;
		init_timer(&cs->dbusytimer);
		resetW6692(cs);
		ph_command(cs, W_L1CMD_RST);
		cs->dc.w6692.ph_state = W_L1CMD_RST;
		W6692_new_ph(cs);
		ph_command(cs, W_L1CMD_ECK);

		cs->bcs[0].BC_SetStack = setstack_w6692;
		cs->bcs[1].BC_SetStack = setstack_w6692;
		cs->bcs[0].BC_Close = close_w6692state;
		cs->bcs[1].BC_Close = close_w6692state;
		W6692Bmode(cs->bcs, 0, 0);
		W6692Bmode(cs->bcs + 1, 0, 0);
	}
	if (part & 2) {
		/* Reenable all IRQ */
		cs->writeW6692(cs, W_IMASK, 0x18);
		cs->writeW6692(cs, W_D_EXIM, 0x00);
		cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00);
		cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00);
		/* Reset D-chan receiver and transmitter */
		cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST);
	}
}
static void
W6692_bh(struct IsdnCardState *cs)
{
	struct PStack *stptr;

	if (!cs)
		return;
	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
		if (cs->debug)
			debugl1(cs, "D-Channel Busy cleared");
		stptr = cs->stlist;
		while (stptr != NULL) {
			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
			stptr = stptr->next;
		}
	}
	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
		W6692_new_ph(cs);
	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
		DChannel_proc_rcv(cs);
	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
		DChannel_proc_xmt(cs);
/*
   if (test_and_clear_bit(D_RX_MON1, &cs->event))
   arcofi_fsm(cs, ARCOFI_RX_END, NULL);
   if (test_and_clear_bit(D_TX_MON1, &cs->event))
   arcofi_fsm(cs, ARCOFI_TX_END, NULL);
 */
}
Beispiel #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);
}
static void
W6692_l1hw(struct PStack *st, int pr, void *arg)
{
	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
	struct sk_buff *skb = arg;
	int val;

	switch (pr) {
		case (PH_DATA | REQUEST):
			if (cs->debug & DEB_DLOG_HEX)
				LogFrame(cs, skb->data, skb->len);
			if (cs->debug & DEB_DLOG_VERBOSE)
				dlogframe(cs, skb, 0);
			if (cs->tx_skb) {
				skb_queue_tail(&cs->sq, skb);
#ifdef L2FRAME_DEBUG		/* psa */
				if (cs->debug & L1_DEB_LAPD)
					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
#endif
			} else {
				cs->tx_skb = skb;
				cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG		/* psa */
				if (cs->debug & L1_DEB_LAPD)
					Logl2Frame(cs, skb, "PH_DATA", 0);
#endif
				W6692_fill_fifo(cs);
			}
			break;
		case (PH_PULL | INDICATION):
			if (cs->tx_skb) {
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
				skb_queue_tail(&cs->sq, skb);
				break;
			}
			if (cs->debug & DEB_DLOG_HEX)
				LogFrame(cs, skb->data, skb->len);
			if (cs->debug & DEB_DLOG_VERBOSE)
				dlogframe(cs, skb, 0);
			cs->tx_skb = skb;
			cs->tx_cnt = 0;
#ifdef L2FRAME_DEBUG		/* psa */
			if (cs->debug & L1_DEB_LAPD)
				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
#endif
			W6692_fill_fifo(cs);
			break;
		case (PH_PULL | REQUEST):
#ifdef L2FRAME_DEBUG		/* psa */
			if (cs->debug & L1_DEB_LAPD)
				debugl1(cs, "-> PH_REQUEST_PULL");
#endif
			if (!cs->tx_skb) {
				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
			} else
				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
			break;
		case (HW_RESET | REQUEST):
			if ((cs->dc.w6692.ph_state == W_L1IND_DRD))
				ph_command(cs, W_L1CMD_ECK);
			else {
				ph_command(cs, W_L1CMD_RST);
				cs->dc.w6692.ph_state = W_L1CMD_RST;
				W6692_new_ph(cs);
			}
			break;
		case (HW_ENABLE | REQUEST):
			ph_command(cs, W_L1CMD_ECK);
			break;
		case (HW_INFO3 | REQUEST):
			ph_command(cs, W_L1CMD_AR8);
			break;
		case (HW_TESTLOOP | REQUEST):
			val = 0;
			if (1 & (long) arg)
				val |= 0x0c;
			if (2 & (long) arg)
				val |= 0x3;
			/* !!! not implemented yet */
			break;
		case (HW_DEACTIVATE | RESPONSE):
			skb_queue_purge(&cs->rq);
			skb_queue_purge(&cs->sq);
			if (cs->tx_skb) {
				dev_kfree_skb_any(cs->tx_skb);
				cs->tx_skb = NULL;
			}
			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
				del_timer(&cs->dbusytimer);
			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
				W6692_sched_event(cs, D_CLEARBUSY);
			break;
		default:
			if (cs->debug & L1_DEB_WARN)
				debugl1(cs, "W6692_l1hw unknown %04x", pr);
			break;
	}
}