jade_irq.c 4.4 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/* $Id: jade_irq.c,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $
Linus Torvalds's avatar
Linus Torvalds committed
2
 *
Linus Torvalds's avatar
Linus Torvalds committed
3
 * Low level JADE IRQ stuff (derived from original hscx_irq.c)
Linus Torvalds's avatar
Linus Torvalds committed
4
 *
Linus Torvalds's avatar
Linus Torvalds committed
5 6 7 8 9
 * Author       Roland Klabunde
 * Copyright    by Roland Klabunde   <R.Klabunde@Berkom.de>
 * 
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
Linus Torvalds's avatar
Linus Torvalds committed
10 11
 *
 */
12
static spinlock_t jade_irq_lock = SPIN_LOCK_UNLOCKED;
Linus Torvalds's avatar
Linus Torvalds committed
13 14 15 16 17 18

static inline void
waitforCEC(struct IsdnCardState *cs, int jade, int reg)
{
  	int to = 50;
  	int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
19
  	while ((jade_read_reg(cs, jade, jade_HDLC_STAR) & mask) && to) {
Linus Torvalds's avatar
Linus Torvalds committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
  		udelay(1);
  		to--;
  	}
  	if (!to)
  		printk(KERN_WARNING "HiSax: waitforCEC (jade) timeout\n");
}


static inline void
waitforXFW(struct IsdnCardState *cs, int jade)
{
  	/* Does not work on older jade versions, don't care */
}

static inline void
35
WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u8 data)
Linus Torvalds's avatar
Linus Torvalds committed
36
{
37
	unsigned long flags;
Linus Torvalds's avatar
Linus Torvalds committed
38

39
	spin_lock_irqsave(&jade_irq_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
40
	waitforCEC(cs, jade, reg);
41
	jade_write_reg(cs, jade, reg, data);
42
	spin_unlock_irqrestore(&jade_irq_lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
43 44 45 46 47 48 49
}



static void
jade_empty_fifo(struct BCState *bcs, int count)
{
50
	u8 *p;
Linus Torvalds's avatar
Linus Torvalds committed
51 52
	struct IsdnCardState *cs = bcs->cs;

53 54
	p = recv_empty_fifo_b(bcs, count);
	if (!p) {
Linus Torvalds's avatar
Linus Torvalds committed
55 56 57
		WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
		return;
	}
58
	jade_read_fifo(bcs, p, count);
Linus Torvalds's avatar
Linus Torvalds committed
59
	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
60

Linus Torvalds's avatar
Linus Torvalds committed
61 62 63 64 65
	if (cs->debug & L1_DEB_HSCX_FIFO) {
		char *t = bcs->blog;

		t += sprintf(t, "jade_empty_fifo %c cnt %d",
			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
66
		QuickHex(t, p, count);
Linus Torvalds's avatar
Linus Torvalds committed
67 68 69 70
		debugl1(cs, bcs->blog);
	}
}

71
static void
Linus Torvalds's avatar
Linus Torvalds committed
72 73 74 75 76
jade_fill_fifo(struct BCState *bcs)
{
	struct IsdnCardState *cs = bcs->cs;
	int more, count;
	int fifo_size = 32;
77 78
	int hscx = bcs->hw.hscx.hscx;
	unsigned char *p;
Linus Torvalds's avatar
Linus Torvalds committed
79

80 81
	p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more);
	if (!p)
Linus Torvalds's avatar
Linus Torvalds committed
82 83
		return;

84
	waitforXFW(cs, hscx);
85
	jade_write_fifo(bcs, p, count);
86 87
	WriteJADECMDR(cs, hscx, jade_HDLC_XCMD,
		      more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
Linus Torvalds's avatar
Linus Torvalds committed
88 89 90 91
}


static inline void
92
jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade)
Linus Torvalds's avatar
Linus Torvalds committed
93
{
94
	u8 r;
Linus Torvalds's avatar
Linus Torvalds committed
95 96 97 98 99 100 101 102 103 104
	struct BCState *bcs = cs->bcs + jade;
	struct sk_buff *skb;
	int fifo_size = 32;
	int count;
	int i_jade = (int) jade; /* To satisfy the compiler */
	
	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
		return;

	if (val & 0x80) {	/* RME */
105
		r = jade_read_reg(cs, i_jade, jade_HDLC_RSTA);
Linus Torvalds's avatar
Linus Torvalds committed
106 107 108 109 110 111 112 113 114 115 116 117
		if ((r & 0xf0) != 0xa0) {
			if (!(r & 0x80))
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
			if ((r & 0x40) && bcs->mode)
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
			if (!(r & 0x20))
				if (cs->debug & L1_DEB_WARN)
					debugl1(cs, "JADE %c CRC error", 'A'+jade);
			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
		} else {
118
			count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
Linus Torvalds's avatar
Linus Torvalds committed
119 120 121
			if (count == 0)
				count = fifo_size;
			jade_empty_fifo(bcs, count);
122
			if ((count = bcs->rcvidx - 1) > 0) {
Linus Torvalds's avatar
Linus Torvalds committed
123 124 125 126 127
				if (cs->debug & L1_DEB_HSCX_FIFO)
					debugl1(cs, "HX Frame %d", count);
				if (!(skb = dev_alloc_skb(count)))
					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
				else {
128
					memcpy(skb_put(skb, count), bcs->rcvbuf, count);
Linus Torvalds's avatar
Linus Torvalds committed
129 130 131 132
					skb_queue_tail(&bcs->rqueue, skb);
				}
			}
		}
133
		bcs->rcvidx = 0;
134
		sched_b_event(bcs, B_RCVBUFREADY);
Linus Torvalds's avatar
Linus Torvalds committed
135 136 137 138 139 140 141 142
	}
	if (val & 0x40) {	/* RPF */
		jade_empty_fifo(bcs, fifo_size);
		if (bcs->mode == L1_MODE_TRANS) {
			/* receive audio data */
			if (!(skb = dev_alloc_skb(fifo_size)))
				printk(KERN_WARNING "HiSax: receive out of memory\n");
			else {
143
				memcpy(skb_put(skb, fifo_size), bcs->rcvbuf, fifo_size);
Linus Torvalds's avatar
Linus Torvalds committed
144 145
				skb_queue_tail(&bcs->rqueue, skb);
			}
146
			bcs->rcvidx = 0;
147
			sched_b_event(bcs, B_RCVBUFREADY);
Linus Torvalds's avatar
Linus Torvalds committed
148 149 150
		}
	}
	if (val & 0x10) {	/* XPR */
151
		xmit_xpr_b(bcs);
Linus Torvalds's avatar
Linus Torvalds committed
152 153 154
	}
}

155 156 157 158 159 160
static void
reset_xmit(struct BCState *bcs)
{
	WriteJADECMDR(bcs->cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
}

161
void
162
jade_int_main(struct IsdnCardState *cs, u8 val, int jade)
Linus Torvalds's avatar
Linus Torvalds committed
163 164 165 166 167 168 169 170 171
{
	struct BCState *bcs;
	bcs = cs->bcs + jade;
	
	if (val & jadeISR_RFO) {
		/* handled with RDO */
		val &= ~jadeISR_RFO;
	}
	if (val & jadeISR_XDU) {
172
		xmit_xdu_b(bcs, reset_xmit);
Linus Torvalds's avatar
Linus Torvalds committed
173 174 175 176 177 178 179
	}
	if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
		if (cs->debug & L1_DEB_HSCX)
			debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val);
		jade_interrupt(cs, val, jade);
	}
}