diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hisax/hfc_2bds0.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/hisax/hfc_2bds0.c')
-rw-r--r-- | drivers/isdn/hisax/hfc_2bds0.c | 1082 |
1 files changed, 1082 insertions, 0 deletions
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c new file mode 100644 index 000000000000..ebea3feef003 --- /dev/null +++ b/drivers/isdn/hisax/hfc_2bds0.c | |||
@@ -0,0 +1,1082 @@ | |||
1 | /* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $ | ||
2 | * | ||
3 | * specific routines for CCD's HFC 2BDS0 | ||
4 | * | ||
5 | * Author Karsten Keil | ||
6 | * Copyright by Karsten Keil <keil@isdn4linux.de> | ||
7 | * | ||
8 | * This software may be used and distributed according to the terms | ||
9 | * of the GNU General Public License, incorporated herein by reference. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include "hisax.h" | ||
15 | #include "hfc_2bds0.h" | ||
16 | #include "isdnl1.h" | ||
17 | #include <linux/interrupt.h> | ||
18 | /* | ||
19 | #define KDEBUG_DEF | ||
20 | #include "kdebug.h" | ||
21 | */ | ||
22 | |||
23 | #define byteout(addr,val) outb(val,addr) | ||
24 | #define bytein(addr) inb(addr) | ||
25 | |||
26 | static void | ||
27 | dummyf(struct IsdnCardState *cs, u_char * data, int size) | ||
28 | { | ||
29 | printk(KERN_WARNING "HiSax: hfcd dummy fifo called\n"); | ||
30 | } | ||
31 | |||
32 | static inline u_char | ||
33 | ReadReg(struct IsdnCardState *cs, int data, u_char reg) | ||
34 | { | ||
35 | register u_char ret; | ||
36 | |||
37 | if (data) { | ||
38 | if (cs->hw.hfcD.cip != reg) { | ||
39 | cs->hw.hfcD.cip = reg; | ||
40 | byteout(cs->hw.hfcD.addr | 1, reg); | ||
41 | } | ||
42 | ret = bytein(cs->hw.hfcD.addr); | ||
43 | #ifdef HFC_REG_DEBUG | ||
44 | if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) | ||
45 | debugl1(cs, "t3c RD %02x %02x", reg, ret); | ||
46 | #endif | ||
47 | } else | ||
48 | ret = bytein(cs->hw.hfcD.addr | 1); | ||
49 | return (ret); | ||
50 | } | ||
51 | |||
52 | static inline void | ||
53 | WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value) | ||
54 | { | ||
55 | if (cs->hw.hfcD.cip != reg) { | ||
56 | cs->hw.hfcD.cip = reg; | ||
57 | byteout(cs->hw.hfcD.addr | 1, reg); | ||
58 | } | ||
59 | if (data) | ||
60 | byteout(cs->hw.hfcD.addr, value); | ||
61 | #ifdef HFC_REG_DEBUG | ||
62 | if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) | ||
63 | debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value); | ||
64 | #endif | ||
65 | } | ||
66 | |||
67 | /* Interface functions */ | ||
68 | |||
69 | static u_char | ||
70 | readreghfcd(struct IsdnCardState *cs, u_char offset) | ||
71 | { | ||
72 | return(ReadReg(cs, HFCD_DATA, offset)); | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value) | ||
77 | { | ||
78 | WriteReg(cs, HFCD_DATA, offset, value); | ||
79 | } | ||
80 | |||
81 | static inline int | ||
82 | WaitForBusy(struct IsdnCardState *cs) | ||
83 | { | ||
84 | int to = 130; | ||
85 | |||
86 | while (!(ReadReg(cs, HFCD_DATA, HFCD_STAT) & HFCD_BUSY) && to) { | ||
87 | udelay(1); | ||
88 | to--; | ||
89 | } | ||
90 | if (!to) | ||
91 | printk(KERN_WARNING "HiSax: WaitForBusy timeout\n"); | ||
92 | return (to); | ||
93 | } | ||
94 | |||
95 | static inline int | ||
96 | WaitNoBusy(struct IsdnCardState *cs) | ||
97 | { | ||
98 | int to = 130; | ||
99 | |||
100 | while ((ReadReg(cs, HFCD_STATUS, HFCD_STATUS) & HFCD_BUSY) && to) { | ||
101 | udelay(1); | ||
102 | to--; | ||
103 | } | ||
104 | if (!to) | ||
105 | printk(KERN_WARNING "HiSax: WaitNoBusy timeout\n"); | ||
106 | return (to); | ||
107 | } | ||
108 | |||
109 | static int | ||
110 | SelFiFo(struct IsdnCardState *cs, u_char FiFo) | ||
111 | { | ||
112 | u_char cip; | ||
113 | |||
114 | if (cs->hw.hfcD.fifo == FiFo) | ||
115 | return(1); | ||
116 | switch(FiFo) { | ||
117 | case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1; | ||
118 | break; | ||
119 | case 1: cip = HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_B1; | ||
120 | break; | ||
121 | case 2: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B2; | ||
122 | break; | ||
123 | case 3: cip = HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_B2; | ||
124 | break; | ||
125 | case 4: cip = HFCD_FIFO | HFCD_Z1 | HFCD_SEND; | ||
126 | break; | ||
127 | case 5: cip = HFCD_FIFO | HFCD_Z1 | HFCD_REC; | ||
128 | break; | ||
129 | default: | ||
130 | debugl1(cs, "SelFiFo Error"); | ||
131 | return(0); | ||
132 | } | ||
133 | cs->hw.hfcD.fifo = FiFo; | ||
134 | WaitNoBusy(cs); | ||
135 | cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0); | ||
136 | WaitForBusy(cs); | ||
137 | return(2); | ||
138 | } | ||
139 | |||
140 | static int | ||
141 | GetFreeFifoBytes_B(struct BCState *bcs) | ||
142 | { | ||
143 | int s; | ||
144 | |||
145 | if (bcs->hw.hfc.f1 == bcs->hw.hfc.f2) | ||
146 | return (bcs->cs->hw.hfcD.bfifosize); | ||
147 | s = bcs->hw.hfc.send[bcs->hw.hfc.f1] - bcs->hw.hfc.send[bcs->hw.hfc.f2]; | ||
148 | if (s <= 0) | ||
149 | s += bcs->cs->hw.hfcD.bfifosize; | ||
150 | s = bcs->cs->hw.hfcD.bfifosize - s; | ||
151 | return (s); | ||
152 | } | ||
153 | |||
154 | static int | ||
155 | GetFreeFifoBytes_D(struct IsdnCardState *cs) | ||
156 | { | ||
157 | int s; | ||
158 | |||
159 | if (cs->hw.hfcD.f1 == cs->hw.hfcD.f2) | ||
160 | return (cs->hw.hfcD.dfifosize); | ||
161 | s = cs->hw.hfcD.send[cs->hw.hfcD.f1] - cs->hw.hfcD.send[cs->hw.hfcD.f2]; | ||
162 | if (s <= 0) | ||
163 | s += cs->hw.hfcD.dfifosize; | ||
164 | s = cs->hw.hfcD.dfifosize - s; | ||
165 | return (s); | ||
166 | } | ||
167 | |||
168 | static int | ||
169 | ReadZReg(struct IsdnCardState *cs, u_char reg) | ||
170 | { | ||
171 | int val; | ||
172 | |||
173 | WaitNoBusy(cs); | ||
174 | val = 256 * ReadReg(cs, HFCD_DATA, reg | HFCB_Z_HIGH); | ||
175 | WaitNoBusy(cs); | ||
176 | val += ReadReg(cs, HFCD_DATA, reg | HFCB_Z_LOW); | ||
177 | return (val); | ||
178 | } | ||
179 | |||
180 | static struct sk_buff | ||
181 | *hfc_empty_fifo(struct BCState *bcs, int count) | ||
182 | { | ||
183 | u_char *ptr; | ||
184 | struct sk_buff *skb; | ||
185 | struct IsdnCardState *cs = bcs->cs; | ||
186 | int idx; | ||
187 | int chksum; | ||
188 | u_char stat, cip; | ||
189 | |||
190 | if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) | ||
191 | debugl1(cs, "hfc_empty_fifo"); | ||
192 | idx = 0; | ||
193 | if (count > HSCX_BUFMAX + 3) { | ||
194 | if (cs->debug & L1_DEB_WARN) | ||
195 | debugl1(cs, "hfc_empty_fifo: incoming packet too large"); | ||
196 | cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); | ||
197 | while (idx++ < count) { | ||
198 | WaitNoBusy(cs); | ||
199 | ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
200 | } | ||
201 | skb = NULL; | ||
202 | } else if (count < 4) { | ||
203 | if (cs->debug & L1_DEB_WARN) | ||
204 | debugl1(cs, "hfc_empty_fifo: incoming packet too small"); | ||
205 | cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); | ||
206 | #ifdef ERROR_STATISTIC | ||
207 | bcs->err_inv++; | ||
208 | #endif | ||
209 | while ((idx++ < count) && WaitNoBusy(cs)) | ||
210 | ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
211 | skb = NULL; | ||
212 | } else if (!(skb = dev_alloc_skb(count - 3))) | ||
213 | printk(KERN_WARNING "HFC: receive out of memory\n"); | ||
214 | else { | ||
215 | ptr = skb_put(skb, count - 3); | ||
216 | idx = 0; | ||
217 | cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); | ||
218 | while (idx < (count - 3)) { | ||
219 | if (!WaitNoBusy(cs)) | ||
220 | break; | ||
221 | *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
222 | ptr++; | ||
223 | idx++; | ||
224 | } | ||
225 | if (idx != count - 3) { | ||
226 | debugl1(cs, "RFIFO BUSY error"); | ||
227 | printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); | ||
228 | dev_kfree_skb_irq(skb); | ||
229 | skb = NULL; | ||
230 | } else { | ||
231 | WaitNoBusy(cs); | ||
232 | chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); | ||
233 | WaitNoBusy(cs); | ||
234 | chksum += ReadReg(cs, HFCD_DATA, cip); | ||
235 | WaitNoBusy(cs); | ||
236 | stat = ReadReg(cs, HFCD_DATA, cip); | ||
237 | if (cs->debug & L1_DEB_HSCX) | ||
238 | debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", | ||
239 | bcs->channel, chksum, stat); | ||
240 | if (stat) { | ||
241 | debugl1(cs, "FIFO CRC error"); | ||
242 | dev_kfree_skb_irq(skb); | ||
243 | skb = NULL; | ||
244 | #ifdef ERROR_STATISTIC | ||
245 | bcs->err_crc++; | ||
246 | #endif | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | WaitForBusy(cs); | ||
251 | WaitNoBusy(cs); | ||
252 | stat = ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F2_INC | | ||
253 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); | ||
254 | WaitForBusy(cs); | ||
255 | return (skb); | ||
256 | } | ||
257 | |||
258 | static void | ||
259 | hfc_fill_fifo(struct BCState *bcs) | ||
260 | { | ||
261 | struct IsdnCardState *cs = bcs->cs; | ||
262 | int idx, fcnt; | ||
263 | int count; | ||
264 | u_char cip; | ||
265 | |||
266 | if (!bcs->tx_skb) | ||
267 | return; | ||
268 | if (bcs->tx_skb->len <= 0) | ||
269 | return; | ||
270 | SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); | ||
271 | cip = HFCB_FIFO | HFCB_F1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); | ||
272 | WaitNoBusy(cs); | ||
273 | bcs->hw.hfc.f1 = ReadReg(cs, HFCD_DATA, cip); | ||
274 | WaitNoBusy(cs); | ||
275 | cip = HFCB_FIFO | HFCB_F2 | HFCB_SEND | HFCB_CHANNEL(bcs->channel); | ||
276 | WaitNoBusy(cs); | ||
277 | bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip); | ||
278 | bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); | ||
279 | if (cs->debug & L1_DEB_HSCX) | ||
280 | debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", | ||
281 | bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2, | ||
282 | bcs->hw.hfc.send[bcs->hw.hfc.f1]); | ||
283 | fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2; | ||
284 | if (fcnt < 0) | ||
285 | fcnt += 32; | ||
286 | if (fcnt > 30) { | ||
287 | if (cs->debug & L1_DEB_HSCX) | ||
288 | debugl1(cs, "hfc_fill_fifo more as 30 frames"); | ||
289 | return; | ||
290 | } | ||
291 | count = GetFreeFifoBytes_B(bcs); | ||
292 | if (cs->debug & L1_DEB_HSCX) | ||
293 | debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx", | ||
294 | bcs->channel, bcs->tx_skb->len, | ||
295 | count, current->state); | ||
296 | if (count < bcs->tx_skb->len) { | ||
297 | if (cs->debug & L1_DEB_HSCX) | ||
298 | debugl1(cs, "hfc_fill_fifo no fifo mem"); | ||
299 | return; | ||
300 | } | ||
301 | cip = HFCB_FIFO | HFCB_FIFO_IN | HFCB_SEND | HFCB_CHANNEL(bcs->channel); | ||
302 | idx = 0; | ||
303 | WaitForBusy(cs); | ||
304 | WaitNoBusy(cs); | ||
305 | WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); | ||
306 | while (idx < bcs->tx_skb->len) { | ||
307 | if (!WaitNoBusy(cs)) | ||
308 | break; | ||
309 | WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]); | ||
310 | idx++; | ||
311 | } | ||
312 | if (idx != bcs->tx_skb->len) { | ||
313 | debugl1(cs, "FIFO Send BUSY error"); | ||
314 | printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); | ||
315 | } else { | ||
316 | bcs->tx_cnt -= bcs->tx_skb->len; | ||
317 | if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && | ||
318 | (PACKET_NOACK != bcs->tx_skb->pkt_type)) { | ||
319 | u_long flags; | ||
320 | spin_lock_irqsave(&bcs->aclock, flags); | ||
321 | bcs->ackcnt += bcs->tx_skb->len; | ||
322 | spin_unlock_irqrestore(&bcs->aclock, flags); | ||
323 | schedule_event(bcs, B_ACKPENDING); | ||
324 | } | ||
325 | dev_kfree_skb_any(bcs->tx_skb); | ||
326 | bcs->tx_skb = NULL; | ||
327 | } | ||
328 | WaitForBusy(cs); | ||
329 | WaitNoBusy(cs); | ||
330 | ReadReg(cs, HFCD_DATA, HFCB_FIFO | HFCB_F1_INC | HFCB_SEND | HFCB_CHANNEL(bcs->channel)); | ||
331 | WaitForBusy(cs); | ||
332 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | static void | ||
337 | hfc_send_data(struct BCState *bcs) | ||
338 | { | ||
339 | struct IsdnCardState *cs = bcs->cs; | ||
340 | |||
341 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
342 | hfc_fill_fifo(bcs); | ||
343 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
344 | } else | ||
345 | debugl1(cs,"send_data %d blocked", bcs->channel); | ||
346 | } | ||
347 | |||
348 | void | ||
349 | main_rec_2bds0(struct BCState *bcs) | ||
350 | { | ||
351 | struct IsdnCardState *cs = bcs->cs; | ||
352 | int z1, z2, rcnt; | ||
353 | u_char f1, f2, cip; | ||
354 | int receive, count = 5; | ||
355 | struct sk_buff *skb; | ||
356 | |||
357 | Begin: | ||
358 | count--; | ||
359 | if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
360 | debugl1(cs,"rec_data %d blocked", bcs->channel); | ||
361 | return; | ||
362 | } | ||
363 | SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel)); | ||
364 | cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel); | ||
365 | WaitNoBusy(cs); | ||
366 | f1 = ReadReg(cs, HFCD_DATA, cip); | ||
367 | cip = HFCB_FIFO | HFCB_F2 | HFCB_REC | HFCB_CHANNEL(bcs->channel); | ||
368 | WaitNoBusy(cs); | ||
369 | f2 = ReadReg(cs, HFCD_DATA, cip); | ||
370 | if (f1 != f2) { | ||
371 | if (cs->debug & L1_DEB_HSCX) | ||
372 | debugl1(cs, "hfc rec %d f1(%d) f2(%d)", | ||
373 | bcs->channel, f1, f2); | ||
374 | z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); | ||
375 | z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel)); | ||
376 | rcnt = z1 - z2; | ||
377 | if (rcnt < 0) | ||
378 | rcnt += cs->hw.hfcD.bfifosize; | ||
379 | rcnt++; | ||
380 | if (cs->debug & L1_DEB_HSCX) | ||
381 | debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", | ||
382 | bcs->channel, z1, z2, rcnt); | ||
383 | if ((skb = hfc_empty_fifo(bcs, rcnt))) { | ||
384 | skb_queue_tail(&bcs->rqueue, skb); | ||
385 | schedule_event(bcs, B_RCVBUFREADY); | ||
386 | } | ||
387 | rcnt = f1 -f2; | ||
388 | if (rcnt<0) | ||
389 | rcnt += 32; | ||
390 | if (rcnt>1) | ||
391 | receive = 1; | ||
392 | else | ||
393 | receive = 0; | ||
394 | } else | ||
395 | receive = 0; | ||
396 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
397 | if (count && receive) | ||
398 | goto Begin; | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | void | ||
403 | mode_2bs0(struct BCState *bcs, int mode, int bc) | ||
404 | { | ||
405 | struct IsdnCardState *cs = bcs->cs; | ||
406 | |||
407 | if (cs->debug & L1_DEB_HSCX) | ||
408 | debugl1(cs, "HFCD bchannel mode %d bchan %d/%d", | ||
409 | mode, bc, bcs->channel); | ||
410 | bcs->mode = mode; | ||
411 | bcs->channel = bc; | ||
412 | switch (mode) { | ||
413 | case (L1_MODE_NULL): | ||
414 | if (bc) { | ||
415 | cs->hw.hfcD.conn |= 0x18; | ||
416 | cs->hw.hfcD.sctrl &= ~SCTRL_B2_ENA; | ||
417 | } else { | ||
418 | cs->hw.hfcD.conn |= 0x3; | ||
419 | cs->hw.hfcD.sctrl &= ~SCTRL_B1_ENA; | ||
420 | } | ||
421 | break; | ||
422 | case (L1_MODE_TRANS): | ||
423 | if (bc) { | ||
424 | cs->hw.hfcD.ctmt |= 2; | ||
425 | cs->hw.hfcD.conn &= ~0x18; | ||
426 | cs->hw.hfcD.sctrl |= SCTRL_B2_ENA; | ||
427 | } else { | ||
428 | cs->hw.hfcD.ctmt |= 1; | ||
429 | cs->hw.hfcD.conn &= ~0x3; | ||
430 | cs->hw.hfcD.sctrl |= SCTRL_B1_ENA; | ||
431 | } | ||
432 | break; | ||
433 | case (L1_MODE_HDLC): | ||
434 | if (bc) { | ||
435 | cs->hw.hfcD.ctmt &= ~2; | ||
436 | cs->hw.hfcD.conn &= ~0x18; | ||
437 | cs->hw.hfcD.sctrl |= SCTRL_B2_ENA; | ||
438 | } else { | ||
439 | cs->hw.hfcD.ctmt &= ~1; | ||
440 | cs->hw.hfcD.conn &= ~0x3; | ||
441 | cs->hw.hfcD.sctrl |= SCTRL_B1_ENA; | ||
442 | } | ||
443 | break; | ||
444 | } | ||
445 | WriteReg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); | ||
446 | WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); | ||
447 | WriteReg(cs, HFCD_DATA, HFCD_CONN, cs->hw.hfcD.conn); | ||
448 | } | ||
449 | |||
450 | static void | ||
451 | hfc_l2l1(struct PStack *st, int pr, void *arg) | ||
452 | { | ||
453 | struct BCState *bcs = st->l1.bcs; | ||
454 | struct sk_buff *skb = arg; | ||
455 | u_long flags; | ||
456 | |||
457 | switch (pr) { | ||
458 | case (PH_DATA | REQUEST): | ||
459 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
460 | if (bcs->tx_skb) { | ||
461 | skb_queue_tail(&bcs->squeue, skb); | ||
462 | } else { | ||
463 | bcs->tx_skb = skb; | ||
464 | // test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); | ||
465 | bcs->cs->BC_Send_Data(bcs); | ||
466 | } | ||
467 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
468 | break; | ||
469 | case (PH_PULL | INDICATION): | ||
470 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
471 | if (bcs->tx_skb) { | ||
472 | printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); | ||
473 | } else { | ||
474 | // test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); | ||
475 | bcs->tx_skb = skb; | ||
476 | bcs->cs->BC_Send_Data(bcs); | ||
477 | } | ||
478 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
479 | break; | ||
480 | case (PH_PULL | REQUEST): | ||
481 | if (!bcs->tx_skb) { | ||
482 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | ||
483 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); | ||
484 | } else | ||
485 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | ||
486 | break; | ||
487 | case (PH_ACTIVATE | REQUEST): | ||
488 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
489 | test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); | ||
490 | mode_2bs0(bcs, st->l1.mode, st->l1.bc); | ||
491 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
492 | l1_msg_b(st, pr, arg); | ||
493 | break; | ||
494 | case (PH_DEACTIVATE | REQUEST): | ||
495 | l1_msg_b(st, pr, arg); | ||
496 | break; | ||
497 | case (PH_DEACTIVATE | CONFIRM): | ||
498 | spin_lock_irqsave(&bcs->cs->lock, flags); | ||
499 | test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); | ||
500 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | ||
501 | mode_2bs0(bcs, 0, st->l1.bc); | ||
502 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | ||
503 | st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); | ||
504 | break; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | void | ||
509 | close_2bs0(struct BCState *bcs) | ||
510 | { | ||
511 | mode_2bs0(bcs, 0, bcs->channel); | ||
512 | if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { | ||
513 | skb_queue_purge(&bcs->rqueue); | ||
514 | skb_queue_purge(&bcs->squeue); | ||
515 | if (bcs->tx_skb) { | ||
516 | dev_kfree_skb_any(bcs->tx_skb); | ||
517 | bcs->tx_skb = NULL; | ||
518 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static int | ||
524 | open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs) | ||
525 | { | ||
526 | if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { | ||
527 | skb_queue_head_init(&bcs->rqueue); | ||
528 | skb_queue_head_init(&bcs->squeue); | ||
529 | } | ||
530 | bcs->tx_skb = NULL; | ||
531 | test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); | ||
532 | bcs->event = 0; | ||
533 | bcs->tx_cnt = 0; | ||
534 | return (0); | ||
535 | } | ||
536 | |||
537 | int | ||
538 | setstack_2b(struct PStack *st, struct BCState *bcs) | ||
539 | { | ||
540 | bcs->channel = st->l1.bc; | ||
541 | if (open_hfcstate(st->l1.hardware, bcs)) | ||
542 | return (-1); | ||
543 | st->l1.bcs = bcs; | ||
544 | st->l2.l2l1 = hfc_l2l1; | ||
545 | setstack_manager(st); | ||
546 | bcs->st = st; | ||
547 | setstack_l1_B(st); | ||
548 | return (0); | ||
549 | } | ||
550 | |||
551 | static void | ||
552 | hfcd_bh(struct IsdnCardState *cs) | ||
553 | { | ||
554 | if (!cs) | ||
555 | return; | ||
556 | if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { | ||
557 | switch (cs->dc.hfcd.ph_state) { | ||
558 | case (0): | ||
559 | l1_msg(cs, HW_RESET | INDICATION, NULL); | ||
560 | break; | ||
561 | case (3): | ||
562 | l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); | ||
563 | break; | ||
564 | case (8): | ||
565 | l1_msg(cs, HW_RSYNC | INDICATION, NULL); | ||
566 | break; | ||
567 | case (6): | ||
568 | l1_msg(cs, HW_INFO2 | INDICATION, NULL); | ||
569 | break; | ||
570 | case (7): | ||
571 | l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); | ||
572 | break; | ||
573 | default: | ||
574 | break; | ||
575 | } | ||
576 | } | ||
577 | if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) | ||
578 | DChannel_proc_rcv(cs); | ||
579 | if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) | ||
580 | DChannel_proc_xmt(cs); | ||
581 | } | ||
582 | |||
583 | static | ||
584 | int receive_dmsg(struct IsdnCardState *cs) | ||
585 | { | ||
586 | struct sk_buff *skb; | ||
587 | int idx; | ||
588 | int rcnt, z1, z2; | ||
589 | u_char stat, cip, f1, f2; | ||
590 | int chksum; | ||
591 | int count=5; | ||
592 | u_char *ptr; | ||
593 | |||
594 | if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
595 | debugl1(cs, "rec_dmsg blocked"); | ||
596 | return(1); | ||
597 | } | ||
598 | SelFiFo(cs, 4 | HFCD_REC); | ||
599 | cip = HFCD_FIFO | HFCD_F1 | HFCD_REC; | ||
600 | WaitNoBusy(cs); | ||
601 | f1 = cs->readisac(cs, cip) & 0xf; | ||
602 | cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; | ||
603 | WaitNoBusy(cs); | ||
604 | f2 = cs->readisac(cs, cip) & 0xf; | ||
605 | while ((f1 != f2) && count--) { | ||
606 | z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC); | ||
607 | z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC); | ||
608 | rcnt = z1 - z2; | ||
609 | if (rcnt < 0) | ||
610 | rcnt += cs->hw.hfcD.dfifosize; | ||
611 | rcnt++; | ||
612 | if (cs->debug & L1_DEB_ISAC) | ||
613 | debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", | ||
614 | f1, f2, z1, z2, rcnt); | ||
615 | idx = 0; | ||
616 | cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC; | ||
617 | if (rcnt > MAX_DFRAME_LEN + 3) { | ||
618 | if (cs->debug & L1_DEB_WARN) | ||
619 | debugl1(cs, "empty_fifo d: incoming packet too large"); | ||
620 | while (idx < rcnt) { | ||
621 | if (!(WaitNoBusy(cs))) | ||
622 | break; | ||
623 | ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
624 | idx++; | ||
625 | } | ||
626 | } else if (rcnt < 4) { | ||
627 | if (cs->debug & L1_DEB_WARN) | ||
628 | debugl1(cs, "empty_fifo d: incoming packet too small"); | ||
629 | while ((idx++ < rcnt) && WaitNoBusy(cs)) | ||
630 | ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
631 | } else if ((skb = dev_alloc_skb(rcnt - 3))) { | ||
632 | ptr = skb_put(skb, rcnt - 3); | ||
633 | while (idx < (rcnt - 3)) { | ||
634 | if (!(WaitNoBusy(cs))) | ||
635 | break; | ||
636 | *ptr = ReadReg(cs, HFCD_DATA_NODEB, cip); | ||
637 | idx++; | ||
638 | ptr++; | ||
639 | } | ||
640 | if (idx != (rcnt - 3)) { | ||
641 | debugl1(cs, "RFIFO D BUSY error"); | ||
642 | printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); | ||
643 | dev_kfree_skb_irq(skb); | ||
644 | skb = NULL; | ||
645 | #ifdef ERROR_STATISTIC | ||
646 | cs->err_rx++; | ||
647 | #endif | ||
648 | } else { | ||
649 | WaitNoBusy(cs); | ||
650 | chksum = (ReadReg(cs, HFCD_DATA, cip) << 8); | ||
651 | WaitNoBusy(cs); | ||
652 | chksum += ReadReg(cs, HFCD_DATA, cip); | ||
653 | WaitNoBusy(cs); | ||
654 | stat = ReadReg(cs, HFCD_DATA, cip); | ||
655 | if (cs->debug & L1_DEB_ISAC) | ||
656 | debugl1(cs, "empty_dfifo chksum %x stat %x", | ||
657 | chksum, stat); | ||
658 | if (stat) { | ||
659 | debugl1(cs, "FIFO CRC error"); | ||
660 | dev_kfree_skb_irq(skb); | ||
661 | skb = NULL; | ||
662 | #ifdef ERROR_STATISTIC | ||
663 | cs->err_crc++; | ||
664 | #endif | ||
665 | } else { | ||
666 | skb_queue_tail(&cs->rq, skb); | ||
667 | schedule_event(cs, D_RCVBUFREADY); | ||
668 | } | ||
669 | } | ||
670 | } else | ||
671 | printk(KERN_WARNING "HFC: D receive out of memory\n"); | ||
672 | WaitForBusy(cs); | ||
673 | cip = HFCD_FIFO | HFCD_F2_INC | HFCD_REC; | ||
674 | WaitNoBusy(cs); | ||
675 | stat = ReadReg(cs, HFCD_DATA, cip); | ||
676 | WaitForBusy(cs); | ||
677 | cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; | ||
678 | WaitNoBusy(cs); | ||
679 | f2 = cs->readisac(cs, cip) & 0xf; | ||
680 | } | ||
681 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
682 | return(1); | ||
683 | } | ||
684 | |||
685 | static void | ||
686 | hfc_fill_dfifo(struct IsdnCardState *cs) | ||
687 | { | ||
688 | int idx, fcnt; | ||
689 | int count; | ||
690 | u_char cip; | ||
691 | |||
692 | if (!cs->tx_skb) | ||
693 | return; | ||
694 | if (cs->tx_skb->len <= 0) | ||
695 | return; | ||
696 | |||
697 | SelFiFo(cs, 4 | HFCD_SEND); | ||
698 | cip = HFCD_FIFO | HFCD_F1 | HFCD_SEND; | ||
699 | WaitNoBusy(cs); | ||
700 | cs->hw.hfcD.f1 = ReadReg(cs, HFCD_DATA, cip) & 0xf; | ||
701 | WaitNoBusy(cs); | ||
702 | cip = HFCD_FIFO | HFCD_F2 | HFCD_SEND; | ||
703 | cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf; | ||
704 | cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND); | ||
705 | if (cs->debug & L1_DEB_ISAC) | ||
706 | debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)", | ||
707 | cs->hw.hfcD.f1, cs->hw.hfcD.f2, | ||
708 | cs->hw.hfcD.send[cs->hw.hfcD.f1]); | ||
709 | fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2; | ||
710 | if (fcnt < 0) | ||
711 | fcnt += 16; | ||
712 | if (fcnt > 14) { | ||
713 | if (cs->debug & L1_DEB_HSCX) | ||
714 | debugl1(cs, "hfc_fill_Dfifo more as 14 frames"); | ||
715 | return; | ||
716 | } | ||
717 | count = GetFreeFifoBytes_D(cs); | ||
718 | if (cs->debug & L1_DEB_ISAC) | ||
719 | debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)", | ||
720 | cs->tx_skb->len, count); | ||
721 | if (count < cs->tx_skb->len) { | ||
722 | if (cs->debug & L1_DEB_ISAC) | ||
723 | debugl1(cs, "hfc_fill_Dfifo no fifo mem"); | ||
724 | return; | ||
725 | } | ||
726 | cip = HFCD_FIFO | HFCD_FIFO_IN | HFCD_SEND; | ||
727 | idx = 0; | ||
728 | WaitForBusy(cs); | ||
729 | WaitNoBusy(cs); | ||
730 | WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx++]); | ||
731 | while (idx < cs->tx_skb->len) { | ||
732 | if (!(WaitNoBusy(cs))) | ||
733 | break; | ||
734 | WriteReg(cs, HFCD_DATA_NODEB, cip, cs->tx_skb->data[idx]); | ||
735 | idx++; | ||
736 | } | ||
737 | if (idx != cs->tx_skb->len) { | ||
738 | debugl1(cs, "DFIFO Send BUSY error"); | ||
739 | printk(KERN_WARNING "HFC S DFIFO channel BUSY Error\n"); | ||
740 | } | ||
741 | WaitForBusy(cs); | ||
742 | WaitNoBusy(cs); | ||
743 | ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); | ||
744 | dev_kfree_skb_any(cs->tx_skb); | ||
745 | cs->tx_skb = NULL; | ||
746 | WaitForBusy(cs); | ||
747 | return; | ||
748 | } | ||
749 | |||
750 | static | ||
751 | struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel) | ||
752 | { | ||
753 | if (cs->bcs[0].mode && (cs->bcs[0].channel == channel)) | ||
754 | return(&cs->bcs[0]); | ||
755 | else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel)) | ||
756 | return(&cs->bcs[1]); | ||
757 | else | ||
758 | return(NULL); | ||
759 | } | ||
760 | |||
761 | void | ||
762 | hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) | ||
763 | { | ||
764 | u_char exval; | ||
765 | struct BCState *bcs; | ||
766 | int count=15; | ||
767 | |||
768 | if (cs->debug & L1_DEB_ISAC) | ||
769 | debugl1(cs, "HFCD irq %x %s", val, | ||
770 | test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? | ||
771 | "locked" : "unlocked"); | ||
772 | val &= cs->hw.hfcD.int_m1; | ||
773 | if (val & 0x40) { /* TE state machine irq */ | ||
774 | exval = cs->readisac(cs, HFCD_STATES) & 0xf; | ||
775 | if (cs->debug & L1_DEB_ISAC) | ||
776 | debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, | ||
777 | exval); | ||
778 | cs->dc.hfcd.ph_state = exval; | ||
779 | schedule_event(cs, D_L1STATECHANGE); | ||
780 | val &= ~0x40; | ||
781 | } | ||
782 | while (val) { | ||
783 | if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
784 | cs->hw.hfcD.int_s1 |= val; | ||
785 | return; | ||
786 | } | ||
787 | if (cs->hw.hfcD.int_s1 & 0x18) { | ||
788 | exval = val; | ||
789 | val = cs->hw.hfcD.int_s1; | ||
790 | cs->hw.hfcD.int_s1 = exval; | ||
791 | } | ||
792 | if (val & 0x08) { | ||
793 | if (!(bcs=Sel_BCS(cs, 0))) { | ||
794 | if (cs->debug) | ||
795 | debugl1(cs, "hfcd spurious 0x08 IRQ"); | ||
796 | } else | ||
797 | main_rec_2bds0(bcs); | ||
798 | } | ||
799 | if (val & 0x10) { | ||
800 | if (!(bcs=Sel_BCS(cs, 1))) { | ||
801 | if (cs->debug) | ||
802 | debugl1(cs, "hfcd spurious 0x10 IRQ"); | ||
803 | } else | ||
804 | main_rec_2bds0(bcs); | ||
805 | } | ||
806 | if (val & 0x01) { | ||
807 | if (!(bcs=Sel_BCS(cs, 0))) { | ||
808 | if (cs->debug) | ||
809 | debugl1(cs, "hfcd spurious 0x01 IRQ"); | ||
810 | } else { | ||
811 | if (bcs->tx_skb) { | ||
812 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
813 | hfc_fill_fifo(bcs); | ||
814 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
815 | } else | ||
816 | debugl1(cs,"fill_data %d blocked", bcs->channel); | ||
817 | } else { | ||
818 | if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { | ||
819 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
820 | hfc_fill_fifo(bcs); | ||
821 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
822 | } else | ||
823 | debugl1(cs,"fill_data %d blocked", bcs->channel); | ||
824 | } else { | ||
825 | schedule_event(bcs, B_XMTBUFREADY); | ||
826 | } | ||
827 | } | ||
828 | } | ||
829 | } | ||
830 | if (val & 0x02) { | ||
831 | if (!(bcs=Sel_BCS(cs, 1))) { | ||
832 | if (cs->debug) | ||
833 | debugl1(cs, "hfcd spurious 0x02 IRQ"); | ||
834 | } else { | ||
835 | if (bcs->tx_skb) { | ||
836 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
837 | hfc_fill_fifo(bcs); | ||
838 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
839 | } else | ||
840 | debugl1(cs,"fill_data %d blocked", bcs->channel); | ||
841 | } else { | ||
842 | if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { | ||
843 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
844 | hfc_fill_fifo(bcs); | ||
845 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
846 | } else | ||
847 | debugl1(cs,"fill_data %d blocked", bcs->channel); | ||
848 | } else { | ||
849 | schedule_event(bcs, B_XMTBUFREADY); | ||
850 | } | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | if (val & 0x20) { /* receive dframe */ | ||
855 | receive_dmsg(cs); | ||
856 | } | ||
857 | if (val & 0x04) { /* dframe transmitted */ | ||
858 | if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) | ||
859 | del_timer(&cs->dbusytimer); | ||
860 | if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) | ||
861 | schedule_event(cs, D_CLEARBUSY); | ||
862 | if (cs->tx_skb) { | ||
863 | if (cs->tx_skb->len) { | ||
864 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
865 | hfc_fill_dfifo(cs); | ||
866 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
867 | } else { | ||
868 | debugl1(cs, "hfc_fill_dfifo irq blocked"); | ||
869 | } | ||
870 | goto afterXPR; | ||
871 | } else { | ||
872 | dev_kfree_skb_irq(cs->tx_skb); | ||
873 | cs->tx_cnt = 0; | ||
874 | cs->tx_skb = NULL; | ||
875 | } | ||
876 | } | ||
877 | if ((cs->tx_skb = skb_dequeue(&cs->sq))) { | ||
878 | cs->tx_cnt = 0; | ||
879 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
880 | hfc_fill_dfifo(cs); | ||
881 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
882 | } else { | ||
883 | debugl1(cs, "hfc_fill_dfifo irq blocked"); | ||
884 | } | ||
885 | } else | ||
886 | schedule_event(cs, D_XMTBUFREADY); | ||
887 | } | ||
888 | afterXPR: | ||
889 | if (cs->hw.hfcD.int_s1 && count--) { | ||
890 | val = cs->hw.hfcD.int_s1; | ||
891 | cs->hw.hfcD.int_s1 = 0; | ||
892 | if (cs->debug & L1_DEB_ISAC) | ||
893 | debugl1(cs, "HFCD irq %x loop %d", val, 15-count); | ||
894 | } else | ||
895 | val = 0; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | static void | ||
900 | HFCD_l1hw(struct PStack *st, int pr, void *arg) | ||
901 | { | ||
902 | struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; | ||
903 | struct sk_buff *skb = arg; | ||
904 | u_long flags; | ||
905 | |||
906 | switch (pr) { | ||
907 | case (PH_DATA | REQUEST): | ||
908 | if (cs->debug & DEB_DLOG_HEX) | ||
909 | LogFrame(cs, skb->data, skb->len); | ||
910 | if (cs->debug & DEB_DLOG_VERBOSE) | ||
911 | dlogframe(cs, skb, 0); | ||
912 | spin_lock_irqsave(&cs->lock, flags); | ||
913 | if (cs->tx_skb) { | ||
914 | skb_queue_tail(&cs->sq, skb); | ||
915 | #ifdef L2FRAME_DEBUG /* psa */ | ||
916 | if (cs->debug & L1_DEB_LAPD) | ||
917 | Logl2Frame(cs, skb, "PH_DATA Queued", 0); | ||
918 | #endif | ||
919 | } else { | ||
920 | cs->tx_skb = skb; | ||
921 | cs->tx_cnt = 0; | ||
922 | #ifdef L2FRAME_DEBUG /* psa */ | ||
923 | if (cs->debug & L1_DEB_LAPD) | ||
924 | Logl2Frame(cs, skb, "PH_DATA", 0); | ||
925 | #endif | ||
926 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
927 | hfc_fill_dfifo(cs); | ||
928 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
929 | } else | ||
930 | debugl1(cs, "hfc_fill_dfifo blocked"); | ||
931 | |||
932 | } | ||
933 | spin_unlock_irqrestore(&cs->lock, flags); | ||
934 | break; | ||
935 | case (PH_PULL | INDICATION): | ||
936 | spin_lock_irqsave(&cs->lock, flags); | ||
937 | if (cs->tx_skb) { | ||
938 | if (cs->debug & L1_DEB_WARN) | ||
939 | debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); | ||
940 | skb_queue_tail(&cs->sq, skb); | ||
941 | spin_unlock_irqrestore(&cs->lock, flags); | ||
942 | break; | ||
943 | } | ||
944 | if (cs->debug & DEB_DLOG_HEX) | ||
945 | LogFrame(cs, skb->data, skb->len); | ||
946 | if (cs->debug & DEB_DLOG_VERBOSE) | ||
947 | dlogframe(cs, skb, 0); | ||
948 | cs->tx_skb = skb; | ||
949 | cs->tx_cnt = 0; | ||
950 | #ifdef L2FRAME_DEBUG /* psa */ | ||
951 | if (cs->debug & L1_DEB_LAPD) | ||
952 | Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); | ||
953 | #endif | ||
954 | if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { | ||
955 | hfc_fill_dfifo(cs); | ||
956 | test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); | ||
957 | } else | ||
958 | debugl1(cs, "hfc_fill_dfifo blocked"); | ||
959 | spin_unlock_irqrestore(&cs->lock, flags); | ||
960 | break; | ||
961 | case (PH_PULL | REQUEST): | ||
962 | #ifdef L2FRAME_DEBUG /* psa */ | ||
963 | if (cs->debug & L1_DEB_LAPD) | ||
964 | debugl1(cs, "-> PH_REQUEST_PULL"); | ||
965 | #endif | ||
966 | if (!cs->tx_skb) { | ||
967 | test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | ||
968 | st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); | ||
969 | } else | ||
970 | test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); | ||
971 | break; | ||
972 | case (HW_RESET | REQUEST): | ||
973 | spin_lock_irqsave(&cs->lock, flags); | ||
974 | cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ | ||
975 | udelay(6); | ||
976 | cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */ | ||
977 | cs->hw.hfcD.mst_m |= HFCD_MASTER; | ||
978 | cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); | ||
979 | cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); | ||
980 | spin_unlock_irqrestore(&cs->lock, flags); | ||
981 | l1_msg(cs, HW_POWERUP | CONFIRM, NULL); | ||
982 | break; | ||
983 | case (HW_ENABLE | REQUEST): | ||
984 | spin_lock_irqsave(&cs->lock, flags); | ||
985 | cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); | ||
986 | spin_unlock_irqrestore(&cs->lock, flags); | ||
987 | break; | ||
988 | case (HW_DEACTIVATE | REQUEST): | ||
989 | spin_lock_irqsave(&cs->lock, flags); | ||
990 | cs->hw.hfcD.mst_m &= ~HFCD_MASTER; | ||
991 | cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); | ||
992 | spin_unlock_irqrestore(&cs->lock, flags); | ||
993 | break; | ||
994 | case (HW_INFO3 | REQUEST): | ||
995 | spin_lock_irqsave(&cs->lock, flags); | ||
996 | cs->hw.hfcD.mst_m |= HFCD_MASTER; | ||
997 | cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); | ||
998 | spin_unlock_irqrestore(&cs->lock, flags); | ||
999 | break; | ||
1000 | default: | ||
1001 | if (cs->debug & L1_DEB_WARN) | ||
1002 | debugl1(cs, "hfcd_l1hw unknown pr %4x", pr); | ||
1003 | break; | ||
1004 | } | ||
1005 | } | ||
1006 | |||
1007 | void | ||
1008 | setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) | ||
1009 | { | ||
1010 | st->l1.l1hw = HFCD_l1hw; | ||
1011 | } | ||
1012 | |||
1013 | static void | ||
1014 | hfc_dbusy_timer(struct IsdnCardState *cs) | ||
1015 | { | ||
1016 | } | ||
1017 | |||
1018 | unsigned int __init | ||
1019 | *init_send_hfcd(int cnt) | ||
1020 | { | ||
1021 | int i, *send; | ||
1022 | |||
1023 | if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) { | ||
1024 | printk(KERN_WARNING | ||
1025 | "HiSax: No memory for hfcd.send\n"); | ||
1026 | return(NULL); | ||
1027 | } | ||
1028 | for (i = 0; i < cnt; i++) | ||
1029 | send[i] = 0x1fff; | ||
1030 | return(send); | ||
1031 | } | ||
1032 | |||
1033 | void __init | ||
1034 | init2bds0(struct IsdnCardState *cs) | ||
1035 | { | ||
1036 | cs->setstack_d = setstack_hfcd; | ||
1037 | if (!cs->hw.hfcD.send) | ||
1038 | cs->hw.hfcD.send = init_send_hfcd(16); | ||
1039 | if (!cs->bcs[0].hw.hfc.send) | ||
1040 | cs->bcs[0].hw.hfc.send = init_send_hfcd(32); | ||
1041 | if (!cs->bcs[1].hw.hfc.send) | ||
1042 | cs->bcs[1].hw.hfc.send = init_send_hfcd(32); | ||
1043 | cs->BC_Send_Data = &hfc_send_data; | ||
1044 | cs->bcs[0].BC_SetStack = setstack_2b; | ||
1045 | cs->bcs[1].BC_SetStack = setstack_2b; | ||
1046 | cs->bcs[0].BC_Close = close_2bs0; | ||
1047 | cs->bcs[1].BC_Close = close_2bs0; | ||
1048 | mode_2bs0(cs->bcs, 0, 0); | ||
1049 | mode_2bs0(cs->bcs + 1, 0, 1); | ||
1050 | } | ||
1051 | |||
1052 | void | ||
1053 | release2bds0(struct IsdnCardState *cs) | ||
1054 | { | ||
1055 | if (cs->bcs[0].hw.hfc.send) { | ||
1056 | kfree(cs->bcs[0].hw.hfc.send); | ||
1057 | cs->bcs[0].hw.hfc.send = NULL; | ||
1058 | } | ||
1059 | if (cs->bcs[1].hw.hfc.send) { | ||
1060 | kfree(cs->bcs[1].hw.hfc.send); | ||
1061 | cs->bcs[1].hw.hfc.send = NULL; | ||
1062 | } | ||
1063 | if (cs->hw.hfcD.send) { | ||
1064 | kfree(cs->hw.hfcD.send); | ||
1065 | cs->hw.hfcD.send = NULL; | ||
1066 | } | ||
1067 | } | ||
1068 | |||
1069 | void | ||
1070 | set_cs_func(struct IsdnCardState *cs) | ||
1071 | { | ||
1072 | cs->readisac = &readreghfcd; | ||
1073 | cs->writeisac = &writereghfcd; | ||
1074 | cs->readisacfifo = &dummyf; | ||
1075 | cs->writeisacfifo = &dummyf; | ||
1076 | cs->BC_Read_Reg = &ReadReg; | ||
1077 | cs->BC_Write_Reg = &WriteReg; | ||
1078 | cs->dbusytimer.function = (void *) hfc_dbusy_timer; | ||
1079 | cs->dbusytimer.data = (long) cs; | ||
1080 | init_timer(&cs->dbusytimer); | ||
1081 | INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); | ||
1082 | } | ||