diff options
Diffstat (limited to 'drivers/isdn')
101 files changed, 6707 insertions, 3091 deletions
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in index 52b80809b..98b11349a 100644 --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -14,7 +14,7 @@ if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then fi bool ' Support isdn diversion services' CONFIG_ISDN_DIVERSION if [ "$CONFIG_X25" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool ' X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25 + bool ' X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25 fi dep_tristate ' ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN dep_tristate ' isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN @@ -52,26 +52,28 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then bool ' HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO bool ' HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL bool ' HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' HiSax Support for Winbond W6692 based cards (EXPERIMENTAL)' CONFIG_HISAX_W6692 # bool ' HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then bool ' HiSax Support for Am7930' CONFIG_HISAX_AMD7930 fi fi fi -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - dep_tristate ' Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN - dep_tristate ' IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN + dep_tristate ' IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN fi dep_tristate ' Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then - bool ' Eicon S, SX, SCOM, Quadro, S2M support' CONFIG_ISDN_DRV_EICON_ISA + bool ' Eicon S, SX, SCOM, Quadro, S2M support' CONFIG_ISDN_DRV_EICON_ISA fi dep_tristate ' AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI - bool ' AVM T1/T1B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA + bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA + bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON fi diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c index 80f06b080..99c93dbed 100644 --- a/drivers/isdn/act2000/act2000_isa.c +++ b/drivers/isdn/act2000/act2000_isa.c @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $ +/* $Id: act2000_isa.c,v 1.10 1999/10/24 18:46:05 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -20,6 +20,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.c,v $ + * Revision 1.10 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * + * Revision 1.9 1999/09/04 06:20:04 keil + * Changes from kernel set_current_state() + * * Revision 1.8 1999/01/05 18:29:25 he * merged remaining schedule_timeout() changes from 2.1.127 * @@ -61,17 +68,17 @@ static act2000_card *irq2card_map[16] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static int isa_irqs[] = +static int act2000_isa_irqs[] = { 3, 5, 7, 10, 11, 12, 15 }; -#define ISA_NRIRQS (sizeof(isa_irqs)/sizeof(int)) +#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int)) static void -isa_delay(long t) +act2000_isa_delay(long t) { sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(t); sti(); } @@ -83,7 +90,7 @@ isa_delay(long t) * 0 = Signature not found. */ static int -isa_reset(unsigned short portbase) +act2000_isa_reset(unsigned short portbase) { unsigned char reg; int i; @@ -109,7 +116,7 @@ isa_reset(unsigned short portbase) } int -isa_detect(unsigned short portbase) +act2000_isa_detect(unsigned short portbase) { int ret = 0; unsigned long flags; @@ -117,13 +124,13 @@ isa_detect(unsigned short portbase) save_flags(flags); cli(); if (!check_region(portbase, ISA_REGION)) - ret = isa_reset(portbase); + ret = act2000_isa_reset(portbase); restore_flags(flags); return ret; } static void -isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) +act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) { act2000_card *card = irq2card_map[irq]; u_char istatus; @@ -138,7 +145,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* RX fifo has data */ istatus &= ISA_ISR_OUT_MASK; outb(0, ISA_PORT_SIS); - isa_receive(card); + act2000_isa_receive(card); outb(ISA_SIS_INT, ISA_PORT_SIS); } if (istatus & ISA_ISR_ERR) { @@ -151,7 +158,7 @@ isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) } static void -isa_select_irq(act2000_card * card) +act2000_isa_select_irq(act2000_card * card) { unsigned char reg; @@ -183,9 +190,9 @@ isa_select_irq(act2000_card * card) } static void -isa_enable_irq(act2000_card * card) +act2000_isa_enable_irq(act2000_card * card) { - isa_select_irq(card); + act2000_isa_select_irq(card); /* Enable READ irq */ outb(ISA_SIS_INT, ISA_PORT_SIS); } @@ -195,7 +202,7 @@ isa_enable_irq(act2000_card * card) * If irq is -1, choose next free irq, else irq is given explicitely. */ int -isa_config_irq(act2000_card * card, short irq) +act2000_isa_config_irq(act2000_card * card, short irq) { int i; unsigned long flags; @@ -213,8 +220,8 @@ isa_config_irq(act2000_card * card, short irq) if (irq == -1) { /* Auto select */ for (i = 0; i < ISA_NRIRQS; i++) { - if (!request_irq(isa_irqs[i], &isa_interrupt, 0, card->regname, NULL)) { - card->irq = isa_irqs[i]; + if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) { + card->irq = act2000_isa_irqs[i]; irq2card_map[card->irq] = card; card->flags |= ACT2000_FLAGS_IVALID; break; @@ -222,7 +229,7 @@ isa_config_irq(act2000_card * card, short irq) } } else { /* Fixed irq */ - if (!request_irq(irq, &isa_interrupt, 0, card->regname, NULL)) { + if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) { card->irq = irq; irq2card_map[card->irq] = card; card->flags |= ACT2000_FLAGS_IVALID; @@ -234,7 +241,7 @@ isa_config_irq(act2000_card * card, short irq) "act2000: Could not request irq\n"); return -EBUSY; } else { - isa_select_irq(card); + act2000_isa_select_irq(card); /* Disable READ and WRITE irq */ outb(0, ISA_PORT_SIS); outb(0, ISA_PORT_SOS); @@ -243,7 +250,7 @@ isa_config_irq(act2000_card * card, short irq) } int -isa_config_port(act2000_card * card, unsigned short portbase) +act2000_isa_config_port(act2000_card * card, unsigned short portbase) { if (card->flags & ACT2000_FLAGS_PVALID) { release_region(card->port, ISA_REGION); @@ -262,7 +269,7 @@ isa_config_port(act2000_card * card, unsigned short portbase) * Release ressources, used by an adaptor. */ void -isa_release(act2000_card * card) +act2000_isa_release(act2000_card * card) { unsigned long flags; @@ -280,7 +287,7 @@ isa_release(act2000_card * card) } static int -isa_writeb(act2000_card * card, u_char data) +act2000_isa_writeb(act2000_card * card, u_char data) { u_char timeout = 40; @@ -297,7 +304,7 @@ isa_writeb(act2000_card * card, u_char data) } static int -isa_readb(act2000_card * card, u_char * data) +act2000_isa_readb(act2000_card * card, u_char * data) { u_char timeout = 40; @@ -314,13 +321,13 @@ isa_readb(act2000_card * card, u_char * data) } void -isa_receive(act2000_card *card) +act2000_isa_receive(act2000_card *card) { u_char c; if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0) return; - while (!isa_readb(card, &c)) { + while (!act2000_isa_readb(card, &c)) { if (card->idat.isa.rcvidx < 8) { card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c; if (card->idat.isa.rcvidx == 8) { @@ -332,7 +339,7 @@ isa_receive(act2000_card *card) if (card->idat.isa.rcvskb == NULL) { card->idat.isa.rcvignore = 1; printk(KERN_WARNING - "isa_receive: no memory\n"); + "act2000_isa_receive: no memory\n"); test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); return; } @@ -341,12 +348,12 @@ isa_receive(act2000_card *card) } else { card->idat.isa.rcvidx = 0; printk(KERN_WARNING - "isa_receive: Invalid CAPI msg\n"); + "act2000_isa_receive: Invalid CAPI msg\n"); { int i; __u8 *p; __u8 *c; __u8 tmp[30]; for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++) c += sprintf(c, "%02x ", *(p++)); - printk(KERN_WARNING "isa_receive: %s\n", tmp); + printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp); } } } @@ -377,7 +384,7 @@ isa_receive(act2000_card *card) } void -isa_send(act2000_card * card) +act2000_isa_send(act2000_card * card) { unsigned long flags; struct sk_buff *skb; @@ -410,11 +417,8 @@ isa_send(act2000_card * card) skb = card->sbuf; l = 0; while (skb->len) { - if (isa_writeb(card, *(skb->data))) { + if (act2000_isa_writeb(card, *(skb->data))) { /* Fifo is full, but more data to send */ -#if 0 - printk(KERN_DEBUG "isa_send: %d bytes\n", l); -#endif test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); /* Schedule myself */ act2000_schedule_tx(card); @@ -437,9 +441,6 @@ isa_send(act2000_card * card) } else dev_kfree_skb(skb); card->sbuf = NULL; -#if 0 - printk(KERN_DEBUG "isa_send: %d bytes\n", l); -#endif } } @@ -447,7 +448,7 @@ isa_send(act2000_card * card) * Get firmware ID, check for 'ISDN' signature. */ static int -isa_getid(act2000_card * card) +act2000_isa_getid(act2000_card * card) { act2000_fwid fid; @@ -457,7 +458,7 @@ isa_getid(act2000_card * card) while (1) { if (count > 510) return -EPROTO; - if (isa_readb(card, p++)) + if (act2000_isa_readb(card, p++)) break; count++; } @@ -476,7 +477,7 @@ isa_getid(act2000_card * card) printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision); if (card->flags & ACT2000_FLAGS_IVALID) { printk(KERN_DEBUG "Enabling Interrupts ...\n"); - isa_enable_irq(card); + act2000_isa_enable_irq(card); } return 0; } @@ -485,7 +486,7 @@ isa_getid(act2000_card * card) * Download microcode into card, check Firmware signature. */ int -isa_download(act2000_card * card, act2000_ddef * cb) +act2000_isa_download(act2000_card * card, act2000_ddef * cb) { int length; int ret; @@ -497,9 +498,9 @@ isa_download(act2000_card * card, act2000_ddef * cb) u_char *buf; act2000_ddef cblock; - if (!isa_reset(card->port)) + if (!act2000_isa_reset(card->port)) return -ENXIO; - isa_delay(HZ / 2); + act2000_isa_delay(HZ / 2); if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock)))) return ret; copy_from_user(&cblock, (char *) cb, sizeof(cblock)); @@ -517,7 +518,7 @@ isa_download(act2000_card * card, act2000_ddef * cb) b = buf; copy_from_user(buf, p, l); while (c < l) { - if (isa_writeb(card, *b++)) { + if (act2000_isa_writeb(card, *b++)) { printk(KERN_WARNING "act2000: loader timed out" " len=%d c=%d\n", length, c); @@ -530,6 +531,6 @@ isa_download(act2000_card * card, act2000_ddef * cb) p += l; } kfree(buf); - isa_delay(HZ / 2); - return (isa_getid(card)); + act2000_isa_delay(HZ / 2); + return (act2000_isa_getid(card)); } diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h index 35a68e7d2..ff3e5419a 100644 --- a/drivers/isdn/act2000/act2000_isa.h +++ b/drivers/isdn/act2000/act2000_isa.h @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $ +/* $Id: act2000_isa.h,v 1.3 1999/10/24 18:46:05 fritz Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: act2000_isa.h,v $ + * Revision 1.3 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * * Revision 1.2 1998/11/05 22:12:43 fritz * Changed mail-address. * @@ -141,12 +145,12 @@ typedef enum { /* Prototypes */ -extern int isa_detect(unsigned short portbase); -extern int isa_config_irq(act2000_card * card, short irq); -extern int isa_config_port(act2000_card * card, unsigned short portbase); -extern int isa_download(act2000_card * card, act2000_ddef * cb); -extern void isa_release(act2000_card * card); -extern void isa_receive(act2000_card *card); -extern void isa_send(act2000_card *card); +extern int act2000_isa_detect(unsigned short portbase); +extern int act2000_isa_config_irq(act2000_card * card, short irq); +extern int act2000_isa_config_port(act2000_card * card, unsigned short portbase); +extern int act2000_isa_download(act2000_card * card, act2000_ddef * cb); +extern void act2000_isa_release(act2000_card * card); +extern void act2000_isa_receive(act2000_card *card); +extern void act2000_isa_send(act2000_card *card); #endif /* act2000_isa_h */ diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c index df2fd68d3..9502b314e 100644 --- a/drivers/isdn/act2000/capi.c +++ b/drivers/isdn/act2000/capi.c @@ -113,10 +113,6 @@ static actcapi_msgdsc valid_msg[] = { {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"}, {{ 0x86, 0x03}, "DATA_B3_RESP"}, {{ 0xff, 0x03}, "MANUFACTURER_RESP"}, -#if 0 -/* CAPI 2.0 */ - {{ 0x05, 0x80}, "LISTEN_REQ (CAPI 2.0)"}, -#endif #endif {{ 0x00, 0x00}, NULL}, }; diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h index 69a104100..0500550db 100644 --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h @@ -322,19 +322,6 @@ typedef struct actcapi_msg { __u16 plci; __u16 info; } select_b3_protocol_conf; -#if 0 - struct listen_req { - __u32 controller; - __u32 infomask; - __u32 cipmask; - __u32 cipmask2; - __u16 dummy; /* 2 Length-bytes of 2 Structs MUST always be 0!!! */ - } listen_req; - struct listen_conf { - __u32 controller; - __u16 info; - } listen_conf; -#else struct listen_req { __u8 controller; __u32 infomask __attribute__ ((packed)); @@ -345,7 +332,6 @@ typedef struct actcapi_msg { __u8 controller; __u16 info __attribute__ ((packed)); } listen_conf; -#endif struct data_b3_req { __u16 fakencci; __u16 datalen; diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index 2ec5e2fd4..f15279253 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -1,4 +1,4 @@ -/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $ +/* $Id: module.c,v 1.11 1999/10/30 09:48:04 keil Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -20,6 +20,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: module.c,v $ + * Revision 1.11 1999/10/30 09:48:04 keil + * miss one prefix act2000 + * + * Revision 1.10 1999/10/24 18:46:05 fritz + * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest + * kernels. + * * Revision 1.9 1999/04/12 13:13:56 fritz * Made cards pointer static to avoid name-clash. * @@ -56,12 +63,12 @@ #include "act2000_isa.h" #include "capi.h" -static unsigned short isa_ports[] = +static unsigned short act2000_isa_ports[] = { 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, }; -#define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short)) +#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short)) static act2000_card *cards = (act2000_card *) NULL; @@ -238,7 +245,7 @@ act2000_transmit(struct act2000_card *card) { switch (card->bus) { case ACT2000_BUS_ISA: - isa_send(card); + act2000_isa_send(card); break; case ACT2000_BUS_PCMCIA: case ACT2000_BUS_MCA: @@ -253,7 +260,7 @@ act2000_receive(struct act2000_card *card) { switch (card->bus) { case ACT2000_BUS_ISA: - isa_receive(card); + act2000_isa_receive(card); break; case ACT2000_BUS_PCMCIA: case ACT2000_BUS_MCA: @@ -296,7 +303,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) case ACT2000_IOCTL_LOADBOOT: switch (card->bus) { case ACT2000_BUS_ISA: - ret = isa_download(card, + ret = act2000_isa_download(card, (act2000_ddef *)a); if (!ret) { card->flags |= ACT2000_FLAGS_LOADED; @@ -701,10 +708,6 @@ act2000_alloccard(int bus, int port, int irq, char *id) card->interface.features = ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_HDLC | -#if 0 -/* Not yet! New Firmware is on the way ... */ - ISDN_FEATURE_L2_TRANS | -#endif ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 20; @@ -762,7 +765,7 @@ unregister_card(act2000_card * card) card->interface.statcallb(&cmd); switch (card->bus) { case ACT2000_BUS_ISA: - isa_release(card); + act2000_isa_release(card); break; case ACT2000_BUS_MCA: case ACT2000_BUS_PCMCIA: @@ -796,11 +799,11 @@ act2000_addcard(int bus, int port, int irq, char *id) switch (bus) { case ACT2000_BUS_ISA: for (i = 0; i < ISA_NRPORTS; i++) - if (isa_detect(isa_ports[i])) { + if (act2000_isa_detect(act2000_isa_ports[i])) { printk(KERN_INFO "act2000: Detected ISA card at port 0x%x\n", - isa_ports[i]); - act2000_alloccard(bus, isa_ports[i], irq, id); + act2000_isa_ports[i]); + act2000_alloccard(bus, act2000_isa_ports[i], irq, id); } break; case ACT2000_BUS_MCA: @@ -823,10 +826,10 @@ act2000_addcard(int bus, int port, int irq, char *id) added++; switch (p->bus) { case ACT2000_BUS_ISA: - if (isa_detect(p->port)) { + if (act2000_isa_detect(p->port)) { if (act2000_registercard(p)) break; - if (isa_config_port(p, p->port)) { + if (act2000_isa_config_port(p, p->port)) { printk(KERN_WARNING "act2000: Could not request port 0x%04x\n", p->port); @@ -834,7 +837,7 @@ act2000_addcard(int bus, int port, int irq, char *id) p->interface.statcallb = NULL; break; } - if (isa_config_irq(p, p->irq)) { + if (act2000_isa_config_irq(p, p->irq)) { printk(KERN_INFO "act2000: No IRQ available, fallback to polling\n"); /* Fall back to polled operation */ diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile index 9f73ea2e3..111c39466 100644 --- a/drivers/isdn/avmb1/Makefile +++ b/drivers/isdn/avmb1/Makefile @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.6 1999/07/20 06:41:44 calle Exp $ +# $Id: Makefile,v 1.7 1999/09/15 08:16:03 calle Exp $ # # Makefile for the CAPI and AVM-B1 device drivers. # @@ -11,6 +11,9 @@ # parent makes.. # # $Log: Makefile,v $ +# Revision 1.7 1999/09/15 08:16:03 calle +# Implementation of 64Bit extention complete. +# # Revision 1.6 1999/07/20 06:41:44 calle # Bugfix: After the redesign of the AVM B1 driver, the driver didn't even # compile, if not selected as modules. @@ -90,6 +93,12 @@ ifeq ($(CONFIG_ISDN_DRV_AVMB1),y) ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA OX_OBJS += b1pcmcia.o endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI + O_OBJS += t1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_C4 + O_OBJS += c4.o + endif OX_OBJS += capiutil.o capidrv.o b1.o else ifeq ($(CONFIG_ISDN_DRV_AVMB1),m) @@ -105,10 +114,16 @@ else ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA M_OBJS += t1isa.o endif - MX_OBJS += capiutil.o capidrv.o b1.o ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA MX_OBJS += b1pcmcia.o endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI + M_OBJS += t1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_C4 + M_OBJS += c4.o + endif + MX_OBJS += capiutil.o capidrv.o b1.o endif endif diff --git a/drivers/isdn/avmb1/avmcard.h b/drivers/isdn/avmb1/avmcard.h index e94c5637c..f4b5df689 100644 --- a/drivers/isdn/avmb1/avmcard.h +++ b/drivers/isdn/avmb1/avmcard.h @@ -1,9 +1,21 @@ /* - * $Id: avmcard.h,v 1.4 1999/08/04 10:10:08 calle Exp $ + * $Id: avmcard.h,v 1.6 1999/11/05 16:38:01 calle Exp $ * * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avmcard.h,v $ + * Revision 1.6 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.5 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.4 1999/08/04 10:10:08 calle * Bugfix: corrected /proc functions, added structure for new AVM cards. * @@ -73,6 +85,7 @@ typedef struct avmcard_dmainfo { __u8 sendbuf[128+2048]; } avmcard_dmainfo; + typedef struct avmcard { char name[32]; unsigned int port; @@ -81,25 +94,34 @@ typedef struct avmcard { enum avmcardtype cardtype; int cardnr; /* for t1isa */ - int versionlen; - char versionbuf[1024]; - char *version[AVM_MAXVERSION]; - - char cardname[32]; - - char infobuf[128]; /* for function procinfo */ char msgbuf[128]; /* capimsg msg part */ char databuf[2048]; /* capimsg data part */ int interrupt; void *mbase; - __u32 csr; + volatile __u32 csr; avmcard_dmainfo *dma; - struct capi_ctr *ctrl; + struct avmctrl_info { + char cardname[32]; + + int versionlen; + char versionbuf[1024]; + char *version[AVM_MAXVERSION]; + + char infobuf[128]; /* for function procinfo */ + + struct avmcard *card; + struct capi_ctr *capi_ctrl; + + } *ctrlinfo; + + int nlogcontr; } avmcard; +typedef struct avmctrl_info avmctrl_info; + extern int b1_irq_table[16]; /* @@ -540,16 +562,16 @@ static inline void b1_setinterrupt(unsigned int base, unsigned irq, } int b1_detect(unsigned int base, enum avmcardtype cardtype); -int b1_load_t4file(unsigned int base, capiloaddatapart * t4file); -int b1_load_config(unsigned int base, capiloaddatapart * config); -int b1_loaded(unsigned int base); +int b1_load_t4file(avmcard *card, capiloaddatapart * t4file); +int b1_load_config(avmcard *card, capiloaddatapart * config); +int b1_loaded(avmcard *card); int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); void b1_reset_ctr(struct capi_ctr *ctrl); void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp); void b1_release_appl(struct capi_ctr *ctrl, __u16 appl); void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -void b1_parse_version(avmcard *card); +void b1_parse_version(avmctrl_info *card); void b1_handle_interrupt(avmcard * card); int b1ctl_read_proc(char *page, char **start, off_t off, diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c index c4dffdacb..900b31c8c 100644 --- a/drivers/isdn/avmb1/b1.c +++ b/drivers/isdn/avmb1/b1.c @@ -1,11 +1,29 @@ /* - * $Id: b1.c,v 1.8 1999/08/22 20:26:22 calle Exp $ + * $Id: b1.c,v 1.12 1999/11/05 16:38:01 calle Exp $ * * Common module for AVM B1 cards. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1.c,v $ + * Revision 1.12 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.11 1999/10/11 22:04:12 keil + * COMPAT_NEED_UACCESS (no include in isdn_compat.h) + * + * Revision 1.10 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.9 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.8 1999/08/22 20:26:22 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -62,13 +80,13 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> +#include <asm/uaccess.h> #include "capilli.h" #include "avmcard.h" #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.8 $"; +static char *revision = "$Revision: 1.12 $"; /* ------------------------------------------------------------- */ @@ -140,11 +158,12 @@ int b1_detect(unsigned int base, enum avmcardtype cardtype) return 0; } -int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) +int b1_load_t4file(avmcard *card, capiloaddatapart * t4file) { unsigned char buf[256]; unsigned char *dp; int i, left, retval; + unsigned int base = card->port; dp = t4file->data; left = t4file->len; @@ -158,7 +177,8 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) } for (i = 0; i < sizeof(buf); i++) if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + printk(KERN_ERR "%s: corrupted firmware file ?\n", + card->name); return -EIO; } left -= sizeof(buf); @@ -174,17 +194,19 @@ int b1_load_t4file(unsigned int base, capiloaddatapart * t4file) } for (i = 0; i < left; i++) if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n"); + printk(KERN_ERR "%s: corrupted firmware file ?\n", + card->name); return -EIO; } } return 0; } -int b1_load_config(unsigned int base, capiloaddatapart * config) +int b1_load_config(avmcard *card, capiloaddatapart * config) { unsigned char buf[256]; unsigned char *dp; + unsigned int base = card->port; int i, j, left, retval; dp = config->data; @@ -233,8 +255,9 @@ int b1_load_config(unsigned int base, capiloaddatapart * config) return 0; } -int b1_loaded(unsigned int base) +int b1_loaded(avmcard *card) { + unsigned int base = card->port; unsigned long stop; unsigned char ans; unsigned long tout = 2; @@ -244,7 +267,8 @@ int b1_loaded(unsigned int base) break; } if (!b1_tx_empty(base)) { - printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n"); + printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n", + card->name); return 0; } b1_put_byte(base, SEND_POLL); @@ -253,11 +277,12 @@ int b1_loaded(unsigned int base) if ((ans = b1_get_byte(base)) == RECEIVE_POLL) { return 1; } - printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans); + printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n", + card->name, ans); return 0; } } - printk(KERN_ERR "b1_loaded: firmware not running\n"); + printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name); return 0; } @@ -265,14 +290,15 @@ int b1_loaded(unsigned int base) int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int retval; b1_reset(port); - if ((retval = b1_load_t4file(port, &data->firmware))) { + if ((retval = b1_load_t4file(card, &data->firmware))) { b1_reset(port); printk(KERN_ERR "%s: failed to load t4file!!\n", card->name); @@ -282,7 +308,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) b1_disable_irq(port); if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(port, &data->configuration))) { + if ((retval = b1_load_config(card, &data->configuration))) { b1_reset(port); printk(KERN_ERR "%s: failed to load config!!\n", card->name); @@ -290,7 +316,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } } - if (!b1_loaded(port)) { + if (!b1_loaded(card)) { printk(KERN_ERR "%s: failed to load t4file.\n", card->name); return -EIO; } @@ -309,13 +335,14 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) void b1_reset_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); b1_reset(port); - memset(card->version, 0, sizeof(card->version)); + memset(cinfo->version, 0, sizeof(cinfo->version)); ctrl->reseted(ctrl); } @@ -323,7 +350,8 @@ void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int nconn, want = rp->level3cnt; @@ -347,7 +375,8 @@ void b1_register_appl(struct capi_ctr *ctrl, void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; @@ -360,7 +389,8 @@ void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; __u16 len = CAPIMSG_LEN(skb->data); @@ -384,25 +414,26 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) /* ------------------------------------------------------------- */ -void b1_parse_version(avmcard *card) +void b1_parse_version(avmctrl_info *cinfo) { - struct capi_ctr *ctrl = card->ctrl; + struct capi_ctr *ctrl = cinfo->capi_ctrl; + avmcard *card = cinfo->card; capi_profile *profp; __u8 *dversion; __u8 flag; int i, j; for (j = 0; j < AVM_MAXVERSION; j++) - card->version[j] = "\0\0" + 1; + cinfo->version[j] = "\0\0" + 1; for (i = 0, j = 0; - j < AVM_MAXVERSION && i < card->versionlen; - j++, i += card->versionbuf[i] + 1) - card->version[j] = &card->versionbuf[i + 1]; + j < AVM_MAXVERSION && i < cinfo->versionlen; + j++, i += cinfo->versionbuf[i] + 1) + cinfo->version[j] = &cinfo->versionbuf[i + 1]; - strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN); - memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile)); + strncpy(ctrl->serial, cinfo->version[VER_SERIAL], CAPI_SERIAL_LEN); + memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile)); strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN); - dversion = card->version[VER_DRIVER]; + dversion = cinfo->version[VER_DRIVER]; ctrl->version.majorversion = 2; ctrl->version.minorversion = 0; ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); @@ -415,23 +446,24 @@ void b1_parse_version(avmcard *card) flag = ((__u8 *)(profp->manu))[1]; switch (flag) { - case 0: if (card->version[VER_CARDTYPE]) - strcpy(card->cardname, card->version[VER_CARDTYPE]); - else strcpy(card->cardname, "B1"); + case 0: if (cinfo->version[VER_CARDTYPE]) + strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]); + else strcpy(cinfo->cardname, "B1"); break; - case 3: strcpy(card->cardname,"PCMCIA B"); break; - case 4: strcpy(card->cardname,"PCMCIA M1"); break; - case 5: strcpy(card->cardname,"PCMCIA M2"); break; - case 6: strcpy(card->cardname,"B1 V3.0"); break; - case 7: strcpy(card->cardname,"B1 PCI"); break; - default: sprintf(card->cardname, "AVM?%u", (unsigned int)flag); break; + case 3: strcpy(cinfo->cardname,"PCMCIA B"); break; + case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break; + case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break; + case 6: strcpy(cinfo->cardname,"B1 V3.0"); break; + case 7: strcpy(cinfo->cardname,"B1 PCI"); break; + default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break; } printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", - card->name, ctrl->cnr, card->cardname); + card->name, ctrl->cnr, cinfo->cardname); flag = ((__u8 *)(profp->manu))[3]; if (flag) - printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n", + printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n", + card->name, ctrl->cnr, (flag & 0x01) ? " DSS1" : "", (flag & 0x02) ? " CT1" : "", @@ -458,7 +490,8 @@ void b1_parse_version(avmcard *card) void b1_handle_interrupt(avmcard * card) { - struct capi_ctr *ctrl = card->ctrl; + avmctrl_info *cinfo = &card->ctrlinfo[0]; + struct capi_ctr *ctrl = cinfo->capi_ctrl; unsigned char b1cmd; struct sk_buff *skb; @@ -481,13 +514,17 @@ void b1_handle_interrupt(avmcard * card) MsgLen = b1_get_slice(card->port, card->msgbuf); DataB3Len = b1_get_slice(card->port, card->databuf); + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); } break; @@ -536,12 +573,12 @@ void b1_handle_interrupt(avmcard * card) case RECEIVE_INIT: - card->versionlen = b1_get_slice(card->port, card->versionbuf); - b1_parse_version(card); + cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); + b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, - card->version[VER_CARDTYPE], - card->version[VER_DRIVER]); + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); ctrl->ready(ctrl); break; @@ -581,7 +618,8 @@ void b1_handle_interrupt(avmcard * card) int b1ctl_read_proc(char *page, char **start, off_t off, int count, int *eof, struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; __u8 flag; int len = 0; char *s; @@ -603,11 +641,11 @@ int b1ctl_read_proc(char *page, char **start, off_t off, len += sprintf(page+len, "%-16s %s\n", "type", s); if (card->cardtype == avm_t1isa) len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); - if ((s = card->version[VER_DRIVER]) != 0) + if ((s = cinfo->version[VER_DRIVER]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = card->version[VER_CARDTYPE]) != 0) + if ((s = cinfo->version[VER_CARDTYPE]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = card->version[VER_SERIAL]) != 0) + if ((s = cinfo->version[VER_SERIAL]) != 0) len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); if (card->cardtype != avm_m1) { @@ -635,7 +673,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off, (flag & 0x04) ? " leased line with D-channel" : "" ); } - len += sprintf(page+len, "%-16s %s\n", "cardname", card->cardname); + len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); if (off+count >= len) *eof = 1; diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c index 9ab198432..01972b2d2 100644 --- a/drivers/isdn/avmb1/b1isa.c +++ b/drivers/isdn/avmb1/b1isa.c @@ -1,11 +1,18 @@ /* - * $Id: b1isa.c,v 1.4 1999/08/22 20:26:24 calle Exp $ + * $Id: b1isa.c,v 1.5 1999/11/05 16:38:01 calle Exp $ * * Module for AVM B1 ISA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1isa.c,v $ + * Revision 1.5 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * * Revision 1.4 1999/08/22 20:26:24 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -49,13 +56,12 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.4 $"; +static char *revision = "$Revision: 1.5 $"; /* ------------------------------------------------------------- */ @@ -92,7 +98,8 @@ static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static void b1isa_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -101,6 +108,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl) di->detach_ctr(ctrl); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -110,6 +118,7 @@ static void b1isa_remove_ctr(struct capi_ctr *ctrl) static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) { + avmctrl_info *cinfo; avmcard *card; int retval; @@ -120,6 +129,15 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "b1isa: no memory.\n"); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "b1isa-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -129,17 +147,20 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) printk(KERN_WARNING "b1isa: ports 0x%03x-0x%03x in use.\n", card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } if (b1_irq_table[card->irq & 0xf] == 0) { printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } if ( card->port != 0x150 && card->port != 0x250 && card->port != 0x300 && card->port != 0x340) { printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } @@ -147,6 +168,7 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) if ((retval = b1_detect(card->port, card->cardtype)) != 0) { printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -158,15 +180,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) if (retval) { printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { printk(KERN_ERR "b1isa: attach controller failed.\n"); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -177,15 +201,17 @@ static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static char *b1isa_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c index 8c0006a78..f4e87b12f 100644 --- a/drivers/isdn/avmb1/b1pci.c +++ b/drivers/isdn/avmb1/b1pci.c @@ -1,11 +1,21 @@ /* - * $Id: b1pci.c,v 1.16 1999/08/11 21:01:07 keil Exp $ + * $Id: b1pci.c,v 1.18 1999/11/05 16:38:01 calle Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.18 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.17 1999/10/05 06:50:07 calle + * Forgot SA_SHIRQ as argument to request_irq. + * * Revision 1.16 1999/08/11 21:01:07 keil * new PCI codefix * @@ -51,13 +61,12 @@ #include <linux/pci.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.16 $"; +static char *revision = "$Revision: 1.18 $"; /* ------------------------------------------------------------- */ @@ -86,11 +95,11 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "b1_interrupt: wrong device\n"); + printk(KERN_WARNING "b1pci: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", card->name); return; } @@ -104,7 +113,8 @@ static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static void b1pci_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -114,6 +124,7 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl) free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); ctrl->driverdata = 0; + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -123,15 +134,17 @@ static void b1pci_remove_ctr(struct capi_ctr *ctrl) static char *b1pci_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ @@ -139,15 +152,25 @@ static char *b1pci_procinfo(struct capi_ctr *ctrl) static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) { avmcard *card; + avmctrl_info *cinfo; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "b1pci: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "b1pci-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -155,15 +178,17 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) if (check_region(card->port, AVMB1_PORTLEN)) { printk(KERN_WARNING - "b1pci: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } b1_reset(card->port); if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -171,19 +196,23 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) request_region(p->port, AVMB1_PORTLEN, card->name); - retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card); + retval = request_irq(card->irq, b1pci_interrupt, SA_SHIRQ, card->name, card); if (retval) { - printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "b1pci: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -252,7 +281,7 @@ int b1pci_init(void) while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { struct capicardparams param; - param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK; + param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; param.irq = dev->irq; printk(KERN_INFO "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", @@ -277,7 +306,7 @@ int b1pci_init(void) printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name); return -ESRCH; #else - printk(KERN_ERR "b1pci: kernel not compiled with PCI.\n"); + printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); return -EIO; #endif } diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c index d6acda9d9..79e343164 100644 --- a/drivers/isdn/avmb1/b1pcmcia.c +++ b/drivers/isdn/avmb1/b1pcmcia.c @@ -1,11 +1,18 @@ /* - * $Id: b1pcmcia.c,v 1.4 1999/08/22 20:26:26 calle Exp $ + * $Id: b1pcmcia.c,v 1.5 1999/11/05 16:38:01 calle Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pcmcia.c,v $ + * Revision 1.5 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * * Revision 1.4 1999/08/22 20:26:26 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -50,13 +57,12 @@ #include <asm/io.h> #include <linux/capi.h> #include <linux/b1pcmcia.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.4 $"; +static char *revision = "$Revision: 1.5 $"; /* ------------------------------------------------------------- */ @@ -75,11 +81,12 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "b1_interrupt: wrong device\n"); + printk(KERN_WARNING "b1pcmcia: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", + card->name); return; } @@ -93,7 +100,8 @@ static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; b1_reset(port); @@ -116,16 +124,26 @@ static int b1pcmcia_add_card(struct capi_driver *driver, unsigned irq, enum avmcardtype cardtype) { + avmctrl_info *cinfo; avmcard *card; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "b1pcmcia: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; switch (cardtype) { case avm_m1: sprintf(card->name, "m1-%x", port); break; case avm_m2: sprintf(card->name, "m2-%x", port); break; @@ -137,8 +155,9 @@ static int b1pcmcia_add_card(struct capi_driver *driver, b1_reset(card->port); if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -146,36 +165,42 @@ static int b1pcmcia_add_card(struct capi_driver *driver, retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card); if (retval) { - printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "b1pcmcia: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } MOD_INC_USE_COUNT; - return card->ctrl->cnr; + return cinfo->capi_ctrl->cnr; } /* ------------------------------------------------------------- */ static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq + sprintf(cinfo->infobuf, "%s %s 0x%x %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0 ); - return card->infobuf; + return cinfo->infobuf; } /* ------------------------------------------------------------- */ @@ -220,7 +245,7 @@ int b1pcmcia_delcard(unsigned int port, unsigned irq) avmcard *card; for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) { - card = (avmcard *)(ctrl->driverdata); + card = ((avmctrl_info *)(ctrl->driverdata))->card; if (card->port == port && card->irq == irq) { b1pcmcia_remove_ctr(ctrl); return 0; diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c index c8cab6919..6d1159d56 100644 --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -1,11 +1,20 @@ /* - * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $ + * $Id: capi.c,v 1.21 1999/09/10 17:24:18 calle Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.21 1999/09/10 17:24:18 calle + * Changes for proposed standard for CAPI2.0: + * - AK148 "Linux Exention" + * + * Revision 1.20 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.19 1999/07/09 15:05:42 keil * compat.h is now isdn_compat.h * @@ -117,7 +126,6 @@ #include <linux/capi.h> #include <linux/kernelcapi.h> -#include <linux/isdn_compat.h> #include "capiutil.h" #include "capicmd.h" #include "capidev.h" @@ -201,9 +209,6 @@ static ssize_t capi_read(struct file *file, char *buf, skb_queue_head(&cdev->recv_queue, skb); return -EMSGSIZE; } - if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) - CAPIMSG_SETDATA(skb->data, buf + CAPIMSG_LEN(skb->data)); retval = copy_to_user(buf, skb->data, skb->len); if (retval) { skb_queue_head(&cdev->recv_queue, skb); @@ -429,7 +434,7 @@ static int capi_ioctl(struct inode *inode, struct file *file, return data.errcode; case CAPI_INSTALLED: - if ((*capifuncs->capi_installed) ()) + if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR) return 0; return -ENXIO; @@ -615,16 +620,12 @@ static struct capi_interface_user cuser = { int capi_init(void) { -#ifdef COMPAT_HAS_NEW_WAITQ int j; -#endif memset(capidevs, 0, sizeof(capidevs)); -#ifdef COMPAT_HAS_NEW_WAITQ for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) { init_waitqueue_head(&capidevs[j].recv_wait); } -#endif if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h index c66554a29..96e37c1f4 100644 --- a/drivers/isdn/avmb1/capidev.h +++ b/drivers/isdn/avmb1/capidev.h @@ -44,11 +44,7 @@ struct capidev { int is_registered; __u16 applid; struct sk_buff_head recv_queue; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t recv_wait; -#else - struct wait_queue *recv_wait; -#endif __u16 errcode; /* Statistic */ unsigned long nopen; diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c index fb83e52a6..6db170e42 100644 --- a/drivers/isdn/avmb1/capidrv.c +++ b/drivers/isdn/avmb1/capidrv.c @@ -1,11 +1,17 @@ /* - * $Id: capidrv.c,v 1.26 1999/08/06 07:41:16 calle Exp $ + * $Id: capidrv.c,v 1.28 1999/11/05 16:22:37 calle Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.28 1999/11/05 16:22:37 calle + * Bugfix: Missing break in switch on ISDN_CMD_HANGUP. + * + * Revision 1.27 1999/09/16 15:13:04 calle + * forgot to change paramter type of contr for lower_callback ... + * * Revision 1.26 1999/08/06 07:41:16 calle * Added the "vbox patch". if (si1 == 1) si2 = 0; * @@ -158,12 +164,11 @@ #include <linux/ctype.h> #include <asm/segment.h> -#include <linux/isdn_compat.h> #include "capiutil.h" #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.26 $"; +static char *revision = "$Revision: 1.28 $"; int debugmode = 0; MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>"); @@ -714,8 +719,6 @@ static struct plcistatechange plcitable[] = /* P-0.1 */ {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, /* P-1 */ {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, @@ -1855,14 +1858,19 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) ); ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ); send_message(card, &cmdcmsg); + return 0; } else if (bchan->plcip) { - bchan->disconnecting = 1; if (bchan->plcip->state == ST_PLCI_INCOMING) { - /* just ignore, we a called from isdn_status_callback(), - * which will return 0 or 2, this is handled by the - * CONNECT_IND handler + /* + * just ignore, we a called from + * isdn_status_callback(), + * which will return 0 or 2, this is handled + * by the CONNECT_IND handler */ - } else { + bchan->disconnecting = 1; + return 0; + } else if (bchan->plcip->plci) { + bchan->disconnecting = 1; capi_fill_DISCONNECT_REQ(&cmdcmsg, global.appid, card->msgid++, @@ -1874,8 +1882,18 @@ static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) ); plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ); send_message(card, &cmdcmsg); + return 0; + } else { + printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n", + card->contrnr, + c->arg); + return -EINVAL; } } + printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n", + card->contrnr, + c->arg); + return -EINVAL; /* ready */ case ISDN_CMD_SETL2: @@ -2022,10 +2040,8 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) (void)capidrv_del_ack(nccip, datahandle); return 0; } -#if 1 printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n", card->contrnr, skb_headroom(skb), msglen); -#endif memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen); errcode = (*capifuncs->capi_put_message) (global.appid, nskb); if (errcode == CAPI_NOERROR) { @@ -2211,10 +2227,6 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp) ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | -#if 0 - ISDN_FEATURE_L2_FAX | - ISDN_FEATURE_L3_FAX | -#endif ISDN_FEATURE_P_UNKNOWN; card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); @@ -2309,7 +2321,7 @@ static int capidrv_delcontr(__u16 contr) } -static void lower_callback(unsigned int cmd, __u16 contr, void *data) +static void lower_callback(unsigned int cmd, __u32 contr, void *data) { switch (cmd) { diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c index 7f1a9f1ad..3482f2a97 100644 --- a/drivers/isdn/avmb1/capiutil.c +++ b/drivers/isdn/avmb1/capiutil.c @@ -1,5 +1,5 @@ /* - * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $ + * $Id: capiutil.c,v 1.10 1999/08/31 11:19:54 paul Exp $ * * CAPI 2.0 convert capi message to capi message struct * @@ -7,6 +7,9 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.c,v $ + * Revision 1.10 1999/08/31 11:19:54 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.9 1999/07/09 15:05:46 keil * compat.h is now isdn_compat.h * @@ -70,7 +73,6 @@ #include <asm/segment.h> #include <linux/config.h> -#include <linux/isdn_compat.h> #include "capiutil.h" /* from CAPI2.0 DDK AVM Berlin GmbH */ @@ -97,7 +99,7 @@ char *capi_info2str(__u16 reason) case 0x1001: return "Too many applications"; case 0x1002: - return "Logical block size to small, must be at least 128 Bytes"; + return "Logical block size too small, must be at least 128 Bytes"; case 0x1003: return "Buffer exceeds 64 kByte"; case 0x1004: diff --git a/drivers/isdn/avmb1/capiutil.h b/drivers/isdn/avmb1/capiutil.h index 38209212d..3825ac308 100644 --- a/drivers/isdn/avmb1/capiutil.h +++ b/drivers/isdn/avmb1/capiutil.h @@ -1,5 +1,5 @@ /* - * $Id: capiutil.h,v 1.2 1997/05/18 09:24:19 calle Exp $ + * $Id: capiutil.h,v 1.4 1999/09/15 08:16:03 calle Exp $ * * CAPI 2.0 defines & types * @@ -7,6 +7,14 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.h,v $ + * Revision 1.4 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.3 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.2 1997/05/18 09:24:19 calle * added verbose disconnect reason reporting to avmb1. * some fixes in capi20 interface. @@ -45,12 +53,10 @@ ((__u8 *)m)[3] = ((__u16)(applid) >> 8) & 0xff; \ } while (0) -#define CAPIMSG_SETDATA(m, data) \ +#define CAPIMSG_SETLEN(m, len) \ do { \ - ((__u8 *)m)[12] = (__u32)(data) & 0xff; \ - ((__u8 *)m)[13] = ((__u32)(data) >> 8) & 0xff; \ - ((__u8 *)m)[14] = ((__u32)(data) >> 16) & 0xff; \ - ((__u8 *)m)[15] = ((__u32)(data) >> 24) & 0xff; \ + ((__u8 *)m)[0] = (__u16)(len) & 0xff; \ + ((__u8 *)m)[1] = ((__u16)(len) >> 8) & 0xff; \ } while (0) /*----- basic-type definitions -----*/ diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c index fc58f1241..75d3f01c2 100644 --- a/drivers/isdn/avmb1/kcapi.c +++ b/drivers/isdn/avmb1/kcapi.c @@ -1,11 +1,25 @@ /* - * $Id: kcapi.c,v 1.6 1999/07/20 06:41:49 calle Exp $ + * $Id: kcapi.c,v 1.10 1999/10/26 15:30:32 calle Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.10 1999/10/26 15:30:32 calle + * Generate error message if user want to add card, but driver module is + * not loaded. + * + * Revision 1.9 1999/10/11 22:04:12 keil + * COMPAT_NEED_UACCESS (no include in isdn_compat.h) + * + * Revision 1.8 1999/09/10 17:24:18 calle + * Changes for proposed standard for CAPI2.0: + * - AK148 "Linux Exention" + * + * Revision 1.7 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.6 1999/07/20 06:41:49 calle * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even * compile, if not selected as modules. @@ -57,7 +71,7 @@ #include <linux/tqueue.h> #include <linux/capi.h> #include <linux/kernelcapi.h> -#include <linux/isdn_compat.h> +#include <asm/uaccess.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" @@ -65,7 +79,7 @@ #include <linux/b1lli.h> #endif -static char *revision = "$Revision: 1.6 $"; +static char *revision = "$Revision: 1.10 $"; /* ------------------------------------------------------------- */ @@ -119,7 +133,7 @@ struct capi_appl { /* ------------------------------------------------------------- */ static struct capi_version driver_version = {2, 0, 1, 1<<4}; -static char driver_serial[CAPI_SERIAL_LEN] = "4711"; +static char driver_serial[CAPI_SERIAL_LEN] = "0004711"; static char capi_manufakturer[64] = "AVM Berlin"; #define APPL(a) (&applications[(a)-1]) @@ -719,7 +733,7 @@ error: /* -------- Notifier ------------------------------------------ */ -static void notify_up(__u16 contr) +static void notify_up(__u32 contr) { struct capi_interface_user *p; @@ -730,7 +744,7 @@ static void notify_up(__u16 contr) } } -static void notify_down(__u16 contr) +static void notify_down(__u32 contr) { struct capi_interface_user *p; printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr); @@ -742,7 +756,7 @@ static void notify_down(__u16 contr) static void notify_handler(void *dummy) { - __u16 contr; + __u32 contr; for (contr=1; VALID_CARD(contr); contr++) if (test_and_clear_bit(contr, ¬ify_up_set)) @@ -984,14 +998,14 @@ void detach_capi_driver(struct capi_driver *driver) /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ -static int capi_installed(void) +static __u16 capi_isinstalled(void) { int i; for (i = 0; i < CAPI_MAXCONTR; i++) { if (cards[i].cardstate == CARD_RUNNING) - return 1; + return CAPI_NOERROR; } - return 0; + return CAPI_REGNOTINSTALLED; } static __u16 capi_register(capi_register_params * rparam, __u16 * applidp) @@ -1053,7 +1067,7 @@ static __u16 capi_release(__u16 applid) static __u16 capi_put_message(__u16 applid, struct sk_buff *skb) { struct capi_ncci *np; - int contr; + __u32 contr; int showctl = 0; __u8 cmd, subcmd; @@ -1131,53 +1145,53 @@ static __u16 capi_set_signal(__u16 applid, return CAPI_NOERROR; } -static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) +static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) { if (contr == 0) { strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN); return CAPI_NOERROR; } -static __u16 capi_get_version(__u16 contr, struct capi_version *verp) +static __u16 capi_get_version(__u32 contr, struct capi_version *verp) { if (contr == 0) { *verp = driver_version; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version)); return CAPI_NOERROR; } -static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN]) +static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN]) { if (contr == 0) { strncpy(serial, driver_serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN); return CAPI_NOERROR; } -static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp) +static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp) { if (contr == 0) { profp->ncontroller = ncards; return CAPI_NOERROR; } if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return 0x2002; + return CAPI_REGNOTINSTALLED; memcpy((void *) profp, &CARD(contr)->profile, sizeof(struct capi_profile)); @@ -1219,7 +1233,12 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) case AVM_CARDTYPE_T1: driver = t1isa_driver; break; default: driver = 0; } - if (!driver || !driver->add_card) { + if (!driver) { + printk(KERN_ERR "kcapi: driver not loaded.\n"); + return -EIO; + } + if (!driver->add_card) { + printk(KERN_ERR "kcapi: driver has no add card function.\n"); return -EIO; } @@ -1277,7 +1296,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate != CARD_RUNNING) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1302,7 +1321,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate > CARD_DETECTED) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1355,7 +1374,7 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) while (card->cardstate != CARD_FREE) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/10); /* 0.1 sec */ if (signal_pending(current)) @@ -1404,7 +1423,7 @@ static int capi_manufacturer(unsigned int cmd, void *data) struct capi_interface avmb1_interface = { - capi_installed, + capi_isinstalled, capi_register, capi_release, capi_put_message, @@ -1479,6 +1498,12 @@ extern int t1isa_init(void); #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA extern int b1pcmcia_init(void); #endif +#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI +extern int t1pci_init(void); +#endif +#ifdef CONFIG_ISDN_DRV_AVMB1_C4 +extern int c4_init(void); +#endif #endif /* @@ -1528,6 +1553,12 @@ int kcapi_init(void) #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA (void)b1pcmcia_init(); #endif +#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI + (void)t1pci_init(); +#endif +#ifdef CONFIG_ISDN_DRV_AVMB1_C4 + (void)c4_init(); +#endif #endif return 0; } diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c index 3546e1061..22a07f2ad 100644 --- a/drivers/isdn/avmb1/t1isa.c +++ b/drivers/isdn/avmb1/t1isa.c @@ -1,11 +1,26 @@ /* - * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $ + * $Id: t1isa.c,v 1.8 1999/11/05 16:38:01 calle Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1isa.c,v $ + * Revision 1.8 1999/11/05 16:38:01 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.7 1999/09/15 08:16:03 calle + * Implementation of 64Bit extention complete. + * + * Revision 1.6 1999/09/07 09:02:53 calle + * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and + * DATA_B3_IND is always directly after the CAPI message. The "Data" member + * ist never used inside the kernel. + * * Revision 1.5 1999/08/22 20:26:28 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -53,13 +68,12 @@ #include <linux/ioport.h> #include <linux/capi.h> #include <asm/io.h> -#include <linux/isdn_compat.h> #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.5 $"; +static char *revision = "$Revision: 1.8 $"; /* ------------------------------------------------------------- */ @@ -162,7 +176,8 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) static void t1_handle_interrupt(avmcard * card) { - struct capi_ctr *ctrl = card->ctrl; + avmctrl_info *cinfo = &card->ctrlinfo[0]; + struct capi_ctr *ctrl = cinfo->capi_ctrl; unsigned char b1cmd; struct sk_buff *skb; @@ -184,12 +199,17 @@ static void t1_handle_interrupt(avmcard * card) MsgLen = t1_get_slice(card->port, card->msgbuf); DataB3Len = t1_get_slice(card->port, card->databuf); + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "t1isa: incoming packet dropped\n"); + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - CAPIMSG_SETDATA(skb->data, skb->data + MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); } break; @@ -199,7 +219,8 @@ static void t1_handle_interrupt(avmcard * card) ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "t1isa: incoming packet dropped\n"); + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); ctrl->handle_capimsg(ctrl, ApplId, skb); @@ -237,12 +258,12 @@ static void t1_handle_interrupt(avmcard * card) case RECEIVE_INIT: - card->versionlen = t1_get_slice(card->port, card->versionbuf); - b1_parse_version(card); + cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); + b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, - card->version[VER_CARDTYPE], - card->version[VER_DRIVER]); + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); ctrl->ready(ctrl); break; @@ -288,11 +309,12 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) card = (avmcard *) devptr; if (!card) { - printk(KERN_WARNING "t1_interrupt: wrong device\n"); + printk(KERN_WARNING "t1isa: interrupt: wrong device\n"); return; } if (card->interrupt) { - printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name); + printk(KERN_ERR "%s: reentering interrupt hander.\n", + card->name); return; } @@ -306,7 +328,8 @@ static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int retval; @@ -314,7 +337,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) t1_disable_irq(port); b1_reset(port); - if ((retval = b1_load_t4file(port, &data->firmware))) { + if ((retval = b1_load_t4file(card, &data->firmware))) { b1_reset(port); printk(KERN_ERR "%s: failed to load t4file!!\n", card->name); @@ -322,7 +345,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(port, &data->configuration))) { + if ((retval = b1_load_config(card, &data->configuration))) { b1_reset(port); printk(KERN_ERR "%s: failed to load config!!\n", card->name); @@ -330,7 +353,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) } } - if (!b1_loaded(port)) { + if (!b1_loaded(card)) { printk(KERN_ERR "%s: failed to load t4file.\n", card->name); return -EIO; } @@ -349,20 +372,22 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) void t1isa_reset_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; t1_disable_irq(port); b1_reset(port); b1_reset(port); - memset(card->version, 0, sizeof(card->version)); + memset(cinfo->version, 0, sizeof(cinfo->version)); ctrl->reseted(ctrl); } static void t1isa_remove_ctr(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; t1_disable_irq(port); @@ -373,6 +398,7 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl) di->detach_ctr(ctrl); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); MOD_DEC_USE_COUNT; @@ -383,16 +409,26 @@ static void t1isa_remove_ctr(struct capi_ctr *ctrl) static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) { struct capi_ctr *ctrl; + avmctrl_info *cinfo; avmcard *card; int retval; card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); if (!card) { - printk(KERN_WARNING "t1isa: no memory.\n"); + printk(KERN_WARNING "%s: no memory.\n", driver->name); return -ENOMEM; } memset(card, 0, sizeof(avmcard)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; sprintf(card->name, "t1isa-%x", p->port); card->port = p->port; card->irq = p->irq; @@ -400,33 +436,42 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) card->cardnr = p->cardnr; if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { - printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port); + printk(KERN_WARNING "%s: illegal port 0x%x.\n", + driver->name, card->port); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } if (check_region(card->port, AVMB1_PORTLEN)) { printk(KERN_WARNING - "t1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } if (hema_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq); + printk(KERN_WARNING "%s: irq %d not valid.\n", + driver->name, card->irq); + kfree(card->ctrlinfo); kfree(card); return -EINVAL; } for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) { - if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) { - printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr); + avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card; + if (cardp->cardnr == card->cardnr) { + printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n", + driver->name, card->cardnr, cardp->port); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } } if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { - printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n", - card->port, retval); + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + kfree(card->ctrlinfo); kfree(card); return -EIO; } @@ -437,17 +482,21 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); if (retval) { - printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } - card->ctrl = di->attach_ctr(driver, card->name, card); - if (!card->ctrl) { - printk(KERN_ERR "t1isa: attach controller failed.\n"); + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", + driver->name); free_irq(card->irq, card); release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); kfree(card); return -EBUSY; } @@ -458,7 +507,8 @@ static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) { - avmcard *card = (avmcard *)(ctrl->driverdata); + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; __u16 len = CAPIMSG_LEN(skb->data); @@ -483,15 +533,18 @@ static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) static char *t1isa_procinfo(struct capi_ctr *ctrl) { - avmcard *card = (avmcard *)(ctrl->driverdata); - if (!card) + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) return ""; - sprintf(card->infobuf, "%s %s 0x%x %d %d", - card->cardname[0] ? card->cardname : "-", - card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-", - card->port, card->irq, card->cardnr + sprintf(cinfo->infobuf, "%s %s 0x%x %d %d", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0, + cinfo->card ? cinfo->card->cardnr : 0 ); - return card->infobuf; + return cinfo->infobuf; } diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c new file mode 100644 index 000000000..ad73e71cd --- /dev/null +++ b/drivers/isdn/avmb1/t1pci.c @@ -0,0 +1,1164 @@ +/* + * $Id: t1pci.c,v 1.2 1999/11/05 16:38:02 calle Exp $ + * + * Module for AVM T1 PCI-card. + * + * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) + * + * $Log: t1pci.c,v $ + * Revision 1.2 1999/11/05 16:38:02 calle + * Cleanups before kernel 2.4: + * - Changed all messages to use card->name or driver->name instead of + * constant string. + * - Moved some data from struct avmcard into new struct avmctrl_info. + * Changed all lowlevel capi driver to match the new structur. + * + * Revision 1.1 1999/10/26 15:31:42 calle + * Added driver for T1-PCI card. + * + * + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/skbuff.h> +#include <linux/delay.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/pci.h> +#include <linux/capi.h> +#include <asm/io.h> +#include "compat.h" +#include "capicmd.h" +#include "capiutil.h" +#include "capilli.h" +#include "avmcard.h" + +static char *revision = "$Revision: 1.2 $"; + +#undef CONFIG_T1PCI_DEBUG +#undef CONFIG_T1PCI_POLLDEBUG + +/* ------------------------------------------------------------- */ + +#ifndef PCI_VENDOR_ID_AVM +#define PCI_VENDOR_ID_AVM 0x1244 +#endif + +#ifndef PCI_DEVICE_ID_AVM_T1 +#define PCI_DEVICE_ID_AVM_T1 0x1200 +#endif + +/* ------------------------------------------------------------- */ + +int suppress_pollack = 0; + +MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>"); + +MODULE_PARM(suppress_pollack, "0-1i"); + + +/* ------------------------------------------------------------- */ + +static struct capi_driver_interface *di; + +/* ------------------------------------------------------------- */ + +static void t1pci_dispatch_tx(avmcard *card); + +/* ------------------------------------------------------------- */ + +/* S5933 */ + +#define AMCC_RXPTR 0x24 +#define AMCC_RXLEN 0x28 +#define AMCC_TXPTR 0x2c +#define AMCC_TXLEN 0x30 + +#define AMCC_INTCSR 0x38 +# define EN_READ_TC_INT 0x00008000L +# define EN_WRITE_TC_INT 0x00004000L +# define EN_TX_TC_INT EN_READ_TC_INT +# define EN_RX_TC_INT EN_WRITE_TC_INT +# define AVM_FLAG 0x30000000L + +# define ANY_S5933_INT 0x00800000L +# define READ_TC_INT 0x00080000L +# define WRITE_TC_INT 0x00040000L +# define TX_TC_INT READ_TC_INT +# define RX_TC_INT WRITE_TC_INT +# define MASTER_ABORT_INT 0x00100000L +# define TARGET_ABORT_INT 0x00200000L +# define BUS_MASTER_INT 0x00200000L +# define ALL_INT 0x000C0000L + +#define AMCC_MCSR 0x3c +# define A2P_HI_PRIORITY 0x00000100L +# define EN_A2P_TRANSFERS 0x00000400L +# define P2A_HI_PRIORITY 0x00001000L +# define EN_P2A_TRANSFERS 0x00004000L +# define RESET_A2P_FLAGS 0x04000000L +# define RESET_P2A_FLAGS 0x02000000L + +/* ------------------------------------------------------------- */ + +#define t1outmeml(addr, value) writel(value, addr) +#define t1inmeml(addr) readl(addr) +#define t1outmemw(addr, value) writew(value, addr) +#define t1inmemw(addr) readw(addr) +#define t1outmemb(addr, value) writeb(value, addr) +#define t1inmemb(addr) readb(addr) + +/* ------------------------------------------------------------- */ + +static inline int t1pci_tx_empty(unsigned int port) +{ + return inb(port + 0x03) & 0x1; +} + +static inline int t1pci_rx_full(unsigned int port) +{ + return inb(port + 0x02) & 0x1; +} + +static int t1pci_tolink(avmcard *card, void *buf, unsigned int len) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + unsigned char *s = (unsigned char *)buf; + while (len--) { + while ( !t1pci_tx_empty(card->port) + && time_before(jiffies, stop)); + if (!t1pci_tx_empty(card->port)) + return -1; + t1outp(card->port, 0x01, *s++); + } + return 0; +} + +static int t1pci_fromlink(avmcard *card, void *buf, unsigned int len) +{ + unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ + unsigned char *s = (unsigned char *)buf; + while (len--) { + while ( !t1pci_rx_full(card->port) + && time_before(jiffies, stop)); + if (!t1pci_rx_full(card->port)) + return -1; + *s++ = t1inp(card->port, 0x00); + } + return 0; +} + +static int WriteReg(avmcard *card, __u32 reg, __u8 val) +{ + __u8 cmd = 0x00; + if ( t1pci_tolink(card, &cmd, 1) == 0 + && t1pci_tolink(card, ®, 4) == 0) { + __u32 tmp = val; + return t1pci_tolink(card, &tmp, 4); + } + return -1; +} + +static __u8 ReadReg(avmcard *card, __u32 reg) +{ + __u8 cmd = 0x01; + if ( t1pci_tolink(card, &cmd, 1) == 0 + && t1pci_tolink(card, ®, 4) == 0) { + __u32 tmp; + if (t1pci_fromlink(card, &tmp, 4) == 0) + return (__u8)tmp; + } + return 0xff; +} + +/* ------------------------------------------------------------- */ + +static inline void _put_byte(void **pp, __u8 val) +{ + __u8 *s = *pp; + *s++ = val; + *pp = s; +} + +static inline void _put_word(void **pp, __u32 val) +{ + __u8 *s = *pp; + *s++ = val & 0xff; + *s++ = (val >> 8) & 0xff; + *s++ = (val >> 16) & 0xff; + *s++ = (val >> 24) & 0xff; + *pp = s; +} + +static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) +{ + unsigned i = len; + _put_word(pp, i); + while (i-- > 0) + _put_byte(pp, *dp++); +} + +static inline __u8 _get_byte(void **pp) +{ + __u8 *s = *pp; + __u8 val; + val = *s++; + *pp = s; + return val; +} + +static inline __u32 _get_word(void **pp) +{ + __u8 *s = *pp; + __u32 val; + val = *s++; + val |= (*s++ << 8); + val |= (*s++ << 16); + val |= (*s++ << 24); + *pp = s; + return val; +} + +static inline __u32 _get_slice(void **pp, unsigned char *dp) +{ + unsigned int len, i; + + len = i = _get_word(pp); + while (i-- > 0) *dp++ = _get_byte(pp); + return len; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_reset(avmcard *card) +{ + unsigned long flags; + + save_flags(flags); + cli(); + card->csr = 0x0; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + t1outmeml(card->mbase+AMCC_MCSR, 0); + t1outmeml(card->mbase+AMCC_RXLEN, 0); + t1outmeml(card->mbase+AMCC_TXLEN, 0); + + t1outp(card->port, T1_RESETLINK, 0x00); + t1outp(card->port, 0x07, 0x00); + + restore_flags(flags); + + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(42 * 1000); + +} + +/* ------------------------------------------------------------- */ + +static int t1pci_detect(avmcard *card) +{ + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ + udelay(10 * 1000); + t1outmeml(card->mbase+AMCC_MCSR, 0); + udelay(42 * 1000); + + t1outmeml(card->mbase+AMCC_RXLEN, 0); + t1outmeml(card->mbase+AMCC_TXLEN, 0); + card->csr = 0x0; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + + if (t1inmeml(card->mbase+AMCC_MCSR) != 0x000000E6) + return 1; + + t1outmeml(card->mbase+AMCC_RXPTR, 0xffffffff); + t1outmeml(card->mbase+AMCC_TXPTR, 0xffffffff); + if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc + || t1inmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc) + return 2; + + t1outmeml(card->mbase+AMCC_RXPTR, 0x0); + t1outmeml(card->mbase+AMCC_TXPTR, 0x0); + if ( t1inmeml(card->mbase+AMCC_RXPTR) != 0x0 + || t1inmeml(card->mbase+AMCC_TXPTR) != 0x0) + return 3; + + t1outp(card->port, T1_RESETLINK, 0x00); + t1outp(card->port, 0x07, 0x00); + + t1outp(card->port, 0x02, 0x02); + t1outp(card->port, 0x03, 0x02); + + if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02 + || t1inp(card->port, 0x3) != 0x03) + return 4; + + t1outp(card->port, 0x02, 0x00); + t1outp(card->port, 0x03, 0x00); + + if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00 + || t1inp(card->port, 0x3) != 0x01) + return 5; + + /* Transputer test */ + + if ( WriteReg(card, 0x80001000, 0x11) != 0 + || WriteReg(card, 0x80101000, 0x22) != 0 + || WriteReg(card, 0x80201000, 0x33) != 0 + || WriteReg(card, 0x80301000, 0x44) != 0) + return 6; + + if ( ReadReg(card, 0x80001000) != 0x11 + || ReadReg(card, 0x80101000) != 0x22 + || ReadReg(card, 0x80201000) != 0x33 + || ReadReg(card, 0x80301000) != 0x44) + return 7; + + if ( WriteReg(card, 0x80001000, 0x55) != 0 + || WriteReg(card, 0x80101000, 0x66) != 0 + || WriteReg(card, 0x80201000, 0x77) != 0 + || WriteReg(card, 0x80301000, 0x88) != 0) + return 8; + + if ( ReadReg(card, 0x80001000) != 0x55 + || ReadReg(card, 0x80101000) != 0x66 + || ReadReg(card, 0x80201000) != 0x77 + || ReadReg(card, 0x80301000) != 0x88) + return 9; + + return 0; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_dispatch_tx(avmcard *card) +{ + avmcard_dmainfo *dma = card->dma; + unsigned long flags; + struct sk_buff *skb; + __u8 cmd, subcmd; + __u16 len; + __u32 txlen; + int inint; + void *p; + + save_flags(flags); + cli(); + + inint = card->interrupt; + + if (card->csr & EN_TX_TC_INT) { /* tx busy */ + restore_flags(flags); + return; + } + + skb = skb_dequeue(&dma->send_queue); + if (!skb) { +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): underrun\n", inint); +#endif + restore_flags(flags); + return; + } + + len = CAPIMSG_LEN(skb->data); + + if (len) { + cmd = CAPIMSG_COMMAND(skb->data); + subcmd = CAPIMSG_SUBCOMMAND(skb->data); + + p = dma->sendbuf; + + if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { + __u16 dlen = CAPIMSG_DATALEN(skb->data); + _put_byte(&p, SEND_DATA_B3_REQ); + _put_slice(&p, skb->data, len); + _put_slice(&p, skb->data + len, dlen); + } else { + _put_byte(&p, SEND_MESSAGE); + _put_slice(&p, skb->data, len); + } + txlen = (__u8 *)p - (__u8 *)dma->sendbuf; +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): put msg len=%d\n", + inint, txlen); +#endif + } else { + txlen = skb->len-2; +#ifdef CONFIG_T1PCI_POLLDEBUG + if (skb->data[2] == SEND_POLLACK) + printk(KERN_INFO "%s: ack to t1\n", card->name); +#endif +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n", + inint, skb->data[2], txlen); +#endif + memcpy(dma->sendbuf, skb->data+2, skb->len-2); + } + txlen = (txlen + 3) & ~3; + + t1outmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf)); + t1outmeml(card->mbase+AMCC_TXLEN, txlen); + + card->csr |= EN_TX_TC_INT; + + if (!inint) + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + + restore_flags(flags); + dev_kfree_skb(skb); +} + +/* ------------------------------------------------------------- */ + +static void queue_pollack(avmcard *card) +{ + struct sk_buff *skb; + void *p; + + skb = alloc_skb(3, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost poll ack\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_POLLACK); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + +static void t1pci_handle_rx(avmcard *card) +{ + avmctrl_info *cinfo = &card->ctrlinfo[0]; + avmcard_dmainfo *dma = card->dma; + struct capi_ctr *ctrl = cinfo->capi_ctrl; + struct sk_buff *skb; + void *p = dma->recvbuf+4; + __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; + __u8 b1cmd = _get_byte(&p); + +#ifdef CONFIG_T1PCI_DEBUG + printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen); +#endif + + switch (b1cmd) { + case RECEIVE_DATA_B3_IND: + + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + DataB3Len = _get_slice(&p, card->databuf); + + if (MsgLen < 30) { /* not CAPI 64Bit */ + memset(card->msgbuf+MsgLen, 0, 30-MsgLen); + MsgLen = 30; + CAPIMSG_SETLEN(card->msgbuf, 30); + } + if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_MESSAGE: + + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { + printk(KERN_ERR "%s: incoming packet dropped\n", + card->name); + } else { + memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); + ctrl->handle_capimsg(ctrl, ApplId, skb); + } + break; + + case RECEIVE_NEW_NCCI: + + ApplId = _get_word(&p); + NCCI = _get_word(&p); + WindowSize = _get_word(&p); + + ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); + + break; + + case RECEIVE_FREE_NCCI: + + ApplId = _get_word(&p); + NCCI = _get_word(&p); + + if (NCCI != 0xffffffff) + ctrl->free_ncci(ctrl, ApplId, NCCI); + else ctrl->appl_released(ctrl, ApplId); + break; + + case RECEIVE_START: +#ifdef CONFIG_T1PCI_POLLDEBUG + printk(KERN_INFO "%s: poll from t1\n", card->name); +#endif + if (!suppress_pollack) + queue_pollack(card); + ctrl->resume_output(ctrl); + break; + + case RECEIVE_STOP: + ctrl->suspend_output(ctrl); + break; + + case RECEIVE_INIT: + + cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); + b1_parse_version(cinfo); + printk(KERN_INFO "%s: %s-card (%s) now active\n", + card->name, + cinfo->version[VER_CARDTYPE], + cinfo->version[VER_DRIVER]); + ctrl->ready(ctrl); + break; + + case RECEIVE_TASK_READY: + ApplId = (unsigned) _get_word(&p); + MsgLen = _get_slice(&p, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: task %d \"%s\" ready.\n", + card->name, ApplId, card->msgbuf); + break; + + case RECEIVE_DEBUGMSG: + MsgLen = _get_slice(&p, card->msgbuf); + card->msgbuf[MsgLen--] = 0; + while ( MsgLen >= 0 + && ( card->msgbuf[MsgLen] == '\n' + || card->msgbuf[MsgLen] == '\r')) + card->msgbuf[MsgLen--] = 0; + printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); + break; + + default: + printk(KERN_ERR "%s: t1pci_interrupt: 0x%x ???\n", + card->name, b1cmd); + return; + } +} + +/* ------------------------------------------------------------- */ + +static void t1pci_handle_interrupt(avmcard *card) +{ + __u32 status = t1inmeml(card->mbase+AMCC_INTCSR); + __u32 newcsr; + + if ((status & ANY_S5933_INT) == 0) + return; + + newcsr = card->csr | (status & ALL_INT); + if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; + if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; + t1outmeml(card->mbase+AMCC_INTCSR, newcsr); + + if ((status & RX_TC_INT) != 0) { + __u8 *recvbuf = card->dma->recvbuf; + __u32 rxlen; + if (card->dma->recvlen == 0) { + card->dma->recvlen = *((__u32 *)recvbuf); + rxlen = (card->dma->recvlen + 3) & ~3; + t1outmeml(card->mbase+AMCC_RXPTR, + virt_to_phys(recvbuf+4)); + t1outmeml(card->mbase+AMCC_RXLEN, rxlen); + } else { + t1pci_handle_rx(card); + card->dma->recvlen = 0; + t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf)); + t1outmeml(card->mbase+AMCC_RXLEN, 4); + } + } + + if ((status & TX_TC_INT) != 0) { + card->csr &= ~EN_TX_TC_INT; + t1pci_dispatch_tx(card); + } else if (card->csr & EN_TX_TC_INT) { + if (t1inmeml(card->mbase+AMCC_TXLEN) == 0) { + card->csr &= ~EN_TX_TC_INT; + t1pci_dispatch_tx(card); + } + } + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); +} + +static void t1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) +{ + avmcard *card; + + card = (avmcard *) devptr; + + if (!card) { + printk(KERN_WARNING "t1pci: interrupt: wrong device\n"); + return; + } + if (card->interrupt) { + printk(KERN_ERR "%s: reentering interrupt hander\n", card->name); + return; + } + + card->interrupt = 1; + + t1pci_handle_interrupt(card); + + card->interrupt = 0; +} + +/* ------------------------------------------------------------- */ + +static int t1pci_loaded(avmcard *card) +{ + unsigned long stop; + unsigned char ans; + unsigned long tout = 2; + unsigned int base = card->port; + + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_tx_empty(base)) + break; + } + if (!b1_tx_empty(base)) { + printk(KERN_ERR "%s: t1pci_loaded: tx err, corrupted t4 file ?\n", + card->name); + return 0; + } + b1_put_byte(base, SEND_POLLACK); + for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { + if (b1_rx_full(base)) { + if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) { + return 1; + } + printk(KERN_ERR "%s: t1pci_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans); + return 0; + } + } + printk(KERN_ERR "%s: t1pci_loaded: firmware not running\n", card->name); + return 0; +} + +/* ------------------------------------------------------------- */ + +static void t1pci_send_init(avmcard *card) +{ + struct sk_buff *skb; + void *p; + + skb = alloc_skb(15, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost register appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_INIT); + _put_word(&p, AVM_NAPPS); + _put_word(&p, AVM_NCCI_PER_CHANNEL*30); + _put_word(&p, card->cardnr - 1); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +static int t1pci_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + unsigned long flags; + int retval; + + t1pci_reset(card); + + if ((retval = b1_load_t4file(card, &data->firmware))) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load t4file!!\n", + card->name); + return retval; + } + + if (data->configuration.len > 0 && data->configuration.data) { + if ((retval = b1_load_config(card, &data->configuration))) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load config!!\n", + card->name); + return retval; + } + } + + if (!t1pci_loaded(card)) { + t1pci_reset(card); + printk(KERN_ERR "%s: failed to load t4file.\n", card->name); + return -EIO; + } + + save_flags(flags); + cli(); + + card->csr = AVM_FLAG; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + t1outmeml(card->mbase+AMCC_MCSR, + EN_A2P_TRANSFERS|EN_P2A_TRANSFERS + |A2P_HI_PRIORITY|P2A_HI_PRIORITY + |RESET_A2P_FLAGS|RESET_P2A_FLAGS); + t1outp(card->port, 0x07, 0x30); + t1outp(card->port, 0x10, 0xF0); + + card->dma->recvlen = 0; + t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf)); + t1outmeml(card->mbase+AMCC_RXLEN, 4); + card->csr |= EN_RX_TC_INT; + t1outmeml(card->mbase+AMCC_INTCSR, card->csr); + restore_flags(flags); + + t1pci_send_init(card); + + return 0; +} + +void t1pci_reset_ctr(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + + t1pci_reset(card); + + memset(cinfo->version, 0, sizeof(cinfo->version)); + ctrl->reseted(ctrl); +} + +static void t1pci_remove_ctr(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + + t1pci_reset(card); + + di->detach_ctr(ctrl); + free_irq(card->irq, card); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + release_region(card->port, AVMB1_PORTLEN); + ctrl->driverdata = 0; + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + + MOD_DEC_USE_COUNT; +} + +/* ------------------------------------------------------------- */ + + +void t1pci_register_appl(struct capi_ctr *ctrl, + __u16 appl, + capi_register_params *rp) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + struct sk_buff *skb; + int want = rp->level3cnt; + int nconn; + void *p; + + if (want > 0) nconn = want; + else nconn = ctrl->profile.nbchannel * -want; + if (nconn == 0) nconn = ctrl->profile.nbchannel; + + skb = alloc_skb(23, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost register appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_REGISTER); + _put_word(&p, appl); + _put_word(&p, 1024 * (nconn+1)); + _put_word(&p, nconn); + _put_word(&p, rp->datablkcnt); + _put_word(&p, rp->datablklen); + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); + + ctrl->appl_registered(ctrl, appl); +} + +/* ------------------------------------------------------------- */ + +void t1pci_release_appl(struct capi_ctr *ctrl, __u16 appl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + struct sk_buff *skb; + void *p; + + skb = alloc_skb(7, GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "%s: no memory, lost release appl.\n", + card->name); + return; + } + p = skb->data; + _put_byte(&p, 0); + _put_byte(&p, 0); + _put_byte(&p, SEND_RELEASE); + _put_word(&p, appl); + + skb_put(skb, (__u8 *)p - (__u8 *)skb->data); + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + + +static void t1pci_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + skb_queue_tail(&card->dma->send_queue, skb); + t1pci_dispatch_tx(card); +} + +/* ------------------------------------------------------------- */ + +static char *t1pci_procinfo(struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + + if (!cinfo) + return ""; + sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", + cinfo->cardname[0] ? cinfo->cardname : "-", + cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", + cinfo->card ? cinfo->card->port : 0x0, + cinfo->card ? cinfo->card->irq : 0, + cinfo->card ? cinfo->card->membase : 0 + ); + return cinfo->infobuf; +} + +static int t1pci_read_proc(char *page, char **start, off_t off, + int count, int *eof, struct capi_ctr *ctrl) +{ + avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); + avmcard *card = cinfo->card; + unsigned long flags; + __u8 flag; + int len = 0; + char *s; + __u32 txaddr, txlen, rxaddr, rxlen, csr; + + len += sprintf(page+len, "%-16s %s\n", "name", card->name); + len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); + len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); + len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); + switch (card->cardtype) { + case avm_b1isa: s = "B1 ISA"; break; + case avm_b1pci: s = "B1 PCI"; break; + case avm_b1pcmcia: s = "B1 PCMCIA"; break; + case avm_m1: s = "M1"; break; + case avm_m2: s = "M2"; break; + case avm_t1isa: s = "T1 ISA (HEMA)"; break; + case avm_t1pci: s = "T1 PCI"; break; + case avm_c4: s = "C4"; break; + default: s = "???"; break; + } + len += sprintf(page+len, "%-16s %s\n", "type", s); + if ((s = cinfo->version[VER_DRIVER]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); + if ((s = cinfo->version[VER_CARDTYPE]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); + if ((s = cinfo->version[VER_SERIAL]) != 0) + len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); + + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[3]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", + "protocol", + (flag & 0x01) ? " DSS1" : "", + (flag & 0x02) ? " CT1" : "", + (flag & 0x04) ? " VN3" : "", + (flag & 0x08) ? " NI1" : "", + (flag & 0x10) ? " AUSTEL" : "", + (flag & 0x20) ? " ESS" : "", + (flag & 0x40) ? " 1TR6" : "" + ); + } + if (card->cardtype != avm_m1) { + flag = ((__u8 *)(ctrl->profile.manu))[5]; + if (flag) + len += sprintf(page+len, "%-16s%s%s%s%s\n", + "linetype", + (flag & 0x01) ? " point to point" : "", + (flag & 0x02) ? " point to multipoint" : "", + (flag & 0x08) ? " leased line without D-channel" : "", + (flag & 0x04) ? " leased line with D-channel" : "" + ); + } + len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + + save_flags(flags); + cli(); + + txaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x2c)); + txaddr -= (__u32)card->dma->sendbuf; + txlen = t1inmeml(card->mbase+0x30); + + rxaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x24)); + rxaddr -= (__u32)card->dma->recvbuf; + rxlen = t1inmeml(card->mbase+0x28); + + csr = t1inmeml(card->mbase+AMCC_INTCSR); + + restore_flags(flags); + + len += sprintf(page+len, "%-16s 0x%lx\n", + "csr (cached)", (unsigned long)card->csr); + len += sprintf(page+len, "%-16s 0x%lx\n", + "csr", (unsigned long)csr); + len += sprintf(page+len, "%-16s %lu\n", + "txoff", (unsigned long)txaddr); + len += sprintf(page+len, "%-16s %lu\n", + "txlen", (unsigned long)txlen); + len += sprintf(page+len, "%-16s %lu\n", + "rxoff", (unsigned long)rxaddr); + len += sprintf(page+len, "%-16s %lu\n", + "rxlen", (unsigned long)rxlen); + + if (off+count >= len) + *eof = 1; + if (len < off) + return 0; + *start = page + off; + return ((count < len-off) ? count : len-off); +} + +/* ------------------------------------------------------------- */ + +static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p) +{ + unsigned long page_offset, base; + avmcard *card; + avmctrl_info *cinfo; + int retval; + + card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); + + if (!card) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + return -ENOMEM; + } + memset(card, 0, sizeof(avmcard)); + card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC); + if (!card->dma) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card); + return -ENOMEM; + } + memset(card->dma, 0, sizeof(avmcard_dmainfo)); + cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); + if (!cinfo) { + printk(KERN_WARNING "%s: no memory.\n", driver->name); + kfree(card->dma); + kfree(card); + return -ENOMEM; + } + memset(cinfo, 0, sizeof(avmctrl_info)); + card->ctrlinfo = cinfo; + cinfo->card = card; + sprintf(card->name, "t1pci-%x", p->port); + card->port = p->port; + card->irq = p->irq; + card->membase = p->membase; + card->cardtype = avm_t1pci; + + if (check_region(card->port, AVMB1_PORTLEN)) { + printk(KERN_WARNING + "%s: ports 0x%03x-0x%03x in use.\n", + driver->name, card->port, card->port + AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + + base = card->membase & PAGE_MASK; + page_offset = card->membase - base; + card->mbase = ioremap_nocache(base, page_offset + 64); + + t1pci_reset(card); + + if ((retval = t1pci_detect(card)) != 0) { + printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", + driver->name, card->port, retval); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EIO; + } + t1pci_reset(card); + + request_region(p->port, AVMB1_PORTLEN, card->name); + + retval = request_irq(card->irq, t1pci_interrupt, SA_SHIRQ, card->name, card); + if (retval) { + printk(KERN_ERR "%s: unable to get IRQ %d.\n", + driver->name, card->irq); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + + cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); + if (!cinfo->capi_ctrl) { + printk(KERN_ERR "%s: attach controller failed.\n", driver->name); + iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); + free_irq(card->irq, card); + release_region(card->port, AVMB1_PORTLEN); + kfree(card->ctrlinfo); + kfree(card->dma); + kfree(card); + return -EBUSY; + } + card->cardnr = cinfo->capi_ctrl->cnr; + + skb_queue_head_init(&card->dma->send_queue); + + MOD_INC_USE_COUNT; + + return 0; +} + +/* ------------------------------------------------------------- */ + +static struct capi_driver t1pci_driver = { + "t1pci", + "0.0", + t1pci_load_firmware, + t1pci_reset_ctr, + t1pci_remove_ctr, + t1pci_register_appl, + t1pci_release_appl, + t1pci_send_message, + + t1pci_procinfo, + t1pci_read_proc, + 0, /* use standard driver_read_proc */ + + 0, /* no add_card function */ +}; + +#ifdef MODULE +#define t1pci_init init_module +void cleanup_module(void); +#endif + +static int ncards = 0; + +int t1pci_init(void) +{ + struct capi_driver *driver = &t1pci_driver; + struct pci_dev *dev = NULL; + char *p; + int retval; + + if ((p = strchr(revision, ':'))) { + strncpy(driver->revision, p + 1, sizeof(driver->revision)); + p = strchr(driver->revision, '$'); + *p = 0; + } + + printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); + + di = attach_capi_driver(driver); + + if (!di) { + printk(KERN_ERR "%s: failed to attach capi_driver\n", + driver->name); + return -EIO; + } + +#ifdef CONFIG_PCI + if (!pci_present()) { + printk(KERN_ERR "%s: no PCI bus present\n", driver->name); + detach_capi_driver(driver); + return -EIO; + } + + while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) { + struct capicardparams param; + + param.port = dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; + param.irq = dev->irq; + param.membase = dev->resource[ 0].start & PCI_BASE_ADDRESS_MEM_MASK; + + printk(KERN_INFO + "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", + driver->name, param.port, param.irq, param.membase); + retval = t1pci_add_card(driver, ¶m); + if (retval != 0) { + printk(KERN_ERR + "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", + driver->name, param.port, param.irq, param.membase); +#ifdef MODULE + cleanup_module(); +#endif + return retval; + } + ncards++; + } + if (ncards) { + printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n", + driver->name, ncards); + return 0; + } + printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name); + return -ESRCH; +#else + printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); + return -EIO; +#endif +} + +#ifdef MODULE +void cleanup_module(void) +{ + detach_capi_driver(&t1pci_driver); +} +#endif diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 035aa3636..58a47bcd8 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -1,5 +1,5 @@ /* - * $Id: divert_procfs.c,v 1.4 1999/08/06 07:42:48 calle Exp $ + * $Id: divert_procfs.c,v 1.5 1999/09/14 20:31:01 werner Exp $ * * Filesystem handling for the diversion supplementary services. * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: divert_procfs.c,v $ + * Revision 1.5 1999/09/14 20:31:01 werner + * + * Removed obsoleted functions for proc fs and synced with new ones. + * * Revision 1.4 1999/08/06 07:42:48 calle * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels. * @@ -38,16 +42,13 @@ #define __NO_VERSION__ #include <linux/module.h> #include <linux/version.h> -#if (LINUX_VERSION_CODE >= 0x020117) #include <linux/poll.h> -#endif #ifdef CONFIG_PROC_FS #include <linux/proc_fs.h> #else #include <linux/fs.h> #endif #include <linux/isdnif.h> -#include <linux/isdn_compat.h> #include "isdn_divert.h" /*********************************/ @@ -56,11 +57,7 @@ ulong if_used = 0; /* number of interface users */ static struct divert_info *divert_info_head = NULL; /* head of queue */ static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */ -#ifdef COMPAT_HAS_NEW_WAITQ static wait_queue_head_t rd_queue; -#else -static struct wait_queue *rd_queue = 0; /* Queue IO */ -#endif /*********************************/ /* put an info buffer into queue */ @@ -101,11 +98,7 @@ void put_info_buffer(char *cp) /**********************************/ /* deflection device read routine */ /**********************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_read(struct inode *inode, struct file *file, char *buf, RWARG count) -#else static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off) -#endif { struct divert_info *inf; int len; @@ -130,11 +123,7 @@ static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff /**********************************/ /* deflection device write routine */ /**********************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_write(struct inode *inode, struct file *file, const char *buf, RWARG count) -#else static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off) -#endif { return(-ENODEV); } /* isdn_divert_write */ @@ -143,17 +132,6 @@ static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t coun /***************************************/ /* select routines for various kernels */ /***************************************/ -#if (LINUX_VERSION_CODE < 0x020117) -static int isdn_divert_select(struct inode *inode, struct file *file, int type, select_table * st) -{ - if (*((struct divert_info **)file->private_data)) - return 1; - else - { if (st) select_wait(&(rd_queue), st); - return 0; - } -} /* isdn_divert_select */ -#else static unsigned int isdn_divert_poll(struct file *file, poll_table * wait) { unsigned int mask = 0; @@ -164,7 +142,6 @@ static unsigned int isdn_divert_poll(struct file *file, poll_table * wait) } return mask; } /* isdn_divert_poll */ -#endif /****************/ /* Open routine */ @@ -188,11 +165,7 @@ static int isdn_divert_open(struct inode *ino, struct file *filep) /*******************/ /* close routine */ /*******************/ -#if (LINUX_VERSION_CODE < 0x020117) -static void isdn_divert_close(struct inode *ino, struct file *filep) -#else static int isdn_divert_close(struct inode *ino, struct file *filep) -#endif { struct divert_info *inf; int flags; @@ -212,10 +185,7 @@ static int isdn_divert_close(struct inode *ino, struct file *filep) kfree(inf); } MOD_DEC_USE_COUNT; -#if (LINUX_VERSION_CODE < 0x020117) -#else return(0); -#endif } /* isdn_divert_close */ /*********/ @@ -301,34 +271,12 @@ static int isdn_divert_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_PROC_FS -#if (LINUX_VERSION_CODE < 0x020117) -static LSTYPE -isdn_divert_lseek(struct inode *inode, struct file *file, LSARG offset, int orig) -#else static loff_t isdn_divert_lseek(struct file *file, loff_t offset, int orig) -#endif { return -ESPIPE; } -#if (LINUX_VERSION_CODE < 0x020117) -static struct file_operations isdn_fops = -{ - isdn_divert_lseek, - isdn_divert_read, - isdn_divert_write, - NULL, /* isdn_readdir */ - isdn_divert_select, /* isdn_select */ - isdn_divert_ioctl, /* isdn_ioctl */ - NULL, /* isdn_mmap */ - isdn_divert_open, - isdn_divert_close, - NULL /* fsync */ -}; - -#else - static struct file_operations isdn_fops = { isdn_divert_lseek, @@ -343,51 +291,33 @@ static struct file_operations isdn_fops = isdn_divert_close, NULL /* fsync */ }; -#endif /* kernel >= 2.1 */ - -/* - * proc directories can do almost nothing.. - */ -struct inode_operations proc_isdn_inode_ops = { - &isdn_fops, /* isdn divert special file-ops */ - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* readpage */ - NULL, /* writepage */ - NULL, /* bmap */ - NULL, /* truncate */ - NULL /* permission */ +struct inode_operations divert_file_inode_operations = { + &isdn_fops, /* default proc file-ops */ + NULL, /* create */ + NULL, /* lookup */ + NULL, /* link */ + NULL, /* unlink */ + NULL, /* symlink */ + NULL, /* mkdir */ + NULL, /* rmdir */ + NULL, /* mknod */ + NULL, /* rename */ + NULL, /* readlink */ + NULL, /* follow_link */ + NULL, /* readpage */ + NULL, /* writepage */ + NULL, /* bmap */ + NULL, /* truncate */ + NULL /* permission */ }; + /****************************/ /* isdn subdir in /proc/net */ /****************************/ -static struct proc_dir_entry isdn_proc_entry = - { 0, 4, "isdn", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, - &proc_dir_inode_operations,NULL,NULL,NULL,NULL,NULL - }; - -static struct proc_dir_entry isdn_divert_entry = -{ 0, 6, "divert",S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_isdn_inode_ops, - NULL - }; - -/*****************************************************************/ -/* variables used for automatic determining existence of proc fs */ -/*****************************************************************/ -static int (*proc_reg_dynamic)(struct proc_dir_entry *, struct proc_dir_entry *) = NULL; -static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL; - +static struct proc_dir_entry *isdn_proc_entry = NULL; +static struct proc_dir_entry *isdn_divert_entry = NULL; #endif CONFIG_PROC_FS /***************************************************************************/ @@ -396,36 +326,19 @@ static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL; int divert_dev_init(void) { int i; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&rd_queue); -#endif #ifdef CONFIG_PROC_FS -#if (LINUX_VERSION_CODE < 0x020117) - (void *) proc_reg_dynamic = get_module_symbol("","proc_register_dynamic"); - (void *) proc_unreg = get_module_symbol("","proc_unregister"); - if (proc_unreg) - { i = proc_reg_dynamic(&proc_net,&isdn_proc_entry); - if (i) return(i); - i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); - if (i) - { proc_unreg(&proc_net,isdn_proc_entry.low_ino); - return(i); - } - } /* proc exists */ -#else - (void *) proc_reg_dynamic = get_module_symbol("","proc_register"); - (void *) proc_unreg = get_module_symbol("","proc_unregister"); - if (proc_unreg) - { i = proc_reg_dynamic(proc_net,&isdn_proc_entry); - if (i) return(i); - i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry); - if (i) - { proc_unreg(proc_net,isdn_proc_entry.low_ino); - return(i); - } - } /* proc exists */ -#endif + isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO ,proc_net); + if (!isdn_proc_entry) + return(-1); + isdn_divert_entry = create_proc_entry("divert",S_IFREG | S_IRUGO,isdn_proc_entry); + if (!isdn_divert_entry) + { + remove_proc_entry("isdn",proc_net); + return(-1); + } + isdn_divert_entry->ops = &divert_file_inode_operations; #endif CONFIG_PROC_FS return(0); @@ -439,16 +352,8 @@ int divert_dev_deinit(void) { int i; #ifdef CONFIG_PROC_FS - if (proc_unreg) - { i = proc_unreg(&isdn_proc_entry,isdn_divert_entry.low_ino); - if (i) return(i); -#if (LINUX_VERSION_CODE < 0x020117) - i = proc_unreg(&proc_net,isdn_proc_entry.low_ino); -#else - i = proc_unreg(proc_net,isdn_proc_entry.low_ino); -#endif - if (i) return(i); - } /* proc exists */ + remove_proc_entry("divert",isdn_proc_entry); + remove_proc_entry("isdn",proc_net); #endif CONFIG_PROC_FS return(0); diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index f10ea18b2..7079232e7 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.c,v 1.4 1999/08/25 20:02:21 werner Exp $ + * $Id: isdn_divert.c,v 1.5 1999/08/31 11:20:04 paul Exp $ * * DSS1 main diversion supplementary handling for i4l. * @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_divert.c,v $ + * Revision 1.5 1999/08/31 11:20:04 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.4 1999/08/25 20:02:21 werner * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts * with existing software definitions. (PtP incomplete called party number) @@ -513,7 +516,7 @@ int isdn_divert_icall(isdn_ctrl *ic) if (cs->akt_state == DEFLECT_ALERT) { strcpy(cs->deflect_dest,dv->rule.to_nr); if (!cs->timer.expires) - { strcpy(ic->parm.setup.eazmsn,"Testtext direkt"); + { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); ic->parm.setup.screen = dv->rule.screen; strcpy(ic->parm.setup.phone,dv->rule.to_nr); cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ @@ -769,18 +772,6 @@ int prot_stat_callback(isdn_ctrl *ic) } -#if 0 - sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id); - p = st + strlen(st); - p1 = ic->parm.dss1_io.data; - i = ic->parm.dss1_io.datalen; - while ((i > 0) && (p - st < 530)) - { p += sprintf(p," %02x",(*p1++) & 0xFF); - i--; - } - sprintf(p, "\n"); - put_info_buffer(st); -#endif break; default: diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h index 1d329c0fb..6ab119ed9 100644 --- a/drivers/isdn/divert/isdn_divert.h +++ b/drivers/isdn/divert/isdn_divert.h @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.h,v 1.3 1999/08/22 20:26:37 calle Exp $ + * $Id: isdn_divert.h,v 1.4 1999/09/02 13:24:12 paul Exp $ * * Header for the diversion supplementary ioctl interface. * @@ -20,6 +20,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_divert.h,v $ + * Revision 1.4 1999/09/02 13:24:12 paul + * cosmetics; text following #endif is not ANSI C + * * Revision 1.3 1999/08/22 20:26:37 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -29,12 +32,9 @@ * Revision 1.2 1999/07/04 21:37:33 werner * Ported from kernel version 2.0 * - * - * */ - #include <linux/ioctl.h> #include <linux/types.h> @@ -94,12 +94,12 @@ typedef struct typedef union { int drv_version; /* return of driver version */ struct - { int drvid; /* id of driver */ - char drvnam[30]; /* name of driver */ + { int drvid; /* id of driver */ + char drvnam[30]; /* name of driver */ } getid; struct - { int ruleidx; /* index of rule */ - divert_rule rule; /* rule parms */ + { int ruleidx; /* index of rule */ + divert_rule rule; /* rule parms */ } getsetrule; struct { u_char subcmd; /* 0 = hangup/reject, @@ -125,7 +125,7 @@ typedef union #include <linux/isdnif.h> #include <linux/isdn_divertif.h> -#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */ +#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */ /**************************************************/ /* structure keeping ascii info for device output */ @@ -153,12 +153,4 @@ extern void deleteprocs(void); extern int deflect_extern_action(u_char, ulong, char *); extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *); -#endif __KERNEL__ - - - - - - - - +#endif /* __KERNEL__ */ diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h index beee023dc..88af10416 100644 --- a/drivers/isdn/eicon/eicon.h +++ b/drivers/isdn/eicon/eicon.h @@ -1,8 +1,8 @@ -/* $Id: eicon.h,v 1.11 1999/08/29 17:23:44 armin Exp $ +/* $Id: eicon.h,v 1.17 1999/10/26 21:15:33 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -21,6 +21,26 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon.h,v $ + * Revision 1.17 1999/10/26 21:15:33 armin + * using define for checking phone number len to avoid buffer overflow. + * + * Revision 1.16 1999/10/08 22:09:33 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.15 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.14 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.13 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.12 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.11 1999/08/29 17:23:44 armin * New setup compat. * Bugfix if compile as not module. @@ -117,6 +137,7 @@ #define MAX_HEADER_LEN 10 +#define MAX_STATUS_BUFFER 150 /* Struct for adding new cards */ typedef struct eicon_cdef { @@ -224,9 +245,9 @@ typedef struct { #include <linux/delay.h> #include <linux/ctype.h> +#include <linux/isdn.h> #include <linux/isdnif.h> -#include <linux/isdn_compat.h> typedef struct { __u16 length __attribute__ ((packed)); /* length of data/parameter field */ @@ -237,7 +258,7 @@ typedef struct { /* Macro for delay via schedule() */ #define SLEEP(j) { \ - current->state = TASK_INTERRUPTIBLE; \ + set_current_state(TASK_INTERRUPTIBLE); \ schedule_timeout(j); \ } @@ -472,7 +493,6 @@ typedef struct { typedef struct { int No; /* Channel Number */ - unsigned short callref; /* Call Reference */ unsigned short fsm_state; /* Current D-Channel state */ unsigned short eazmask; /* EAZ-Mask for this Channel */ int queued; /* User-Data Bytes in TX queue */ @@ -489,9 +509,13 @@ typedef struct { entity e; /* Entity */ char cpn[32]; /* remember cpn */ char oad[32]; /* remember oad */ + char dsa[32]; /* remember dsa */ + char osa[32]; /* remember osa */ unsigned char cause[2]; /* Last Cause */ unsigned char si1; unsigned char si2; + unsigned char plan; + unsigned char screen; } eicon_chan; typedef struct { @@ -527,7 +551,7 @@ typedef struct { #define EICON_STATE_LISTEN 15 #define EICON_STATE_WMCONN 16 -#define EICON_MAX_QUEUED 8000 /* 2 * maxbuff */ +#define EICON_MAX_QUEUE 2138 #define EICON_LOCK_TX 0 #define EICON_LOCK_RX 1 @@ -581,6 +605,8 @@ typedef struct eicon_card { struct sk_buff_head sndq; /* Send-Message queue */ struct sk_buff_head rackq; /* Req-Ack-Message queue */ struct sk_buff_head sackq; /* Data-Ack-Message queue */ + struct sk_buff_head statq; /* Status-Message queue */ + int statq_entries; u_char *ack_msg; /* Ptr to User Data in User skb */ __u16 need_b3ack; /* Flag: Need ACK for current skb */ struct sk_buff *sbuf; /* skb which is currently sent */ @@ -602,8 +628,9 @@ typedef struct eicon_card { isdn_if interface; /* Interface to upper layer */ char regname[35]; /* Name used for request_region */ #ifdef CONFIG_MCA - int mca_slot; /* # of cards MCA slot */ -#endif + int mca_slot; /* # of cards MCA slot */ + int mca_io; /* MCA cards IO port */ +#endif /* CONFIG_MCA */ } eicon_card; /* -----------------------------------------------------------** @@ -668,6 +695,7 @@ extern int eicon_info(char *, int , void *); #endif /* CONFIG_MCA */ extern ulong DebugVar; +extern void eicon_log(eicon_card * card, int level, const char *fmt, ...); #endif /* __KERNEL__ */ diff --git a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c index af9c30483..d8634bdbe 100644 --- a/drivers/isdn/eicon/eicon_idi.c +++ b/drivers/isdn/eicon/eicon_idi.c @@ -1,4 +1,4 @@ -/* $Id: eicon_idi.c,v 1.15 1999/08/28 21:32:50 armin Exp $ +/* $Id: eicon_idi.c,v 1.24 1999/10/26 21:15:33 armin Exp $ * * ISDN lowlevel-module for Eicon.Diehl active cards. * IDI interface @@ -6,6 +6,11 @@ * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * + * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH + * for sponsoring and testing fax + * capabilities with Diva Server cards. + * (dor@deutschemailbox.de) + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -21,6 +26,35 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_idi.c,v $ + * Revision 1.24 1999/10/26 21:15:33 armin + * using define for checking phone number len to avoid buffer overflow. + * + * Revision 1.23 1999/10/11 18:13:25 armin + * Added fax capabilities for Eicon Diva Server cards. + * + * Revision 1.22 1999/10/08 22:09:33 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.21 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.20 1999/09/21 20:35:43 armin + * added more error checking. + * + * Revision 1.19 1999/09/21 20:06:40 armin + * Added pointer checks. + * + * Revision 1.18 1999/09/07 12:48:05 armin + * Prepared for sub-address usage. + * + * Revision 1.17 1999/09/07 12:35:39 armin + * Better checking and channel Id handling. + * + * Revision 1.16 1999/09/04 13:44:19 armin + * Fix of V.42 analog Modem negotiation handling. + * * Revision 1.15 1999/08/28 21:32:50 armin * Prepared for fax related functions. * Now compilable without errors/warnings. @@ -96,7 +130,7 @@ #undef EICON_FULL_SERVICE_OKTETT -char *eicon_idi_revision = "$Revision: 1.15 $"; +char *eicon_idi_revision = "$Revision: 1.24 $"; eicon_manifbuf *manbuf; @@ -162,9 +196,14 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan) reqbuf->XBuffer.P[l++] = 5; break; case ISDN_PROTO_L2_TRANS: - case ISDN_PROTO_L2_MODEM: reqbuf->XBuffer.P[l++] = 2; break; + case ISDN_PROTO_L2_MODEM: + if (chan->fsm_state == EICON_STATE_IWAIT) + reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */ + else + reqbuf->XBuffer.P[l++] = 10; /* V.42 */ + break; case ISDN_PROTO_L2_FAX: if (chan->fsm_state == EICON_STATE_IWAIT) reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */ @@ -275,8 +314,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan) reqbuf->XBuffer.P[8] = 0; reqbuf->XBuffer.length = l; reqbuf->Reference = 0; /* Sig Entity */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No); + eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No); return(0); } @@ -292,8 +330,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -305,8 +342,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) chan2->ptr = chan; reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - if (DebugVar & 8) - printk(KERN_DEBUG "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); + eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); if (layer) cmd |= 0x700; switch(cmd) { case ASSIGN: @@ -345,8 +381,7 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) idi_put_req(reqbuf, IDI_N_DISC_ACK, 1); break; default: - if (DebugVar & 1) - printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No); + eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No); dev_kfree_skb(skb); dev_kfree_skb(skb2); return(-1); @@ -361,8 +396,10 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan) { - if (DebugVar & 16) - printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); + if ((!card) || (!chan)) + return 1; + + eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); if (!chan->e.D3Id) { idi_do_req(card, chan, ASSIGN, 0); } @@ -416,15 +453,19 @@ idi_si2bc(int si1, int si2, char *bc, char *hlc) int idi_hangup(eicon_card *card, eicon_chan *chan) { + if ((!card) || (!chan)) + return 1; + if ((chan->fsm_state == EICON_STATE_ACTIVE) || (chan->fsm_state == EICON_STATE_WMCONN)) { if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1); } if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1); - idi_do_req(card, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No); + if (chan->fsm_state != EICON_STATE_NULL) { + idi_do_req(card, chan, HANGUP, 0); + chan->fsm_state = EICON_STATE_NULL; + } + eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No); #ifdef CONFIG_ISDN_TTY_FAX chan->fax = 0; #endif @@ -434,10 +475,21 @@ idi_hangup(eicon_card *card, eicon_chan *chan) int idi_connect_res(eicon_card *card, eicon_chan *chan) { - chan->fsm_state = EICON_STATE_IWAIT; - idi_do_req(card, chan, CALL_RES, 0); - idi_do_req(card, chan, ASSIGN, 1); - return(0); + if ((!card) || (!chan)) + return 1; + + chan->fsm_state = EICON_STATE_IWAIT; + idi_do_req(card, chan, CALL_RES, 0); + + /* check if old NetID has been removed */ + if (chan->e.B2Id) { + eicon_log(card, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", + chan->No, chan->e.B2Id); + idi_do_req(card, chan, REMOVE, 1); + } + + idi_do_req(card, chan, ASSIGN, 1); + return(0); } int @@ -447,6 +499,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, int l = 0; int i; unsigned char tmp; + unsigned char *sub, *sp; unsigned char bc[5]; unsigned char hlc[5]; struct sk_buff *skb; @@ -454,12 +507,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, eicon_REQ *reqbuf; eicon_chan_ptr *chan2; + if ((!card) || (!chan)) + return 1; + skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -475,18 +530,52 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, reqbuf->ReqCh = 0; reqbuf->ReqId = 1; + sub = NULL; + sp = phone; + while (*sp) { + if (*sp == '.') { + sub = sp + 1; + *sp = 0; + } else + sp++; + } reqbuf->XBuffer.P[l++] = CPN; reqbuf->XBuffer.P[l++] = strlen(phone) + 1; reqbuf->XBuffer.P[l++] = 0x81; for(i=0; i<strlen(phone);i++) - reqbuf->XBuffer.P[l++] = phone[i]; + reqbuf->XBuffer.P[l++] = phone[i] & 0x7f; + if (sub) { + reqbuf->XBuffer.P[l++] = DSA; + reqbuf->XBuffer.P[l++] = strlen(sub) + 2; + reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ + reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ + while (*sub) + reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; + } + sub = NULL; + sp = eazmsn; + while (*sp) { + if (*sp == '.') { + sub = sp + 1; + *sp = 0; + } else + sp++; + } reqbuf->XBuffer.P[l++] = OAD; reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2; reqbuf->XBuffer.P[l++] = 0x01; reqbuf->XBuffer.P[l++] = 0x80; for(i=0; i<strlen(eazmsn);i++) - reqbuf->XBuffer.P[l++] = eazmsn[i]; + reqbuf->XBuffer.P[l++] = eazmsn[i] & 0x7f; + if (sub) { + reqbuf->XBuffer.P[l++] = OSA; + reqbuf->XBuffer.P[l++] = strlen(sub) + 2; + reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ + reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ + while (*sub) + reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; + } if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) { reqbuf->XBuffer.P[l++] = BC; @@ -500,6 +589,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, reqbuf->XBuffer.P[l++] = hlc[i]; } } + reqbuf->XBuffer.P[l++] = CAI; reqbuf->XBuffer.P[l++] = 6; reqbuf->XBuffer.P[l++] = 0x09; @@ -570,8 +660,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, skb_queue_tail(&card->sndq, skb2); eicon_schedule_tx(card); - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); + eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); return(0); } @@ -588,9 +677,10 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi __u16 code; isdn_ctrl cmd; - memset(message, 0, sizeof(idi_ind_message)); + memset(message, 0, sizeof(idi_ind_message)); + + if ((!len) || (!buffer[pos])) return; - if ((!len) || (!buffer[pos])) return; while(pos <= len) { w = buffer[pos++]; if (!w) return; @@ -620,8 +710,18 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi else code = w; code |= (codeset<<8); + if (pos + wlen > len) { + eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No, + wlen, code, (pos + wlen) - len); + return; + } + switch(code) { case OAD: + if (wlen > sizeof(message->oad)) { + pos += wlen; + break; + } j = 1; if (wlen) { message->plan = buffer[pos++]; @@ -634,11 +734,14 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi } for(i=0; i < wlen-j; i++) message->oad[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, - message->plan, message->screen, message->oad); + eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, + message->plan, message->screen, message->oad); break; case RDN: + if (wlen > sizeof(message->rdn)) { + pos += wlen; + break; + } j = 1; if (wlen) { if (!(buffer[pos++] & 0x80)) { @@ -648,92 +751,116 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi } for(i=0; i < wlen-j; i++) message->rdn[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No, + eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No, message->rdn); break; case CPN: + if (wlen > sizeof(message->cpn)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->cpn[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, - (__u8)message->cpn[0], message->cpn + 1); + eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, + (__u8)message->cpn[0], message->cpn + 1); break; case DSA: - pos++; - for(i=0; i < wlen-1; i++) + if (wlen > sizeof(message->dsa)) { + pos += wlen; + break; + } + pos += 2; + for(i=0; i < wlen-2; i++) message->dsa[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); + eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); break; case OSA: - pos++; - for(i=0; i < wlen-1; i++) + if (wlen > sizeof(message->osa)) { + pos += wlen; + break; + } + pos += 2; + for(i=0; i < wlen-2; i++) message->osa[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); + eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); break; case BC: + if (wlen > sizeof(message->bc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->bc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, - message->bc[0],message->bc[1],message->bc[2]); + eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, + message->bc[0],message->bc[1],message->bc[2]); break; case 0x800|BC: + if (wlen > sizeof(message->e_bc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_bc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); break; case LLC: + if (wlen > sizeof(message->llc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->llc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], - message->llc[1],message->llc[2],message->llc[3]); + eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], + message->llc[1],message->llc[2],message->llc[3]); break; case HLC: + if (wlen > sizeof(message->hlc)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->hlc[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, - message->hlc[0], message->hlc[1], - message->hlc[2], message->hlc[3], message->hlc[4]); + eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, + message->hlc[0], message->hlc[1], + message->hlc[2], message->hlc[3], message->hlc[4]); break; case DSP: case 0x600|DSP: + if (wlen > sizeof(message->display)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->display[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No, - message->display); + eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No, + message->display); break; case 0x600|KEY: + if (wlen > sizeof(message->keypad)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->keypad[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No, - message->keypad); + eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No, + message->keypad); break; case NI: case 0x600|NI: if (wlen) { - if (DebugVar & 4) { - switch(buffer[pos] & 127) { - case 0: - printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No); - break; - case 1: - printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No); - break; - case 2: - printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No); - break; - default: - printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n", - chan->No, buffer[pos] & 127); - } + switch(buffer[pos] & 127) { + case 0: + eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No); + break; + case 1: + eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No); + break; + case 2: + eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No); + break; + default: + eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n", + chan->No, buffer[pos] & 127); } pos += wlen; } @@ -741,80 +868,91 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi case PI: case 0x600|PI: if (wlen > 1) { - if (DebugVar & 4) { - switch(buffer[pos+1] & 127) { - case 1: - printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); - break; - case 2: - printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); - break; - case 3: - printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); - break; - case 4: - printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); - break; - case 5: - printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No); - break; - case 8: - printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No); - break; - default: - printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n", - chan->No, buffer[pos+1] & 127); - } + switch(buffer[pos+1] & 127) { + case 1: + eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); + break; + case 2: + eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); + break; + case 3: + eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); + break; + case 4: + eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); + break; + case 5: + eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No); + break; + case 8: + eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No); + break; + default: + eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n", + chan->No, buffer[pos+1] & 127); } } pos += wlen; break; case CAU: + if (wlen > sizeof(message->cau)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->cau[i] = buffer[pos++]; memcpy(&chan->cause, &message->cau, 2); - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No, - message->cau[0],message->cau[1]); + eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No, + message->cau[0],message->cau[1]); break; case 0x800|CAU: + if (wlen > sizeof(message->e_cau)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_cau[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No, - message->e_cau[0],message->e_cau[1]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No, + message->e_cau[0],message->e_cau[1]); break; case 0x800|CHI: + if (wlen > sizeof(message->e_chi)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->e_chi[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, - message->e_cau[0]); + eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, + message->e_cau[0]); break; case 0x800|0x7a: pos ++; message->e_mt=buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); + eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); break; case DT: + if (wlen > sizeof(message->dt)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->dt[i] = buffer[pos++]; - if (DebugVar & 4) - printk(KERN_DEBUG"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, - message->dt[2], message->dt[1], message->dt[0], - message->dt[3], message->dt[4], message->dt[5]); + eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, + message->dt[2], message->dt[1], message->dt[0], + message->dt[3], message->dt[4], message->dt[5]); break; case 0x600|SIN: + if (wlen > sizeof(message->sin)) { + pos += wlen; + break; + } for(i=0; i < wlen; i++) message->sin[i] = buffer[pos++]; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No, - message->sin[0],message->sin[1]); + eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No, + message->sin[0],message->sin[1]); break; case 0x600|CPS: - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No); + eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No); pos += wlen; break; case 0x600|CIF: @@ -822,8 +960,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi if (buffer[pos + i] != '0') break; memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i); cmd.parm.num[wlen - i] = 0; - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); + eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); pos += wlen; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_CINF; @@ -831,8 +968,11 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi ccard->interface.statcallb(&cmd); break; case 0x600|DATE: - if (DebugVar & 2) - printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No); + eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No); + pos += wlen; + break; + case 0xa1: + eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No); pos += wlen; break; case 0xe08: @@ -852,8 +992,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi case 0x880: /* Managment Information Element */ if (!manbuf) { - if (DebugVar & 1) - printk(KERN_WARNING"idi_err: manbuf not allocated\n"); + eicon_log(ccard, 1, "idi_err: manbuf not allocated\n"); } else { memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen); @@ -865,9 +1004,8 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi break; default: pos += wlen; - if (DebugVar & 6) - printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", - chan->No, code, wlen); + eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", + chan->No, code, wlen); } } } @@ -908,110 +1046,1095 @@ idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned ch int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer) { + eicon_t30_s *t30 = (eicon_t30_s *) buffer; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n"); + return 0; + } + memset(t30, 0, sizeof(eicon_t30_s)); + t30->station_id_len = EICON_FAXID_LEN; + memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN); + t30->resolution = chan->fax->resolution; + t30->rate = chan->fax->rate + 1; /* eicon rate starts with 1 */ + t30->format = T30_FORMAT_SFF; + t30->pages_low = 0; + t30->pages_high = 0; + t30->atf = 1; /* optimised for AT+F command set */ + t30->code = 0; + t30->feature_bits_low = 0; + t30->feature_bits_high = 0; + t30->control_bits_low = 0; + t30->control_bits_high = 0; + + if (chan->fax->nbc) { + /* set compression by DCC value */ + switch(chan->fax->compression) { + case (0): /* 1-D modified */ + break; + case (1): /* 2-D modified Read */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + break; + case (2): /* 2-D uncompressed */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + break; + case (3): /* 2-D modified Read */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + break; + } + } else { + /* set compression to best */ + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; + t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; + t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; + t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + } + switch(chan->fax->ecm) { + case (0): /* disable ECM */ + break; + case (1): + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES; + break; + case (2): + t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; + t30->feature_bits_low |= T30_FEATURE_BIT_ECM; + break; + } - return(0); + if (DebugVar & 128) { + char st[40]; + eicon_log(NULL, 128, "sT30:code = %x\n", t30->code); + eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate); + eicon_log(NULL, 128, "sT30:res = %x\n", t30->resolution); + eicon_log(NULL, 128, "sT30:format = %x\n", t30->format); + eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low); + eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high); + eicon_log(NULL, 128, "sT30:atf = %x\n", t30->atf); + eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low); + eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high); + eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low); + eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high); + //eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5); + //eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6); + //eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7); + eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len); + eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len); + strncpy(st, t30->station_id, t30->station_id_len); + st[t30->station_id_len] = 0; + eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st); + } + return(sizeof(eicon_t30_s)); } /* send fax struct */ int idi_send_edata(eicon_card *card, eicon_chan *chan) { + struct sk_buff *skb; + struct sk_buff *skb2; + eicon_REQ *reqbuf; + eicon_chan_ptr *chan2; + + if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { + eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state); + return -ENODEV; + } + eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No); + + skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC); + skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); + + if ((!skb) || (!skb2)) { + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No); + if (skb) + dev_kfree_skb(skb); + if (skb2) + dev_kfree_skb(skb2); + return -ENOMEM; + } + + chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); + chan2->ptr = chan; - /* TODO , code follows */ + reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ)); + + reqbuf->Req = IDI_N_EDATA; + reqbuf->ReqCh = 0; + reqbuf->ReqId = 1; + + reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P); + reqbuf->Reference = 1; /* Net Entity */ + skb_queue_tail(&chan->e.X, skb); + skb_queue_tail(&card->sndq, skb2); + eicon_schedule_tx(card); return (0); } void idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) { + eicon_t30_s *p = (eicon_t30_s *)buffer; + int i; - /* TODO , code follows */ + if (DebugVar & 128) { + char st[40]; + eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s)); + eicon_log(ccard, 128, "rT30:code = %x\n", p->code); + eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate); + eicon_log(ccard, 128, "rT30:res = %x\n", p->resolution); + eicon_log(ccard, 128, "rT30:format = %x\n", p->format); + eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low); + eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high); + eicon_log(ccard, 128, "rT30:atf = %x\n", p->atf); + eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low); + eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high); + eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low); + eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high); + //eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5); + //eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6); + //eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7); + eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len); + eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len); + strncpy(st, p->station_id, p->station_id_len); + st[p->station_id_len] = 0; + eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st); + } + if (!chan->fax) { + eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n"); + return; + } + chan->fax->code = p->code; + i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1); + memcpy(chan->fax->r_id, p->station_id, i); + chan->fax->r_id[i] = 0; + chan->fax->r_resolution = p->resolution; + chan->fax->r_rate = p->rate - 1; + chan->fax->r_binary = 0; /* no binary support */ + chan->fax->r_width = 0; + chan->fax->r_length = 2; + chan->fax->r_scantime = 0; + chan->fax->r_compression = 0; + chan->fax->r_ecm = 0; + if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) { + chan->fax->r_compression = 1; + if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) { + chan->fax->r_compression = 2; + } + } + if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) { + chan->fax->r_compression = 3; + } + if (p->feature_bits_low & T30_FEATURE_BIT_ECM) { + chan->fax->r_ecm = 2; + if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES) + chan->fax->r_ecm = 1; + } } void idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header) { + static __u16 wd2sff[] = { + 1728, 2048, 2432, 1216, 864 + }; + static __u16 ln2sff[2][3] = { + { 1143, 1401, 0 } , { 2287, 2802, 0 } + }; + struct sk_buff *skb; + eicon_sff_dochead *doc; + eicon_sff_pagehead *page; + u_char *docp; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n"); + return; + } + if (header == 2) { /* DocHeader + PageHeader */ + skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC); + } else { + skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC); + } + if (!skb) { + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No); + return; + } + + if (header == 2) { /* DocHeader + PageHeader */ + docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); + doc = (eicon_sff_dochead *) docp; + page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead)); + memset(docp, 0,sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); + doc->id = 0x66666653; + doc->version = 0x01; + doc->off1pagehead = sizeof(eicon_sff_dochead); + } else { + page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead)); + memset(page, 0, sizeof(eicon_sff_pagehead)); + } + switch(header) { + case 1: /* PageHeaderEnd */ + page->pageheadid = 254; + page->pageheadlen = 0; + break; + case 0: /* PageHeader */ + case 2: /* DocHeader + PageHeader */ + page->pageheadid = 254; + page->pageheadlen = sizeof(eicon_sff_pagehead) - 2; + page->resvert = chan->fax->resolution; + page->reshoriz = 0; /* always 203 dpi */ + page->coding = 0; /* always 1D */ + page->linelength = wd2sff[chan->fax->width]; + page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length]; + eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength); + eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength); + break; + } + idi_send_data(card, chan, 0, skb, 0); } void idi_fax_cmd(eicon_card *card, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ + if ((!card) || (!chan)) + return; + if (!chan->fax) { + eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n"); + return; + } + switch (chan->fax->code) { + case ISDN_TTY_FAX_DT: + if (chan->fax->phase == ISDN_FAX_PHASE_B) { + idi_send_edata(card, chan); + break; + } + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + idi_send_edata(card, chan); + break; + } + break; + + case ISDN_TTY_FAX_DR: + if (chan->fax->phase == ISDN_FAX_PHASE_B) { + idi_send_edata(card, chan); + + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_CFR; + card->interface.statcallb(&cmd); + + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + card->interface.statcallb(&cmd); + + /* telling 1-D compression */ + chan->fax->r_compression = 0; + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DCS; + card->interface.statcallb(&cmd); + + chan->fax2.NextObject = FAX_OBJECT_DOCU; + chan->fax2.PrevObject = FAX_OBJECT_DOCU; + + break; + } + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + idi_send_edata(card, chan); + break; + } + break; + + case ISDN_TTY_FAX_ET: + switch(chan->fax->fet) { + case 0: + case 1: + idi_fax_send_header(card, chan, 0); + break; + case 2: + idi_fax_send_header(card, chan, 1); + break; + } + break; + } } void idi_edata_rcveop(eicon_card *card, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ - + if (!chan->fax) { + eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n"); + return; + } + cmd.driver = card->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_ET; + card->interface.statcallb(&cmd); } void idi_reset_fax_stat(eicon_chan *chan) { - - /* TODO , code follows */ - + chan->fax2.LineLen = 0; + chan->fax2.LineData = 0; + chan->fax2.LineDataLen = 0; + chan->fax2.NullByteExist = 0; + chan->fax2.Dle = 0; + chan->fax2.PageCount = 0; + chan->fax2.Eop = 0; } void idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len) { + isdn_ctrl cmd; + + if (!chan->fax) { + eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n"); + return; + } + if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) { + idi_parse_edata(ccard, chan, buffer, len); + + if (chan->fax->phase == ISDN_FAX_PHASE_A) { + idi_reset_fax_stat(chan); + + chan->fsm_state = EICON_STATE_ACTIVE; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_FCON; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DIS; + ccard->interface.statcallb(&cmd); + + if (chan->fax->r_compression != 0) { + /* telling fake compression in second DIS message */ + chan->fax->r_compression = 0; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_DIS; + ccard->interface.statcallb(&cmd); + } + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */ + ccard->interface.statcallb(&cmd); + } else + if (chan->fax->phase == ISDN_FAX_PHASE_D) { + + if ((chan->fax->code == EDATA_T30_MCF) && + (chan->fax->fet != 2)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_PTS; + ccard->interface.statcallb(&cmd); + } + + switch(chan->fax->fet) { + case 0: /* new page */ + /* stay in phase D , wait on cmd +FDT */ + break; + case 1: /* new document */ + /* link-level switch to phase B */ + break; + case 2: /* session end */ + default: + /* idi_send_edata(ccard, chan); */ + break; + } + } + } + + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + idi_parse_edata(ccard, chan, buffer, len); - /* TODO , code follows */ + if ((chan->fax->code == EDATA_T30_DCS) && + (chan->fax->phase == ISDN_FAX_PHASE_A)) { + idi_reset_fax_stat(chan); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_BCONN; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); + + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_FCON_I; + ccard->interface.statcallb(&cmd); + } else + if ((chan->fax->code == EDATA_T30_TRAIN_OK) && + (chan->fax->phase == ISDN_FAX_PHASE_A)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_RID; + ccard->interface.statcallb(&cmd); + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; + ccard->interface.statcallb(&cmd); + } else + if ((chan->fax->code == EDATA_T30_TRAIN_OK) && + (chan->fax->phase == ISDN_FAX_PHASE_B)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; + ccard->interface.statcallb(&cmd); + } else + if (chan->fax->phase == ISDN_FAX_PHASE_C) { + switch(chan->fax->code) { + case EDATA_T30_TRAIN_OK: + idi_send_edata(ccard, chan); + break; + case EDATA_T30_MPS: + chan->fax->fet = 0; + idi_edata_rcveop(ccard, chan); + break; + case EDATA_T30_EOM: + chan->fax->fet = 1; + idi_edata_rcveop(ccard, chan); + break; + case EDATA_T30_EOP: + chan->fax->fet = 2; + idi_edata_rcveop(ccard, chan); + break; + } + } + } } void fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len) { - - /* TODO , code follows */ - + struct sk_buff *skb; + + skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC); + if (!skb) { + eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No); + return; + } + skb_reserve(skb, MAX_HEADER_LEN); + memcpy(skb_put(skb, len), Data, len); + ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); } void idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) { + eicon_OBJBUFFER InBuf; + eicon_OBJBUFFER LineBuf; + unsigned int Length = 0; + unsigned int aLength = 0; + unsigned int ObjectSize = 0; + unsigned int ObjHeadLen = 0; + unsigned int ObjDataLen = 0; + __u8 Recordtype; + __u8 PageHeaderLen; + __u8 Event; + eicon_sff_pagehead *ob_page; + + __u16 Cl2Eol = 0x8000; + +# define EVENT_NONE 0 +# define EVENT_NEEDDATA 1 + + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n"); + return; + } + + + + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + InBuf.Data = skb->data; + InBuf.Size = skb->len; + InBuf.Len = 0; + InBuf.Next = InBuf.Data; + LineBuf.Data = chan->fax2.abLine; + LineBuf.Size = sizeof(chan->fax2.abLine); + LineBuf.Len = chan->fax2.LineLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + + Event = EVENT_NONE; + while (Event == EVENT_NONE) { + switch(chan->fax2.NextObject) { + case FAX_OBJECT_DOCU: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < sizeof(eicon_sff_dochead)) { + Event = EVENT_NEEDDATA; + break; + } + ObjectSize = sizeof(eicon_sff_dochead); + Length = ObjectSize; + if (LineBuf.Len < Length) { + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + InBuf.Len += Length; + InBuf.Next += Length; + } else { + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + } + chan->fax2.PrevObject = FAX_OBJECT_DOCU; + chan->fax2.NextObject = FAX_OBJECT_PAGE; + break; + + case FAX_OBJECT_PAGE: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < 2) { + Event = EVENT_NEEDDATA; + break; + } + if (LineBuf.Len == 0) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + if (LineBuf.Len == 1) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + PageHeaderLen = *(LineBuf.Data + 1); + ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead); + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + Length = ObjectSize; + /* extract page dimensions */ + if (LineBuf.Len < Length) { + aLength = Length - LineBuf.Len; + memcpy(LineBuf.Next, InBuf.Next, aLength); + LineBuf.Next += aLength; + InBuf.Next += aLength; + LineBuf.Len += aLength; + InBuf.Len += aLength; + } + if (Length > 2) { + ob_page = (eicon_sff_pagehead *)LineBuf.Data; + switch(ob_page->linelength) { + case 2048: + chan->fax->r_width = 1; + break; + case 2432: + chan->fax->r_width = 2; + break; + case 1216: + chan->fax->r_width = 3; + break; + case 864: + chan->fax->r_width = 4; + break; + case 1728: + default: + chan->fax->r_width = 0; + } + switch(ob_page->pagelength) { + case 1143: + case 2287: + chan->fax->r_length = 0; + break; + case 1401: + case 2802: + chan->fax->r_length = 1; + break; + default: + chan->fax->r_length = 2; + } + eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength); + eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength); + } + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + + chan->fax2.PrevObject = FAX_OBJECT_PAGE; + chan->fax2.NextObject = FAX_OBJECT_LINE; + break; + + case FAX_OBJECT_LINE: + Length = LineBuf.Len + (InBuf.Size - InBuf.Len); + if (Length < 1) { + Event = EVENT_NEEDDATA; + break; + } + if (LineBuf.Len == 0) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + Recordtype = *LineBuf.Data; + if (Recordtype == 0) { + /* recordtype pixel row (2 byte length) */ + ObjHeadLen = 3; + if (Length < ObjHeadLen) { + Event = EVENT_NEEDDATA; + break; + } + while (LineBuf.Len < ObjHeadLen) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + ObjDataLen = *((__u16*) (LineBuf.Data + 1)); + ObjectSize = ObjHeadLen + ObjDataLen; + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + } else + if ((Recordtype >= 1) && (Recordtype <= 216)) { + /* recordtype pixel row (1 byte length) */ + ObjHeadLen = 1; + ObjDataLen = Recordtype; + ObjectSize = ObjHeadLen + ObjDataLen; + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + } else + if ((Recordtype >= 217) && (Recordtype <= 253)) { + /* recordtype empty lines */ + ObjHeadLen = 1; + ObjDataLen = 0; + ObjectSize = ObjHeadLen + ObjDataLen; + LineBuf.Len--; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len); + break; + } else + if (Recordtype == 254) { + /* recordtype page header */ + chan->fax2.PrevObject = FAX_OBJECT_LINE; + chan->fax2.NextObject = FAX_OBJECT_PAGE; + break; + } else { + /* recordtype user information */ + ObjHeadLen = 2; + if (Length < ObjHeadLen) { + Event = EVENT_NEEDDATA; + break; + } + while (LineBuf.Len < ObjHeadLen) { + *LineBuf.Next++ = *InBuf.Next++; + LineBuf.Len++; + InBuf.Len++; + } + ObjDataLen = *(LineBuf.Data + 1); + ObjectSize = ObjHeadLen + ObjDataLen; + if (ObjDataLen == 0) { + /* illegal line coding */ + LineBuf.Len -= ObjHeadLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len); + break; + } else { + /* user information */ + if (Length < ObjectSize) { + Event = EVENT_NEEDDATA; + break; + } + Length = ObjectSize; + if (LineBuf.Len < Length) { + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + InBuf.Len += Length; + InBuf.Next += Length; + } else { + LineBuf.Len -= Length; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); + } + } + break; + } + Length = ObjectSize; + if (LineBuf.Len > ObjHeadLen) { + fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen, + (LineBuf.Len - ObjHeadLen)); + } + Length -= LineBuf.Len; + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + if (Length > 0) { + fax_put_rcv(ccard, chan, InBuf.Next, Length); + InBuf.Len += Length; + InBuf.Next += Length; + } + fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol)); + break; + } /* end of switch (chan->fax2.NextObject) */ + } /* end of while (Event==EVENT_NONE) */ + if (InBuf.Len < InBuf.Size) { + Length = InBuf.Size - InBuf.Len; + if ((LineBuf.Len + Length) > LineBuf.Size) { + eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No, + Length); + } else { + memcpy(LineBuf.Next, InBuf.Next, Length); + LineBuf.Len += Length; + } + } + chan->fax2.LineLen = LineBuf.Len; + } else { /* CONN_OUT */ + /* On CONN_OUT we do not need incoming data, drop it */ + /* maybe later for polling */ + } - /* TODO , code follows */ +# undef EVENT_NONE +# undef EVENT_NEEDDATA + return; } int idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf) { + struct sk_buff *skb; - /* TODO , code follows */ + skb = alloc_skb(OutBuf->Len, GFP_ATOMIC); + if (!skb) { + eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No); + return(-1); + } + memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len); - return(0); + OutBuf->Len = 0; + OutBuf->Next = OutBuf->Data; + + return(idi_send_data(ccard, chan, 0, skb, 1)); } int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) { + isdn_ctrl cmd; + eicon_OBJBUFFER InBuf; + __u8 InData; + __u8 InMask; + eicon_OBJBUFFER OutBuf; + eicon_OBJBUFFER LineBuf; + __u32 LineData; + unsigned int LineDataLen; + __u8 Byte; + __u8 Event; + int ret = 1; + +# define EVENT_NONE 0 +# define EVENT_EOD 1 +# define EVENT_EOL 2 +# define EVENT_EOP 3 + + if ((!ccard) || (!chan)) + return -1; - /* TODO , code follows */ + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n"); + return -1; + } - return(0); + if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { + /* Simply ignore any data written in data mode when receiving a fax. */ + /* This is not completely correct because only XON's should come here. */ + dev_kfree_skb(skb); + return 1; + } + + if (chan->fax->phase != ISDN_FAX_PHASE_C) { + dev_kfree_skb(skb); + return 1; + } + + if (chan->queued + skb->len > 1200) + return 0; + + InBuf.Data = skb->data; + InBuf.Size = skb->len; + InBuf.Len = 0; + InBuf.Next = InBuf.Data; + InData = 0; + InMask = 0; + + LineBuf.Data = chan->fax2.abLine; + LineBuf.Size = sizeof(chan->fax2.abLine); + LineBuf.Len = chan->fax2.LineLen; + LineBuf.Next = LineBuf.Data + LineBuf.Len; + LineData = chan->fax2.LineData; + LineDataLen = chan->fax2.LineDataLen; + + OutBuf.Data = chan->fax2.abFrame; + OutBuf.Size = sizeof(chan->fax2.abFrame); + OutBuf.Len = 0; + OutBuf.Next = OutBuf.Data; + + Event = EVENT_NONE; + + chan->fax2.Eop = 0; + + for (;;) { + for (;;) { + if (InMask == 0) { + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) { + chan->fax2.Dle = _DLE_; + InBuf.Next++; + InBuf.Len++; + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + } + if (chan->fax2.Dle == _DLE_) { + chan->fax2.Dle = 0; + if (*InBuf.Next == _ETX_) { + Event = EVENT_EOP; + break; + } else + if (*InBuf.Next == _DLE_) { + /* do nothing */ + } else { + eicon_log(ccard, 1, + "idi_err: Ch%d: unknown DLE escape %02x found\n", + chan->No, *InBuf.Next); + InBuf.Next++; + InBuf.Len++; + if (InBuf.Len >= InBuf.Size) { + Event = EVENT_EOD; + break; + } + } + } + InBuf.Len++; + InData = *InBuf.Next++; + InMask = (chan->fax->bor) ? 0x80 : 0x01; + } + while (InMask) { + LineData >>= 1; + LineDataLen++; + if (InData & InMask) + LineData |= 0x80000000; + if (chan->fax->bor) + InMask >>= 1; + else + InMask <<= 1; + + if ((LineDataLen >= T4_EOL_BITSIZE) && + ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) { + Event = EVENT_EOL; + if (LineDataLen > T4_EOL_BITSIZE) { + Byte = (__u8) + ((LineData & ~T4_EOL_MASK_DWORD) >> + (32 - LineDataLen)); + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + } + LineDataLen = 0; + break; + } + if (LineDataLen >= T4_EOL_BITSIZE + 8) { + Byte = (__u8) + ((LineData & ~T4_EOL_MASK_DWORD) >> + (32 - T4_EOL_BITSIZE - 8)); + LineData &= T4_EOL_MASK_DWORD; + LineDataLen = T4_EOL_BITSIZE; + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + } + } + if (Event != EVENT_NONE) + break; + } + + if ((Event != EVENT_EOL) && (Event != EVENT_EOP)) + break; + + if ((Event == EVENT_EOP) && (LineDataLen > 0)) { + LineData >>= 32 - LineDataLen; + LineDataLen = 0; + while (LineData != 0) { + Byte = (__u8) LineData; + LineData >>= 8; + if (Byte == 0) { + if (! chan->fax2.NullByteExist) { + chan->fax2.NullBytesPos = LineBuf.Len; + chan->fax2.NullByteExist = 1; + } + } else { + chan->fax2.NullByteExist = 0; + } + if (LineBuf.Len < LineBuf.Size) { + *LineBuf.Next++ = Byte; + LineBuf.Len++; + } + + } + } + if (chan->fax2.NullByteExist) { + if (chan->fax2.NullBytesPos == 0) { + LineBuf.Len = 0; + } else { + LineBuf.Len = chan->fax2.NullBytesPos + 1; + } + } + if (LineBuf.Len > 0) { + if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) { + ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); + } + if (LineBuf.Len <= 216) { + *OutBuf.Next++ = (__u8) LineBuf.Len; + OutBuf.Len++; + } else { + *OutBuf.Next++ = 0; + *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len; + OutBuf.Len += 3; + } + memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len); + OutBuf.Next += LineBuf.Len; + OutBuf.Len += LineBuf.Len; + } + LineBuf.Len = 0; + LineBuf.Next = LineBuf.Data; + chan->fax2.NullByteExist = 0; + if (Event == EVENT_EOP) + break; + + Event = EVENT_NONE; + } + + if (Event == EVENT_EOP) { + chan->fax2.Eop = 1; + chan->fax2.PageCount++; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_EOP; + ccard->interface.statcallb(&cmd); + } + if (OutBuf.Len > 0) { + ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); + } + + chan->fax2.LineLen = LineBuf.Len; + chan->fax2.LineData = LineData; + chan->fax2.LineDataLen = LineDataLen; + +# undef EVENT_NONE +# undef EVENT_EOD +# undef EVENT_EOL +# undef EVENT_EOP + + if (ret >= 0) + dev_kfree_skb(skb); + if (ret == 0) + ret = 1; + return(ret); } void idi_fax_hangup(eicon_card *ccard, eicon_chan *chan) { + isdn_ctrl cmd; - /* TODO , code follows */ - + if (!chan->fax) { + eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n"); + return; + } + if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) && + (chan->fax->code == 0)) { + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + chan->fax->r_code = ISDN_TTY_FAX_PTS; + ccard->interface.statcallb(&cmd); + } + if ((chan->fax->code > 1) && (chan->fax->code < 120)) + chan->fax->code += 120; + chan->fax->r_code = ISDN_TTY_FAX_HNG; + cmd.driver = ccard->myid; + cmd.command = ISDN_STAT_FAXIND; + cmd.arg = chan->No; + ccard->interface.statcallb(&cmd); } #endif /******** FAX ********/ @@ -1025,20 +2148,17 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int eicon_chan_ptr *chan2; if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - if (DebugVar & 1) - printk(KERN_DEBUG"idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); + eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); return -ENODEV; } - if (DebugVar & 8) - printk(KERN_DEBUG"idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, - UReq, buffer[0], buffer[1], buffer[2], buffer[3]); + eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, + UReq, buffer[0], buffer[1], buffer[2], buffer[3]); skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1072,6 +2192,9 @@ idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value) u_char buf[6]; struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; + if ((!ccard) || (!chan)) + return; + memset(buf, 0, 6); switch(cmd) { case ISDN_AUDIO_SETDD: @@ -1103,14 +2226,15 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' }; + if ((!ccard) || (!chan)) + return; + switch (buffer[0]) { case DSP_UDATA_INDICATION_SYNC: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); + eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_OFF: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_DCD_ON: if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && @@ -1122,31 +2246,24 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); ccard->interface.statcallb(&cmd); } - if (DebugVar & 8) { - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); - printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - } + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_CTS_OFF: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); break; case DSP_UDATA_INDICATION_CTS_ON: - if (DebugVar & 8) { - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); - printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - } + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); + eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, + p->norm, p->options, p->speed, p->delay); break; case DSP_UDATA_INDICATION_DISCONNECT: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); break; case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, - dtmf_code[buffer[1]]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, + dtmf_code[buffer[1]]); cmd.driver = ccard->myid; cmd.command = ISDN_STAT_AUDIO; cmd.parm.num[0] = ISDN_AUDIO_DTMF; @@ -1155,8 +2272,7 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int ccard->interface.statcallb(&cmd); break; default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); } } @@ -1164,23 +2280,35 @@ void idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) { int tmp; + char tnum[64]; + int dlev; int free_buff; + ulong flags; struct sk_buff *skb2; eicon_IND *ind = (eicon_IND *)skb->data; eicon_chan *chan; idi_ind_message message; isdn_ctrl cmd; + if (!ccard) { + eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n"); + dev_kfree_skb(skb); + return; + } + if ((chan = ccard->IdTable[ind->IndId]) == NULL) { + eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n"); dev_kfree_skb(skb); return; } - if ((DebugVar & 128) || - ((DebugVar & 16) && (ind->Ind != 8))) { - printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No, - ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); - } + if (ind->Ind != 8) + dlev = 144; + else + dlev = 128; + + eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No, + ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); free_buff = 1; /* Signal Layer */ @@ -1188,16 +2316,16 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); switch(ind->Ind) { case HANGUP: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No); while((skb2 = skb_dequeue(&chan->e.X))) { dev_kfree_skb(skb2); } - chan->e.busy = 0; + save_flags(flags); + cli(); chan->queued = 0; chan->waitq = 0; chan->waitpq = 0; - chan->fsm_state = EICON_STATE_NULL; + restore_flags(flags); if (message.e_cau[0] & 0x7f) { cmd.driver = ccard->myid; cmd.arg = chan->No; @@ -1207,58 +2335,83 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); } chan->cause[0] = 0; - cmd.driver = ccard->myid; - cmd.arg = chan->No; - cmd.command = ISDN_STAT_DHUP; - ccard->interface.statcallb(&cmd); - eicon_idi_listen_req(ccard, chan); #ifdef CONFIG_ISDN_TTY_FAX if (!chan->e.B2Id) chan->fax = 0; #endif + if (((chan->fsm_state == EICON_STATE_ACTIVE) || + (chan->fsm_state == EICON_STATE_WMCONN)) || + ((chan->l2prot == ISDN_PROTO_L2_FAX) && + (chan->fsm_state == EICON_STATE_OBWAIT))) { + chan->fsm_state = EICON_STATE_NULL; + } else { + if (chan->e.B2Id) + idi_do_req(ccard, chan, REMOVE, 1); + chan->fsm_state = EICON_STATE_NULL; + cmd.driver = ccard->myid; + cmd.arg = chan->No; + cmd.command = ISDN_STAT_DHUP; + ccard->interface.statcallb(&cmd); + eicon_idi_listen_req(ccard, chan); + } break; case INDICATE_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Indicate_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No); + if (chan->fsm_state != EICON_STATE_LISTEN) { + eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n", + chan->No, chan->fsm_state); + idi_do_req(ccard, chan, HANGUP, 0); + break; + } chan->fsm_state = EICON_STATE_ICALL; idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2); strcpy(chan->cpn, message.cpn + 1); - if (strlen(message.dsa)) { - strcat(chan->cpn, "."); - strcat(chan->cpn, message.dsa); - } strcpy(chan->oad, message.oad); + strcpy(chan->dsa, message.dsa); + strcpy(chan->osa, message.osa); + chan->plan = message.plan; + chan->screen = message.screen; try_stat_icall_again: cmd.driver = ccard->myid; cmd.command = ISDN_STAT_ICALL; cmd.arg = chan->No; cmd.parm.setup.si1 = chan->si1; cmd.parm.setup.si2 = chan->si2; - strcpy(cmd.parm.setup.eazmsn, chan->cpn); - strcpy(cmd.parm.setup.phone, chan->oad); - cmd.parm.setup.plan = message.plan; - cmd.parm.setup.screen = message.screen; + strcpy(tnum, chan->cpn); + if (strlen(chan->dsa)) { + strcat(tnum, "."); + strcat(tnum, chan->dsa); + } + tnum[ISDN_MSNLEN - 1] = 0; + strcpy(cmd.parm.setup.eazmsn, tnum); + strcpy(tnum, chan->oad); + if (strlen(chan->osa)) { + strcat(tnum, "."); + strcat(tnum, chan->osa); + } + tnum[ISDN_MSNLEN - 1] = 0; + strcpy(cmd.parm.setup.phone, tnum); + cmd.parm.setup.plan = chan->plan; + cmd.parm.setup.screen = chan->screen; tmp = ccard->interface.statcallb(&cmd); switch(tmp) { case 0: /* no user responding */ idi_do_req(ccard, chan, HANGUP, 0); + chan->fsm_state = EICON_STATE_NULL; break; case 1: /* alert */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call Alert\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) { chan->fsm_state = EICON_STATE_ICALL; idi_do_req(ccard, chan, CALL_ALERT, 0); } break; case 2: /* reject */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No); idi_do_req(ccard, chan, REJECT, 0); break; case 3: /* incomplete number */ - if (DebugVar & 8) - printk(KERN_DEBUG"idi_req: Ch%d: Incomplete Number\n", chan->No); + eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No); switch(ccard->type) { case EICON_CTYPE_MAESTRAP: case EICON_CTYPE_S2M: @@ -1272,8 +2425,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } break; case INFO_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALLW) && (message.cpn[0])) { strcat(chan->cpn, message.cpn + 1); @@ -1281,35 +2433,45 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } break; case CALL_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Call_Ind\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No); if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) { chan->fsm_state = EICON_STATE_IBWAIT; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_DCONN; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); - if (chan->l2prot != ISDN_PROTO_L2_FAX) { - idi_do_req(ccard, chan, IDI_N_CONNECT, 1); - } + switch(chan->l2prot) { + case ISDN_PROTO_L2_FAX: #ifdef CONFIG_ISDN_TTY_FAX - else { - if (chan->fax) - chan->fax->phase = ISDN_FAX_PHASE_A; - } + if (chan->fax) + chan->fax->phase = ISDN_FAX_PHASE_A; #endif + break; + case ISDN_PROTO_L2_MODEM: + /* do nothing, wait for connect */ + break; + default: + idi_do_req(ccard, chan, IDI_N_CONNECT, 1); + } } else idi_hangup(ccard, chan); break; case CALL_CON: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Call_Con\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No); if (chan->fsm_state == EICON_STATE_OCALL) { chan->fsm_state = EICON_STATE_OBWAIT; cmd.driver = ccard->myid; cmd.command = ISDN_STAT_DCONN; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); + + /* check if old NetID has been removed */ + if (chan->e.B2Id) { + eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", + chan->No, chan->e.B2Id); + idi_do_req(ccard, chan, REMOVE, 1); + } + idi_do_req(ccard, chan, ASSIGN, 1); idi_do_req(ccard, chan, IDI_N_CONNECT, 1); #ifdef CONFIG_ISDN_TTY_FAX @@ -1322,12 +2484,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_hangup(ccard, chan); break; case AOC_IND: - if (DebugVar & 8) - printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No); + eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No); break; default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); } } /* Network Layer */ @@ -1341,8 +2501,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) else switch(ind->Ind) { case IDI_N_CONNECT_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect_Ack\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No); if (chan->l2prot == ISDN_PROTO_L2_MODEM) { chan->fsm_state = EICON_STATE_WMCONN; break; @@ -1362,8 +2521,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) } } else { - if (DebugVar & 1) - printk(KERN_DEBUG "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n"); + eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n"); } #endif break; @@ -1375,8 +2533,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); break; case IDI_N_CONNECT: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No); + eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No); if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1); if (chan->l2prot == ISDN_PROTO_L2_FAX) { break; @@ -1392,9 +2549,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); break; case IDI_N_DISC: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No); if (chan->e.B2Id) { + while((skb2 = skb_dequeue(&chan->e.X))) { + dev_kfree_skb(skb2); + } idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1); idi_do_req(ccard, chan, REMOVE, 1); } @@ -1404,23 +2563,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) idi_fax_hangup(ccard, chan); } #endif + save_flags(flags); + cli(); chan->queued = 0; chan->waitq = 0; chan->waitpq = 0; + restore_flags(flags); idi_do_req(ccard, chan, HANGUP, 0); if (chan->fsm_state == EICON_STATE_ACTIVE) { cmd.driver = ccard->myid; cmd.command = ISDN_STAT_BHUP; cmd.arg = chan->No; ccard->interface.statcallb(&cmd); + chan->fsm_state = EICON_STATE_NULL; } #ifdef CONFIG_ISDN_TTY_FAX chan->fax = 0; #endif break; case IDI_N_DISC_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No); #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); @@ -1429,13 +2591,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) #endif break; case IDI_N_DATA_ACK: - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No); + eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No); break; case IDI_N_DATA: skb_pull(skb, sizeof(eicon_IND) - 1); - if (DebugVar & 128) - printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); + eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); if (chan->l2prot == ISDN_PROTO_L2_FAX) { #ifdef CONFIG_ISDN_TTY_FAX idi_faxdata_rcv(ccard, chan, skb); @@ -1454,27 +2614,26 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) break; #endif default: - if (DebugVar & 8) - printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); + eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); } } else { - if (DebugVar & 1) - printk(KERN_ERR "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); + eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); } - if (free_buff) dev_kfree_skb(skb); + if (free_buff) + dev_kfree_skb(skb); } int idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) { + ulong flags; isdn_ctrl cmd; if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) { /* I dont know why this happens, just ignoring this RC */ - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, - ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); + eicon_log(ccard, 16, "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, + ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); return 1; } @@ -1488,27 +2647,27 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) /* Remove an Id */ if (chan->e.Req == REMOVE) { if (ack->Reference != chan->e.ref) { - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, - ack->Reference, chan->e.ref); + eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, + ack->Reference, chan->e.ref); return 0; } + save_flags(flags); + cli(); ccard->IdTable[ack->RcId] = NULL; - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, - ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); + eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, + ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); if (!chan->e.ReqCh) chan->e.D3Id = 0; else chan->e.B2Id = 0; + restore_flags(flags); return 1; } /* Signal layer */ if (!chan->e.ReqCh) { - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); + eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); } else { /* Network layer */ switch(chan->e.Req & 0x0f) { @@ -1522,7 +2681,10 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) cmd.parm.length = chan->waitpq; ccard->interface.statcallb(&cmd); } + save_flags(flags); + cli(); chan->waitpq = 0; + restore_flags(flags); #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { if (((chan->queued - chan->waitq) < 1) && @@ -1536,20 +2698,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) ccard->interface.statcallb(&cmd); } else { - if (DebugVar & 1) - printk(KERN_DEBUG "idi_ack: Sent with NULL fax struct, ERROR\n"); + eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n"); } } } #endif } + save_flags(flags); + cli(); chan->queued -= chan->waitq; if (chan->queued < 0) chan->queued = 0; + restore_flags(flags); break; default: - if (DebugVar & 16) - printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); + eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, + ack->RcId, ack->RcCh, ack->Reference); } } return 1; @@ -1559,22 +2722,30 @@ void idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) { int j; + ulong flags; eicon_RC *ack = (eicon_RC *)skb->data; eicon_chan *chan; isdn_ctrl cmd; int dCh = -1; + if (!ccard) { + eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n"); + dev_kfree_skb(skb); + return; + } + + save_flags(flags); + cli(); if ((chan = ccard->IdTable[ack->RcId]) != NULL) dCh = chan->No; - + restore_flags(flags); switch (ack->Rc) { case OK_FC: case N_FLOW_CONTROL: case ASSIGN_RC: - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n", - dCh, ack->Rc); + eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n", + dCh, ack->Rc); break; case READY_INT: case TIMER_INT: @@ -1583,8 +2754,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case OK: if (!chan) { - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh); + eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh); break; } if (!idi_handle_ack_ok(ccard, chan, ack)) @@ -1593,29 +2763,29 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case ASSIGN_OK: if (chan) { - if (DebugVar & 1) - printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", - chan->No, chan->e.D3Id, chan->e.B2Id); + eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", + chan->No, chan->e.D3Id, chan->e.B2Id); } + save_flags(flags); + cli(); for(j = 0; j < ccard->nchannels + 1; j++) { - if (ccard->bch[j].e.ref == ack->Reference) { + if ((ccard->bch[j].e.ref == ack->Reference) && + (ccard->bch[j].e.Req == ASSIGN)) { if (!ccard->bch[j].e.ReqCh) ccard->bch[j].e.D3Id = ack->RcId; else ccard->bch[j].e.B2Id = ack->RcId; ccard->IdTable[ack->RcId] = &ccard->bch[j]; - ccard->bch[j].e.busy = 0; - ccard->bch[j].e.ref = 0; - if (DebugVar & 16) - printk(KERN_DEBUG"idi_ack: Ch%d: Id %x assigned (%s)\n", j, - ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); + chan = &ccard->bch[j]; + eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, + ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); break; } } + restore_flags(flags); if (j > ccard->nchannels) { - if (DebugVar & 24) - printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", - ack->Reference, ack->RcId); + eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", + ack->Reference, ack->RcId); } break; @@ -1627,9 +2797,19 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) case UNKNOWN_IE: case WRONG_IE: default: - if (DebugVar & 1) - printk(KERN_ERR "eicon_ack: Ch%d: Not OK !!: Rc=%d Id=%x Ch=%d\n", dCh, - ack->Rc, ack->RcId, ack->RcCh); + if (!chan) { + eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh); + break; + } else + switch (chan->e.Req) { + case 12: /* Alert */ + eicon_log(ccard, 2, "eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n", + dCh, ack->Rc, ack->RcId, ack->RcCh); + break; + default: + eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n", + dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req); + } if (dCh == ccard->nchannels) { /* Management */ chan->fsm_state = 2; } else if (dCh >= 0) { @@ -1642,8 +2822,13 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) ccard->interface.statcallb(&cmd); } } - if (chan) + save_flags(flags); + cli(); + if (chan) { + chan->e.ref = 0; chan->e.busy = 0; + } + restore_flags(flags); dev_kfree_skb(skb); eicon_schedule_tx(ccard); } @@ -1658,21 +2843,25 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int len, plen = 0, offset = 0; unsigned long flags; + if ((!card) || (!chan)) { + eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n"); + return -1; + } + if (chan->fsm_state != EICON_STATE_ACTIVE) { - if (DebugVar & 1) - printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); + eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); return -ENODEV; } len = skb->len; - if (len > 2138) /* too much for the shared memory */ + if (len > EICON_MAX_QUEUE) /* too much for the shared memory */ return -1; if (!len) return 0; - if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED)) + if (chan->queued + len > EICON_MAX_QUEUE) return 0; - if (DebugVar & 128) - printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len); + + eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len); save_flags(flags); cli(); @@ -1685,8 +2874,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, if ((!xmit_skb) || (!skb2)) { restore_flags(flags); - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); + eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); if (xmit_skb) dev_kfree_skb(skb); if (skb2) @@ -1740,8 +2928,7 @@ eicon_idi_manage_assign(eicon_card *card) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_skb failed in manage_assign()\n"); + eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n"); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1783,8 +2970,7 @@ eicon_idi_manage_remove(eicon_card *card) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_skb failed in manage_remove()\n"); + eicon_log(card, 1, "idi_err: alloc_skb failed in manage_remove()\n"); if (skb) dev_kfree_skb(skb); if (skb2) @@ -1850,8 +3036,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) chan->fsm_state = 0; if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n"); + eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n"); chan->e.D3Id = 0; return -ENOMEM; } @@ -1865,8 +3050,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); if ((!skb) || (!skb2)) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err_manif: alloc_skb failed in manage()\n"); + eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n"); if (skb) dev_kfree_skb(skb); if (skb2) diff --git a/drivers/isdn/eicon/eicon_io.c b/drivers/isdn/eicon/eicon_io.c index 60b5b4818..779f241e0 100644 --- a/drivers/isdn/eicon/eicon_io.c +++ b/drivers/isdn/eicon/eicon_io.c @@ -1,4 +1,4 @@ -/* $Id: eicon_io.c,v 1.4 1999/08/22 20:26:47 calle Exp $ +/* $Id: eicon_io.c,v 1.8 1999/10/08 22:09:34 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * Code for communicating with hardware. @@ -24,6 +24,20 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_io.c,v $ + * Revision 1.8 1999/10/08 22:09:34 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.7 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.6 1999/09/21 20:35:43 armin + * added more error checking. + * + * Revision 1.5 1999/08/31 11:20:11 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.4 1999/08/22 20:26:47 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -51,19 +65,21 @@ void eicon_io_rcv_dispatch(eicon_card *ccard) { + ulong flags; struct sk_buff *skb, *skb2, *skb_new; eicon_IND *ind, *ind2, *ind_new; eicon_chan *chan; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_io_rcv_dispatch: NULL card!\n"); + eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n"); return; } while((skb = skb_dequeue(&ccard->rcvq))) { ind = (eicon_IND *)skb->data; + save_flags(flags); + cli(); if ((chan = ccard->IdTable[ind->IndId]) == NULL) { if (DebugVar & 1) { switch(ind->Ind) { @@ -71,14 +87,16 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { /* doesn't matter if this happens */ break; default: - printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); - printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); + eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); } } + restore_flags(flags); dev_kfree_skb(skb); continue; } + restore_flags(flags); if (chan->e.complete) { /* check for rec-buffer chaining */ if (ind->MLength == ind->RBuffer.length) { @@ -94,10 +112,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { } } else { + save_flags(flags); + cli(); if (!(skb2 = skb_dequeue(&chan->e.R))) { chan->e.complete = 1; - if (DebugVar & 1) - printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n"); + eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n"); + restore_flags(flags); dev_kfree_skb(skb); continue; } @@ -105,8 +125,8 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length), GFP_ATOMIC); if (!skb_new) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in rcv_dispatch()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n"); + restore_flags(flags); dev_kfree_skb(skb); dev_kfree_skb(skb2); continue; @@ -125,12 +145,14 @@ eicon_io_rcv_dispatch(eicon_card *ccard) { dev_kfree_skb(skb2); if (ind->MLength == ind->RBuffer.length) { chan->e.complete = 2; + restore_flags(flags); idi_handle_ind(ccard, skb_new); continue; } else { chan->e.complete = 0; skb_queue_tail(&chan->e.R, skb_new); + restore_flags(flags); continue; } } @@ -142,8 +164,7 @@ eicon_io_ack_dispatch(eicon_card *ccard) { struct sk_buff *skb; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_io_ack_dispatch: NULL card!\n"); + eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n"); return; } while((skb = skb_dequeue(&ccard->rackq))) { @@ -399,13 +420,13 @@ eicon_io_transmit(eicon_card *ccard) { int scom = 0; int tmp = 0; int quloop = 1; + int dlev = 0; pci_card = &ccard->hwif.pci; isa_card = &ccard->hwif.isa; if (!ccard) { - if (DebugVar & 1) - printk(KERN_WARNING "eicon_transmit: NULL card!\n"); + eicon_log(ccard, 1, "eicon_transmit: NULL card!\n"); return; } @@ -438,7 +459,7 @@ eicon_io_transmit(eicon_card *ccard) { prram = 0; break; default: - printk(KERN_WARNING "eicon_transmit: unsupported card-type!\n"); + eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n"); return; } @@ -457,16 +478,14 @@ eicon_io_transmit(eicon_card *ccard) { } restore_flags(flags); skb_queue_head(&ccard->sndq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: Card not ready\n"); + eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); return; } } else { if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) { restore_flags(flags); skb_queue_head(&ccard->sndq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: Card not ready\n"); + eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); return; } } @@ -479,8 +498,7 @@ eicon_io_transmit(eicon_card *ccard) { cli(); reqbuf = (eicon_REQ *)skb->data; if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) { - if (DebugVar & 16) - printk(KERN_WARNING "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); + eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); } else { if (scom) { ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length); @@ -495,7 +513,7 @@ eicon_io_transmit(eicon_card *ccard) { ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh); ram_outb(ccard, &ReqOut->Req, reqbuf->Req); } - + dlev = 160; if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */ if (!reqbuf->Reference) { /* Signal Layer */ @@ -517,6 +535,7 @@ eicon_io_transmit(eicon_card *ccard) { ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */ chan->waitq = reqbuf->XBuffer.length; chan->waitpq += reqbuf->XBuffer.length; + dlev = 128; } } @@ -544,13 +563,12 @@ eicon_io_transmit(eicon_card *ccard) { else ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); - chan->e.busy = 1; - if (DebugVar & 32) - printk(KERN_DEBUG "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", - reqbuf->Req, - ram_inb(ccard, &ReqOut->ReqId), - reqbuf->ReqCh, reqbuf->XBuffer.length, - chan->e.ref); + chan->e.busy = 1; + eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", + reqbuf->Req, + ram_inb(ccard, &ReqOut->ReqId), + reqbuf->ReqCh, reqbuf->XBuffer.length, + chan->e.ref); } restore_flags(flags); dev_kfree_skb(skb); @@ -559,8 +577,7 @@ eicon_io_transmit(eicon_card *ccard) { } else { skb_queue_tail(&ccard->sackq, skb2); - if (DebugVar & 32) - printk(KERN_INFO "eicon: transmit: busy chan %d\n", chan->No); + eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); } if (scom) @@ -601,10 +618,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned char *irqprobe = 0; int scom = 0; int tmp = 0; + int dlev = 0; if (!ccard) { - printk(KERN_WARNING "eicon_irq: spurious interrupt %d\n", irq); + eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq); return; } @@ -656,7 +674,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { prram = 0; break; default: - printk(KERN_WARNING "eicon_irq: unsupported card-type!\n"); + eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n"); return; } @@ -706,24 +724,21 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { case EICON_CTYPE_QUADRO: case EICON_CTYPE_S2M: if (!(readb(isa_card->intack))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; #endif case EICON_CTYPE_MAESTRAP: if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; case EICON_CTYPE_MAESTRA: outw(0x3fe, pci_card->PCIreg + M_ADDR); if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */ - if (DebugVar & 1) - printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n"); + eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); return; } break; @@ -735,8 +750,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { if ((tmp = ram_inb(ccard, &com->Rc))) { eicon_RC *ack; if (tmp == READY_INT) { - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=READY_INT\n"); + eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n"); if (ccard->ReadyInt) { ccard->ReadyInt--; ram_outb(ccard, &com->Rc, 0); @@ -744,17 +758,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { } else { skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); ack->Rc = tmp; ack->RcId = ram_inb(ccard, &com->RcId); ack->RcCh = ram_inb(ccard, &com->RcCh); ack->Reference = ccard->ref_in++; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - tmp,ack->RcId,ack->RcCh,ack->Reference); + eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", + tmp,ack->RcId,ack->RcCh,ack->Reference); skb_queue_tail(&ccard->rackq, skb); eicon_schedule_ack(ccard); } @@ -770,8 +782,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { int len = ram_inw(ccard, &com->RBuffer.length); skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); ind->Ind = tmp; @@ -779,9 +790,12 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { ind->IndCh = ram_inb(ccard, &com->IndCh); ind->MInd = ram_inb(ccard, &com->MInd); ind->MLength = ram_inw(ccard, &com->MLength); - ind->RBuffer.length = len; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + ind->RBuffer.length = len; + if ((tmp == 1) || (tmp == 8)) + dlev = 128; + else + dlev = 192; + eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len); skb_queue_tail(&ccard->rcvq, skb); @@ -804,17 +818,15 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { if((Rc=ram_inb(ccard, &RcIn->Rc))) { skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); ack->Rc = Rc; ack->RcId = ram_inb(ccard, &RcIn->RcId); ack->RcCh = ram_inb(ccard, &RcIn->RcCh); ack->Reference = ram_inw(ccard, &RcIn->Reference); - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - Rc,ack->RcId,ack->RcCh,ack->Reference); + eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", + Rc,ack->RcId,ack->RcCh,ack->Reference); skb_queue_tail(&ccard->rackq, skb); eicon_schedule_ack(ccard); } @@ -839,8 +851,7 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { int len = ram_inw(ccard, &IndIn->RBuffer.length); skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); if (!skb) { - if (DebugVar & 1) - printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n"); + eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); } else { ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); ind->Ind = Ind; @@ -849,8 +860,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { ind->MInd = ram_inb(ccard, &IndIn->MInd); ind->MLength = ram_inw(ccard, &IndIn->MLength); ind->RBuffer.length = len; - if (DebugVar & 64) - printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", + if ((Ind == 1) || (Ind == 8)) + dlev = 128; + else + dlev = 192; + eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len); skb_queue_tail(&ccard->rcvq, skb); diff --git a/drivers/isdn/eicon/eicon_isa.c b/drivers/isdn/eicon/eicon_isa.c index 75122559c..a89d18b12 100644 --- a/drivers/isdn/eicon/eicon_isa.c +++ b/drivers/isdn/eicon/eicon_isa.c @@ -1,9 +1,9 @@ -/* $Id: eicon_isa.c,v 1.7 1999/08/22 20:26:48 calle Exp $ +/* $Id: eicon_isa.c,v 1.9 1999/09/08 20:17:31 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * Hardware-specific code for old ISA cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -22,6 +22,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_isa.c,v $ + * Revision 1.9 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.8 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.7 1999/08/22 20:26:48 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -64,7 +70,9 @@ #define release_shmem release_region #define request_shmem request_region -char *eicon_isa_revision = "$Revision: 1.7 $"; +char *eicon_isa_revision = "$Revision: 1.9 $"; + +#undef EICON_MCA_DEBUG #ifdef CONFIG_ISDN_DRV_EICON_ISA @@ -107,7 +115,7 @@ eicon_isa_printpar(eicon_isa_card *card) { case EICON_CTYPE_SCOM: case EICON_CTYPE_QUADRO: case EICON_CTYPE_S2M: - printk(KERN_INFO "Eicon %s at 0x%lx, irq %d\n", + printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n", eicon_ctype_name[card->type], (unsigned long)card->shmem, card->irq); @@ -210,12 +218,30 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { return -EBUSY; } request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN"); +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize); +#endif card->mvalid = 1; /* clear any pending irq's */ readb(card->intack); +#ifdef CONFIG_MCA + if (card->type == EICON_CTYPE_SCOM) { + outb_p(0,card->io+1); + } + else { + printk(KERN_WARNING "eicon_isa_boot: Card type yet not supported.\n"); + return -EINVAL; + }; + +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: card->io = %x.\n", card->io); + printk(KERN_INFO "eicon_isa_boot: card->irq = %d.\n", (int)card->irq); +#endif +#else /* set reset-line active */ writeb(0, card->stopcpu); +#endif /* CONFIG_MCA */ /* clear irq-requests */ writeb(0, card->intack); readb(card->intack); @@ -242,7 +268,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { /* Start CPU */ writeb(cbuf.boot_opt, &boot->ctrl); +#ifdef CONFIG_MCA + outb_p(0, card->io); +#else writeb(0, card->startcpu); +#endif /* CONFIG_MCA */ /* Delay 0.2 sec. */ SLEEP(20); @@ -254,7 +284,11 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(10); } if (readb(&boot->ctrl) != 0) { - printk(KERN_WARNING "eicon_isa_boot: CPU test failed\n"); + printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n"); +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n", + readb(&boot->ctrl)); +#endif eicon_isa_release_shmem(card); return -EIO; } @@ -307,7 +341,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { return -EFAULT; if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); + printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n"); return -ENOMEM; } @@ -323,7 +357,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { /* Check for valid IRQ */ if ((card->irq < 0) || (card->irq > 15) || (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) { - printk(KERN_WARNING "eicon_isa_boot: illegal irq: %d\n", card->irq); + printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq); eicon_isa_release_shmem(card); kfree(code); return -EINVAL; @@ -332,7 +366,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card)) card->ivalid = 1; else { - printk(KERN_WARNING "eicon_isa_boot: irq %d already in use.\n", + printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n", card->irq); eicon_isa_release_shmem(card); kfree(code); @@ -343,7 +377,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { tmp = readb(&boot->msize); if (tmp != 8 && tmp != 16 && tmp != 24 && tmp != 32 && tmp != 48 && tmp != 60) { - printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); + printk(KERN_WARNING "eicon_isa_load: invalid memsize\n"); eicon_isa_release_shmem(card); return -EIO; } @@ -366,7 +400,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (readb(&boot->ctrl)) { - printk(KERN_WARNING "eicon_isa_boot: download timeout at 0x%x\n", p-code); + printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code); eicon_isa_release(card); kfree(code); return -EIO; @@ -389,7 +423,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (readw(&boot->signature) != 0x4447) { - printk(KERN_WARNING "eicon_isa_boot: firmware selftest failed %04x\n", + printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n", readw(&boot->signature)); eicon_isa_release(card); return -EIO; @@ -414,11 +448,15 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { SLEEP(2); } if (card->irqprobe == 1) { - printk(KERN_WARNING "eicon_isa_boot: IRQ test failed\n"); + printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq); eicon_isa_release(card); return -EIO; } } +#ifdef EICON_MCA_DEBUG + printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq); +#endif + writeb(card->irq, &card->shmem->com.Int); /* initializing some variables */ diff --git a/drivers/isdn/eicon/eicon_isa.h b/drivers/isdn/eicon/eicon_isa.h index 5b0dc1a6a..7f86bd9ff 100644 --- a/drivers/isdn/eicon/eicon_isa.h +++ b/drivers/isdn/eicon/eicon_isa.h @@ -1,8 +1,8 @@ -/* $Id: eicon_isa.h,v 1.3 1999/03/29 11:19:47 armin Exp $ +/* $Id: eicon_isa.h,v 1.5 1999/09/08 20:17:31 armin Exp $ * * ISDN low-level module for Eicon.Diehl active ISDN-Cards. * - * Copyright 1998 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -21,6 +21,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_isa.h,v $ + * Revision 1.5 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.4 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.3 1999/03/29 11:19:47 armin * I/O stuff now in seperate file (eicon_io.c) * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. @@ -106,6 +112,9 @@ typedef union { typedef struct { int ramsize; int irq; /* IRQ */ +#ifdef CONFIG_MCA + int io; /* IO-port for MCA brand */ +#endif /* CONFIG_MCA */ void* card; eicon_isa_shmem* shmem; /* Shared-memory area */ unsigned char* intack; /* Int-Acknowledge */ diff --git a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c index 1ac22aa80..2cad8a504 100644 --- a/drivers/isdn/eicon/eicon_mod.c +++ b/drivers/isdn/eicon/eicon_mod.c @@ -1,8 +1,8 @@ -/* $Id: eicon_mod.c,v 1.11 1999/08/29 17:23:45 armin Exp $ +/* $Id: eicon_mod.c,v 1.18 1999/10/11 18:13:25 armin Exp $ * * ISDN lowlevel-module for Eicon.Diehl active cards. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1998,99 by Armin Schindler (mac@melware.de) * Copyright 1999 Cytronics & Melware (info@melware.de) * @@ -11,6 +11,11 @@ * * Deutsche Telekom AG for S2M support. * + * Deutsche Mailbox Saar-Lor-Lux GmbH + * for sponsoring and testing fax + * capabilities with Diva Server cards. + * (dor@deutschemailbox.de) + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) @@ -26,6 +31,30 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: eicon_mod.c,v $ + * Revision 1.18 1999/10/11 18:13:25 armin + * Added fax capabilities for Eicon Diva Server cards. + * + * Revision 1.17 1999/10/08 22:09:34 armin + * Some fixes of cards interface handling. + * Bugfix of NULL pointer occurence. + * Changed a few log outputs. + * + * Revision 1.16 1999/09/26 14:17:53 armin + * Improved debug and log via readstat() + * + * Revision 1.15 1999/09/08 20:17:31 armin + * Added microchannel patch from Erik Weber. + * + * Revision 1.14 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.13 1999/09/04 17:37:59 armin + * Removed not used define, did not work and caused error + * in 2.3.16 + * + * Revision 1.12 1999/08/31 11:20:14 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.11 1999/08/29 17:23:45 armin * New setup compat. * Bugfix if compile as not module. @@ -82,7 +111,7 @@ #include <linux/init.h> #ifdef CONFIG_MCA #include <linux/mca.h> -#endif +#endif /* CONFIG_MCA */ #include "eicon.h" @@ -91,7 +120,7 @@ static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains start of card-list */ -static char *eicon_revision = "$Revision: 1.11 $"; +static char *eicon_revision = "$Revision: 1.18 $"; extern char *eicon_pci_revision; extern char *eicon_isa_revision; @@ -172,8 +201,7 @@ find_channel(eicon_card *card, int channel) { if ((channel >= 0) && (channel < card->nchannels)) return &(card->bch[channel]); - if (DebugVar & 1) - printk(KERN_WARNING "eicon: Invalid channel %d\n", channel); + eicon_log(card, 1, "eicon: Invalid channel %d\n", channel); return NULL; } @@ -239,87 +267,6 @@ eicon_find_eaz(eicon_card *card, char eaz) return("\0"); } -#if 0 -/* - * Add or delete an MSN to the MSN list - * - * First character of msneaz is EAZ, rest is MSN. - * If length of eazmsn is 1, delete that entry. - */ -static int -eicon_set_msn(eicon_card *card, char *eazmsn) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q = NULL; - unsigned long flags; - int i; - - if (!strlen(eazmsn)) - return 0; - if (strlen(eazmsn) > 16) - return -EINVAL; - for (i = 0; i < strlen(eazmsn); i++) - if (!isdigit(eazmsn[i])) - return -EINVAL; - if (strlen(eazmsn) == 1) { - /* Delete a single MSN */ - while (p) { - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - if (q) - q->next = p->next; - else - card->msn_list = p->next; - restore_flags(flags); - kfree(p); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping for EAZ %c deleted\n", - eazmsn[0]); - return 0; - } - q = p; - p = p->next; - } - return 0; - } - /* Add a single MSN */ - while (p) { - /* Found in list, replace MSN */ - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping for EAZ %c changed to %s\n", - eazmsn[0], - &eazmsn[1]); - return 0; - } - p = p->next; - } - /* Not found in list, add new entry */ - p = kmalloc(sizeof(msn_entry), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->eaz = eazmsn[0]; - strcpy(p->msn, &eazmsn[1]); - p->next = card->msn_list; - save_flags(flags); - cli(); - card->msn_list = p; - restore_flags(flags); - if (DebugVar & 8) - printk(KERN_DEBUG - "Mapping %c -> %s added\n", - eazmsn[0], - &eazmsn[1]); - return 0; -} -#endif static void eicon_rcv_dispatch(struct eicon_card *card) @@ -331,9 +278,8 @@ eicon_rcv_dispatch(struct eicon_card *card) eicon_io_rcv_dispatch(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); } } @@ -347,9 +293,8 @@ eicon_ack_dispatch(struct eicon_card *card) eicon_io_ack_dispatch(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); } } @@ -363,9 +308,8 @@ eicon_transmit(struct eicon_card *card) eicon_io_transmit(card); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_transmit: Illegal bustype %d\n", card->bus); + eicon_log(card, 1, + "eicon_transmit: Illegal bustype %d\n", card->bus); } } @@ -375,8 +319,7 @@ static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq) int ret_val; if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) { - if (DebugVar & 1) - printk(KERN_WARNING "idi_err: alloc_xlogreq_t failed\n"); + eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n"); return -ENOMEM; } if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) { @@ -406,9 +349,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) int ret = 0; unsigned long flags; - if (DebugVar & 16) - printk(KERN_WARNING "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n", - c->command, c->arg, (ulong) *c->parm.num); + eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n", + c->command, c->arg, (ulong) *c->parm.num); switch (c->command) { case ISDN_CMD_IOCTL: @@ -428,9 +370,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return card->hwif.pci.PCIram; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -440,17 +381,25 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return -EBUSY; switch (card->bus) { case EICON_BUS_ISA: - case EICON_BUS_MCA: if (eicon_isa_find_card(a, card->hwif.isa.irq, card->regname) < 0) return -EFAULT; card->hwif.isa.shmem = (eicon_isa_shmem *)a; return 0; + case EICON_BUS_MCA: +#if CONFIG_MCA + if (eicon_mca_find_card( + 0, a, + card->hwif.isa.irq, + card->regname) < 0) + return -EFAULT; + card->hwif.isa.shmem = (eicon_isa_shmem *)a; + return 0; +#endif /* CONFIG_MCA */ default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -465,9 +414,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return card->hwif.pci.irq; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -482,9 +430,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) card->hwif.isa.irq = a; return 0; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -500,9 +447,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) &(((eicon_codebuf *)a)->isa)); break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -534,9 +480,8 @@ eicon_command(eicon_card * card, isdn_ctrl * c) } break; default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon: Illegal BUS type %d\n", card->bus); ret = -ENODEV; } @@ -592,18 +537,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return ret; } else return -ENODEV; #endif -#if 0 - case EICON_IOCTL_SETMSN: - if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp)))) - return -EFAULT; - if ((ret = eicon_set_msn(card, tmp))) - return ret; -#if 0 - if (card->flags & EICON_FLAGS_RUNNING) - return(eicon_capi_manufacturer_req_msn(card)); -#endif - return 0; -#endif case EICON_IOCTL_ADDCARD: if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef)))) return -EFAULT; @@ -612,7 +545,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c) return 0; case EICON_IOCTL_DEBUGVAR: DebugVar = a; - printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar); + eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar); return 0; #ifdef MODULE case EICON_IOCTL_FREEIT: @@ -633,8 +566,7 @@ eicon_command(eicon_card * card, isdn_ctrl * c) cli(); if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { restore_flags(flags); - if (DebugVar & 1) - printk(KERN_WARNING "Dial on channel %d with state %d\n", + eicon_log(card, 1, "Dial on channel %d with state %d\n", chan->No, chan->fsm_state); return -EBUSY; } @@ -643,7 +575,6 @@ eicon_command(eicon_card * card, isdn_ctrl * c) else tmp[0] = c->parm.setup.eazmsn[0]; chan->fsm_state = EICON_STATE_OCALL; - chan->callref = 0xffff; restore_flags(flags); ret = idi_connect_req(card, chan, c->parm.setup.phone, @@ -738,20 +669,17 @@ eicon_command(eicon_card * card, isdn_ctrl * c) case ISDN_CMD_GETEAZ: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n"); + eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n"); return 0; case ISDN_CMD_SETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n"); + eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n"); return 0; case ISDN_CMD_GETSIL: if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - if (DebugVar & 1) - printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n"); + eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); return 0; case ISDN_CMD_LOCK: MOD_INC_USE_COUNT; @@ -817,36 +745,58 @@ if_command(isdn_ctrl * c) static int if_writecmd(const u_char * buf, int len, int user, int id, int channel) { -#if 0 - /* Not yet used */ - eicon_card *card = eicon_findcard(id); - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return (len); - return (len); - } - printk(KERN_ERR - "eicon: if_writecmd called with invalid driverId!\n"); -#endif return (len); } static int if_readstatus(u_char * buf, int len, int user, int id, int channel) { -#if 0 - /* Not yet used */ + int count = 0; + int cnt = 0; + ulong flags = 0; + u_char *p = buf; + struct sk_buff *skb; + eicon_card *card = eicon_findcard(id); if (card) { if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - return (eicon_readstatus(buf, len, user, card)); + + save_flags(flags); + cli(); + while((skb = skb_dequeue(&card->statq))) { + + if ((skb->len + count) > len) + cnt = len - count; + else + cnt = skb->len; + + if (user) + copy_to_user(p, skb->data, cnt); + else + memcpy(p, skb->data, cnt); + + count += cnt; + p += cnt; + + if (cnt == skb->len) { + dev_kfree_skb(skb); + if (card->statq_entries > 0) + card->statq_entries--; + } else { + skb_pull(skb, cnt); + skb_queue_head(&card->statq, skb); + restore_flags(flags); + return count; + } + } + card->statq_entries = 0; + restore_flags(flags); + return count; } printk(KERN_ERR "eicon: if_readstatus called with invalid driverId!\n"); -#endif return 0; } @@ -861,14 +811,11 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) len = skb->len; if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) { - dev_kfree_skb(skb); + if (!card->flags & EICON_FLAGS_RUNNING) return -ENODEV; - } - if (!(chan = find_channel(card, channel))) { - dev_kfree_skb(skb); + if (!(chan = find_channel(card, channel))) return -ENODEV; - } + if (chan->fsm_state == EICON_STATE_ACTIVE) { #ifdef CONFIG_ISDN_TTY_FAX if (chan->l2prot == ISDN_PROTO_L2_FAX) { @@ -880,16 +827,115 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) ret = idi_send_data(card, chan, ack, skb, 1); return (ret); } else { - dev_kfree_skb(skb); return -ENODEV; } } printk(KERN_ERR "eicon: if_sendbuf called with invalid driverId!\n"); - dev_kfree_skb(skb); return -ENODEV; } +/* jiftime() copied from HiSax */ +inline int +jiftime(char *s, long mark) +{ + s += 8; + + *s-- = '\0'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = '.'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 6 + '0'; + mark /= 6; + *s-- = ':'; + *s-- = mark % 10 + '0'; + mark /= 10; + *s-- = mark % 10 + '0'; + return(8); +} + +void +eicon_putstatus(eicon_card * card, char * buf) +{ + ulong flags; + int count; + isdn_ctrl cmd; + u_char *p; + struct sk_buff *skb; + + if (!card) + return; + + save_flags(flags); + cli(); + count = strlen(buf); + skb = alloc_skb(count, GFP_ATOMIC); + if (!skb) { + restore_flags(flags); + printk(KERN_ERR "eicon: could not alloc skb in putstatus\n"); + return; + } + p = skb_put(skb, count); + memcpy(p, buf, count); + + skb_queue_tail(&card->statq, skb); + + if (card->statq_entries >= MAX_STATUS_BUFFER) { + if ((skb = skb_dequeue(&card->statq))) { + count -= skb->len; + dev_kfree_skb(skb); + } else + count = 0; + } else + card->statq_entries++; + + restore_flags(flags); + if (count) { + cmd.command = ISDN_STAT_STAVAIL; + cmd.driver = card->myid; + cmd.arg = count; + card->interface.statcallb(&cmd); + } +} + +/* + * Debug and Log + */ +void +eicon_log(eicon_card * card, int level, const char *fmt, ...) +{ + va_list args; + char Line[160]; + u_char *p; + + + if ((DebugVar & level) || (DebugVar & 256)) { + va_start(args, fmt); + + if (DebugVar & level) { + if (DebugVar & 256) { + /* log-buffer */ + p = Line; + p += jiftime(p, jiffies); + *p++ = 32; + p += vsprintf(p, fmt, args); + *p = 0; + eicon_putstatus(card, Line); + } else { + /* printk, syslogd */ + vsprintf(Line, fmt, args); + printk(KERN_DEBUG "%s", Line); + } + } + + va_end(args); + } +} + /* * Allocate a new card-struct, initialize it @@ -912,7 +958,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) qloop = (Type == EICON_CTYPE_QUADRO)?2:0; for (i = 0; i <= qloop; i++) { if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { - printk(KERN_WARNING + eicon_log(card, 1, "eicon: (%s) Could not allocate card-struct.\n", id); return; } @@ -921,6 +967,8 @@ eicon_alloccard(int Type, int membase, int irq, char *id) skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->rackq); skb_queue_head_init(&card->sackq); + skb_queue_head_init(&card->statq); + card->statq_entries = 0; card->snd_tq.routine = (void *) (void *) eicon_transmit; card->snd_tq.data = card; card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch; @@ -992,7 +1040,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) p = p->next; } if (!p) { - printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n"); + eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n"); kfree(card); return; } @@ -1014,7 +1062,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | - /* ISDN_FEATURE_L2_FAX | */ + ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FAX; card->hwif.pci.card = (void *)card; @@ -1038,7 +1086,7 @@ eicon_alloccard(int Type, int membase, int irq, char *id) ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038 | ISDN_FEATURE_L2_MODEM | - /* ISDN_FEATURE_L2_FAX | */ + ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_TRANSDSP | ISDN_FEATURE_L3_FAX; card->hwif.pci.card = (void *)card; @@ -1087,13 +1135,13 @@ eicon_alloccard(int Type, int membase, int irq, char *id) break; #endif default: - printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type); + eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type); kfree(card); return; } if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1) , GFP_KERNEL))) { - printk(KERN_WARNING + eicon_log(card, 1, "eicon: (%s) Could not allocate bch-struct.\n", id); kfree(card); return; @@ -1131,7 +1179,7 @@ eicon_registercard(eicon_card * card) case EICON_BUS_MCA: eicon_isa_printpar(&card->hwif.isa); break; -#endif +#endif /* CONFIG_MCA */ #endif case EICON_BUS_PCI: #if CONFIG_PCI @@ -1139,9 +1187,8 @@ eicon_registercard(eicon_card * card) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon_registercard: Illegal BUS type %d\n", + eicon_log(card, 1, + "eicon_registercard: Illegal BUS type %d\n", card->bus); return -1; } @@ -1170,7 +1217,7 @@ unregister_card(eicon_card * card) case EICON_BUS_ISA: #ifdef CONFIG_MCA case EICON_BUS_MCA: -#endif +#endif /* CONFIG_MCA */ eicon_isa_release(&card->hwif.isa); break; #endif @@ -1180,9 +1227,8 @@ unregister_card(eicon_card * card) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: Invalid BUS type %d\n", + eicon_log(card, 1, + "eicon: Invalid BUS type %d\n", card->bus); break; } @@ -1191,6 +1237,26 @@ unregister_card(eicon_card * card) static void eicon_freecard(eicon_card *card) { + int i; + struct sk_buff *skb; + + for(i = 0; i < (card->nchannels + 1); i++) { + while((skb = skb_dequeue(&card->bch[i].e.X))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->bch[i].e.R))) + dev_kfree_skb(skb); + } + while((skb = skb_dequeue(&card->sndq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->rcvq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->rackq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->sackq))) + dev_kfree_skb(skb); + while((skb = skb_dequeue(&card->statq))) + dev_kfree_skb(skb); + eicon_clear_msn(card); kfree(card->bch); kfree(card); @@ -1236,9 +1302,8 @@ eicon_addcard(int Type, int membase, int irq, char *id) break; #endif default: - if (DebugVar & 1) - printk(KERN_WARNING - "eicon: addcard: Invalid BUS type %d\n", + printk(KERN_ERR + "eicon: addcard: Invalid BUS type %d\n", p->bus); } } else @@ -1250,7 +1315,7 @@ eicon_addcard(int Type, int membase, int irq, char *id) p = p->next; } else { /* registering failed, remove card from list, free memory */ - printk(KERN_WARNING + printk(KERN_ERR "eicon: Initialization of %s failed\n", p->interface.id); if (q) { @@ -1275,7 +1340,7 @@ eicon_addcard(int Type, int membase, int irq, char *id) #define eicon_init init_module #endif -int __init +int eicon_init(void) { int card_count = 0; @@ -1317,10 +1382,9 @@ eicon_init(void) printk(KERN_INFO "eicon: No MCA bus, ISDN-interfaces not probed.\n"); } else { - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_find_card, irq=%d.\n", - irq); + eicon_log(card, 8, + "eicon_mca_find_card, irq=%d.\n", + irq); if (!eicon_mca_find_card(0, membase, irq, id)) card_count++; }; @@ -1361,12 +1425,14 @@ cleanup_module(void) eicon_card *card = cards; eicon_card *last; while (card) { +#ifdef CONFIG_ISDN_DRV_EICON_ISA #ifdef CONFIG_MCA if (MCA_bus) { mca_mark_as_unused (card->mca_slot); mca_set_adapter_procfn(card->mca_slot, NULL, NULL); }; +#endif /* CONFIG_MCA */ #endif unregister_card(card); card = card->next; @@ -1382,7 +1448,6 @@ cleanup_module(void) #else /* no module */ -#ifdef COMPAT_HAS_NEW_SETUP static int __init eicon_setup(char *line) { @@ -1391,12 +1456,6 @@ eicon_setup(char *line) char *str; str = get_options(line, 4, ints); -#else -void __init -eicon_setup(char *str, int *ints) -{ - int i, argc; -#endif argc = ints[0]; i = 1; @@ -1424,13 +1483,9 @@ eicon_setup(char *str, int *ints) #else printk(KERN_INFO "Eicon ISDN active driver setup\n"); #endif -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("eicon=", eicon_setup); -#else -} -#endif #endif /* MODULE */ @@ -1456,10 +1511,9 @@ int eicon_mca_find_card(int type, /* type-idx of eicon-card */ { int j, curr_slot = 0; - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", - type, membase, irq); + eicon_log(card, 8, + "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", + type, membase, irq); /* find a no-driver-assigned eicon card */ for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) { @@ -1524,11 +1578,10 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ int irq_array1[]={3,4,0,0,2,10,11,12}; adf_pos0 = mca_read_stored_pos(slot,2); - if (DebugVar & 8) - printk(KERN_DEBUG - "eicon_mca_probe irq=%d, membase=%d\n", - irq, - membase); + eicon_log(card, 8, + "eicon_mca_probe irq=%d, membase=%d\n", + irq, + membase); switch (a_idx) { case 0: /* P/2-Adapter (== PRI/S2M ? ) */ cards_membase= 0xC0000+((adf_pos0>>4)*0x4000); @@ -1542,7 +1595,7 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ if (irq == -1) { irq = cards_irq; } else { - if (irq != irq) + if (irq != cards_irq) return ENODEV; }; cards_io= 0xC00 + ((adf_pos0>>4)*0x10); @@ -1575,7 +1628,7 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ if (irq == -1) { irq = cards_irq; } else { - if (irq != irq) + if (irq != cards_irq) return ENODEV; }; type = 0; @@ -1591,8 +1644,12 @@ int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ mca_mark_as_used(slot); cards->mca_slot = slot; /* card->io noch setzen oder ?? */ - if (DebugVar & 8) - printk("eicon_addcard: erfolgreich fuer slot: %d.\n", + cards->mca_io = cards_io; + cards->hwif.isa.io = cards_io; + /* reset card */ + outb_p(0,cards_io+1); + + eicon_log(card, 8, "eicon_addcard: successful for slot # %d.\n", cards->mca_slot+1); return 0 ; /* eicon_addcard hat eine Karte zugefuegt */ } else { diff --git a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c index c1919e9f8..5c96302cb 100644 --- a/drivers/isdn/eicon/eicon_pci.c +++ b/drivers/isdn/eicon/eicon_pci.c @@ -152,8 +152,8 @@ int eicon_pci_find_card(char *ID) aparms->type = EICON_CTYPE_MAESTRA; aparms->irq = pdev->irq; - preg = get_pcibase(pdev, 2) & 0xfffffffc; - pcfg = get_pcibase(pdev, 1) & 0xffffff80; + preg = pdev->resource[ 2].start & 0xfffffffc; + pcfg = pdev->resource[ 1].start & 0xffffff80; #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); @@ -174,9 +174,9 @@ int eicon_pci_find_card(char *ID) printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n"); aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/ aparms->irq = pdev->irq; - pram = get_pcibase(pdev, 0) & 0xfffff000; - preg = get_pcibase(pdev, 2) & 0xfffff000; - pcfg = get_pcibase(pdev, 4) & 0xfffff000; + pram = pdev->resource[ 0].start & 0xfffff000; + preg = pdev->resource[ 2].start & 0xfffff000; + pcfg = pdev->resource[ 4].start & 0xfffff000; #ifdef EICON_PCI_DEBUG printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile index 051df6182..e37d9c404 100644 --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -30,6 +30,8 @@ ISAR_OBJ := HFC_OBJ := HFC_2BDS0 := JADE_OBJ := +W6692_OBJ := + ifeq ($(CONFIG_HISAX_16_0),y) O_OBJS += teles0.o ISAC_OBJ := isac.o @@ -170,6 +172,10 @@ ifeq ($(CONFIG_HISAX_GAZEL),y) HSCX_OBJ := hscx.o endif +ifeq ($(CONFIG_HISAX_W6692),y) + W6692_OBJ := w6692.o +endif + # ifeq ($(CONFIG_HISAX_TESTEMU),y) # O_OBJS += testemu.o # endif @@ -179,7 +185,7 @@ ifeq ($(ISAC_OBJ), isac.o) endif O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ) -O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) +O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ) OX_OBJS += config.o O_TARGET := diff --git a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c index 7bcc8827c..2770aa65e 100644 --- a/drivers/isdn/hisax/amd7930.c +++ b/drivers/isdn/hisax/amd7930.c @@ -749,8 +749,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_amd7930(struct IsdnCard *card) +__initfunc(int +setup_amd7930(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c index 9e582641d..e8abc9de2 100644 --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -154,8 +154,6 @@ init_arcofi(struct IsdnCardState *cs) { cs->dc.isac.arcofitimer.function = (void *) arcofi_timer; cs->dc.isac.arcofitimer.data = (long) cs; init_timer(&cs->dc.isac.arcofitimer); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&cs->dc.isac.arcofi_wait); -#endif test_and_set_bit(HW_ARCOFI, &cs->HW_Flags); } diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c index 06d8b59d0..10657ad63 100644 --- a/drivers/isdn/hisax/asuscom.c +++ b/drivers/isdn/hisax/asuscom.c @@ -1,4 +1,4 @@ -/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $ +/* $Id: asuscom.c,v 1.8 1999/09/04 06:20:05 keil Exp $ * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * @@ -8,6 +8,9 @@ * * * $Log: asuscom.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/07/12 21:04:53 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -39,7 +42,7 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.7 $"; +const char *Asuscom_revision = "$Revision: 1.8 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -288,13 +291,13 @@ reset_asuscom(struct IsdnCardState *cs) byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == ASUS_IPAC) writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0); else byteout(cs->hw.asus.adr, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == ASUS_IPAC) { writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0); @@ -326,8 +329,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_asuscom(struct IsdnCard *card) +__initfunc(int +setup_asuscom(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c index f96db3675..55df36f0f 100644 --- a/drivers/isdn/hisax/avm_a1.c +++ b/drivers/isdn/hisax/avm_a1.c @@ -227,8 +227,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_avm_a1(struct IsdnCard *card) +__initfunc(int +setup_avm_a1(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c index 862829ab3..76382c372 100644 --- a/drivers/isdn/hisax/avm_a1p.c +++ b/drivers/isdn/hisax/avm_a1p.c @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $ +/* $Id: avm_a1p.c,v 2.5 1999/09/01 08:26:34 calle Exp $ * * avm_a1p.c low level stuff for the following AVM cards: * A1 PCMCIA @@ -8,6 +8,9 @@ * Author Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avm_a1p.c,v $ + * Revision 2.5 1999/09/01 08:26:34 calle + * Patch from Daniel Beichl <dani@ecomag.net> to make A1 PCMCIA work again. + * * Revision 2.4 1999/07/12 21:04:55 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -71,7 +74,7 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.4 $"; +static const char *avm_revision = "$Revision: 2.5 $"; static inline u_char ReadISAC(struct IsdnCardState *cs, u_char offset) @@ -245,6 +248,7 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return 0; case CARD_INIT: + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); clear_pending_isac_ints(cs); clear_pending_hscx_ints(cs); inithscxisac(cs, 1); @@ -262,8 +266,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return 0; } -int __init -setup_avm_a1_pcmcia(struct IsdnCard *card) +__initfunc(int +setup_avm_a1_pcmcia(struct IsdnCard *card)) { u_char model, vers; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index cd293f147..f343bfb5a 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.11 1999/08/11 21:01:18 keil Exp $ +/* $Id: avm_pci.c,v 1.12 1999/09/04 06:20:05 keil Exp $ * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations @@ -7,6 +7,9 @@ * * * $Log: avm_pci.c,v $ + * Revision 1.12 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.11 1999/08/11 21:01:18 keil * new PCI codefix * @@ -50,13 +53,10 @@ #include "isac.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.11 $"; +static const char *avm_pci_rev = "$Revision: 1.12 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -482,7 +482,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) { if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hdlc.count = 0; bcs->tx_skb = NULL; } @@ -609,7 +609,7 @@ close_hdlcstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -734,11 +734,11 @@ reset_avmpcipnp(struct IsdnCardState *cs) save_flags(flags); sti(); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); } @@ -773,14 +773,10 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_avm __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_avm_pcipnp(struct IsdnCard *card) +__initfunc(int +setup_avm_pcipnp(struct IsdnCard *card)) { u_int val, ver; struct IsdnCardState *cs = card->cs; @@ -796,7 +792,6 @@ setup_avm_pcipnp(struct IsdnCard *card) cs->subtyp = AVM_FRITZ_PNP; } else { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "FritzPCI: no PCI bus present\n"); return(0); @@ -808,7 +803,7 @@ setup_avm_pcipnp(struct IsdnCard *card) printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n"); return(0); } - cs->hw.avm.cfg_reg = get_pcibase(dev_avm, 1) & + cs->hw.avm.cfg_reg = dev_avm->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; if (!cs->hw.avm.cfg_reg) { printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); @@ -819,36 +814,6 @@ setup_avm_pcipnp(struct IsdnCard *card) printk(KERN_WARNING "FritzPCI: No PCI card found\n"); return(0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int ioaddr; - unsigned char irq; - - if (pcibios_find_device (PCI_VENDOR_AVM, - PCI_FRITZPCI_ID, pci_index, - &pci_bus, &pci_device_fn) != 0) { - continue; - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &ioaddr); - cs->irq = irq; - cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; - if (!cs->hw.avm.cfg_reg) { - printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); - return(0); - } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; #else printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c index 57d99b436..cb999972c 100644 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.7 1999/08/22 20:26:55 calle Exp $ +/* $Id: bkm_a4t.c,v 1.8 1999/09/04 06:20:05 keil Exp $ * bkm_a4t.c low level stuff for T-Berkom A4T * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -7,6 +7,9 @@ * Author Roland Klabunde (R.Klabunde@Berkom.de) * * $Log: bkm_a4t.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/08/22 20:26:55 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -42,13 +45,10 @@ #include "isdnl1.h" #include "bkm_ax.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *bkm_a4t_revision = "$Revision: 1.7 $"; +const char *bkm_a4t_revision = "$Revision: 1.8 $"; static inline u_char @@ -231,11 +231,11 @@ reset_bkm(struct IsdnCardState *cs) sti(); /* Issue the I20 soft reset */ pI20_Regs->i20SysControl = 0xFF; /* all in */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove the soft reset */ pI20_Regs->i20SysControl = sysRESET | 0xFF; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Set our configuration */ pI20_Regs->i20SysControl = sysRESET | sysCFG; @@ -246,14 +246,14 @@ reset_bkm(struct IsdnCardState *cs) g_A4T_ISAC_RES | g_A4T_JADE_BOOTR | g_A4T_ISAR_BOOTR; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove RESET state from ISDN */ pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | g_A4T_JADE_RES | g_A4T_ISAR_RES); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); restore_flags(flags); } @@ -288,23 +288,16 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_a4t __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init - setup_bkm_a4t(struct IsdnCard *card) +__initfunc(int + setup_bkm_a4t(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; u_int pci_memaddr = 0, found = 0; I20_REGISTER_FILE *pI20_Regs; #if CONFIG_PCI -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq = 0; -#endif #endif strcpy(tmp, bkm_a4t_revision); @@ -315,7 +308,6 @@ int __init return (0); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); return (0); @@ -327,40 +319,14 @@ int __init &sub_sys_id); if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { found = 1; - pci_memaddr = get_pcibase(dev_a4t, 0); + pci_memaddr = dev_a4t->resource[ 0].start; cs->irq = dev_a4t->irq; } } -#else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(I20_VENDOR_ID, - I20_DEVICE_ID, - pci_index, - &pci_bus, - &pci_device_fn) == PCIBIOS_SUCCESSFUL) { - u_int sub_sys_id = 0; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); - if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) { - found = 1; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - cs->irq = pci_irq; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - break; - } - } - } -#endif /* COMPAT_HAS_NEW_PCI */ if (!found) { printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); return (0); } -#ifndef COMPAT_HAS_NEW_PCI - pci_index++; -#endif if (!cs->irq) { /* IRQ range check ?? */ printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); return (0); diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index e32c4544a..fda6c213c 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.7 1999/08/22 20:26:58 calle Exp $ +/* $Id: bkm_a8.c,v 1.8 1999/09/04 06:20:05 keil Exp $ * bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive) * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -7,6 +7,9 @@ * Author Roland Klabunde (R.Klabunde@Berkom.de) * * $Log: bkm_a8.c,v $ + * Revision 1.8 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 1.7 1999/08/22 20:26:58 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -41,15 +44,12 @@ #include "isdnl1.h" #include "bkm_ax.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ extern const char *CardType[]; -const char sct_quadro_revision[] = "$Revision: 1.7 $"; +const char sct_quadro_revision[] = "$Revision: 1.8 $"; /* To survive the startup phase */ typedef struct { @@ -298,13 +298,13 @@ reset_bkm(struct IsdnCardState *cs) save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); /* Remove the soft reset */ wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10 * HZ) / 1000); restore_flags(flags); } @@ -341,14 +341,10 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_a8 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init - setup_sct_quadro(struct IsdnCard *card) +__initfunc(int + setup_sct_quadro(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -372,7 +368,6 @@ int __init printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n", CardType[card->typ]); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "bkm_a4t: no PCI bus present\n"); return (0); @@ -384,46 +379,18 @@ int __init &sub_sys_id); if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { found = 1; - pci_ioaddr1 = get_pcibase(dev_a8, 1); + pci_ioaddr1 = dev_a8->resource[ 1].start; pci_irq = dev_a8->irq; pci_bus = dev_a8->bus->number; pci_device_fn = dev_a8->devfn; } } -#else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device( - PLX_VENDOR_ID, - PLX_DEVICE_ID, - pci_index, - &pci_bus, - &pci_device_fn) == PCIBIOS_SUCCESSFUL) { - - u_int sub_sys_id = 0; - - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id); - if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) { - found = 1; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr1); - cs->irq = pci_irq; - break; - } - } - } -#endif /* COMPAT_HAS_NEW_PCI */ if (!found) { printk(KERN_WARNING "HiSax: %s (%s): Card not found\n", CardType[card->typ], sct_quadro_subtypes[cs->subtyp]); return (0); } -#ifndef COMPAT_HAS_NEW_PCI - pci_index++; /* need for more as one card */ -#endif if (!pci_irq) { /* IRQ range check ?? */ printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n", CardType[card->typ], @@ -445,9 +412,7 @@ int __init pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK; pcibios_write_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, pci_ioaddr1); -#ifdef COMPAT_HAS_NEW_PCI - get_pcibase(dev_a8, 1) = pci_ioaddr1; -#endif /* COMPAT_HAS_NEW_PCI */ + dev_a8->resource[ 1].start = pci_ioaddr1; } /* End HACK */ #endif diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c index ce0428a46..e4c26d9de 100644 --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.34 1999/08/25 20:02:34 werner Exp $ +/* $Id: callc.c,v 2.39 1999/10/14 20:25:28 keil Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,6 +11,21 @@ * Fritz Elfert * * $Log: callc.c,v $ + * Revision 2.39 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.38 1999/10/11 22:16:27 keil + * Suspend/Resume is possible without explicit ID too + * + * Revision 2.37 1999/09/20 19:49:47 keil + * Fix wrong init of PStack + * + * Revision 2.36 1999/09/20 12:13:13 keil + * Fix hang if no protocol was selected + * + * Revision 2.35 1999/09/04 06:20:05 keil + * Changes from kernel set_current_state() + * * Revision 2.34 1999/08/25 20:02:34 werner * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts * with existing software definitions. (PtP incomplete called party number) @@ -145,15 +160,10 @@ #include "../avmb1/capicmd.h" /* this should be moved in a common place */ #ifdef MODULE -#ifdef COMPAT_HAS_NEW_SYMTAB #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) -#else -extern long mod_use_count_; -#define MOD_USE_COUNT mod_use_count_ -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.34 $"; +const char *lli_revision = "$Revision: 2.39 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -209,7 +219,7 @@ discard_queue(struct sk_buff_head *q) int ret=0; while ((skb = skb_dequeue(q))) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); ret++; } return(ret); @@ -1122,12 +1132,37 @@ dchan_l3l4(struct PStack *st, int pr, void *arg) } static void +dummy_pstack(struct PStack *st, int pr, void *arg) { + printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg); +} + +static void +init_PStack(struct PStack **stp) { + *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); + (*stp)->next = NULL; + (*stp)->l1.l1l2 = dummy_pstack; + (*stp)->l1.l1hw = dummy_pstack; + (*stp)->l1.l1tei = dummy_pstack; + (*stp)->l2.l2tei = dummy_pstack; + (*stp)->l2.l2l1 = dummy_pstack; + (*stp)->l2.l2l3 = dummy_pstack; + (*stp)->l3.l3l2 = dummy_pstack; + (*stp)->l3.l3ml3 = dummy_pstack; + (*stp)->l3.l3l4 = dummy_pstack; + (*stp)->lli.l4l3 = dummy_pstack; + (*stp)->ma.layer = dummy_pstack; +} + +static void init_d_st(struct Channel *chanp) { - struct PStack *st = chanp->d_st; + struct PStack *st; struct IsdnCardState *cs = chanp->cs; char tmp[16]; + init_PStack(&chanp->d_st); + st = chanp->d_st; + st->next = NULL; HiSax_addlist(cs, st); setstack_HiSax(st, cs); st->l2.sap = 0; @@ -1166,28 +1201,6 @@ callc_debug(struct FsmInst *fi, char *fmt, ...) } static void -dummy_pstack(struct PStack *st, int pr, void *arg) { - printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg); -} - -static void -init_PStack(struct PStack **stp) { - *stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC); - (*stp)->next = NULL; - (*stp)->l1.l1l2 = dummy_pstack; - (*stp)->l1.l1hw = dummy_pstack; - (*stp)->l1.l1tei = dummy_pstack; - (*stp)->l2.l2tei = dummy_pstack; - (*stp)->l2.l2l1 = dummy_pstack; - (*stp)->l2.l2l3 = dummy_pstack; - (*stp)->l3.l3l2 = dummy_pstack; - (*stp)->l3.l3ml3 = dummy_pstack; - (*stp)->l3.l3l4 = dummy_pstack; - (*stp)->lli.l4l3 = dummy_pstack; - (*stp)->ma.layer = dummy_pstack; -} - -static void init_chan(int chan, struct IsdnCardState *csta) { struct Channel *chanp = csta->channel + chan; @@ -1209,10 +1222,6 @@ init_chan(int chan, struct IsdnCardState *csta) FsmInitTimer(&chanp->fi, &chanp->dial_timer); FsmInitTimer(&chanp->fi, &chanp->drel_timer); if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { - init_PStack(&chanp->d_st); - if (chan) - csta->channel->d_st->next = chanp->d_st; - chanp->d_st->next = NULL; init_d_st(chanp); } else { chanp->d_st = csta->channel->d_st; @@ -1289,7 +1298,7 @@ lldata_handler(struct PStack *st, int pr, void *arg) if (chanp->data_open) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } break; case (DL_ESTABLISH | INDICATION): @@ -1319,7 +1328,7 @@ lltrans_handler(struct PStack *st, int pr, void *arg) chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb); else { link_debug(chanp, 0, "channel not open"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } break; case (PH_ACTIVATE | INDICATION): @@ -1426,7 +1435,7 @@ leased_l4l3(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): link_debug(chanp, 0, "leased line d-channel DATA"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); break; case (DL_ESTABLISH | REQUEST): st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); @@ -1450,7 +1459,7 @@ leased_l1l2(struct PStack *st, int pr, void *arg) switch (pr) { case (PH_DATA | INDICATION): link_debug(chanp, 0, "leased line d-channel DATA"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): @@ -1475,11 +1484,6 @@ leased_l1l2(struct PStack *st, int pr, void *arg) } static void -channel_report(struct Channel *chanp) -{ -} - -static void distr_debug(struct IsdnCardState *csta, int debugflags) { int i; @@ -1512,7 +1516,6 @@ capi_debug(struct Channel *chanp, capi_msg *cm) { char *t = tmpbuf; - t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan); t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length); t--; *t= 0; @@ -1529,20 +1532,16 @@ lli_got_fac_req(struct Channel *chanp, capi_msg *cm) { return; switch(cm->para[3]) { case 4: /* Suspend */ - if (cm->para[5]) { - strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); - FsmEvent(&chanp->fi, EV_SUSPEND, cm); - } + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + FsmEvent(&chanp->fi, EV_SUSPEND, cm); break; case 5: /* Resume */ - if (cm->para[5]) { - strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); - if (chanp->fi.state == ST_NULL) { - FsmEvent(&chanp->fi, EV_RESUME, cm); - } else { - FsmDelTimer(&chanp->dial_timer, 72); - FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73); - } + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + if (chanp->fi.state == ST_NULL) { + FsmEvent(&chanp->fi, EV_RESUME, cm); + } else { + FsmDelTimer(&chanp->dial_timer, 72); + FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73); } break; } @@ -1694,9 +1693,8 @@ HiSax_command(isdn_ctrl * ic) case (ISDN_CMD_IOCTL): switch (ic->arg) { case (0): - HiSax_reportcard(csta->cardnr); - for (i = 0; i < 2; i++) - channel_report(&csta->channel[i]); + num = *(unsigned int *) ic->parm.num; + HiSax_reportcard(csta->cardnr, num); break; case (1): num = *(unsigned int *) ic->parm.num; @@ -1904,7 +1902,7 @@ HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb) chanp->bcs->tx_cnt += len; st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } - idev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb(skb); } else len = 0; restore_flags(flags); diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index dc0fa46a0..a75810f02 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -1,10 +1,32 @@ -/* $Id: config.c,v 2.33 1999/08/30 11:57:52 keil Exp $ +/* $Id: config.c,v 2.40 1999/10/30 13:09:45 keil Exp $ * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden * * * $Log: config.c,v $ + * Revision 2.40 1999/10/30 13:09:45 keil + * Version 3.3c + * + * Revision 2.39 1999/10/16 14:44:45 keil + * Fix module parm if only NICCY was selected + * + * Revision 2.38 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.37 1999/09/20 12:11:08 keil + * Fix hang if no protocol was selected + * + * Revision 2.36 1999/09/07 05:43:58 werner + * + * Added io as parameter 0 for HFC-PCI cards, if manual selection needed. + * + * Revision 2.35 1999/09/04 06:35:09 keil + * Winbond W6692 support + * + * Revision 2.34 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 2.33 1999/08/30 11:57:52 keil * Fix broken avm pcmcia * @@ -126,10 +148,7 @@ #include <linux/stddef.h> #include <linux/timer.h> #include <linux/config.h> -#include <linux/isdn_compat.h> -#ifdef COMPAT_HAS_NEW_SETUP #include <linux/init.h> -#endif #include "hisax.h" #include <linux/module.h> #include <linux/kernel_stat.h> @@ -182,6 +201,8 @@ * 33 Scitel Quadro p0=subcontroller (4*S0, subctrl 1...4) * 34 Gazel ISDN cards * 35 HFC 2BDS0 PCI none + * 36 Winbond 6692 PCI none + * * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1 * * @@ -195,7 +216,7 @@ const char *CardType[] = "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)", "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir", - "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", + "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692", }; void HiSax_closecard(int cardnr); @@ -204,15 +225,7 @@ void HiSax_closecard(int cardnr); #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} int elsa_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(elsa_init_pcmcia); -#else -static struct symbol_table hisax_syms_elsa = { -#include <linux/symtab_begin.h> - X(elsa_init_pcmcia), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_ELSA */ #ifdef CONFIG_HISAX_AVM_A1 @@ -228,17 +241,8 @@ static struct symbol_table hisax_syms_elsa = { #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA #define DEFAULT_CFG {11,0x170,0,0} int avm_a1_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(avm_a1_init_pcmcia); EXPORT_SYMBOL(HiSax_closecard); -#else -static struct symbol_table hisax_syms_avm_a1= { -#include <linux/symtab_begin.h> - X(avm_a1_init_pcmcia), - X(HiSax_closecard), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_AVM_A1_PCMCIA */ #ifdef CONFIG_HISAX_FRITZPCI @@ -310,15 +314,7 @@ static struct symbol_table hisax_syms_avm_a1= { #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER #define DEFAULT_CFG {11,0x270,0,0} int sedl_init_pcmcia(void*, int, int*, int); -#ifdef COMPAT_HAS_NEW_SYMTAB EXPORT_SYMBOL(sedl_init_pcmcia); -#else -static struct symbol_table hisax_syms_sedl= { -#include <linux/symtab_begin.h> - X(sedl_init_pcmcia), -#include <linux/symtab_end.h> -}; -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* CONFIG_HISAX_SEDLBAUER */ #ifdef CONFIG_HISAX_SPORTSTER @@ -406,6 +402,13 @@ static struct symbol_table hisax_syms_sedl= { #define DEFAULT_CFG {15,0x180,0,0} #endif +#ifdef CONFIG_HISAX_W6692 +#undef DEFAULT_CARD +#undef DEFAULT_CFG +#define DEFAULT_CARD ISDN_CTYPE_W6692 +#define DEFAULT_CFG {0,0,0,0} +#endif + #ifdef CONFIG_HISAX_1TR6 #define DEFAULT_PROTO ISDN_PTYPE_1TR6 #define DEFAULT_PROTO_NAME "1TR6" @@ -483,7 +486,6 @@ static int mem[] HISAX_INITDATA = {0, 0, 0, 0, 0, 0, 0, 0}; static char *id HISAX_INITDATA = HiSaxID; -#ifdef COMPAT_HAS_NEW_SYMTAB MODULE_AUTHOR("Karsten Keil"); MODULE_PARM(type, "1-8i"); MODULE_PARM(protocol, "1-8i"); @@ -491,11 +493,10 @@ MODULE_PARM(io, "1-8i"); MODULE_PARM(irq, "1-8i"); MODULE_PARM(mem, "1-8i"); MODULE_PARM(id, "s"); -#ifdef CONFIG_HISAX_16_3 /* For Creatix/Teles PnP */ +#ifdef IO0_IO1 MODULE_PARM(io0, "1-8i"); MODULE_PARM(io1, "1-8i"); -#endif /* CONFIG_HISAX_16_3 */ -#endif /* COMPAT_HAS_NEW_SYMTAB */ +#endif /* IO0_IO1 */ #endif /* MODULE */ int nrcards; @@ -528,9 +529,9 @@ HiSaxVersion(void)) printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n"); #ifdef MODULE - printk(KERN_INFO "HiSax: Version 3.3a (module)\n"); + printk(KERN_INFO "HiSax: Version 3.3c (module)\n"); #else - printk(KERN_INFO "HiSax: Version 3.3a (kernel)\n"); + printk(KERN_INFO "HiSax: Version 3.3c (kernel)\n"); #endif strcpy(tmp, l1_revision); printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp)); @@ -560,7 +561,6 @@ HiSax_mod_inc_use_count(void) #ifdef MODULE #define HiSax_init init_module #else -#ifdef COMPAT_HAS_NEW_SETUP #define MAX_ARG (HISAX_MAX_CARDS*5) static int __init HiSax_setup(char *line) @@ -570,12 +570,6 @@ HiSax_setup(char *line) char *str; str = get_options(line, MAX_ARG, ints); -#else -void __init -HiSax_setup(char *str, int *ints) -{ - int i, j, argc; -#endif argc = ints[0]; printk(KERN_DEBUG"HiSax_setup: argc(%d) str(%s)\n", argc, str); i = 0; @@ -615,14 +609,10 @@ HiSax_setup(char *str, int *ints) strcpy(HiSaxID, "HiSax"); HiSax_id = HiSaxID; } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("hisax=", HiSax_setup); -#else -} -#endif /* COMPAT_HAS_NEW_SETUP */ #endif /* MODULES */ #if CARD_TELES0 @@ -717,11 +707,11 @@ extern int setup_saphir(struct IsdnCard *card); extern int setup_testemu(struct IsdnCard *card); #endif -#if CARD_BKM_A4T +#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); #endif -#if CARD_SCT_QUADRO +#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); #endif @@ -729,6 +719,10 @@ extern int setup_sct_quadro(struct IsdnCard *card); extern int setup_gazel(struct IsdnCard *card); #endif +#if CARD_W6692 +extern int setup_w6692(struct IsdnCard *card); +#endif + /* * Find card with given driverId */ @@ -967,7 +961,7 @@ closecard(int cardnr) csta->rcvbuf = NULL; } if (csta->tx_skb) { - idev_kfree_skb(csta->tx_skb, FREE_WRITE); + dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; } if (csta->DC_Close != NULL) { @@ -1000,7 +994,7 @@ HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) while (cnt) { cs->cardmsg(cs, CARD_INIT, NULL); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); /* Timeout 10ms */ schedule_timeout((10*HZ)/1000); restore_flags(flags); @@ -1254,6 +1248,11 @@ checkcard(int cardnr, char *id, int *busy_flag)) ret = setup_gazel(card); break; #endif +#if CARD_W6692 + case ISDN_CTYPE_W6692: + ret = setup_w6692(card); + break; +#endif default: printk(KERN_WARNING "HiSax: Support for %s Card not selected\n", @@ -1357,6 +1356,7 @@ HiSax_inithardware(int *busy_flag)) kfree((void *) cards[i].cs); cards[i].cs = NULL; HiSax_shiftcards(i); + nrcards--; } } return foundcards; @@ -1387,12 +1387,9 @@ HiSax_closecard(int cardnr) } void -HiSax_reportcard(int cardnr) +HiSax_reportcard(int cardnr, int sel) { struct IsdnCardState *cs = cards[cardnr].cs; - struct PStack *stptr; - struct l3_process *pc; - int j, i = 1; printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1); printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]); @@ -1400,50 +1397,38 @@ HiSax_reportcard(int cardnr) printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n", (ulong) & HiSax_reportcard); printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs); - printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n", + printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc1 flg %x\n", cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag); printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n", cs->bcs[0].mode, cs->bcs[0].channel); printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n", cs->bcs[1].mode, cs->bcs[1].channel); - printk(KERN_DEBUG "HiSax: cs setstack_d 0x%lX\n", (ulong) cs->setstack_d); - printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist)); - stptr = cs->stlist; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp); - printk(KERN_DEBUG "HiSax: dst%d l1.l1hw 0x%lX\n", i, (ulong) stptr->l1.l1hw); - printk(KERN_DEBUG "HiSax: tei %d sapi %d\n", - stptr->l2.tei, stptr->l2.sap); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - pc = stptr->l3.proc; - while (pc) { - printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref, - (ulong) pc); - printk(KERN_DEBUG "HiSax: state %d st 0x%lX chan 0x%lX\n", - pc->state, (ulong) pc->st, (ulong) pc->chan); - pc = pc->next; - } - stptr = stptr->next; - i++; - } - for (j = 0; j < 2; j++) { - printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j, - (ulong) & cs->channel[j]); - stptr = cs->channel[j].b_st; - i = 1; - while (stptr != NULL) { - printk(KERN_DEBUG "HiSax: b_st%d 0x%lX\n", i, (ulong) stptr); - printk(KERN_DEBUG "HiSax: man 0x%lX\n", (ulong) stptr->ma.layer); - stptr = stptr->next; - i++; - } +#ifdef ERROR_STATISTIC + printk(KERN_DEBUG "HiSax: dc errors(rx,crc,tx) %d,%d,%d\n", + cs->err_rx, cs->err_crc, cs->err_tx); + printk(KERN_DEBUG "HiSax: bc0 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n", + cs->bcs[0].err_inv, cs->bcs[0].err_rdo, cs->bcs[0].err_crc, cs->bcs[0].err_tx); + printk(KERN_DEBUG "HiSax: bc1 errors(inv,rdo,crc,tx) %d,%d,%d,%d\n", + cs->bcs[1].err_inv, cs->bcs[1].err_rdo, cs->bcs[1].err_crc, cs->bcs[1].err_tx); + if (sel == 99) { + cs->err_rx = 0; + cs->err_crc = 0; + cs->err_tx = 0; + cs->bcs[0].err_inv = 0; + cs->bcs[0].err_rdo = 0; + cs->bcs[0].err_crc = 0; + cs->bcs[0].err_tx = 0; + cs->bcs[1].err_inv = 0; + cs->bcs[1].err_rdo = 0; + cs->bcs[1].err_crc = 0; + cs->bcs[1].err_tx = 0; } +#endif } -int __init -HiSax_init(void) +__initfunc(int +HiSax_init(void)) { int i; @@ -1452,27 +1437,18 @@ HiSax_init(void) #ifdef CONFIG_HISAX_ELSA if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) { /* we have exported and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_elsa); -#endif return 0; } #endif #ifdef CONFIG_HISAX_SEDLBAUER if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) { /* we have to export and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_sedl); -#endif return 0; } #endif #ifdef CONFIG_HISAX_AVM_A1_PCMCIA if (type[0] == ISDN_CTYPE_A1_PCMCIA) { /* we have to export and return in this case */ -#ifndef COMPAT_HAS_NEW_SYMTAB - register_symtab(&hisax_syms_avm_a1); -#endif return 0; } #endif @@ -1515,6 +1491,7 @@ HiSax_init(void) break; #endif case ISDN_CTYPE_ELSA: + case ISDN_CTYPE_HFC_PCI: cards[i].para[0] = io[i]; break; case ISDN_CTYPE_16_3: @@ -1550,6 +1527,7 @@ HiSax_init(void) case ISDN_CTYPE_NETJET: case ISDN_CTYPE_AMD7930: case ISDN_CTYPE_TELESPCI: + case ISDN_CTYPE_W6692: break; case ISDN_CTYPE_BKM_A4T: break; @@ -1582,11 +1560,6 @@ HiSax_init(void) if (HiSax_inithardware(NULL)) { /* Install only, if at least one card found */ #ifdef MODULE -#ifndef COMPAT_HAS_NEW_SYMTAB - /* No symbols to export, hide all symbols */ - register_symtab(NULL); - printk(KERN_INFO "HiSax: module installed\n"); -#endif /* COMPAT_HAS_NEW_SYMTAB */ #endif /* MODULE */ return (0); } else { @@ -1629,9 +1602,7 @@ int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 8 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ for (i = 0; i < HISAX_MAX_CARDS; i++) { @@ -1680,9 +1651,7 @@ int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 8 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ for (i = 0; i < HISAX_MAX_CARDS; i++) { @@ -1731,12 +1700,10 @@ int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) nrcards = 0; HiSaxVersion(); - if (id) /* If id= string used */ - HiSax_id = id; - /* Initialize all 16 structs, even though we only accept + /* Initialize all structs, even though we only accept two pcmcia cards */ - for (i = 0; i < 16; i++) { + for (i = 0; i < HISAX_MAX_CARDS; i++) { cards[i].para[0] = irq[i]; cards[i].para[1] = io[i]; cards[i].typ = type[i]; diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 8ec1a536c..f1161e63d 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.16 1999/08/11 21:01:25 keil Exp $ +/* $Id: diva.c,v 1.17 1999/09/04 06:20:06 keil Exp $ * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -12,6 +12,9 @@ * * * $Log: diva.c,v $ + * Revision 1.17 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.16 1999/08/11 21:01:25 keil * new PCI codefix * @@ -74,13 +77,10 @@ #include "ipac.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.16 $"; +const char *Diva_revision = "$Revision: 1.17 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -550,7 +550,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "HSCX: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -566,7 +565,6 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -583,7 +581,7 @@ Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } @@ -752,30 +750,30 @@ reset_diva(struct IsdnCardState *cs) sti(); if (cs->subtyp == DIVA_IPAC_ISA) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); } else if (cs->subtyp == DIVA_IPAC_PCI) { unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + PITA_MISC_REG); *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); *ireg = PITA_PARA_MPX_MODE; - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); } else { /* DIVA 2.0 */ cs->hw.diva.ctrl_reg = 0; /* Reset On */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->subtyp == DIVA_ISA) cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; @@ -880,16 +878,12 @@ Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_diva(struct IsdnCard *card) +__initfunc(int +setup_diva(struct IsdnCard *card)) { int bytecnt; u_char val; @@ -927,7 +921,6 @@ setup_diva(struct IsdnCard *card) bytecnt = 8; } else { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Diva: no PCI bus present\n"); return(0); @@ -938,23 +931,23 @@ setup_diva(struct IsdnCard *card) PCI_DIVA20_ID, dev_diva))) { cs->subtyp = DIVA_PCI; cs->irq = dev_diva->irq; - cs->hw.diva.cfg_reg = get_pcibase(dev_diva, 2) + cs->hw.diva.cfg_reg = dev_diva->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA20_U_ID, dev_diva_u))) { cs->subtyp = DIVA_PCI; cs->irq = dev_diva_u->irq; - cs->hw.diva.cfg_reg = get_pcibase(dev_diva_u, 2) + cs->hw.diva.cfg_reg = dev_diva_u->resource[ 2].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL, PCI_DIVA_201, dev_diva201))) { cs->subtyp = DIVA_IPAC_PCI; cs->irq = dev_diva201->irq; cs->hw.diva.pci_cfg = - (ulong) ioremap((get_pcibase(dev_diva201, 0) + (ulong) ioremap((dev_diva201->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK), 4096); cs->hw.diva.cfg_reg = - (ulong) ioremap((get_pcibase(dev_diva201, 1) + (ulong) ioremap((dev_diva201->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK), 4096); } else { printk(KERN_WARNING "Diva: No PCI card found\n"); @@ -970,66 +963,6 @@ setup_diva(struct IsdnCard *card) printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); return(0); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_PCI; - else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA20_U_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_PCI; - else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL, - PCI_DIVA_201, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = DIVA_IPAC_PCI; - else - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - if (cs->subtyp == DIVA_IPAC_PCI) { - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - cs->hw.diva.pci_cfg = (ulong) ioremap(pci_ioaddr, - 4096); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - cs->hw.diva.cfg_reg = (ulong) ioremap(pci_ioaddr, - 4096); - } else { - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - cs->hw.diva.pci_cfg = pci_ioaddr & ~3; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr); - cs->hw.diva.cfg_reg = pci_ioaddr & ~3; - } - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Diva: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); - return(0); - } - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; #else printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c index c2d6cf2d3..4dbe40c38 100644 --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.18 1999/08/25 16:50:54 keil Exp $ +/* $Id: elsa.c,v 2.19 1999/09/04 06:20:06 keil Exp $ * elsa.c low level stuff for Elsa isdn cards * @@ -14,6 +14,9 @@ * for ELSA PCMCIA support * * $Log: elsa.c,v $ + * Revision 2.19 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 2.18 1999/08/25 16:50:54 keil * Fix bugs which cause 2.3.14 hangs (waitqueue init) * @@ -91,15 +94,12 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/serial.h> #include <linux/serial_reg.h> extern const char *CardType[]; -const char *Elsa_revision = "$Revision: 2.18 $"; +const char *Elsa_revision = "$Revision: 2.19 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI", @@ -578,10 +578,10 @@ reset_elsa(struct IsdnCardState *cs) save_flags(flags); sti(); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); @@ -785,7 +785,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) cs->hw.elsa.status |= ELSA_TIMER_AKTIV; byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); byteout(cs->hw.elsa.timer, 0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((110*HZ)/1000); restore_flags(flags); cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; @@ -928,12 +928,8 @@ probe_elsa(struct IsdnCardState *cs) return (CARD_portlist[i]); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_qs1000 __initdata = NULL; static struct pci_dev *dev_qs3000 __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif int setup_elsa(struct IsdnCard *card) @@ -1051,7 +1047,6 @@ setup_elsa(struct IsdnCard *card) cs->irq); } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Elsa: no PCI bus present\n"); return(0); @@ -1061,17 +1056,17 @@ setup_elsa(struct IsdnCard *card) dev_qs1000))) { cs->subtyp = ELSA_QS1000PCI; cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = get_pcibase(dev_qs1000, 1) & + cs->hw.elsa.cfg = dev_qs1000->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = get_pcibase(dev_qs1000, 3) & + cs->hw.elsa.base = dev_qs1000->resource[ 3].start & PCI_BASE_ADDRESS_IO_MASK; } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS3000_ID, dev_qs3000))) { cs->subtyp = ELSA_QS3000PCI; cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = get_pcibase(dev_qs3000, 1) & + cs->hw.elsa.cfg = dev_qs3000->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; - cs->hw.elsa.base = get_pcibase(dev_qs3000, 3) & + cs->hw.elsa.base = dev_qs3000->resource[ 3].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); @@ -1096,54 +1091,6 @@ setup_elsa(struct IsdnCard *card) HZDELAY(500); /* wait 500*10 ms */ restore_flags(flags); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_ELSA, - PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = ELSA_QS1000PCI; - else if (pcibios_find_device(PCI_VENDOR_ELSA, - PCI_QS3000_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = ELSA_QS3000PCI; - else - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.elsa.cfg = pci_ioaddr; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_3, &pci_ioaddr); - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Elsa: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); - return(0); - } - - if (!pci_ioaddr) { - printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); - return(0); - } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->hw.elsa.base = pci_ioaddr; - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->hw.elsa.ale = cs->hw.elsa.base; cs->hw.elsa.isac = cs->hw.elsa.base +1; cs->hw.elsa.hscx = cs->hw.elsa.base +1; diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c index e4b35e502..529a74815 100644 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -298,7 +298,7 @@ modem_fill(struct BCState *bcs) { (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } } @@ -389,74 +389,6 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done) } } -#if 0 -static inline void check_modem_status(struct IsdnCardState *cs) -{ - int status; - struct async_struct *info = cs->hw.elsa.info; - struct async_icount *icount; - - status = serial_inp(info, UART_MSR); - - if (status & UART_MSR_ANY_DELTA) { - icount = &info->state->icount; - /* update input line counters */ - if (status & UART_MSR_TERI) - icount->rng++; - if (status & UART_MSR_DDSR) - icount->dsr++; - if (status & UART_MSR_DDCD) { - icount->dcd++; - } - if (status & UART_MSR_DCTS) - icount->cts++; -// wake_up_interruptible(&info->delta_msr_wait); - } - - if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttys%d CD now %s...", info->line, - (status & UART_MSR_DCD) ? "on" : "off"); -#endif - if (status & UART_MSR_DCD) -// wake_up_interruptible(&info->open_wait); -; - else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && - (info->flags & ASYNC_CALLOUT_NOHUP))) { -#ifdef SERIAL_DEBUG_OPEN - printk("doing serial hangup..."); -#endif - if (info->tty) - tty_hangup(info->tty); - } - } -#if 0 - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { - if (status & UART_MSR_CTS) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx start..."); -#endif - info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - serial_outp(info, UART_IER, info->IER); -// rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - return; - } - } else { - if (!(status & UART_MSR_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx stop..."); -#endif - info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - serial_outp(info, UART_IER, info->IER); - } - } - } -#endif 0 -} -#endif static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) { @@ -510,13 +442,13 @@ close_elsastate(struct BCState *bcs) bcs->hw.hscx.rcvbuf = NULL; } while ((skb = skb_dequeue(&bcs->rqueue))) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } while ((skb = skb_dequeue(&bcs->squeue))) { - idev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb(skb); } if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c index ef64a4702..c104253c7 100644 --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -37,9 +37,6 @@ #include "isdnl1.h" #include "ipac.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *gazel_revision = "$Revision: 2.6 $"; @@ -573,11 +570,7 @@ setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) return (0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_tel __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif static int setup_gazelpci(struct IsdnCardState *cs) @@ -589,42 +582,19 @@ setup_gazelpci(struct IsdnCardState *cs) printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); found = 0; -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_WARNING "Gazel: No PCI bus present\n"); return 1; } -#endif seekcard = GAZEL_R685; for (nbseek = 0; nbseek < 3; nbseek++) { -#ifdef COMPAT_HAS_NEW_PCI if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) { pci_irq = dev_tel->irq; - pci_ioaddr0 = get_pcibase(dev_tel, 1); - pci_ioaddr1 = get_pcibase(dev_tel, 2); + pci_ioaddr0 = dev_tel->resource[ 1].start; + pci_ioaddr1 = dev_tel->resource[ 2].start; found = 1; } -#else - for (; pci_index < 0xff; pci_index++) { - u_char pci_bus, pci_device_fn; - - if (pcibios_find_device(GAZEL_MANUFACTURER, seekcard, - pci_index, &pci_bus, &pci_device_fn) - != PCIBIOS_SUCCESSFUL) - break; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr0); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_2, &pci_ioaddr1); - found = 1; - break; - } -#endif /* COMPAT_HAS_NEW_PCI */ if (found) break; else { @@ -636,9 +606,6 @@ setup_gazelpci(struct IsdnCardState *cs) seekcard = GAZEL_DJINN_ITOO; break; } -#ifndef COMPAT_HAS_NEW_PCI - pci_index = 0; -#endif } } if (!found) { @@ -690,8 +657,8 @@ setup_gazelpci(struct IsdnCardState *cs) return (0); } -int __init - setup_gazel(struct IsdnCard *card) +__initfunc(int + setup_gazel(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c index 266916c39..bb388c5c2 100644 --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.10 1999/10/14 20:25:28 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -6,6 +6,9 @@ * * * $Log: hfc_2bds0.c,v $ + * Revision 1.10 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.9 1999/07/01 08:11:35 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -260,6 +263,9 @@ static struct sk_buff if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfc_empty_fifo: incoming packet too small"); cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif cli(); while ((idx++ < count) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); @@ -267,7 +273,6 @@ static struct sk_buff } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { - SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel); @@ -285,7 +290,7 @@ static struct sk_buff sti(); debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; } else { cli(); @@ -301,8 +306,11 @@ static struct sk_buff bcs->channel, chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif } } } @@ -390,7 +398,7 @@ hfc_fill_fifo(struct BCState *bcs) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } WaitForBusy(cs); @@ -592,7 +600,7 @@ close_2bs0(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -634,17 +642,6 @@ hfcd_bh(struct IsdnCardState *cs) */ if (!cs) return; -#if 0 - if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy cleared"); - stptr = cs->stlist; - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); - stptr = stptr->next; - } - } -#endif if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { switch (cs->dc.hfcd.ph_state) { case (0): @@ -737,7 +734,6 @@ int receive_dmsg(struct IsdnCardState *cs) while ((idx++ < rcnt) && WaitNoBusy(cs)) ReadReg(cs, HFCD_DATA_NODEB, cip); } else if ((skb = dev_alloc_skb(rcnt - 3))) { - SET_SKB_FREE(skb); ptr = skb_put(skb, rcnt - 3); while (idx < (rcnt - 3)) { cli(); @@ -752,8 +748,11 @@ int receive_dmsg(struct IsdnCardState *cs) sti(); debugl1(cs, "RFIFO D BUSY error"); printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + cs->err_rx++; +#endif } else { cli(); WaitNoBusy(cs); @@ -768,8 +767,11 @@ int receive_dmsg(struct IsdnCardState *cs) chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + cs->err_crc++; +#endif } else { skb_queue_tail(&cs->rq, skb); sched_event_D(cs, D_RCVBUFREADY); @@ -865,7 +867,7 @@ hfc_fill_dfifo(struct IsdnCardState *cs) cli(); WaitNoBusy(cs); ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND); - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; sti(); WaitForBusy(cs); @@ -999,7 +1001,7 @@ hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) } goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -1114,32 +1116,6 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg) cs->hw.hfcD.mst_m |= HFCD_MASTER; cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); break; -#if 0 - case (HW_TESTLOOP | REQUEST): - u_char val = 0; - if (1 & (int) arg) - val |= 0x0c; - if (2 & (int) arg) - val |= 0x3; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - if (!val) { - cs->writeisac(cs, ISAC_SPCR, 0xa); - cs->writeisac(cs, ISAC_ADF1, 0x2); - } else { - cs->writeisac(cs, ISAC_SPCR, val); - cs->writeisac(cs, ISAC_ADF1, 0xa); - } - } else { - /* IOM 2 Mode */ - cs->writeisac(cs, ISAC_SPCR, val); - if (val) - cs->writeisac(cs, ISAC_ADF1, 0x8); - else - cs->writeisac(cs, ISAC_ADF1, 0x0); - } - break; -#endif default: if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcd_l1hw unknown pr %4x", pr); @@ -1156,24 +1132,10 @@ setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) static void hfc_dbusy_timer(struct IsdnCardState *cs) { -#if 0 - struct PStack *stptr; - if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy"); - test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); - stptr = cs->stlist; - - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); - stptr = stptr->next; - } - } -#endif } -unsigned int * __init -init_send_hfcd(int cnt) +__initfunc(unsigned int +*init_send_hfcd(int cnt)) { int i, *send; @@ -1187,8 +1149,8 @@ init_send_hfcd(int cnt) return(send); } -void __init -init2bds0(struct IsdnCardState *cs) +__initfunc(void +init2bds0(struct IsdnCardState *cs)) { cs->setstack_d = setstack_hfcd; cs->dbusytimer.function = (void *) hfc_dbusy_timer; diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c index 71767c888..6620b90ec 100644 --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $ +/* $Id: hfc_2bs0.c,v 1.10 1999/10/14 20:25:28 keil Exp $ * specific routines for CCD's HFC 2BS0 * @@ -6,6 +6,9 @@ * * * $Log: hfc_2bs0.c,v $ + * Revision 1.10 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.9 1999/07/01 08:11:36 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -217,12 +220,14 @@ hfc_empty_fifo(struct BCState *bcs, int count) stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif return (NULL); } if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFC: receive out of memory\n"); else { - SET_SKB_FREE(skb); ptr = skb_put(skb, count - 3); idx = 0; cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); @@ -233,7 +238,7 @@ hfc_empty_fifo(struct BCState *bcs, int count) if (idx != count - 3) { debugl1(cs, "RFIFO BUSY error"); printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); @@ -251,8 +256,11 @@ hfc_empty_fifo(struct BCState *bcs, int count) bcs->channel, chksum, stat); if (stat) { debugl1(cs, "FIFO CRC error"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); skb = NULL; +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif } WaitNoBusy(cs); stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | @@ -325,7 +333,7 @@ hfc_fill_fifo(struct BCState *bcs) bcs->tx_cnt -= count; if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; WaitForBusy(cs); WaitNoBusy(cs); @@ -523,7 +531,7 @@ close_hfcstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -559,8 +567,8 @@ setstack_hfc(struct PStack *st, struct BCState *bcs) return (0); } -void __init -init_send(struct BCState *bcs) +__initfunc(void +init_send(struct BCState *bcs)) { int i; @@ -573,8 +581,8 @@ init_send(struct BCState *bcs) bcs->hw.hfc.send[i] = 0x1fff; } -void __init -inithfc(struct IsdnCardState *cs) +__initfunc(void +inithfc(struct IsdnCardState *cs)) { init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 9d8968e98..518c1670a 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.18 1999/08/29 17:05:44 werner Exp $ +/* $Id: hfc_pci.c,v 1.23 1999/11/07 17:01:55 keil Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -23,6 +23,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: hfc_pci.c,v $ + * Revision 1.23 1999/11/07 17:01:55 keil + * fix for 2.3 pci structs + * + * Revision 1.22 1999/10/10 20:14:27 werner + * + * Correct B2-chan usage in conjuntion with echo mode. First implementation of NT-leased line mode. + * + * Revision 1.21 1999/10/02 17:47:49 werner + * + * Changed init order, added correction for page alignment with shared mem + * + * Revision 1.20 1999/09/07 06:18:55 werner + * + * Added io parameter for HFC-PCI based cards. Needed only with multiple cards + * when initialisation/selection order needs to be set. + * + * Revision 1.19 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.18 1999/08/29 17:05:44 werner * corrected tx_lo line setup. Datasheet is not correct. * @@ -91,40 +110,40 @@ #include "hfc_pci.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.18 $"; +static const char *hfcpci_revision = "$Revision: 1.23 $"; /* table entry in the PCI devices list */ typedef struct { - int vendor_id; - int device_id; - char *vendor_name; - char *card_name; - } PCI_ENTRY; - -static const PCI_ENTRY id_list[] = { - {0x1397,0x2BD0,"CCD/Billion/Asuscom","2BD0"}, - {0x1397,0xB000,"Billion","B000"}, - {0x1397,0xB006,"Billion","B006"}, - {0x1397,0xB007,"Billion","B007"}, - {0x1397,0xB008,"Billion","B008"}, - {0x1397,0xB009,"Billion","B009"}, - {0x1397,0xB00A,"Billion","B00A"}, - {0x1397,0xB00B,"Billion","B00B"}, - {0x1397,0xB00C,"Billion","B00C"}, - {0x1043,0x0675,"Asuscom/Askey","675"}, - {0x0871,0xFFA2,"German telekom","T-Concept"}, - {0x0871,0xFFA1,"German telekom","A1T"}, - {0x1051,0x0100,"Motorola MC145575","MC145575"}, - {0x1397,0xB100,"Seyeon","B100"}, - {0x15B0,0x2BD0,"Zoltrix","2BD0"}, - {0,0,NULL,NULL}, + int vendor_id; + int device_id; + char *vendor_name; + char *card_name; +} PCI_ENTRY; + +#define NT_T1_COUNT 20 /* number of 3.125ms interrupts for G2 timeout */ + +static const PCI_ENTRY id_list[] = +{ + {0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"}, + {0x1397, 0xB000, "Billion", "B000"}, + {0x1397, 0xB006, "Billion", "B006"}, + {0x1397, 0xB007, "Billion", "B007"}, + {0x1397, 0xB008, "Billion", "B008"}, + {0x1397, 0xB009, "Billion", "B009"}, + {0x1397, 0xB00A, "Billion", "B00A"}, + {0x1397, 0xB00B, "Billion", "B00B"}, + {0x1397, 0xB00C, "Billion", "B00C"}, + {0x1043, 0x0675, "Asuscom/Askey", "675"}, + {0x0871, 0xFFA2, "German telekom", "T-Concept"}, + {0x0871, 0xFFA1, "German telekom", "A1T"}, + {0x1051, 0x0100, "Motorola MC145575", "MC145575"}, + {0x1397, 0xB100, "Seyeon", "B100"}, + {0x15B0, 0x2BD0, "Zoltrix", "2BD0"}, + {0, 0, NULL, NULL}, }; @@ -151,9 +170,21 @@ releasehfcpci(struct IsdnCardState *cs) void release_io_hfcpci(struct IsdnCardState *cs) { + int flags; + + save_flags(flags); + cli(); + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + restore_flags(flags); + Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ + sti(); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ #if CONFIG_PCI - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disabe memory mapped ports + busmaster */ -#endif /* CONFIG_PCI */ + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ +#endif /* CONFIG_PCI */ releasehfcpci(cs); del_timer(&cs->hw.hfcpci.timer); kfree(cs->hw.hfcpci.share_start); @@ -170,16 +201,20 @@ reset_hfcpci(struct IsdnCardState *cs) { long flags; + save_flags(flags); + cli(); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + printk(KERN_INFO "HFC_PCI: resetting card\n"); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ if (Read_hfc(cs, HFCPCI_STATUS) & 2) printk(KERN_WARNING "HFC-PCI init bit busy\n"); @@ -187,25 +222,23 @@ reset_hfcpci(struct IsdnCardState *cs) cs->hw.hfcpci.fifo_en = 0x30; /* only D fifos enabled */ Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */ + cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK; /* no echo connect , threshold */ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); Write_hfc(cs, HFCPCI_CLKDEL, 0x0e); /* ST-Bit delay for TE-Mode */ cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE; Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); /* S/T Auto awake */ - cs->hw.hfcpci.bswapped = 0; /* no exchange */ + cs->hw.hfcpci.bswapped = 0; /* no exchange */ + cs->hw.hfcpci.nt_mode = 0; /* we are in TE mode */ cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); - cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; - cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | - HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER; + cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | + HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); /* Clear already pending ints */ if (Read_hfc(cs, HFCPCI_INT_S1)); - if (Read_hfc(cs, HFCPCI_INT_S2)); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2); /* HFC ST 2 */ udelay(10); @@ -213,24 +246,29 @@ reset_hfcpci(struct IsdnCardState *cs) cs->hw.hfcpci.mst_m = HFCPCI_MASTER; /* HFC Master Mode */ Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); - cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */ + cs->hw.hfcpci.sctrl = 0x40; /* set tx_lo mode, error in datasheet ! */ Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); cs->hw.hfcpci.sctrl_r = 0; Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); - /* Init GCI/IOM2 in master mode */ + /* Init GCI/IOM2 in master mode */ /* Slots 0 and 1 are set for B-chan 1 and 2 */ /* D- and monitor/CI channel are not enabled */ /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ - /* STIO2 is used as data input, B1+B2 from IOM->ST */ + /* STIO2 is used as data input, B1+B2 from IOM->ST */ /* ST B-channel send disabled -> continous 1s */ /* The IOM slots are always enabled */ - cs->hw.hfcpci.conn = 0x36; /* set data flow directions */ + cs->hw.hfcpci.conn = 0x36; /* set data flow directions */ Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); - Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */ - Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */ - Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */ - Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */ + Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* B1-Slot 0 STIO1 out enabled */ + Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* B2-Slot 1 STIO1 out enabled */ + Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* B1-Slot 0 STIO2 in enabled */ + Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* B2-Slot 1 STIO2 in enabled */ + + /* Finally enable IRQ output */ + cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + if (Read_hfc(cs, HFCPCI_INT_S2)); restore_flags(flags); } @@ -317,12 +355,11 @@ hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int cou } else if (!(skb = dev_alloc_skb(count - 3))) printk(KERN_WARNING "HFCPCI: receive out of memory\n"); else { - SET_SKB_FREE(skb); total = count; count -= 3; ptr = skb_put(skb, count); - if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) + if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) maxlen = count; /* complete transfer */ else maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ @@ -381,7 +418,6 @@ receive_dmsg(struct IsdnCardState *cs) df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1); } else if ((skb = dev_alloc_skb(rcnt - 3))) { - SET_SKB_FREE(skb); total = rcnt; rcnt -= 3; ptr = skb_put(skb, rcnt); @@ -415,55 +451,56 @@ receive_dmsg(struct IsdnCardState *cs) /*******************************************************************************/ /* check for transparent receive data and read max one threshold size if avail */ /*******************************************************************************/ -int hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata) -{ unsigned short *z1r, *z2r; - int new_z2, fcnt, maxlen; - struct sk_buff *skb; - u_char *ptr, *ptr1; +int +hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata) +{ + unsigned short *z1r, *z2r; + int new_z2, fcnt, maxlen; + struct sk_buff *skb; + u_char *ptr, *ptr1; - z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ - z2r = z1r + 1; + z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ + z2r = z1r + 1; - if (!(fcnt = *z1r - *z2r)) - return(0); /* no data avail */ + if (!(fcnt = *z1r - *z2r)) + return (0); /* no data avail */ - if (fcnt <= 0) - fcnt += B_FIFO_SIZE; /* bytes actually buffered */ - if (fcnt > HFCPCI_BTRANS_THRESHOLD) - fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ + if (fcnt <= 0) + fcnt += B_FIFO_SIZE; /* bytes actually buffered */ + if (fcnt > HFCPCI_BTRANS_THRESHOLD) + fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ - new_z2 = *z2r + fcnt; /* new position in fifo */ - if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_z2 = *z2r + fcnt; /* new position in fifo */ + if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ - if (!(skb = dev_alloc_skb(fcnt))) + if (!(skb = dev_alloc_skb(fcnt))) printk(KERN_WARNING "HFCPCI: receive out of memory\n"); - else { - SET_SKB_FREE(skb); - ptr = skb_put(skb, fcnt); - if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) - maxlen = fcnt; /* complete transfer */ - else - maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ - - ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ - memcpy(ptr, ptr1, maxlen); /* copy data */ - fcnt -= maxlen; - - if (fcnt) { /* rest remaining */ - ptr += maxlen; - ptr1 = bdata; /* start of buffer */ - memcpy(ptr, ptr1, fcnt); /* rest */ - } - cli(); - skb_queue_tail(&bcs->rqueue, skb); - sti(); - hfcpci_sched_event(bcs, B_RCVBUFREADY); - } - - *z2r = new_z2; /* new position */ - return(1); -} /* hfcpci_empty_fifo_trans */ + else { + ptr = skb_put(skb, fcnt); + if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) + maxlen = fcnt; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ + + ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + fcnt -= maxlen; + + if (fcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, fcnt); /* rest */ + } + cli(); + skb_queue_tail(&bcs->rqueue, skb); + sti(); + hfcpci_sched_event(bcs, B_RCVBUFREADY); + } + + *z2r = new_z2; /* new position */ + return (1); +} /* hfcpci_empty_fifo_trans */ /**********************************/ /* B-channel main receive routine */ @@ -524,11 +561,10 @@ main_rec_hfcpci(struct BCState *bcs) receive = 1; else receive = 0; - } else - if (bcs->mode == L1_MODE_TRANS) - receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); - else - receive = 0; + } else if (bcs->mode == L1_MODE_TRANS) + receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); + else + receive = 0; test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; @@ -603,7 +639,7 @@ hfcpci_fill_dfifo(struct IsdnCardState *cs) df->f1 = new_f1; /* next frame */ restore_flags(flags); - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; return; } @@ -620,7 +656,7 @@ hfcpci_fill_fifo(struct BCState *bcs) bzfifo_type *bz; u_char *bdata; u_char new_f1, *src, *dst; - unsigned short *z1t, *z2t; + unsigned short *z1t, *z2t; if (!bcs->tx_skb) return; @@ -639,57 +675,53 @@ hfcpci_fill_fifo(struct BCState *bcs) } if (bcs->mode == L1_MODE_TRANS) { - z1t = &bz->za[MAX_B_FRAMES].z1; - z2t = z1t + 1; - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", - bcs->channel, *z1t, *z2t); - fcnt = *z2t - *z1t; - if (fcnt <= 0) - fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ - fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ - - while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { - if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { - /* data is suitable for fifo */ - count = bcs->tx_skb->len; - - new_z1 = *z1t + count; /* new buffer Position */ - if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z1 -= B_FIFO_SIZE; /* buffer wrap */ - src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (*z1t - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ - if (maxlen > count) - maxlen = count; /* limit size */ - memcpy(dst, src, maxlen); /* first copy */ - - count -= maxlen; /* remaining bytes */ - if (count) { - dst = bdata; /* start of buffer */ - src += maxlen; /* new position */ - memcpy(dst, src, count); - } - bcs->tx_cnt -= bcs->tx_skb->len; - fcnt += bcs->tx_skb->len; - *z1t = new_z1; /* now send data */ - } - else - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", - bcs->channel, bcs->tx_skb->len); - - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); - cli(); - bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ - sti(); - } - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - restore_flags(flags); - return; + z1t = &bz->za[MAX_B_FRAMES].z1; + z2t = z1t + 1; + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", + bcs->channel, *z1t, *z2t); + fcnt = *z2t - *z1t; + if (fcnt <= 0) + fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ + fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ + + while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { + if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { + /* data is suitable for fifo */ + count = bcs->tx_skb->len; + + new_z1 = *z1t + count; /* new buffer Position */ + if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) + new_z1 -= B_FIFO_SIZE; /* buffer wrap */ + src = bcs->tx_skb->data; /* source pointer */ + dst = bdata + (*z1t - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ + if (maxlen > count) + maxlen = count; /* limit size */ + memcpy(dst, src, maxlen); /* first copy */ + + count -= maxlen; /* remaining bytes */ + if (count) { + dst = bdata; /* start of buffer */ + src += maxlen; /* new position */ + memcpy(dst, src, count); + } + bcs->tx_cnt -= bcs->tx_skb->len; + fcnt += bcs->tx_skb->len; + *z1t = new_z1; /* now send data */ + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", + bcs->channel, bcs->tx_skb->len); + + dev_kfree_skb(bcs->tx_skb); + cli(); + bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ + sti(); + } + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + restore_flags(flags); + return; } - - if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)", bcs->channel, bz->f1, bz->f2, @@ -749,57 +781,113 @@ hfcpci_fill_fifo(struct BCState *bcs) bz->f1 = new_f1; /* next frame */ restore_flags(flags); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } +/**********************************************/ +/* D-channel l1 state call for leased NT-mode */ +/**********************************************/ +static void +dch_nt_l2l1(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + + switch (pr) { + case (PH_DATA | REQUEST): + case (PH_PULL | REQUEST): + case (PH_PULL | INDICATION): + st->l1.l1hw(st, pr, arg); + break; + case (PH_ACTIVATE | REQUEST): + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); + break; + case (PH_TESTLOOP | REQUEST): + if (1 & (long) arg) + debugl1(cs, "PH_TEST_LOOP B1"); + if (2 & (long) arg) + debugl1(cs, "PH_TEST_LOOP B2"); + if (!(3 & (long) arg)) + debugl1(cs, "PH_TEST_LOOP DISABLED"); + st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg); + break; + default: + if (cs->debug) + debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr); + break; + } +} + + + /***********************/ /* set/reset echo mode */ -/***********************/ +/***********************/ static int -hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) +hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int flags; - int i = *(unsigned int *) ic->parm.num; - - if (cs->chanlimit > 1) - return(-EINVAL); - - save_flags(flags); - cli(); - if (i) { - cs->logecho = 1; - cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ - cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; - } - else { - cs->logecho = 0; - cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */ - cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; - cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; - } - cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ - cs->hw.hfcpci.ctmt &= ~2; - Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); - Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); - Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); - Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); - Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); - Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - restore_flags(flags); - return(0); -} /* hfcpci_auxcmd */ + int flags; + int i = *(unsigned int *) ic->parm.num; + + if ((ic->arg == 98) && + (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) { + save_flags(flags); + cli(); + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ + udelay(10); + cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT; + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); /* set NT-mode */ + udelay(10); + Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1); /* HFC ST G1 */ + udelay(10); + Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + cs->dc.hfcpci.ph_state = 1; + cs->hw.hfcpci.nt_mode = 1; + cs->hw.hfcpci.nt_timer = 0; + cs->stlist->l2.l2l1 = dch_nt_l2l1; + restore_flags(flags); + debugl1(cs, "NT mode activated"); + return (0); + } + if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) || + (cs->hw.hfcpci.nt_mode) || (ic->arg != 12)) + return (-EINVAL); + + save_flags(flags); + cli(); + if (i) { + cs->logecho = 1; + cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ + cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX; + } else { + cs->logecho = 0; + cs->hw.hfcpci.trm &= ~0x20; /* disable echo chan */ + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC; + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX; + } + cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; + cs->hw.hfcpci.conn |= 0x10; /* B2-IOM -> B2-ST */ + cs->hw.hfcpci.ctmt &= ~2; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); + Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); + Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + restore_flags(flags); + return (0); +} /* hfcpci_auxcmd */ /*****************************/ /* E-channel receive routine */ /*****************************/ -static void receive_emsg(struct IsdnCardState *cs) +static void +receive_emsg(struct IsdnCardState *cs) { long flags; int rcnt; @@ -836,55 +924,54 @@ static void receive_emsg(struct IsdnCardState *cs) if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", zp->z1, zp->z2, rcnt); - new_z2 = zp->z2 + rcnt; /* new position in fifo */ + new_z2 = zp->z2 + rcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) - new_z2 -= B_FIFO_SIZE; /* buffer wrap */ + new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; - if ((rcnt > 256 + 3) || (count < 4) || + if ((rcnt > 256 + 3) || (count < 4) || (*(bdata + (zp->z1 - B_SUB_VAL)))) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); - bz->za[new_f2].z2 = new_z2; - bz->f2 = new_f2; /* next buffer */ + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ } else { - total = rcnt; - rcnt -= 3; - ptr = e_buffer; - - if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) - maxlen = rcnt; /* complete transfer */ - else - maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ + total = rcnt; + rcnt -= 3; + ptr = e_buffer; - ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ - memcpy(ptr, ptr1, maxlen); /* copy data */ - rcnt -= maxlen; + if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) + maxlen = rcnt; /* complete transfer */ + else + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - if (rcnt) { /* rest remaining */ - ptr += maxlen; - ptr1 = bdata; /* start of buffer */ - memcpy(ptr, ptr1, rcnt); /* rest */ - } - bz->za[new_f2].z2 = new_z2; - bz->f2 = new_f2; /* next buffer */ - if (cs->debug & DEB_DLOG_HEX) { - ptr = cs->dlog; - if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { - *ptr++ = 'E'; - *ptr++ = 'C'; - *ptr++ = 'H'; - *ptr++ = 'O'; - *ptr++ = ':'; - ptr += QuickHex(ptr, e_buffer, total - 3); - ptr--; - *ptr++ = '\n'; - *ptr = 0; - HiSax_putstatus(cs, NULL, cs->dlog); - } else - HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); - } + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ + memcpy(ptr, ptr1, maxlen); /* copy data */ + rcnt -= maxlen; - } + if (rcnt) { /* rest remaining */ + ptr += maxlen; + ptr1 = bdata; /* start of buffer */ + memcpy(ptr, ptr1, rcnt); /* rest */ + } + bz->za[new_f2].z2 = new_z2; + bz->f2 = new_f2; /* next buffer */ + if (cs->debug & DEB_DLOG_HEX) { + ptr = cs->dlog; + if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) { + *ptr++ = 'E'; + *ptr++ = 'C'; + *ptr++ = 'H'; + *ptr++ = 'O'; + *ptr++ = ':'; + ptr += QuickHex(ptr, e_buffer, total - 3); + ptr--; + *ptr++ = '\n'; + *ptr = 0; + HiSax_putstatus(cs, NULL, cs->dlog); + } else + HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3); + } + } rcnt = bz->f1 - bz->f2; if (rcnt < 0) @@ -900,7 +987,7 @@ static void receive_emsg(struct IsdnCardState *cs) goto Begin; restore_flags(flags); return; -} /* receive_emsg */ +} /* receive_emsg */ /*********************/ /* Interrupt handler */ @@ -919,6 +1006,9 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n"); return; } + if (!(cs->hw.hfcpci.int_m2 & 0x08)) + return; /* not initialised */ + if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { val = Read_hfc(cs, HFCPCI_INT_S1); if (cs->debug & L1_DEB_ISAC) @@ -931,7 +1021,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? "locked" : "unlocked"); val &= cs->hw.hfcpci.int_m1; - if (val & 0x40) { /* TE state machine irq */ + if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, @@ -940,6 +1030,14 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) sched_event_D_pci(cs, D_L1STATECHANGE); val &= ~0x40; } + if (val & 0x80) { /* timer irq */ + if (cs->hw.hfcpci.nt_mode) { + if ((--cs->hw.hfcpci.nt_timer) < 0) + sched_event_D_pci(cs, D_L1STATECHANGE); + } + val &= ~0x80; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + } while (val) { save_flags(flags); cli(); @@ -954,24 +1052,23 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) cs->hw.hfcpci.int_s1 = exval; } if (val & 0x08) { - if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x08 IRQ"); } else main_rec_hfcpci(bcs); } - if (val & 0x10) { - if (cs->logecho) - receive_emsg(cs); - else - if (!(bcs = Sel_BCS(cs, 1))) { + if (val & 0x10) { + if (cs->logecho) + receive_emsg(cs); + else if (!(bcs = Sel_BCS(cs, 1))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x10 IRQ"); } else main_rec_hfcpci(bcs); } if (val & 0x01) { - if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) { + if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) { if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { @@ -1036,7 +1133,7 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) } goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -1070,20 +1167,6 @@ hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) static void hfcpci_dbusy_timer(struct IsdnCardState *cs) { -#if 0 - struct PStack *stptr; - if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy"); - test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); - stptr = cs->stlist; - - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); - stptr = stptr->next; - } - } -#endif } /*************************************/ @@ -1094,6 +1177,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + int flags; switch (pr) { case (PH_DATA | REQUEST): @@ -1169,39 +1253,46 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg) Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); break; case (HW_DEACTIVATE | REQUEST): - cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; + cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); break; case (HW_INFO3 | REQUEST): cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); break; -#if 0 case (HW_TESTLOOP | REQUEST): - u_char val = 0; - if (1 & (int) arg) - val |= 0x0c; - if (2 & (int) arg) - val |= 0x3; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - if (!val) { - cs->writeisac(cs, ISAC_SPCR, 0xa); - cs->writeisac(cs, ISAC_ADF1, 0x2); - } else { - cs->writeisac(cs, ISAC_SPCR, val); - cs->writeisac(cs, ISAC_ADF1, 0xa); - } - } else { - /* IOM 2 Mode */ - cs->writeisac(cs, ISAC_SPCR, val); - if (val) - cs->writeisac(cs, ISAC_ADF1, 0x8); - else - cs->writeisac(cs, ISAC_ADF1, 0x0); + switch ((int) arg) { + case (1): + Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ + Write_hfc(cs, HFCPCI_B1_RSL, 0x80); /* rx slot */ + save_flags(flags); + cli(); + cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1; + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); + break; + + case (2): + Write_hfc(cs, HFCPCI_B2_SSL, 0x81); /* tx slot */ + Write_hfc(cs, HFCPCI_B2_RSL, 0x81); /* rx slot */ + save_flags(flags); + cli(); + cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08; + Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); + break; + + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); + return; } + save_flags(flags); + cli(); + cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ + Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + restore_flags(flags); break; -#endif default: if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr); @@ -1241,113 +1332,127 @@ mode_hfcpci(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; bzfifo_type *bzr, *bzt; - int flags; + int flags, fifo2; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d", mode, bc, bcs->channel); bcs->mode = mode; bcs->channel = bc; - if (cs->chanlimit > 1) { - cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ - cs->hw.hfcpci.sctrl_e &= ~0x80; - } - else { - if (bc) { - cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ - cs->hw.hfcpci.sctrl_e |= 0x80; - bc = 0; /* B1 controller used */ - } - else { - cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ - cs->hw.hfcpci.sctrl_e &= ~0x80; - } - } + fifo2 = bc; save_flags(flags); cli(); + if (cs->chanlimit > 1) { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } else { + if (bc) { + if (mode != L1_MODE_NULL) { + cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */ + cs->hw.hfcpci.sctrl_e |= 0x80; + } else { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + fifo2 = 0; + } else { + cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */ + cs->hw.hfcpci.sctrl_e &= ~0x80; + } + } switch (mode) { case (L1_MODE_NULL): if (bc) { cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); } else { cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + } else { cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; case (L1_MODE_TRANS): if (bc) { - cs->hw.hfcpci.ctmt |= 2; - cs->hw.hfcpci.conn &= ~0x18; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); - bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; - bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; } else { - cs->hw.hfcpci.ctmt |= 1; - cs->hw.hfcpci.conn &= ~0x03; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + cs->hw.hfcpci.ctmt |= 2; + cs->hw.hfcpci.conn &= ~0x18; + bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; + bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2; + } else { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); - bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; - bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); + cs->hw.hfcpci.ctmt |= 1; + cs->hw.hfcpci.conn &= ~0x03; + bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1; + bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1; } bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; - bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; + bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; bzr->f1 = MAX_B_FRAMES; - bzr->f2 = bzr->f1; /* init F pointers to remain constant */ + bzr->f2 = bzr->f1; /* init F pointers to remain constant */ bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; - bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; + bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; bzt->f1 = MAX_B_FRAMES; - bzt->f2 = bzt->f1; /* init F pointers to remain constant */ + bzt->f2 = bzt->f1; /* init F pointers to remain constant */ break; case (L1_MODE_HDLC): if (bc) { - cs->hw.hfcpci.ctmt &= ~2; - cs->hw.hfcpci.conn &= ~0x18; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; - cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); } else { - cs->hw.hfcpci.ctmt &= ~1; - cs->hw.hfcpci.conn &= ~0x3; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; + } + if (fifo2) { + cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2; + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); + cs->hw.hfcpci.ctmt &= ~2; + cs->hw.hfcpci.conn &= ~0x18; + } else { cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); + cs->hw.hfcpci.ctmt &= ~1; + cs->hw.hfcpci.conn &= ~0x03; } break; case (L1_MODE_EXTRN): if (bc) { - cs->hw.hfcpci.conn |= 0x10; + cs->hw.hfcpci.conn |= 0x10; cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); } else { - cs->hw.hfcpci.conn |= 0x02; + cs->hw.hfcpci.conn |= 0x02; cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA; cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA; cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1; - cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC); + cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); } break; } + Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - restore_flags(flags); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl); Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r); Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt); Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn); + restore_flags(flags); } /******************************/ @@ -1420,7 +1525,7 @@ close_hfcpci(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -1467,40 +1572,72 @@ setstack_2b(struct PStack *st, struct BCState *bcs) static void hfcpci_bh(struct IsdnCardState *cs) { + int flags; /* struct PStack *stptr; */ if (!cs) return; -#if 0 - if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { - if (cs->debug) - debugl1(cs, "D-Channel Busy cleared"); - stptr = cs->stlist; - while (stptr != NULL) { - stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); - stptr = stptr->next; - } - } -#endif if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { - switch (cs->dc.hfcpci.ph_state) { - case (0): - l1_msg(cs, HW_RESET | INDICATION, NULL); - break; - case (3): - l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); - break; - case (8): - l1_msg(cs, HW_RSYNC | INDICATION, NULL); - break; - case (6): - l1_msg(cs, HW_INFO2 | INDICATION, NULL); - break; - case (7): - l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); - break; - default: - break; + if (!cs->hw.hfcpci.nt_mode) + switch (cs->dc.hfcpci.ph_state) { + case (0): + l1_msg(cs, HW_RESET | INDICATION, NULL); + break; + case (3): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + case (8): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + case (6): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + case (7): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + default: + break; + } else { + switch (cs->dc.hfcpci.ph_state) { + case (2): + save_flags(flags); + cli(); + if (cs->hw.hfcpci.nt_timer < 0) { + cs->hw.hfcpci.nt_timer = 0; + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* Clear already pending ints */ + if (Read_hfc(cs, HFCPCI_INT_S1)); + + Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); + udelay(10); + Write_hfc(cs, HFCPCI_STATES, 4); + cs->dc.hfcpci.ph_state = 4; + } else { + cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER; + cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125; + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); + cs->hw.hfcpci.nt_timer = NT_T1_COUNT; + Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3); /* allow G2 -> G3 transition */ + } + restore_flags(flags); + break; + case (1): + case (3): + case (4): + save_flags(flags); + cli(); + cs->hw.hfcpci.nt_timer = 0; + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + restore_flags(flags); + break; + default: + break; + } } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) @@ -1513,8 +1650,8 @@ hfcpci_bh(struct IsdnCardState *cs) /*************************************/ /* Alloc memory send data for queues */ /*************************************/ -unsigned int * __init - init_send_hfcpci(int cnt) +__initfunc(unsigned int + *init_send_hfcpci(int cnt)) { int i, *send; @@ -1531,18 +1668,14 @@ unsigned int * __init /********************************/ /* called for card init message */ /********************************/ -void __init - inithfcpci(struct IsdnCardState *cs) +__initfunc(void + inithfcpci(struct IsdnCardState *cs)) { cs->setstack_d = setstack_hfcpci; cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; cs->dbusytimer.data = (long) cs; init_timer(&cs->dbusytimer); cs->tqueue.routine = (void *) (void *) hfcpci_bh; -#if 0 - if (!cs->hw.hfcpci.send) - cs->hw.hfcpci.send = init_send_hfcpci(16); -#endif if (!cs->bcs[0].hw.hfc.send) cs->bcs[0].hw.hfc.send = init_send_hfcpci(32); if (!cs->bcs[1].hw.hfc.send) @@ -1579,7 +1712,7 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) inithfcpci(cs); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ /* now switch timer interrupt off */ cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; @@ -1596,52 +1729,49 @@ hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) /* this variable is used as card index when more than one cards are present */ -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_hfcpci __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif #endif /* CONFIG_PCI */ -int __init - setup_hfcpci(struct IsdnCard *card) +__initfunc(int + setup_hfcpci(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; + unsigned short cmd; char tmp[64]; int i; -#ifdef COMPAT_HAS_NEW_PCI - struct pci_dev *tmp_hfcpci = NULL; -#endif + struct pci_dev *tmp_hfcpci = NULL; strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); #if CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; -#if 0 - cs->hw.hfcpci.send = NULL; -#endif cs->bcs[0].hw.hfc.send = NULL; cs->bcs[1].hw.hfc.send = NULL; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; if (cs->typ == ISDN_CTYPE_HFC_PCI) { -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "HFC-PCI: no PCI bus present\n"); return (0); } i = 0; - while (id_list[i].vendor_id) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - if (tmp_hfcpci) break; - i++; - } - + while (id_list[i].vendor_id) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + i++; + if (tmp_hfcpci) { + if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + continue; + else + break; + } + } + if (tmp_hfcpci) { - dev_hfcpci = tmp_hfcpci; /* old device */ + i--; + dev_hfcpci = tmp_hfcpci; /* old device */ cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number; cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn; cs->irq = dev_hfcpci->irq; @@ -1649,43 +1779,45 @@ int __init printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); return (0); } - cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name); + cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); } else { printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); return (0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char irq; - - i = 0; - while (id_list[i].vendor_id) { - if (pcibios_find_device(id_list[i].vendor_id, - id_list[i].device_id, pci_index, - &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0) - break; - i++; - } - if (!id_list[i].vendor_id) - continue; - - pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - cs->irq = irq; - + if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { + printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n"); + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, + PCI_COMMAND, + 0x0103); /* set SERR */ + pcibios_read_config_word(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, + PCI_COMMAND, + &cmd); + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, + PCI_COMMAND, + cmd & ~2); + (int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1); + pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, + PCI_BASE_ADDRESS_1, + (int) cs->hw.hfcpci.pci_io); + pcibios_write_config_word(cs->hw.hfcpci.pci_bus, + cs->hw.hfcpci.pci_device_fn, + PCI_COMMAND, + cmd); pcibios_read_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1, - (void *) &cs->hw.hfcpci.pci_io); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name); - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "HFC-PCI: No card found\n"); - return (0); + cs->hw.hfcpci.pci_device_fn, + PCI_BASE_ADDRESS_1, + (void *) &cs->hw.hfcpci.pci_io); + if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { + printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io); + return (0); + } + dev_hfcpci->resource[1].start = (int) cs->hw.hfcpci.pci_io; } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ if (!cs->hw.hfcpci.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); @@ -1701,16 +1833,16 @@ int __init (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, 0x80, - (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, (u_int) virt_to_bus(cs->hw.hfcpci.fifos), cs->irq, HZ); pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ - cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m1 = 0; Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); @@ -1735,7 +1867,7 @@ int __init reset_hfcpci(cs); cs->cardmsg = &hfcpci_card_msg; - cs->auxcmd = &hfcpci_auxcmd; + cs->auxcmd = &hfcpci_auxcmd; return (1); #else printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h index ae04d3d16..e8597d730 100644 --- a/drivers/isdn/hisax/hfc_pci.h +++ b/drivers/isdn/hisax/hfc_pci.h @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.h,v 1.6 1999/08/28 21:04:29 werner Exp $ +/* $Id: hfc_pci.h,v 1.7 1999/10/10 20:13:06 werner Exp $ * specific defines for CCD's HFC 2BDS0 PCI chips * @@ -21,6 +21,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: hfc_pci.h,v $ + * Revision 1.7 1999/10/10 20:13:06 werner + * + * Corrected timer constant + * * Revision 1.6 1999/08/28 21:04:29 werner * Implemented full audio support (transparent mode) * @@ -129,7 +133,7 @@ /* bits in CTMT (Write) */ #define HFCPCI_CLTIMER 0x80 -#define HFCPCI_TIM3_125 0x00 +#define HFCPCI_TIM3_125 0x04 #define HFCPCI_TIM25 0x10 #define HFCPCI_TIM50 0x14 #define HFCPCI_TIM400 0x18 diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c index 05735e150..8654857fd 100644 --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -1,4 +1,4 @@ -/* $Id: hfcscard.c,v 1.4 1999/08/09 18:59:59 keil Exp $ +/* $Id: hfcscard.c,v 1.5 1999/09/04 06:20:06 keil Exp $ * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10) * @@ -6,6 +6,9 @@ * * * $Log: hfcscard.c,v $ + * Revision 1.5 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.4 1999/08/09 18:59:59 keil * Fix S0 init - Thanks to Stefan Gybas * @@ -27,7 +30,7 @@ extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.4 $"; +static const char *hfcs_revision = "$Revision: 1.5 $"; static void hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) @@ -82,13 +85,13 @@ reset_hfcs(struct IsdnCardState *cs) cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); cs->hw.hfcD.cirm = 0; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_INTB; @@ -135,7 +138,7 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) init2bds0(cs); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((80*HZ)/1000); cs->hw.hfcD.ctmt |= HFCD_TIM800; cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); @@ -148,8 +151,8 @@ hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_hfcs(struct IsdnCard *card) +__initfunc(int +setup_hfcs(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 0fdf65a40..230628486 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -1,8 +1,18 @@ -/* $Id: hisax.h,v 2.34 1999/08/25 17:00:04 keil Exp $ +/* $Id: hisax.h,v 2.37 1999/10/14 20:25:28 keil Exp $ * Basic declarations, defines and prototypes * * $Log: hisax.h,v $ + * Revision 2.37 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * + * Revision 2.36 1999/10/10 20:16:15 werner + * + * Added variable to hfcpci union. + * + * Revision 2.35 1999/09/04 06:35:09 keil + * Winbond W6692 support + * * Revision 2.34 1999/08/25 17:00:04 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -137,6 +147,8 @@ #include <linux/tty.h> #include <linux/serial_reg.h> +#undef ERROR_STATISTIC + #define REQUEST 0 #define CONFIRM 1 #define INDICATION 2 @@ -447,6 +459,13 @@ struct hscx_hw { u_char tsaxr1; }; +struct w6692B_hw { + int bchan; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ +}; + struct isar_reg { unsigned int Flags; volatile u_char bstat; @@ -571,6 +590,12 @@ struct BCState { int event; int (*BC_SetStack) (struct PStack *, struct BCState *); void (*BC_Close) (struct BCState *); +#ifdef ERROR_STATISTIC + int err_crc; + int err_tx; + int err_rdo; + int err_inv; +#endif union { struct hscx_hw hscx; struct hdlc_hw hdlc; @@ -578,6 +603,7 @@ struct BCState { struct hfcB_hw hfc; struct tiger_hw tiger; struct amd7930_hw amd7930; + struct w6692B_hw w6692; } hw; }; @@ -744,7 +770,8 @@ struct hfcPCI_hw { unsigned char fifo; unsigned char fifo_en; unsigned char bswapped; - /* unsigned int *send; */ + unsigned char nt_mode; + int nt_timer; unsigned char pci_bus; unsigned char pci_device_fn; unsigned char *pci_io; /* start of PCI IO memory */ @@ -813,6 +840,11 @@ struct gazel_hw { unsigned char iom2; }; +struct w6692_hw { + unsigned int iobase; + struct timer_list timer; +}; + #ifdef CONFIG_HISAX_TESTEMU struct te_hw { unsigned char *sfifo; @@ -821,13 +853,8 @@ struct te_hw { unsigned char *sfifo_e; int sfifo_cnt; unsigned int stat; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t rwaitq; wait_queue_head_t swaitq; -#else - struct wait_queue *rwaitq; - struct wait_queue *swaitq; -#endif }; #endif @@ -847,11 +874,7 @@ struct isac_chip { int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t arcofi_wait; -#else - struct wait_queue *arcofi_wait; -#endif u_char arcofi_bc; u_char arcofi_state; u_char mocr; @@ -866,6 +889,10 @@ struct hfcpci_chip { int ph_state; }; +struct w6692_chip { + int ph_state; +}; + #define HW_IOM1 0 #define HW_IPAC 1 #define HW_ISAR 2 @@ -910,6 +937,7 @@ struct IsdnCardState { #endif struct bkm_hw ax; struct gazel_hw gazel; + struct w6692_hw w6692; } hw; int myid; isdn_if iif; @@ -940,6 +968,7 @@ struct IsdnCardState { struct isac_chip isac; struct hfcd_chip hfcd; struct hfcpci_chip hfcpci; + struct w6692_chip w6692; } dc; u_char *rcvbuf; int rcvidx; @@ -948,6 +977,11 @@ struct IsdnCardState { int event; struct tq_struct tqueue; struct timer_list dbusytimer; +#ifdef ERROR_STATISTIC + int err_crc; + int err_tx; + int err_rx; +#endif }; #define MON0_RX 1 @@ -992,7 +1026,8 @@ struct IsdnCardState { #define ISDN_CTYPE_SCT_QUADRO 33 #define ISDN_CTYPE_GAZEL 34 #define ISDN_CTYPE_HFC_PCI 35 -#define ISDN_CTYPE_COUNT 35 +#define ISDN_CTYPE_W6692 36 +#define ISDN_CTYPE_COUNT 36 #ifdef ISDN_CHIP_ISAC @@ -1007,10 +1042,6 @@ struct IsdnCardState { #define __initdata #endif -#ifndef __init -#define __init -#endif - #define HISAX_INITFUNC(__arginit) __initfunc(__arginit) #define HISAX_INITDATA __initdata @@ -1243,6 +1274,15 @@ struct IsdnCardState { #define CARD_GAZEL 0 #endif +#ifdef CONFIG_HISAX_W6692 +#define CARD_W6692 1 +#ifndef ISDN_CHIP_W6692 +#define ISDN_CHIP_W6692 1 +#endif +#else +#define CARD_W6692 0 +#endif + #define TEI_PER_CARD 0 #ifdef CONFIG_HISAX_1TR6 @@ -1336,7 +1376,7 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); -void HiSax_reportcard(int cardnr); +void HiSax_reportcard(int cardnr, int sel); int QuickHex(char *txt, u_char * p, int cnt); void LogFrame(struct IsdnCardState *cs, u_char * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c index 290c89f50..1c57cd3f1 100644 --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -219,7 +219,7 @@ close_hscxstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c index ecc1e825e..655508f70 100644 --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 keil Exp $ +/* $Id: hscx_irq.c,v 1.13 1999/10/14 20:25:28 keil Exp $ * hscx_irq.c low level b-channel stuff for Siemens HSCX * @@ -7,6 +7,9 @@ * This is an include file for fast inline IRQ stuff * * $Log: hscx_irq.c,v $ + * Revision 1.13 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.12 1999/07/01 08:11:42 keil * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel * @@ -181,16 +184,28 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (val & 0x80) { /* RME */ r = READHSCX(cs, hscx, HSCX_RSTA); if ((r & 0xf0) != 0xa0) { - if (!(r & 0x80)) + if (!(r & 0x80)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX invalid frame"); - if ((r & 0x40) && bcs->mode) +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif + } + if ((r & 0x40) && bcs->mode) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX RDO mode=%d", bcs->mode); - if (!(r & 0x20)) +#ifdef ERROR_STATISTIC + bcs->err_rdo++; +#endif + } + if (!(r & 0x20)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "HSCX CRC error"); +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif + } WriteHSCXCMDR(cs, hscx, 0x80); } else { count = READHSCX(cs, hscx, HSCX_RBCL) & ( @@ -204,7 +219,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "HSCX: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -220,7 +234,6 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -237,7 +250,7 @@ hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } @@ -267,6 +280,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) if (bcs->mode == 1) hscx_fill_fifo(bcs); else { +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ @@ -297,6 +313,9 @@ hscx_int_main(struct IsdnCardState *cs, u_char val) /* Here we lost an TX interrupt, so * restart transmitting the whole frame. */ +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif if (bcs->tx_skb) { skb_push(bcs->tx_skb, bcs->hw.hscx.count); bcs->tx_cnt += bcs->hw.hscx.count; diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 46d5daef0..a992f76c4 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.23 1999/08/25 16:50:52 keil Exp $ +/* $Id: isac.c,v 1.24 1999/10/14 20:25:28 keil Exp $ * isac.c ISAC specific routines * @@ -9,6 +9,9 @@ * ../../../Documentation/isdn/HiSax.cert * * $Log: isac.c,v $ + * Revision 1.24 1999/10/14 20:25:28 keil + * add a statistic for error monitoring + * * Revision 1.23 1999/08/25 16:50:52 keil * Fix bugs which cause 2.3.14 hangs (waitqueue init) * @@ -281,12 +284,20 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (val & 0x80) { /* RME */ exval = cs->readisac(cs, ISAC_RSTA); if ((exval & 0x70) != 0x20) { - if (exval & 0x40) + if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC RDO"); - if (!(exval & 0x20)) +#ifdef ERROR_STATISTIC + cs->err_rx++; +#endif + } + if (!(exval & 0x20)) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC CRC error"); +#ifdef ERROR_STATISTIC + cs->err_crc++; +#endif + } cs->writeisac(cs, ISAC_CMDR, 0x80); } else { count = cs->readisac(cs, ISAC_RBCL) & 0x1f; @@ -300,7 +311,6 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (!(skb = alloc_skb(count, GFP_ATOMIC))) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), cs->rcvbuf, count); skb_queue_tail(&cs->rq, skb); } @@ -328,7 +338,7 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) isac_fill_fifo(cs); goto afterXPR; } else { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } @@ -372,6 +382,9 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (exval & 0x40) { /* XDU */ debugl1(cs, "ISAC XDU"); printk(KERN_WARNING "HiSax: ISAC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) @@ -614,7 +627,7 @@ ISAC_l1hw(struct PStack *st, int pr, void *arg) discard_queue(&cs->rq); discard_queue(&cs->sq); if (cs->tx_skb) { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_skb = NULL; } if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) @@ -670,7 +683,7 @@ dbusy_timer_handler(struct IsdnCardState *cs) /* discard frame; reset transceiver */ test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); if (cs->tx_skb) { - idev_kfree_skb(cs->tx_skb, FREE_WRITE); + dev_kfree_skb(cs->tx_skb); cs->tx_cnt = 0; cs->tx_skb = NULL; } else { diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c index 96442ff7d..417f2157d 100644 --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.5 1999/08/25 16:59:55 keil Exp $ +/* $Id: isar.c,v 1.7 1999/10/14 20:25:29 keil Exp $ * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -6,6 +6,12 @@ * * * $Log: isar.c,v $ + * Revision 1.7 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * + * Revision 1.6 1999/08/31 11:20:20 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.5 1999/08/25 16:59:55 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -459,7 +465,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) case L1_MODE_TRANS: case L1_MODE_V32: if ((skb = dev_alloc_skb(ireg->clsb))) { - SET_SKB_FREE(skb); rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); skb_queue_tail(&bcs->rqueue, skb); isar_sched_event(bcs, B_RCVBUFREADY); @@ -478,6 +483,12 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame error %x len %d", ireg->cmsb, ireg->clsb); +#ifdef ERROR_STATISTIC + if (ireg->cmsb & HDLC_ERR_RER) + bcs->err_inv++; + if (ireg->cmsb & HDLC_ERR_CER) + bcs->err_crc++; +#endif bcs->hw.isar.rcvidx = 0; cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { @@ -493,7 +504,6 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) { printk(KERN_WARNING "ISAR: receive out of memory\n"); } else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); skb_queue_tail(&bcs->rqueue, skb); @@ -593,7 +603,7 @@ send_frames(struct BCState *bcs) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.isar.txcnt = 0; bcs->tx_skb = NULL; } @@ -789,10 +799,19 @@ isar_int_main(struct IsdnCardState *cs) check_send(cs, ireg->cmsb); break; case ISAR_IIS_BSTEV: - cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); +#ifdef ERROR_STATISTIC + if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { + if (ireg->cmsb == BSTEV_TBO) + bcs->err_tx++; + if (ireg->cmsb == BSTEV_RBO) + bcs->err_rdo++; + } +#endif if (cs->debug & L1_DEB_WARN) debugl1(cs, "Buffer STEV dpath%d msb(%x)", ireg->iis>>6, ireg->cmsb); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); + break; case ISAR_IIS_PSTEV: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { rcv_mbox(cs, ireg, (u_char *)ireg->par); @@ -1022,8 +1041,8 @@ modeisar(struct BCState *bcs, int mode, int bc) &bcs->hw.isar.reg->Flags)) bcs->hw.isar.dpath = 1; else { - printk(KERN_WARNING"isar modeisar analog funktions only with DP1\n"); - debugl1(cs, "isar modeisar analog funktions only with DP1"); + printk(KERN_WARNING"isar modeisar analog works only with DP1\n"); + debugl1(cs, "isar modeisar analog works only with DP1"); return(1); } break; @@ -1159,7 +1178,7 @@ close_isarstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); if (bcs->cs->debug & L1_DEB_HSCX) @@ -1223,7 +1242,7 @@ isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { ll_run(cs, features); break; default: - printk(KERN_DEBUG "HiSax: invalid ioclt %d\n", + printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", (int) ic->arg); return(-EINVAL); } diff --git a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h index c6ac6532b..f2bc4820a 100644 --- a/drivers/isdn/hisax/isar.h +++ b/drivers/isdn/hisax/isar.h @@ -1,10 +1,13 @@ -/* $Id: isar.h,v 1.5 1999/08/25 16:59:59 keil Exp $ +/* $Id: isar.h,v 1.6 1999/10/14 20:25:29 keil Exp $ * isar.h ISAR (Siemens PSB 7110) specific defines * * Author Karsten Keil (keil@isdn4linux.de) * * * $Log: isar.h,v $ + * Revision 1.6 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * * Revision 1.5 1999/08/25 16:59:59 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -178,12 +181,17 @@ #define HDLC_FSD 0x20 #define HDLC_FST 0x20 #define HDLC_ERROR 0x1c +#define HDLC_ERR_FAD 0x10 +#define HDLC_ERR_RER 0x08 +#define HDLC_ERR_CER 0x01 #define SART_NMD 0x01 #define BSTAT_RDM0 0x1 #define BSTAT_RDM1 0x2 #define BSTAT_RDM2 0x4 #define BSTAT_RDM3 0x8 +#define BSTEV_TBO 0x1f +#define BSTEV_RBO 0x2f extern int ISARVersion(struct IsdnCardState *cs, char *s); extern void isar_int_main(struct IsdnCardState *cs); diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c index c819c4811..768217025 100644 --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -318,12 +318,12 @@ DChannel_proc_rcv(struct IsdnCardState *cs) stptr = cs->stlist; if (skb->len<3) { debugl1(cs, "D-channel frame too short(%d)",skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((skb->data[0] & 1) || !(skb->data[1] &1)) { debugl1(cs, "D-channel frame wrong EA0/EA1"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } sapi = skb->data[0] >> 2; @@ -350,7 +350,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs) stptr = stptr->next; } } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } else if (sapi == CTRL_SAPI) { /* sapi 0 */ found = 0; while (stptr != NULL) @@ -361,7 +361,7 @@ DChannel_proc_rcv(struct IsdnCardState *cs) } else stptr = stptr->next; if (!found) - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } } } diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index ca721ea86..69e320262 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -201,7 +201,7 @@ freewin1(struct Layer2 *l2) for (i = 0; i < MAX_WINDOW; i++) { if (l2->windowar[i]) { cnt++; - idev_kfree_skb(l2->windowar[i], FREE_WRITE); + dev_kfree_skb(l2->windowar[i]); l2->windowar[i] = NULL; } } @@ -480,7 +480,7 @@ setva(struct PStack *st, unsigned int nr) len = l2->windowar[l2->sow]->len; if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) len = -1; - idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE); + dev_kfree_skb(l2->windowar[l2->sow]); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; if (st->lli.l2writewakeup && (len >=0)) @@ -501,7 +501,6 @@ send_uframe(struct PStack *st, u_char cmd, u_char cr) printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n"); return; } - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -515,7 +514,7 @@ get_PollFlag(struct PStack * st, struct sk_buff * skb) inline void FreeSkb(struct sk_buff *skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } @@ -970,7 +969,6 @@ enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf) printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n"); return; } - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), tmp, i); enqueue_super(st, skb); } @@ -1343,7 +1341,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) if (l2->windowar[p1]) { printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n", p1); - idev_kfree_skb(l2->windowar[p1], FREE_WRITE); + dev_kfree_skb(l2->windowar[p1]); } l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC); @@ -1367,7 +1365,6 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg) "isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1); oskb = skb; skb = alloc_skb(oskb->len + i, GFP_ATOMIC); - SET_SKB_FREE(skb); memcpy(skb_put(skb, i), header, i); memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); FreeSkb(oskb); @@ -1788,12 +1785,12 @@ isdnl2_l3l2(struct PStack *st, int pr, void *arg) switch (pr) { case (DL_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) { - idev_kfree_skb((struct sk_buff *) arg, FREE_READ); + dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_UNIT_DATA | REQUEST): if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) { - idev_kfree_skb((struct sk_buff *) arg, FREE_READ); + dev_kfree_skb((struct sk_buff *) arg); } break; case (DL_ESTABLISH | REQUEST): diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c index 458afe920..6dc8bd9d0 100644 --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -260,7 +260,6 @@ l3_alloc_skb(int len) printk(KERN_WARNING "HiSax: No skb for D-channel\n"); return (NULL); } - SET_SKB_FREE(skb); skb_reserve(skb, MAX_HEADER_LEN); return (skb); } @@ -272,7 +271,7 @@ no_l3_proto(struct PStack *st, int pr, void *arg) HiSax_putstatus(st->l1.hardware, "L3", "no D protocol"); if (skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } } diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c index dd713921a..245b40bc0 100644 --- a/drivers/isdn/hisax/isurf.c +++ b/drivers/isdn/hisax/isurf.c @@ -1,10 +1,13 @@ -/* $Id: isurf.c,v 1.5 1999/08/25 17:00:02 keil Exp $ +/* $Id: isurf.c,v 1.6 1999/09/04 06:20:06 keil Exp $ * isurf.c low level stuff for Siemens I-Surf/I-Talk cards * * Author Karsten Keil (keil@isdn4linux.de) * * $Log: isurf.c,v $ + * Revision 1.6 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.5 1999/08/25 17:00:02 keil * Make ISAR V32bis modem running * Make LL->HL interface open for additional commands @@ -34,7 +37,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.5 $"; +static const char *ISurf_revision = "$Revision: 1.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -154,10 +157,10 @@ reset_isurf(struct IsdnCardState *cs, u_char chips) byteout(cs->hw.isurf.reset, chips); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -206,8 +209,8 @@ isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { return(isar_auxcmd(cs, ic)); } -int __init -setup_isurf(struct IsdnCard *card) +__initfunc(int +setup_isurf(struct IsdnCard *card)) { int ver; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c index 389d043a3..cb94d5bb3 100644 --- a/drivers/isdn/hisax/ix1_micro.c +++ b/drivers/isdn/hisax/ix1_micro.c @@ -282,8 +282,8 @@ ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) } -int __init -setup_ix1micro(struct IsdnCard *card) +__initfunc(int +setup_ix1micro(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c index 5699f28a7..4f07eed87 100644 --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -214,7 +214,7 @@ close_jadestate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } diff --git a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c index 9cfcc7d6d..e54c80c1a 100644 --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c @@ -161,7 +161,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -177,7 +176,6 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (!(skb = dev_alloc_skb(fifo_size))) printk(KERN_WARNING "HiSax: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); skb_queue_tail(&bcs->rqueue, skb); } @@ -194,7 +192,7 @@ jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->hw.hscx.count = 0; bcs->tx_skb = NULL; } diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c index ba8d95dbd..31b25acdf 100644 --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -94,14 +94,14 @@ l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); l3_1tr6_release_req(pc, 0, NULL); } static void l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (pc->st->l3.debug & L3_DEB_WARN) l3_debug(pc->st, msg); l3_1tr6_release_req(pc, 0, NULL); @@ -251,7 +251,7 @@ l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) if ((FAC_SPV == p[3]) || (FAC_Activate == p[3])) pc->para.spv = 1; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); /* Signal all services, linklevel takes care of Service-Indicator */ if (bcfound) { @@ -290,7 +290,7 @@ l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3AddTimer(&pc->timer, T304, CC_T304); pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } @@ -321,7 +321,7 @@ l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing call sent WE0_chanID", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); @@ -332,7 +332,7 @@ l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); @@ -363,7 +363,7 @@ l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) } } else if (pc->st->l3.debug & L3_DEB_CHARGE) l3_debug(pc->st, "charging info not found"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } @@ -372,7 +372,7 @@ l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } static void @@ -386,7 +386,7 @@ l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) return; } newl3state(pc, 10); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); pc->para.chargeinfo = 0; pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } @@ -414,7 +414,7 @@ l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing REL cause", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); StopAllL3Timer(pc); newl3state(pc, 0); l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); @@ -427,7 +427,7 @@ l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); StopAllL3Timer(pc); newl3state(pc, 0); pc->para.cause = NO_CAUSE; @@ -484,7 +484,7 @@ l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing connack date", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); newl3state(pc, 12); pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); } @@ -499,7 +499,7 @@ l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) l3_1tr6_error(pc, "missing connack date", skb); return; } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); newl3state(pc, 10); pc->para.chargeinfo = 0; L3DelTimer(&pc->timer); @@ -814,7 +814,7 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 len only %d", skb->len); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) { @@ -824,7 +824,7 @@ up1tr6(struct PStack *st, int pr, void *arg) skb->data[0], skb->len); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (skb->data[1] != 1) { @@ -832,13 +832,13 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 CR len not 1"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } cr = skb->data[2]; mt = skb->data[3]; if (skb->data[0] == PROTO_DIS_N0) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%s N0 mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt); @@ -853,11 +853,11 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 no roc mem"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) || @@ -865,7 +865,7 @@ up1tr6(struct PStack *st, int pr, void *arg) (mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) || (mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) || (mt == MT_N1_INFO)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else { if (!(proc = new_l3_process(st, cr))) { @@ -873,7 +873,7 @@ up1tr6(struct PStack *st, int pr, void *arg) sprintf(tmp, "up1tr6 no roc mem"); l3_debug(st, tmp); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } mt = MT_N1_INVALID; @@ -884,7 +884,7 @@ up1tr6(struct PStack *st, int pr, void *arg) ((1 << proc->state) & datastln1[i].state)) break; if (i == DATASTLN1_LEN) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if (st->l3.debug & L3_DEB_STATE) { sprintf(tmp, "up1tr6%sstate %d mt %x unhandled", (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c index 22a5de9fa..035ee54ca 100644 --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -1,4 +1,4 @@ -/* $Id: l3dss1.c,v 2.19 1999/08/25 16:55:23 keil Exp $ +/* $Id: l3dss1.c,v 2.20 1999/10/11 22:16:27 keil Exp $ * EURO/DSS1 D-channel protocol * @@ -13,6 +13,9 @@ * Fritz Elfert * * $Log: l3dss1.c,v $ + * Revision 2.20 1999/10/11 22:16:27 keil + * Suspend/Resume is possible without explicit ID too + * * Revision 2.19 1999/08/25 16:55:23 keil * Fix for test case TC10011 * @@ -90,7 +93,7 @@ #include <linux/ctype.h> extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.19 $"; +const char *dss1_revision = "$Revision: 2.20 $"; #define EXT_BEARER_CAPS 1 @@ -2520,14 +2523,13 @@ l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); - - *p++ = IE_CALL_ID; l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; - } else { + } else if (l) { l3_debug(pc->st, "SUS wrong CALL_ID len %d", l); return; } @@ -2596,13 +2598,13 @@ l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) MsgHead(p, pc->callref, MT_RESUME); - *p++ = IE_CALL_ID; l = *msg++; if (l && (l <= 10)) { /* Max length 10 octets */ + *p++ = IE_CALL_ID; *p++ = l; for (i = 0; i < l; i++) *p++ = *msg++; - } else { + } else if (l) { l3_debug(pc->st, "RES wrong CALL_ID len %d", l); return; } @@ -2976,7 +2978,7 @@ dss1up(struct PStack *st, int pr, void *arg) } if (skb->len < 3) { l3_debug(st, "dss1up frame too short(%d)", skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } @@ -2986,13 +2988,13 @@ dss1up(struct PStack *st, int pr, void *arg) (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", skb->data[0], skb->len); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } cr = getcallref(skb->data); if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "dss1up frame too short(%d)", skb->len); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } mt = skb->data[skb->data[1] + 2]; @@ -3001,26 +3003,26 @@ dss1up(struct PStack *st, int pr, void *arg) if (cr == -2) { /* wrong Callref */ if (st->l3.debug & L3_DEB_WARN) l3_debug(st, "dss1up wrong Callref"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (cr == -1) { /* Dummy Callref */ if (mt == MT_FACILITY) if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) { l3dss1_parse_facility(st, NULL, (pr == (DL_DATA | INDICATION)) ? -1 : -2, p); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (st->l3.debug & L3_DEB_WARN) l3_debug(st, "dss1up dummy Callref (no facility msg or ie)"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) || (((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) { /* Global CallRef */ if (st->l3.debug & L3_DEB_STATE) l3_debug(st, "dss1up Global CallRef"); global_handler(st, mt, skb); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (!(proc = getl3proc(st, cr))) { /* No transaction process exist, that means no call with @@ -3032,7 +3034,7 @@ dss1up(struct PStack *st, int pr, void *arg) /* Setup with wrong CREF flag */ if (st->l3.debug & L3_DEB_STATE) l3_debug(st, "dss1up wrong CRef flag"); - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if (!(proc = dss1_new_l3_process(st, cr))) { @@ -3040,7 +3042,7 @@ dss1up(struct PStack *st, int pr, void *arg) * CAUSE 0x2f "Resource unavailable", but this * need a new_l3_process too ... arghh */ - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } } else if (mt == MT_STATUS) { @@ -3074,17 +3076,17 @@ dss1up(struct PStack *st, int pr, void *arg) l3dss1_msg_without_setup(proc, 0, NULL); } } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else if (mt == MT_RELEASE_COMPLETE) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } else { /* ETS 300-104 part 2 * if setup has not been made and a message type * (except MT_SETUP and RELEASE_COMPLETE) is received, * we must send MT_RELEASE_COMPLETE cause 81 */ - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); if ((proc = dss1_new_l3_process(st, cr))) { proc->para.cause = 81; l3dss1_msg_without_setup(proc, 0, NULL); @@ -3093,7 +3095,7 @@ dss1up(struct PStack *st, int pr, void *arg) } } if (l3dss1_check_messagetype_validity(proc, mt, skb)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) @@ -3120,7 +3122,7 @@ dss1up(struct PStack *st, int pr, void *arg) } datastatelist[i].rout(proc, pr, skb); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } diff --git a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc index 481a7dc72..985bd4cb4 100644 --- a/drivers/isdn/hisax/md5sums.asc +++ b/drivers/isdn/hisax/md5sums.asc @@ -6,26 +6,26 @@ # Eicon Technology Diva 2.01 PCI cards in the moment. # Read ../../../Documentation/isdn/HiSax.cert for more informations. # -0cc164fadd4ec0e2983ec9735e209cbd isac.c -5fe8cb5526c78c91f61b0a94a423ea5d isdnl1.c -3b9522e8bf9e1c3e7848d729fc3dc05d isdnl2.c -f4184a50e35e5b568608e6cb7a693319 isdnl3.c -ef70f4269fdc2ca15100f9b776afaa0d tei.c -65be616dd9d0e06c788d4fdd0fe5fe0a callc.c +3c2b1c96274cba97a8261d1cecc662b8 isac.c +a9a15d069dbacb383cc24c238cb5ebbe isdnl1.c +bb51bd223040b511c18f091da5ab6456 isdnl2.c +b7aa7f97b2374967a4aca7c52991142c isdnl3.c +a23fbf8879c1432b04640b8b04bdf419 tei.c +d7072dbbeeb7c4c45f3810ed13cf5545 callc.c bf9605b36429898f7be6630034e83230 cert.c -97c5e31c2739665b9c2976a30ce0b357 l3dss1.c -b674eee9314a7cc413971c84003cf1d2 l3_1tr6.c -51b2ef1efb221bb09fd08ab28bd2c565 elsa.c -24cda374da44b57f6a1bb215424267b5 diva.c +0e500813968adacaea2ef22c9cdd89eb l3dss1.c +2d748ced0eea375b21fe7ea91ca7917c l3_1tr6.c +d45fde1c90dda636ab134f2a51db435e elsa.c +0b5fb429f5bfe188fd42a5be01abbb14 diva.c # end of md5sums -----BEGIN PGP SIGNATURE----- Version: 2.6.3i Charset: noconv -iQCVAwUBN8RgFjpxHvX/mS9tAQFzFQP/dOgnppDIm5ug1hnlWjQ/0BVurKEEJ64r -DYDHwkcog+0gVE/EB1A7WUDqpFEnj52OZeoVinCfdVuVjP8IkrAJ8dCONsnXjBXz -pzM+FunP1LFxuv2TVM0f642j98JxS8rObGWH8ZwY36P2QfNp47zorO2F9WvdCkuz -sxJUtMUOlQ8= -=8uEP +iQCVAwUBOCYF6jpxHvX/mS9tAQFnxQP/dpHyNjbo5BhFEZ8qIgpPJzoCgV+b2pB+ +h9Z/Q1jg8l23L/lP9dW00ogrKnKziVUUJqg+wWVEAA7BnNVr3aeyQKFTVuOnK5MC +Oy0Z98p530vgOBiZ47elNfpefjhfD3duSSYNA4R9fEHVZB/atKFYvB5GDGmrwjIZ +2f3g3kBP5Os= +=zNnO -----END PGP SIGNATURE----- diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c index fa85bbd27..be65f1101 100644 --- a/drivers/isdn/hisax/mic.c +++ b/drivers/isdn/hisax/mic.c @@ -224,8 +224,8 @@ mic_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_mic(struct IsdnCard *card) +__initfunc(int +setup_mic(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c index d88442e37..3b502f7db 100644 --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.13 1999/08/11 21:01:31 keil Exp $ +/* $Id: netjet.c,v 1.16 1999/10/14 20:25:29 keil Exp $ * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * @@ -7,6 +7,15 @@ * Thanks to Traverse Technologie Australia for documents and informations * * $Log: netjet.c,v $ + * Revision 1.16 1999/10/14 20:25:29 keil + * add a statistic for error monitoring + * + * Revision 1.15 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * + * Revision 1.14 1999/08/31 11:20:25 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.13 1999/08/11 21:01:31 keil * new PCI codefix * @@ -59,9 +68,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif #include <linux/interrupt.h> #include <linux/ppp_defs.h> @@ -75,7 +81,7 @@ extern const char *CardType[]; -const char *NETjet_revision = "$Revision: 1.13 $"; +const char *NETjet_revision = "$Revision: 1.16 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -406,7 +412,6 @@ static void got_frame(struct BCState *bcs, int count) { if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "TIGER: receive out of memory\n"); else { - SET_SKB_FREE(skb); memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } @@ -526,19 +531,26 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ debugl1(bcs->cs, "tiger: frame not byte aligned"); state=HDLC_FLAG_SEARCH; bcs->hw.tiger.r_err++; +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x", i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0); if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) { got_frame(bcs, (bitcnt>>3)-3); - } else + } else { if (bcs->cs->debug) { debugl1(bcs->cs, "tiger FCS error"); printframe(bcs->cs, bcs->hw.tiger.rcvbuf, (bitcnt>>3)-1, "rec"); bcs->hw.tiger.r_err++; } +#ifdef ERROR_STATISTIC + bcs->err_crc++; +#endif + } state=HDLC_FLAG_FOUND; } bitcnt=0; @@ -556,10 +568,13 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ if ((state == HDLC_FRAME_FOUND) && !(bitcnt & 7)) { if ((bitcnt>>3)>=HSCX_BUFMAX) { - debugl1(bcs->cs, "tiger: frame to big"); + debugl1(bcs->cs, "tiger: frame too big"); r_val=0; state=HDLC_FLAG_SEARCH; bcs->hw.tiger.r_err++; +#ifdef ERROR_STATISTIC + bcs->err_inv++; +#endif } else { bcs->hw.tiger.rcvbuf[(bitcnt>>3)-1] = r_val; bcs->hw.tiger.r_fcs = @@ -584,6 +599,12 @@ static void read_tiger(struct IsdnCardState *cs) { if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) { debugl1(cs,"tiger warn read double dma %x/%x", cs->hw.njet.irqstat0, cs->hw.njet.last_is0); +#ifdef ERROR_STATISTIC + if (cs->bcs[0].mode) + cs->bcs[0].err_rdo++; + if (cs->bcs[1].mode) + cs->bcs[1].err_rdo++; +#endif return; } else { cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ; @@ -705,7 +726,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { if (bcs->st->lli.l1writewakeup && (PACKET_NOACK != bcs->tx_skb->pkt_type)) bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len); - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); @@ -755,6 +776,12 @@ static void write_tiger(struct IsdnCardState *cs) { if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) { debugl1(cs,"tiger warn write double dma %x/%x", cs->hw.njet.irqstat0, cs->hw.njet.last_is0); +#ifdef ERROR_STATISTIC + if (cs->bcs[0].mode) + cs->bcs[0].err_tx++; + if (cs->bcs[1].mode) + cs->bcs[1].err_tx++; +#endif return; } else { cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE; @@ -842,7 +869,7 @@ close_tigerstate(struct BCState *bcs) discard_queue(&bcs->rqueue); discard_queue(&bcs->squeue); if (bcs->tx_skb) { - idev_kfree_skb(bcs->tx_skb, FREE_WRITE); + dev_kfree_skb(bcs->tx_skb); bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -889,8 +916,8 @@ setstack_tiger(struct PStack *st, struct BCState *bcs) } -void __init -inittiger(struct IsdnCardState *cs) +__initfunc(void +inittiger(struct IsdnCardState *cs)) { if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), GFP_KERNEL | GFP_DMA))) { @@ -1027,11 +1054,11 @@ reset_netjet(struct IsdnCardState *cs) sti(); cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ restore_flags(flags); cs->hw.njet.auxd = 0; @@ -1074,23 +1101,15 @@ NETjet_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_netjet __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_netjet(struct IsdnCard *card) +__initfunc(int +setup_netjet(struct IsdnCard *card)) { int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; #if CONFIG_PCI -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_ioaddr, found; -#endif #endif strcpy(tmp, NETjet_revision); printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp)); @@ -1098,7 +1117,6 @@ setup_netjet(struct IsdnCard *card) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); @@ -1110,7 +1128,7 @@ setup_netjet(struct IsdnCard *card) printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); return(0); } - cs->hw.njet.base = get_pcibase(dev_netjet, 0) + cs->hw.njet.base = dev_netjet->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; if (!cs->hw.njet.base) { printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); @@ -1120,41 +1138,6 @@ setup_netjet(struct IsdnCard *card) printk(KERN_WARNING "NETjet: No PCI card found\n"); return(0); } -#else - found = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH, - PCI_NETJET_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - found = 1; - else - continue; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - if (found) - break; - } - if (!found) { - printk(KERN_WARNING "NETjet: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_ioaddr & PCI_BASE_ADDRESS_IO_MASK; - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; bytecnt = 256; diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c index 7574a8e8f..4198bb5e0 100644 --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -40,9 +40,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *niccy_revision = "$Revision: 1.8 $"; @@ -259,14 +256,10 @@ niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *niccy_dev __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_niccy(struct IsdnCard *card) +__initfunc(int +setup_niccy(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -306,7 +299,6 @@ setup_niccy(struct IsdnCard *card) } else { #if CONFIG_PCI u_int pci_ioaddr; -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Niccy: no PCI bus present\n"); return(0); @@ -320,66 +312,21 @@ setup_niccy(struct IsdnCard *card) return(0); } cs->irq = niccy_dev->irq; - if (!get_pcibase(niccy_dev, 0)) { + if (!niccy_dev->resource[ 0].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); return(0); } - cs->hw.niccy.cfg_reg = get_pcibase(niccy_dev, 0) & PCI_BASE_ADDRESS_IO_MASK; - if (!get_pcibase(niccy_dev, 1)) { + cs->hw.niccy.cfg_reg = niccy_dev->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; + if (!niccy_dev->resource[ 1].start) { printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); return(0); } - pci_ioaddr = get_pcibase(niccy_dev, 1) & PCI_BASE_ADDRESS_IO_MASK; + pci_ioaddr = niccy_dev->resource[ 1].start & PCI_BASE_ADDRESS_IO_MASK; cs->subtyp = NICCY_PCI; } else { printk(KERN_WARNING "Niccy: No PCI card found\n"); return(0); } -#else - u_char pci_bus, pci_device_fn, pci_irq; - - cs->subtyp = 0; - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device(PCI_VENDOR_DR_NEUHAUS, - PCI_NICCY_ID, pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) - cs->subtyp = NICCY_PCI; - else - continue; - /* get IRQ */ - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - /* get IO pci AMCC address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); - return(0); - } - cs->hw.niccy.cfg_reg = pci_ioaddr & ~3 ; - /* get IO address */ - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_ioaddr); - if (cs->subtyp) - break; - } - if (!cs->subtyp) { - printk(KERN_WARNING "Niccy: No PCI card found\n"); - return(0); - } - pci_index++; - if (!pci_irq) { - printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); - return(0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); - return(0); - } - pci_ioaddr &= ~3; /* remove io/mem flag */ - cs->irq = pci_irq; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c index d8dfb2ee3..51bc11658 100644 --- a/drivers/isdn/hisax/s0box.c +++ b/drivers/isdn/hisax/s0box.c @@ -212,8 +212,8 @@ S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_s0box(struct IsdnCard *card) +__initfunc(int +setup_s0box(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c index 0d524faa8..955a9a4de 100644 --- a/drivers/isdn/hisax/saphir.c +++ b/drivers/isdn/hisax/saphir.c @@ -1,4 +1,4 @@ -/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $ +/* $Id: saphir.c,v 1.4 1999/09/04 06:20:06 keil Exp $ * saphir.c low level stuff for HST Saphir 1 * @@ -8,6 +8,9 @@ * * * $Log: saphir.c,v $ + * Revision 1.4 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.3 1999/07/12 21:05:26 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -26,7 +29,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.3 $"; +static char *saphir_rev = "$Revision: 1.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -234,10 +237,10 @@ saphir_reset(struct IsdnCardState *cs) save_flags(flags); sti(); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ restore_flags(flags); byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); @@ -265,8 +268,8 @@ saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) } -int __init -setup_saphir(struct IsdnCard *card) +__initfunc(int +setup_saphir(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c index 2640555b2..daa7953d9 100644 --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.16 1999/08/29 18:23:01 niemann Exp $ +/* $Id: sedlbauer.c,v 1.17 1999/09/04 06:20:06 keil Exp $ * sedlbauer.c low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -17,6 +17,9 @@ * Edgar Toernig * * $Log: sedlbauer.c,v $ + * Revision 1.17 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.16 1999/08/29 18:23:01 niemann * Fixed typo in errormsg * @@ -100,13 +103,10 @@ #include "isar.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; -const char *Sedlbauer_revision = "$Revision: 1.16 $"; +const char *Sedlbauer_revision = "$Revision: 1.17 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", @@ -474,10 +474,10 @@ reset_sedlbauer(struct IsdnCardState *cs) writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); @@ -489,10 +489,10 @@ reset_sedlbauer(struct IsdnCardState *cs) byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -542,15 +542,11 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) } #ifdef SEDLBAUER_PCI -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_sedl __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif #endif -int __init -setup_sedlbauer(struct IsdnCard *card) +__initfunc(int +setup_sedlbauer(struct IsdnCard *card)) { int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; @@ -585,7 +581,6 @@ setup_sedlbauer(struct IsdnCard *card) /* Probe for Sedlbauer speed pci */ #if SEDLBAUER_PCI #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "Sedlbauer: no PCI bus present\n"); return(0); @@ -597,41 +592,12 @@ setup_sedlbauer(struct IsdnCard *card) printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); return(0); } - cs->hw.sedl.cfg_reg = get_pcibase(dev_sedl, 0) & + cs->hw.sedl.cfg_reg = dev_sedl->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK; } else { printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); return(0); } -#else - for (; pci_index < 255; pci_index++) { - unsigned char pci_bus, pci_device_fn; - unsigned int ioaddr; - unsigned char irq; - - if (pcibios_find_device (PCI_VENDOR_SEDLBAUER, - PCI_SPEEDPCI_ID, pci_index, - &pci_bus, &pci_device_fn) != 0) { - continue; - } - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &ioaddr); - cs->irq = irq; - cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; - if (!cs->hw.sedl.cfg_reg) { - printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n"); - return(0); - } - break; - } - if (pci_index == 255) { - printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); - return(0); - } - pci_index++; -#endif /* COMPAT_HAS_NEW_PCI */ cs->irq_flags |= SA_SHIRQ; cs->hw.sedl.bus = SEDL_BUS_PCI; cs->hw.sedl.chip = SEDL_CHIP_IPAC; diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c index 29fae02f7..91a6a6ae1 100644 --- a/drivers/isdn/hisax/sportster.c +++ b/drivers/isdn/hisax/sportster.c @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $ +/* $Id: sportster.c,v 1.10 1999/09/04 06:20:06 keil Exp $ * sportster.c low level stuff for USR Sportster internal TA * @@ -7,6 +7,9 @@ * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation * * $Log: sportster.c,v $ + * Revision 1.10 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * * Revision 1.9 1999/07/12 21:05:29 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -43,7 +46,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.9 $"; +const char *sportster_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -177,11 +180,11 @@ reset_sportster(struct IsdnCardState *cs) byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -208,8 +211,8 @@ Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -get_io_range(struct IsdnCardState *cs) +__initfunc(int +get_io_range(struct IsdnCardState *cs)) { int i, j, adr; @@ -234,8 +237,8 @@ get_io_range(struct IsdnCardState *cs) } } -int __init -setup_sportster(struct IsdnCard *card) +__initfunc(int +setup_sportster(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c index f21284bec..8454f1554 100644 --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -169,7 +169,6 @@ put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei) printk(KERN_WARNING "HiSax: No skb for TEI manager\n"); return; } - SET_SKB_FREE(skb); bp = skb_put(skb, 3); bp[0] = (TEI_SAPI << 2); bp[1] = (GROUP_TEI << 1) | 0x1; @@ -371,7 +370,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg) int mt; if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) { - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); return; } @@ -417,7 +416,7 @@ tei_l1l2(struct PStack *st, int pr, void *arg) st->ma.tei_m.printdebug(&st->ma.tei_m, "tei handler wrong pr %x\n", pr); } - idev_kfree_skb(skb, FREE_READ); + dev_kfree_skb(skb); } static void diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c index 430ea2768..c34dc5613 100644 --- a/drivers/isdn/hisax/teleint.c +++ b/drivers/isdn/hisax/teleint.c @@ -1,4 +1,4 @@ -/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $ +/* $Id: teleint.c,v 1.11 1999/09/04 06:20:06 keil Exp $ * teleint.c low level stuff for TeleInt isdn cards * @@ -6,6 +6,12 @@ * * * $Log: teleint.c,v $ + * Revision 1.11 1999/09/04 06:20:06 keil + * Changes from kernel set_current_state() + * + * Revision 1.10 1999/08/31 11:20:27 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.9 1999/07/12 21:05:30 keil * fix race in IRQ handling * added watchdog for lost IRQs @@ -45,7 +51,7 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.9 $"; +const char *TeleInt_revision = "$Revision: 1.11 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -64,7 +70,7 @@ readreg(unsigned int ale, unsigned int adr, u_char off) while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); restore_flags(flags); return (0); } @@ -86,7 +92,7 @@ readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); return; } data[i] = bytein(adr); @@ -108,7 +114,7 @@ writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); restore_flags(flags); return; } @@ -130,7 +136,7 @@ writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int siz while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { - printk(KERN_WARNING "TeleInt Busy not inaktive\n"); + printk(KERN_WARNING "TeleInt Busy not inactive\n"); return; } byteout(adr, data[i]); @@ -254,11 +260,11 @@ reset_TeleInt(struct IsdnCardState *cs) byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */ save_flags(flags); sti(); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((30*HZ)/1000); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((10*HZ)/1000); restore_flags(flags); } @@ -289,8 +295,8 @@ TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_TeleInt(struct IsdnCard *card) +__initfunc(int +setup_TeleInt(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c index 4046c4357..866e8dac5 100644 --- a/drivers/isdn/hisax/teles0.c +++ b/drivers/isdn/hisax/teles0.c @@ -295,8 +295,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_teles0(struct IsdnCard *card) +__initfunc(int +setup_teles0(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c index 3210a6af6..0db245abc 100644 --- a/drivers/isdn/hisax/teles3.c +++ b/drivers/isdn/hisax/teles3.c @@ -321,8 +321,8 @@ Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -int __init -setup_teles3(struct IsdnCard *card) +__initfunc(int +setup_teles3(struct IsdnCard *card)) { u_char val; struct IsdnCardState *cs = card->cs; diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c index 9ffe99918..eee4ba322 100644 --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -42,9 +42,6 @@ #include "hscx.h" #include "isdnl1.h" #include <linux/pci.h> -#ifndef COMPAT_HAS_NEW_PCI -#include <linux/bios32.h> -#endif extern const char *CardType[]; const char *telespci_revision = "$Revision: 2.9 $"; @@ -304,29 +301,19 @@ TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) return(0); } -#ifdef COMPAT_HAS_NEW_PCI static struct pci_dev *dev_tel __initdata = NULL; -#else -static int pci_index __initdata = 0; -#endif -int __init -setup_telespci(struct IsdnCard *card) +__initfunc(int +setup_telespci(struct IsdnCard *card)) { struct IsdnCardState *cs = card->cs; char tmp[64]; -#ifndef COMPAT_HAS_NEW_PCI - u_char pci_bus, pci_device_fn, pci_irq; - u_int pci_memaddr; - u_char found = 0; -#endif strcpy(tmp, telespci_revision); printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (cs->typ != ISDN_CTYPE_TELESPCI) return (0); #if CONFIG_PCI -#ifdef COMPAT_HAS_NEW_PCI if (!pci_present()) { printk(KERN_ERR "TelesPCI: no PCI bus present\n"); return(0); @@ -337,41 +324,15 @@ setup_telespci(struct IsdnCard *card) printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); return(0); } - cs->hw.teles0.membase = (u_int) ioremap(get_pcibase(dev_tel, 0), + cs->hw.teles0.membase = (u_int) ioremap(dev_tel->resource[ 0].start, PAGE_SIZE); printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", - get_pcibase(dev_tel, 0), dev_tel->irq); + dev_tel->resource[ 0].start, dev_tel->irq); } else { printk(KERN_WARNING "TelesPCI: No PCI card found\n"); return(0); } #else - for (; pci_index < 0xff; pci_index++) { - if (pcibios_find_device (0x11DE, 0x6120, - pci_index, &pci_bus, &pci_device_fn) - == PCIBIOS_SUCCESSFUL) { - found = 1; - } else { - break; - } - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq); - - printk(KERN_INFO "Found: Zoran, base-address: 0x%x," - " irq: 0x%x\n", pci_memaddr, pci_irq); - break; - } - if (!found) { - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return(0); - } - pci_index++; - cs->irq = pci_irq; - cs->hw.teles0.membase = (u_int) vremap(pci_memaddr, PAGE_SIZE); -#endif /* COMPAT_HAS_NEW_PCI */ -#else printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); return (0); diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c new file mode 100644 index 000000000..724ce52c9 --- /dev/null +++ b/drivers/isdn/hisax/w6692.c @@ -0,0 +1,1063 @@ +/* $Id: w6692.c,v 1.1 1999/09/04 06:28:58 keil Exp $ + + * w6692.c Winbond W6692 specific routines + * + * Author Petr Novak <petr.novak@i.cz> + * (based on HiSax driver by Karsten Keil) + * + * This file is (c) under GNU PUBLIC LICENSE + * + * $Log: w6692.c,v $ + * Revision 1.1 1999/09/04 06:28:58 keil + * first revision + * + * + * + */ + +#include <linux/config.h> +#define __NO_VERSION__ +#include "hisax.h" +#include "w6692.h" +#include "isdnl1.h" +#include <linux/interrupt.h> +#include <linux/pci.h> + +#define PCI_VEND_ASUSCOM 0x675 +#define PCI_DEV_ASUSCOMPCI1 0x1702 +#ifndef PCI_VENDOR_ID_WINBOND2 +#define PCI_VENDOR_ID_WINBOND2 0x1050 +#endif +#define PCI_DEVICE_W6692 0x6692 + +/* table entry in the PCI devices list */ +typedef struct { + int vendor_id; + int device_id; + char *vendor_name; + char *card_name; +} PCI_ENTRY; + +static const PCI_ENTRY id_list[] = +{ + {PCI_VEND_ASUSCOM, PCI_DEV_ASUSCOMPCI1, "AsusCom", "TA XXX"}, + {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_W6692, "Winbond", "W6692"}, + {0, 0, NULL, NULL} +}; + +extern const char *CardType[]; + +const char *w6692_revision = "$Revision: 1.1 $"; + +#define DBUSY_TIMER_VALUE 80 + +static char *W6692Ver[] HISAX_INITDATA = +{"W6692 V00", "W6692 V01", "W6692 V10", + "W6692 V11"}; + +static void +W6692Version(struct IsdnCardState *cs, char *s) +{ + int val; + + val = cs->readW6692(cs, W_D_RBCH); + printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]); +} + +static void +ph_command(struct IsdnCardState *cs, unsigned int command) +{ + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_command %x", command); + cs->writeisac(cs, W_CIX, command); +} + + +static void +W6692_new_ph(struct IsdnCardState *cs) +{ + switch (cs->dc.w6692.ph_state) { + case (W_L1CMD_RST): + ph_command(cs, W_L1CMD_DRC); + l1_msg(cs, HW_RESET | INDICATION, NULL); + /* fallthru */ + case (W_L1IND_CD): + l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL); + break; + case (W_L1IND_DRD): + l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL); + break; + case (W_L1IND_CE): + l1_msg(cs, HW_POWERUP | CONFIRM, NULL); + break; + case (W_L1IND_LD): + l1_msg(cs, HW_RSYNC | INDICATION, NULL); + break; + case (W_L1IND_ARD): + l1_msg(cs, HW_INFO2 | INDICATION, NULL); + break; + case (W_L1IND_AI8): + l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL); + break; + case (W_L1IND_AI10): + l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL); + break; + default: + break; + } +} + +static void +W6692_bh(struct IsdnCardState *cs) +{ + struct PStack *stptr; + + if (!cs) + return; + if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { + if (cs->debug) + debugl1(cs, "D-Channel Busy cleared"); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr = stptr->next; + } + } + if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) + W6692_new_ph(cs); + if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) + DChannel_proc_rcv(cs); + if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) + DChannel_proc_xmt(cs); +/* + if (test_and_clear_bit(D_RX_MON1, &cs->event)) + arcofi_fsm(cs, ARCOFI_RX_END, NULL); + if (test_and_clear_bit(D_TX_MON1, &cs->event)) + arcofi_fsm(cs, ARCOFI_TX_END, NULL); + */ +} + +void +W6692_sched_event(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + queue_task(&cs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void +W6692B_sched_event(struct BCState *bcs, int event) +{ + bcs->event |= 1 << event; + queue_task(&bcs->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +static void +W6692_empty_fifo(struct IsdnCardState *cs, int count) +{ + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + save_flags(flags); + cli(); + cs->readW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + restore_flags(flags); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +static void +W6692_fill_fifo(struct IsdnCardState *cs) +{ + int count, more; + u_char *ptr; + long flags; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_fill_fifo"); + + if (!cs->tx_skb) + return; + + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > W_D_FIFO_THRESH) { + more = !0; + count = W_D_FIFO_THRESH; + } + save_flags(flags); + cli(); + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); + restore_flags(flags); + if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + debugl1(cs, "W6692_fill_fifo dbusytimer running"); + del_timer(&cs->dbusytimer); + } + init_timer(&cs->dbusytimer); + cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); + add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } +} + +static void +W6692B_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + long flags; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_empty_fifo"); + + if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + bcs->hw.w6692.rcvidx = 0; + return; + } + ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; + bcs->hw.w6692.rcvidx += count; + save_flags(flags); + cli(); + READW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_empty_fifo %c cnt %d", + bcs->hw.w6692.bchan ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static void +W6692B_fill_fifo(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + int more, count; + u_char *ptr; + long flags; + + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > W_B_FIFO_THRESH) { + more = !0; + count = W_B_FIFO_THRESH; + } else + count = bcs->tx_skb->len; + + save_flags(flags); + cli(); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.w6692.count += count; + WRITEW6692BFIFO(cs, bcs->hw.w6692.bchan, ptr, count); + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); + restore_flags(flags); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_fill_fifo %c cnt %d", + bcs->hw.w6692.bchan ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } +} + +static void +W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) +{ + u_char val; + u_char r; + struct BCState *bcs = cs->bcs + bchan; + struct sk_buff *skb; + int count; + + val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR); + debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val); + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) { + debugl1(cs, "W6692B not INIT yet"); + return; + } + if (val & W_B_EXI_RME) { /* RME */ + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) { + if ((r & W_B_STAR_RDOV) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B RDOV mode=%d", + bcs->mode); + if (r & W_B_STAR_CRCE) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B CRC error"); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); + } else { + count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); + if (count == 0) + count = W_B_FIFO_THRESH; + W6692B_empty_fifo(bcs, count); + if ((count = bcs->hw.w6692.rcvidx) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "W6692 Bchan Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.w6692.rcvidx = 0; + W6692B_sched_event(bcs, B_RCVBUFREADY); + } + if (val & W_B_EXI_RMR) { /* RMR */ + W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.w6692.rcvidx = 0; + W6692B_sched_event(bcs, B_RCVBUFREADY); + } + } + if (val & W_B_EXI_XFR) { /* XFR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + W6692B_fill_fifo(bcs); + return; + } else { + if (bcs->st->lli.l1writewakeup && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) + bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.w6692.count); + dev_kfree_skb(bcs->tx_skb); + bcs->hw.w6692.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.w6692.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_sched_event(bcs, B_XMTBUFREADY); + } + } + if (val & W_B_EXI_XDUN) { /* XDUN */ + if (bcs->mode == 1) + W6692B_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + cs->BC_Write_Reg(cs, bcs->hw.w6692.bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B EXIR %x Lost TX", val); + } + } +} + +static void +W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val, exval, v1; + struct sk_buff *skb; + unsigned int count; + long flags; + int icnt = 5; + + if (!cs) { + printk(KERN_WARNING "W6692: Spurious interrupt!\n"); + return; + } + val = cs->readW6692(cs, W_ISTA); + + StartW6692: + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 ISTA %x", val); + + if (val & W_INT_D_RME) { /* RME */ + exval = cs->readW6692(cs, W_D_RSTA); + if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { + if (exval & W_D_RSTA_RDOV) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 RDOV"); + if (exval & W_D_RSTA_CRCE) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D-channel CRC error"); + if (exval & W_D_RSTA_RMB) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D-channel ABORT"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); + } else { + count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); + if (count == 0) + count = W_D_FIFO_THRESH; + W6692_empty_fifo(cs, count); + save_flags(flags); + cli(); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } + restore_flags(flags); + } + cs->rcvidx = 0; + W6692_sched_event(cs, D_RCVBUFREADY); + } + if (val & W_INT_D_RMR) { /* RMR */ + W6692_empty_fifo(cs, W_D_FIFO_THRESH); + } + if (val & W_INT_D_XFR) { /* XFR */ + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + W6692_fill_fifo(cs); + goto afterXFR; + } else { + dev_kfree_skb(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else + W6692_sched_event(cs, D_XMTBUFREADY); + } + afterXFR: + if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 spurious XINT!"); + } + if (val & W_INT_D_EXI) { /* EXI */ + exval = cs->readW6692(cs, W_D_EXIR); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 D_EXIR %02x", exval); + if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */ + debugl1(cs, "W6692 D-chan underrun/collision"); + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n"); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n"); + debugl1(cs, "W6692 XDUN/XCOL no skb"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); + } + } + if (exval & W_D_EXI_RDOV) { /* RDOV */ + debugl1(cs, "W6692 D-channel RDOV"); + printk(KERN_WARNING "HiSax: W6692 D-RDOV\n"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST); + } + if (exval & W_D_EXI_TIN2) { /* TIN2 - never */ + debugl1(cs, "W6692 spurious TIN2 interrupt"); + } + if (exval & W_D_EXI_MOC) { /* MOC - not supported */ + debugl1(cs, "W6692 spurious MOC interrupt"); + v1 = cs->readW6692(cs, W_MOSR); + debugl1(cs, "W6692 MOSR %02x", v1); + } + if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ + v1 = cs->readW6692(cs, W_CIR); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "W6692 ISC CIR=0x%02X", v1); + if (v1 & W_CIR_ICC) { + cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state); + W6692_sched_event(cs, D_L1STATECHANGE); + } + if (v1 & W_CIR_SCC) { + v1 = cs->readW6692(cs, W_SQR); + debugl1(cs, "W6692 SCC SQR=0x%02X", v1); + } + } + if (exval & W_D_EXI_WEXP) { + debugl1(cs, "W6692 spurious WEXP interrupt!"); + } + if (exval & W_D_EXI_TEXP) { + debugl1(cs, "W6692 spurious TEXP interrupt!"); + } + } + if (val & W_INT_B1_EXI) { + debugl1(cs, "W6692 B channel 1 interrupt"); + W6692B_interrupt(cs, 0); + } + if (val & W_INT_B2_EXI) { + debugl1(cs, "W6692 B channel 2 interrupt"); + W6692B_interrupt(cs, 1); + } + val = cs->readW6692(cs, W_ISTA); + if (val && icnt) { + icnt--; + goto StartW6692; + } + if (!icnt) { + printk(KERN_WARNING "W6692 IRQ LOOP\n"); + cs->writeW6692(cs, W_IMASK, 0xff); + } +} + +static void +W6692_l1hw(struct PStack *st, int pr, void *arg) +{ + struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; + struct sk_buff *skb = arg; + int val; + + switch (pr) { + case (PH_DATA | REQUEST): + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + W6692_fill_fifo(cs); + } + break; + case (PH_PULL | INDICATION): + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + W6692_fill_fifo(cs); + break; + case (PH_PULL | REQUEST): +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (HW_RESET | REQUEST): + if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) + ph_command(cs, W_L1CMD_ECK); + else { + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + } + break; + case (HW_ENABLE | REQUEST): + ph_command(cs, W_L1CMD_ECK); + break; + case (HW_INFO3 | REQUEST): + ph_command(cs, W_L1CMD_AR8); + break; + case (HW_TESTLOOP | REQUEST): + val = 0; + if (1 & (long) arg) + val |= 0x0c; + if (2 & (long) arg) + val |= 0x3; + /* !!! not implemented yet */ + break; + case (HW_DEACTIVATE | RESPONSE): + discard_queue(&cs->rq); + discard_queue(&cs->sq); + if (cs->tx_skb) { + dev_kfree_skb(cs->tx_skb); + cs->tx_skb = NULL; + } + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + W6692_sched_event(cs, D_CLEARBUSY); + break; + default: + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_l1hw unknown %04x", pr); + break; + } +} + +static void +setstack_W6692(struct PStack *st, struct IsdnCardState *cs) +{ + st->l1.l1hw = W6692_l1hw; +} + +static void +DC_Close_W6692(struct IsdnCardState *cs) +{ +} + +static void +dbusy_timer_handler(struct IsdnCardState *cs) +{ + struct PStack *stptr; + int rbch, star; + + if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + rbch = cs->readW6692(cs, W_D_RBCH); + star = cs->readW6692(cs, W_D_STAR); + if (cs->debug) + debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x", + rbch, star); + if (star & W_D_STAR_XBZ) { /* D-Channel Busy */ + test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); + stptr = cs->stlist; + while (stptr != NULL) { + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr = stptr->next; + } + } else { + /* discard frame; reset transceiver */ + test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags); + if (cs->tx_skb) { + dev_kfree_skb(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } else { + printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n"); + debugl1(cs, "D-Channel Busy no skb"); + } + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); + } + } +} + +static void +W6692Bmode(struct BCState *bcs, int mode, int bc) +{ + struct IsdnCardState *cs = bcs->cs; + int bchan = bcs->hw.w6692.bchan; + + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "w6692 %c mode %d ichan %d", + '1' + bchan, mode, bc); + bcs->mode = mode; + bcs->channel = bc; + + switch (mode) { + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0); + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); + cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff); + break; + } + if (mode) + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | + W_B_CMDR_RACT | W_B_CMDR_XRST); + cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00); +} + +static void +W6692_l2l1(struct PStack *st, int pr, void *arg) +{ + struct sk_buff *skb = arg; + long flags; + + switch (pr) { + case (PH_DATA | REQUEST): + save_flags(flags); + cli(); + if (st->l1.bcs->tx_skb) { + skb_queue_tail(&st->l1.bcs->squeue, skb); + restore_flags(flags); + } else { + st->l1.bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->hw.w6692.count = 0; + restore_flags(flags); + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + } + break; + case (PH_PULL | INDICATION): + if (st->l1.bcs->tx_skb) { + printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n"); + break; + } + test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + st->l1.bcs->tx_skb = skb; + st->l1.bcs->hw.w6692.count = 0; + st->l1.bcs->cs->BC_Send_Data(st->l1.bcs); + break; + case (PH_PULL | REQUEST): + if (!st->l1.bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + break; + case (PH_ACTIVATE | REQUEST): + test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc); + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | REQUEST): + l1_msg_b(st, pr, arg); + break; + case (PH_DEACTIVATE | CONFIRM): + test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); + W6692Bmode(st->l1.bcs, 0, st->l1.bc); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + break; + } +} + +static void +close_w6692state(struct BCState *bcs) +{ + W6692Bmode(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.w6692.rcvbuf) { + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + discard_queue(&bcs->rqueue); + discard_queue(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } +} + +static int +open_w6692state(struct IsdnCardState *cs, struct BCState *bcs) +{ + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for w6692.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.w6692.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); +} + +static int +setstack_w6692(struct PStack *st, struct BCState *bcs) +{ + bcs->channel = st->l1.bc; + if (open_w6692state(st->l1.hardware, bcs)) + return (-1); + st->l1.bcs = bcs; + st->l2.l2l1 = W6692_l2l1; + setstack_manager(st); + bcs->st = st; + setstack_l1_B(st); + return (0); +} + +HISAX_INITFUNC(void initW6692(struct IsdnCardState *cs, int part)) +{ + if (part & 1) { + cs->tqueue.routine = (void *) (void *) W6692_bh; + cs->setstack_d = setstack_W6692; + cs->DC_Close = DC_Close_W6692; + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + + cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); + cs->writeW6692(cs, W_D_CTL, 0x00); + cs->writeW6692(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_D_SAM, 0xff); + cs->writeW6692(cs, W_D_TAM, 0xff); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT); + cs->writeW6692(cs, W_IMASK, 0x18); + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + ph_command(cs, W_L1CMD_ECK); + + cs->bcs[0].BC_SetStack = setstack_w6692; + cs->bcs[1].BC_SetStack = setstack_w6692; + cs->bcs[0].BC_Close = close_w6692state; + cs->bcs[1].BC_Close = close_w6692state; + cs->bcs[0].hw.w6692.bchan = 0; + cs->bcs[1].hw.w6692.bchan = 1; + W6692Bmode(cs->bcs, 0, 0); + W6692Bmode(cs->bcs + 1, 0, 0); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeW6692(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00); + /* Reset D-chan receiver and transmitter */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + } +} + +/* Interface functions */ + +static u_char +ReadW6692(struct IsdnCardState *cs, u_char offset) +{ + return (inb(cs->hw.w6692.iobase + offset)); +} + +static void +WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + offset); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); +} + +static u_char +ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset) +{ + return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); +} + +static void +WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); +} + +static int +w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + return (0); + case CARD_RELEASE: + release_region(cs->hw.w6692.iobase, 256); + return (0); + case CARD_INIT: + initW6692(cs, 3); + return (0); + case CARD_TEST: + return (0); + } + return (0); +} + +static int id_idx = 0; + +static struct pci_dev *dev_w6692 __initdata = NULL; + +__initfunc(int setup_w6692(struct IsdnCard *card)) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + u_char found = 0; + u_char pci_irq = 0; + u_int pci_ioaddr = 0; + + strcpy(tmp, w6692_revision); + printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_W6692) + return (0); +#if CONFIG_PCI + if (!pci_present()) { + printk(KERN_ERR "W6692: no PCI bus present\n"); + return (0); + } + while (id_list[id_idx].vendor_id) { + dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, + id_list[id_idx].device_id, + dev_w6692); + if (dev_w6692) + break; + id_idx++; + } + if (dev_w6692) { + found = 1; + pci_irq = dev_w6692->irq; + /* I think address 0 is allways the configuration area */ + /* and address 1 is the real IO space KKe 03.09.99 */ + pci_ioaddr = dev_w6692->resource[ 1].start; + } + if (!found) { + printk(KERN_WARNING "W6692: No PCI card found\n"); + return (0); + } + cs->irq = pci_irq; + if (!cs->irq) { + printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); + return (0); + } + pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK; + if (!pci_ioaddr) { + printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); + return (0); + } + cs->hw.w6692.iobase = pci_ioaddr; + printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", + id_list[id_idx].vendor_name, id_list[id_idx].card_name, + pci_ioaddr, dev_w6692->irq); + if (check_region((cs->hw.w6692.iobase), 256)) { + printk(KERN_WARNING + "HiSax: %s I/O ports %x-%x already in use\n", + id_list[id_idx].card_name, + cs->hw.w6692.iobase, + cs->hw.w6692.iobase + 255); + return (0); + } else { + request_region(cs->hw.w6692.iobase, 256, + id_list[id_idx].card_name); + } +#else + printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: W6692 unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + printk(KERN_INFO + "HiSax: %s config irq:%d I/O:%x\n", + id_list[id_idx].card_name, cs->irq, + cs->hw.w6692.iobase); + + cs->readW6692 = &ReadW6692; + cs->writeW6692 = &WriteW6692; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadW6692B; + cs->BC_Write_Reg = &WriteW6692B; + cs->BC_Send_Data = &W6692B_fill_fifo; + cs->cardmsg = &w6692_card_msg; + cs->irq_func = &W6692_interrupt; + W6692Version(cs, "W6692:"); + printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); + printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); + printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); + printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); + printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); + return (1); +} diff --git a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h new file mode 100644 index 000000000..4990b0082 --- /dev/null +++ b/drivers/isdn/hisax/w6692.h @@ -0,0 +1,190 @@ +/* $Id: w6692.h,v 1.1 1999/09/04 06:28:58 keil Exp $ + + * w6692.h Winbond W6692 specific defines + * + * Author Petr Novak <petr.novak@i.cz> + * + * + * $Log: w6692.h,v $ + * Revision 1.1 1999/09/04 06:28:58 keil + * first revision + * + * + * Revision 1.0 1999/08/28 21:58:00 pnovak + * first version + * + * + */ + +/* map W6692 functions to ISAC functions */ +#define readW6692 readisac +#define writeW6692 writeisac +#define readW6692fifo readisacfifo +#define writeW6692fifo writeisacfifo + +/* B-channel FIFO read/write routines */ + +#define READW6692BFIFO(cs,bchan,ptr,count) \ + insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count) + +#define WRITEW6692BFIFO(cs,bchan,ptr,count) \ + outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count) + +/* Specifications of W6692 registers */ + +#define W_D_RFIFO 0x00 /* R */ +#define W_D_XFIFO 0x04 /* W */ +#define W_D_CMDR 0x08 /* W */ +#define W_D_MODE 0x0c /* R/W */ +#define W_D_TIMR 0x10 /* R/W */ +#define W_ISTA 0x14 /* R_clr */ +#define W_IMASK 0x18 /* R/W */ +#define W_D_EXIR 0x1c /* R_clr */ +#define W_D_EXIM 0x20 /* R/W */ +#define W_D_STAR 0x24 /* R */ +#define W_D_RSTA 0x28 /* R */ +#define W_D_SAM 0x2c /* R/W */ +#define W_D_SAP1 0x30 /* R/W */ +#define W_D_SAP2 0x34 /* R/W */ +#define W_D_TAM 0x38 /* R/W */ +#define W_D_TEI1 0x3c /* R/W */ +#define W_D_TEI2 0x40 /* R/W */ +#define W_D_RBCH 0x44 /* R */ +#define W_D_RBCL 0x48 /* R */ +#define W_TIMR2 0x4c /* W */ +#define W_L1_RC 0x50 /* R/W */ +#define W_D_CTL 0x54 /* R/W */ +#define W_CIR 0x58 /* R */ +#define W_CIX 0x5c /* W */ +#define W_SQR 0x60 /* R */ +#define W_SQX 0x64 /* W */ +#define W_PCTL 0x68 /* R/W */ +#define W_MOR 0x6c /* R */ +#define W_MOX 0x70 /* R/W */ +#define W_MOSR 0x74 /* R_clr */ +#define W_MOCR 0x78 /* R/W */ +#define W_GCR 0x7c /* R/W */ + +#define W_B_RFIFO 0x80 /* R */ +#define W_B_XFIFO 0x84 /* W */ +#define W_B_CMDR 0x88 /* W */ +#define W_B_MODE 0x8c /* R/W */ +#define W_B_EXIR 0x90 /* R_clr */ +#define W_B_EXIM 0x94 /* R/W */ +#define W_B_STAR 0x98 /* R */ +#define W_B_ADM1 0x9c /* R/W */ +#define W_B_ADM2 0xa0 /* R/W */ +#define W_B_ADR1 0xa4 /* R/W */ +#define W_B_ADR2 0xa8 /* R/W */ +#define W_B_RBCL 0xac /* R */ +#define W_B_RBCH 0xb0 /* R */ + +#define W_XADDR 0xf4 /* R/W */ +#define W_XDATA 0xf8 /* R/W */ +#define W_EPCTL 0xfc /* W */ + +/* W6692 register bits */ + +#define W_D_CMDR_XRST 0x01 +#define W_D_CMDR_XME 0x02 +#define W_D_CMDR_XMS 0x08 +#define W_D_CMDR_STT 0x10 +#define W_D_CMDR_RRST 0x40 +#define W_D_CMDR_RACK 0x80 + +#define W_D_MODE_RLP 0x01 +#define W_D_MODE_DLP 0x02 +#define W_D_MODE_MFD 0x04 +#define W_D_MODE_TEE 0x08 +#define W_D_MODE_TMS 0x10 +#define W_D_MODE_RACT 0x40 +#define W_D_MODE_MMS 0x80 + +#define W_INT_B2_EXI 0x01 +#define W_INT_B1_EXI 0x02 +#define W_INT_D_EXI 0x04 +#define W_INT_XINT0 0x08 +#define W_INT_XINT1 0x10 +#define W_INT_D_XFR 0x20 +#define W_INT_D_RME 0x40 +#define W_INT_D_RMR 0x80 + +#define W_D_EXI_WEXP 0x01 +#define W_D_EXI_TEXP 0x02 +#define W_D_EXI_ISC 0x04 +#define W_D_EXI_MOC 0x08 +#define W_D_EXI_TIN2 0x10 +#define W_D_EXI_XCOL 0x20 +#define W_D_EXI_XDUN 0x40 +#define W_D_EXI_RDOV 0x80 + +#define W_D_STAR_DRDY 0x10 +#define W_D_STAR_XBZ 0x20 +#define W_D_STAR_XDOW 0x80 + +#define W_D_RSTA_RMB 0x10 +#define W_D_RSTA_CRCE 0x20 +#define W_D_RSTA_RDOV 0x40 + +#define W_D_CTL_SRST 0x20 + +#define W_CIR_SCC 0x80 +#define W_CIR_ICC 0x40 +#define W_CIR_COD_MASK 0x0f + +#define W_B_CMDR_XRST 0x01 +#define W_B_CMDR_XME 0x02 +#define W_B_CMDR_XMS 0x04 +#define W_B_CMDR_RACT 0x20 +#define W_B_CMDR_RRST 0x40 +#define W_B_CMDR_RACK 0x80 + +#define W_B_MODE_FTS0 0x01 +#define W_B_MODE_FTS1 0x02 +#define W_B_MODE_SW56 0x04 +#define W_B_MODE_BSW0 0x08 +#define W_B_MODE_BSW1 0x10 +#define W_B_MODE_EPCM 0x20 +#define W_B_MODE_ITF 0x40 +#define W_B_MODE_MMS 0x80 + +#define W_B_EXI_XDUN 0x01 +#define W_B_EXI_XFR 0x02 +#define W_B_EXI_RDOV 0x10 +#define W_B_EXI_RME 0x20 +#define W_B_EXI_RMR 0x40 + +#define W_B_STAR_XBZ 0x01 +#define W_B_STAR_XDOW 0x04 +#define W_B_STAR_RMB 0x10 +#define W_B_STAR_CRCE 0x20 +#define W_B_STAR_RDOV 0x40 + +#define W_B_RBCH_LOV 0x20 + +/* W6692 Layer1 commands */ + +#define W_L1CMD_ECK 0x00 +#define W_L1CMD_RST 0x01 +#define W_L1CMD_SCP 0x04 +#define W_L1CMD_SSP 0x02 +#define W_L1CMD_AR8 0x08 +#define W_L1CMD_AR10 0x09 +#define W_L1CMD_EAL 0x0a +#define W_L1CMD_DRC 0x0f + +/* W6692 Layer1 indications */ + +#define W_L1IND_CE 0x07 +#define W_L1IND_DRD 0x00 +#define W_L1IND_LD 0x04 +#define W_L1IND_ARD 0x08 +#define W_L1IND_TI 0x0a +#define W_L1IND_ATI 0x0b +#define W_L1IND_AI8 0x0c +#define W_L1IND_AI10 0x0d +#define W_L1IND_CD 0x0f + +/* FIFO thresholds */ +#define W_D_FIFO_THRESH 64 +#define W_B_FIFO_THRESH 64 diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 26ac3502d..92ee95a2e 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1,8 +1,8 @@ -/* $Id: icn.c,v 1.59 1999/08/28 22:10:55 keil Exp $ +/* $Id: icn.c,v 1.62 1999/09/06 07:29:35 fritz Exp $ * ISDN low-level module for the ICN active ISDN-Card. * - * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.c,v $ + * Revision 1.62 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * + * Revision 1.61 1999/09/03 14:06:58 fritz + * Fixed a memory leak. + * + * Revision 1.60 1999/08/31 11:20:32 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.59 1999/08/28 22:10:55 keil * __setup function should be static * @@ -238,7 +247,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.59 $"; +*revision = "$Revision: 1.62 $"; static int icn_addcard(int, char *, char *); @@ -467,7 +476,7 @@ icn_pollbchan_receive(int channel, icn_card * card) if (!eflag) { if ((cnt = card->rcvidx[channel])) { if (!(skb = dev_alloc_skb(cnt))) { - printk(KERN_WARNING "ïcn: receive out of memory\n"); + printk(KERN_WARNING "icn: receive out of memory\n"); break; } memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); @@ -545,12 +554,10 @@ icn_pollbchan_send(int channel, icn_card * card) if (!skb->len) { save_flags(flags); cli(); - if (card->xskb[channel]) { + if (card->xskb[channel]) card->xskb[channel] = NULL; - restore_flags(flags); - dev_kfree_skb(skb); - } else - restore_flags(flags); + restore_flags(flags); + dev_kfree_skb(skb); if (card->xlen[channel]) { cmd.command = ISDN_STAT_BSENT; cmd.driver = card->myid; @@ -1852,7 +1859,6 @@ icn_addcard(int port, char *id1, char *id2) #ifdef MODULE #define icn_init init_module #else -#ifdef COMPAT_HAS_NEW_SETUP #include <linux/init.h> static int __init icn_setup(char *line) @@ -1863,14 +1869,6 @@ icn_setup(char *line) static char sid2[20]; str = get_options(line, 2, ints); -#else -void -icn_setup(char *str, int *ints) -{ - char *p; - static char sid[20]; - static char sid2[20]; -#endif if (ints[0]) portbase = ints[1]; if (ints[0] > 1) @@ -1884,13 +1882,9 @@ icn_setup(char *str, int *ints) icn_id2 = sid2; } } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("icn=", icn_setup); -#else -} -#endif #endif /* MODULES */ int diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 3bd2819ce..6d40a695c 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -1,8 +1,8 @@ -/* $Id: icn.h,v 1.28 1997/10/10 15:56:18 fritz Exp $ +/* $Id: icn.h,v 1.29 1999/09/06 07:29:35 fritz Exp $ * ISDN lowlevel-module for the ICN active ISDN-Card. * - * Copyright 1994 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1994 by Fritz Elfert (fritz@isdn4linux.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: icn.h,v $ + * Revision 1.29 1999/09/06 07:29:35 fritz + * Changed my mail-address. + * * Revision 1.28 1997/10/10 15:56:18 fritz * New HL<->LL interface: * New BSENT callback with nr. of bytes included. diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c index 10414ee94..ba890846d 100644 --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.86 1999/07/31 12:59:42 armin Exp $ +/* $Id: isdn_common.c,v 1.93 1999/11/04 13:11:36 keil Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -21,6 +21,40 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.c,v $ + * Revision 1.93 1999/11/04 13:11:36 keil + * Reinit of v110 structs + * + * Revision 1.92 1999/10/31 15:59:50 he + * more skb headroom checks + * + * Revision 1.91 1999/10/28 22:48:45 armin + * Bugfix: isdn_free_channel() now frees the channel, + * even when the usage of the ttyI has changed. + * + * Revision 1.90 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * + * Revision 1.89 1999/10/16 14:46:47 keil + * replace kmalloc with vmalloc for the big dev struct + * + * Revision 1.88 1999/10/02 00:39:26 he + * Fixed a 2.3.x wait queue initialization (was causing panics) + * + * Revision 1.87 1999/09/12 16:19:39 detabc + * added abc features + * low cost routing for net-interfaces (only the HL side). + * need more implementation in the isdnlog-utility + * udp info support (first part). + * different EAZ on outgoing call's. + * more checks on D-Channel callbacks (double use of channels). + * tested and running with kernel 2.3.17 + * * Revision 1.86 1999/07/31 12:59:42 armin * Added tty fax capabilities. * @@ -362,6 +396,7 @@ #include <linux/module.h> #include <linux/version.h> #include <linux/poll.h> +#include <linux/vmalloc.h> #include <linux/isdn.h> #include "isdn_common.h" #include "isdn_tty.h" @@ -381,7 +416,7 @@ isdn_dev *dev = (isdn_dev *) 0; -static char *isdn_revision = "$Revision: 1.86 $"; +static char *isdn_revision = "$Revision: 1.93 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; @@ -1039,9 +1074,6 @@ isdn_status_callback(isdn_ctrl * c) isdn_free_queue(&dev->drv[di]->rpqueue[i]); kfree(dev->drv[di]->rpqueue); kfree(dev->drv[di]->rcv_waitq); -#ifndef COMPAT_HAS_NEW_WAITQ - kfree(dev->drv[di]->snd_waitq); -#endif kfree(dev->drv[di]); dev->drv[di] = NULL; dev->drvid[di][0] = '\0'; @@ -1103,11 +1135,7 @@ isdn_getnum(char **p) * of the mapping (di,ch)<->minor, happen during the sleep? --he */ int -#ifdef COMPAT_HAS_NEW_WAITQ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) -#else -isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep) -#endif { int left; int count; @@ -1535,6 +1563,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) * are serialized by means of a semaphore. */ switch (cmd) { + case IIOCNETLCR: + printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); + return -ENODEV; #ifdef CONFIG_NETDEVICES case IIOCNETAIF: /* Add a network-interface */ @@ -2092,13 +2123,19 @@ isdn_free_channel(int di, int ch, int usage) save_flags(flags); cli(); for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (((dev->usage[i] & ISDN_USAGE_MASK) == usage) && + if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) && (dev->drvmap[i] == di) && (dev->chanmap[i] == ch)) { dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE); strcpy(dev->num[i], "???"); dev->ibytes[i] = 0; dev->obytes[i] = 0; +// 20.10.99 JIM, try to reinitialize v110 ! + dev->v110emu[i] = 0; + atomic_set(&(dev->v110use[i]), 0); + isdn_v110_close(dev->v110[i]); + dev->v110[i] = NULL; +// 20.10.99 JIM, try to reinitialize v110 ! isdn_info_update(); isdn_free_queue(&dev->drv[di]->rpqueue[ch]); } @@ -2180,8 +2217,33 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) /* V.110 must always be acknowledged */ ack = 1; ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb); - } else - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); + } else { + int hl = dev->drv[drvidx]->interface->hl_hdrlen; + + if( skb_headroom(skb) < hl ){ + /* + * This should only occur when new HL driver with + * increased hl_hdrlen was loaded after netdevice + * was created and connected to the new driver. + * + * The V.110 branch (re-allocates on its own) does + * not need this + */ + struct sk_buff * skb_tmp; + + skb_tmp = skb_realloc_headroom(skb, hl); + printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); + if (!skb_tmp) return -ENOMEM; /* 0 better? */ + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); + if( ret > 0 ){ + dev_kfree_skb(skb); + } else { + dev_kfree_skb(skb_tmp); + } + } else { + ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); + } + } if (ret > 0) { dev->obytes[idx] += ret; if (dev->v110[idx]) { @@ -2202,43 +2264,11 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) int register_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL); - - if (!new) { - printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n"); - return -1; - } - while (*pp && (*pp)->orig != m) - pp = &(*pp)->next; - if (*pp != NULL) { - printk(KERN_WARNING "isdn: Module %s already registered\n", m->name); - return -1; - } - while (*pp && ((*pp)->module.priority < m->priority)) - pp = &(*pp)->next; - new->next = *pp; - new->orig = m; - new->module = *m; - - *pp = new; -#endif return 0; } int unregister_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - - while (*pp && *pp != m) - pp = &(*pp)->next; - if (*pp == NULL) { - printk(KERN_WARNING "isdn: Module %s not found\n", m->name); - return -1; - } -#endif return 0; } @@ -2248,9 +2278,7 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) int j, k, m; ulong flags; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&d->st_waitq); -#endif if (d->flags & DRV_FLAG_RUNNING) return -1; if (n < 1) return 0; @@ -2300,14 +2328,9 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) if ((adding) && (d->rcv_waitq)) kfree(d->rcv_waitq); -#ifdef COMPAT_HAS_NEW_WAITQ d->rcv_waitq = (wait_queue_head_t *) kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL); if (!d->rcv_waitq) { -#else - if (!(d->rcv_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { -#endif printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); if (!adding) { kfree(d->rpqueue); @@ -2316,30 +2339,11 @@ isdn_add_channels(driver *d, int drvidx, int n, int adding) } return -1; } -#ifdef COMPAT_HAS_NEW_WAITQ d->snd_waitq = d->rcv_waitq + m; for (j = 0; j < m; j++) { init_waitqueue_head(&d->rcv_waitq[j]); init_waitqueue_head(&d->snd_waitq[j]); } -#else - memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m); - - if ((adding) && (d->snd_waitq)) - kfree(d->snd_waitq); - if (!(d->snd_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n"); - if (!adding) { - kfree(d->rcv_waitq); - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - } - return -1; - } - memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m); -#endif dev->channels += n; save_flags(flags); @@ -2513,33 +2517,26 @@ isdn_init(void) int i; char tmprev[50]; - sti(); - if (!(dev = (isdn_dev *) kmalloc(sizeof(isdn_dev), GFP_KERNEL))) { + if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); return -EIO; } memset((char *) dev, 0, sizeof(isdn_dev)); init_timer(&dev->timer); dev->timer.function = isdn_timer_funct; -#ifdef COMPAT_HAS_NEW_WAITQ init_MUTEX(&dev->sem); init_waitqueue_head(&dev->info_waitq); -#else - dev->sem = MUTEX; -#endif for (i = 0; i < ISDN_MAX_CHANNELS; i++) { dev->drvmap[i] = -1; dev->chanmap[i] = -1; dev->m_idx[i] = -1; strcpy(dev->num[i], "???"); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&dev->mdm.info[i].open_wait); init_waitqueue_head(&dev->mdm.info[i].close_wait); -#endif } if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { printk(KERN_WARNING "isdn: Could not register control devices\n"); - kfree(dev); + vfree(dev); return -EIO; } if ((i = isdn_tty_modem_init()) < 0) { @@ -2548,7 +2545,7 @@ isdn_init(void) tty_unregister_driver(&dev->mdm.cua_modem); if (i <= -2) tty_unregister_driver(&dev->mdm.tty_modem); - kfree(dev); + vfree(dev); unregister_chrdev(ISDN_MAJOR, "isdn"); return -EIO; } @@ -2560,7 +2557,7 @@ isdn_init(void) for (i = 0; i < ISDN_MAX_CHANNELS; i++) kfree(dev->mdm.info[i].xmit_buf - 4); unregister_chrdev(ISDN_MAJOR, "isdn"); - kfree(dev); + vfree(dev); return -EIO; } #endif /* CONFIG_ISDN_PPP */ @@ -2629,7 +2626,7 @@ cleanup_module(void) printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n"); } else { del_timer(&dev->timer); - kfree(dev); + vfree(dev); printk(KERN_NOTICE "ISDN-subsystem unloaded\n"); } restore_flags(flags); diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h index e6fb122f6..3c60d7c80 100644 --- a/drivers/isdn/isdn_common.h +++ b/drivers/isdn/isdn_common.h @@ -1,4 +1,4 @@ -/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $ +/* $Id: isdn_common.h,v 1.17 1999/10/27 21:21:17 detabc Exp $ * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). * @@ -21,6 +21,15 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_common.h,v $ + * Revision 1.17 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * * Revision 1.16 1999/07/01 08:29:54 keil * compatibility to 2.3 kernel * @@ -118,11 +127,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di); extern void isdn_timer_ctrl(int tf, int onoff); extern void isdn_unexclusive_channel(int di, int ch); extern int isdn_getnum(char **); -#ifdef COMPAT_HAS_NEW_WAITQ extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *); -#else -extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**); -#endif extern int isdn_get_free_channel(int, int, int, int, int); extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); extern int register_isdn(isdn_if * i); diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c index 9d54f0127..e1c7cb75d 100644 --- a/drivers/isdn/isdn_net.c +++ b/drivers/isdn/isdn_net.c @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.89 1999/08/22 20:26:03 calle Exp $ +/* $Id: isdn_net.c,v 1.95 1999/10/27 21:21:17 detabc Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -21,6 +21,38 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_net.c,v $ + * Revision 1.95 1999/10/27 21:21:17 detabc + * Added support for building logically-bind-group's per interface. + * usefull for outgoing call's with more then one isdn-card. + * + * Switchable support to dont reset the hangup-timeout for + * receive frames. Most part's of the timru-rules for receiving frames + * are now obsolete. If the input- or forwarding-firewall deny + * the frame, the line will be not hold open. + * + * Revision 1.94 1999/10/02 11:07:02 he + * Changed tbusy logic in indn_net.c + * + * Revision 1.93 1999/09/23 22:22:41 detabc + * added tcp-keepalive-detect with local response (ipv4 only) + * added host-only-interface support + * (source ipaddr == interface ipaddr) (ipv4 only) + * ok with kernel 2.3.18 and 2.2.12 + * + * Revision 1.92 1999/09/13 23:25:17 he + * serialized xmitting frames from isdn_ppp and BSENT statcallb + * + * Revision 1.91 1999/09/12 16:19:39 detabc + * added abc features + * low cost routing for net-interfaces (only the HL side). + * need more implementation in the isdnlog-utility + * udp info support (first part). + * different EAZ on outgoing call's. + * more checks on D-Channel callbacks (double use of channels). + * tested and running with kernel 2.3.17 + * + * Revision 1.90 1999/09/04 22:21:39 detabc + * * Revision 1.89 1999/08/22 20:26:03 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -360,13 +392,58 @@ #include "isdn_concap.h" #endif + +#ifndef ISDN_NEW_TBUSY +#define ISDN_NEW_TBUSY +#endif +#ifdef ISDN_NEW_TBUSY +/* + * Outline of new tbusy handling: + * + * Old method, roughly spoken, consisted of setting tbusy when entering + * isdn_net_start_xmit() and at several other locations and clearing + * it from isdn_net_start_xmit() thread when sending was successful. + * + * With 2.3.x multithreaded network core, to prevent problems, tbusy should + * only be set by the isdn_net_start_xmit() thread and only when a tx-busy + * condition is detected. Other threads (in particular isdn_net_stat_callb()) + * are only allowed to clear tbusy. + * + * -HE + */ + +/* + * Tell upper layers that the network device is ready to xmit more frames. + */ +static void __inline__ isdn_net_dev_xon(struct net_device * dev) +{ + dev->tbusy = 0; + mark_bh(NET_BH); +} + +static void __inline__ isdn_net_lp_xon(isdn_net_local * lp) +{ + lp->netdev->dev.tbusy = 0; + if(lp->master) lp->master->tbusy = 0; + mark_bh(NET_BH); +} + +/* + * Ask upper layers to temporarily cease passing us more xmit frames. + */ +static void __inline__ isdn_net_dev_xoff(struct net_device * dev) +{ + dev->tbusy = 1; +} +#endif + /* Prototypes */ int isdn_net_force_dial_lp(isdn_net_local *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); static int isdn_net_xmit(struct net_device *, isdn_net_local *, struct sk_buff *); -char *isdn_net_revision = "$Revision: 1.89 $"; +char *isdn_net_revision = "$Revision: 1.95 $"; /* * Code for raw-networking over ISDN @@ -408,7 +485,11 @@ isdn_net_reset(struct net_device *dev) save_flags(flags); cli(); /* Avoid glitch on writes to CMD regs */ dev->interrupt = 0; +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xon(dev); +#else dev->tbusy = 0; +#endif #ifdef CONFIG_ISDN_X25 if( cprot && cprot -> pops && dops ) cprot -> pops -> restart ( cprot, dev, dops ); @@ -607,6 +688,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) (!lp->dialstate)) { lp->stats.tx_packets++; lp->stats.tx_bytes += c->parm.length; + /* some HL drivers deliver + ISDN_STAT_BSENT from hw interrupt. + Output routines in isdn_ppp are now + called with irq disabled such that + dequeueing the sav_skb while another + frame is sent will not occur. + */ if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) { struct net_device *mdev; if (lp->master) @@ -615,13 +703,19 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) mdev = &lp->netdev->dev; if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) { lp->sav_skb = NULL; +#ifndef ISDN_NEW_TBUSY mark_bh(NET_BH); +#endif } else { return 1; } } +#ifdef ISDN_NEW_TBUSY + isdn_net_lp_xon(lp); +#else if (test_and_clear_bit(0, (void *) &(p->dev.tbusy))) mark_bh(NET_BH); +#endif } return 1; case ISDN_STAT_DCONN: @@ -704,7 +798,6 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) lp->dialstarted = 0; lp->dialwait_timer = 0; - /* Immediately send first skb to speed up arp */ #ifdef CONFIG_ISDN_PPP if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) isdn_ppp_wakeup_daemon(lp); @@ -715,11 +808,15 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) if( pops->connect_ind) pops->connect_ind(cprot); #endif /* CONFIG_ISDN_X25 */ + /* Immediately send first skb to speed up arp */ if (lp->first_skb) { if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb))) lp->first_skb = NULL; } +#ifdef ISDN_NEW_TBUSY + if(! lp->first_skb) isdn_net_lp_xon(lp); +#else else { /* * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb). @@ -728,6 +825,7 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c) lp->netdev->dev.tbusy = 0; mark_bh(NET_BH); } +#endif /* ISDN_NEW_TBUSY */ return 1; } break; @@ -1162,6 +1260,7 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) break; } printk(KERN_INFO "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n", + p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19], addinfo); @@ -1180,8 +1279,12 @@ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp) * standard send-routine, else send directly. * * Return: 0 on success, !0 on failure. + */ +#ifndef ISDN_NEW_TBUSY +/* * Side-effects: ndev->tbusy is cleared on success. */ +#endif int isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb) @@ -1192,13 +1295,17 @@ isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp, ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); if (ret == len) { lp->transcount += len; +#ifndef ISDN_NEW_TBUSY clear_bit(0, (void *) &(ndev->tbusy)); +#endif return 0; } if (ret < 0) { dev_kfree_skb(skb); lp->stats.tx_errors++; +#ifndef ISDN_NEW_TBUSY clear_bit(0, (void *) &(ndev->tbusy)); +#endif return 0; } return 1; @@ -1244,7 +1351,11 @@ isdn_net_xmit(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb) if (lp->srobin == ndev) ret = isdn_net_send_skb(ndev, lp, skb); else +#ifdef ISDN_NEW_TBUSY + ret = isdn_net_start_xmit(skb, lp->srobin); +#else ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin); +#endif lp->srobin = (slp->slave) ? slp->slave : ndev; slp = (isdn_net_local *) (lp->srobin->priv); if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0))) @@ -1298,15 +1409,19 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) #ifdef CONFIG_ISDN_X25 struct concap_proto * cprot = lp -> netdev -> cprot; #endif - if (ndev->tbusy) { if (jiffies - ndev->trans_start < (2 * HZ)) return 1; if (!lp->dialstate) lp->stats.tx_errors++; ndev->trans_start = jiffies; +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xon(ndev); +#endif } +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */ +#endif #ifdef CONFIG_ISDN_X25 /* At this point hard_start_xmit() passes control to the encapsulation protocol (if present). @@ -1320,7 +1435,11 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) when a dl_establish request is received from the upper layer. */ if( cprot ) { - return cprot -> pops -> encap_and_xmit ( cprot , skb); + int ret = cprot -> pops -> encap_and_xmit ( cprot , skb); +#ifdef ISDN_NEW_TBUSY + if(ret) isdn_net_dev_xoff(ndev); +#endif + return ret; } else #endif /* auto-dialing xmit function */ @@ -1339,7 +1458,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } if (lp->phone[1]) { @@ -1355,7 +1476,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) if(jiffies < lp->dialwait_timer) { isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif restore_flags(flags); return 0; } else @@ -1364,22 +1487,28 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* Grab a free ISDN-Channel */ if (((chi = - isdn_get_free_channel(ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) && + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel) + ) < 0) && ((chi = - isdn_get_free_channel(ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel^1)) < 0)) { + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel^1) + ) < 0)) { restore_flags(flags); isdn_net_unreachable(ndev, skb, "No channel"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } /* Log packet, which triggered dialing */ @@ -1399,6 +1528,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) } restore_flags(flags); isdn_net_dial(); /* Initiate dialing */ +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#endif return 1; /* let upper layer requeue skb packet */ } #endif @@ -1412,7 +1544,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) } lp->first_skb = skb; /* Initiate dialing */ +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif restore_flags(flags); isdn_net_dial(); return 0; @@ -1420,21 +1554,37 @@ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev) isdn_net_unreachable(ndev, skb, "No phone number"); dev_kfree_skb(skb); +#ifndef ISDN_NEW_TBUSY ndev->tbusy = 0; +#endif return 0; } } else { - /* Connection is established, try sending */ + /* Device is connected to an ISDN channel */ ndev->trans_start = jiffies; if (!lp->dialstate) { + /* ISDN connection is established, try sending */ + int ret; if (lp->first_skb) { - if (isdn_net_xmit(ndev, lp, lp->first_skb)) + if (isdn_net_xmit(ndev, lp, lp->first_skb)){ +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#endif return 1; +} lp->first_skb = NULL; } - return (isdn_net_xmit(ndev, lp, skb)); + ret = (isdn_net_xmit(ndev, lp, skb)); +#ifdef ISDN_NEW_TBUSY + if(ret) isdn_net_dev_xoff(ndev); +#endif + return ret; } else +#ifdef ISDN_NEW_TBUSY + isdn_net_dev_xoff(ndev); +#else ndev->tbusy = 1; +#endif } } return 1; @@ -1915,7 +2065,7 @@ isdn_net_rebuild_header(struct sk_buff *skb) } /* - * Interface-setup. (called just after registering a new interface) + * Interface-setup. (just after registering a new interface) */ static int isdn_net_init(struct net_device *ndev) @@ -2046,7 +2196,6 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) isdn_net_phone *n; ulong flags; char nr[32]; - /* Search name in netdev-chain */ save_flags(flags); cli(); @@ -2258,10 +2407,15 @@ isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) lp->name, nr, eaz); if (lp->phone[1]) { /* Grab a free ISDN-Channel */ - if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, + if ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) { + lp->pre_device, + lp->pre_channel) + ) < 0) { + printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name); restore_flags(flags); return 0; @@ -2368,10 +2522,14 @@ isdn_net_force_dial_lp(isdn_net_local * lp) cli(); /* Grab a free ISDN-Channel */ - if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel)) < 0) { + if ((chi = + isdn_get_free_channel( + ISDN_USAGE_NET, + lp->l2_proto, + lp->l3_proto, + lp->pre_device, + lp->pre_channel) + ) < 0) { printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); restore_flags(flags); return -EAGAIN; @@ -3076,7 +3234,6 @@ isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) if (dev->netdev == NULL) isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); restore_flags(flags); - kfree(p->local); kfree(p); diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c index 78c71c7fe..06c2d83ad 100644 --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.52 1999/08/22 20:26:07 calle Exp $ +/* $Id: isdn_ppp.c,v 1.60 1999/11/04 20:29:55 he Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -19,6 +19,34 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ppp.c,v $ + * Revision 1.60 1999/11/04 20:29:55 he + * applied Andre Beck's reset_free fix + * + * Revision 1.59 1999/10/31 15:59:50 he + * more skb headroom checks + * + * Revision 1.58 1999/10/30 13:13:01 keil + * Henners isdn_ppp_skb_push:under fix + * + * Revision 1.57 1999/10/05 22:47:17 he + * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr + * and network address translation) + * + * Revision 1.56 1999/09/29 16:01:06 he + * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb() + * + * Revision 1.55 1999/09/23 22:07:51 detabc + * + * make ipc_head common usable (for use compressor with raw-ip) + * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect. + * ~ + * + * Revision 1.54 1999/09/13 23:25:17 he + * serialized xmitting frames from isdn_ppp and BSENT statcallb + * + * Revision 1.53 1999/08/31 11:18:14 paul + * various spelling corrections (new checksums may be needed, Karsten!) + * * Revision 1.52 1999/08/22 20:26:07 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -212,10 +240,6 @@ /* TODO: right tbusy handling when using MP */ -/* - * experimental for dynamic addressing: readdress IP frames - */ -#undef ISDN_SYNCPPP_READDRESS #define CONFIG_ISDN_CCP 1 #include <linux/config.h> @@ -258,6 +282,7 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, unsigned char code, unsigned char id, unsigned char *data, int len); static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is); +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is); static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, unsigned char id); static void isdn_ppp_ccp_timer_callback(unsigned long closure); @@ -281,9 +306,10 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb, static void isdn_ppp_free_mpqueue(isdn_net_dev *); #endif -char *isdn_ppp_revision = "$Revision: 1.52 $"; +char *isdn_ppp_revision = "$Revision: 1.60 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; + static struct isdn_ppp_compressor *ipc_head = NULL; /* @@ -354,10 +380,6 @@ isdn_ppp_free(isdn_net_local * lp) printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp); is->lp = NULL; /* link is down .. set lp to NULL */ -#ifdef ISDN_SYNCPPP_READDRESS - is->old_pa_addr = 0x0; - is->old_pa_dstaddr = 0x0; -#endif lp->ppp_slot = -1; /* is this OK ?? */ restore_flags(flags); @@ -450,9 +472,6 @@ isdn_ppp_wakeup_daemon(isdn_net_local * lp) ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; -#ifndef COMPAT_HAS_NEW_WAITQ - if (ippp_table[lp->ppp_slot]->wq) -#endif wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); } @@ -470,11 +489,7 @@ isdn_ppp_closewait(int slot) return 0; is = ippp_table[slot]; -#ifdef COMPAT_HAS_NEW_WAITQ if (is->state) -#else - if (is->state && is->wq) -#endif wake_up_interruptible(&is->wq); is->state = IPPP_CLOSEWAIT; @@ -515,9 +530,6 @@ isdn_ppp_open(int min, struct file *file) } is = file->private_data = ippp_table[slot]; -#if 0 - if (is->debug & 0x1) -#endif printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state); /* compression stuff */ @@ -539,11 +551,7 @@ isdn_ppp_open(int min, struct file *file) is->mru = 1524; /* MRU, default 1524 */ is->maxcid = 16; /* VJ: maxcid */ is->tk = current; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&is->wq); -#else - is->wq = NULL; /* read() wait queue */ -#endif is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ is->last = is->rq; is->minor = min; @@ -615,9 +623,9 @@ isdn_ppp_release(int min, struct file *file) is->comp_stat = is->link_comp_stat = NULL; is->decomp_stat = is->link_decomp_stat = NULL; + /* Clean up if necessary */ if(is->reset) - kfree(is->reset); - is->reset = NULL; + isdn_ppp_ccp_reset_free(is); /* this slot is ready for new connections */ is->state = 0; @@ -719,10 +727,6 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) } is->pppcfg = val; break; -#if 0 - case PPPIOCGSTAT: /* read PPP statistic information */ - break; -#endif case PPPIOCGIDLE: /* get idle time information */ if (lp) { struct ppp_idle pidle; @@ -911,9 +915,6 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) is->last = bl->next; restore_flags(flags); -#ifndef COMPAT_HAS_NEW_WAITQ - if (is->wq) -#endif wake_up_interruptible(&is->wq); return len; @@ -1004,6 +1005,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) lp->dialstate == 0 && (lp->flags & ISDN_NET_CONNECTED)) { unsigned short hl; + unsigned long flags; int cnt; struct sk_buff *skb; /* @@ -1027,6 +1029,8 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */ + save_flags(flags); + cli(); if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { if (lp->sav_skb) { dev_kfree_skb(lp->sav_skb); @@ -1035,6 +1039,7 @@ isdn_ppp_write(int min, struct file *file, const char *buf, int count) printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", cnt, count); lp->sav_skb = skb; } + restore_flags(flags); } } return count; @@ -1115,7 +1120,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } if (net_dev->local->master) { - printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n"); + printk(KERN_WARNING "isdn_ppp_receive: net_dev != master\n"); net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev; } if (skb->data[0] == 0xff && skb->data[1] == 0x03) @@ -1459,6 +1464,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) isdn_net_dev *nd; unsigned int proto = PPP_IP; /* 0x21 */ struct ippp_struct *ipt,*ipts; + unsigned long flags; if (mdev) mlp = (isdn_net_local *) (mdev->priv); @@ -1470,12 +1476,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) ipts = ippp_table[mlp->ppp_slot]; if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ -#ifdef ISDN_SYNCPPP_READDRESS - if (!ipts->old_pa_addr) - ipts->old_pa_addr = mdev->pa_addr; - if (!ipts->old_pa_dstaddr) - ipts->old_pa_dstaddr = mdev->pa_dstaddr; -#endif if (ipts->debug & 0x1) printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name); return 1; @@ -1484,21 +1484,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) switch (ntohs(skb->protocol)) { case ETH_P_IP: proto = PPP_IP; -#ifdef ISDN_SYNCPPP_READDRESS - if (ipts->old_pa_addr != mdev->pa_addr) { - struct iphdr *ipfr; - ipfr = (struct iphdr *) skb->data; - if(ipts->debug & 0x4) - printk(KERN_DEBUG "IF-address changed from %lx to %lx\n", ipts->old_pa_addr, mdev->pa_addr); - if (ipfr->version == 4) { - if (ipfr->saddr == ipts->old_pa_addr) { - printk(KERN_DEBUG "readdressing %lx to %lx\n", ipfr->saddr, mdev->pa_addr); - ipfr->saddr = mdev->pa_addr; - } - } - } - /* dstaddr change not so important */ -#endif break; case ETH_P_IPX: proto = PPP_IPX; /* untested */ @@ -1529,8 +1514,6 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) /* Pull off the fake header we stuck on earlier to keep * the fragemntation code happy. - * this will break the ISDN_SYNCPPP_READDRESS hack a few lines - * above. So, enabling this is no longer allowed */ skb_pull(skb,IPPP_MAX_HEADER); @@ -1548,7 +1531,13 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) * sk_buff. old call to dev_alloc_skb only reserved * 16 bytes, now we are looking what the driver want. */ - hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; + /* + * Note: hl might still be insufficient because the method + * above does not account for a possibible MPPP slave channel + * which had larger HL header space requirements than the + * master. + */ new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC); if (new_skb) { u_char *buf; @@ -1654,13 +1643,16 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot); } + save_flags(flags); + cli(); if (isdn_net_send_skb(netdev, lp, skb)) { - if (lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */ + if (lp->sav_skb) { /* should never happen as sav_skb are sent with disabled IRQs) */ printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name); dev_kfree_skb(skb); } else lp->sav_skb = skb; } + restore_flags(flags); return 0; } @@ -1744,12 +1736,6 @@ isdn_ppp_bundle(struct ippp_struct *is, int unit) ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); -#if 0 - if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) { - printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n", - ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg); - } -#endif restore_flags(flags); return 0; @@ -2075,9 +2061,6 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int len; isdn_net_local *lp = (isdn_net_local *) dev->priv; -#if 0 - printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot); -#endif if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) return -EINVAL; @@ -2241,17 +2224,20 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, { struct sk_buff *skb; unsigned char *p; - int count; + int count, hl; + unsigned long flags; int cnt = 0; isdn_net_local *lp = is->lp; /* Alloc large enough skb */ - skb = dev_alloc_skb(len + 16); + hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; + skb = alloc_skb(len + hl + 16,GFP_ATOMIC); if(!skb) { printk(KERN_WARNING "ippp: CCP cannot send reset - out of memory\n"); return; } + skb_reserve(skb, hl); /* We may need to stuff an address and control field first */ if(!(is->pppcfg & SC_COMP_AC)) { @@ -2284,6 +2270,8 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, especially dunno what the sav_skb stuff is good for. */ count = skb->len; + save_flags(flags); + cli(); if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { if (lp->sav_skb) { @@ -2297,21 +2285,41 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, cnt, count); lp->sav_skb = skb; } + restore_flags(flags); } /* Allocate the reset state vector */ static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) { struct ippp_ccp_reset *r; - printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n"); r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); - if(!r) + if(!r) { + printk(KERN_ERR "ippp_ccp: failed to allocate reset data" + " structure - no mem\n"); return NULL; + } memset(r, 0, sizeof(struct ippp_ccp_reset)); + printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); is->reset = r; return r; } +/* Destroy the reset state vector. Kill all pending timers first. */ +static void isdn_ppp_ccp_reset_free(struct ippp_struct *is) +{ + unsigned int id; + + printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n", + is->reset); + for(id = 0; id < 256; id++) { + if(is->reset->rs[id]) { + isdn_ppp_ccp_reset_free_state(is, (unsigned char)id); + } + } + kfree(is->reset); + is->reset = NULL; +} + /* Free a given state and clear everything up for later reallocation */ static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, unsigned char id) @@ -2653,13 +2661,7 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, } if(type) { /* type=1 => Link compression */ -#if 0 - compressor = is->link_compressor; - stat = is->link_comp_stat; - new_proto = PPP_LINK_COMP; -#else return skb_in; -#endif } else { if(!master) { @@ -2683,9 +2685,11 @@ static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, } /* Allow for at least 150 % expansion (for now) */ - skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32); + skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 + + skb_headroom(skb_in), GFP_ATOMIC); if(!skb_out) return skb_in; + skb_reserve(skb_out, skb_headroom(skb_in)); ret = (compressor->compress)(stat,skb_in,skb_out,*proto); if(!ret) { @@ -2914,7 +2918,6 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct } } - int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) { ipc->next = ipc_head; @@ -2949,6 +2952,16 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_ printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit, (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num); + /* If is has no valid reset state vector, we cannot allocate a + decompressor. The decompressor would cause reset transactions + sooner or later, and they need that vector. */ + + if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) { + printk(KERN_ERR "ippp_ccp: no reset data structure - can't" + " allow decompression.\n"); + return -ENOMEM; + } + while(ipc) { if(ipc->num == num) { stat = ipc->alloc(data); @@ -3000,5 +3013,3 @@ static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_ } return -EINVAL; } - - diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c index e502f90da..5b301adb9 100644 --- a/drivers/isdn/isdn_tty.c +++ b/drivers/isdn/isdn_tty.c @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.73 1999/08/28 21:56:27 keil Exp $ +/* $Id: isdn_tty.c,v 1.80 1999/11/07 13:34:30 armin Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -20,6 +20,30 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.c,v $ + * Revision 1.80 1999/11/07 13:34:30 armin + * Fixed AT command line editor + * + * Revision 1.79 1999/10/29 18:35:08 armin + * Check number len in isdn_get_msnstr() to avoid buffer overflow. + * + * Revision 1.78 1999/10/28 23:03:51 armin + * Bugfix: now freeing channel on modem_hup() even when + * usage on ttyI has changed and error-report for + * AT-commands on wrong channel-state. + * + * Revision 1.77 1999/10/26 21:13:14 armin + * using define for checking phone number len in isdn_tty_getdial() + * + * Revision 1.76 1999/10/11 22:16:26 keil + * Suspend/Resume is possible without explicit ID too + * + * Revision 1.75 1999/10/08 18:59:32 armin + * Bugfix of too small MSN buffer and checking phone number + * in isdn_tty_getdial() + * + * Revision 1.74 1999/09/04 06:20:04 keil + * Changes from kernel set_current_state() + * * Revision 1.73 1999/08/28 21:56:27 keil * misplaced #endif caused ttyI crash in 2.3.X * @@ -348,7 +372,7 @@ static int bit2si[8] = static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.73 $"; +char *isdn_tty_revision = "$Revision: 1.80 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() @@ -1014,7 +1038,6 @@ void isdn_tty_modem_hup(modem_info * info, int local) { isdn_ctrl cmd; - int usage; if (!info) return; @@ -1068,10 +1091,7 @@ isdn_tty_modem_hup(modem_info * info, int local) } isdn_all_eaz(info->isdn_driver, info->isdn_channel); info->emu.mdmreg[REG_RINGCNT] = 0; - usage = isdn_calc_usage(info->emu.mdmreg[REG_SI1I], - info->emu.mdmreg[REG_L2PROT]); - isdn_free_channel(info->isdn_driver, info->isdn_channel, - usage); + isdn_free_channel(info->isdn_driver, info->isdn_channel, 0); } info->isdn_driver = -1; info->isdn_channel = -1; @@ -1108,8 +1128,8 @@ isdn_tty_suspend(char *id, modem_info * info, atemu * m) printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); #endif l = strlen(id); - if ((info->isdn_driver >= 0) && l) { - cmd.parm.cmsg.Length = l+17; + if ((info->isdn_driver >= 0)) { + cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; @@ -1147,10 +1167,6 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) int l; l = strlen(id); - if (!l) { - isdn_tty_modem_result(4, info); - return; - } for (j = 7; j >= 0; j--) if (m->mdmreg[REG_SI1] & (1 << j)) { si = bit2si[j]; @@ -1204,7 +1220,7 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m) isdn_command(&cmd); cmd.driver = info->isdn_driver; cmd.arg = info->isdn_channel; - cmd.parm.cmsg.Length = l+17; + cmd.parm.cmsg.Length = l+18; cmd.parm.cmsg.Command = CAPI_FACILITY; cmd.parm.cmsg.Subcommand = CAPI_REQ; cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; @@ -1901,12 +1917,7 @@ isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) static int isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info) { -#ifdef COMPAT_HAS_NEW_WAITQ DECLARE_WAITQUEUE(wait, NULL); -#else - struct wait_queue wait = - {current, NULL}; -#endif int do_clocal = 0; unsigned long flags; int retval; @@ -2157,7 +2168,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) */ timeout = jiffies + HZ; while (!(info->lsr & UART_LSR_TEMT)) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(20); if (time_after(jiffies,timeout)) break; @@ -2173,7 +2184,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp) info->ncarrier = 0; tty->closing = 0; if (info->blocked_open) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(50); wake_up_interruptible(&info->open_wait); } @@ -2375,11 +2386,7 @@ isdn_tty_modem_init(void) return -3; } #endif -#ifdef COMPAT_HAS_NEW_WAITQ init_MUTEX(&info->write_sem); -#else - info->write_sem = MUTEX; -#endif sprintf(info->last_cause, "0000"); sprintf(info->last_num, "none"); info->last_dir = 0; @@ -2396,13 +2403,8 @@ isdn_tty_modem_init(void) info->blocked_open = 0; info->callout_termios = m->cua_modem.init_termios; info->normal_termios = m->tty_modem.init_termios; -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); -#else - info->open_wait = 0; - info->close_wait = 0; -#endif info->isdn_driver = -1; info->isdn_channel = -1; info->drv_index = -1; @@ -3101,9 +3103,12 @@ isdn_tty_show_profile(int ridx, modem_info * info) static void isdn_tty_get_msnstr(char *n, char **p) { - while ((*p[0] >= '0' && *p[0] <= '9') || + int limit = ISDN_MSNLEN - 1; + + while (((*p[0] >= '0' && *p[0] <= '9') || /* Why a comma ??? */ - (*p[0] == ',')) + (*p[0] == ',')) && + (limit--)) *n++ = *p[0]++; *n = '\0'; } @@ -3115,16 +3120,18 @@ static void isdn_tty_getdial(char *p, char *q,int cnt) { int first = 1; - int limit=39; /* MUST match the size in isdn_tty_parse to avoid - buffer overflow */ + int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid + buffer overflow */ while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) { if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) || - (*p == '*') || (*p == '#')) + (*p == '*') || (*p == '#')) { *q++ = *p; - p++; - if(!--limit) + limit--; + } + if(!limit) break; + p++; first = 0; } *q = 0; @@ -3268,6 +3275,8 @@ isdn_tty_cmd_ATand(char **p, modem_info * info) case 'F': /* &F -Set Factory-Defaults */ p[0]++; + if (info->msr & UART_MSR_DCD) + PARSE_ERROR1; isdn_tty_reset_profile(m); isdn_tty_modem_reset_regs(info, 1); break; @@ -3919,6 +3928,12 @@ isdn_tty_parse_at(modem_info * info) break; case 'D': /* D - Dial */ + if (info->msr & UART_MSR_DCD) + PARSE_ERROR; + if (info->msr & UART_MSR_RI) { + isdn_tty_modem_result(3, info); + return; + } isdn_tty_getdial(++p, ds, sizeof ds); p += strlen(p); if (!strlen(m->msn)) @@ -4113,7 +4128,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) c = *p; total++; if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { - /* Separator (CR oder LF) */ + /* Separator (CR or LF) */ m->mdmcmd[m->mdmcmdl] = 0; if (m->mdmreg[REG_ECHO] & BIT_ECHO) { eb[0] = c; @@ -4126,7 +4141,7 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) continue; } if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) { - /* Backspace-Funktion */ + /* Backspace-Function */ if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) { if (m->mdmcmdl) m->mdmcmdl--; @@ -4144,18 +4159,24 @@ isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) if (m->mdmcmdl < 255) { c = my_toupper(c); switch (m->mdmcmdl) { - case 0: - if (c == 'A') - m->mdmcmd[m->mdmcmdl] = c; - break; case 1: - if (c == 'T') + if (c == 'T') { m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; + break; + } else + m->mdmcmdl = 0; + /* Fall through, check for 'A' */ + case 0: + if (c == 'A') { + m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; + } break; default: m->mdmcmd[m->mdmcmdl] = c; + m->mdmcmd[++m->mdmcmdl] = 0; } - m->mdmcmd[++m->mdmcmdl] = 0; } } } diff --git a/drivers/isdn/isdn_tty.h b/drivers/isdn/isdn_tty.h index 87acd7be2..1c27b8300 100644 --- a/drivers/isdn/isdn_tty.h +++ b/drivers/isdn/isdn_tty.h @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.h,v 1.16 1999/08/22 20:26:10 calle Exp $ +/* $Id: isdn_tty.h,v 1.17 1999/09/21 19:00:35 armin Exp $ * header for Linux ISDN subsystem, tty related functions (linklevel). * @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_tty.h,v $ + * Revision 1.17 1999/09/21 19:00:35 armin + * Extended FCON message with added CPN + * can now be activated with Bit 1 of Reg 23. + * * Revision 1.16 1999/08/22 20:26:10 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -154,6 +158,7 @@ #define REG_CPN 23 #define BIT_CPN 1 +#define BIT_CPNFCON 2 extern void isdn_tty_modem_escape(void); extern void isdn_tty_modem_ring(void); diff --git a/drivers/isdn/isdn_ttyfax.c b/drivers/isdn/isdn_ttyfax.c index 7665aa812..9b7268b32 100644 --- a/drivers/isdn/isdn_ttyfax.c +++ b/drivers/isdn/isdn_ttyfax.c @@ -1,4 +1,4 @@ -/* $Id: isdn_ttyfax.c,v 1.3 1999/08/22 20:26:12 calle Exp $ +/* $Id: isdn_ttyfax.c,v 1.4 1999/09/21 19:00:35 armin Exp $ * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). * * Copyright 1999 by Armin Schindler (mac@melware.de) @@ -20,6 +20,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_ttyfax.c,v $ + * Revision 1.4 1999/09/21 19:00:35 armin + * Extended FCON message with added CPN + * can now be activated with Bit 1 of Reg 23. + * * Revision 1.3 1999/08/22 20:26:12 calle * backported changes from kernel 2.3.14: * - several #include "config.h" gone, others come. @@ -46,7 +50,7 @@ #include "isdn_ttyfax.h" -static char *isdn_tty_fax_revision = "$Revision: 1.3 $"; +static char *isdn_tty_fax_revision = "$Revision: 1.4 $"; #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } @@ -98,7 +102,7 @@ static void isdn_tty_fax_modem_result(int code, modem_info * info) break; case 2: /* +FCON */ /* Append CPN, if enabled */ - if ((m->mdmreg[REG_CPN] & BIT_CPN) && + if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) && (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { sprintf(rs, "/%s", m->cpn); isdn_tty_at_cout(rs, info); @@ -907,76 +911,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* LO=n - Flow control opts */ - if (!strncmp(p[0], "LO", 2)) { /* TODO */ - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->lo); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1,2"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 2)) - PARSE_ERROR1; - f->lo = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif -#if 0 - /* LPL=n - Doc for polling cmd */ - if (!strncmp(p[0], "LPL", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->lpl); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 1)) - PARSE_ERROR1; - f->lpl = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* MDL? - DCE Model */ if (!strncmp(p[0], "MDL?", 4)) { @@ -1066,41 +1000,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* PTS=n - Page transfer status */ - if (!strncmp(p[0], "PTS", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d",f->pts); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0-5"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 5)) - PARSE_ERROR1; - f->pts = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* REL=n - Phase C received EOL alignment */ if (!strncmp(p[0], "REL", 3)) { @@ -1148,41 +1047,6 @@ int isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) return 0; } -#if 0 - /* SPL=n - Enable polling */ - if (!strncmp(p[0], "SPL", 3)) { /* TODO */ - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->spl); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') - { - p[0]++; - sprintf(rs, "\r\n0,1"); - isdn_tty_at_cout(rs, info); - } - else - { - par = isdn_getnum(p); - if ((par < 0) || (par > 1)) - PARSE_ERROR1; - f->spl = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#endif /* Phase C Transmit Data Block Size */ if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */ diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c index ae62378b8..a3ac19caf 100644 --- a/drivers/isdn/isdn_v110.c +++ b/drivers/isdn/isdn_v110.c @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.c,v 1.2 1998/02/22 19:44:25 fritz Exp $ +/* $Id: isdn_v110.c,v 1.3 1999/10/30 09:49:28 keil Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_v110.c,v $ + * Revision 1.3 1999/10/30 09:49:28 keil + * Reinit of v110 structs + * * Revision 1.2 1998/02/22 19:44:25 fritz * Bugfixes and improvements regarding V.110, V.110 now running. * @@ -36,7 +39,7 @@ #undef ISDN_V110_DEBUG -char *isdn_v110_revision = "$Revision: 1.2 $"; +char *isdn_v110_revision = "$Revision: 1.3 $"; #define V110_38400 255 #define V110_19200 15 @@ -148,21 +151,13 @@ isdn_v110_open(unsigned char key, int hdrlen, int maxsize) } /* isdn_v110_close frees private V.110 data structures */ -static void +void isdn_v110_close(isdn_v110_stream * v) { if (v == NULL) return; #ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "v110 close\n"); -#if 0 - printk(KERN_DEBUG "isdn_v110_close: nbytes=%d\n", v->nbytes); - printk(KERN_DEBUG "isdn_v110_close: nbits=%d\n", v->nbits); - printk(KERN_DEBUG "isdn_v110_close: key=%d\n", v->key); - printk(KERN_DEBUG "isdn_v110_close: SyncInit=%d\n", v->SyncInit); - printk(KERN_DEBUG "isdn_v110:close: decodelen=%d\n", v->decodelen); - printk(KERN_DEBUG "isdn_v110_close: framelen=%d\n", v->framelen); -#endif #endif kfree(v->encodebuf); kfree(v); diff --git a/drivers/isdn/isdn_v110.h b/drivers/isdn/isdn_v110.h index 9ab5a93f3..4bb694849 100644 --- a/drivers/isdn/isdn_v110.h +++ b/drivers/isdn/isdn_v110.h @@ -1,4 +1,4 @@ -/* $Id: isdn_v110.h,v 1.1 1998/02/20 17:32:11 fritz Exp $ +/* $Id: isdn_v110.h,v 1.2 1999/10/30 09:49:28 keil Exp $ * Linux ISDN subsystem, V.110 related functions (linklevel). * @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdn_v110.h,v $ + * Revision 1.2 1999/10/30 09:49:28 keil + * Reinit of v110 structs + * * Revision 1.1 1998/02/20 17:32:11 fritz * First checkin (not yet completely functionable). * @@ -41,5 +44,6 @@ extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); extern int isdn_v110_stat_callback(int, isdn_ctrl *); +extern void isdn_v110_close(isdn_v110_stream * v); #endif diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 2e580e1c7..9168aca8c 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1,8 +1,8 @@ -/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $ +/* $Id: isdnloop.c,v 1.9 1999/09/06 07:29:36 fritz Exp $ * ISDN low-level module implementing a dummy loop driver. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.c,v $ + * Revision 1.9 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * * Revision 1.8 1998/11/18 18:59:43 armin * changes for 2.1.127 * @@ -56,7 +59,7 @@ #include "isdnloop.h" static char -*revision = "$Revision: 1.8 $"; +*revision = "$Revision: 1.9 $"; static int isdnloop_addcard(char *); diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index 42906c143..82266edbe 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -1,8 +1,8 @@ -/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $ +/* $Id: isdnloop.h,v 1.4 1999/09/06 07:29:36 fritz Exp $ * Loopback lowlevel module for testing of linklevel. * - * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de) + * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: isdnloop.h,v $ + * Revision 1.4 1999/09/06 07:29:36 fritz + * Changed my mail-address. + * * Revision 1.3 1998/04/14 20:59:35 he * merged 2.1.94 changes * diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 77f0ed45f..679aaddeb 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -86,9 +86,7 @@ int pcbit_init_dev(int board, int mem_base, int irq) dev_pcbit[board] = dev; memset(dev, 0, sizeof(struct pcbit_dev)); -#ifdef COMPAT_HAS_NEW_WAITQ init_waitqueue_head(&dev->set_running_wq); -#endif if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) dev->sh_mem = (unsigned char*) mem_base; @@ -593,20 +591,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, dev->b1->s_refnum, dev->b2->s_refnum); #endif -#if 0 - if (dev->b1->s_refnum == refnum) - chan = dev->b1; - else { - - if (dev->b2->s_refnum == refnum) - chan = dev->b2; - else { - chan = NULL; - printk(KERN_WARNING "Connection Confirm - refnum doesn't match chan\n"); - break; - } - } -#else /* We just try to find a channel in the right state */ if (dev->b1->fsm_state == ST_CALL_INIT) @@ -620,7 +604,6 @@ void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, break; } } -#endif if (capi_decode_conn_conf(chan, skb, &complete)) { printk(KERN_DEBUG "conn_conf indicates error\n"); pcbit_fsm_event(dev, chan, EV_ERROR, NULL); diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c index bc1b079a2..36bd6f8aa 100644 --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -375,16 +375,11 @@ pcbit_receive(struct pcbit_dev *dev) if (dev->read_frame) { printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n"); -#if 0 - pcbit_l2_error(dev); - return; -#else /* discard previous queued frame */ if (dev->read_frame->skb) kfree_skb(dev->read_frame->skb); kfree(dev->read_frame); dev->read_frame = NULL; -#endif } frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC); @@ -460,14 +455,10 @@ pcbit_receive(struct pcbit_dev *dev) if (!(frame = dev->read_frame)) { printk("Type 1 frame and no frame queued\n"); -#if 1 /* usually after an error: toss frame */ dev->readptr += tt; if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN) dev->readptr -= BANKLEN; -#else - pcbit_l2_error(dev); -#endif return; } diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c index 799552019..9d3aa8007 100644 --- a/drivers/isdn/pcbit/module.c +++ b/drivers/isdn/pcbit/module.c @@ -102,7 +102,6 @@ void cleanup_module(void) } #else -#ifdef COMPAT_HAS_NEW_SETUP #define MAX_PARA (MAX_PCBIT_CARDS * 2) #include <linux/init.h> static int __init pcbit_setup(char *line) @@ -112,11 +111,6 @@ static int __init pcbit_setup(char *line) int ints[MAX_PARA+1]; str = get_options(line, MAX_PARA, ints); -#else -void pcbit_setup(char *str, int *ints) -{ - int i, j, argc; -#endif argc = ints[0]; i = 0; j = 1; @@ -135,13 +129,9 @@ void pcbit_setup(char *str, int *ints) i++; } -#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("pcbit=", pcbit_setup); -#else -} -#endif #endif diff --git a/drivers/isdn/pcbit/pcbit.h b/drivers/isdn/pcbit/pcbit.h index 45c68871d..d284cc70f 100644 --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -68,11 +68,7 @@ struct pcbit_dev { struct frame_buf *write_queue; /* Protocol start */ -#ifdef COMPAT_HAS_NEW_WAITQ wait_queue_head_t set_running_wq; -#else - struct wait_queue *set_running_wq; -#endif struct timer_list set_running_timer; struct timer_list error_recover_timer; diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 788950eeb..e455c074e 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -164,7 +164,7 @@ int init_sc(void) if(do_reset) { pr_debug("Doing a SAFE probe reset\n"); outb(0xFF, io[b] + RESET_OFFSET); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(milliseconds(10000)); } pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], @@ -512,19 +512,10 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(PRI_BASEPG_VAL, pgport); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); -#if 0 -/* - * For Gary: - * If it's a timing problem, it should be gone with the above schedule() - * Another possible reason may be the missing volatile in the original - * code. readl() does this for us. - */ - printk(""); /* Hack! Doesn't work without this !!!??? */ -#endif if(sig == SIGNATURE) return PRI_BOARD; @@ -532,13 +523,10 @@ int identify_board(unsigned long rambase, unsigned int iobase) * Try to identify a PRI card */ outb(BRI_BASEPG_VAL, pgport); - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); sig = readl(rambase + SIG_OFFSET); pr_debug("Looking for a signature, got 0x%x\n", sig); -#if 0 - printk(""); /* Hack! Doesn't work without this !!!??? */ -#endif if(sig == SIGNATURE) return BRI_BOARD; @@ -567,7 +555,7 @@ int identify_board(unsigned long rambase, unsigned int iobase) */ x = 0; while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); x++; } diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c index 9915cb0d8..141d5254d 100644 --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -15,9 +15,6 @@ extern int send_and_receive(int, unsigned int, unsigned char,unsigned char, extern board *adapter[]; -#if 0 -static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" }; -#endif int GetStatus(int card, boardInfo *); @@ -42,7 +39,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename); if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCLOAD: Command Failed, LoadProc while engine running.\n", + pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n", adapter[card]->devicename); return -1; } @@ -56,12 +53,12 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, 0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT); if(status) { - pr_debug("%s: SCIOCLOAD: Command Failed, status = %d\n", + pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", adapter[card]->devicename, status); return -1; } else { - pr_debug("%s: SCIOCLOAD: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename); return 0; } } @@ -70,7 +67,7 @@ int sc_ioctl(int card, scs_ioctl *data) { pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename); if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCSTART: Command Failed, Engine already running.\n", + pr_debug("%s: SCIOCSTART: command failed, engine already running.\n", adapter[card]->devicename); return -1; } @@ -94,16 +91,16 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(&switchtype, (char *) data->dataptr, sizeof(char)))) return err; - pr_debug("%s: SCIOCSETSWITCH: Setting switch type to %d\n", adapter[card]->devicename, + pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename, switchtype); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType, 0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSWITCH: Command Successful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETSWITCH: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -123,10 +120,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSWITCH: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSWITCH: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -156,10 +153,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETSPID: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSPID: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -188,18 +185,18 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(spid, (char *) data->dataptr, sizeof(spid)))) return err; - pr_debug("%s: SCIOCSETSPID: Setting channel %d spid to %s\n", + pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", adapter[card]->devicename, data->channel, spid); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSPID, data->channel, strlen(spid), spid, &rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSPID: Command Successful\n", + pr_debug("%s: SCIOCSETSPID: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETSPID: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -219,10 +216,10 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status) { - pr_debug("%s: SCIOCGETDN: Command Sucessful\n", adapter[card]->devicename); + pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETDN: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -252,18 +249,18 @@ int sc_ioctl(int card, scs_ioctl *data) if ((err = copy_from_user(dn, (char *) data->dataptr, sizeof(dn)))) return err; - pr_debug("%s: SCIOCSETDN: Setting channel %d dn to %s\n", + pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", adapter[card]->devicename, data->channel, dn); status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetMyNumber, data->channel, strlen(dn),dn,&rcvmsg, SAR_TIMEOUT); if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETDN: Command Successful\n", + pr_debug("%s: SCIOCSETDN: command successful\n", adapter[card]->devicename); return 0; } else { - pr_debug("%s: SCIOCSETDN: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } @@ -273,7 +270,7 @@ int sc_ioctl(int card, scs_ioctl *data) pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename); /* adapter[card]->trace = !adapter[card]->trace; - pr_debug("%s: SCIOCTRACE: Tracing turned %s\n", adapter[card]->devicename, + pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename, adapter[card]->trace ? "ON" : "OFF"); */ break; @@ -305,11 +302,11 @@ int sc_ioctl(int card, scs_ioctl *data) status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSPEED: Command Sucessful\n", + pr_debug("%s: SCIOCGETSPEED: command successful\n", adapter[card]->devicename); } else { - pr_debug("%s: SCIOCGETSPEED: Command Failed (status = %d)\n", + pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n", adapter[card]->devicename, status); return status; } diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c index 4d4765f79..871a69643 100644 --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -1,5 +1,5 @@ /* - * $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $ + * $Id: message.c,v 1.5 1999/09/04 06:20:07 keil Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * message.c - functions for sending and receiving control messages @@ -266,7 +266,7 @@ int send_and_receive(int card, tries = 0; /* wait for the response */ while (tries < timeout) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); pr_debug("SAR waiting..\n"); diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c index d75cb04d7..31e562c57 100644 --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -1,5 +1,5 @@ /* - * $Id: packet.c,v 1.4 1998/02/12 23:08:50 keil Exp $ + * $Id: packet.c,v 1.5 1999/08/31 11:20:41 paul Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * This program is free software; you can redistribute it and/or modify @@ -52,11 +52,11 @@ int sndpkt(int devId, int channel, struct sk_buff *data) card = get_card_from_id(devId); if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return -ENODEV; } - pr_debug("%s: Send Packet: frst = 0x%x nxt = %d f = %d n = %d\n", + pr_debug("%s: sndpkt: frst = 0x%x nxt = %d f = %d n = %d\n", adapter[card]->devicename, adapter[card]->channel[channel].first_sendbuf, adapter[card]->channel[channel].next_sendbuf, @@ -64,26 +64,26 @@ int sndpkt(int devId, int channel, struct sk_buff *data) adapter[card]->channel[channel].num_sendbufs); if(!adapter[card]->channel[channel].free_sendbufs) { - pr_debug("%s: Out out TX buffers\n", adapter[card]->devicename); + pr_debug("%s: out of TX buffers\n", adapter[card]->devicename); return -EINVAL; } if(data->len > BUFFER_SIZE) { - pr_debug("%s: Data overflows buffer size (data > buffer)\n", adapter[card]->devicename); + pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename); return -EINVAL; } ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf * BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf; ReqLnkWrite.msg_len = data->len; /* sk_buff size */ - pr_debug("%s: Writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, + pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset); memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len); /* * sendmessage */ - pr_debug("%s: Send Packet size=%d, buf_offset=0x%x buf_indx=%d\n", + pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n", adapter[card]->devicename, ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset, adapter[card]->channel[channel].next_sendbuf); @@ -92,7 +92,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data) channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite); len = data->len; if(status) { - pr_debug("%s: Failed to send packet, status = %d\n", adapter[card]->devicename, status); + pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status); return -1; } else { @@ -101,7 +101,7 @@ int sndpkt(int devId, int channel, struct sk_buff *data) ++adapter[card]->channel[channel].next_sendbuf == adapter[card]->channel[channel].num_sendbufs ? 0 : adapter[card]->channel[channel].next_sendbuf; - pr_debug("%s: Packet sent successfully\n", adapter[card]->devicename); + pr_debug("%s: packet sent successfully\n", adapter[card]->devicename); dev_kfree_skb(data); indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len); } @@ -114,7 +114,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) struct sk_buff *skb; if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return; } @@ -122,7 +122,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) case 0x01: case 0x02: case 0x70: - pr_debug("%s: Error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); + pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); return; case 0x00: if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) { @@ -144,7 +144,7 @@ void rcvpkt(int card, RspMessage *rcvmsg) /* * Recycle the buffer */ - pr_debug("%s: Buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); + pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); /* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */ newll.buff_offset = rcvmsg->msg_data.response.buff_offset; newll.msg_len = BUFFER_SIZE; @@ -163,30 +163,30 @@ int setup_buffers(int card, int c) LLData RcvBuffOffset; if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); + pr_debug("invalid param: %d is not a valid card id\n", card); return -ENODEV; } /* * Calculate the buffer offsets (send/recv/send/recv) */ - pr_debug("%s: Seting up channel buffer space in shared RAM\n", adapter[card]->devicename); + pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename); buffer_size = BUFFER_SIZE; nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2; nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers; - pr_debug("%s: Calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, + pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, nBuffers, buffer_size); if(nBuffers < 2) { - pr_debug("%s: Not enough buffer space\n", adapter[card]->devicename); + pr_debug("%s: not enough buffer space\n", adapter[card]->devicename); return -1; } cBase = (nBuffers * buffer_size) * (c - 1); - pr_debug("%s: Channel buffer offset from Shared RAM: 0x%x\n", adapter[card]->devicename, cBase); + pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase); adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase; adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2; adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2; adapter[card]->channel[c-1].next_sendbuf = 0; - pr_debug("%s: Send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", + pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", adapter[card]->devicename, adapter[card]->channel[c-1].first_sendbuf, adapter[card]->channel[c-1].num_sendbufs, @@ -196,13 +196,13 @@ int setup_buffers(int card, int c) /* * Prep the receive buffers */ - pr_debug("%s: Adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); + pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); for (i = 0 ; i < nBuffers / 2; i++) { RcvBuffOffset.buff_offset = ((adapter[card]->channel[c-1].first_sendbuf + (nBuffers / 2) * buffer_size) + (buffer_size * i)); RcvBuffOffset.msg_len = buffer_size; - pr_debug("%s: Adding RcvBuffer #%d offset=0x%x sz=%d buffsz:%d\n", + pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n", adapter[card]->devicename, i + 1, RcvBuffOffset.buff_offset, RcvBuffOffset.msg_len,buffer_size); |