aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/hysdn
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/hysdn
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/hysdn')
-rw-r--r--drivers/isdn/hysdn/Kconfig18
-rw-r--r--drivers/isdn/hysdn/Makefile11
-rw-r--r--drivers/isdn/hysdn/boardergo.c453
-rw-r--r--drivers/isdn/hysdn/boardergo.h100
-rw-r--r--drivers/isdn/hysdn/hycapi.c797
-rw-r--r--drivers/isdn/hysdn/hysdn_boot.c399
-rw-r--r--drivers/isdn/hysdn/hysdn_defs.h298
-rw-r--r--drivers/isdn/hysdn/hysdn_init.c254
-rw-r--r--drivers/isdn/hysdn/hysdn_net.c348
-rw-r--r--drivers/isdn/hysdn/hysdn_pof.h78
-rw-r--r--drivers/isdn/hysdn/hysdn_procconf.c443
-rw-r--r--drivers/isdn/hysdn/hysdn_proclog.c441
-rw-r--r--drivers/isdn/hysdn/hysdn_sched.c207
-rw-r--r--drivers/isdn/hysdn/ince1pc.h134
14 files changed, 3981 insertions, 0 deletions
diff --git a/drivers/isdn/hysdn/Kconfig b/drivers/isdn/hysdn/Kconfig
new file mode 100644
index 000000000000..c6d8a7042988
--- /dev/null
+++ b/drivers/isdn/hysdn/Kconfig
@@ -0,0 +1,18 @@
1#
2# Config.in for HYSDN ISDN driver
3#
4config HYSDN
5 tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)"
6 depends on m && PROC_FS && PCI && BROKEN_ON_SMP
7 help
8 Say Y here if you have one of Hypercope's active PCI ISDN cards
9 Champ, Ergo and Metro. You will then get a module called hysdn.
10 Please read the file <file:Documentation/isdn/README.hysdn> for more
11 information.
12
13config HYSDN_CAPI
14 bool "HYSDN CAPI 2.0 support"
15 depends on HYSDN && ISDN_CAPI
16 help
17 Say Y here if you like to use Hypercope's CAPI 2.0 interface.
18
diff --git a/drivers/isdn/hysdn/Makefile b/drivers/isdn/hysdn/Makefile
new file mode 100644
index 000000000000..da63b636267d
--- /dev/null
+++ b/drivers/isdn/hysdn/Makefile
@@ -0,0 +1,11 @@
1# Makefile for the hysdn ISDN device driver
2
3# Each configuration option enables a list of files.
4
5obj-$(CONFIG_HYSDN) += hysdn.o
6
7# Multipart objects.
8
9hysdn-y := hysdn_procconf.o hysdn_proclog.o boardergo.o \
10 hysdn_boot.o hysdn_sched.o hysdn_net.o hysdn_init.o
11hysdn-$(CONFIG_HYSDN_CAPI) += hycapi.o
diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
new file mode 100644
index 000000000000..e19a01a305a9
--- /dev/null
+++ b/drivers/isdn/hysdn/boardergo.c
@@ -0,0 +1,453 @@
1/* $Id: boardergo.c,v 1.5.6.7 2001/11/06 21:58:19 kai Exp $
2 *
3 * Linux driver for HYSDN cards, specific routines for ergo type boards.
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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 * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same
12 * DPRAM interface and layout with only minor differences all related
13 * stuff is done here, not in separate modules.
14 *
15 */
16
17#include <linux/config.h>
18#include <linux/sched.h>
19#include <linux/signal.h>
20#include <linux/kernel.h>
21#include <linux/ioport.h>
22#include <linux/interrupt.h>
23#include <linux/vmalloc.h>
24#include <linux/delay.h>
25#include <asm/io.h>
26
27#include "hysdn_defs.h"
28#include "boardergo.h"
29
30#define byteout(addr,val) outb(val,addr)
31#define bytein(addr) inb(addr)
32
33/***************************************************/
34/* The cards interrupt handler. Called from system */
35/***************************************************/
36static irqreturn_t
37ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs)
38{
39 hysdn_card *card = dev_id; /* parameter from irq */
40 tErgDpram *dpr;
41 ulong flags;
42 uchar volatile b;
43
44 if (!card)
45 return IRQ_NONE; /* error -> spurious interrupt */
46 if (!card->irq_enabled)
47 return IRQ_NONE; /* other device interrupting or irq switched off */
48
49 save_flags(flags);
50 cli(); /* no further irqs allowed */
51
52 if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
53 restore_flags(flags); /* restore old state */
54 return IRQ_NONE; /* no interrupt requested by E1 */
55 }
56 /* clear any pending ints on the board */
57 dpr = card->dpram;
58 b = dpr->ToPcInt; /* clear for ergo */
59 b |= dpr->ToPcIntMetro; /* same for metro */
60 b |= dpr->ToHyInt; /* and for champ */
61
62 /* start kernel task immediately after leaving all interrupts */
63 if (!card->hw_lock)
64 schedule_work(&card->irq_queue);
65 restore_flags(flags);
66 return IRQ_HANDLED;
67} /* ergo_interrupt */
68
69/******************************************************************************/
70/* ergo_irq_bh is the function called by the immediate kernel task list after */
71/* being activated with queue_task and no interrupts active. This task is the */
72/* only one handling data transfer from or to the card after booting. The task */
73/* may be queued from everywhere (interrupts included). */
74/******************************************************************************/
75static void
76ergo_irq_bh(hysdn_card * card)
77{
78 tErgDpram *dpr;
79 int again;
80 ulong flags;
81
82 if (card->state != CARD_STATE_RUN)
83 return; /* invalid call */
84
85 dpr = card->dpram; /* point to DPRAM */
86
87 save_flags(flags);
88 cli();
89 if (card->hw_lock) {
90 restore_flags(flags); /* hardware currently unavailable */
91 return;
92 }
93 card->hw_lock = 1; /* we now lock the hardware */
94
95 do {
96 sti(); /* reenable other ints */
97 again = 0; /* assume loop not to be repeated */
98
99 if (!dpr->ToHyFlag) {
100 /* we are able to send a buffer */
101
102 if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel,
103 ERG_TO_HY_BUF_SIZE)) {
104 dpr->ToHyFlag = 1; /* enable tx */
105 again = 1; /* restart loop */
106 }
107 } /* we are able to send a buffer */
108 if (dpr->ToPcFlag) {
109 /* a message has arrived for us, handle it */
110
111 if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) {
112 dpr->ToPcFlag = 0; /* we worked the data */
113 again = 1; /* restart loop */
114 }
115 } /* a message has arrived for us */
116 cli(); /* no further ints */
117 if (again) {
118 dpr->ToHyInt = 1;
119 dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
120 } else
121 card->hw_lock = 0; /* free hardware again */
122 } while (again); /* until nothing more to do */
123
124 restore_flags(flags);
125} /* ergo_irq_bh */
126
127
128/*********************************************************/
129/* stop the card (hardware reset) and disable interrupts */
130/*********************************************************/
131static void
132ergo_stopcard(hysdn_card * card)
133{
134 ulong flags;
135 uchar val;
136
137 hysdn_net_release(card); /* first release the net device if existing */
138#ifdef CONFIG_HYSDN_CAPI
139 hycapi_capi_stop(card);
140#endif /* CONFIG_HYSDN_CAPI */
141 save_flags(flags);
142 cli();
143 val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */
144 val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */
145 byteout(card->iobase + PCI9050_INTR_REG, val);
146 card->irq_enabled = 0;
147 byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET); /* reset E1 processor */
148 card->state = CARD_STATE_UNUSED;
149 card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */
150
151 restore_flags(flags);
152} /* ergo_stopcard */
153
154/**************************************************************************/
155/* enable or disable the cards error log. The event is queued if possible */
156/**************************************************************************/
157static void
158ergo_set_errlog_state(hysdn_card * card, int on)
159{
160 ulong flags;
161
162 if (card->state != CARD_STATE_RUN) {
163 card->err_log_state = ERRLOG_STATE_OFF; /* must be off */
164 return;
165 }
166 save_flags(flags);
167 cli();
168
169 if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
170 ((card->err_log_state == ERRLOG_STATE_ON) && on)) {
171 restore_flags(flags);
172 return; /* nothing to do */
173 }
174 if (on)
175 card->err_log_state = ERRLOG_STATE_START; /* request start */
176 else
177 card->err_log_state = ERRLOG_STATE_STOP; /* request stop */
178
179 restore_flags(flags);
180 schedule_work(&card->irq_queue);
181} /* ergo_set_errlog_state */
182
183/******************************************/
184/* test the cards RAM and return 0 if ok. */
185/******************************************/
186static const char TestText[36] = "This Message is filler, why read it";
187
188static int
189ergo_testram(hysdn_card * card)
190{
191 tErgDpram *dpr = card->dpram;
192
193 memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable)); /* clear all Traps */
194 dpr->ToHyInt = 1; /* E1 INTR state forced */
195
196 memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText,
197 sizeof(TestText));
198 if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText,
199 sizeof(TestText)))
200 return (-1);
201
202 memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText,
203 sizeof(TestText));
204 if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText,
205 sizeof(TestText)))
206 return (-1);
207
208 return (0);
209} /* ergo_testram */
210
211/*****************************************************************************/
212/* this function is intended to write stage 1 boot image to the cards buffer */
213/* this is done in two steps. First the 1024 hi-words are written (offs=0), */
214/* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the */
215/* PCI-write-buffers flushed and the card is taken out of reset. */
216/* The function then waits for a reaction of the E1 processor or a timeout. */
217/* Negative return values are interpreted as errors. */
218/*****************************************************************************/
219static int
220ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs)
221{
222 uchar *dst;
223 tErgDpram *dpram;
224 int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */
225
226 if (card->debug_flags & LOG_POF_CARD)
227 hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs);
228
229 dst = card->dpram; /* pointer to start of DPRAM */
230 dst += (offs + ERG_DPRAM_FILL_SIZE); /* offset in the DPRAM */
231 while (cnt--) {
232 *dst++ = *(buf + 1); /* high byte */
233 *dst++ = *buf; /* low byte */
234 dst += 2; /* point to next longword */
235 buf += 2; /* buffer only filled with words */
236 }
237
238 /* if low words (offs = 2) have been written, clear the rest of the DPRAM, */
239 /* flush the PCI-write-buffer and take the E1 out of reset */
240 if (offs) {
241 memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE); /* fill the DPRAM still not cleared */
242 dpram = card->dpram; /* get pointer to dpram structure */
243 dpram->ToHyNoDpramErrLog = 0xFF; /* write a dpram register */
244 while (!dpram->ToHyNoDpramErrLog); /* reread volatile register to flush PCI */
245
246 byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN); /* start E1 processor */
247 /* the interrupts are still masked */
248
249 sti();
250 msleep_interruptible(20); /* Timeout 20ms */
251
252 if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) {
253 if (card->debug_flags & LOG_POF_CARD)
254 hysdn_addlog(card, "ERGO: write bootldr no answer");
255 return (-ERR_BOOTIMG_FAIL);
256 }
257 } /* start_boot_img */
258 return (0); /* successful */
259} /* ergo_writebootimg */
260
261/********************************************************************************/
262/* ergo_writebootseq writes the buffer containing len bytes to the E1 processor */
263/* using the boot spool mechanism. If everything works fine 0 is returned. In */
264/* case of errors a negative error value is returned. */
265/********************************************************************************/
266static int
267ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len)
268{
269 tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram;
270 uchar *dst;
271 uchar buflen;
272 int nr_write;
273 uchar tmp_rdptr;
274 uchar wr_mirror;
275 int i;
276
277 if (card->debug_flags & LOG_POF_CARD)
278 hysdn_addlog(card, "ERGO: write boot seq len=%d ", len);
279
280 dst = sp->Data; /* point to data in spool structure */
281 buflen = sp->Len; /* maximum len of spooled data */
282 wr_mirror = sp->WrPtr; /* only once read */
283 sti();
284
285 /* try until all bytes written or error */
286 i = 0x1000; /* timeout value */
287 while (len) {
288
289 /* first determine the number of bytes that may be buffered */
290 do {
291 tmp_rdptr = sp->RdPtr; /* first read the pointer */
292 i--; /* decrement timeout */
293 } while (i && (tmp_rdptr != sp->RdPtr)); /* wait for stable pointer */
294
295 if (!i) {
296 if (card->debug_flags & LOG_POF_CARD)
297 hysdn_addlog(card, "ERGO: write boot seq timeout");
298 return (-ERR_BOOTSEQ_FAIL); /* value not stable -> timeout */
299 }
300 if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0)
301 nr_write += buflen; /* now we got number of free bytes - 1 in buffer */
302
303 if (!nr_write)
304 continue; /* no free bytes in buffer */
305
306 if (nr_write > len)
307 nr_write = len; /* limit if last few bytes */
308 i = 0x1000; /* reset timeout value */
309
310 /* now we know how much bytes we may put in the puffer */
311 len -= nr_write; /* we savely could adjust len before output */
312 while (nr_write--) {
313 *(dst + wr_mirror) = *buf++; /* output one byte */
314 if (++wr_mirror >= buflen)
315 wr_mirror = 0;
316 sp->WrPtr = wr_mirror; /* announce the next byte to E1 */
317 } /* while (nr_write) */
318
319 } /* while (len) */
320 return (0);
321} /* ergo_writebootseq */
322
323/***********************************************************************************/
324/* ergo_waitpofready waits for a maximum of 10 seconds for the completition of the */
325/* boot process. If the process has been successful 0 is returned otherwise a */
326/* negative error code is returned. */
327/***********************************************************************************/
328static int
329ergo_waitpofready(struct HYSDN_CARD *card)
330{
331 tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */
332 int timecnt = 10000 / 50; /* timeout is 10 secs max. */
333 ulong flags;
334 int msg_size;
335 int i;
336
337 if (card->debug_flags & LOG_POF_CARD)
338 hysdn_addlog(card, "ERGO: waiting for pof ready");
339 while (timecnt--) {
340 /* wait until timeout */
341
342 if (dpr->ToPcFlag) {
343 /* data has arrived */
344
345 if ((dpr->ToPcChannel != CHAN_SYSTEM) ||
346 (dpr->ToPcSize < MIN_RDY_MSG_SIZE) ||
347 (dpr->ToPcSize > MAX_RDY_MSG_SIZE) ||
348 ((*(ulong *) dpr->ToPcBuf) != RDY_MAGIC))
349 break; /* an error occurred */
350
351 /* Check for additional data delivered during SysReady */
352 msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE;
353 if (msg_size > 0)
354 if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size))
355 break;
356
357 if (card->debug_flags & LOG_POF_RECORD)
358 hysdn_addlog(card, "ERGO: pof boot success");
359 save_flags(flags);
360 cli();
361
362 card->state = CARD_STATE_RUN; /* now card is running */
363 /* enable the cards interrupt */
364 byteout(card->iobase + PCI9050_INTR_REG,
365 bytein(card->iobase + PCI9050_INTR_REG) |
366 (PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1));
367 card->irq_enabled = 1; /* we are ready to receive interrupts */
368
369 dpr->ToPcFlag = 0; /* reset data indicator */
370 dpr->ToHyInt = 1;
371 dpr->ToPcInt = 1; /* interrupt to E1 for all cards */
372
373 restore_flags(flags);
374 if ((hynet_enable & (1 << card->myid))
375 && (i = hysdn_net_create(card)))
376 {
377 ergo_stopcard(card);
378 card->state = CARD_STATE_BOOTERR;
379 return (i);
380 }
381#ifdef CONFIG_HYSDN_CAPI
382 if((i = hycapi_capi_create(card))) {
383 printk(KERN_WARNING "HYSDN: failed to create capi-interface.\n");
384 }
385#endif /* CONFIG_HYSDN_CAPI */
386 return (0); /* success */
387 } /* data has arrived */
388 sti();
389 msleep_interruptible(50); /* Timeout 50ms */
390 } /* wait until timeout */
391
392 if (card->debug_flags & LOG_POF_CARD)
393 hysdn_addlog(card, "ERGO: pof boot ready timeout");
394 return (-ERR_POF_TIMEOUT);
395} /* ergo_waitpofready */
396
397
398
399/************************************************************************************/
400/* release the cards hardware. Before releasing do a interrupt disable and hardware */
401/* reset. Also unmap dpram. */
402/* Use only during module release. */
403/************************************************************************************/
404static void
405ergo_releasehardware(hysdn_card * card)
406{
407 ergo_stopcard(card); /* first stop the card if not already done */
408 free_irq(card->irq, card); /* release interrupt */
409 release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */
410 release_region(card->iobase + PCI9050_USER_IO, 1);
411 vfree(card->dpram);
412 card->dpram = NULL; /* release shared mem */
413} /* ergo_releasehardware */
414
415
416/*********************************************************************************/
417/* acquire the needed hardware ports and map dpram. If an error occurs a nonzero */
418/* value is returned. */
419/* Use only during module init. */
420/*********************************************************************************/
421int
422ergo_inithardware(hysdn_card * card)
423{
424 if (!request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN"))
425 return (-1);
426 if (!request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN")) {
427 release_region(card->iobase + PCI9050_INTR_REG, 1);
428 return (-1); /* ports already in use */
429 }
430 card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1;
431 if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) {
432 release_region(card->iobase + PCI9050_INTR_REG, 1);
433 release_region(card->iobase + PCI9050_USER_IO, 1);
434 return (-1);
435 }
436
437 ergo_stopcard(card); /* disable interrupts */
438 if (request_irq(card->irq, ergo_interrupt, SA_SHIRQ, "HYSDN", card)) {
439 ergo_releasehardware(card); /* return the acquired hardware */
440 return (-1);
441 }
442 /* success, now setup the function pointers */
443 card->stopcard = ergo_stopcard;
444 card->releasehardware = ergo_releasehardware;
445 card->testram = ergo_testram;
446 card->writebootimg = ergo_writebootimg;
447 card->writebootseq = ergo_writebootseq;
448 card->waitpofready = ergo_waitpofready;
449 card->set_errlog_state = ergo_set_errlog_state;
450 INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card);
451
452 return (0);
453} /* ergo_inithardware */
diff --git a/drivers/isdn/hysdn/boardergo.h b/drivers/isdn/hysdn/boardergo.h
new file mode 100644
index 000000000000..b56ff0889ead
--- /dev/null
+++ b/drivers/isdn/hysdn/boardergo.h
@@ -0,0 +1,100 @@
1/* $Id: boardergo.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..).
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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
14/************************************************/
15/* defines for the dual port memory of the card */
16/************************************************/
17#define ERG_DPRAM_PAGE_SIZE 0x2000 /* DPRAM occupies a 8K page */
18#define BOOT_IMG_SIZE 4096
19#define ERG_DPRAM_FILL_SIZE (ERG_DPRAM_PAGE_SIZE - BOOT_IMG_SIZE)
20
21#define ERG_TO_HY_BUF_SIZE 0x0E00 /* 3072 bytes buffer size to card */
22#define ERG_TO_PC_BUF_SIZE 0x0E00 /* 3072 bytes to PC, too */
23
24/* following DPRAM layout copied from OS2-driver boarderg.h */
25typedef struct ErgDpram_tag {
26/*0000 */ uchar ToHyBuf[ERG_TO_HY_BUF_SIZE];
27/*0E00 */ uchar ToPcBuf[ERG_TO_PC_BUF_SIZE];
28
29 /*1C00 */ uchar bSoftUart[SIZE_RSV_SOFT_UART];
30 /* size 0x1B0 */
31
32 /*1DB0 *//* tErrLogEntry */ uchar volatile ErrLogMsg[64];
33 /* size 64 bytes */
34 /*1DB0 ulong ulErrType; */
35 /*1DB4 ulong ulErrSubtype; */
36 /*1DB8 ulong ucTextSize; */
37 /*1DB9 ulong ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */
38 /*1DF0 */
39
40/*1DF0 */ word volatile ToHyChannel;
41/*1DF2 */ word volatile ToHySize;
42 /*1DF4 */ uchar volatile ToHyFlag;
43 /* !=0: msg for Hy waiting */
44 /*1DF5 */ uchar volatile ToPcFlag;
45 /* !=0: msg for PC waiting */
46/*1DF6 */ word volatile ToPcChannel;
47/*1DF8 */ word volatile ToPcSize;
48 /*1DFA */ uchar bRes1DBA[0x1E00 - 0x1DFA];
49 /* 6 bytes */
50
51/*1E00 */ uchar bRestOfEntryTbl[0x1F00 - 0x1E00];
52/*1F00 */ ulong TrapTable[62];
53 /*1FF8 */ uchar bRes1FF8[0x1FFB - 0x1FF8];
54 /* low part of reset vetor */
55/*1FFB */ uchar ToPcIntMetro;
56 /* notes:
57 * - metro has 32-bit boot ram - accessing
58 * ToPcInt and ToHyInt would be the same;
59 * so we moved ToPcInt to 1FFB.
60 * Because on the PC side both vars are
61 * readonly (reseting on int from E1 to PC),
62 * we can read both vars on both cards
63 * without destroying anything.
64 * - 1FFB is the high byte of the reset vector,
65 * so E1 side should NOT change this byte
66 * when writing!
67 */
68/*1FFC */ uchar volatile ToHyNoDpramErrLog;
69 /* note: ToHyNoDpramErrLog is used to inform
70 * boot loader, not to use DPRAM based
71 * ErrLog; when DOS driver is rewritten
72 * this becomes obsolete
73 */
74/*1FFD */ uchar bRes1FFD;
75 /*1FFE */ uchar ToPcInt;
76 /* E1_intclear; on CHAMP2: E1_intset */
77 /*1FFF */ uchar ToHyInt;
78 /* E1_intset; on CHAMP2: E1_intclear */
79} tErgDpram;
80
81/**********************************************/
82/* PCI9050 controller local register offsets: */
83/* copied from boarderg.c */
84/**********************************************/
85#define PCI9050_INTR_REG 0x4C /* Interrupt register */
86#define PCI9050_USER_IO 0x51 /* User I/O register */
87
88 /* bitmask for PCI9050_INTR_REG: */
89#define PCI9050_INTR_REG_EN1 0x01 /* 1= enable (def.), 0= disable */
90#define PCI9050_INTR_REG_POL1 0x02 /* 1= active high (def.), 0= active low */
91#define PCI9050_INTR_REG_STAT1 0x04 /* 1= intr. active, 0= intr. not active (def.) */
92#define PCI9050_INTR_REG_ENPCI 0x40 /* 1= PCI interrupts enable (def.) */
93
94 /* bitmask for PCI9050_USER_IO: */
95#define PCI9050_USER_IO_EN3 0x02 /* 1= disable , 0= enable (def.) */
96#define PCI9050_USER_IO_DIR3 0x04 /* 1= output (def.), 0= input */
97#define PCI9050_USER_IO_DAT3 0x08 /* 1= high (def.) , 0= low */
98
99#define PCI9050_E1_RESET ( PCI9050_USER_IO_DIR3) /* 0x04 */
100#define PCI9050_E1_RUN (PCI9050_USER_IO_DAT3|PCI9050_USER_IO_DIR3) /* 0x0C */
diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
new file mode 100644
index 000000000000..8ee25b2ccce1
--- /dev/null
+++ b/drivers/isdn/hysdn/hycapi.c
@@ -0,0 +1,797 @@
1/* $Id: hycapi.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, CAPI2.0-Interface.
4 *
5 * Author Ulrich Albrecht <u.albrecht@hypercope.de> for Hypercope GmbH
6 * Copyright 2000 by Hypercope GmbH
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/module.h>
14#include <linux/version.h>
15#include <linux/signal.h>
16#include <linux/kernel.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19
20#define VER_DRIVER 0
21#define VER_CARDTYPE 1
22#define VER_HWID 2
23#define VER_SERIAL 3
24#define VER_OPTION 4
25#define VER_PROTO 5
26#define VER_PROFILE 6
27#define VER_CAPI 7
28
29#include "hysdn_defs.h"
30#include <linux/kernelcapi.h>
31
32static char hycapi_revision[]="$Revision: 1.8.6.4 $";
33
34unsigned int hycapi_enable = 0xffffffff;
35MODULE_PARM(hycapi_enable, "i");
36
37typedef struct _hycapi_appl {
38 unsigned int ctrl_mask;
39 capi_register_params rp;
40 struct sk_buff *listen_req[CAPI_MAXCONTR];
41} hycapi_appl;
42
43static hycapi_appl hycapi_applications[CAPI_MAXAPPL];
44
45static inline int _hycapi_appCheck(int app_id, int ctrl_no)
46{
47 if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) ||
48 (app_id > CAPI_MAXAPPL))
49 {
50 printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no);
51 return -1;
52 }
53 return ((hycapi_applications[app_id-1].ctrl_mask & (1 << (ctrl_no-1))) != 0);
54}
55
56/******************************
57Kernel-Capi callback reset_ctr
58******************************/
59
60void
61hycapi_reset_ctr(struct capi_ctr *ctrl)
62{
63 hycapictrl_info *cinfo = ctrl->driverdata;
64
65#ifdef HYCAPI_PRINTFNAMES
66 printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n");
67#endif
68 capilib_release(&cinfo->ncci_head);
69 capi_ctr_reseted(ctrl);
70}
71
72/******************************
73Kernel-Capi callback remove_ctr
74******************************/
75
76void
77hycapi_remove_ctr(struct capi_ctr *ctrl)
78{
79 int i;
80 hycapictrl_info *cinfo = NULL;
81 hysdn_card *card = NULL;
82#ifdef HYCAPI_PRINTFNAMES
83 printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n");
84#endif
85 cinfo = (hycapictrl_info *)(ctrl->driverdata);
86 if(!cinfo) {
87 printk(KERN_ERR "No hycapictrl_info set!");
88 return;
89 }
90 card = cinfo->card;
91 capi_ctr_suspend_output(ctrl);
92 for(i=0; i<CAPI_MAXAPPL;i++) {
93 if(hycapi_applications[i].listen_req[ctrl->cnr-1]) {
94 kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr-1]);
95 hycapi_applications[i].listen_req[ctrl->cnr-1] = NULL;
96 }
97 }
98 detach_capi_ctr(ctrl);
99 ctrl->driverdata = NULL;
100 kfree(card->hyctrlinfo);
101
102
103 card->hyctrlinfo = NULL;
104}
105
106/***********************************************************
107
108Queue a CAPI-message to the controller.
109
110***********************************************************/
111
112static void
113hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb)
114{
115 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
116 hysdn_card *card = cinfo->card;
117
118 spin_lock_irq(&cinfo->lock);
119#ifdef HYCAPI_PRINTFNAMES
120 printk(KERN_NOTICE "hycapi_send_message\n");
121#endif
122 cinfo->skbs[cinfo->in_idx++] = skb; /* add to buffer list */
123 if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB)
124 cinfo->in_idx = 0; /* wrap around */
125 cinfo->sk_count++; /* adjust counter */
126 if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) {
127 /* inform upper layers we're full */
128 printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n",
129 card->myid);
130 capi_ctr_suspend_output(ctrl);
131 }
132 cinfo->tx_skb = skb;
133 spin_unlock_irq(&cinfo->lock);
134 schedule_work(&card->irq_queue);
135}
136
137/***********************************************************
138hycapi_register_internal
139
140Send down the CAPI_REGISTER-Command to the controller.
141This functions will also be used if the adapter has been rebooted to
142re-register any applications in the private list.
143
144************************************************************/
145
146static void
147hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl,
148 capi_register_params *rp)
149{
150 char ExtFeatureDefaults[] = "49 /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*";
151 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
152 hysdn_card *card = cinfo->card;
153 struct sk_buff *skb;
154 __u16 len;
155 __u8 _command = 0xa0, _subcommand = 0x80;
156 __u16 MessageNumber = 0x0000;
157 __u16 MessageBufferSize = 0;
158 int slen = strlen(ExtFeatureDefaults);
159#ifdef HYCAPI_PRINTFNAMES
160 printk(KERN_NOTICE "hycapi_register_appl\n");
161#endif
162 MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen;
163
164 len = CAPI_MSG_BASELEN + 8 + slen + 1;
165 if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
166 printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n",
167 card->myid);
168 return;
169 }
170 memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16));
171 memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16));
172 memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command));
173 memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand));
174 memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16));
175 memcpy(skb_put(skb,sizeof(__u16)), &MessageBufferSize, sizeof(__u16));
176 memcpy(skb_put(skb,sizeof(__u16)), &(rp->level3cnt), sizeof(__u16));
177 memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablkcnt), sizeof(__u16));
178 memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablklen), sizeof(__u16));
179 memcpy(skb_put(skb,slen), ExtFeatureDefaults, slen);
180 hycapi_applications[appl-1].ctrl_mask |= (1 << (ctrl->cnr-1));
181 hycapi_send_message(ctrl, skb);
182}
183
184/************************************************************
185hycapi_restart_internal
186
187After an adapter has been rebootet, re-register all applications and
188send a LISTEN_REQ (if there has been such a thing )
189
190*************************************************************/
191
192static void hycapi_restart_internal(struct capi_ctr *ctrl)
193{
194 int i;
195 struct sk_buff *skb;
196#ifdef HYCAPI_PRINTFNAMES
197 printk(KERN_WARNING "HYSDN: hycapi_restart_internal");
198#endif
199 for(i=0; i<CAPI_MAXAPPL; i++) {
200 if(_hycapi_appCheck(i+1, ctrl->cnr) == 1) {
201 hycapi_register_internal(ctrl, i+1,
202 &hycapi_applications[i].rp);
203 if(hycapi_applications[i].listen_req[ctrl->cnr-1]) {
204 skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr-1], GFP_ATOMIC);
205 hycapi_sendmsg_internal(ctrl, skb);
206 }
207 }
208 }
209}
210
211/*************************************************************
212Register an application.
213Error-checking is done for CAPI-compliance.
214
215The application is recorded in the internal list.
216*************************************************************/
217
218void
219hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl,
220 capi_register_params *rp)
221{
222 int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0;
223 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
224 hysdn_card *card = cinfo->card;
225 int chk = _hycapi_appCheck(appl, ctrl->cnr);
226 if(chk < 0) {
227 return;
228 }
229 if(chk == 1) {
230 printk(KERN_INFO "HYSDN: apl %d already registered\n", appl);
231 return;
232 }
233 MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt;
234 rp->datablkcnt = MaxBDataBlocks;
235 MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen ;
236 rp->datablklen = MaxBDataLen;
237
238 MaxLogicalConnections = rp->level3cnt;
239 if (MaxLogicalConnections < 0) {
240 MaxLogicalConnections = card->bchans * -MaxLogicalConnections;
241 }
242 if (MaxLogicalConnections == 0) {
243 MaxLogicalConnections = card->bchans;
244 }
245
246 rp->level3cnt = MaxLogicalConnections;
247 memcpy(&hycapi_applications[appl-1].rp,
248 rp, sizeof(capi_register_params));
249}
250
251/*********************************************************************
252
253hycapi_release_internal
254
255Send down a CAPI_RELEASE to the controller.
256*********************************************************************/
257
258static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl)
259{
260 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
261 hysdn_card *card = cinfo->card;
262 struct sk_buff *skb;
263 __u16 len;
264 __u8 _command = 0xa1, _subcommand = 0x80;
265 __u16 MessageNumber = 0x0000;
266
267 capilib_release_appl(&cinfo->ncci_head, appl);
268
269#ifdef HYCAPI_PRINTFNAMES
270 printk(KERN_NOTICE "hycapi_release_appl\n");
271#endif
272 len = CAPI_MSG_BASELEN;
273 if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
274 printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n",
275 card->myid);
276 return;
277 }
278 memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16));
279 memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16));
280 memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command));
281 memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand));
282 memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16));
283 hycapi_send_message(ctrl, skb);
284 hycapi_applications[appl-1].ctrl_mask &= ~(1 << (ctrl->cnr-1));
285}
286
287/******************************************************************
288hycapi_release_appl
289
290Release the application from the internal list an remove it's
291registration at controller-level
292******************************************************************/
293
294void
295hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl)
296{
297 int chk;
298
299 chk = _hycapi_appCheck(appl, ctrl->cnr);
300 if(chk<0) {
301 printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr);
302 return;
303 }
304 if(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]) {
305 kfree_skb(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]);
306 hycapi_applications[appl-1].listen_req[ctrl->cnr-1] = NULL;
307 }
308 if(chk == 1)
309 {
310 hycapi_release_internal(ctrl, appl);
311 }
312}
313
314
315/**************************************************************
316Kill a single controller.
317**************************************************************/
318
319int hycapi_capi_release(hysdn_card *card)
320{
321 hycapictrl_info *cinfo = card->hyctrlinfo;
322 struct capi_ctr *ctrl;
323#ifdef HYCAPI_PRINTFNAMES
324 printk(KERN_NOTICE "hycapi_capi_release\n");
325#endif
326 if(cinfo) {
327 ctrl = &cinfo->capi_ctrl;
328 hycapi_remove_ctr(ctrl);
329 }
330 return 0;
331}
332
333/**************************************************************
334hycapi_capi_stop
335
336Stop CAPI-Output on a card. (e.g. during reboot)
337***************************************************************/
338
339int hycapi_capi_stop(hysdn_card *card)
340{
341 hycapictrl_info *cinfo = card->hyctrlinfo;
342 struct capi_ctr *ctrl;
343#ifdef HYCAPI_PRINTFNAMES
344 printk(KERN_NOTICE "hycapi_capi_stop\n");
345#endif
346 if(cinfo) {
347 ctrl = &cinfo->capi_ctrl;
348/* ctrl->suspend_output(ctrl); */
349 capi_ctr_reseted(ctrl);
350 }
351 return 0;
352}
353
354/***************************************************************
355hycapi_send_message
356
357Send a message to the controller.
358
359Messages are parsed for their Command/Subcommand-type, and appropriate
360action's are performed.
361
362Note that we have to muck around with a 64Bit-DATA_REQ as there are
363firmware-releases that do not check the MsgLen-Indication!
364
365***************************************************************/
366
367u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
368{
369 __u16 appl_id;
370 int _len, _len2;
371 __u8 msghead[64];
372 hycapictrl_info *cinfo = ctrl->driverdata;
373 u16 retval = CAPI_NOERROR;
374
375 appl_id = CAPIMSG_APPID(skb->data);
376 switch(_hycapi_appCheck(appl_id, ctrl->cnr))
377 {
378 case 0:
379/* printk(KERN_INFO "Need to register\n"); */
380 hycapi_register_internal(ctrl,
381 appl_id,
382 &(hycapi_applications[appl_id-1].rp));
383 break;
384 case 1:
385 break;
386 default:
387 printk(KERN_ERR "HYCAPI: Controller mixup!\n");
388 retval = CAPI_ILLAPPNR;
389 goto out;
390 }
391 switch(CAPIMSG_CMD(skb->data)) {
392 case CAPI_DISCONNECT_B3_RESP:
393 capilib_free_ncci(&cinfo->ncci_head, appl_id,
394 CAPIMSG_NCCI(skb->data));
395 break;
396 case CAPI_DATA_B3_REQ:
397 _len = CAPIMSG_LEN(skb->data);
398 if (_len > 22) {
399 _len2 = _len - 22;
400 memcpy(msghead, skb->data, 22);
401 memcpy(skb->data + _len2, msghead, 22);
402 skb_pull(skb, _len2);
403 CAPIMSG_SETLEN(skb->data, 22);
404 retval = capilib_data_b3_req(&cinfo->ncci_head,
405 CAPIMSG_APPID(skb->data),
406 CAPIMSG_NCCI(skb->data),
407 CAPIMSG_MSGID(skb->data));
408 }
409 break;
410 case CAPI_LISTEN_REQ:
411 if(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1])
412 {
413 kfree_skb(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]);
414 hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = NULL;
415 }
416 if (!(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = skb_copy(skb, GFP_ATOMIC)))
417 {
418 printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n");
419 }
420 break;
421 default:
422 break;
423 }
424 out:
425 if (retval == CAPI_NOERROR)
426 hycapi_sendmsg_internal(ctrl, skb);
427 else
428 dev_kfree_skb_any(skb);
429
430 return retval;
431}
432
433/*********************************************************************
434hycapi_read_proc
435
436Informations provided in the /proc/capi-entries.
437
438*********************************************************************/
439
440int hycapi_read_proc(char *page, char **start, off_t off,
441 int count, int *eof, struct capi_ctr *ctrl)
442{
443 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
444 hysdn_card *card = cinfo->card;
445 int len = 0;
446 char *s;
447#ifdef HYCAPI_PRINTFNAMES
448 printk(KERN_NOTICE "hycapi_read_proc\n");
449#endif
450 len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname);
451 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase);
452 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
453
454 switch (card->brdtype) {
455 case BD_PCCARD: s = "HYSDN Hycard"; break;
456 case BD_ERGO: s = "HYSDN Ergo2"; break;
457 case BD_METRO: s = "HYSDN Metro4"; break;
458 case BD_CHAMP2: s = "HYSDN Champ2"; break;
459 case BD_PLEXUS: s = "HYSDN Plexus30"; break;
460 default: s = "???"; break;
461 }
462 len += sprintf(page+len, "%-16s %s\n", "type", s);
463 if ((s = cinfo->version[VER_DRIVER]) != 0)
464 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
465 if ((s = cinfo->version[VER_CARDTYPE]) != 0)
466 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
467 if ((s = cinfo->version[VER_SERIAL]) != 0)
468 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
469
470 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
471
472 if (off+count >= len)
473 *eof = 1;
474 if (len < off)
475 return 0;
476 *start = page + off;
477 return ((count < len-off) ? count : len-off);
478}
479
480/**************************************************************
481hycapi_load_firmware
482
483This does NOT load any firmware, but the callback somehow is needed
484on capi-interface registration.
485
486**************************************************************/
487
488int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
489{
490#ifdef HYCAPI_PRINTFNAMES
491 printk(KERN_NOTICE "hycapi_load_firmware\n");
492#endif
493 return 0;
494}
495
496
497char *hycapi_procinfo(struct capi_ctr *ctrl)
498{
499 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata);
500#ifdef HYCAPI_PRINTFNAMES
501 printk(KERN_NOTICE "hycapi_proc_info\n");
502#endif
503 if (!cinfo)
504 return "";
505 sprintf(cinfo->infobuf, "%s %s 0x%x %d %s",
506 cinfo->cardname[0] ? cinfo->cardname : "-",
507 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
508 cinfo->card ? cinfo->card->iobase : 0x0,
509 cinfo->card ? cinfo->card->irq : 0,
510 hycapi_revision
511 );
512 return cinfo->infobuf;
513}
514
515/******************************************************************
516hycapi_rx_capipkt
517
518Receive a capi-message.
519
520All B3_DATA_IND are converted to 64K-extension compatible format.
521New nccis are created if necessary.
522*******************************************************************/
523
524void
525hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len)
526{
527 struct sk_buff *skb;
528 hycapictrl_info *cinfo = card->hyctrlinfo;
529 struct capi_ctr *ctrl;
530 __u16 ApplId;
531 __u16 MsgLen, info;
532 __u16 len2, CapiCmd;
533 __u32 CP64[2] = {0,0};
534#ifdef HYCAPI_PRINTFNAMES
535 printk(KERN_NOTICE "hycapi_rx_capipkt\n");
536#endif
537 if(!cinfo) {
538 return;
539 }
540 ctrl = &cinfo->capi_ctrl;
541 if(len < CAPI_MSG_BASELEN) {
542 printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n",
543 card->myid, len);
544 return;
545 }
546 MsgLen = CAPIMSG_LEN(buf);
547 ApplId = CAPIMSG_APPID(buf);
548 CapiCmd = CAPIMSG_CMD(buf);
549
550 if((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) {
551 len2 = len + (30 - MsgLen);
552 if (!(skb = alloc_skb(len2, GFP_ATOMIC))) {
553 printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n",
554 card->myid);
555 return;
556 }
557 memcpy(skb_put(skb, MsgLen), buf, MsgLen);
558 memcpy(skb_put(skb, 2*sizeof(__u32)), CP64, 2* sizeof(__u32));
559 memcpy(skb_put(skb, len - MsgLen), buf + MsgLen,
560 len - MsgLen);
561 CAPIMSG_SETLEN(skb->data, 30);
562 } else {
563 if (!(skb = alloc_skb(len, GFP_ATOMIC))) {
564 printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n",
565 card->myid);
566 return;
567 }
568 memcpy(skb_put(skb, len), buf, len);
569 }
570 switch(CAPIMSG_CMD(skb->data))
571 {
572 case CAPI_CONNECT_B3_CONF:
573/* Check info-field for error-indication: */
574 info = CAPIMSG_U16(skb->data, 12);
575 switch(info)
576 {
577 case 0:
578 capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data),
579 hycapi_applications[ApplId-1].rp.datablkcnt);
580
581 break;
582 case 0x0001:
583 printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current "
584 "protocol. NCPI ignored.\n", card->myid);
585 break;
586 case 0x2001:
587 printk(KERN_ERR "HYSDN Card%d: Message not supported in"
588 " current state\n", card->myid);
589 break;
590 case 0x2002:
591 printk(KERN_ERR "HYSDN Card%d: invalid PLCI\n", card->myid);
592 break;
593 case 0x2004:
594 printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid);
595 break;
596 case 0x3008:
597 printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n",
598 card->myid);
599 break;
600 default:
601 printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n",
602 card->myid, info);
603 break;
604 }
605 break;
606 case CAPI_CONNECT_B3_IND:
607 capilib_new_ncci(&cinfo->ncci_head, ApplId,
608 CAPIMSG_NCCI(skb->data),
609 hycapi_applications[ApplId-1].rp.datablkcnt);
610 break;
611 case CAPI_DATA_B3_CONF:
612 capilib_data_b3_conf(&cinfo->ncci_head, ApplId,
613 CAPIMSG_NCCI(skb->data),
614 CAPIMSG_MSGID(skb->data));
615 break;
616 default:
617 break;
618 }
619 capi_ctr_handle_message(ctrl, ApplId, skb);
620}
621
622/******************************************************************
623hycapi_tx_capiack
624
625Internally acknowledge a msg sent. This will remove the msg from the
626internal queue.
627
628*******************************************************************/
629
630void hycapi_tx_capiack(hysdn_card * card)
631{
632 hycapictrl_info *cinfo = card->hyctrlinfo;
633#ifdef HYCAPI_PRINTFNAMES
634 printk(KERN_NOTICE "hycapi_tx_capiack\n");
635#endif
636 if(!cinfo) {
637 return;
638 }
639 spin_lock_irq(&cinfo->lock);
640 kfree_skb(cinfo->skbs[cinfo->out_idx]); /* free skb */
641 cinfo->skbs[cinfo->out_idx++] = NULL;
642 if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB)
643 cinfo->out_idx = 0; /* wrap around */
644
645 if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB) /* dec usage count */
646 capi_ctr_resume_output(&cinfo->capi_ctrl);
647 spin_unlock_irq(&cinfo->lock);
648}
649
650/***************************************************************
651hycapi_tx_capiget(hysdn_card *card)
652
653This is called when polling for messages to SEND.
654
655****************************************************************/
656
657struct sk_buff *
658hycapi_tx_capiget(hysdn_card *card)
659{
660 hycapictrl_info *cinfo = card->hyctrlinfo;
661 if(!cinfo) {
662 return (struct sk_buff *)NULL;
663 }
664 if (!cinfo->sk_count)
665 return (struct sk_buff *)NULL; /* nothing available */
666
667 return (cinfo->skbs[cinfo->out_idx]); /* next packet to send */
668}
669
670
671/**********************************************************
672int hycapi_init()
673
674attach the capi-driver to the kernel-capi.
675
676***********************************************************/
677
678int hycapi_init(void)
679{
680 int i;
681 for(i=0;i<CAPI_MAXAPPL;i++) {
682 memset(&(hycapi_applications[i]), 0, sizeof(hycapi_appl));
683 }
684 return(0);
685}
686
687/**************************************************************
688hycapi_cleanup(void)
689
690detach the capi-driver to the kernel-capi. Actually this should
691free some more ressources. Do that later.
692**************************************************************/
693
694void
695hycapi_cleanup(void)
696{
697}
698
699/********************************************************************
700hycapi_capi_create(hysdn_card *card)
701
702Attach the card with its capi-ctrl.
703*********************************************************************/
704
705static void hycapi_fill_profile(hysdn_card *card)
706{
707 hycapictrl_info *cinfo = NULL;
708 struct capi_ctr *ctrl = NULL;
709 cinfo = card->hyctrlinfo;
710 if(!cinfo) return;
711 ctrl = &cinfo->capi_ctrl;
712 strcpy(ctrl->manu, "Hypercope");
713 ctrl->version.majorversion = 2;
714 ctrl->version.minorversion = 0;
715 ctrl->version.majormanuversion = 3;
716 ctrl->version.minormanuversion = 2;
717 ctrl->profile.ncontroller = card->myid;
718 ctrl->profile.nbchannel = card->bchans;
719 ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER |
720 GLOBAL_OPTION_B_CHANNEL_OPERATION;
721 ctrl->profile.support1 = B1_PROT_64KBIT_HDLC |
722 (card->faxchans ? B1_PROT_T30 : 0) |
723 B1_PROT_64KBIT_TRANSPARENT;
724 ctrl->profile.support2 = B2_PROT_ISO7776 |
725 (card->faxchans ? B2_PROT_T30 : 0) |
726 B2_PROT_TRANSPARENT;
727 ctrl->profile.support3 = B3_PROT_TRANSPARENT |
728 B3_PROT_T90NL |
729 (card->faxchans ? B3_PROT_T30 : 0) |
730 (card->faxchans ? B3_PROT_T30EXT : 0) |
731 B3_PROT_ISO8208;
732}
733
734int
735hycapi_capi_create(hysdn_card *card)
736{
737 hycapictrl_info *cinfo = NULL;
738 struct capi_ctr *ctrl = NULL;
739 int retval;
740#ifdef HYCAPI_PRINTFNAMES
741 printk(KERN_NOTICE "hycapi_capi_create\n");
742#endif
743 if((hycapi_enable & (1 << card->myid)) == 0) {
744 return 1;
745 }
746 if (!card->hyctrlinfo) {
747 cinfo = (hycapictrl_info *) kmalloc(sizeof(hycapictrl_info), GFP_ATOMIC);
748 if (!cinfo) {
749 printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n");
750 return -ENOMEM;
751 }
752 memset(cinfo, 0, sizeof(hycapictrl_info));
753 card->hyctrlinfo = cinfo;
754 cinfo->card = card;
755 spin_lock_init(&cinfo->lock);
756 INIT_LIST_HEAD(&cinfo->ncci_head);
757
758 switch (card->brdtype) {
759 case BD_PCCARD: strcpy(cinfo->cardname,"HYSDN Hycard"); break;
760 case BD_ERGO: strcpy(cinfo->cardname,"HYSDN Ergo2"); break;
761 case BD_METRO: strcpy(cinfo->cardname,"HYSDN Metro4"); break;
762 case BD_CHAMP2: strcpy(cinfo->cardname,"HYSDN Champ2"); break;
763 case BD_PLEXUS: strcpy(cinfo->cardname,"HYSDN Plexus30"); break;
764 default: strcpy(cinfo->cardname,"HYSDN ???"); break;
765 }
766
767 ctrl = &cinfo->capi_ctrl;
768 ctrl->driver_name = "hycapi";
769 ctrl->driverdata = cinfo;
770 ctrl->register_appl = hycapi_register_appl;
771 ctrl->release_appl = hycapi_release_appl;
772 ctrl->send_message = hycapi_send_message;
773 ctrl->load_firmware = hycapi_load_firmware;
774 ctrl->reset_ctr = hycapi_reset_ctr;
775 ctrl->procinfo = hycapi_procinfo;
776 ctrl->ctr_read_proc = hycapi_read_proc;
777 strcpy(ctrl->name, cinfo->cardname);
778 ctrl->owner = THIS_MODULE;
779
780 retval = attach_capi_ctr(ctrl);
781 if (retval) {
782 printk(KERN_ERR "hycapi: attach controller failed.\n");
783 return -EBUSY;
784 }
785 /* fill in the blanks: */
786 hycapi_fill_profile(card);
787 capi_ctr_ready(ctrl);
788 } else {
789 /* resume output on stopped ctrl */
790 ctrl = &card->hyctrlinfo->capi_ctrl;
791 hycapi_fill_profile(card);
792 capi_ctr_ready(ctrl);
793 hycapi_restart_internal(ctrl);
794/* ctrl->resume_output(ctrl); */
795 }
796 return 0;
797}
diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c
new file mode 100644
index 000000000000..6c04281e57b8
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_boot.c
@@ -0,0 +1,399 @@
1/* $Id: hysdn_boot.c,v 1.4.6.4 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards
4 * specific routines for booting and pof handling
5 *
6 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
7 * Copyright 1999 by Werner Cornelius (werner@titro.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include <linux/vmalloc.h>
15#include <linux/slab.h>
16#include <asm/uaccess.h>
17
18#include "hysdn_defs.h"
19#include "hysdn_pof.h"
20
21/********************************/
22/* defines for pof read handler */
23/********************************/
24#define POF_READ_FILE_HEAD 0
25#define POF_READ_TAG_HEAD 1
26#define POF_READ_TAG_DATA 2
27
28/************************************************************/
29/* definition of boot specific data area. This data is only */
30/* needed during boot and so allocated dynamically. */
31/************************************************************/
32struct boot_data {
33 word Cryptor; /* for use with Decrypt function */
34 word Nrecs; /* records remaining in file */
35 uchar pof_state; /* actual state of read handler */
36 uchar is_crypted; /* card data is crypted */
37 int BufSize; /* actual number of bytes bufferd */
38 int last_error; /* last occurred error */
39 word pof_recid; /* actual pof recid */
40 ulong pof_reclen; /* total length of pof record data */
41 ulong pof_recoffset; /* actual offset inside pof record */
42 union {
43 uchar BootBuf[BOOT_BUF_SIZE]; /* buffer as byte count */
44 tPofRecHdr PofRecHdr; /* header for actual record/chunk */
45 tPofFileHdr PofFileHdr; /* header from POF file */
46 tPofTimeStamp PofTime; /* time information */
47 } buf;
48};
49
50/*****************************************************/
51/* start decryption of successive POF file chuncks. */
52/* */
53/* to be called at start of POF file reading, */
54/* before starting any decryption on any POF record. */
55/*****************************************************/
56void
57StartDecryption(struct boot_data *boot)
58{
59 boot->Cryptor = CRYPT_STARTTERM;
60} /* StartDecryption */
61
62
63/***************************************************************/
64/* decrypt complete BootBuf */
65/* NOTE: decryption must be applied to all or none boot tags - */
66/* to HI and LO boot loader and (all) seq tags, because */
67/* global Cryptor is started for whole POF. */
68/***************************************************************/
69void
70DecryptBuf(struct boot_data *boot, int cnt)
71{
72 uchar *bufp = boot->buf.BootBuf;
73
74 while (cnt--) {
75 boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0);
76 *bufp++ ^= (uchar) boot->Cryptor;
77 }
78} /* DecryptBuf */
79
80/********************************************************************************/
81/* pof_handle_data executes the required actions dependent on the active record */
82/* id. If successful 0 is returned, a negative value shows an error. */
83/********************************************************************************/
84static int
85pof_handle_data(hysdn_card * card, int datlen)
86{
87 struct boot_data *boot = card->boot; /* pointer to boot specific data */
88 long l;
89 uchar *imgp;
90 int img_len;
91
92 /* handle the different record types */
93 switch (boot->pof_recid) {
94
95 case TAG_TIMESTMP:
96 if (card->debug_flags & LOG_POF_RECORD)
97 hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText);
98 break;
99
100 case TAG_CBOOTDTA:
101 DecryptBuf(boot, datlen); /* we need to encrypt the buffer */
102 case TAG_BOOTDTA:
103 if (card->debug_flags & LOG_POF_RECORD)
104 hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
105 (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA",
106 datlen, boot->pof_recoffset);
107
108 if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) {
109 boot->last_error = EPOF_BAD_IMG_SIZE; /* invalid length */
110 return (boot->last_error);
111 }
112 imgp = boot->buf.BootBuf; /* start of buffer */
113 img_len = datlen; /* maximum length to transfer */
114
115 l = POF_BOOT_LOADER_OFF_IN_PAGE -
116 (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1));
117 if (l > 0) {
118 /* buffer needs to be truncated */
119 imgp += l; /* advance pointer */
120 img_len -= l; /* adjust len */
121 }
122 /* at this point no special handling for data wrapping over buffer */
123 /* is necessary, because the boot image always will be adjusted to */
124 /* match a page boundary inside the buffer. */
125 /* The buffer for the boot image on the card is filled in 2 cycles */
126 /* first the 1024 hi-words are put in the buffer, then the low 1024 */
127 /* word are handled in the same way with different offset. */
128
129 if (img_len > 0) {
130 /* data available for copy */
131 if ((boot->last_error =
132 card->writebootimg(card, imgp,
133 (boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0)
134 return (boot->last_error);
135 }
136 break; /* end of case boot image hi/lo */
137
138 case TAG_CABSDATA:
139 DecryptBuf(boot, datlen); /* we need to encrypt the buffer */
140 case TAG_ABSDATA:
141 if (card->debug_flags & LOG_POF_RECORD)
142 hysdn_addlog(card, "POF got %s len=%d offs=0x%lx",
143 (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
144 datlen, boot->pof_recoffset);
145
146 if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
147 return (boot->last_error); /* error writing data */
148
149 if (boot->pof_recoffset + datlen >= boot->pof_reclen)
150 return (card->waitpofready(card)); /* data completely spooled, wait for ready */
151
152 break; /* end of case boot seq data */
153
154 default:
155 if (card->debug_flags & LOG_POF_RECORD)
156 hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid,
157 datlen, boot->pof_recoffset);
158
159 break; /* simply skip record */
160 } /* switch boot->pof_recid */
161
162 return (0);
163} /* pof_handle_data */
164
165
166/******************************************************************************/
167/* pof_write_buffer is called when the buffer has been filled with the needed */
168/* number of data bytes. The number delivered is additionally supplied for */
169/* verification. The functions handles the data and returns the needed number */
170/* of bytes for the next action. If the returned value is 0 or less an error */
171/* occurred and booting must be aborted. */
172/******************************************************************************/
173int
174pof_write_buffer(hysdn_card * card, int datlen)
175{
176 struct boot_data *boot = card->boot; /* pointer to boot specific data */
177
178 if (!boot)
179 return (-EFAULT); /* invalid call */
180 if (boot->last_error < 0)
181 return (boot->last_error); /* repeated error */
182
183 if (card->debug_flags & LOG_POF_WRITE)
184 hysdn_addlog(card, "POF write: got %d bytes ", datlen);
185
186 switch (boot->pof_state) {
187 case POF_READ_FILE_HEAD:
188 if (card->debug_flags & LOG_POF_WRITE)
189 hysdn_addlog(card, "POF write: checking file header");
190
191 if (datlen != sizeof(tPofFileHdr)) {
192 boot->last_error = -EPOF_INTERNAL;
193 break;
194 }
195 if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) {
196 boot->last_error = -EPOF_BAD_MAGIC;
197 break;
198 }
199 /* Setup the new state and vars */
200 boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */
201 boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */
202 boot->last_error = sizeof(tPofRecHdr); /* new length */
203 break;
204
205 case POF_READ_TAG_HEAD:
206 if (card->debug_flags & LOG_POF_WRITE)
207 hysdn_addlog(card, "POF write: checking tag header");
208
209 if (datlen != sizeof(tPofRecHdr)) {
210 boot->last_error = -EPOF_INTERNAL;
211 break;
212 }
213 boot->pof_recid = boot->buf.PofRecHdr.PofRecId; /* actual pof recid */
214 boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen; /* total length */
215 boot->pof_recoffset = 0; /* no starting offset */
216
217 if (card->debug_flags & LOG_POF_RECORD)
218 hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ",
219 boot->pof_recid, boot->pof_reclen);
220
221 boot->pof_state = POF_READ_TAG_DATA; /* now start with tag data */
222 if (boot->pof_reclen < BOOT_BUF_SIZE)
223 boot->last_error = boot->pof_reclen; /* limit size */
224 else
225 boot->last_error = BOOT_BUF_SIZE; /* maximum */
226
227 if (!boot->last_error) { /* no data inside record */
228 boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */
229 boot->last_error = sizeof(tPofRecHdr); /* new length */
230 }
231 break;
232
233 case POF_READ_TAG_DATA:
234 if (card->debug_flags & LOG_POF_WRITE)
235 hysdn_addlog(card, "POF write: getting tag data");
236
237 if (datlen != boot->last_error) {
238 boot->last_error = -EPOF_INTERNAL;
239 break;
240 }
241 if ((boot->last_error = pof_handle_data(card, datlen)) < 0)
242 return (boot->last_error); /* an error occurred */
243 boot->pof_recoffset += datlen;
244 if (boot->pof_recoffset >= boot->pof_reclen) {
245 boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */
246 boot->last_error = sizeof(tPofRecHdr); /* new length */
247 } else {
248 if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE)
249 boot->last_error = boot->pof_reclen - boot->pof_recoffset; /* limit size */
250 else
251 boot->last_error = BOOT_BUF_SIZE; /* maximum */
252 }
253 break;
254
255 default:
256 boot->last_error = -EPOF_INTERNAL; /* unknown state */
257 break;
258 } /* switch (boot->pof_state) */
259
260 return (boot->last_error);
261} /* pof_write_buffer */
262
263
264/*******************************************************************************/
265/* pof_write_open is called when an open for boot on the cardlog device occurs. */
266/* The function returns the needed number of bytes for the next operation. If */
267/* the returned number is less or equal 0 an error specified by this code */
268/* occurred. Additionally the pointer to the buffer data area is set on success */
269/*******************************************************************************/
270int
271pof_write_open(hysdn_card * card, uchar ** bufp)
272{
273 struct boot_data *boot; /* pointer to boot specific data */
274
275 if (card->boot) {
276 if (card->debug_flags & LOG_POF_OPEN)
277 hysdn_addlog(card, "POF open: already opened for boot");
278 return (-ERR_ALREADY_BOOT); /* boot already active */
279 }
280 /* error no mem available */
281 if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) {
282 if (card->debug_flags & LOG_MEM_ERR)
283 hysdn_addlog(card, "POF open: unable to allocate mem");
284 return (-EFAULT);
285 }
286 card->boot = boot;
287 card->state = CARD_STATE_BOOTING;
288 memset(boot, 0, sizeof(struct boot_data));
289
290 card->stopcard(card); /* first stop the card */
291 if (card->testram(card)) {
292 if (card->debug_flags & LOG_POF_OPEN)
293 hysdn_addlog(card, "POF open: DPRAM test failure");
294 boot->last_error = -ERR_BOARD_DPRAM;
295 card->state = CARD_STATE_BOOTERR; /* show boot error */
296 return (boot->last_error);
297 }
298 boot->BufSize = 0; /* Buffer is empty */
299 boot->pof_state = POF_READ_FILE_HEAD; /* read file header */
300 StartDecryption(boot); /* if POF File should be encrypted */
301
302 if (card->debug_flags & LOG_POF_OPEN)
303 hysdn_addlog(card, "POF open: success");
304
305 *bufp = boot->buf.BootBuf; /* point to buffer */
306 return (sizeof(tPofFileHdr));
307} /* pof_write_open */
308
309/********************************************************************************/
310/* pof_write_close is called when an close of boot on the cardlog device occurs. */
311/* The return value must be 0 if everything has happened as desired. */
312/********************************************************************************/
313int
314pof_write_close(hysdn_card * card)
315{
316 struct boot_data *boot = card->boot; /* pointer to boot specific data */
317
318 if (!boot)
319 return (-EFAULT); /* invalid call */
320
321 card->boot = NULL; /* no boot active */
322 kfree(boot);
323
324 if (card->state == CARD_STATE_RUN)
325 card->set_errlog_state(card, 1); /* activate error log */
326
327 if (card->debug_flags & LOG_POF_OPEN)
328 hysdn_addlog(card, "POF close: success");
329
330 return (0);
331} /* pof_write_close */
332
333/*********************************************************************************/
334/* EvalSysrTokData checks additional records delivered with the Sysready Message */
335/* when POF has been booted. A return value of 0 is used if no error occurred. */
336/*********************************************************************************/
337int
338EvalSysrTokData(hysdn_card * card, uchar * cp, int len)
339{
340 u_char *p;
341 u_char crc;
342
343 if (card->debug_flags & LOG_POF_RECORD)
344 hysdn_addlog(card, "SysReady Token data length %d", len);
345
346 if (len < 2) {
347 hysdn_addlog(card, "SysReady Token Data to short");
348 return (1);
349 }
350 for (p = cp, crc = 0; p < (cp + len - 2); p++)
351 if ((crc & 0x80))
352 crc = (((u_char) (crc << 1)) + 1) + *p;
353 else
354 crc = ((u_char) (crc << 1)) + *p;
355 crc = ~crc;
356 if (crc != *(cp + len - 1)) {
357 hysdn_addlog(card, "SysReady Token Data invalid CRC");
358 return (1);
359 }
360 len--; /* don't check CRC byte */
361 while (len > 0) {
362
363 if (*cp == SYSR_TOK_END)
364 return (0); /* End of Token stream */
365
366 if (len < (*(cp + 1) + 2)) {
367 hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1));
368 return (1);
369 }
370 switch (*cp) {
371 case SYSR_TOK_B_CHAN: /* 1 */
372 if (*(cp + 1) != 1)
373 return (1); /* length invalid */
374 card->bchans = *(cp + 2);
375 break;
376
377 case SYSR_TOK_FAX_CHAN: /* 2 */
378 if (*(cp + 1) != 1)
379 return (1); /* length invalid */
380 card->faxchans = *(cp + 2);
381 break;
382
383 case SYSR_TOK_MAC_ADDR: /* 3 */
384 if (*(cp + 1) != 6)
385 return (1); /* length invalid */
386 memcpy(card->mac_addr, cp + 2, 6);
387 break;
388
389 default:
390 hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1));
391 break;
392 }
393 len -= (*(cp + 1) + 2); /* adjust len */
394 cp += (*(cp + 1) + 2); /* and pointer */
395 }
396
397 hysdn_addlog(card, "no end token found");
398 return (1);
399} /* EvalSysrTokData */
diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h
new file mode 100644
index 000000000000..4cee26e558ee
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_defs.h
@@ -0,0 +1,298 @@
1/* $Id: hysdn_defs.h,v 1.5.6.3 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards
4 * global definitions and exported vars and functions.
5 *
6 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
7 * Copyright 1999 by Werner Cornelius (werner@titro.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#ifndef HYSDN_DEFS_H
15#define HYSDN_DEFS_H
16
17#include <linux/config.h>
18#include <linux/hysdn_if.h>
19#include <linux/interrupt.h>
20#include <linux/workqueue.h>
21#include <linux/skbuff.h>
22
23/****************************/
24/* storage type definitions */
25/****************************/
26#define uchar unsigned char
27#define uint unsigned int
28#define ulong unsigned long
29#define word unsigned short
30
31#include "ince1pc.h"
32
33#ifdef CONFIG_HYSDN_CAPI
34#include <linux/capi.h>
35#include <linux/isdn/capicmd.h>
36#include <linux/isdn/capiutil.h>
37#include <linux/isdn/capilli.h>
38
39/***************************/
40/* CAPI-Profile values. */
41/***************************/
42
43#define GLOBAL_OPTION_INTERNAL_CONTROLLER 0x0001
44#define GLOBAL_OPTION_EXTERNAL_CONTROLLER 0x0002
45#define GLOBAL_OPTION_HANDSET 0x0004
46#define GLOBAL_OPTION_DTMF 0x0008
47#define GLOBAL_OPTION_SUPPL_SERVICES 0x0010
48#define GLOBAL_OPTION_CHANNEL_ALLOCATION 0x0020
49#define GLOBAL_OPTION_B_CHANNEL_OPERATION 0x0040
50
51#define B1_PROT_64KBIT_HDLC 0x0001
52#define B1_PROT_64KBIT_TRANSPARENT 0x0002
53#define B1_PROT_V110_ASYNCH 0x0004
54#define B1_PROT_V110_SYNCH 0x0008
55#define B1_PROT_T30 0x0010
56#define B1_PROT_64KBIT_INV_HDLC 0x0020
57#define B1_PROT_56KBIT_TRANSPARENT 0x0040
58
59#define B2_PROT_ISO7776 0x0001
60#define B2_PROT_TRANSPARENT 0x0002
61#define B2_PROT_SDLC 0x0004
62#define B2_PROT_LAPD 0x0008
63#define B2_PROT_T30 0x0010
64#define B2_PROT_PPP 0x0020
65#define B2_PROT_TRANSPARENT_IGNORE_B1_FRAMING_ERRORS 0x0040
66
67#define B3_PROT_TRANSPARENT 0x0001
68#define B3_PROT_T90NL 0x0002
69#define B3_PROT_ISO8208 0x0004
70#define B3_PROT_X25_DCE 0x0008
71#define B3_PROT_T30 0x0010
72#define B3_PROT_T30EXT 0x0020
73
74#define HYSDN_MAXVERSION 8
75
76/* Number of sendbuffers in CAPI-queue */
77#define HYSDN_MAX_CAPI_SKB 20
78
79#endif /* CONFIG_HYSDN_CAPI*/
80
81/************************************************/
82/* constants and bits for debugging/log outputs */
83/************************************************/
84#define LOG_MAX_LINELEN 120
85#define DEB_OUT_SYSLOG 0x80000000 /* output to syslog instead of proc fs */
86#define LOG_MEM_ERR 0x00000001 /* log memory errors like kmalloc failure */
87#define LOG_POF_OPEN 0x00000010 /* log pof open and close activities */
88#define LOG_POF_RECORD 0x00000020 /* log pof record parser */
89#define LOG_POF_WRITE 0x00000040 /* log detailed pof write operation */
90#define LOG_POF_CARD 0x00000080 /* log pof related card functions */
91#define LOG_CNF_LINE 0x00000100 /* all conf lines are put to procfs */
92#define LOG_CNF_DATA 0x00000200 /* non comment conf lines are shown with channel */
93#define LOG_CNF_MISC 0x00000400 /* additional conf line debug outputs */
94#define LOG_SCHED_ASYN 0x00001000 /* debug schedulers async tx routines */
95#define LOG_PROC_OPEN 0x00100000 /* open and close from procfs are logged */
96#define LOG_PROC_ALL 0x00200000 /* all actions from procfs are logged */
97#define LOG_NET_INIT 0x00010000 /* network init and deinit logging */
98
99#define DEF_DEB_FLAGS 0x7fff000f /* everything is logged to procfs */
100
101/**********************************/
102/* proc filesystem name constants */
103/**********************************/
104#define PROC_SUBDIR_NAME "hysdn"
105#define PROC_CONF_BASENAME "cardconf"
106#define PROC_LOG_BASENAME "cardlog"
107
108/***********************************/
109/* PCI 32 bit parms for IO and MEM */
110/***********************************/
111#define PCI_REG_PLX_MEM_BASE 0
112#define PCI_REG_PLX_IO_BASE 1
113#define PCI_REG_MEMORY_BASE 3
114
115/**************/
116/* card types */
117/**************/
118#define BD_NONE 0U
119#define BD_PERFORMANCE 1U
120#define BD_VALUE 2U
121#define BD_PCCARD 3U
122#define BD_ERGO 4U
123#define BD_METRO 5U
124#define BD_CHAMP2 6U
125#define BD_PLEXUS 7U
126
127/******************************************************/
128/* defined states for cards shown by reading cardconf */
129/******************************************************/
130#define CARD_STATE_UNUSED 0 /* never been used or booted */
131#define CARD_STATE_BOOTING 1 /* booting is in progress */
132#define CARD_STATE_BOOTERR 2 /* a previous boot was aborted */
133#define CARD_STATE_RUN 3 /* card is active */
134
135/*******************************/
136/* defines for error_log_state */
137/*******************************/
138#define ERRLOG_STATE_OFF 0 /* error log is switched off, nothing to do */
139#define ERRLOG_STATE_ON 1 /* error log is switched on, wait for data */
140#define ERRLOG_STATE_START 2 /* start error logging */
141#define ERRLOG_STATE_STOP 3 /* stop error logging */
142
143/*******************************/
144/* data structure for one card */
145/*******************************/
146typedef struct HYSDN_CARD {
147
148 /* general variables for the cards */
149 int myid; /* own driver card id */
150 uchar bus; /* pci bus the card is connected to */
151 uchar devfn; /* slot+function bit encoded */
152 word subsysid; /* PCI subsystem id */
153 uchar brdtype; /* type of card */
154 uint bchans; /* number of available B-channels */
155 uint faxchans; /* number of available fax-channels */
156 uchar mac_addr[6]; /* MAC Address read from card */
157 uint irq; /* interrupt number */
158 uint iobase; /* IO-port base address */
159 ulong plxbase; /* PLX memory base */
160 ulong membase; /* DPRAM memory base */
161 ulong memend; /* DPRAM memory end */
162 void *dpram; /* mapped dpram */
163 int state; /* actual state of card -> CARD_STATE_** */
164 struct HYSDN_CARD *next; /* pointer to next card */
165
166 /* data areas for the /proc file system */
167 void *proclog; /* pointer to proclog filesystem specific data */
168 void *procconf; /* pointer to procconf filesystem specific data */
169
170 /* debugging and logging */
171 uchar err_log_state; /* actual error log state of the card */
172 ulong debug_flags; /* tells what should be debugged and where */
173 void (*set_errlog_state) (struct HYSDN_CARD *, int);
174
175 /* interrupt handler + interrupt synchronisation */
176 struct work_struct irq_queue; /* interrupt task queue */
177 uchar volatile irq_enabled; /* interrupt enabled if != 0 */
178 uchar volatile hw_lock; /* hardware is currently locked -> no access */
179
180 /* boot process */
181 void *boot; /* pointer to boot private data */
182 int (*writebootimg) (struct HYSDN_CARD *, uchar *, ulong);
183 int (*writebootseq) (struct HYSDN_CARD *, uchar *, int);
184 int (*waitpofready) (struct HYSDN_CARD *);
185 int (*testram) (struct HYSDN_CARD *);
186
187 /* scheduler for data transfer (only async parts) */
188 uchar async_data[256]; /* async data to be sent (normally for config) */
189 word volatile async_len; /* length of data to sent */
190 word volatile async_channel; /* channel number for async transfer */
191 int volatile async_busy; /* flag != 0 sending in progress */
192 int volatile net_tx_busy; /* a network packet tx is in progress */
193
194 /* network interface */
195 void *netif; /* pointer to network structure */
196
197 /* init and deinit stopcard for booting, too */
198 void (*stopcard) (struct HYSDN_CARD *);
199 void (*releasehardware) (struct HYSDN_CARD *);
200#ifdef CONFIG_HYSDN_CAPI
201 struct hycapictrl_info {
202 char cardname[32];
203 spinlock_t lock;
204 int versionlen;
205 char versionbuf[1024];
206 char *version[HYSDN_MAXVERSION];
207
208 char infobuf[128]; /* for function procinfo */
209
210 struct HYSDN_CARD *card;
211 struct capi_ctr capi_ctrl;
212 struct sk_buff *skbs[HYSDN_MAX_CAPI_SKB];
213 int in_idx, out_idx; /* indexes to buffer ring */
214 int sk_count; /* number of buffers currently in ring */
215 struct sk_buff *tx_skb; /* buffer for tx operation */
216
217 struct list_head ncci_head;
218 } *hyctrlinfo;
219#endif /* CONFIG_HYSDN_CAPI */
220} hysdn_card;
221
222#ifdef CONFIG_HYSDN_CAPI
223typedef struct hycapictrl_info hycapictrl_info;
224#endif /* CONFIG_HYSDN_CAPI */
225
226
227/*****************/
228/* exported vars */
229/*****************/
230extern int cardmax; /* number of found cards */
231extern hysdn_card *card_root; /* pointer to first card */
232
233
234
235/*************************/
236/* im/exported functions */
237/*************************/
238extern char *hysdn_getrev(const char *);
239
240/* hysdn_procconf.c */
241extern int hysdn_procconf_init(void); /* init proc config filesys */
242extern void hysdn_procconf_release(void); /* deinit proc config filesys */
243
244/* hysdn_proclog.c */
245extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */
246extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */
247extern void put_log_buffer(hysdn_card *, char *); /* output log data */
248extern void hysdn_addlog(hysdn_card *, char *,...); /* output data to log */
249extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */
250
251/* boardergo.c */
252extern int ergo_inithardware(hysdn_card * card); /* get hardware -> module init */
253
254/* hysdn_boot.c */
255extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */
256extern int pof_write_open(hysdn_card *, uchar **); /* open proc file for writing pof */
257extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */
258extern int EvalSysrTokData(hysdn_card *, uchar *, int); /* Check Sysready Token Data */
259
260/* hysdn_sched.c */
261extern int hysdn_sched_tx(hysdn_card *, uchar *, word volatile *, word volatile *,
262 word);
263extern int hysdn_sched_rx(hysdn_card *, uchar *, word, word);
264extern int hysdn_tx_cfgline(hysdn_card *, uchar *, word); /* send one cfg line */
265
266/* hysdn_net.c */
267extern unsigned int hynet_enable;
268extern char *hysdn_net_revision;
269extern int hysdn_net_create(hysdn_card *); /* create a new net device */
270extern int hysdn_net_release(hysdn_card *); /* delete the device */
271extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */
272extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */
273extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */
274extern void hysdn_rx_netpkt(hysdn_card *, uchar *, word); /* rxed packet from network */
275
276#ifdef CONFIG_HYSDN_CAPI
277extern unsigned int hycapi_enable;
278extern int hycapi_capi_create(hysdn_card *); /* create a new capi device */
279extern int hycapi_capi_release(hysdn_card *); /* delete the device */
280extern int hycapi_capi_stop(hysdn_card *card); /* suspend */
281extern int hycapi_load_firmware(struct capi_ctr *, capiloaddata *);
282extern void hycapi_reset_ctr(struct capi_ctr *);
283extern void hycapi_remove_ctr(struct capi_ctr *);
284extern void hycapi_register_appl(struct capi_ctr *, __u16 appl,
285 capi_register_params *);
286extern void hycapi_release_appl(struct capi_ctr *, __u16 appl);
287extern u16 hycapi_send_message(struct capi_ctr *, struct sk_buff *skb);
288extern char *hycapi_procinfo(struct capi_ctr *);
289extern int hycapi_read_proc(char *page, char **start, off_t off,
290 int count, int *eof, struct capi_ctr *card);
291extern void hycapi_rx_capipkt(hysdn_card * card, uchar * buf, word len);
292extern void hycapi_tx_capiack(hysdn_card * card);
293extern struct sk_buff *hycapi_tx_capiget(hysdn_card *card);
294extern int hycapi_init(void);
295extern void hycapi_cleanup(void);
296#endif /* CONFIG_HYSDN_CAPI */
297
298#endif /* HYSDN_DEFS_H */
diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c
new file mode 100644
index 000000000000..5cac2bf5f4b0
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_init.c
@@ -0,0 +1,254 @@
1/* $Id: hysdn_init.c,v 1.6.6.6 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, init functions.
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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/config.h>
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/version.h>
17#include <linux/poll.h>
18#include <linux/vmalloc.h>
19#include <linux/slab.h>
20#include <linux/pci.h>
21
22#include "hysdn_defs.h"
23
24static struct pci_device_id hysdn_pci_tbl[] = {
25 {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
26 {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
27 {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO},
28 {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO},
29 { } /* Terminating entry */
30};
31MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
32MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards");
33MODULE_AUTHOR("Werner Cornelius");
34MODULE_LICENSE("GPL");
35
36static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
37int cardmax; /* number of found cards */
38hysdn_card *card_root = NULL; /* pointer to first card */
39
40/**********************************************/
41/* table assigning PCI-sub ids to board types */
42/* the last entry contains all 0 */
43/**********************************************/
44static struct {
45 word subid; /* PCI sub id */
46 uchar cardtyp; /* card type assigned */
47} pci_subid_map[] = {
48
49 {
50 PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO
51 },
52 {
53 PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2
54 },
55 {
56 PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO
57 },
58 {
59 PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO
60 },
61 {
62 0, 0
63 } /* terminating entry */
64};
65
66
67/*********************************************************************/
68/* search_cards searches for available cards in the pci config data. */
69/* If a card is found, the card structure is allocated and the cards */
70/* ressources are reserved. cardmax is incremented. */
71/*********************************************************************/
72static void
73search_cards(void)
74{
75 struct pci_dev *akt_pcidev = NULL;
76 hysdn_card *card, *card_last;
77 int i;
78
79 card_root = NULL;
80 card_last = NULL;
81 while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
82 akt_pcidev)) != NULL) {
83 if (pci_enable_device(akt_pcidev))
84 continue;
85
86 if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) {
87 printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
88 return;
89 }
90 memset(card, 0, sizeof(hysdn_card));
91 card->myid = cardmax; /* set own id */
92 card->bus = akt_pcidev->bus->number;
93 card->devfn = akt_pcidev->devfn; /* slot + function */
94 card->subsysid = akt_pcidev->subsystem_device;
95 card->irq = akt_pcidev->irq;
96 card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
97 card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
98 card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
99 card->brdtype = BD_NONE; /* unknown */
100 card->debug_flags = DEF_DEB_FLAGS; /* set default debug */
101 card->faxchans = 0; /* default no fax channels */
102 card->bchans = 2; /* and 2 b-channels */
103 for (i = 0; pci_subid_map[i].subid; i++)
104 if (pci_subid_map[i].subid == card->subsysid) {
105 card->brdtype = pci_subid_map[i].cardtyp;
106 break;
107 }
108 if (card->brdtype != BD_NONE) {
109 if (ergo_inithardware(card)) {
110 printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase);
111 kfree(card);
112 continue;
113 }
114 } else {
115 printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid);
116 kfree(card); /* release mem */
117 continue;
118 }
119 cardmax++;
120 card->next = NULL; /*end of chain */
121 if (card_last)
122 card_last->next = card; /* pointer to next card */
123 else
124 card_root = card;
125 card_last = card; /* new chain end */
126 } /* device found */
127} /* search_cards */
128
129/************************************************************************************/
130/* free_resources frees the acquired PCI resources and returns the allocated memory */
131/************************************************************************************/
132static void
133free_resources(void)
134{
135 hysdn_card *card;
136
137 while (card_root) {
138 card = card_root;
139 if (card->releasehardware)
140 card->releasehardware(card); /* free all hardware resources */
141 card_root = card_root->next; /* remove card from chain */
142 kfree(card); /* return mem */
143
144 } /* while card_root */
145} /* free_resources */
146
147/**************************************************************************/
148/* stop_cards disables (hardware resets) all cards and disables interrupt */
149/**************************************************************************/
150static void
151stop_cards(void)
152{
153 hysdn_card *card;
154
155 card = card_root; /* first in chain */
156 while (card) {
157 if (card->stopcard)
158 card->stopcard(card);
159 card = card->next; /* remove card from chain */
160 } /* while card */
161} /* stop_cards */
162
163
164/****************************************************************************/
165/* The module startup and shutdown code. Only compiled when used as module. */
166/* Using the driver as module is always advisable, because the booting */
167/* image becomes smaller and the driver code is only loaded when needed. */
168/* Additionally newer versions may be activated without rebooting. */
169/****************************************************************************/
170
171/******************************************************/
172/* extract revision number from string for log output */
173/******************************************************/
174char *
175hysdn_getrev(const char *revision)
176{
177 char *rev;
178 char *p;
179
180 if ((p = strchr(revision, ':'))) {
181 rev = p + 2;
182 p = strchr(rev, '$');
183 *--p = 0;
184 } else
185 rev = "???";
186 return rev;
187}
188
189
190/****************************************************************************/
191/* init_module is called once when the module is loaded to do all necessary */
192/* things like autodetect... */
193/* If the return value of this function is 0 the init has been successful */
194/* and the module is added to the list in /proc/modules, otherwise an error */
195/* is assumed and the module will not be kept in memory. */
196/****************************************************************************/
197static int __init
198hysdn_init(void)
199{
200 char tmp[50];
201
202 strcpy(tmp, hysdn_init_revision);
203 printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp));
204 strcpy(tmp, hysdn_net_revision);
205 printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp));
206 search_cards();
207 printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax);
208
209 if (hysdn_procconf_init()) {
210 free_resources(); /* proc file_sys not created */
211 return (-1);
212 }
213#ifdef CONFIG_HYSDN_CAPI
214 if(cardmax > 0) {
215 if(hycapi_init()) {
216 printk(KERN_ERR "HYCAPI: init failed\n");
217 return(-1);
218 }
219 }
220#endif /* CONFIG_HYSDN_CAPI */
221 return (0); /* no error */
222} /* init_module */
223
224
225/***********************************************************************/
226/* cleanup_module is called when the module is released by the kernel. */
227/* The routine is only called if init_module has been successful and */
228/* the module counter has a value of 0. Otherwise this function will */
229/* not be called. This function must release all resources still allo- */
230/* cated as after the return from this function the module code will */
231/* be removed from memory. */
232/***********************************************************************/
233static void __exit
234hysdn_exit(void)
235{
236#ifdef CONFIG_HYSDN_CAPI
237 hysdn_card *card;
238#endif /* CONFIG_HYSDN_CAPI */
239 stop_cards();
240#ifdef CONFIG_HYSDN_CAPI
241 card = card_root; /* first in chain */
242 while (card) {
243 hycapi_capi_release(card);
244 card = card->next; /* remove card from chain */
245 } /* while card */
246 hycapi_cleanup();
247#endif /* CONFIG_HYSDN_CAPI */
248 hysdn_procconf_release();
249 free_resources();
250 printk(KERN_NOTICE "HYSDN: module unloaded\n");
251} /* cleanup_module */
252
253module_init(hysdn_init);
254module_exit(hysdn_exit);
diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c
new file mode 100644
index 000000000000..babec8157ae6
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_net.c
@@ -0,0 +1,348 @@
1/* $Id: hysdn_net.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, net (ethernet type) handling routines.
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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 * This net module has been inspired by the skeleton driver from
12 * Donald Becker (becker@CESDIS.gsfc.nasa.gov)
13 *
14 */
15
16#include <linux/module.h>
17#include <linux/version.h>
18#include <linux/signal.h>
19#include <linux/kernel.h>
20#include <linux/netdevice.h>
21#include <linux/etherdevice.h>
22#include <linux/skbuff.h>
23#include <linux/inetdevice.h>
24
25#include "hysdn_defs.h"
26
27unsigned int hynet_enable = 0xffffffff;
28MODULE_PARM(hynet_enable, "i");
29
30/* store the actual version for log reporting */
31char *hysdn_net_revision = "$Revision: 1.8.6.4 $";
32
33#define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */
34
35/****************************************************************************/
36/* structure containing the complete network data. The structure is aligned */
37/* in a way that both, the device and statistics are kept inside it. */
38/* for proper access, the device structure MUST be the first var/struct */
39/* inside the definition. */
40/****************************************************************************/
41struct net_local {
42 struct net_device netdev; /* the network device */
43 struct net_device_stats stats;
44 /* additional vars may be added here */
45 char dev_name[9]; /* our own device name */
46
47 /* Tx control lock. This protects the transmit buffer ring
48 * state along with the "tx full" state of the driver. This
49 * means all netif_queue flow control actions are protected
50 * by this lock as well.
51 */
52 spinlock_t lock;
53 struct sk_buff *skbs[MAX_SKB_BUFFERS]; /* pointers to tx-skbs */
54 int in_idx, out_idx; /* indexes to buffer ring */
55 int sk_count; /* number of buffers currently in ring */
56}; /* net_local */
57
58
59/*****************************************************/
60/* Get the current statistics for this card. */
61/* This may be called with the card open or closed ! */
62/*****************************************************/
63static struct net_device_stats *
64net_get_stats(struct net_device *dev)
65{
66 return (&((struct net_local *) dev)->stats);
67} /* net_device_stats */
68
69/*********************************************************************/
70/* Open/initialize the board. This is called (in the current kernel) */
71/* sometime after booting when the 'ifconfig' program is run. */
72/* This routine should set everything up anew at each open, even */
73/* registers that "should" only need to be set once at boot, so that */
74/* there is non-reboot way to recover if something goes wrong. */
75/*********************************************************************/
76static int
77net_open(struct net_device *dev)
78{
79 struct in_device *in_dev;
80 hysdn_card *card = dev->priv;
81 int i;
82
83 netif_start_queue(dev); /* start tx-queueing */
84
85 /* Fill in the MAC-level header (if not already set) */
86 if (!card->mac_addr[0]) {
87 for (i = 0; i < ETH_ALEN - sizeof(ulong); i++)
88 dev->dev_addr[i] = 0xfc;
89 if ((in_dev = dev->ip_ptr) != NULL) {
90 struct in_ifaddr *ifa = in_dev->ifa_list;
91 if (ifa != NULL)
92 memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong));
93 }
94 } else
95 memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN);
96
97 return (0);
98} /* net_open */
99
100/*******************************************/
101/* flush the currently occupied tx-buffers */
102/* must only be called when device closed */
103/*******************************************/
104static void
105flush_tx_buffers(struct net_local *nl)
106{
107
108 while (nl->sk_count) {
109 dev_kfree_skb(nl->skbs[nl->out_idx++]); /* free skb */
110 if (nl->out_idx >= MAX_SKB_BUFFERS)
111 nl->out_idx = 0; /* wrap around */
112 nl->sk_count--;
113 }
114} /* flush_tx_buffers */
115
116
117/*********************************************************************/
118/* close/decativate the device. The device is not removed, but only */
119/* deactivated. */
120/*********************************************************************/
121static int
122net_close(struct net_device *dev)
123{
124
125 netif_stop_queue(dev); /* disable queueing */
126
127 flush_tx_buffers((struct net_local *) dev);
128
129 return (0); /* success */
130} /* net_close */
131
132/************************************/
133/* send a packet on this interface. */
134/* new style for kernel >= 2.3.33 */
135/************************************/
136static int
137net_send_packet(struct sk_buff *skb, struct net_device *dev)
138{
139 struct net_local *lp = (struct net_local *) dev;
140
141 spin_lock_irq(&lp->lock);
142
143 lp->skbs[lp->in_idx++] = skb; /* add to buffer list */
144 if (lp->in_idx >= MAX_SKB_BUFFERS)
145 lp->in_idx = 0; /* wrap around */
146 lp->sk_count++; /* adjust counter */
147 dev->trans_start = jiffies;
148
149 /* If we just used up the very last entry in the
150 * TX ring on this device, tell the queueing
151 * layer to send no more.
152 */
153 if (lp->sk_count >= MAX_SKB_BUFFERS)
154 netif_stop_queue(dev);
155
156 /* When the TX completion hw interrupt arrives, this
157 * is when the transmit statistics are updated.
158 */
159
160 spin_unlock_irq(&lp->lock);
161
162 if (lp->sk_count <= 3) {
163 schedule_work(&((hysdn_card *) dev->priv)->irq_queue);
164 }
165 return (0); /* success */
166} /* net_send_packet */
167
168
169
170/***********************************************************************/
171/* acknowlegde a packet send. The network layer will be informed about */
172/* completion */
173/***********************************************************************/
174void
175hysdn_tx_netack(hysdn_card * card)
176{
177 struct net_local *lp = card->netif;
178
179 if (!lp)
180 return; /* non existing device */
181
182
183 if (!lp->sk_count)
184 return; /* error condition */
185
186 lp->stats.tx_packets++;
187 lp->stats.tx_bytes += lp->skbs[lp->out_idx]->len;
188
189 dev_kfree_skb(lp->skbs[lp->out_idx++]); /* free skb */
190 if (lp->out_idx >= MAX_SKB_BUFFERS)
191 lp->out_idx = 0; /* wrap around */
192
193 if (lp->sk_count-- == MAX_SKB_BUFFERS) /* dec usage count */
194 netif_start_queue((struct net_device *) lp);
195} /* hysdn_tx_netack */
196
197/*****************************************************/
198/* we got a packet from the network, go and queue it */
199/*****************************************************/
200void
201hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len)
202{
203 struct net_local *lp = card->netif;
204 struct sk_buff *skb;
205
206 if (!lp)
207 return; /* non existing device */
208
209 lp->stats.rx_bytes += len;
210
211 skb = dev_alloc_skb(len);
212 if (skb == NULL) {
213 printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
214 lp->netdev.name);
215 lp->stats.rx_dropped++;
216 return;
217 }
218 skb->dev = &lp->netdev;
219
220 /* copy the data */
221 memcpy(skb_put(skb, len), buf, len);
222
223 /* determine the used protocol */
224 skb->protocol = eth_type_trans(skb, &lp->netdev);
225
226 netif_rx(skb);
227 lp->stats.rx_packets++; /* adjust packet count */
228
229} /* hysdn_rx_netpkt */
230
231/*****************************************************/
232/* return the pointer to a network packet to be send */
233/*****************************************************/
234struct sk_buff *
235hysdn_tx_netget(hysdn_card * card)
236{
237 struct net_local *lp = card->netif;
238
239 if (!lp)
240 return (NULL); /* non existing device */
241
242 if (!lp->sk_count)
243 return (NULL); /* nothing available */
244
245 return (lp->skbs[lp->out_idx]); /* next packet to send */
246} /* hysdn_tx_netget */
247
248
249/*******************************************/
250/* init function called by register device */
251/*******************************************/
252static int
253net_init(struct net_device *dev)
254{
255 /* setup the function table */
256 dev->open = net_open;
257 dev->stop = net_close;
258 dev->hard_start_xmit = net_send_packet;
259 dev->get_stats = net_get_stats;
260
261 /* Fill in the fields of the device structure with ethernet values. */
262 ether_setup(dev);
263
264 return (0); /* success */
265} /* net_init */
266
267/*****************************************************************************/
268/* hysdn_net_create creates a new net device for the given card. If a device */
269/* already exists, it will be deleted and created a new one. The return value */
270/* 0 announces success, else a negative error code will be returned. */
271/*****************************************************************************/
272int
273hysdn_net_create(hysdn_card * card)
274{
275 struct net_device *dev;
276 int i;
277 if(!card) {
278 printk(KERN_WARNING "No card-pt in hysdn_net_create!\n");
279 return (-ENOMEM);
280 }
281 hysdn_net_release(card); /* release an existing net device */
282 if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
283 printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
284 return (-ENOMEM);
285 }
286 memset(dev, 0, sizeof(struct net_local)); /* clean the structure */
287
288 spin_lock_init(&((struct net_local *) dev)->lock);
289
290 /* initialise necessary or informing fields */
291 dev->base_addr = card->iobase; /* IO address */
292 dev->irq = card->irq; /* irq */
293 dev->init = net_init; /* the init function of the device */
294 if(dev->name) {
295 strcpy(dev->name, ((struct net_local *) dev)->dev_name);
296 }
297 if ((i = register_netdev(dev))) {
298 printk(KERN_WARNING "HYSDN: unable to create network device\n");
299 kfree(dev);
300 return (i);
301 }
302 dev->priv = card; /* remember pointer to own data structure */
303 card->netif = dev; /* setup the local pointer */
304
305 if (card->debug_flags & LOG_NET_INIT)
306 hysdn_addlog(card, "network device created");
307 return (0); /* and return success */
308} /* hysdn_net_create */
309
310/***************************************************************************/
311/* hysdn_net_release deletes the net device for the given card. The return */
312/* value 0 announces success, else a negative error code will be returned. */
313/***************************************************************************/
314int
315hysdn_net_release(hysdn_card * card)
316{
317 struct net_device *dev = card->netif;
318
319 if (!dev)
320 return (0); /* non existing */
321
322 card->netif = NULL; /* clear out pointer */
323 dev->stop(dev); /* close the device */
324
325 flush_tx_buffers((struct net_local *) dev); /* empty buffers */
326
327 unregister_netdev(dev); /* release the device */
328 free_netdev(dev); /* release the memory allocated */
329 if (card->debug_flags & LOG_NET_INIT)
330 hysdn_addlog(card, "network device deleted");
331
332 return (0); /* always successful */
333} /* hysdn_net_release */
334
335/*****************************************************************************/
336/* hysdn_net_getname returns a pointer to the name of the network interface. */
337/* if the interface is not existing, a "-" is returned. */
338/*****************************************************************************/
339char *
340hysdn_net_getname(hysdn_card * card)
341{
342 struct net_device *dev = card->netif;
343
344 if (!dev)
345 return ("-"); /* non existing */
346
347 return (dev->name);
348} /* hysdn_net_getname */
diff --git a/drivers/isdn/hysdn/hysdn_pof.h b/drivers/isdn/hysdn/hysdn_pof.h
new file mode 100644
index 000000000000..6cd81b9b08bc
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_pof.h
@@ -0,0 +1,78 @@
1/* $Id: hysdn_pof.h,v 1.2.6.1 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, definitions used for handling pof-files.
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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/************************/
14/* POF specific defines */
15/************************/
16#define BOOT_BUF_SIZE 0x1000 /* =4096, maybe moved to other h file */
17#define CRYPT_FEEDTERM 0x8142
18#define CRYPT_STARTTERM 0x81a5
19 /* max. timeout time in seconds
20 * from end of booting to POF is ready
21 */
22#define POF_READY_TIME_OUT_SEC 10
23
24/**********************************/
25/* defines for 1.stage boot image */
26/**********************************/
27
28/* the POF file record containing the boot loader image
29 * has 2 pages a 16KB:
30 * 1. page contains the high 16-bit part of the 32-bit E1 words
31 * 2. page contains the low 16-bit part of the 32-bit E1 words
32 *
33 * In each 16KB page we assume the start of the boot loader code
34 * in the highest 2KB part (at offset 0x3800);
35 * the rest (0x0000..0x37FF) is assumed to contain 0 bytes.
36 */
37
38#define POF_BOOT_LOADER_PAGE_SIZE 0x4000 /* =16384U */
39#define POF_BOOT_LOADER_TOTAL_SIZE (2U*POF_BOOT_LOADER_PAGE_SIZE)
40
41#define POF_BOOT_LOADER_CODE_SIZE 0x0800 /* =2KB =2048U */
42
43 /* offset in boot page, where loader code may start */
44 /* =0x3800= 14336U */
45#define POF_BOOT_LOADER_OFF_IN_PAGE (POF_BOOT_LOADER_PAGE_SIZE-POF_BOOT_LOADER_CODE_SIZE)
46
47
48/*--------------------------------------POF file record structs------------*/
49typedef struct PofFileHdr_tag { /* Pof file header */
50/*00 */ ulong Magic __attribute__((packed));
51/*04 */ ulong N_PofRecs __attribute__((packed));
52/*08 */
53} tPofFileHdr;
54
55typedef struct PofRecHdr_tag { /* Pof record header */
56/*00 */ word PofRecId __attribute__((packed));
57/*02 */ ulong PofRecDataLen __attribute__((packed));
58/*06 */
59} tPofRecHdr;
60
61typedef struct PofTimeStamp_tag {
62/*00 */ ulong UnixTime __attribute__((packed));
63 /*04 */ uchar DateTimeText[0x28] __attribute__((packed));
64 /* =40 */
65/*2C */
66} tPofTimeStamp;
67
68 /* tPofFileHdr.Magic value: */
69#define TAGFILEMAGIC 0x464F501AUL
70 /* tPofRecHdr.PofRecId values: */
71#define TAG_ABSDATA 0x1000 /* abs. data */
72#define TAG_BOOTDTA 0x1001 /* boot data */
73#define TAG_COMMENT 0x0020
74#define TAG_SYSCALL 0x0021
75#define TAG_FLOWCTRL 0x0022
76#define TAG_TIMESTMP 0x0010 /* date/time stamp of version */
77#define TAG_CABSDATA 0x1100 /* crypted abs. data */
78#define TAG_CBOOTDTA 0x1101 /* crypted boot data */
diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c
new file mode 100644
index 000000000000..5da507e532fc
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_procconf.c
@@ -0,0 +1,443 @@
1/* $Id: hysdn_procconf.c,v 1.8.6.4 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
4 *
5 * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 *
7 * Copyright 1999 by Werner Cornelius (werner@titro.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/version.h>
16#include <linux/poll.h>
17#include <linux/proc_fs.h>
18#include <linux/pci.h>
19#include <linux/smp_lock.h>
20
21#include "hysdn_defs.h"
22
23static char *hysdn_procconf_revision = "$Revision: 1.8.6.4 $";
24
25#define INFO_OUT_LEN 80 /* length of info line including lf */
26
27/********************************************************/
28/* defines and data structure for conf write operations */
29/********************************************************/
30#define CONF_STATE_DETECT 0 /* waiting for detect */
31#define CONF_STATE_CONF 1 /* writing config data */
32#define CONF_STATE_POF 2 /* writing pof data */
33#define CONF_LINE_LEN 255 /* 255 chars max */
34
35struct conf_writedata {
36 hysdn_card *card; /* card the device is connected to */
37 int buf_size; /* actual number of bytes in the buffer */
38 int needed_size; /* needed size when reading pof */
39 int state; /* actual interface states from above constants */
40 uchar conf_line[CONF_LINE_LEN]; /* buffered conf line */
41 word channel; /* active channel number */
42 uchar *pof_buffer; /* buffer when writing pof */
43};
44
45/***********************************************************************/
46/* process_line parses one config line and transfers it to the card if */
47/* necessary. */
48/* if the return value is negative an error occurred. */
49/***********************************************************************/
50static int
51process_line(struct conf_writedata *cnf)
52{
53 uchar *cp = cnf->conf_line;
54 int i;
55
56 if (cnf->card->debug_flags & LOG_CNF_LINE)
57 hysdn_addlog(cnf->card, "conf line: %s", cp);
58
59 if (*cp == '-') { /* option */
60 cp++; /* point to option char */
61
62 if (*cp++ != 'c')
63 return (0); /* option unknown or used */
64 i = 0; /* start value for channel */
65 while ((*cp <= '9') && (*cp >= '0'))
66 i = i * 10 + *cp++ - '0'; /* get decimal number */
67 if (i > 65535) {
68 if (cnf->card->debug_flags & LOG_CNF_MISC)
69 hysdn_addlog(cnf->card, "conf channel invalid %d", i);
70 return (-ERR_INV_CHAN); /* invalid channel */
71 }
72 cnf->channel = i & 0xFFFF; /* set new channel number */
73 return (0); /* success */
74 } /* option */
75 if (*cp == '*') { /* line to send */
76 if (cnf->card->debug_flags & LOG_CNF_DATA)
77 hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp);
78 return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1,
79 cnf->channel)); /* send the line without * */
80 } /* line to send */
81 return (0);
82} /* process_line */
83
84/***********************************/
85/* conf file operations and tables */
86/***********************************/
87
88/****************************************************/
89/* write conf file -> boot or send cfg line to card */
90/****************************************************/
91static ssize_t
92hysdn_conf_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
93{
94 struct conf_writedata *cnf;
95 int i;
96 uchar ch, *cp;
97
98 if (!count)
99 return (0); /* nothing to handle */
100
101 if (!(cnf = file->private_data))
102 return (-EFAULT); /* should never happen */
103
104 if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */
105 if (copy_from_user(&ch, buf, 1)) /* get first char for detect */
106 return (-EFAULT);
107
108 if (ch == 0x1A) {
109 /* we detected a pof file */
110 if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0)
111 return (cnf->needed_size); /* an error occurred -> exit */
112 cnf->buf_size = 0; /* buffer is empty */
113 cnf->state = CONF_STATE_POF; /* new state */
114 } else {
115 /* conf data has been detected */
116 cnf->buf_size = 0; /* buffer is empty */
117 cnf->state = CONF_STATE_CONF; /* requested conf data write */
118 if (cnf->card->state != CARD_STATE_RUN)
119 return (-ERR_NOT_BOOTED);
120 cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */
121 cnf->channel = 4098; /* default channel for output */
122 }
123 } /* state was auto detect */
124 if (cnf->state == CONF_STATE_POF) { /* pof write active */
125 i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */
126 if (i <= 0)
127 return (-EINVAL); /* size error handling pof */
128
129 if (i < count)
130 count = i; /* limit requested number of bytes */
131 if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count))
132 return (-EFAULT); /* error while copying */
133 cnf->buf_size += count;
134
135 if (cnf->needed_size == cnf->buf_size) {
136 cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */
137 if (cnf->needed_size <= 0) {
138 cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */
139 return (cnf->needed_size); /* an error occurred */
140 }
141 cnf->buf_size = 0; /* buffer is empty again */
142 }
143 }
144 /* pof write active */
145 else { /* conf write active */
146
147 if (cnf->card->state != CARD_STATE_RUN) {
148 if (cnf->card->debug_flags & LOG_CNF_MISC)
149 hysdn_addlog(cnf->card, "cnf write denied -> not booted");
150 return (-ERR_NOT_BOOTED);
151 }
152 i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */
153 if (i > 0) {
154 /* copy remaining bytes into buffer */
155
156 if (count > i)
157 count = i; /* limit transfer */
158 if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count))
159 return (-EFAULT); /* error while copying */
160
161 i = count; /* number of chars in buffer */
162 cp = cnf->conf_line + cnf->buf_size;
163 while (i) {
164 /* search for end of line */
165 if ((*cp < ' ') && (*cp != 9))
166 break; /* end of line found */
167 cp++;
168 i--;
169 } /* search for end of line */
170
171 if (i) {
172 /* delimiter found */
173 *cp++ = 0; /* string termination */
174 count -= (i - 1); /* subtract remaining bytes from count */
175 while ((i) && (*cp < ' ') && (*cp != 9)) {
176 i--; /* discard next char */
177 count++; /* mark as read */
178 cp++; /* next char */
179 }
180 cnf->buf_size = 0; /* buffer is empty after transfer */
181 if ((i = process_line(cnf)) < 0) /* handle the line */
182 count = i; /* return the error */
183 }
184 /* delimiter found */
185 else {
186 cnf->buf_size += count; /* add chars to string */
187 if (cnf->buf_size >= CONF_LINE_LEN - 1) {
188 if (cnf->card->debug_flags & LOG_CNF_MISC)
189 hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count);
190 return (-ERR_CONF_LONG);
191 }
192 } /* not delimited */
193
194 }
195 /* copy remaining bytes into buffer */
196 else {
197 if (cnf->card->debug_flags & LOG_CNF_MISC)
198 hysdn_addlog(cnf->card, "cnf line too long");
199 return (-ERR_CONF_LONG);
200 }
201 } /* conf write active */
202
203 return (count);
204} /* hysdn_conf_write */
205
206/*******************************************/
207/* read conf file -> output card info data */
208/*******************************************/
209static ssize_t
210hysdn_conf_read(struct file *file, char __user *buf, size_t count, loff_t * off)
211{
212 char *cp;
213 int i;
214
215 if (file->f_mode & FMODE_READ) {
216 if (!(cp = file->private_data))
217 return (-EFAULT); /* should never happen */
218 i = strlen(cp); /* get total string length */
219 if (*off < i) {
220 /* still bytes to transfer */
221 cp += *off; /* point to desired data offset */
222 i -= *off; /* remaining length */
223 if (i > count)
224 i = count; /* limit length to transfer */
225 if (copy_to_user(buf, cp, i))
226 return (-EFAULT); /* copy error */
227 *off += i; /* adjust offset */
228 } else
229 return (0);
230 } else
231 return (-EPERM); /* no permission to read */
232
233 return (i);
234} /* hysdn_conf_read */
235
236/******************/
237/* open conf file */
238/******************/
239static int
240hysdn_conf_open(struct inode *ino, struct file *filep)
241{
242 hysdn_card *card;
243 struct proc_dir_entry *pd;
244 struct conf_writedata *cnf;
245 char *cp, *tmp;
246
247 /* now search the addressed card */
248 lock_kernel();
249 card = card_root;
250 while (card) {
251 pd = card->procconf;
252 if (pd == PDE(ino))
253 break;
254 card = card->next; /* search next entry */
255 }
256 if (!card) {
257 unlock_kernel();
258 return (-ENODEV); /* device is unknown/invalid */
259 }
260 if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
261 hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x",
262 filep->f_uid, filep->f_gid, filep->f_mode);
263
264 if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
265 /* write only access -> write boot file or conf line */
266
267 if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
268 unlock_kernel();
269 return (-EFAULT);
270 }
271 cnf->card = card;
272 cnf->buf_size = 0; /* nothing buffered */
273 cnf->state = CONF_STATE_DETECT; /* start auto detect */
274 filep->private_data = cnf;
275
276 } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
277 /* read access -> output card info data */
278
279 if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
280 unlock_kernel();
281 return (-EFAULT); /* out of memory */
282 }
283 filep->private_data = tmp; /* start of string */
284
285 /* first output a headline */
286 sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device");
287 cp = tmp; /* start of string */
288 while (*cp)
289 cp++;
290 while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
291 *cp++ = ' ';
292 *cp++ = '\n';
293
294 /* and now the data */
295 sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08lx %7d %9d %3d %s",
296 card->myid,
297 card->bus,
298 PCI_SLOT(card->devfn),
299 card->brdtype,
300 card->irq,
301 card->iobase,
302 card->membase,
303 card->bchans,
304 card->faxchans,
305 card->state,
306 hysdn_net_getname(card));
307 while (*cp)
308 cp++;
309 while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
310 *cp++ = ' ';
311 *cp++ = '\n';
312 *cp = 0; /* end of string */
313 } else { /* simultaneous read/write access forbidden ! */
314 unlock_kernel();
315 return (-EPERM); /* no permission this time */
316 }
317 unlock_kernel();
318 return nonseekable_open(ino, filep);
319} /* hysdn_conf_open */
320
321/***************************/
322/* close a config file. */
323/***************************/
324static int
325hysdn_conf_close(struct inode *ino, struct file *filep)
326{
327 hysdn_card *card;
328 struct conf_writedata *cnf;
329 int retval = 0;
330 struct proc_dir_entry *pd;
331
332 lock_kernel();
333 /* search the addressed card */
334 card = card_root;
335 while (card) {
336 pd = card->procconf;
337 if (pd == PDE(ino))
338 break;
339 card = card->next; /* search next entry */
340 }
341 if (!card) {
342 unlock_kernel();
343 return (-ENODEV); /* device is unknown/invalid */
344 }
345 if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
346 hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x",
347 filep->f_uid, filep->f_gid, filep->f_mode);
348
349 if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
350 /* write only access -> write boot file or conf line */
351 if (filep->private_data) {
352 cnf = filep->private_data;
353
354 if (cnf->state == CONF_STATE_POF)
355 retval = pof_write_close(cnf->card); /* close the pof write */
356 kfree(filep->private_data); /* free allocated memory for buffer */
357
358 } /* handle write private data */
359 } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
360 /* read access -> output card info data */
361
362 if (filep->private_data)
363 kfree(filep->private_data); /* release memory */
364 }
365 unlock_kernel();
366 return (retval);
367} /* hysdn_conf_close */
368
369/******************************************************/
370/* table for conf filesystem functions defined above. */
371/******************************************************/
372static struct file_operations conf_fops =
373{
374 .llseek = no_llseek,
375 .read = hysdn_conf_read,
376 .write = hysdn_conf_write,
377 .open = hysdn_conf_open,
378 .release = hysdn_conf_close,
379};
380
381/*****************************/
382/* hysdn subdir in /proc/net */
383/*****************************/
384struct proc_dir_entry *hysdn_proc_entry = NULL;
385
386/*******************************************************************************/
387/* hysdn_procconf_init is called when the module is loaded and after the cards */
388/* have been detected. The needed proc dir and card config files are created. */
389/* The log init is called at last. */
390/*******************************************************************************/
391int
392hysdn_procconf_init(void)
393{
394 hysdn_card *card;
395 uchar conf_name[20];
396
397 hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
398 if (!hysdn_proc_entry) {
399 printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
400 return (-1);
401 }
402 card = card_root; /* point to first card */
403 while (card) {
404
405 sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
406 if ((card->procconf = (void *) create_proc_entry(conf_name,
407 S_IFREG | S_IRUGO | S_IWUSR,
408 hysdn_proc_entry)) != NULL) {
409 ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
410 ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
411 hysdn_proclog_init(card); /* init the log file entry */
412 }
413 card = card->next; /* next entry */
414 }
415
416 printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procconf_revision));
417 return (0);
418} /* hysdn_procconf_init */
419
420/*************************************************************************************/
421/* hysdn_procconf_release is called when the module is unloaded and before the cards */
422/* resources are released. The module counter is assumed to be 0 ! */
423/*************************************************************************************/
424void
425hysdn_procconf_release(void)
426{
427 hysdn_card *card;
428 uchar conf_name[20];
429
430 card = card_root; /* start with first card */
431 while (card) {
432
433 sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid);
434 if (card->procconf)
435 remove_proc_entry(conf_name, hysdn_proc_entry);
436
437 hysdn_proclog_release(card); /* init the log file entry */
438
439 card = card->next; /* point to next card */
440 }
441
442 remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
443}
diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
new file mode 100644
index 000000000000..8ef2b7c952a6
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_proclog.c
@@ -0,0 +1,441 @@
1/* $Id: hysdn_proclog.c,v 1.9.6.3 2001/09/23 22:24:54 kai Exp $
2 *
3 * Linux driver for HYSDN cards, /proc/net filesystem log functions.
4 *
5 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
6 * Copyright 1999 by Werner Cornelius (werner@titro.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/module.h>
14#include <linux/version.h>
15#include <linux/poll.h>
16#include <linux/proc_fs.h>
17#include <linux/pci.h>
18#include <linux/smp_lock.h>
19
20#include "hysdn_defs.h"
21
22/* the proc subdir for the interface is defined in the procconf module */
23extern struct proc_dir_entry *hysdn_proc_entry;
24
25/*************************************************/
26/* structure keeping ascii log for device output */
27/*************************************************/
28struct log_data {
29 struct log_data *next;
30 ulong usage_cnt; /* number of files still to work */
31 void *proc_ctrl; /* pointer to own control procdata structure */
32 char log_start[2]; /* log string start (final len aligned by size) */
33};
34
35/**********************************************/
36/* structure holding proc entrys for one card */
37/**********************************************/
38struct procdata {
39 struct proc_dir_entry *log; /* log entry */
40 char log_name[15]; /* log filename */
41 struct log_data *log_head, *log_tail; /* head and tail for queue */
42 int if_used; /* open count for interface */
43 int volatile del_lock; /* lock for delete operations */
44 uchar logtmp[LOG_MAX_LINELEN];
45 wait_queue_head_t rd_queue;
46};
47
48
49/**********************************************/
50/* log function for cards error log interface */
51/**********************************************/
52void
53hysdn_card_errlog(hysdn_card * card, tErrLogEntry * logp, int maxsize)
54{
55 char buf[ERRLOG_TEXT_SIZE + 40];
56
57 sprintf(buf, "LOG 0x%08lX 0x%08lX : %s\n", logp->ulErrType, logp->ulErrSubtype, logp->ucText);
58 put_log_buffer(card, buf); /* output the string */
59} /* hysdn_card_errlog */
60
61/***************************************************/
62/* Log function using format specifiers for output */
63/***************************************************/
64void
65hysdn_addlog(hysdn_card * card, char *fmt,...)
66{
67 struct procdata *pd = card->proclog;
68 char *cp;
69 va_list args;
70
71 if (!pd)
72 return; /* log structure non existent */
73
74 cp = pd->logtmp;
75 cp += sprintf(cp, "HYSDN: card %d ", card->myid);
76
77 va_start(args, fmt);
78 cp += vsprintf(cp, fmt, args);
79 va_end(args);
80 *cp++ = '\n';
81 *cp = 0;
82
83 if (card->debug_flags & DEB_OUT_SYSLOG)
84 printk(KERN_INFO "%s", pd->logtmp);
85 else
86 put_log_buffer(card, pd->logtmp);
87
88} /* hysdn_addlog */
89
90/********************************************/
91/* put an log buffer into the log queue. */
92/* This buffer will be kept until all files */
93/* opened for read got the contents. */
94/* Flushes buffers not longer in use. */
95/********************************************/
96void
97put_log_buffer(hysdn_card * card, char *cp)
98{
99 struct log_data *ib;
100 struct procdata *pd = card->proclog;
101 int i;
102 unsigned long flags;
103
104 if (!pd)
105 return;
106 if (!cp)
107 return;
108 if (!*cp)
109 return;
110 if (pd->if_used <= 0)
111 return; /* no open file for read */
112
113 if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
114 return; /* no memory */
115 strcpy(ib->log_start, cp); /* set output string */
116 ib->next = NULL;
117 ib->proc_ctrl = pd; /* point to own control structure */
118 save_flags(flags);
119 cli();
120 ib->usage_cnt = pd->if_used;
121 if (!pd->log_head)
122 pd->log_head = ib; /* new head */
123 else
124 pd->log_tail->next = ib; /* follows existing messages */
125 pd->log_tail = ib; /* new tail */
126 i = pd->del_lock++; /* get lock state */
127 restore_flags(flags);
128
129 /* delete old entrys */
130 if (!i)
131 while (pd->log_head->next) {
132 if ((pd->log_head->usage_cnt <= 0) &&
133 (pd->log_head->next->usage_cnt <= 0)) {
134 ib = pd->log_head;
135 pd->log_head = pd->log_head->next;
136 kfree(ib);
137 } else
138 break;
139 } /* pd->log_head->next */
140 pd->del_lock--; /* release lock level */
141 wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */
142} /* put_log_buffer */
143
144
145/******************************/
146/* file operations and tables */
147/******************************/
148
149/****************************************/
150/* write log file -> set log level bits */
151/****************************************/
152static ssize_t
153hysdn_log_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
154{
155 ulong u = 0;
156 int found = 0;
157 uchar *cp, valbuf[128];
158 long base = 10;
159 hysdn_card *card = (hysdn_card *) file->private_data;
160
161 if (count > (sizeof(valbuf) - 1))
162 count = sizeof(valbuf) - 1; /* limit length */
163 if (copy_from_user(valbuf, buf, count))
164 return (-EFAULT); /* copy failed */
165
166 valbuf[count] = 0; /* terminating 0 */
167 cp = valbuf;
168 if ((count > 2) && (valbuf[0] == '0') && (valbuf[1] == 'x')) {
169 cp += 2; /* pointer after hex modifier */
170 base = 16;
171 }
172 /* scan the input for debug flags */
173 while (*cp) {
174 if ((*cp >= '0') && (*cp <= '9')) {
175 found = 1;
176 u *= base; /* adjust to next digit */
177 u += *cp++ - '0';
178 continue;
179 }
180 if (base != 16)
181 break; /* end of number */
182
183 if ((*cp >= 'a') && (*cp <= 'f')) {
184 found = 1;
185 u *= base; /* adjust to next digit */
186 u += *cp++ - 'a' + 10;
187 continue;
188 }
189 break; /* terminated */
190 }
191
192 if (found) {
193 card->debug_flags = u; /* remember debug flags */
194 hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags);
195 }
196 return (count);
197} /* hysdn_log_write */
198
199/******************/
200/* read log file */
201/******************/
202static ssize_t
203hysdn_log_read(struct file *file, char __user *buf, size_t count, loff_t * off)
204{
205 struct log_data *inf;
206 int len;
207 struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
208 struct procdata *pd = NULL;
209 hysdn_card *card;
210
211 if (!*((struct log_data **) file->private_data)) {
212 if (file->f_flags & O_NONBLOCK)
213 return (-EAGAIN);
214
215 /* sorry, but we need to search the card */
216 card = card_root;
217 while (card) {
218 pd = card->proclog;
219 if (pd->log == pde)
220 break;
221 card = card->next; /* search next entry */
222 }
223 if (card)
224 interruptible_sleep_on(&(pd->rd_queue));
225 else
226 return (-EAGAIN);
227
228 }
229 if (!(inf = *((struct log_data **) file->private_data)))
230 return (0);
231
232 inf->usage_cnt--; /* new usage count */
233 file->private_data = &inf->next; /* next structure */
234 if ((len = strlen(inf->log_start)) <= count) {
235 if (copy_to_user(buf, inf->log_start, len))
236 return -EFAULT;
237 *off += len;
238 return (len);
239 }
240 return (0);
241} /* hysdn_log_read */
242
243/******************/
244/* open log file */
245/******************/
246static int
247hysdn_log_open(struct inode *ino, struct file *filep)
248{
249 hysdn_card *card;
250 struct procdata *pd = NULL;
251 ulong flags;
252
253 lock_kernel();
254 card = card_root;
255 while (card) {
256 pd = card->proclog;
257 if (pd->log == PDE(ino))
258 break;
259 card = card->next; /* search next entry */
260 }
261 if (!card) {
262 unlock_kernel();
263 return (-ENODEV); /* device is unknown/invalid */
264 }
265 filep->private_data = card; /* remember our own card */
266
267 if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
268 /* write only access -> write log level only */
269 } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
270
271 /* read access -> log/debug read */
272 save_flags(flags);
273 cli();
274 pd->if_used++;
275 if (pd->log_head)
276 filep->private_data = &pd->log_tail->next;
277 else
278 filep->private_data = &pd->log_head;
279 restore_flags(flags);
280 } else { /* simultaneous read/write access forbidden ! */
281 unlock_kernel();
282 return (-EPERM); /* no permission this time */
283 }
284 unlock_kernel();
285 return nonseekable_open(ino, filep);
286} /* hysdn_log_open */
287
288/*******************************************************************************/
289/* close a cardlog file. If the file has been opened for exclusive write it is */
290/* assumed as pof data input and the pof loader is noticed about. */
291/* Otherwise file is handled as log output. In this case the interface usage */
292/* count is decremented and all buffers are noticed of closing. If this file */
293/* was the last one to be closed, all buffers are freed. */
294/*******************************************************************************/
295static int
296hysdn_log_close(struct inode *ino, struct file *filep)
297{
298 struct log_data *inf;
299 struct procdata *pd;
300 hysdn_card *card;
301 int retval = 0;
302 unsigned long flags;
303
304
305 lock_kernel();
306 if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
307 /* write only access -> write debug level written */
308 retval = 0; /* success */
309 } else {
310 /* read access -> log/debug read, mark one further file as closed */
311
312 pd = NULL;
313 save_flags(flags);
314 cli();
315 inf = *((struct log_data **) filep->private_data); /* get first log entry */
316 if (inf)
317 pd = (struct procdata *) inf->proc_ctrl; /* still entries there */
318 else {
319 /* no info available -> search card */
320 card = card_root;
321 while (card) {
322 pd = card->proclog;
323 if (pd->log == PDE(ino))
324 break;
325 card = card->next; /* search next entry */
326 }
327 if (card)
328 pd = card->proclog; /* pointer to procfs log */
329 }
330 if (pd)
331 pd->if_used--; /* decrement interface usage count by one */
332
333 while (inf) {
334 inf->usage_cnt--; /* decrement usage count for buffers */
335 inf = inf->next;
336 }
337 restore_flags(flags);
338
339 if (pd)
340 if (pd->if_used <= 0) /* delete buffers if last file closed */
341 while (pd->log_head) {
342 inf = pd->log_head;
343 pd->log_head = pd->log_head->next;
344 kfree(inf);
345 }
346 } /* read access */
347 unlock_kernel();
348
349 return (retval);
350} /* hysdn_log_close */
351
352/*************************************************/
353/* select/poll routine to be able using select() */
354/*************************************************/
355static unsigned int
356hysdn_log_poll(struct file *file, poll_table * wait)
357{
358 unsigned int mask = 0;
359 struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
360 hysdn_card *card;
361 struct procdata *pd = NULL;
362
363 if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
364 return (mask); /* no polling for write supported */
365
366 /* we need to search the card */
367 card = card_root;
368 while (card) {
369 pd = card->proclog;
370 if (pd->log == pde)
371 break;
372 card = card->next; /* search next entry */
373 }
374 if (!card)
375 return (mask); /* card not found */
376
377 poll_wait(file, &(pd->rd_queue), wait);
378
379 if (*((struct log_data **) file->private_data))
380 mask |= POLLIN | POLLRDNORM;
381
382 return mask;
383} /* hysdn_log_poll */
384
385/**************************************************/
386/* table for log filesystem functions defined above. */
387/**************************************************/
388static struct file_operations log_fops =
389{
390 .llseek = no_llseek,
391 .read = hysdn_log_read,
392 .write = hysdn_log_write,
393 .poll = hysdn_log_poll,
394 .open = hysdn_log_open,
395 .release = hysdn_log_close,
396};
397
398
399/***********************************************************************************/
400/* hysdn_proclog_init is called when the module is loaded after creating the cards */
401/* conf files. */
402/***********************************************************************************/
403int
404hysdn_proclog_init(hysdn_card * card)
405{
406 struct procdata *pd;
407
408 /* create a cardlog proc entry */
409
410 if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
411 memset(pd, 0, sizeof(struct procdata));
412 sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
413 if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
414 pd->log->proc_fops = &log_fops;
415 pd->log->owner = THIS_MODULE;
416 }
417
418 init_waitqueue_head(&(pd->rd_queue));
419
420 card->proclog = (void *) pd; /* remember procfs structure */
421 }
422 return (0);
423} /* hysdn_proclog_init */
424
425/************************************************************************************/
426/* hysdn_proclog_release is called when the module is unloaded and before the cards */
427/* conf file is released */
428/* The module counter is assumed to be 0 ! */
429/************************************************************************************/
430void
431hysdn_proclog_release(hysdn_card * card)
432{
433 struct procdata *pd;
434
435 if ((pd = (struct procdata *) card->proclog) != NULL) {
436 if (pd->log)
437 remove_proc_entry(pd->log_name, hysdn_proc_entry);
438 kfree(pd); /* release memory */
439 card->proclog = NULL;
440 }
441} /* hysdn_proclog_release */
diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c
new file mode 100644
index 000000000000..4fa3b01707cd
--- /dev/null
+++ b/drivers/isdn/hysdn/hysdn_sched.c
@@ -0,0 +1,207 @@
1/* $Id: hysdn_sched.c,v 1.5.6.4 2001/11/06 21:58:19 kai Exp $
2 *
3 * Linux driver for HYSDN cards
4 * scheduler routines for handling exchange card <-> pc.
5 *
6 * Author Werner Cornelius (werner@titro.de) for Hypercope GmbH
7 * Copyright 1999 by Werner Cornelius (werner@titro.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include <linux/config.h>
15#include <linux/sched.h>
16#include <linux/signal.h>
17#include <linux/kernel.h>
18#include <linux/ioport.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21#include <asm/io.h>
22
23#include "hysdn_defs.h"
24
25/*****************************************************************************/
26/* hysdn_sched_rx is called from the cards handler to announce new data is */
27/* available from the card. The routine has to handle the data and return */
28/* with a nonzero code if the data could be worked (or even thrown away), if */
29/* no room to buffer the data is available a zero return tells the card */
30/* to keep the data until later. */
31/*****************************************************************************/
32int
33hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan)
34{
35
36 switch (chan) {
37 case CHAN_NDIS_DATA:
38 if (hynet_enable & (1 << card->myid)) {
39 /* give packet to network handler */
40 hysdn_rx_netpkt(card, buf, len);
41 }
42 break;
43
44 case CHAN_ERRLOG:
45 hysdn_card_errlog(card, (tErrLogEntry *) buf, len);
46 if (card->err_log_state == ERRLOG_STATE_ON)
47 card->err_log_state = ERRLOG_STATE_START; /* start new fetch */
48 break;
49#ifdef CONFIG_HYSDN_CAPI
50 case CHAN_CAPI:
51/* give packet to CAPI handler */
52 if (hycapi_enable & (1 << card->myid)) {
53 hycapi_rx_capipkt(card, buf, len);
54 }
55 break;
56#endif /* CONFIG_HYSDN_CAPI */
57 default:
58 printk(KERN_INFO "irq message channel %d len %d unhandled \n", chan, len);
59 break;
60
61 } /* switch rx channel */
62
63 return (1); /* always handled */
64} /* hysdn_sched_rx */
65
66/*****************************************************************************/
67/* hysdn_sched_tx is called from the cards handler to announce that there is */
68/* room in the tx-buffer to the card and data may be sent if needed. */
69/* If the routine wants to send data it must fill buf, len and chan with the */
70/* appropriate data and return a nonzero value. With a zero return no new */
71/* data to send is assumed. maxlen specifies the buffer size available for */
72/* sending. */
73/*****************************************************************************/
74int
75hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile *chan, word maxlen)
76{
77 struct sk_buff *skb;
78
79 if (card->net_tx_busy) {
80 card->net_tx_busy = 0; /* reset flag */
81 hysdn_tx_netack(card); /* acknowledge packet send */
82 } /* a network packet has completely been transferred */
83 /* first of all async requests are handled */
84 if (card->async_busy) {
85 if (card->async_len <= maxlen) {
86 memcpy(buf, card->async_data, card->async_len);
87 *len = card->async_len;
88 *chan = card->async_channel;
89 card->async_busy = 0; /* reset request */
90 return (1);
91 }
92 card->async_busy = 0; /* in case of length error */
93 } /* async request */
94 if ((card->err_log_state == ERRLOG_STATE_START) &&
95 (maxlen >= ERRLOG_CMD_REQ_SIZE)) {
96 strcpy(buf, ERRLOG_CMD_REQ); /* copy the command */
97 *len = ERRLOG_CMD_REQ_SIZE; /* buffer length */
98 *chan = CHAN_ERRLOG; /* and channel */
99 card->err_log_state = ERRLOG_STATE_ON; /* new state is on */
100 return (1); /* tell that data should be send */
101 } /* error log start and able to send */
102 if ((card->err_log_state == ERRLOG_STATE_STOP) &&
103 (maxlen >= ERRLOG_CMD_STOP_SIZE)) {
104 strcpy(buf, ERRLOG_CMD_STOP); /* copy the command */
105 *len = ERRLOG_CMD_STOP_SIZE; /* buffer length */
106 *chan = CHAN_ERRLOG; /* and channel */
107 card->err_log_state = ERRLOG_STATE_OFF; /* new state is off */
108 return (1); /* tell that data should be send */
109 } /* error log start and able to send */
110 /* now handle network interface packets */
111 if ((hynet_enable & (1 << card->myid)) &&
112 (skb = hysdn_tx_netget(card)) != NULL)
113 {
114 if (skb->len <= maxlen) {
115 memcpy(buf, skb->data, skb->len); /* copy the packet to the buffer */
116 *len = skb->len;
117 *chan = CHAN_NDIS_DATA;
118 card->net_tx_busy = 1; /* we are busy sending network data */
119 return (1); /* go and send the data */
120 } else
121 hysdn_tx_netack(card); /* aknowledge packet -> throw away */
122 } /* send a network packet if available */
123#ifdef CONFIG_HYSDN_CAPI
124 if( ((hycapi_enable & (1 << card->myid))) &&
125 ((skb = hycapi_tx_capiget(card)) != NULL) )
126 {
127 if (skb->len <= maxlen) {
128 memcpy(buf, skb->data, skb->len);
129 *len = skb->len;
130 *chan = CHAN_CAPI;
131 hycapi_tx_capiack(card);
132 return (1); /* go and send the data */
133 }
134 }
135#endif /* CONFIG_HYSDN_CAPI */
136 return (0); /* nothing to send */
137} /* hysdn_sched_tx */
138
139
140/*****************************************************************************/
141/* send one config line to the card and return 0 if successful, otherwise a */
142/* negative error code. */
143/* The function works with timeouts perhaps not giving the greatest speed */
144/* sending the line, but this should be meaningless beacuse only some lines */
145/* are to be sent and this happens very seldom. */
146/*****************************************************************************/
147int
148hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan)
149{
150 int cnt = 50; /* timeout intervalls */
151 ulong flags;
152
153 if (card->debug_flags & LOG_SCHED_ASYN)
154 hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
155
156 save_flags(flags);
157 cli();
158 while (card->async_busy) {
159 sti();
160
161 if (card->debug_flags & LOG_SCHED_ASYN)
162 hysdn_addlog(card, "async tx-cfg delayed");
163
164 msleep_interruptible(20); /* Timeout 20ms */
165 if (!--cnt) {
166 restore_flags(flags);
167 return (-ERR_ASYNC_TIME); /* timed out */
168 }
169 cli();
170 } /* wait for buffer to become free */
171
172 strcpy(card->async_data, line);
173 card->async_len = strlen(line) + 1;
174 card->async_channel = chan;
175 card->async_busy = 1; /* request transfer */
176
177 /* now queue the task */
178 schedule_work(&card->irq_queue);
179 sti();
180
181 if (card->debug_flags & LOG_SCHED_ASYN)
182 hysdn_addlog(card, "async tx-cfg data queued");
183
184 cnt++; /* short delay */
185 cli();
186
187 while (card->async_busy) {
188 sti();
189
190 if (card->debug_flags & LOG_SCHED_ASYN)
191 hysdn_addlog(card, "async tx-cfg waiting for tx-ready");
192
193 msleep_interruptible(20); /* Timeout 20ms */
194 if (!--cnt) {
195 restore_flags(flags);
196 return (-ERR_ASYNC_TIME); /* timed out */
197 }
198 cli();
199 } /* wait for buffer to become free again */
200
201 restore_flags(flags);
202
203 if (card->debug_flags & LOG_SCHED_ASYN)
204 hysdn_addlog(card, "async tx-cfg data send");
205
206 return (0); /* line send correctly */
207} /* hysdn_tx_cfgline */
diff --git a/drivers/isdn/hysdn/ince1pc.h b/drivers/isdn/hysdn/ince1pc.h
new file mode 100644
index 000000000000..4a115a87c782
--- /dev/null
+++ b/drivers/isdn/hysdn/ince1pc.h
@@ -0,0 +1,134 @@
1/*
2 * Linux driver for HYSDN cards
3 * common definitions for both sides of the bus:
4 * - conventions both spoolers must know
5 * - channel numbers agreed upon
6 *
7 * Author M. Steinkopf
8 * Copyright 1999 by M. Steinkopf
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 */
14
15#ifndef __INCE1PC_H__
16#define __INCE1PC_H__
17
18/* basic scalar definitions have same meanning,
19 * but their declaration location depends on environment
20 */
21
22/*--------------------------------------channel numbers---------------------*/
23#define CHAN_SYSTEM 0x0001 /* system channel (spooler to spooler) */
24#define CHAN_ERRLOG 0x0005 /* error logger */
25#define CHAN_CAPI 0x0064 /* CAPI interface */
26#define CHAN_NDIS_DATA 0x1001 /* NDIS data transfer */
27
28/*--------------------------------------POF ready msg-----------------------*/
29 /* NOTE: after booting POF sends system ready message to PC: */
30#define RDY_MAGIC 0x52535953UL /* 'SYSR' reversed */
31#define RDY_MAGIC_SIZE 4 /* size in bytes */
32
33#define MAX_N_TOK_BYTES 255
34
35#define MIN_RDY_MSG_SIZE RDY_MAGIC_SIZE
36#define MAX_RDY_MSG_SIZE (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES)
37
38#define SYSR_TOK_END 0
39#define SYSR_TOK_B_CHAN 1 /* nr. of B-Channels; DataLen=1; def: 2 */
40#define SYSR_TOK_FAX_CHAN 2 /* nr. of FAX Channels; DataLen=1; def: 0 */
41#define SYSR_TOK_MAC_ADDR 3 /* MAC-Address; DataLen=6; def: auto */
42#define SYSR_TOK_ESC 255 /* undefined data size yet */
43 /* default values, if not corrected by token: */
44#define SYSR_TOK_B_CHAN_DEF 2 /* assume 2 B-Channels */
45#define SYSR_TOK_FAX_CHAN_DEF 1 /* assume 1 FAX Channel */
46
47/* syntax of new SYSR token stream:
48 * channel: CHAN_SYSTEM
49 * msgsize: MIN_RDY_MSG_SIZE <= x <= MAX_RDY_MSG_SIZE
50 * RDY_MAGIC_SIZE <= x <= (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES)
51 * msg : 0 1 2 3 {4 5 6 ..}
52 * S Y S R MAX_N_TOK_BYTES bytes of TokenStream
53 *
54 * TokenStream := empty
55 * | {NonEndTokenChunk} EndToken RotlCRC
56 * NonEndTokenChunk:= NonEndTokenId DataLen [Data]
57 * NonEndTokenId := 0x01 .. 0xFE 1 BYTE
58 * DataLen := 0x00 .. 0xFF 1 BYTE
59 * Data := DataLen bytes
60 * EndToken := 0x00
61 * RotlCRC := special 1 byte CRC over all NonEndTokenChunk bytes
62 * s. RotlCRC algorithm
63 *
64 * RotlCRC algorithm:
65 * ucSum= 0 1 uchar
66 * for all NonEndTokenChunk bytes:
67 * ROTL(ucSum,1) rotate left by 1
68 * ucSum += Char; add current byte with swap around
69 * RotlCRC= ~ucSum; invert all bits for result
70 *
71 * note:
72 * - for 16-bit FIFO add padding 0 byte to achieve even token data bytes!
73 */
74
75/*--------------------------------------error logger------------------------*/
76 /* note: pof needs final 0 ! */
77#define ERRLOG_CMD_REQ "ERRLOG ON"
78#define ERRLOG_CMD_REQ_SIZE 10 /* with final 0 byte ! */
79#define ERRLOG_CMD_STOP "ERRLOG OFF"
80#define ERRLOG_CMD_STOP_SIZE 11 /* with final 0 byte ! */
81
82#define ERRLOG_ENTRY_SIZE 64 /* sizeof(tErrLogEntry) */
83 /* remaining text size = 55 */
84#define ERRLOG_TEXT_SIZE (ERRLOG_ENTRY_SIZE-2*4-1)
85
86typedef struct ErrLogEntry_tag {
87
88/*00 */ ulong ulErrType;
89
90/*04 */ ulong ulErrSubtype;
91
92/*08 */ uchar ucTextSize;
93
94 /*09 */ uchar ucText[ERRLOG_TEXT_SIZE];
95 /* ASCIIZ of len ucTextSize-1 */
96
97/*40 */
98} tErrLogEntry;
99
100
101#if defined(__TURBOC__)
102#if sizeof(tErrLogEntry) != ERRLOG_ENTRY_SIZE
103#error size of tErrLogEntry != ERRLOG_ENTRY_SIZE
104#endif /* */
105#endif /* */
106
107/*--------------------------------------DPRAM boot spooler------------------*/
108 /* this is the struture used between pc and
109 * hyperstone to exchange boot data
110 */
111#define DPRAM_SPOOLER_DATA_SIZE 0x20
112typedef struct DpramBootSpooler_tag {
113
114/*00 */ uchar Len;
115
116/*01 */ volatile uchar RdPtr;
117
118/*02 */ uchar WrPtr;
119
120/*03 */ uchar Data[DPRAM_SPOOLER_DATA_SIZE];
121
122/*23 */
123} tDpramBootSpooler;
124
125
126#define DPRAM_SPOOLER_MIN_SIZE 5 /* Len+RdPtr+Wrptr+2*data */
127#define DPRAM_SPOOLER_DEF_SIZE 0x23 /* current default size */
128
129/*--------------------------------------HYCARD/ERGO DPRAM SoftUart----------*/
130 /* at DPRAM offset 0x1C00: */
131#define SIZE_RSV_SOFT_UART 0x1B0 /* 432 bytes reserved for SoftUart */
132
133
134#endif /* __INCE1PC_H__ */