From 8e5fce469981ce05f3a0605d3a9655ec1361a7e0 Mon Sep 17 00:00:00 2001 From: Matthias Urlichs Date: Wed, 25 Oct 1995 13:36:04 +0100 Subject: [PATCH] isdn-15 --- DOKU | 23 +- Make.config | 8 +- Make.rules | 1 + Makefile | 8 +- README | 13 + cards/capi/bintec.c | 67 ++- cards/capi/capi.h | 65 +- config/config.dist | 15 +- include/config.h | 7 +- include/isdn_12.h | 11 +- include/isdn_23.h | 9 +- include/isdn_3.h | 7 +- include/isdn_34.h | 4 +- include/phone_1TR6.h | 16 +- isdn_2/isdn_2.c | 96 ++- isdn_3/Makefile | 8 +- isdn_3/capi.c | 1188 +++++++++++++++++++++++-------------- isdn_3/isdn_3.c | 15 +- isdn_3/prot_1TR6_common.c | 26 +- isdn_3/prot_ETS.c | 45 +- isdn_4/Makefile | 1 + isdn_4/cf.c | 40 +- isdn_4/conn.c | 32 +- isdn_4/info.c | 120 ++-- isdn_4/loader.c | 60 +- isdn_4/malldebug.c | 2 +- isdn_4/master.h | 15 +- isdn_4/match.c | 189 ++++-- isdn_4/stream.c | 2 +- isdn_4/texts.c | 62 ++ isdn_4/unused.c | 4 + isdn_4/util.c | 7 + isdn_4/work.c | 65 +- ksupport/dump.c | 5 +- ksupport/log.c | 2 +- patches/biglog | 20 + patches/debugmsg | 158 +++++ patches/loadable.slip | 2 + patches/loadserial | 307 ++++++++++ patches/more_free | 18 + patches/nm.background | 15 + patches/panicreboot | 120 ++++ patches/setnoswap | 21 + patches/symbols | 70 +++ str_if/str_linux.c | 2 + streams/streams_io.c | 14 +- streams/streams_sys.c | 2 +- tools/isdn.conf | 2 +- 48 files changed, 2269 insertions(+), 720 deletions(-) create mode 100644 patches/biglog create mode 100644 patches/debugmsg create mode 100644 patches/loadable.slip create mode 100644 patches/loadserial create mode 100644 patches/more_free create mode 100644 patches/nm.background create mode 100644 patches/panicreboot create mode 100644 patches/setnoswap create mode 100644 patches/symbols diff --git a/DOKU b/DOKU index bc86590..1b367cf 100644 --- a/DOKU +++ b/DOKU @@ -815,15 +815,20 @@ Die Reihenfolge ist wichtig. In der Konfiguration verhält sich eine CAPI-Karte ansonsten wie der 1TR6-Treiber, und zwar AUCH DANN WENN DAS TEIl AM EURO-ISDN HÄNGT. + :pb Verwendet die CAPI wie eine Nebenstellenanlage, d.h. ankommend + Akkumulation ankommender Ziffern, abgehend dynamisches Mapping + EAZ->Nebenstellennummer. (Teilweise implementiert: ankommend + funktioniert nur Blockwahl.) :sp 0 Bintec-Karte. [bintec] Auf diese Karte muß zunächst boot.68k und dann entweder bri.68k, - bri_4.68k oder pmx.68k geladen werden. + bri_4.68k oder pmx.68k geladen werden (LF-Zeile). :lp X X X CAPI-Bitmasken für EAZ, Service, Infos. Hexadezimal. - Default: 3FFF FFFF 003F. + Default: 03FF E7BF 003F. :st XXXXX Protokollstack XXXXX laden. Siehe Handbuch zur Karte. Default ist u_dss1_pmp. :ea N NNN EAZ N auf (lokale) Endnummer NNN mappen. Default ist die letzte Ziffer der Nummer. + Nicht bei :pb verwenden. DP-Zeile ("Dial Prefix") @@ -957,16 +962,18 @@ framelo ... oder die unteren Bits. Sinnvoll dann, wenn jemand den Daten- strom auf eine 56-kBaud-Leitung umsetzt. -CL-Zeile ("Card Limit") +CL-Zeile ("Connection Limit") -------- -Form: CL +Form: CL Beispiel> -CM Tel? * 2 -Begrenzt die Zahl der verwendbaren B-Kanäle einer Karte. -Ueber das Limit hinausgehende Anrufe werden mit BUSY abgelehnt, es sei denn -in der entsprechenden P-Zeile steht der entsprechende Parameter. +CL * * * Tel? 2 + +Begrenzt die Zahl der für einen gegebenen Verbindungstyp verwendbaren +B-Kanäle. Ueber das Limit hinausgehende Anrufe werden mit BUSY abgelehnt, +es sei denn in der entsprechenden P-Zeile steht der entsprechende +Parameter. LF-Zeile ("Load File") diff --git a/Make.config b/Make.config index f18eeac..1c4c61f 100644 --- a/Make.config +++ b/Make.config @@ -4,14 +4,14 @@ SHELL = /bin/sh ## =()@>()= -CARDS = teles +CARDS = ncp16 ncp teles bintec ## =()@>()= -PROTOCOLS = phone tei +PROTOCOLS = phone capi tei fixed ## =()@>()= SUBPROTOCOLS = euro german ## =()@>()= -KERNELSRC := /usr/src/linux +KERNELSRC := /usr/src/kernel/linux-test ifdef KERNEL ## =()@>()= @@ -37,7 +37,7 @@ LD = ld ## =()@>()= LDFLAGS = ## =()@>()= -RANLIB = echo +RANLIB = ranlib ## =()@>()= STR_IF = str_linux ## =()@>()= diff --git a/Make.rules b/Make.rules index cab3554..8faa019 100644 --- a/Make.rules +++ b/Make.rules @@ -19,6 +19,7 @@ unexport DOCARDS unexport WHAT unexport REALSOURCE unexport DOSRC +unexport SUBDIRS ifneq ($(strip $(DOCARDS)),) KERNEL=1 diff --git a/Makefile b/Makefile index 61a6ac4..bc7a0bf 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# config and include are first, tools is next +# config and include are first, then libraries, tools, modules+programs SUBDIRS = config include tools compat streams support isdn_3 isdn_4 \ ksupport isdn_2 str_if cards x75 alaw tools van_j strslip \ v110 pr_on strslip fakeh t70 rate timer reconnect ip_mon @@ -11,9 +11,13 @@ dep: depend TOPDIR=. include Make.rules -.diddepend:: Makefile +.diddepend: Makefile $(MAKE) depend touch .diddepend clean:: rm -f .toldem .diddepend + +master: + set -e; for i in config support isdn_3 isdn_4 ; do $(MAKE) -C $$i all ; done + diff --git a/README b/README index 175cff7..7c2ffc5 100644 --- a/README +++ b/README @@ -4,6 +4,19 @@ Die Anleitung und der ganze Kram findet sich in der Datei DOKU, oder README.isdn in den Kernelsourcen. +*** 1995-10-24 + +Release 15. + +Support fuer intelligente Karten ist _fast_ da, wo er hinsoll... + +GCC 2.7.0 wird empfohlen. Support fuer intelligente Karten geht nicht ohne +(wegen attribute((packed)); ich habe keine Lust, die CAPI-Datenstrukturen +von Hand zusammenzuschrauben). + +Ansonsten siehe unten. Feedback bitte! + + *** 1995-10-21 Release 14. diff --git a/cards/capi/bintec.c b/cards/capi/bintec.c index aae525c..4603aab 100644 --- a/cards/capi/bintec.c +++ b/cards/capi/bintec.c @@ -32,6 +32,7 @@ #include #include #include "loader.h" +#include "kernel.h" #ifdef linux #include /* htons and friends */ @@ -316,12 +317,15 @@ printf("d"); switch(bp->type) { case BOARD_ID_PMX: bp->card.nr_chans = 30; + bp->card.nr_dchans = 1; break; case BOARD_ID_BRI: bp->card.nr_chans = 2; + bp->card.nr_dchans = 1; break; case BOARD_ID_BRI4: bp->card.nr_chans = 8; + bp->card.nr_dchans = 4; break; default: printf("BINTEC: unknown board ID %d\n",bp->type); @@ -455,7 +459,7 @@ putstart(struct _bintec *bp, int len) splx(ms); return -EAGAIN; } - DEBUG(capiout) printf("BINTEC write %d bytes at %d, free %d\n",len,wi,space); + if(0)DEBUG(capiout) printf("BINTEC write %d bytes at %d, free %d\n",len,wi,space); bp->sndoffset = wi; bp->sndbufsize = sz; bp->sndend = (wi+len+2) % sz; @@ -589,7 +593,7 @@ getstart(struct _bintec *bp) bp->rcvoffset = sz; return -EFAULT; } - DEBUG(capi) printf("BINTEC: reading %d bytes at %d\n",len,ri); + if(0)DEBUG(capi) printf("BINTEC: reading %d bytes at %d\n",len,ri); bp->rcvend = (ri + len + 2) % sz; return len; } @@ -925,11 +929,18 @@ sendone(struct _bintec *bp, int thechan) else len += 2; DEBUG(capiout) { + if(thechan == 0) { + struct CAPI_every_header *capi; + capi = ((typeof(capi))mb->b_rptr); + if(capi->PRIM_type == CAPI_ALIVE_RESP) + goto foo; + } printf("BINTEC: Send %d bytes on chan %d",len,thechan); if(thechan == 0) log_printmsg(NULL,": ",mb,">>"); else printf("\n"); + foo:; } err = putstart(bp,len > MAXSEND ? MAXSEND : len ); /* auto-puts the length */ if(err >= 0) { @@ -1025,14 +1036,20 @@ postproc(struct _bintec *bp, mblk_t *mb, int ch) int err; struct CAPI_every_header *capi; - DEBUG(capi) log_printmsg(NULL,"BINTEC read packet:",mb,"> "); - capi = (typeof(capi))mb->b_rptr; + + DEBUG(capi) if(capi->PRIM_type != CAPI_ALIVE_IND) log_printmsg(NULL,"BINTEC read packet:",mb,"> "); + switch(capi->PRIM_type) { case CAPI_ALIVE_IND: err = 0; capi->PRIM_type = CAPI_ALIVE_RESP; - S_enqueue(&bp->chan[0].q_out,mb); + if(bp->chan[0].q_out.nblocks < 100) + S_enqueue(&bp->chan[0].q_out,mb); + else { + isdn2_chstate(&bp->card,MDL_ERROR_IND,0); + return -EIO; + } if(bp->chan[0].q_out.nblocks == 1) sendone(bp,0); break; @@ -1058,8 +1075,15 @@ postproc(struct _bintec *bp, mblk_t *mb, int ch) chan = &bp->chan[ch]; else return -ERESTART; - S_enqueue(&chan->q_in,mb); - if(chan->q_out.nblocks == 1) + if(chan->q_in.nblocks < 200) + S_enqueue(&chan->q_in,mb); + else { + freemsg(mb); + /* TODO: Throw the connection away. Right now we kill the + card instead. */ + isdn2_chstate(&bp->card,MDL_ERROR_IND,0); + } + if(chan->q_in.nblocks == 1) pushone(bp,ch); } break; @@ -1093,7 +1117,12 @@ postproc(struct _bintec *bp, mblk_t *mb, int ch) default: if(!isdn2_canrecv(&bp->card,0)) { printf("BINTEC read: cannot accept packet\n"); - S_enqueue(&bp->chan[0].q_in,mb); + if(bp->chan[0].q_in.nblocks < 100) + S_enqueue(&bp->chan[0].q_in,mb); + else { + printf("BINTEC: incoming queue full\n"); + isdn2_chstate(&bp->card,MDL_ERROR_IND,0); + } return 0; } else if((err = isdn2_recv(&bp->card,0,mb)) != 0) { printf("BINTEC read error: err %d\n",err); @@ -1188,8 +1217,8 @@ DoIRQ(struct _bintec *bp) err = getstart(bp); if(err >= 0) { int len = err; - if(err < 4) { - if(bp->waitmsg > 0) { + if((err < 4) || (bp->waitmsg > 0)) { + if((err == 1) && (bp->waitmsg > 0)) { if(!--bp->waitmsg) { DEBUG(info) printf("BINTEC: card is online\n"); isdn2_new_state(&bp->card,1); @@ -1199,7 +1228,6 @@ DoIRQ(struct _bintec *bp) err = getend(bp); continue; } - /* XXX figure out the channel, use a smaller offset */ err = get16(bp); len -= 2; if(err == htons(1)) { @@ -1257,6 +1285,10 @@ DoIRQ(struct _bintec *bp) linkb(mb,m2); } } + } else if(len < capilen) { + DEBUG(info)printf("BINTEC:read: want %d bytes, got %d\n",capilen,len), + freemsg(mb); + continue; } switch(capi->PRIM_type) { case CAPI_DATAB3_CONF: @@ -1269,7 +1301,18 @@ DoIRQ(struct _bintec *bp) if(err >= 0) { err = postproc(bp,mb,ch); if(err == -ERESTART) { - S_enqueue(&bp->q_unknown,mb); + static int prcnt; + if(bp->q_unknown.nblocks > 100) { + if(prcnt < 3) { + prcnt++; + DEBUG(info)printf("BINTEC:read: 'unknown data' queue full\n"); + } + freemsg(mb); + } else { + S_enqueue(&bp->q_unknown,mb); + if(prcnt) + prcnt--; + } err = 0; } } diff --git a/cards/capi/capi.h b/cards/capi/capi.h index cc16366..7ca201c 100644 --- a/cards/capi/capi.h +++ b/cards/capi/capi.h @@ -9,7 +9,7 @@ # define _APIDEF_H_ /* static char _sccsid_apidef_h[] = "@(#)apidef.h 1.28"; */ -#if defined __GNUC__ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6)) # define PACK __attribute__ ((packed)) # define _PACK #else @@ -107,56 +107,117 @@ /* CAPI error codes */ /* */ /************************************************************************/ +#define ID_E_REGISTER CHAR2('%','Y') #define CAPI_E_REGISTER 0x1001 +#define ID_E_APPLICATION CHAR2('%','X') #define CAPI_E_APPLICATION 0x1002 +#define ID_E_MSGLENGTH CHAR2('%','W') #define CAPI_E_MSGLENGTH 0x1003 +#define ID_E_COMMAND CHAR2('%','V') #define CAPI_E_COMMAND 0x1004 +#define ID_E_QUEUEFULL CHAR2('%','U') #define CAPI_E_QUEUEFULL 0x1005 +#define ID_E_NOMSG CHAR2('%','T') #define CAPI_E_NOMSG 0x1006 +#define ID_E_MSGOVERFLOW CHAR2('%','S') #define CAPI_E_MSGOVERFLOW 0x1007 +#define ID_E_DEINSTALL CHAR2('%','R') #define CAPI_E_DEINSTALL 0x1008 +#define ID_E_CONTROLLER CHAR2('%','Q') #define CAPI_E_CONTROLLER 0x2001 +#define ID_E_PLCI CHAR2('%','P') #define CAPI_E_PLCI 0x2002 +#define ID_E_NCCI CHAR2('%','O') #define CAPI_E_NCCI 0x2003 +#define ID_E_TYPE CHAR2('%','4') +#define CAPI_E_TYPE 0x2004 +#define ID_E_BCHANNEL CHAR2('%','N') #define CAPI_E_BCHANNEL 0x3101 +#define ID_E_INFOMASK CHAR2('%','M') #define CAPI_E_INFOMASK 0x3102 +#define ID_E_EAZMASK CHAR2('%','L') #define CAPI_E_EAZMASK 0x3103 +#define ID_E_SIMASK CHAR2('%','K') #define CAPI_E_SIMASK 0x3104 +#define ID_E_B2PROTO CHAR2('%','J') #define CAPI_E_B2PROTO 0x3105 +#define ID_E_DLPD CHAR2('%','I') #define CAPI_E_DLPD 0x3106 +#define ID_E_B3PROTO CHAR2('%','H') #define CAPI_E_B3PROTO 0x3107 +#define ID_E_NCPD CHAR2('%','G') #define CAPI_E_NCPD 0x3108 +#define ID_E_NCPI CHAR2('%','F') #define CAPI_E_NCPI 0x3109 +#define ID_E_DATAB3FLAGS CHAR2('%','E') #define CAPI_E_DATAB3FLAGS 0x310a +#define ID_E_CONTROLLERFAILED CHAR2('%','D') #define CAPI_E_CONTROLLERFAILED 0x3201 +#define ID_E_REGCONFLICT CHAR2('%','C') #define CAPI_E_REGCONFLICT 0x3202 +#define ID_E_CMDNOTSUPPORTED CHAR2('%','B') #define CAPI_E_CMDNOTSUPPORTED 0x3203 +#define ID_E_PLCIACT CHAR2('%','A') #define CAPI_E_PLCIACT 0x3204 +#define ID_E_NCCIACT CHAR2('%','z') #define CAPI_E_NCCIACT 0x3205 +#define ID_E_B2NOTSUPPORT CHAR2('%','y') #define CAPI_E_B2NOTSUPPORT 0x3206 +#define ID_E_B2STATE CHAR2('%','x') #define CAPI_E_B2STATE 0x3207 +#define ID_E_B3NOTSUPPORT CHAR2('%','w') #define CAPI_E_B3NOTSUPPORT 0x3208 +#define ID_E_B3STATE CHAR2('%','v') #define CAPI_E_B3STATE 0x3209 +#define ID_E_B2DLPDPARA CHAR2('%','u') #define CAPI_E_B2DLPDPARA 0x320a +#define ID_E_B3NCPDPARA CHAR2('%','t') #define CAPI_E_B3NCPDPARA 0x320b +#define ID_E_B3NCPIPARA CHAR2('%','5') +#define CAPI_E_B3NCPIPARA 0x320c +#define ID_E_DATALEN CHAR2('%','s') #define CAPI_E_DATALEN 0x320d +#define ID_E_DTMF CHAR2('%','q') #define CAPI_E_DTMF 0x320e +#define ID_E_NOL1 CHAR2('%','p') #define CAPI_E_NOL1 0x3301 +#define ID_E_NOL2 CHAR2('%','o') #define CAPI_E_NOL2 0x3302 +#define ID_E_SETUPBCHANLAYER1 CHAR2('%','n') #define CAPI_E_SETUPBCHANLAYER1 0x3303 +#define ID_E_SETUPBCHANLAYER2 CHAR2('%','m') #define CAPI_E_SETUPBCHANLAYER2 0x3304 +#define ID_E_ABORTDCHANLAYER1 CHAR2('%','1') +#define CAPI_E_ABORTDCHANLAYER1 0x3305 +#define ID_E_ABORTDCHANLAYER2 CHAR2('%','2') +#define CAPI_E_ABORTDCHANLAYER2 0x3306 +#define ID_E_ABORTDCHANLAYER3 CHAR2('%','3') +#define CAPI_E_ABORTDCHANLAYER3 0x3307 +#define ID_E_ABORTBCHANLAYER1 CHAR2('%','l') #define CAPI_E_ABORTBCHANLAYER1 0x3308 +#define ID_E_ABORTBCHANLAYER2 CHAR2('%','k') #define CAPI_E_ABORTBCHANLAYER2 0x3309 +#define ID_E_ABORTBCHANLAYER3 CHAR2('%','j') #define CAPI_E_ABORTBCHANLAYER3 0x330a +#define ID_E_REBCHANLAYER2 CHAR2('%','6') +#define CAPI_E_REBCHANLAYER2 0x330b +#define ID_E_REBCHANLAYER3 CHAR2('%','i') #define CAPI_E_REBCHANLAYER3 0x330c - +#define ID_E_NOFAX CHAR2('%','h') #define CAPI_E_NOFAX 0x4001 +#define ID_E_BADLINE CHAR2('%','g') #define CAPI_E_BADLINE 0x4004 +#define ID_E_NOANSWER CHAR2('%','f') #define CAPI_E_NOANSWER 0x4008 +#define ID_E_REMDISC CHAR2('%','e') #define CAPI_E_REMDISC 0x4009 +#define ID_E_NOCMD CHAR2('%','d') #define CAPI_E_NOCMD 0x400a +#define ID_E_INCOMPAT CHAR2('%','c') #define CAPI_E_INCOMPAT 0x400b +#define ID_E_BADDATA CHAR2('%','b') #define CAPI_E_BADDATA 0x400c +#define ID_E_PROTO CHAR2('%','a') #define CAPI_E_PROTO 0x400d diff --git a/config/config.dist b/config/config.dist index 645cdfc..b01c468 100644 --- a/config/config.dist +++ b/config/config.dist @@ -48,6 +48,12 @@ PROTOCOLS phone tei SUBPROTOCOLS euro german ## ## +## Debugging? DO or DONT +## +#### =()@>()= +DEBUGGING DO +## +## ## ## Stuff to define ## @@ -177,15 +183,6 @@ TIMEOUT NEW #### =()@>()= ADDERROR DONT ## -## Debugging? DO or DONT -#### =()@>()= -DEBUGGING DO -#### =()@>()= -CONF_MOD2 0x30 -## 0x00, 0x33 -#### =()@>()= -CONF_DEBUG 0x5016 -## 0x5006, 0xf3df ### ISDN configuration options diff --git a/include/config.h b/include/config.h index b3f8ed9..4698f6b 100644 --- a/include/config.h +++ b/include/config.h @@ -38,12 +38,7 @@ typedef unsigned char streamchar; /* =()<#define @@_ADDERROR>()= */ #define DONT_ADDERROR -#ifdef KERNEL -/* =()<#define CONF_MOD2 @@>()= */ -#define CONF_MOD2 0x30 -/* =()<#define CONF_DEBUG @@>()= */ -#define CONF_DEBUG 0x5016 -#else +#ifndef KERNEL #ifdef DO_DEBUGGING #ifndef CONFIG_DEBUG_STREAMS diff --git a/include/isdn_12.h b/include/isdn_12.h index 4102f07..0d681a9 100644 --- a/include/isdn_12.h +++ b/include/isdn_12.h @@ -67,9 +67,9 @@ typedef int (*C_data) (struct _isdn1_card * card, short channel, mblk_t * data); typedef int (*C_flush) (struct _isdn1_card * card, short channel); struct _isdn1_card { - ushort nr_chans; /* Basic access has 2, cheap cards have just - * one. */ - void *ctl; /* Pointer for L1 data structures, card + uchar_t nr_chans; /* total per card */ + uchar_t nr_dchans; /* zero == one. */ + void *ctl; /* Pointer for L2 data structures, card * drivers must not touch this. */ #if 0 struct _isdn_chan *chan; /* Pointer to array. First is the D channel. */ @@ -106,6 +106,11 @@ extern int isdn2_unregister (struct _isdn1_card *card); */ extern void isdn2_new_state (struct _isdn1_card *card, char state); +/* + * Report errors / changes in card state, for intelligent cards + */ +extern void isdn2_chstate (struct _isdn1_card *card, uchar_t ind, short add); + /* * Callback to test availability of queue space. Cards are not required to call * this. diff --git a/include/isdn_23.h b/include/isdn_23.h index abaf38f..d920361 100644 --- a/include/isdn_23.h +++ b/include/isdn_23.h @@ -97,7 +97,8 @@ typedef struct _isdn23_hdr { struct { /* Card present. Request: L1 Up, bchans * compared */ uchar_t card; /* Card ID. Counting up from zero. */ - uchar_t bchans; + uchar_t dchans; /* for the card */ + uchar_t bchans; /* per D channel */ uchar_t flags; /* Some stuff */ #define HDR_CARD_PP 01 long id; /* Unique ID of this card, for hardware @@ -171,7 +172,11 @@ typedef struct _isdn23_hdr { */ } sel; -} __attribute__((packed)) *isdn23_hdr; +} +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6)) + __attribute__((packed)) +#endif + *isdn23_hdr; /* Aliases for writing actual programs. *//* Keys for debugging L2. */ #define hdr_atcmd sel._hdr_atcmd /* A */ diff --git a/include/isdn_3.h b/include/isdn_3.h index 93554c9..0f9351b 100644 --- a/include/isdn_3.h +++ b/include/isdn_3.h @@ -30,7 +30,8 @@ typedef struct _isdn3_card { /* One per card */ ulong_t modes; /* Mask of permitted modes on this card. */ uchar_t nr; /* Card number, for L2. */ uchar_t TEI; /* For reference */ - uchar_t bchans; /* Number of B channels. */ + uchar_t dchans; /* Number of D channels per card. */ + uchar_t bchans; /* Number of B channels per D channel. */ unsigned is_up:1; } *isdn3_card; @@ -134,7 +135,7 @@ typedef struct _isdn3_hndl { ** Calls managed by this connection are chained off the struct. **/ -#define NITALK 3 +#define NITALK 11 #define NSTALK 1 typedef struct _isdn3_talk { /* one per card's D channel connection */ @@ -152,7 +153,7 @@ typedef struct _isdn3_talk { /* one per card's D channel connection */ ** One struct isdn3_conn represents one ISDN call. **/ #define STACK_LEN 10 -#define NICONN 15 +#define NICONN 16 #define NSCONN 3 typedef struct _isdn3_conn { diff --git a/include/isdn_34.h b/include/isdn_34.h index 797c219..98d97b0 100644 --- a/include/isdn_34.h +++ b/include/isdn_34.h @@ -125,7 +125,8 @@ #endif #define ARG_CONNREF CHAR2 ('C','r') /* uchar refnum for a connection. */ #define ARG_CARD CHAR2 ('c','d') /* ident Card */ -#define ARG_CHANNEL CHAR2 ('b','c') /* uchar B channel to use */ +#define ARG_SUBCARD CHAR2 ('c','s') /* D channel on card */ +#define ARG_CHANNEL CHAR2 ('b','c') /* B channel to use */ #define ARG_ASSOC CHAR2 ('a','=') /* associate card IDs */ #define ARG_LISTEN CHAR2 ('l','p') /* listen params */ @@ -134,6 +135,7 @@ #define ARG_FMINOR CHAR2 ('m','f') /* uchar minor number of command * connection */ #define ARG_CALLREF CHAR2 ('c','r') /* long call reference number */ +#define ARG_PBX CHAR2 ('p','b') /* behave like a PBX */ #define ARG_EAZ CHAR2 ('e','a') /* map EAZ to local phone nr */ #define ARG_LNUMBER CHAR2 ('l','r') /* local phone nr */ #define ARG_NUMBER CHAR2 ('n','r') /* remote phone nr */ diff --git a/include/phone_1TR6.h b/include/phone_1TR6.h index a9e530b..4109921 100644 --- a/include/phone_1TR6.h +++ b/include/phone_1TR6.h @@ -128,14 +128,14 @@ #define ID_N6_serviceInd CHAR2('s','I') #define PT_N6_chargingInfo 0x02 #define ID_N6_chargingInfo CHAR2('C','I') -#define PT_N6_Date 0x03 -#define ID_N6_Date CHAR2('D','a') -#define PT_N6_FacSelect 0x05 -#define ID_N6_FacSelect CHAR2('F','S') -#define PT_N6_FacStatus 0x06 -#define ID_N6_FacStatus CHAR2('F','s') -#define PT_N6_StatusCalled 0x07 -#define ID_N6_StatusCalled CHAR2('S','C') +#define PT_N6_date 0x03 +#define ID_N6_date CHAR2('D','a') +#define PT_N6_facSelect 0x05 +#define ID_N6_facSelect CHAR2('F','S') +#define PT_N6_facStatus 0x06 +#define ID_N6_facStatus CHAR2('F','s') +#define PT_N6_statusCalled 0x07 +#define ID_N6_statusCalled CHAR2('S','C') #define PT_N6_addTransAttr 0x08 #define ID_N6_addTransAttr CHAR2('t','A') diff --git a/isdn_2/isdn_2.c b/isdn_2/isdn_2.c index fd7d391..3fa08e6 100644 --- a/isdn_2/isdn_2.c +++ b/isdn_2/isdn_2.c @@ -57,10 +57,10 @@ void logh__printmsg(unsigned int line,void *log,const char *text, mblk_t *mb) /* Debugging */ #ifdef CONFIG_DEBUG_ISDN -int mod2 = CONF_MOD2; -int isdn2_debug = CONF_DEBUG; +int isdn2_log = 0x00; +int isdn2_debug = 0x5016; #else -int mod2 = 0; /* necessary for _any_ debugging... */ +int isdn2_log = 0; /* necessary for _any_ debugging... */ #define isdn2_debug 0 #endif @@ -404,27 +404,23 @@ D_register (isdn2_card card, uchar_t SAPI, uchar_t ch, uchar_t broadcast) return 0; } + + /* * State change for this connection. Called by X75. */ static int -D_state (isdn2_state state, uchar_t ind, short add) +sendstate (isdn2_card card, uchar_t ch, uchar_t SAPI, uchar_t ind, short add) { isdn23_hdr hdr; mblk_t *mb; - uchar_t ch; -#ifdef DO_MULTI_TEI - ch = state->bchan; -#else - ch = 0; -#endif if (isdn2_debug & 0x40) - printf ("%sD_state %d %x:%x\n",KERN_DEBUG, state->card->nr, ind, add); + printf ("%ssendstate %d %x:%x\n",KERN_DEBUG, card->nr, ind, add); if (ind == MDL_ERROR_IND) { if(add & (ERR_C | ERR_D | ERR_G /* | ERR_H */ )) { printf("%s\nISDN Fatal Error, TEI cleared\n",KERN_DEBUG); - state->card->TEI[ch] = TEI_BROADCAST; + card->TEI[ch] = TEI_BROADCAST; } } @@ -432,8 +428,8 @@ D_state (isdn2_state state, uchar_t ind, short add) if (mb == NULL) { if (isdn2_debug & 0x10) - printf ("%sD_state: nomem to send ind %x:%x for %d:%x/%x\n",KERN_DEBUG, ind, add, - state->card->nr, state->SAPI, state->card->TEI[ch]); + printf ("%ssendstate: nomem to send ind %x:%x for %d:%x/%x\n",KERN_DEBUG, ind, add, + card->nr, SAPI, card->TEI[ch]); return -ENOMEM; } hdr = ((isdn23_hdr) mb->b_wptr)++; @@ -442,10 +438,10 @@ D_state (isdn2_state state, uchar_t ind, short add) case DL_ESTABLISH_CONF: hdr->key = HDR_OPENPROT; hdr->seqnum = hdrseq; hdrseq += 2; - hdr->hdr_openprot.card = state->card->nr; - hdr->hdr_openprot.SAPI = state->SAPI; + hdr->hdr_openprot.card = card->nr; + hdr->hdr_openprot.SAPI = SAPI; #ifdef DO_MULTI_TEI - hdr->hdr_openprot.bchan = state->bchan; + hdr->hdr_openprot.bchan = ch; #endif hdr->hdr_openprot.ind = ind; break; @@ -453,21 +449,20 @@ D_state (isdn2_state state, uchar_t ind, short add) case DL_RELEASE_CONF: hdr->key = HDR_CLOSEPROT; hdr->seqnum = hdrseq; hdrseq += 2; - hdr->hdr_closeprot.card = state->card->nr; - hdr->hdr_closeprot.SAPI = state->SAPI; + hdr->hdr_closeprot.card = card->nr; + hdr->hdr_closeprot.SAPI = SAPI; hdr->hdr_closeprot.ind = ind; #ifdef DO_MULTI_TEI - hdr->hdr_closeprot.bchan = state->bchan; + hdr->hdr_closeprot.bchan = ch; #endif - /* D_kill_one (state, ind); */ break; default: hdr->key = HDR_NOTIFY; hdr->seqnum = hdrseq; hdrseq += 2; - hdr->hdr_notify.card = state->card->nr; - hdr->hdr_notify.SAPI = state->SAPI; + hdr->hdr_notify.card = card->nr; + hdr->hdr_notify.SAPI = SAPI; #ifdef DO_MULTI_TEI - hdr->hdr_notify.bchan = state->bchan; + hdr->hdr_notify.bchan = ch; #endif hdr->hdr_notify.ind = ind; hdr->hdr_notify.add = add; @@ -480,11 +475,42 @@ D_state (isdn2_state state, uchar_t ind, short add) freemsg (mb); return -ENXIO; } - D_checkactive (state->card); return 0; } +/* + * State change for this connection. Called by X75. + */ +static int +D_state (isdn2_state state, uchar_t ind, short add) +{ + uchar_t ch; + int err; + +#ifdef DO_MULTI_TEI + ch = state->bchan; +#else + ch = 0; +#endif + err = sendstate(state->card,ch,state->SAPI,ind,add); + + D_checkactive (state->card); + return err; +} + +void +isdn2_chstate (struct _isdn1_card *card, uchar_t ind, short add) +{ + isdn2_card ctl; + + ctl = (isdn2_card) card->ctl; + if (ctl == NULL) + return; + sendstate(ctl,0,0,ind,add); +} + + #ifdef CONFIG_DEBUG_ISDN #define set_card_status(a,b) deb_set_card_status(__FILE__,__LINE__,a,b) #endif @@ -941,7 +967,7 @@ D_send (isdn2_state state, char cmd, mblk_t * mb) else if (DATA_START(mb) + 2 <= mb->b_rptr && DATA_REFS(mb) == 1) { *--mb->b_rptr = (((cmd & 2) ? TEI_BROADCAST : state->card->TEI[ch]) << 1) | 1; *--mb->b_rptr = (state->SAPI << 2) | ((cmd & 1) ? 0 : 2); - if(mod2 & 0x20) { + if(isdn2_log & 0x20) { printf ("%s*** %d", KERN_DEBUG,state->card->nr); log_printmsg (NULL, " Send", mb, KERN_DEBUG); } @@ -958,7 +984,7 @@ D_send (isdn2_state state, char cmd, mblk_t * mb) *mb2->b_wptr++ = (state->SAPI << 2) | ((cmd & 1) ? 0 : 2); *mb2->b_wptr++ = (((cmd & 2) ? TEI_BROADCAST : state->card->TEI[ch]) << 1) | 1; linkb (mb2, mb); - if(mod2 & 0x20) { + if(isdn2_log & 0x20) { printf ("%s*** %d", KERN_DEBUG,state->card->nr); log_printmsg (NULL, " Send", mb2, KERN_DEBUG); } @@ -1382,7 +1408,7 @@ isdn2_recv (struct _isdn1_card *card, short channel, mblk_t * data) if(msgdsize(data) < 0) return 0; #endif - if(mod2 & 0x10) { + if(isdn2_log & 0x10) { printf ("%s*** %d", KERN_DEBUG,ctl->nr); log_printmsg (NULL, " Recv", data, KERN_DEBUG); } @@ -1560,7 +1586,13 @@ isdn2_sendcard (isdn2_card card) hdr->seqnum = hdrseq; hdrseq += 2; hdr->hdr_card.card = card->nr; hdr->hdr_card.id = card->id; - hdr->hdr_card.bchans = card->card->nr_chans; + if(card->card->nr_dchans < 2) { + hdr->hdr_card.dchans = 1; + hdr->hdr_card.bchans = card->card->nr_chans; + } else { + hdr->hdr_card.dchans = card->card->nr_dchans; + hdr->hdr_card.bchans = card->card->nr_chans / card->card->nr_dchans; + } hdr->hdr_card.modes = card->card->modes; if (isdn_chan.qptr != NULL) { if(isdn2_debug & 0x2000) logh_printmsg (NULL, "Up", mb); @@ -2031,7 +2063,7 @@ poplist (queue_t * q, char initial) if ((mb = allocb (32, BPRI_MED)) != NULL) { if (initial) { - if (mod2 & 4) { + if (isdn2_log & 4) { *mb->b_wptr++ = 's'; *mb->b_wptr++ = 't'; *mb->b_wptr++ = 'r'; @@ -2045,7 +2077,7 @@ poplist (queue_t * q, char initial) *mb->b_wptr++ = 'o'; *mb->b_wptr++ = 't'; *mb->b_wptr++ = 'o'; - if (mod2 & 1) { + if (isdn2_log & 1) { *mb->b_wptr++ = ' '; *mb->b_wptr++ = 's'; *mb->b_wptr++ = 't'; @@ -2054,7 +2086,7 @@ poplist (queue_t * q, char initial) *mb->b_wptr++ = 'o'; *mb->b_wptr++ = 'g'; } - if (mod2 & 2) { + if (isdn2_log & 2) { *mb->b_wptr++ = ' '; *mb->b_wptr++ = 'q'; *mb->b_wptr++ = 'i'; diff --git a/isdn_3/Makefile b/isdn_3/Makefile index a2a6cc0..5e2b961 100644 --- a/isdn_3/Makefile +++ b/isdn_3/Makefile @@ -2,15 +2,21 @@ TOPDIR=.. include $(TOPDIR)/Make.config PSOURCES := isdn_3.c $(addsuffix .c,$(PROTOCOLS)) +ifneq ($(strip $(filter capi, $(PROTOCOLS))),) +PCOMMON=1 +endif ifneq ($(strip $(filter phone, $(PROTOCOLS))),) ifneq ($(strip $(filter euro, $(SUBPROTOCOLS))),) PSOURCES += prot_ETS.c endif ifneq ($(strip $(filter german, $(SUBPROTOCOLS))),) PSOURCES += prot_1TR6_1.c -PSOURCES += prot_1TR6_common.c +PCOMMON=1 endif endif +ifeq ($(PCOMMON),1) +PSOURCES += prot_1TR6_common.c +endif EXTRA_CFLAGS=$(addsuffix _,$(addprefix -D_,$(PROTOCOLS) $(SUBPROTOCOLS))) diff --git a/isdn_3/capi.c b/isdn_3/capi.c index 46b9b57..dfcb4be 100644 --- a/isdn_3/capi.c +++ b/isdn_3/capi.c @@ -18,20 +18,26 @@ #include "asm/byteorder.h" #include "sapi.h" +#define NBOARD 4 /* number of D channels on one card */ -#if NICONN <= 14 -#error "Need NICONN > 14" -#endif -#if NITALK <= 1 -#error "Need NITALK > 1" -#endif -#define message_id talki[0] -#define tstate talki[1] +#define ST_pbx 2 /* Bits! */ +#if NITALK <=NBOARD+3 +#error "Need NITALK > NBOARD+3" +#endif +#define tappl talki +#define regnum talki[NBOARD+0] /* current interface I'm talking about */ +#define message_id talki[NBOARD+1] /* Expected msgid for current interface */ +#define tstate talki[NBOARD+2] /* State of the current interface */ +#define lasteaz talki[NBOARD+3] /* last EAZ we used up */ + +#if NICONN <= 15 +#error "Need NICONN > 15" +#endif #define ncci0 conni[0] -#define waitflags conni[1] -#define msgid0 conni[2] -#define WF_CONNECTACTIVE_IND 3 +#define waitflags conni[1] /* what're we waiting for */ +#define msgid0 conni[2] /* for connect_resp */ +#define WF_CONNECTACTIVE_IND 3 /* conni[WF_*] for IDs pertaining to that message */ #define WF_CONNECTB3ACTIVE_IND 4 #define WF_DISCONNECTB3_IND 5 #define WF_DISCONNECT_IND 6 @@ -43,6 +49,7 @@ #define WF_DISCONNECTB3_CONF 12 #define WF_DISCONNECT_CONF 13 #define WF_CONNECT_CONF 14 +#define WF_CONTROL_EAZ 15 /* Card states */ #define STATE_BOOTING 1 @@ -53,19 +60,29 @@ #define STATE_CONF_LAST 99 #define STATE_RUNNING 100 -#define RUN_CAPI_TALERT 01 +#define STATE_DEAD 255 -#define VAL_CAPI_TALERT ( 2 *HZ) /* timer for delaying an ALERT response */ +#define RUN_CAPI_TCONN 01 +#define RUN_CAPI_TWAITEAZ 02 +#define RUN_CAPI_TFOO 04 -static void CAPI_TALERT (isdn3_conn conn); +#define VAL_CAPI_TCONN ( 40 *HZ) /* timer for delaying an ALERT response */ +#define VAL_CAPI_TWAITEAZ ( HZ/2) /* timer for waiting for the EAZ */ +#define VAL_CAPI_TFOO ( 10 * HZ) /* timer for waiting for teardown */ + +static void CAPI_TCONN (isdn3_conn conn); +static void CAPI_TWAITEAZ (isdn3_conn conn); +static void CAPI_TFOO (isdn3_conn conn); /* Connection states: 0: unknown - 1: outgoing, wait for CONNECT_CONF - 2: outgoing, wait for CONNECTACTIVE_IND SELECTB2_CONF SELECTB3_CONF - 3: outgoing, wait for CONNECTB3_CONF CONNECTB3ACTIVE_IND + 1: outgoing, wait for EAZ + 2: outgoing, wait for CONNECT_CONF + 3: outgoing, wait for CONNECTACTIVE_IND SELECTB2_CONF SELECTB3_CONF + 4: outgoing, wait for CONNECTB3_CONF CONNECTB3ACTIVE_IND + 6: incoming, wait for EAZ 7: incoming, wait for master program 8: incoming, wait for SELECTB2_CONF SELECTB3_CONF 9: incoming, wait for LISTENB3_CONF CONNECTACTIVE_IND CONNECTB3_CONF CONNECTB3ACTIVE_IND @@ -75,42 +92,64 @@ static void CAPI_TALERT (isdn3_conn conn); 20: wait for DISCONNECTB3_CONF DISCONNECTB3_IND 21: wait for DISCONNECT_CONF DISCONNECT_IND 22: wait for DISCONNECTB3_CONF DISCONNECTB3_IND DISCONNECT_CONF DISCONNECT_IND + 99: delay wait */ struct capi_info { unsigned short service; + unsigned char subcard; + unsigned char bchan; unsigned char flags; - unsigned char eaz; +#define INF_SPV 01 + unsigned char lnr[MAXNR]; unsigned char nr[MAXNR]; }; extern void log_printmsg (void *log, const char *text, mblk_t * mp, const char*); +ushort_t capi_infotoid(ushort_t info); +static int report_incoming (isdn3_conn conn); +static int send_disconnect(isdn3_conn conn, char do_L3, ushort_t cause); +static void checkterm (isdn3_conn conn); static void capi_timerup (isdn3_conn conn) { - rtimer (CAPI_TALERT, conn); + rtimer (CAPI_TCONN, conn); + rtimer (CAPI_TWAITEAZ, conn); + rtimer (CAPI_TFOO, conn); } #define setstate(a,b) Xsetstate(__LINE__,(a),(b)) static void Xsetstate(unsigned int deb_line, isdn3_conn conn, uchar_t state) { -printf ("Conn CAPI:%d %08lx: State %d --> %d\n", deb_line, conn->call_ref, conn->state, state); +printf ("Conn CAPI:%d %05lx: State %d --> %d\n", deb_line, conn->call_ref, conn->state, state); if(conn->state == state) return; + if(conn->state >= 1 && conn->state < 15 && (state < 1 || state >= 15)) + untimer(CAPI_TCONN, conn); switch(conn->state) { - case 13: - untimer(CAPI_TALERT, conn); + case 6: + untimer(CAPI_TWAITEAZ, conn); + break; + case 99: + untimer(CAPI_TFOO, conn); break; } + if(state >= 1 && state < 15 && (conn->state < 1 || conn->state >= 15)) + timer(CAPI_TCONN,conn); + conn->state = state; + switch(state) { - case 13: - timer(CAPI_TALERT,conn); + case 6: + timer(CAPI_TWAITEAZ,conn); + break; + case 99: + timer(CAPI_TFOO,conn); break; } } @@ -136,7 +175,7 @@ capi_send(isdn3_talk talk, ushort_t appl, ushort_t msgtype, mblk_t *data, ushort capi = ((struct CAPI_every_header *)mb->b_wptr)++; bzero(capi,sizeof(*capi)); capi->len = sizeof(*capi) + (data ? msgdsize(data) : 0); - capi->appl = 0; + capi->appl = appl; capi->PRIM_type = msgtype; capi->messid = msgid; @@ -173,16 +212,33 @@ capi_sendctl(isdn3_talk talk, ushort_t appl, ushort_t code, mblk_t *data, ushort * LLHH type CCCC protocol ... */ - static void -CAPI_TALERT(isdn3_conn conn) +CAPI_TWAITEAZ(isdn3_conn conn) { - printf("CAPI_TALERT %08lx\n",conn->call_ref); + printf("CAPI_TWAITEAZ %05lx\n",conn->call_ref); + conn->timerflags &= ~RUN_CAPI_TWAITEAZ; if(conn->state != 6) return; - /* Hmmm. Do we really have to do this? I think not... */ - /* So let's try without. */ - conn->timerflags &= ~RUN_CAPI_TALERT; + report_incoming(conn); +} + +static void +CAPI_TFOO(isdn3_conn conn) +{ + printf("CAPI_TFOO %05lx\n",conn->call_ref); + conn->timerflags &= ~RUN_CAPI_TFOO; + setstate(conn,0); + checkterm(conn); +} + +static void +CAPI_TCONN(isdn3_conn conn) +{ + printf("CAPI_TCONN %05lx\n",conn->call_ref); + conn->timerflags &= ~RUN_CAPI_TCONN; + if(conn->state < 1 || conn->state >= 15) + return; + send_disconnect(conn,0,0); } static int @@ -225,10 +281,94 @@ send_setup(isdn3_conn conn) err = capi_send(conn->talk,conn->call_ref >> 16, CAPI_SELECTB3_REQ, m3, conn->conni[WF_SELECTB3_CONF] = newmsgid(conn->talk)); if(err < 0) freemsg(m3); + else { + conn->waitflags = 1 << WF_SELECTB2_CONF; + conn->waitflags |= 1 << WF_SELECTB3_CONF; + } } return err; } +static int +send_open(isdn3_talk talk) +{ + struct apiopen *capi; + int err; + mblk_t *data; +#ifdef _euro_ +#define DEFPROFILE "u_dss1_pmp" +#endif +#ifndef DEFPROFILE +#define DEFPROFILE "u_1tr6_pmp" +#endif + char profile[32] = DEFPROFILE; + { /* Find correct driver name */ + int err; char skip = 0; + mblk_t *info = talk->card->info; + if(info != NULL) { + streamchar *sta = info->b_rptr; + ushort_t idx; + + while(m_getid(info,&idx) == 0) { + long sap; + switch(idx) { + case ARG_PROTOCOL: + if (m_geti(info,&sap) == 0) { + skip = (sap != SAPI_CAPI); + } + break; + case ARG_SUBPROT: + if (m_geti(info,&sap) == 0 && !skip) { + switch(sap) { + case SAPI_CAPI_BINTEC: + skip=0; + break; + default: + /* Wrong card. TODO: Do something! */ + info->b_rptr = sta; + return -ENXIO; + } + } + break; + case ARG_SUBCARD: + if (m_geti(info,&sap) == 0 && !skip) + skip = (sap != talk->regnum+1); + break; + case ARG_STACK: + if(skip) + break; + if((err = m_getstr(info,profile,sizeof(profile)-1)) < 0) + strcpy(profile,DEFPROFILE); + break; + case ARG_PBX: + if(skip) + break; + talk->state |= 1<<(talk->regnum+ST_pbx); + break; + } + } + info->b_rptr = sta; + } + } + + data = allocb(sizeof(*capi), BPRI_MED); + if(data == NULL) /* XXX error processing */ + return -ENOMEM; + capi = ((struct apiopen *)data->b_wptr)++; + bzero(capi,sizeof(*capi)); + strcpy(capi->protocol,profile); + capi->teid = ~0; + capi->t3id = ~0; + capi->contrl = 0; + capi->time = time(NULL); + if((err = capi_sendctl(talk,talk->tappl[talk->regnum],CONTROL_API_OPEN,data,newmsgid(talk))) < 0) { + freemsg(data); + return err; + } + talk->tstate = STATE_OPENING; + return err; +} + static int chstate (isdn3_talk talk, uchar_t ind, short add) { @@ -237,134 +377,42 @@ chstate (isdn3_talk talk, uchar_t ind, short add) case PH_ACTIVATE_NOTE: case DL_ESTABLISH_IND: case DL_ESTABLISH_CONF: + talk->regnum = 0; { - { - isdn3_conn conn, nconn; - for(conn = talk->conn; conn != NULL; conn = nconn) { - nconn = conn->next; - capi_timerup(conn); - } - } - if(talk->tstate != STATE_BOOTING) { - /* TODO: reset / restart / XXX the card? */ - break; - } - { - struct apiopen *capi; - int err; - mblk_t *data; -#define DEFPROFILE "u_dss1_pmp" - char profile[32] = DEFPROFILE; - { /* Find correct driver name */ - int err; char skip = 0; - mblk_t *info = talk->card->info; - if(info != NULL) { - streamchar *sta = info->b_rptr; - ushort_t idx; - - while(m_getid(info,&idx) == 0) { - long sap; - switch(idx) { - case ARG_PROTOCOL: - if (m_geti(info,&sap) == 0) { - skip = (sap != SAPI_CAPI); - } - break; - case ARG_SUBPROT: - if (m_geti(info,&sap) == 0 && !skip) { - switch(sap) { - case SAPI_CAPI_BINTEC: - skip=0; - break; - default: - /* Wrong card. TODO: Do something! */ - info->b_rptr = sta; - return -ENXIO; - } - } - break; - case ARG_STACK: - if(skip) - break; - if((err = m_getstr(info,profile,sizeof(profile)-1)) < 0) - strcpy(profile,DEFPROFILE); - break; - } - } - info->b_rptr = sta; - } - } - - data = allocb(sizeof(*capi), BPRI_MED); - if(data == NULL) /* XXX error processing */ - return -ENOMEM; - capi = ((struct apiopen *)data->b_wptr)++; - bzero(capi,sizeof(*capi)); - strcpy(capi->protocol,"u_dss1_pmp"); - capi->teid = ~0; - capi->t3id = ~0; - capi->contrl = 0; - capi->time = time(NULL); - if((err = capi_sendctl(talk,0,CONTROL_API_OPEN,data,newmsgid(talk))) < 0) { - freemsg(data); - break; - } - talk->tstate = STATE_OPENING; + isdn3_conn conn, nconn; + for(conn = talk->conn; conn != NULL; conn = nconn) { + nconn = conn->next; + capi_timerup(conn); } } - } - return 0; - -#if 0 /* to end of function */ - int killit = 0; - - if(0)printf ("PHONE state for card %d says %s:%o\n", talk->card->nr, conv_ind(ind), add); - switch (ind) { - case DL_ESTABLISH_IND: - case DL_ESTABLISH_CONF:{ - isdn3_conn conn, nconn; - - for (conn = talk->conn; conn != NULL; conn = nconn) { - isdn3_prot prot = isdn3_findprot (talk->card->info, conn->subprotocol); - - nconn = conn->next; - if (prot != NULL) - (*prot->chstate) (conn, ind, add); - } - - talk->tstate |= PHONE_UP; - if(0)printf ("PHONE is UP\n"); - } break; - case PH_DEACTIVATE_IND: - /* break; */ - case PH_DEACTIVATE_CONF: - case PH_DISCONNECT_IND: - killit = 1; - /* FALL THRU */ + if(talk->tstate != STATE_BOOTING) { + /* TODO: reset / restart / XXX the card? */ + break; + } + send_open(talk); + break; + case MDL_ERROR_IND: case DL_RELEASE_IND: - case DL_RELEASE_CONF: { + case DL_RELEASE_CONF: + case PH_DEACTIVATE_CONF: + case PH_DEACTIVATE_IND: + case PH_DISCONNECT_IND: + talk->regnum = 0; + talk->tstate = STATE_BOOTING; + { isdn3_conn conn, nconn; - - for (conn = talk->conn; conn != NULL; conn = nconn) { - isdn3_prot prot = isdn3_findprot (talk->card->info, conn->subprotocol); - + for(conn = talk->conn; conn != NULL; conn = nconn) { nconn = conn->next; - if (prot != NULL) - (*prot->chstate) (conn, ind, add); - else - isdn3_killconn (conn, 1); + setstate(conn,0); + checkterm(conn); } - - talk->tstate &= ~PHONE_UP; - if(0)printf ("PHONE i4s DOWN\n"); } break; } return 0; -#endif } -static inline isdn3_conn +static isdn3_conn capi_findconn(isdn3_talk talk, ushort_t appl, ushort_t plci) { isdn3_conn conn; @@ -372,35 +420,35 @@ capi_findconn(isdn3_talk talk, ushort_t appl, ushort_t plci) for(conn = talk->conn; conn != NULL; conn = conn->next) { if(conn->call_ref == cref) { - printf(" (conn %08lx) ",conn->call_ref); + printf(" (conn %05lx) ",conn->call_ref); return conn; } } return NULL; } -static inline isdn3_conn +static isdn3_conn capi_findconn3(isdn3_talk talk, ushort_t appl, ushort_t ncci) { isdn3_conn conn; for(conn = talk->conn; conn != NULL; conn = conn->next) { if((conn->call_ref >> 16) == appl && conn->ncci0 == ncci) { - printf(" (conn %08lx) ",conn->call_ref); + printf(" (conn %05lx) ",conn->call_ref); return conn; } } return NULL; } -static inline isdn3_conn -capi_findconnm(isdn3_talk talk, ushort_t appl, ushort_t msgid) +static isdn3_conn +capi_findconnm(isdn3_talk talk, ushort_t appl, ushort_t msgid, ushort_t index) { isdn3_conn conn; for(conn = talk->conn; conn != NULL; conn = conn->next) { - if((conn->call_ref >> 16) == appl && conn->msgid0 == msgid) { - printf(" (conn %08lx) ",conn->call_ref); + if((conn->call_ref >> 16) == appl && conn->conni[index] == msgid) { + printf(" (conn %05lx) ",conn->call_ref); return conn; } } @@ -418,7 +466,7 @@ report_incoming (isdn3_conn conn) setstate (conn, 0); return -ENOMEM; } - m_putid (mb, IND_CONN); + m_putid (mb, IND_INCOMING); conn_info (conn, mb); if ((err = isdn3_at_send (conn, mb, 0)) != 0) { @@ -429,8 +477,34 @@ report_incoming (isdn3_conn conn) return err; } +static void +report_addcause(mblk_t *mb, ushort_t info, ushort_t cause) +{ + extern ushort_t n1_causetoid(uchar_t id); + + m_putsx(mb,ARG_CAUSE); + if(cause != 0) + m_putsx2(mb,n1_causetoid(cause&0x7F)); + m_putsx2(mb,capi_infotoid(info)); +} + static void -report_terminate (isdn3_conn conn) +report_nocard (isdn3_talk talk, ushort_t info) +{ + mblk_t *mb = allocb (64, BPRI_MED); + + talk->state = STATE_DEAD; + + m_putid (mb, IND_NOCARD); + m_putlx (mb, talk->card->id); + report_addcause(mb,info,0); + if (isdn3_at_send (NULL, mb, 0) < 0) + freemsg (mb); + return; +} + +static void +report_terminate (isdn3_conn conn, ushort_t info, ushort_t cause) { int err = 0; @@ -443,6 +517,7 @@ report_terminate (isdn3_conn conn) conn->minorstate |= MS_TERM_SENT; m_putid (mb, IND_DISC); } + report_addcause(mb,info,cause); conn_info (conn, mb); if ((err = isdn3_at_send (conn, mb, 0)) != 0) { freemsg (mb); @@ -456,13 +531,13 @@ static void checkterm (isdn3_conn conn) { if (conn->state == 0) { - report_terminate (conn); + report_terminate (conn,0,0); isdn3_killconn (conn, 1); /* XXX */ } } static int -send_disconnect(isdn3_conn conn, char do_L3) +send_disconnect(isdn3_conn conn, char do_L3, ushort_t cause) { int err; @@ -471,49 +546,115 @@ send_disconnect(isdn3_conn conn, char do_L3) if(conn->state == 0) return 0; conn->waitflags = 0; - report_terminate(conn); - if(do_L3 && (conn->state < 20)) { - struct CAPI_disconnectb3_req *c3; - mblk_t *m3 = allocb(sizeof(*c3),BPRI_MED); - if(m3 == NULL) - return -ENOMEM; + report_terminate(conn,0,0); + switch(conn->state) { + case 6: + case 7: + case 8: + { + struct CAPI_connect_resp *c3; + mblk_t *m3 = allocb(sizeof(*c3),BPRI_MED); + if(m3 == NULL) + return -ENOMEM; - c3 = ((typeof(c3))m3->b_wptr)++; - bzero(c3,sizeof(*c3)); - c3->ncci = conn->ncci0; - if((err = capi_send(conn->talk,conn->call_ref >> 16,CAPI_DISCONNECTB3_REQ,m3, - conn->conni[WF_DISCONNECTB3_CONF] = newmsgid(conn->talk))) < 0) { - freemsg(m3); - } else { - conn->waitflags |= 1 << WF_DISCONNECTB3_CONF; - conn->waitflags |= 1 << WF_DISCONNECTB3_IND; - setstate(conn,20); + c3 = ((typeof(c3))m3->b_wptr)++; + bzero(c3,sizeof(*c3)); + c3->plci = conn->call_ref; + c3->reject = cause ? ((cause >= 0x100) ? cause : cause | 0x3480) : 0x3480|N1_CallRejected; + if((err = capi_send(conn->talk,conn->call_ref >> 16,CAPI_CONNECT_RESP,m3, + newmsgid(conn->talk))) < 0) { + setstate(conn,0); + freemsg(m3); + } else + setstate(conn,99); } - } - { - struct CAPI_disconnect_req *c3; - mblk_t *m3 = allocb(sizeof(*c3),BPRI_MED); - if(m3 == NULL) - return -ENOMEM; + break; + case 15: + if(do_L3) { + struct CAPI_disconnectb3_req *c3; + mblk_t *m3 = allocb(sizeof(*c3),BPRI_MED); + if(m3 == NULL) + return -ENOMEM; - c3 = ((typeof(c3))m3->b_wptr)++; - bzero(c3,sizeof(*c3)); - c3->plci = conn->call_ref; - if((err = capi_send(conn->talk,conn->call_ref >> 16,CAPI_DISCONNECT_REQ,m3, - conn->conni[WF_DISCONNECT_CONF] = newmsgid(conn->talk))) < 0) { - freemsg(m3); - } else { - conn->waitflags |= 1 << WF_DISCONNECT_CONF; - conn->waitflags |= 1 << WF_DISCONNECT_IND; - if(conn->state < 20) - setstate(conn,21); - else - setstate(conn,22); + c3 = ((typeof(c3))m3->b_wptr)++; + bzero(c3,sizeof(*c3)); + c3->ncci = conn->ncci0; + if((err = capi_send(conn->talk,conn->call_ref >> 16,CAPI_DISCONNECTB3_REQ,m3, + conn->conni[WF_DISCONNECTB3_CONF] = newmsgid(conn->talk))) < 0) { + freemsg(m3); + } else { + conn->waitflags |= 1 << WF_DISCONNECTB3_CONF; + conn->waitflags |= 1 << WF_DISCONNECTB3_IND; + setstate(conn,20); + } + } + /* FALL THRU */ + default: + { + struct CAPI_disconnect_req *c3; + mblk_t *m3 = allocb(sizeof(*c3),BPRI_MED); + if(m3 == NULL) + return -ENOMEM; + + c3 = ((typeof(c3))m3->b_wptr)++; + bzero(c3,sizeof(*c3)); + c3->plci = conn->call_ref; + c3->cause = cause; + if((err = capi_send(conn->talk,conn->call_ref >> 16,CAPI_DISCONNECT_REQ,m3, + conn->conni[WF_DISCONNECT_CONF] = newmsgid(conn->talk))) < 0) { + freemsg(m3); + } else { + conn->waitflags |= 1 << WF_DISCONNECT_CONF; + conn->waitflags |= 1 << WF_DISCONNECT_IND; + if(conn->state < 20) + setstate(conn,21); + else + setstate(conn,22); + } } } return err; } +static int +send_dialout(isdn3_conn conn) +{ + int err; + struct CAPI_connect_req *c2; + struct capi_info *info = conn->p_data; + mblk_t *m2; + + if(info == NULL) + return -ENXIO; + m2 = allocb(sizeof(*c2)+strlen(info->nr)+((info->flags & INF_SPV) != 0),BPRI_MED); + + if(m2 == NULL) + return -ENOMEM; + c2 = ((typeof(c2))m2->b_wptr++); + bzero(c2,sizeof(*c2)); + c2->infomask = ~0; + c2->channel = (info->bchan ? info->bchan : CAPI_ANYBCHANNEL); + c2->DST_service = info->service >> 8; + c2->DST_addinfo = info->service; + if(info->lnr[0] != '\0') + c2->SRC_eaz = info->lnr[strlen(info->lnr)-1]; + c2->telnolen = strlen(info->nr); + strncpy(m2->b_wptr,info->nr,c2->telnolen); + m2->b_wptr += strlen(info->nr); + if(info->flags & INF_SPV) { + c2->telnolen++; + *m2->b_wptr++ = 'S'; + } + conn->call_ref = conn->talk->tappl[info->subcard]<<16; + if((err = capi_send(conn->talk,conn->talk->tappl[info->subcard],CAPI_CONNECT_REQ,m2,conn->conni[WF_CONNECT_CONF]=newmsgid(conn->talk))) < 0) + freemsg(m2); + else { + conn->waitflags = 1<state) { default: err = -EIO; - if(send_disconnect(conn,0) < 0) + if(send_disconnect(conn,0,N1_LocalProcErr) < 0) setstate(conn,0); break; - case 3: + case 4: case 9: setstate(conn,15); isdn3_setup_conn (conn, EST_CONNECT); @@ -559,7 +700,7 @@ after_selectb(isdn3_conn conn) else { conn->waitflags = 1<waitflags |= 1<state); - err = send_disconnect(conn,0); + err = send_disconnect(conn,0,N1_LocalProcErr); if(err < 0) setstate(conn,0); } if(err < 0) - send_disconnect(conn,0); + send_disconnect(conn,0,N1_OutOfOrder); return err; } @@ -616,6 +757,9 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) int err = 0; isdn3_conn conn = 0; + if(talk->state == STATE_DEAD) + return -ENXIO; + printf("CAPI: recv %d, in state %ld\n",isUI,talk->tstate); origmb = data->b_rptr; if(data->b_wptr-data->b_rptr < sizeof(*capi)) @@ -636,13 +780,13 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn3(talk,capi->appl,c2->ncci)) == NULL) { - printf("CAPI error: DISCONNECTB3_CONF has unknown cref3 %04x%04x\n",capi->appl,c2->ncci); + printf("CAPI error: DISCONNECTB3_CONF has unknown cref3 %x%04x\n",capi->appl,c2->ncci); err = -ENXIO; break; } if(c2->info != 0) { printf("CAPI error: DISCONNECTB3_CONF returns %04x\n",c2->info); - send_disconnect(conn,0); + send_disconnect(conn,0,N1_OutOfOrder); break; } if(conn->waitflags & (1<b_rptr)++; if((conn = capi_findconn3(talk,capi->appl,c2->ncci)) == NULL) { - printf("CAPI error: DISCONNECTB3_IND has unknown cref3 %04x%04x\n",capi->appl,c2->ncci); + printf("CAPI error: DISCONNECTB3_IND has unknown cref3 %x%04x\n",capi->appl,c2->ncci); err = -ENXIO; break; } if((c2->info == 0) && (conn->waitflags & (1<waitflags &=~ (1<waitflags == 0) { - report_terminate(conn); + report_terminate(conn,0,0); if(conn->state == 20) { - err = send_disconnect(conn,0); + err = send_disconnect(conn,0,0); if(err < 0) setstate(conn,0); } else @@ -683,11 +827,9 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } } else if((c2->info != 0) || (conn->state >= 20)) { printf("CAPI error: DISCONNECTB3_IND in wrong state %d, info %04x\n",conn->state,c2->info); - err = -EIO; - } else { isdn3_setup_conn (conn, EST_DISCONNECT); - send_disconnect(conn,0); - report_terminate(conn); + send_disconnect(conn,0,N1_OutOfOrder); + report_terminate(conn,c2->info,0); } { int err3 = 0; @@ -703,7 +845,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) freemsg(m3); } if(err == 0) - err = send_disconnect(conn,0); + err = send_disconnect(conn,0,0); if(err == 0) err = err3; } @@ -716,23 +858,22 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: DISCONNECT_IND has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: DISCONNECT_IND has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } if((c2->info == 0) && (conn->waitflags & (1<waitflags &=~ (1<waitflags == 0) { - report_terminate(conn); + report_terminate(conn,0,0); setstate(conn,0); } - } else if((c2->info != 0) || (conn->state >= 21)) { - printf("CAPI error: DISCONNECT_IND in wrong state %d, info %04x\n",conn->state,c2->info); - err = -EIO; } else { + if((c2->info != 0) || (conn->state >= 21)) + printf("CAPI error: DISCONNECT_IND in wrong state %d, info %04x\n",conn->state,c2->info); isdn3_setup_conn (conn, EST_DISCONNECT); - send_disconnect(conn,0); - report_terminate(conn); + send_disconnect(conn,0,0); + report_terminate(conn,c2->info,0); } { int err3 = 0; @@ -748,7 +889,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) freemsg(m3); } if(err == 0) - err = send_disconnect(conn,0); + err = send_disconnect(conn,0,0); if(err == 0) err = err3; } @@ -762,21 +903,21 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: DISCONNECT_CONF has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: DISCONNECT_CONF has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } if((c2->info == 0) || (conn->waitflags & (1<waitflags &=~ (1<waitflags == 0) { - report_terminate(conn); + report_terminate(conn,c2->info,0); setstate(conn,0); } } else { printf("CAPI error: DISCONNECT_CONF in wrong state %d, info %04x\n",conn->state,c2->info); isdn3_setup_conn (conn, EST_DISCONNECT); setstate(conn,0); - report_terminate(conn); + report_terminate(conn,c2->info,0); } } break; @@ -787,15 +928,14 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) if(data->b_wptr-data->b_rptr < sizeof(*c2)) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; - if((conn = capi_findconn(talk,capi->appl,c2->plci)) != NULL) { - printf("CAPI error: CONNECT_CONF has known cref %04x%04x\n",capi->appl,c2->plci); + if((c2->info == 0) && ((conn = capi_findconn(talk,capi->appl,c2->plci)) != NULL)) { + printf("CAPI error: CONNECT_CONF has known cref %x%04x\n",capi->appl,c2->plci); setstate(conn,0); err = -ENXIO; break; } - if((conn = capi_findconnm(talk,capi->appl,capi->messid)) == NULL) { + if((conn = capi_findconnm(talk,capi->appl,capi->messid,WF_CONNECT_CONF)) == NULL) { printf("CAPI error: CONNECT_CONF has unknown msgid %04x.%04x\n",capi->appl,capi->messid); - setstate(conn,0); err = -ENXIO; break; } @@ -804,20 +944,20 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) conn->waitflags &=~ (1<waitflags == 0) { if((err = send_setup(conn)) < 0) { - if(send_disconnect(conn,0) < 0) { + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) { setstate(conn,0); } } else { conn->waitflags |= 1<state,c2->info); isdn3_setup_conn (conn, EST_DISCONNECT); - report_terminate(conn); - if(send_disconnect(conn,0) < 0) + report_terminate(conn,c2->info,0); + if(send_disconnect(conn,0,N1_LocalProcErr) < 0) setstate(conn,0); } } @@ -830,7 +970,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: SELECTB2_CONF has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: SELECTB2_CONF has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } @@ -839,8 +979,8 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = after_selectb(conn); } else { printf("CAPI error: SELECTB2_CONF in wrong state %d, info %04x\n",conn->state,c2->info); - report_terminate(conn); - if(send_disconnect(conn,0) < 0) + report_terminate(conn,c2->info,0); + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } } @@ -852,7 +992,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: SELECTB3_CONF has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: SELECTB3_CONF has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } @@ -861,8 +1001,8 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = after_selectb(conn); } else { printf("CAPI error: SELECTB3_CONF in wrong state %d, info %04x\n",conn->state,c2->info); - report_terminate(conn); - if(send_disconnect(conn,0) < 0) + report_terminate(conn,c2->info,0); + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } } @@ -874,7 +1014,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: CONNECTACTIVE_IND has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: CONNECTACTIVE_IND has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } @@ -883,7 +1023,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = after_active(conn); } else { printf("CAPI error: CONNECTACTIVE_IND in wrong state %d\n",conn->state); - if(send_disconnect(conn,0) < 0) + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } { @@ -911,7 +1051,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: LISTENB3_CONF has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: LISTENB3_CONF has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } @@ -921,7 +1061,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } else { err = -EIO; printf("CAPI error: LISTENB3_CONF in wrong state %d, info %04x\n",conn->state,c2->info); - if(send_disconnect(conn,0) < 0) + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } } @@ -933,7 +1073,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { - printf("CAPI error: CONNECTB3_CONF has unknown cref %04x%04x\n",capi->appl,c2->plci); + printf("CAPI error: CONNECTB3_CONF has unknown cref %x%04x\n",capi->appl,c2->plci); err = -ENXIO; break; } @@ -962,7 +1102,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = -EIO; printf("CAPI error: CONNECTB3_CONF in wrong state %d, info %04x\n",conn->state,c2->info); exSendD: - if(send_disconnect(conn,0) < 0) + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } } @@ -975,7 +1115,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) goto less_room; c2 = ((typeof(c2))data->b_rptr)++; if((conn = capi_findconn3(talk,capi->appl,c2->ncci)) == NULL) { - printf("CAPI error: CONNECTB3ACTIVE_IND has unknown cref %04x%04x\n",capi->appl,c2->ncci); + printf("CAPI error: CONNECTB3ACTIVE_IND has unknown cref %x%04x\n",capi->appl,c2->ncci); err = -ENXIO; break; } @@ -984,7 +1124,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = after_active(conn); } else { printf("CAPI error: CONNECTB3ACTIVE_IND in wrong state %d\n",conn->state); - if(send_disconnect(conn,0) < 0) + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) setstate(conn,0); } { @@ -1016,7 +1156,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) if(data->b_wptr-data->b_rptr < c2->telnolen) goto less_room; if((conn = capi_findconn(talk,capi->appl,c2->plci)) != NULL) { /* Duplicate. Hmmm. */ - printf("CAPI error: Incoming call has dup cref %04x%04x for conn %d\n",capi->appl, c2->plci,conn->conn_id); + printf("CAPI error: Incoming call has dup cref %x%04x for conn %d\n",capi->appl, c2->plci,conn->conn_id); err = 0; break; } else { @@ -1028,16 +1168,48 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) err = -ENOMEM; } else { struct capi_info *info = conn->p_data; - info->eaz = c2->DST_eaz; + + bzero(info,sizeof(*info)); + info->subcard = ~0; + { + int i; + for(i=0;i < talk->card->dchans; i++) { + if(capi->appl == talk->tappl[i]) { + info->subcard = i; + break; + } + } + } + if(c2->DST_eaz) { + info->lnr[0] = '/'; + info->lnr[1] = c2->DST_eaz; + info->lnr[2] = '\0'; + } else + info->lnr[0] = '\0'; info->service = (c2->DST_service << 8) | c2->DST_addinfo; - bcopy(data->b_rptr,info->nr,c2->telnolen); + if(c2->telnolen > 1) { + int nrlen = c2->telnolen; + switch(*data->b_rptr) { + case 0x91: /* international number */ + case 0xA1: /* national number */ + data->b_rptr++; nrlen--; + if(data->b_rptr[nrlen-1] == 'S') /* SPV */ + nrlen--; + if(nrlen >= MAXNR) + nrlen = MAXNR-1; + bcopy(data->b_rptr,info->nr,nrlen); + break; + default: + err = -EINVAL; + break; + } + } conn->call_ref = (capi->appl << 16) | c2->plci; conn->msgid0 = capi->messid; - err = report_incoming(conn); - if(err == 0) { - setstate(conn,7); + if(err >= 0) { + setstate(conn,6); break; } } @@ -1059,10 +1231,111 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } break; + case CAPI_INFO_IND: + { + struct CAPI_info_ind *c2; + mblk_t *m3; + struct capi_info *info; + + if(data->b_wptr-data->b_rptr < sizeof(*c2)) + goto less_room; + c2 = ((typeof(c2))data->b_rptr)++; + if((conn = capi_findconn(talk,capi->appl,c2->plci)) == NULL) { + printf("CAPI error: INFO_IND has unknown cref %x%04x\n",capi->appl,c2->plci); + err = -ENXIO; + break; + } + if(conn->p_data == NULL) { + if((conn->p_data = malloc(sizeof(struct capi_info))) == NULL) { + err = -ENOMEM; + break; + } + bzero(conn->p_data,sizeof(struct capi_info)); + ((struct capi_info *)conn->p_data)->subcard = 0; + } + info = conn->p_data; + + m3 = allocb(256,BPRI_MED); + if(m3 != NULL) { + switch(c2->info_number) { + case AI_CAUSE: +#if 0 + { + m_putid(m3,IND_INFO); + m_putid(m3,ID_N1_INFO); + m_putsx(m3,ARG_CAUSE); + m_puts(m3,data->b_rptr,c2->infolen); + } +#endif + break; + case AI_DISPLAY: + { + m_putid(m3,IND_INFO); + m_putid(m3,ID_N1_INFO); + m_putsx(m3,ID_N0_display); + m_puts(m3,data->b_rptr,c2->infolen); + } + break; + case AI_DAD: + { + int nrlen = c2->infolen; + switch(*data->b_rptr) { + case 0x81: + data->b_rptr++; nrlen--; + if(nrlen >= MAXNR) + nrlen = MAXNR-1; + bcopy(data->b_rptr,info->lnr,nrlen); + setstate(conn,7); + report_incoming(conn); + break; + default: + err = -EINVAL; + break; + } + } + break; + case AI_UUINFO: + break; + case AI_CHARGE: + break; + case AI_DATE: + { + m_putid(m3,IND_INFO); + m_putid(m3,ID_N1_INFO); + m_putsx(m3,ID_N6_date); + m_puts(m3,data->b_rptr,c2->infolen); + } + break; + case AI_CPS: + break; + default: + printf("CAPI error: unknown INFO_IND ID %x\n",c2->info_number); + freemsg(m3); m3 = NULL; + break; + } + } + if(m3 != NULL) { + conn_info (conn, m3); + if ((err = isdn3_at_send (conn, m3, 0)) < 0) + freemsg(m3); + } + } + break; + /* Non-connection-related messages */ case CAPI_REGISTER_CONF: + if(talk->tstate != STATE_REGISTER) { + printf("CAPI error: bad state\n"); + break; + } +#if 0 + if(talk->message_id != capi->messid) { + printf("CAPI error: register bad ID %d, want %ld\n",capi->messid,talk->message_id); + break; + } +#endif talk->tstate = STATE_CONF_LAST; - /* TODO: get parameters (EAZMAP, et al.) and send them */ + talk->tappl[talk->regnum] = capi->appl; { mblk_t *info = talk->card->info; if(info != NULL) { @@ -1091,9 +1364,15 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } } break; + case ARG_SUBCARD: + if (m_geti(info,&sap) == 0 && !skip) + skip = (sap != talk->regnum+1); + break; case ARG_EAZ: if(skip) break; + if(talk->state & 1<<(talk->regnum+ST_pbx)) + break; { char eaz; struct eazmapping *ce; @@ -1116,7 +1395,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) break; } mp->b_wptr += len; - if((err = capi_sendctl(talk,0,CONTROL_EAZMAPPING,mp,newmsgid(talk))) < 0) { + if((err = capi_sendctl(talk,talk->tappl[talk->regnum],CONTROL_EAZMAPPING,mp,newmsgid(talk))) < 0) { freemsg(mp); break; } @@ -1136,9 +1415,9 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) return -ENOMEM; c2 = ((struct CAPI_listen_req *)mp->b_wptr)++; bzero(c2,sizeof(*c2)); - c2->info_mask = 0x003F; + c2->info_mask = 0xC00000FF; c2->eaz_mask = 0x03FF; - c2->service_mask = 0xFFFF; + c2->service_mask = 0xE7BF; { /* Find correct driver name */ int err; char skip = 0; mblk_t *info = talk->card->info; @@ -1167,6 +1446,10 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } } break; + case ARG_SUBCARD: + if (m_geti(info,&sap) == 0 && !skip) + skip = (sap != talk->regnum+1); + break; case ARG_LISTEN: { long x; @@ -1188,7 +1471,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) info->b_rptr = sta; } } - if((err = capi_send(talk,0,CAPI_LISTEN_REQ,mp,newmsgid(talk))) < 0) { + if((err = capi_send(talk,talk->tappl[talk->regnum],CAPI_LISTEN_REQ,mp,newmsgid(talk))) < 0) { freemsg(mp); return err; } @@ -1201,14 +1484,18 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) c2 = ((typeof(c2))data->b_rptr)++; if(c2->info != 0) { printf("CAPI error: LISTEN failed %04x\n",c2->info); + report_nocard(talk,c2->info); return -EIO; } if(talk->tstate < STATE_CONF_FIRST || talk->tstate > STATE_CONF_LAST) { printf("CAPI error: LISTEN return in bad state\n"); return -EIO; } - if(++talk->tstate == STATE_CONF_LAST) + if(++talk->tstate == STATE_CONF_LAST) { talk->tstate = STATE_RUNNING; + if(++talk->regnum < talk->card->dchans) + send_open(talk); + } } break; case CAPI_ALIVE_IND: @@ -1216,7 +1503,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) printf("CAPI: ALIVE_REQ in state %ld\n",talk->tstate); goto printit; } - err = capi_send(talk,0,CAPI_ALIVE_RESP,NULL,capi->messid); + err = capi_send(talk,capi->appl,CAPI_ALIVE_RESP,NULL,capi->messid); break; case CAPI_CONTROL_CONF: { @@ -1226,8 +1513,41 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) c2 = ((struct CAPI_control_conf *)data->b_rptr)++; switch(c2->type) { default: - printf("Unknown control_conf type 0x%02x\n",c2->type); + printf("CAPI: Unknown control_conf type 0x%02x\n",c2->type); goto printit; + case CONTROL_EAZMAPPING: + { + if(talk->tstate == STATE_RUNNING) { + if((conn = capi_findconnm(talk,capi->appl,capi->messid,WF_CONTROL_EAZ)) == NULL) { + printf("CAPI error: CONTROL_EAZMAPPING has unknown conn\n"); + err = -ENXIO; + break; + } + if((c2->info == 0) && (conn->waitflags & (1<waitflags &=~ (1<state,c2->info); + if(send_disconnect(conn,0,N1_OutOfOrder) < 0) + setstate(conn,0); + } + } else if(talk->tstate < STATE_CONF_FIRST || talk->tstate > STATE_CONF_LAST) { + printf("CAPI error: CONTROL_EAZ in wrong state %d, info %04x\n",conn->state,c2->info); + } + if(c2->info != 0) { + printf("CAPI error: EAZMAPPING failed %04x\n",c2->info); + report_nocard(talk,c2->info); + return -EIO; + } + if(++talk->tstate == STATE_CONF_LAST) { + printf("CAPI: EAZMAPPING after LISTEN_CONF ???\n"); + talk->tstate = STATE_RUNNING; + if(++talk->regnum < talk->card->dchans) + send_open(talk); + } + } + break; case CONTROL_API_OPEN: /* Boot: Step One */ if(talk->tstate != STATE_OPENING) { printf("CAPI error: API_OPEN reply for bad state\n"); @@ -1235,10 +1555,12 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) } if(c2->info <= 0) { printf("CAPI error: open failed!\n"); + report_nocard(talk,c2->info); return -EIO; } - if(c2->info > 1) - printf("CAPI: %d D channels -- using only the first, for now\n",c2->info); + if(talk->card->dchans != c2->info) { + printf("CAPI: %d D channels -- that should be %d\n",c2->info,talk->card->dchans); + } { struct CAPI_register_req *c3; @@ -1248,100 +1570,23 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) c3 = ((struct CAPI_register_req *)mp->b_wptr)++; bzero(c3,sizeof(*c3)); c3->nmess = 10; - c3->nconn = 2 /* TODO: 30 */ ; + c3->nconn = talk->card->bchans + (talk->card->bchans >> 1) + 1;; c3->ndblock = c3->nconn*10; c3->dblocksiz = 4096; - if((err = capi_send(talk,0,CAPI_REGISTER_REQ,mp,newmsgid(talk))) < 0) { + if((err = capi_send(talk,talk->tappl[talk->regnum],CAPI_REGISTER_REQ,mp,newmsgid(talk))) < 0) { freemsg(mp); break; } talk->tstate = STATE_REGISTER; } - break; } } + break; } if(err >= 0) freemsg(data); return err; -#if 0 - isdn3_conn conn = NULL; - uchar_t prot; - long cref = 0; - char cref_net = 0; - uchar_t msgtype; - uchar_t c; - uchar_t *mdata; - ushort_t mlen; - - if (0) - printf ("Phone_Recv: "); - if ((data = pullupm (data, 0)) == NULL) - return 0; - prot = *data->b_rptr++; - if ((data = pullupm (data, 0)) == NULL) - return 0; - c = *data->b_rptr++; - if ((data = pullupm (data, 0)) == NULL) - return 0; - if (c & 0xF0 || c > 4) - return 0; - if ((data = pullupm (data, 0)) == NULL) - return 0; - if (c != 0 && *data->b_rptr & 0x80) { - cref_net = 1; - *data->b_rptr &= ~0x80; - } - cref = 0; - while (c--) { - cref = (cref << 8) + (*data->b_rptr++ & 0xFF); - if ((data = pullupm (data, 0)) == NULL) - return 0; - } - if (!cref_net) - cref = -(cref+1); - else - cref = cref+1; - - msgtype = *data->b_rptr++; - if ((data = pullupm (data, 0)) == NULL) { - mdata = NULL; - mlen = 0; - } else { - mblk_t *mb = pullupm (data, -1); - - if (mb == NULL) { - freemsg (data); - printf ("No Pullup\n"); - isdn3_killconn (conn, 1); /* Nothing to be done... */ - return 0; - } - data = mb; - mdata = (uchar_t *) mb->b_rptr; - mlen = (uchar_t *) mb->b_wptr - mdata; - } - conn = isdn3_findconn (talk, prot, cref); - if (conn == NULL) { - conn = isdn3_new_conn (talk); - if (conn == NULL) - goto out; - conn->call_ref = cref; - conn->subprotocol = prot; - printf (" NewConn"); - } { - isdn3_prot proto = isdn3_findprot (talk->card->info, conn->subprotocol); - - if (proto != NULL) - (*proto->recv) (conn, msgtype, isUI, mdata, mlen); - else - isdn3_killconn (conn, 1); - } - out: - if (data != NULL) - freemsg (data); - return 0; -#endif less_room: printf("CAPI error: too few data bytes\n"); printit: @@ -1355,7 +1600,7 @@ recv (isdn3_talk talk, char isUI, mblk_t * data) static int send (isdn3_conn conn, mblk_t * data) { - printf("CAPI: send %08lx\n",conn->call_ref); + printf("CAPI: send %05lx\n",conn->call_ref); return -ENXIO; #if 0 isdn3_prot prot = isdn3_findprot (conn->card->info, conn->subprotocol); @@ -1379,8 +1624,12 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) /* uchar_t svc = 0; */ struct capi_info *info; int force = 0; + uchar_t cause = 0; - printf("CAPI: sendcmd %08lx %04x: ",conn->call_ref,id); + if(conn->talk->state == STATE_DEAD) + return -ENXIO; + + printf("CAPI: sendcmd %05lx %04x: ",conn->call_ref,id); { mblk_t *mb = data; if(mb == NULL) printf("NULL"); else @@ -1395,6 +1644,7 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) return -ENOMEM; } bzero(conn->p_data,sizeof(struct capi_info)); + ((struct capi_info *)conn->p_data)->subcard = 0; } conn->lockit++; info = conn->p_data; @@ -1403,31 +1653,67 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) oldpos = data->b_rptr; while ((err = m_getsx (data, &typ)) == 0) { - switch (typ) { - case ARG_SERVICE: - if ((err = m_getx (data, &x)) != 0) { + switch(typ) { + case ARG_CAUSE: + { + extern uchar_t n1_idtocause(ushort_t); + ushort_t causeid; + + if (m_getid (data, &causeid) != 0) + break; + cause = n1_idtocause(causeid); + } + break; + + case ARG_SUBCARD: + if ((err = m_geti (data, &x)) != 0) { + printf("GetX Subcard: "); + RetErr: data->b_rptr = oldpos; - printf("GetX Service: "); conn->lockit--; return err; + } + if(x < 1 || x > conn->talk->card->dchans) { + err = -ENXIO; + goto RetErr; + } + if(id == CMD_DIAL) + info->subcard = x-1; + else if(info->subcard != x-1) { + printf("GetX Subcard.: %d != %ld-1",info->subcard,x); + err = -EINVAL; + goto RetErr; + } + break; + case ARG_SERVICE: + if ((err = m_getx (data, &x)) != 0) { + printf("GetX Service: "); + goto RetErr; } info->service = x; break; - case ARG_EAZ: - if ((err = m_getc (data, &info->eaz)) != 0) { - data->b_rptr = oldpos; - printf("GetX EAZ: "); - conn->lockit--; - return err; + case ARG_SPV: + info->flags |= INF_SPV; + break; + case ARG_CHANNEL: + if ((err = m_geti (data, &x)) != 0) { + printf("GetX Bchan: "); + goto RetErr; + } + info->bchan = x; + break; + case ARG_LNUMBER: + m_getskip (data); + if ((err = m_getstr (data, (char *) info->lnr, MAXNR)) != 0) { + printf("GetStr LNumber: "); + goto RetErr; } break; case ARG_NUMBER: m_getskip (data); if ((err = m_getstr (data, (char *) info->nr, MAXNR)) != 0) { - data->b_rptr = oldpos; printf("GetStr Number: "); - conn->lockit--; - return err; + goto RetErr; } break; case ARG_FORCE: @@ -1454,12 +1740,10 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) } err = send_setup(conn); if(err == 0) { - freemsg(data); setstate(conn,8); - conn->waitflags = 1 << WF_SELECTB2_CONF; - conn->waitflags |= 1 << WF_SELECTB3_CONF; + freemsg(data); } else - send_disconnect(conn,0); + send_disconnect(conn,0,N1_OutOfOrder); } case CMD_DIAL: { @@ -1473,37 +1757,38 @@ sendcmd (isdn3_conn conn, ushort_t id, mblk_t * data) conn->lockit--; return -EINVAL; } - { - struct CAPI_connect_req *c2; - mblk_t *m2 = allocb(sizeof(*c2)+strlen(info->nr),BPRI_MED); + if((info->lnr[0] != '\0') && (conn->talk->state & (1<<(info->subcard+ST_pbx)))) { + char eaz; + struct eazmapping *ce; + mblk_t *mp; + int len = strlen(info->lnr+1); - if(m2 == NULL) - return -ENOMEM; - c2 = ((typeof(c2))m2->b_wptr++); - bzero(c2,sizeof(*c2)); - c2->infomask = ~0; - c2->DST_service = info->service >> 8; - c2->DST_addinfo = info->service; - c2->SRC_eaz = info->eaz; - c2->telnolen = strlen(info->nr); - strcpy(m2->b_wptr,info->nr); - m2->b_wptr += strlen(info->nr); - if((err = capi_send(conn->talk,0,CAPI_CONNECT_REQ,m2,conn->conni[WF_CONNECT_CONF]=newmsgid(conn->talk))) < 0) - freemsg(m2); + eaz = ++conn->talk->lasteaz; + if(eaz > 8) eaz = 1; + eaz += '0'; + mp = allocb(sizeof(*ce)+len, BPRI_MED); + if(mp == NULL) + break; + ce = ((struct eazmapping *)mp->b_wptr)++; + bzero(ce,sizeof(*ce)); + ce->eaz = eaz; + ce->telnolen = len; + strncpy(mp->b_wptr,info->lnr+1,len); + mp->b_wptr += len; + if((err = capi_sendctl(conn->talk,conn->talk->tappl[conn->talk->regnum],CONTROL_EAZMAPPING,mp,conn->conni[WF_CONTROL_EAZ] = newmsgid(conn->talk))) < 0) + freemsg(mp); else { - conn->waitflags = 1<waitflags = 1<call_ref); + printf("CAPI: report %05lx: ",conn->call_ref); { mblk_t *mb = data; if(mb == NULL) printf("NULL"); else @@ -1547,83 +1832,48 @@ report (isdn3_conn conn, mblk_t * data) m_putsx (data, ARG_NUMBER); m_putsz (data, info->nr); } - if (info->eaz != 0) { - m_putsx (data, ARG_EAZ); - *data->b_wptr++=' '; - *data->b_wptr++=info->eaz; + if (info->lnr[0] != 0) { + m_putsx (data, ARG_LNUMBER); + m_putsz (data, info->lnr); } if (info->service != 0) { m_putsx (data, ARG_SERVICE); m_putx (data, info->service); } + if(info->subcard != (unsigned char) ~0) { + m_putsx (data, ARG_SUBCARD); + m_puti (data,info->subcard+1); + } } static void ckill (isdn3_talk talk, char force) { printf("CAPI: ckill %d\n",force); -#if 0 - if (force) { - if (talk->tstate & PHONE_UP) { - talk->tstate &= ~PHONE_UP; - if(0)printf("Phone is aDown\n"); - isdn3_chstate (talk, DL_RELEASE_REQ, 0, CH_CLOSEPROT); - } - } -#endif } static void killconn (isdn3_conn conn, char force) { - printf("CAPI: killconn %08lx: %d\n",conn->call_ref,force); + printf("CAPI: killconn %05lx: %d\n",conn->call_ref,force); + conn->lockit++; + if (force) { + untimer (CAPI_TCONN, conn); + untimer (CAPI_TWAITEAZ, conn); + } + send_disconnect(conn, !force, 0); if (conn->p_data != NULL) { free (conn->p_data); conn->p_data = NULL; } - if (force) { - untimer (CAPI_TALERT, conn); - } - switch(conn->state) { - } - -#if 0 - isdn3_talk talk = conn->talk; - isdn3_prot prot = isdn3_findprot (conn->card->info, conn->subprotocol); - - if (prot != NULL) - (*prot->killconn) (conn, force); - - if (talk != NULL && talk->conn == NULL && (talk->tstate & PHONE_UP)) { - /* Last talker got closed. Shutdown for level 2. */ - talk->tstate &= ~PHONE_UP; - if(0)printf ("PHONE i2s DOWN\n"); - (void) isdn3_chstate (talk, DL_RELEASE_REQ, 0, CH_CLOSEPROT); - } else { -#if 0 - printf ("Killconn: Phone s1tays up"); - if (talk == NULL) - printf (": Talk NULL"); - else if (talk->conn != NULL) - printf (": talk->conn %x (ref %08lx, state %d)", talk->conn, talk->conn->call_ref, talk->conn->state); - if (!(talk->tstate & PHONE_UP)) - if(0)printf (": PHONE i3s DOWN\n"); - printf ("\n"); -#endif - } -#endif + conn->lockit--; + checkterm(conn); } static void hook (isdn3_conn conn) { - printf("CAPI: hook %08lx\n",conn->call_ref); -#if 0 - isdn3_prot prot = isdn3_findprot (conn->card->info, conn->subprotocol); - - if (prot != NULL && prot->hook != NULL) - (*prot->hook) (conn); -#endif + printf("CAPI: hook %05lx\n",conn->call_ref); } @@ -1640,6 +1890,7 @@ newcard (isdn3_card card) } talk->message_id = 0x4000; talk->tstate = STATE_BOOTING; + if(card->is_up) chstate (talk, DL_ESTABLISH_CONF,0); @@ -1658,7 +1909,7 @@ proto(struct _isdn3_conn * conn, mblk_t **data, char down) { mblk_t *mb = *data; - printf("CAPI: proto %08lx %s: ",conn->call_ref, down ? "down" : "up"); + printf("CAPI: proto %05lx %s: ",conn->call_ref, down ? "down" : "up"); if(mb == NULL) printf("NULL"); else while(mb != NULL) { dumpascii(mb->b_rptr,mb->b_wptr-mb->b_rptr); @@ -1683,3 +1934,74 @@ struct _isdn3_hndl CAPI_hndl = &sendcmd, &ckill, &killconn, &hook, &proto, }; + + + +ushort_t +capi_infotoid(ushort_t info) +{ + extern ushort_t n1_causetoid(uchar_t); + + if((info & 0xFF00) == 0x3400) + return n1_causetoid(info & 0x7F); + switch(info) { + default: return CHAR2('?','?'); + case CAPI_E_REGISTER: return ID_E_REGISTER; + case CAPI_E_APPLICATION: return ID_E_APPLICATION; + case CAPI_E_MSGLENGTH: return ID_E_MSGLENGTH; + case CAPI_E_COMMAND: return ID_E_COMMAND; + case CAPI_E_QUEUEFULL: return ID_E_QUEUEFULL; + case CAPI_E_NOMSG: return ID_E_NOMSG; + case CAPI_E_MSGOVERFLOW: return ID_E_MSGOVERFLOW; + case CAPI_E_DEINSTALL: return ID_E_DEINSTALL; + case CAPI_E_CONTROLLER: return ID_E_CONTROLLER; + case CAPI_E_PLCI: return ID_E_PLCI; + case CAPI_E_NCCI: return ID_E_NCCI; + case CAPI_E_TYPE: return ID_E_TYPE; + case CAPI_E_BCHANNEL: return ID_E_BCHANNEL; + case CAPI_E_INFOMASK: return ID_E_INFOMASK; + case CAPI_E_EAZMASK: return ID_E_EAZMASK; + case CAPI_E_SIMASK: return ID_E_SIMASK; + case CAPI_E_B2PROTO: return ID_E_B2PROTO; + case CAPI_E_DLPD: return ID_E_DLPD; + case CAPI_E_B3PROTO: return ID_E_B3PROTO; + case CAPI_E_NCPD: return ID_E_NCPD; + case CAPI_E_NCPI: return ID_E_NCPI; + case CAPI_E_DATAB3FLAGS: return ID_E_DATAB3FLAGS; + case CAPI_E_CONTROLLERFAILED: return ID_E_CONTROLLERFAILED; + case CAPI_E_REGCONFLICT: return ID_E_REGCONFLICT; + case CAPI_E_CMDNOTSUPPORTED: return ID_E_CMDNOTSUPPORTED; + case CAPI_E_PLCIACT: return ID_E_PLCIACT; + case CAPI_E_NCCIACT: return ID_E_NCCIACT; + case CAPI_E_B2NOTSUPPORT: return ID_E_B2NOTSUPPORT; + case CAPI_E_B2STATE: return ID_E_B2STATE; + case CAPI_E_B3NOTSUPPORT: return ID_E_B3NOTSUPPORT; + case CAPI_E_B3STATE: return ID_E_B3STATE; + case CAPI_E_B2DLPDPARA: return ID_E_B2DLPDPARA; + case CAPI_E_B3NCPDPARA: return ID_E_B3NCPDPARA; + case CAPI_E_B3NCPIPARA: return ID_E_B3NCPIPARA; + case CAPI_E_DATALEN: return ID_E_DATALEN; + case CAPI_E_DTMF: return ID_E_DTMF; + case CAPI_E_NOL1: return ID_E_NOL1; + case CAPI_E_NOL2: return ID_E_NOL2; + case CAPI_E_SETUPBCHANLAYER1: return ID_E_SETUPBCHANLAYER1; + case CAPI_E_SETUPBCHANLAYER2: return ID_E_SETUPBCHANLAYER2; + case CAPI_E_ABORTDCHANLAYER1: return ID_E_ABORTDCHANLAYER1; + case CAPI_E_ABORTDCHANLAYER2: return ID_E_ABORTDCHANLAYER2; + case CAPI_E_ABORTDCHANLAYER3: return ID_E_ABORTDCHANLAYER3; + case CAPI_E_ABORTBCHANLAYER1: return ID_E_ABORTBCHANLAYER1; + case CAPI_E_ABORTBCHANLAYER2: return ID_E_ABORTBCHANLAYER2; + case CAPI_E_ABORTBCHANLAYER3: return ID_E_ABORTBCHANLAYER3; + case CAPI_E_REBCHANLAYER2: return ID_E_REBCHANLAYER2; + case CAPI_E_REBCHANLAYER3: return ID_E_REBCHANLAYER3; + case CAPI_E_NOFAX: return ID_E_NOFAX; + case CAPI_E_BADLINE: return ID_E_BADLINE; + case CAPI_E_NOANSWER: return ID_E_NOANSWER; + case CAPI_E_REMDISC: return ID_E_REMDISC; + case CAPI_E_NOCMD: return ID_E_NOCMD; + case CAPI_E_INCOMPAT: return ID_E_INCOMPAT; + case CAPI_E_BADDATA: return ID_E_BADDATA; + case CAPI_E_PROTO: return ID_E_PROTO; + } +} + diff --git a/isdn_3/isdn_3.c b/isdn_3/isdn_3.c index 78615de..6480871 100644 --- a/isdn_3/isdn_3.c +++ b/isdn_3/isdn_3.c @@ -970,13 +970,11 @@ isdn3_new_conn (isdn3_talk talk) memset(conn,0,sizeof (*conn)); ms = splstr(); - conn->conn_id = conn_id; + conn->conn_id = conn_id; conn_id += 2; conn->card = talk->card; conn->next = talk->conn; conn->talk = talk; - conn->call_ref = 0; talk->conn = conn; - conn_id += 2; splx (ms); return conn; } @@ -1485,11 +1483,6 @@ printf("ErX g\n"); case ARG_CALLREF: if ((err = m_geti (mx, &call_ref)) != 0) goto err_out; - if (call_ref == 0 || call_ref < -128 || call_ref > 127) { -printf("ErX h\n"); - err = -EINVAL; - goto err_out; - } break; case ARG_INT: do_int = 1; @@ -2010,7 +2003,7 @@ printf("ErX k\n"); break; case CMD_PROT: m_getskip (mx); - if (mx->b_rptr < mx->b_wptr && *mx->b_rptr == PROTO_MODE) { + if ((mx->b_rptr < mx->b_wptr) && (*mx->b_rptr == PROTO_MODE)) { if (0) printf ("Proto SetMode\n"); /* Protocol setup completed. Or so it seems. */ @@ -2458,7 +2451,7 @@ isdn3_findtalk (isdn3_card card, isdn3_hndl hndl, mblk_t *info, int create) int i; int err; -char systr[100] = ""; +char systr[200] = ""; if(card->info != NULL) sprintf(systr+strlen(systr),"'%-*s'",card->info->b_wptr-card->info->b_rptr,card->info->b_rptr); else strcat(systr,"NULL"); @@ -3075,6 +3068,7 @@ printf(" *SM %d: %d %d.%d\n",__LINE__,conn->conn_id,conn->minor,conn->fminor); card->nr = hdr.hdr_card.card; card->id = hdr.hdr_card.id; card->TEI = TEI_BROADCAST; + card->dchans = hdr.hdr_card.dchans; card->bchans = hdr.hdr_card.bchans; card->modes = hdr.hdr_card.modes; card->next = isdn_card; @@ -3082,6 +3076,7 @@ printf(" *SM %d: %d %d.%d\n",__LINE__,conn->conn_id,conn->minor,conn->fminor); if ((mx = allocb (32, BPRI_MED)) != 0) { m_putid (mx, IND_CARD); m_putlx (mx, hdr.hdr_card.id); + m_puti (mx, hdr.hdr_card.dchans); m_puti (mx, hdr.hdr_card.bchans); m_putx (mx, hdr.hdr_card.modes); putnext (q, mx); diff --git a/isdn_3/prot_1TR6_common.c b/isdn_3/prot_1TR6_common.c index 82b0a7e..0d4056e 100644 --- a/isdn_3/prot_1TR6_common.c +++ b/isdn_3/prot_1TR6_common.c @@ -174,12 +174,12 @@ report_adddate (mblk_t * mb, uchar_t * data, int len) int qd_len; uchar_t *qd_data; - qd_data = qd_find (data, len, 6, PT_N6_Date, &qd_len); + qd_data = qd_find (data, len, 6, PT_N6_date, &qd_len); if (qd_data == NULL) return; if (qd_len < 1) return; - m_putsx (mb, ID_N6_Date); + m_putsx (mb, ID_N6_date); m_puts (mb, qd_data, qd_len); } @@ -204,12 +204,12 @@ report_addstatus (mblk_t * mb, uchar_t * data, int len) int qd_len; uchar_t *qd_data; - qd_data = qd_find (data, len, 6, PT_N6_StatusCalled, &qd_len); + qd_data = qd_find (data, len, 6, PT_N6_statusCalled, &qd_len); if (qd_data == NULL) return; if (qd_len < 1) return; - m_putsx (mb, ID_N6_StatusCalled); + m_putsx (mb, ID_N6_statusCalled); switch (*qd_data) { case N1_St_Unknown: m_putsx2 (mb, ID_N1_St_Unknown); @@ -223,7 +223,8 @@ report_addstatus (mblk_t * mb, uchar_t * data, int len) m_puts (mb, qd_data, qd_len); } -ushort_t n1_causetoid(uchar_t id) +ushort_t +n1_causetoid(uchar_t id) { switch(id) { default: return CHAR2('?','?'); @@ -258,7 +259,8 @@ ushort_t n1_causetoid(uchar_t id) } } -uchar_t n1_idtocause(ushort_t id) +uchar_t +n1_idtocause(ushort_t id) { switch(id) { default: return 0; @@ -293,7 +295,8 @@ uchar_t n1_idtocause(ushort_t id) } } -ushort_t n1_facsubtoid(uchar_t id) +ushort_t +n1_facsubtoid(uchar_t id) { switch(id) { default: return CHAR2('?','?'); @@ -304,7 +307,8 @@ ushort_t n1_facsubtoid(uchar_t id) } } -ushort_t n1_factoid(uchar_t id) +ushort_t +n1_factoid(uchar_t id) { switch(id) { default: return CHAR2('?','?'); @@ -330,7 +334,8 @@ ushort_t n1_factoid(uchar_t id) } } -uchar_t n1_idtofacsub(ushort_t id) +uchar_t +n1_idtofacsub(ushort_t id) { switch(id) { default: return 0; @@ -341,7 +346,8 @@ uchar_t n1_idtofacsub(ushort_t id) } } -uchar_t n1_idtofac(ushort_t id) +uchar_t +n1_idtofac(ushort_t id) { switch(id) { default: return 0; diff --git a/isdn_3/prot_ETS.c b/isdn_3/prot_ETS.c index 4389eea..99e6d05 100644 --- a/isdn_3/prot_ETS.c +++ b/isdn_3/prot_ETS.c @@ -437,6 +437,12 @@ printf("FacL 8 is %d %d\n",ilen,nlen); ilen--; } +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6)) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + #define FOO1(s,a,b) \ while(nlen > 1) { \ int ilen = qd_data[1]; \ @@ -446,7 +452,7 @@ printf("FooL" ##s " is %d,%d\n",nlen,ilen); \ } \ nlen -= ilen+2; \ if((*qd_data & 0xFF) == (a)) { \ - int nlen __attribute__((unused)) = ilen; \ + int nlen UNUSED = ilen; \ qd_data += 2; \ b; \ } else { \ @@ -668,20 +674,29 @@ get_ET_nr (isdn3_conn conn, uchar_t * data, int len, uchar_t *nrpos, uchar_t wha if (qd_len < 1) return 0; switch(*qd_data & 0x70) { - case 0x00: - break; /* unknown */ - case 0x10: - *nrpos++='+'; break; /* international */ - case 0x20: - *nrpos++='='; break; /* national */ - case 0x30: - break; /* network specific */ - case 0x40: - *nrpos++='-'; break; /* subscriber */ - case 0x60: - *nrpos++='.'; break; /* abbreviated */ - case 0x70: - *nrpos++='x'; break; /* extension */ + case 0x00: /* unknown */ + if(qd_data[0] == 0x00 && qd_data[1] == 0x83) + *nrpos++ = '='; /* at least one PBX is stupid */ + else if(qd_data[0] == 0x81) + *nrpos++='.'; /* the very same PBX */ + break; + case 0x10: /* international */ + *nrpos++='+'; + break; + case 0x20: /* national */ + *nrpos++='='; + break; + case 0x30: /* network specific */ + break; + case 0x40: /* subscriber */ + *nrpos++='-'; + break; + case 0x60: /* abbreviated */ + *nrpos++='.'; + break; + case 0x70: /* extension */ + *nrpos++='.'; + break; } while (qd_len-- > 0 && (*qd_data++ & 0x80) == 0) ; if (qd_len < 1) diff --git a/isdn_4/Makefile b/isdn_4/Makefile index 96da6cf..44e2f23 100644 --- a/isdn_4/Makefile +++ b/isdn_4/Makefile @@ -1,5 +1,6 @@ PROGRAM = master EXTRA_LIBS=../isdn_3.a ../support.a +EXTRA_CFLAGS=$(addsuffix _,$(addprefix -D_,$(PROTOCOLS) $(SUBPROTOCOLS))) TOPDIR=.. include $(TOPDIR)/Make.rules diff --git a/isdn_4/cf.c b/isdn_4/cf.c index d8263a8..f6f848f 100644 --- a/isdn_4/cf.c +++ b/isdn_4/cf.c @@ -102,6 +102,27 @@ skipword (char **li) } #endif +void +do_subclass(cf c) +{ + char *info; + if((info = strchr(c->card,'/')) != NULL) { + int x = 0; + *info++ = '\0'; + c->mask = 0; + while(*info != 0) { + if(*info >= '0' && *info <= '9') { + x = x * 10 + *info - '0'; + } else if(x != 0) { + c->mask = 1<<(x-1); + x = 0; + } + info++; + } + } else + c->mask = ~0; +} + /* Read a config file */ void read_file (FILE * ffile, char *errf) @@ -124,6 +145,7 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; c->type = li; if (skipsp (&li)) c->args = ""; else c->args = li; + do_subclass(c); chkone(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); @@ -150,6 +172,7 @@ read_file (FILE * ffile, char *errf) break; } } + do_subclass(c); chkone(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); @@ -170,6 +193,7 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; c->arg = li; if (skipsp (&li)) break; c->args = li; chkone(c); + do_subclass(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); @@ -190,6 +214,7 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; c->type = li; if (!skipsp (&li)) c->arg = li; chkone(c); + do_subclass(c); c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); @@ -205,6 +230,7 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; c->arg = li; if (skipsp (&li)) c->args = ""; else c->args = li; chkone(c); + do_subclass(c); c->cclass = str_enter(c->cclass); c->card = str_enter(c->card); c->arg = str_enter(c->arg); @@ -218,6 +244,7 @@ read_file (FILE * ffile, char *errf) if (!skipsp (&li)) c->args = li; else c->args = c->arg; if(c->args[0] == '\0') c->args = c->arg; chkone(c); + do_subclass(c); c->card = str_enter(c->card); c->arg = str_enter(c->arg); c->args = str_enter(c->args); @@ -240,6 +267,7 @@ read_file (FILE * ffile, char *errf) if ((pw = getpwnam (username)) == NULL) break; chkone(c); + do_subclass(c); c->num = pw->pw_uid; c->num2 = pw->pw_gid; c->protocol = str_enter(c->protocol); @@ -265,6 +293,7 @@ read_file (FILE * ffile, char *errf) if ((pw = getpwnam (username)) == NULL) break; chkone(c); + do_subclass(c); c->num = pw->pw_uid; c->num2 = pw->pw_gid; c->protocol = str_enter(c->protocol); @@ -283,6 +312,7 @@ read_file (FILE * ffile, char *errf) if (skipsp (&li)) break; c->arg = li; if(!skipsp (&li)) break; chkone(c); + do_subclass(c); c->card = str_enter(c->card); c->arg = str_enter(c->arg); c->num2 = ++seqnum; @@ -295,20 +325,26 @@ read_file (FILE * ffile, char *errf) break; if (skipsp (&li)) break; chkone(c); + do_subclass(c); c->arg = li; c->card = str_enter(c->card); app (&cf_CM, c); continue; case CHAR2 ('C', 'L'): - if (skipsp (&li)) break; c->card = li; + if (skipsp (&li)) break; c->protocol = li; + if (skipsp (&li)) break; c->site = li; if (skipsp (&li)) break; c->cclass = li; + if (skipsp (&li)) break; c->card = li; if (skipsp (&li)) break; if ((c->num = atoi (li)) == 0 && li[0] != '0') break;; if (!skipsp (&li)) c->args = li; chkone(c); + do_subclass(c); + c->protocol = str_enter(c->protocol); c->site = str_enter(c->site); c->cclass = str_enter(c->cclass); + c->card = str_enter(c->card); c->args = str_enter(c->args); app (&cf_CL, c); continue; @@ -344,7 +380,7 @@ read_args (void *nix) CFREE (cf_CL); seqnum = 0; - for(conn=theconn; conn != NULL; conn = conn->next) { + for(conn=isdn4_conn; conn != NULL; conn = conn->next) { if((cg = conn->cg) == NULL) continue; cg->dl = NULL; diff --git a/isdn_4/conn.c b/isdn_4/conn.c index 65f5273..4584fe1 100644 --- a/isdn_4/conn.c +++ b/isdn_4/conn.c @@ -21,6 +21,7 @@ conngrab Xnewgrab(conngrab master, int lin) if(master == NULL) { bzero(slave,sizeof(*slave)); slave->cclass = str_enter("*"); + slave->mask = ~0; } else { if(master->refs == 0 || master->protocol == (char *)0xdeadbeef) panic("FreeGrab"); @@ -63,7 +64,7 @@ void Xdropgrab(conngrab cg,int lin) /* Set the reference number. For debugging. */ void Xsetconnref(const char *deb_file, unsigned int deb_line, conninfo conn, int connref) { - if(0)printf("-%s:%d: SetConnRef.%p %d/%d/%ld -> %d\n",deb_file,deb_line,conn,conn->minor,conn->fminor,conn->connref,connref); + printf("-%s:%d: SetConnRef.%p %d/%d/%ld -> %d\n",deb_file,deb_line,conn,conn->minor,conn->fminor,conn->connref,connref); conn->connref = connref; } @@ -79,7 +80,7 @@ void connreport(char *foo) db.db_lim = ans + sizeof (ans); xx.b_datap = &db; - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { struct iovec io[2]; chkone(conn); @@ -111,9 +112,10 @@ void ReportConn(conninfo conn) spf += sprintf(spf,"%s%d:%d %s %s %s %d %s/%s %ld %ld %s", conn->ignore?"!":"", conn->minor, conn->seqnum, conn->cg ? conn->cg->site : "-", - conn->cg ? conn->cg->protocol : "-", conn->cg ? conn->cg->cclass : "-", conn->pid, - state2str(conn->state), conn->cg ? conn->cg->card : "-", conn->charge, - conn->ccharge, FlagInfo(conn->flags)); + conn->cg ? conn->cg->protocol : "-", conn->cg ? conn->cg->cclass : "-", + conn->pid, state2str(conn->state), + conn->cg ? conn->cg->card : (conn->cardname ? conn->cardname : "-"), + conn->charge, conn->ccharge, FlagInfo(conn->flags)); if(conn->cg != NULL && (conn->cg->flags ^ conn->flags) != 0) { int foo = strlen(FlagInfo(conn->cg->flags ^ conn->flags)); int bar = strlen(FlagInfo(conn->cg->flags)); @@ -159,8 +161,10 @@ void Xsetconnstate(const char *deb_file, unsigned int deb_line,conninfo conn, CS timeout(time_reconn,conn,5*HZ); } } +#if 0 if(conn->state <= c_down) setconnref(conn,0); +#endif if(state == c_up) conn->cause = 0; else if(state == c_going_up) @@ -209,8 +213,7 @@ void Xsetconnstate(const char *deb_file, unsigned int deb_line,conninfo conn, CS conn->cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ xconn->cg = conn->cg; - xconn->next = theconn; - theconn = xconn; + xconn->next = isdn4_conn; isdn4_conn = xconn; dropconn(xconn); } kill(conn->pid,SIGTERM); @@ -277,7 +280,7 @@ Xdropconn (struct conninfo *conn, const char *deb_file, unsigned int deb_line) { /* unchain the conn from the list */ /* Could use a doubly-linked list here, but what the ... */ - struct conninfo **pconn = &theconn; + struct conninfo **pconn = &isdn4_conn; while(*pconn != NULL) { if(*pconn == conn) { *pconn = conn->next; @@ -377,11 +380,15 @@ void try_reconn(struct conninfo *conn) chkone(cg); cg->refs++; - cg->nr = NULL; cg->nrsuf = NULL; + if(conn->want_reconn < MAX_RECONN) { /* if ==, we have a direct callback */ + cg->nr = NULL; cg->nrsuf = NULL; + } + else + cg->flags &=~F_NRCOMPLETE; cg->lnr = NULL; cg->lnrsuf = NULL; - cg->card = str_enter("*");; - cg->cclass = str_enter("*");; - cg->flags &=~(F_MOVEFLAGS|F_INCOMING|F_OUTCOMPLETE|F_NRCOMPLETE|F_LNRCOMPLETE); + cg->card = conn->cardname ? conn->cardname : "*"; + cg->cclass = conn->classname ? conn->classname : "*"; + cg->flags &=~(F_MOVEFLAGS|F_INCOMING|F_OUTCOMPLETE|F_LNRCOMPLETE); cg->flags |= F_OUTGOING; if((cg->flags & (F_PERMANENT|F_LEASED)) == F_PERMANENT) cg->flags |= F_DIALUP; @@ -406,7 +413,6 @@ void try_reconn(struct conninfo *conn) } dropgrab(cg); if(ret != NULL) { - setconnstate(conn,c_going_up); if(!strcmp(ret,"0BUSY")) { conn->cause = ID_priv_Busy; if ((conn->flags & F_PERMANENT) && (conn->minor != 0)) { diff --git a/isdn_4/info.c b/isdn_4/info.c index af91010..6dcf782 100644 --- a/isdn_4/info.c +++ b/isdn_4/info.c @@ -204,7 +204,7 @@ find_conn(void) struct conninfo *xconn = NULL; if(0)printf ("Check Conn %ld/%ld/%ld: ", minor, fminor, connref); if(fminor == 0) fminor = minor; - for (conn = theconn; conn != NULL; conn = conn->next) { + for (conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(0)printf ("%d/%d/%ld ", conn->minor, conn->fminor, conn->connref); @@ -319,17 +319,24 @@ int do_card(void) { cf dl; - long nbchan; + long nbchan, ndchan; long cardcap; int ret; struct isdncard *card; + struct loader *ld; if ((ret = m_getstr (&xx, crd, 4)) != 0) return ret; + if ((ret = m_geti (&xx, &ndchan)) != 0) + return ret; if ((ret = m_geti (&xx, &nbchan)) != 0) return ret; if ((ret = m_getx (&xx, &cardcap)) != 0) return ret; + for(ld = isdn4_loader; ld != NULL; ld = ld->next) { + if (!strcmp(ld->name, crd)) + return -EEXIST; + } for(card = isdn4_card; card != NULL; card = card->next) { if (!strcmp(card->name, crd)) return -EEXIST; @@ -340,12 +347,13 @@ do_card(void) bzero(card,sizeof(*card)); card->name = str_enter(crd); card->nrbchan = nbchan; + card->nrdchan = ndchan; + card->mask = (1<cap = cardcap; - card->next = isdn4_card; - isdn4_card = card; + card->next = isdn4_card; isdn4_card = card; if(cardcap & CHM_INTELLIGENT) { - struct loader *ld = malloc(sizeof(struct loader)); + ld = malloc(sizeof(struct loader)); if(ld == NULL) return -errno; bzero(ld,sizeof(*ld)); @@ -357,7 +365,6 @@ do_card(void) card->name = str_enter("NULL"); ld->card = card; - card_load(ld); } else { struct iovec io[3]; int len; @@ -394,6 +401,21 @@ do_card(void) } (void) strwritev (xs_mon, io,len, 1); } + + conn = malloc(sizeof(*conn)); + if(conn != NULL) { + bzero(conn,sizeof(*conn)); + conn->seqnum = ++connseq; + conn->causeInfo = ld ? "loading" : "passive interface"; + conn->cause = ID_priv_Print; + conn->cardname = ld ? ld->name : card->name; + conn->next = isdn4_conn; isdn4_conn = conn; + if(ld != NULL) + ld->connseq = conn->seqnum; + dropconn(conn); + } + if(ld != NULL) + card_load(ld); do_run_now++; timeout(run_now,NULL,3*HZ); @@ -411,10 +433,31 @@ do_nocard(void) return ret; for (pcard = &isdn4_card; *pcard != NULL; pcard = &(*pcard)->next) { if (!strcmp((*pcard)->name, crd)) { + struct loader *ld; struct isdncard *card = *pcard; *pcard = card->next; - free(card); - return 0; + + for(ld = isdn4_loader; ld != NULL; ld = ld->next) { + if (ld->card == card) { + card_load_fail(ld,-EIO); + break; + } + } + conn = malloc(sizeof(*conn)); + if(conn != NULL) { + bzero(conn,sizeof(*conn)); + conn->seqnum = ++connseq; + if(cause == 0) { + conn->causeInfo = "interface died"; + conn->cause = ID_priv_Print; + } else + conn->cause = cause; + conn->cardname = card->name; + conn->next = isdn4_conn; isdn4_conn = conn; + dropconn(conn); + } + resp = NULL; + break; } } return -ENOENT; @@ -440,7 +483,7 @@ do_cardproto(void) } cg->card = str_enter(crd); cg->protocol = str_enter(prot); - if ((resp = findsite (&cg)) != NULL) { + if ((resp = findsite (&cg,1)) != NULL) { dropgrab(cg); if(conn != NULL) { conn->want_reconn = 0; @@ -451,7 +494,7 @@ do_cardproto(void) } } - syslog (LOG_ERR, "ISDN NoProtocol1 %ld %s", minor, data); + syslog (LOG_ERR, "ISDN NoProtocol1 %s %ld %s", resp, minor, data); xx.b_rptr = xx.b_wptr = ans; db.db_base = ans; db.db_lim = ans + sizeof (ans); @@ -547,7 +590,7 @@ do_proto(void) if (crd[0] != '\0') cg->card = str_enter(crd); - if ((resp = findsite (&cg)) != NULL) { + if ((resp = findsite (&cg,1)) != NULL) { dropgrab(cg); syslog (LOG_ERR, "ISDN NoProtocol3 %ld %s", minor, data); @@ -619,7 +662,7 @@ do_incoming(void) cinf->b_wptr += len; cg->par_in = cinf; cg->card = str_enter(crd); - if ((resp = findit (&cg)) != NULL) + if ((resp = findit (&cg,0)) != NULL) goto inc_err; if (quitnow) { resp = "SHUTTING DOWN"; @@ -631,6 +674,7 @@ do_incoming(void) } { char *sit = NULL,*pro = NULL,*car = NULL,*cla = NULL; /* GCC */ + ulong_t sub = 0; if(0)printf("Hunt for %s/%s/%s/%s/%o\n",cg->site,cg->protocol,cg->card,cg->cclass,cg->flags); /* Figure out which program to run. */ for (cfr = cf_R; cfr != NULL; cfr = cfr->next) { @@ -639,6 +683,7 @@ do_incoming(void) if ((sit = wildmatch (cg->site, cfr->site)) == NULL) continue; if ((pro = wildmatch (cg->protocol, cfr->protocol)) == NULL) continue; if ((car = wildmatch (cg->card, cfr->card)) == NULL) continue; + if ((sub = maskmatch (cg->mask, cfr->mask)) == 0) continue; if ((cla =classmatch (cg->cclass, cfr->cclass)) == NULL) continue; break; } @@ -647,6 +692,7 @@ do_incoming(void) goto inc_err; } cg->site = sit; cg->protocol = pro; cg->cclass = cla; cg->card = car; + cg->mask = sub; } if((bchan < 0) && (cg->flags & F_CHANBUSY)) { resp = "0BUSY other"; @@ -711,8 +757,7 @@ do_incoming(void) cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ conn->cg = cg; - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; dropconn(conn); } resp = NULL; @@ -740,13 +785,14 @@ do_incoming(void) DUMPW (mz->b_rptr, xlen); (void) strwrite (xs_mon, mz->b_rptr, xlen, 1); freeb(mz); + resp = NULL; - dropgrab(conn->cg); cg->refs++; conn->cg = cg; + cg->refs++; dropgrab(conn->cg); conn->cg = cg; ReportConn(conn); #if 1 /* cg->flags &=~ F_INCOMING; */ /* cg->flags |= F_OUTGOING; */ - if((conn = startconn(cg,fminor,connref,NULL)) != conn) + if(startconn(cg,fminor,connref,NULL) != conn) resp = "ClashRestart Failed"; #endif conn = malloc(sizeof(*conn)); @@ -758,8 +804,7 @@ do_incoming(void) cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ conn->cg = cg; - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; dropconn(conn); } } @@ -786,8 +831,7 @@ do_incoming(void) conn->cause = 999999; setconnstate(conn, c_down); ReportConn(conn); - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; resp = runprog (cfr, &conn, &cg); if(resp != NULL) dropconn(conn); @@ -860,8 +904,7 @@ do_incoming(void) cg->refs++; /* dropgrab(conn->cg); ** is new anyway */ conn->cg = cg; - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; run_rp(conn,'r'); dropconn(conn); } @@ -880,7 +923,7 @@ do_conn(void) if(conn == NULL || (conn->flags & F_OUTGOING)) { syslog (LOG_INFO, "ISDN Out %ld %s", minor, data); - if(1 /* conn == NULL ** || !(conn->dialin & 2) */ ) { + if(minor > 0 || fminor > 0 /* conn == NULL ** || !(conn->dialin & 2) */ ) { resp = "CARRIER"; xx.b_rptr = xx.b_wptr = ans; @@ -888,7 +931,7 @@ do_conn(void) db.db_lim = ans + sizeof (ans); m_putid (&xx, CMD_PROT); m_putsx (&xx, ARG_FMINOR); - m_puti (&xx, minor); + m_puti (&xx, minor ? minor : fminor); m_putdelim (&xx); m_putid (&xx, PROTO_AT); m_putsz (&xx, (uchar_t *) resp); @@ -1155,7 +1198,7 @@ do_close(void) } } { - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->minor == minor && conn->ignore == 3) { dropconn(conn); continue; @@ -1458,7 +1501,7 @@ do_atcmd(void) } /* AT recognized */ /* If we're AT/Listening, stop it. */ - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->minor == minor && conn->ignore == 3) { dropconn(conn); break; @@ -1489,7 +1532,7 @@ do_atcmd(void) if(m_geti(&xx,&minor) != 0) { kill_progs(NULL); } else { - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(conn->minor == minor) @@ -1521,13 +1564,13 @@ do_atcmd(void) } do_quitnow(NULL); break; - case 'b': /* AT&B# */ + case 'b': /* AT/B# */ case 'B': /* Reenable a connection. */ { if(m_geti(&xx,&minor) != 0) { return 3; } - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(conn->minor == minor) @@ -1575,7 +1618,7 @@ do_atcmd(void) resp = "ERROR"; return 1; } - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(conn->minor == minor) @@ -1637,7 +1680,7 @@ do_atcmd(void) } sp = resp = msgbuf; sp += sprintf(sp,"#:ref id site protocol class pid state/card cost total flags,rem.nr;loc.nr cause\r\n"); - for(fconn = theconn; fconn != NULL; fconn = fconn->next) { + for(fconn = isdn4_conn; fconn != NULL; fconn = fconn->next) { if(fconn->ignore < 3) { sp += sprintf(sp,"%s%d:%d %s %s %s %d %s/%s %ld %ld %s %s\r\n", fconn->ignore?"!":"", fconn->minor, fconn->seqnum, @@ -1645,7 +1688,7 @@ do_atcmd(void) (fconn->cg && fconn->cg->protocol) ? fconn->cg->protocol : "-", (fconn->cg && fconn->cg->cclass) ? fconn->cg->cclass : "-", fconn->pid, state2str(fconn->state), - (fconn->cg && fconn->cg->card) ? fconn->cg->card : "-", + (fconn->cg && fconn->cg->card) ? fconn->cg->card : (fconn->cardname ? fconn->cardname : "-"), fconn->charge, fconn->ccharge, FlagInfo(fconn->flags), CauseInfo(fconn->cause, fconn->causeInfo)); } @@ -1656,8 +1699,7 @@ do_atcmd(void) conn->seqnum = ++connseq; conn->ignore = 3; conn->minor = minor; - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; } /* sprintf(sp,"OK"); */ *--sp = '\0'; *--sp = '\0'; /* Take off the CRLF at the end; the driver will put it back */ @@ -1894,7 +1936,7 @@ do_atcmd(void) conn->seqnum = ++connseq; conn->fminor = fminor; conn->minor = minor; - conn->next = theconn; theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; } } @@ -1917,7 +1959,7 @@ do_atcmd(void) cg->nr = str_enter(m1); cg->flags |= F_NRCOMPLETE; } - resp = findit (&cg); + resp = findit (&cg,0); if (resp != NULL) { freeb (md); dropgrab(cg); @@ -1996,7 +2038,7 @@ printf("GotAnError: Minor %ld, connref %ld, hdr %s\n",minor,connref,HdrName(hdrv return 0; } if(conn == NULL && connref != 0) { - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->connref == connref) break; } @@ -2010,6 +2052,7 @@ printf("GotAnError: Minor %ld, connref %ld, hdr %s\n",minor,connref,HdrName(hdrv if (wildmatch (conn->cg->site, cfr->site) == NULL) continue; if (wildmatch (conn->cg->protocol, cfr->protocol) == NULL) continue; if (wildmatch (conn->cg->card, cfr->card) == NULL) continue; + if (maskmatch (conn->cg->mask, cfr->mask) == 0) continue; if (classmatch (conn->cg->cclass, cfr->cclass) == NULL) continue; break; } @@ -2029,8 +2072,7 @@ printf("GotAnError: Minor %ld, connref %ld, hdr %s\n",minor,connref,HdrName(hdrv conn->cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ xconn->cg = conn->cg; - xconn->next = theconn; - theconn = xconn; + xconn->next = isdn4_conn; isdn4_conn = xconn; dropconn(xconn); } } diff --git a/isdn_4/loader.c b/isdn_4/loader.c index ff8d31d..65d2981 100644 --- a/isdn_4/loader.c +++ b/isdn_4/loader.c @@ -19,7 +19,7 @@ struct loader { #endif static void -card_load_close(struct loader *ld) +card_load_close(struct loader *ld, char success) { if(ld->name != NULL) ld->card->name = ld->name; @@ -37,6 +37,29 @@ card_load_close(struct loader *ld) ldp = &(*ldp)->next; } } + if(success) { + char newconn = 0; + struct conninfo *conn; + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { + if(conn->seqnum == ld->connseq) + break; + } + if(conn == NULL) { + conn = malloc(sizeof(*conn)); + newconn = 1; + } + if(conn != NULL) { + if(newconn) { + bzero(conn,sizeof(*conn)); + conn->cause = ID_priv_Print; + conn->cardname = ld->card->name; + conn->seqnum = ++connseq; + conn->next = isdn4_conn; isdn4_conn = conn; + } + conn->causeInfo = "active interface"; + dropconn(conn); + } + } free(ld); } @@ -45,6 +68,14 @@ card_load_fail(struct loader *ld, int err) { mblk_t *mj = allocb (32, BPRI_LO); int len; + struct isdncard **pcard, *card = ld->card; + + for (pcard = &isdn4_card; *pcard != NULL; pcard = &(*pcard)->next) { + if (card == *pcard) { + *pcard = card->next; + break; + } + } syslog(LOG_ERR,"Card %s was not loaded: Error at file %d, pos %d\n",ld->card,ld->nrfile,ld->foffset); @@ -60,7 +91,30 @@ card_load_fail(struct loader *ld, int err) freeb (mj); } - card_load_close(ld); + { + char newconn = 0; + struct conninfo *conn; + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { + if(conn->seqnum == ld->connseq) + break; + } + if(conn == NULL) { + conn = malloc(sizeof(*conn)); + newconn = 1; + } + if(conn != NULL) { + if(newconn) { + bzero(conn,sizeof(*conn)); + conn->cause = ID_priv_Print; + conn->seqnum = ++connseq; + conn->next = isdn4_conn; isdn4_conn = conn; + } + conn->causeInfo = "Load failed"; + dropconn(conn); + } + } + card_load_close(ld,0); + free(card); } void @@ -213,7 +267,7 @@ card_load(struct loader *ld) len++; } (void) strwritev (xs_mon, io,len, 1); - card_load_close(ld); + card_load_close(ld,1); do_run_now++; timeout(run_now,NULL,HZ/3); diff --git a/isdn_4/malldebug.c b/isdn_4/malldebug.c index 2311937..1c235fa 100644 --- a/isdn_4/malldebug.c +++ b/isdn_4/malldebug.c @@ -229,7 +229,7 @@ void chkone(void *foo) void chkall(void) { struct conninfo *conn; - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { chkone(conn); chkone(conn->cg); } #if 0 /* takes much too long */ diff --git a/isdn_4/master.h b/isdn_4/master.h index 193b55c..6ce0b2f 100644 --- a/isdn_4/master.h +++ b/isdn_4/master.h @@ -198,6 +198,7 @@ EXTERN struct string { char *str_enter(char *master); char *wildmatch(char *a, char *b); char *classmatch(char *a, char *b); +ulong_t maskmatch(ulong_t a, ulong_t b); char *strippat(char *a); @@ -221,6 +222,7 @@ typedef struct proginfo { char *protocol; char *cclass; char *card; + ulong_t mask; char *type; pid_t pid; } *_proginfo; @@ -250,6 +252,7 @@ typedef struct conngrab { char *protocol; char *cclass; char *card; + ulong_t mask; char *oldnr; char *oldlnr; char *nr; @@ -283,7 +286,7 @@ typedef struct conninfo { int retiming; int ctimer; int cause; - char *causeInfo; + char *causeInfo, *cardname, *classname; int seqnum; short retries; unsigned timer_reconn:1; @@ -334,7 +337,7 @@ char *FlagInfo(int flag); /* The List */ -EXTERN struct conninfo *theconn INIT(NULL); +EXTERN struct conninfo *isdn4_conn INIT(NULL); #define newgrab(x) Xnewgrab((x),__LINE__) @@ -417,6 +420,7 @@ typedef struct _cf { char *arg; char *args; int num, num2; + ulong_t mask; char got_err; } *cf; @@ -460,8 +464,8 @@ void Xbreak(void); char * pmatch1 (cf prot, conngrab *cgm); char * pmatch (conngrab *cgm); -char * findsite (conngrab *foo); -char * findit (conngrab *foo); +char * findsite (conngrab *foo, int nobusy); +char * findit (conngrab *foo, int nobusy); #if 0 mblk_t * getprot (char *protocol, char *site, char *cclass, char *suffix); @@ -512,6 +516,7 @@ struct loader { long foffset; /* position in load file */ struct loader *next; int cardnum; + int connseq; unsigned timer:1; }; void card_load(struct loader *ld); @@ -522,7 +527,9 @@ struct isdncard { struct isdncard *next; char *name; long cap; + ushort_t nrdchan; /* seqnum... */ ushort_t nrbchan; + ulong_t mask; }; EXTERN struct isdncard *isdn4_card INIT(NULL); diff --git a/isdn_4/match.c b/isdn_4/match.c index 10b9726..b22165e 100644 --- a/isdn_4/match.c +++ b/isdn_4/match.c @@ -42,6 +42,7 @@ char * pmatch1 (cf prot, conngrab *cgm) { char *sit, *pro, *cla, *car; + ulong_t sub; char first = 1; conngrab cg = *cgm; @@ -51,12 +52,14 @@ pmatch1 (cf prot, conngrab *cgm) pro = wildmatch(cg->protocol,prot->protocol);if(pro == NULL) return "6ERR Match PROTOCOL"; car = wildmatch(cg->card, prot->card); if(car == NULL) return "6ERR Match CARD"; cla =classmatch(cg->cclass, prot->cclass); if(cla == NULL) return "6ERR Match CLASS"; + sub = maskmatch(cg->mask, prot->mask); if(sub == 0) return "6ERR Match SUBCARD"; /* OK, that fits. Make a copy to assign the values to. */ cg = newgrab(cg); if(cg == NULL) return "0OUT OF MEMORY"; cg->site = sit; cg->protocol = pro; cg->card = car; cg->cclass = cla; + cg->mask = sub; /* Now scan this line's, and all matching followup lines', flags. */ for (first = 1; prot != NULL; prot = prot->next, first = 0) { @@ -82,6 +85,7 @@ pmatch1 (cf prot, conngrab *cgm) pro = wildmatch(cg->protocol,prot->protocol);if(pro==NULL) continue; car = wildmatch(cg->card, prot->card); if(car==NULL) continue; cla =classmatch(cg->cclass, prot->cclass); if(cla==NULL) continue; + sub = maskmatch(cg->mask, prot->mask); if(sub==0) continue; } /* Now make another copy for the parameters. If they don't fit we'll have to undo everything. */ @@ -92,6 +96,7 @@ pmatch1 (cf prot, conngrab *cgm) } if(!first) { cgc->site = sit; cgc->protocol = pro; cgc->card = car; cgc->cclass = cla; + cgc->mask = sub; } if(cgc->par_out == NULL) { /* No outgoing parameter list? Yet! */ if ((cgc->par_out = allocb(256,BPRI_LO)) == NULL) { @@ -401,7 +406,7 @@ pmatch (conngrab *cgm) /* Scan the configuration, incorporate matching entries into *foo. */ char * -findsite (conngrab *foo) +findsite (conngrab *foo, int ignbusy) { cf dp = NULL; cf dl = NULL; @@ -417,6 +422,7 @@ findsite (conngrab *foo) for (dl = cf_DL; dl != NULL; dl = dl->next) { /* find a matching local number. */ char *matcrd; char *matclass; + ulong_t matsub; if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ @@ -424,17 +430,24 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ continue; if ((matcrd = wildmatch (cg->card, dl->card)) == NULL) continue; + if ((matsub = maskmatch (cg->mask, dl->mask)) == 0) + continue; if(!(cg->flags & F_LEASED)) { /* ... and a working dial prefix. */ char *crd; + ulong_t sub; for (dp = cf_DP; dp != NULL; dp = dp->next) { - if ((crd = wildmatch (cg->card, dp->card)) != NULL) - break; + if ((crd = wildmatch (cg->card, dp->card)) == NULL) + continue; + if ((sub = maskmatch (cg->mask, dp->mask)) == 0) + continue; + break; } if (dp == NULL) { errstr = "9CARD UNKNOWN"; continue; } matcrd = crd; + matsub = sub; } /* if everybody had DSS1, we could skip the prefix nonsense... */ /* Now find a site to call out to. */ @@ -450,6 +463,7 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ char *matsit; char *matcar; char *matpro; + ulong_t matsub; if(d == NULL) { numwrap = 0; @@ -473,6 +487,8 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ if((matcar = wildmatch(matcrd,d->card)) == NULL) continue; if((matcla = classmatch(cg->cclass,d->cclass)) == NULL) continue; if((matcla = classmatch(matcla,matclass)) == NULL) continue; + if((matsub = maskmatch(cg->mask,d->mask)) == 0) continue; + if((matsub = maskmatch(matsub,matsub)) == 0) continue; if(!matchflag(cg->flags,d->type)) continue; /* Preliminary match OK, remember the data so far. */ @@ -482,6 +498,7 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ cg->site = matsit; cg->cclass = matcla; cg->card = matcar; cg->protocol = matpro; + cg->mask = matsub; if(0)printf("%s...",matsit); if(!(cg->flags & F_LEASED)) { @@ -530,19 +547,11 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ } /* Do we have a matching P line? */ - if ((errstrx = pmatch (&cg)) == NULL) { /* We have what we need. Now figure out if we can use it. */ - struct conninfo *conn; + if ((errstrx = pmatch (&cg)) == NULL) { + /* We have what we need. Now figure out if we can use it. */ cf cl = NULL; - int nrconn = 0, naconn = 0; int nrbchan = 0; - /* Check if there's a limiter. */ - for(cl = cf_CL; cl != NULL; cl = cl->next) { - if(classmatch(cg->cclass,cl->cclass) == NULL) - continue; - if(wildmatch(cg->card, cl->card)) - break; - } /* Check if we know how many B channels the card has */ { struct isdncard *ca; @@ -554,28 +563,73 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ } } } - for(conn = theconn; conn != NULL; conn = conn->next) { - if(conn->ignore || !conn->cg) - continue; - if(wildmatch(conn->cg->site,cg->site) && - wildmatch(conn->cg->protocol,cg->protocol)) - continue; - if((conn->state >= c_going_up) && wildmatch(conn->cg->card, cg->card)) { - nrconn ++; - if(!(conn->flags & F_IGNORELIMIT)) - naconn++; + + if((nrbchan > 0) && !ignbusy) { + int nrconn = 0; + struct conninfo *conn; + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { + if(conn->ignore || !conn->cg) + continue; + if(conn->state >= c_going_up) { + if(wildmatch(conn->cg->card, cg->card) == NULL) + continue; + nrconn ++; + } + } + if(nrconn >= nrbchan) { + errstr = "0BUSY"; + dropgrab(errcg); errcg = cg; cg->refs++; + continue; /* try the next D line */ } } - if(((nrbchan > 0) && (nrconn >= nrbchan)) || ((cl != NULL) && (naconn >= cl->num) && !(cg->flags & F_IGNORELIMIT))) { - errstr = "0BUSY"; - dropgrab(errcg); errcg = cg; cg->refs++; - continue; + /* Check if there's a limiter. Actually, there may be more + than one. */ + for(cl = ignbusy ? NULL : cf_CL; cl != NULL; cl = cl->next) { + struct conninfo *conn; + int naconn = 0; + + if(classmatch(cg->cclass,cl->cclass) == NULL) + continue; + if(wildmatch(cg->card, cl->card) == NULL) + continue; + if(wildmatch(cg->site, cl->site) == NULL) + continue; + if(wildmatch(cg->protocol, cl->protocol) == NULL) + continue; + if(maskmatch(cg->mask, cl->mask) == 0) + continue; + + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { + if(conn->ignore || !conn->cg) + continue; + if(conn->state >= c_going_up) { + if(wildmatch(conn->cg->card, cl->card) == NULL) + continue; + if(wildmatch(conn->cg->protocol, cl->protocol) == NULL) + continue; + if(wildmatch(conn->cg->site, cl->site) == NULL) + continue; + if(classmatch(conn->cg->cclass, cl->cclass) == NULL) + continue; + if(maskmatch(conn->cg->mask,cl->mask) == 0) + continue; + if(!(conn->flags & F_IGNORELIMIT)) + naconn++; + } + } + if((cl != NULL) && (naconn >= cl->num) && !(cg->flags & F_IGNORELIMIT)) { + errstr = "0BUSY"; + dropgrab(errcg); errcg = cg; cg->refs++; + break; + } + } + if(cl == NULL) { /* checked all of them */ + if (cg->par_out != NULL && strchr(d->type, 'H') != NULL && !(cg->flags & F_OUTCOMPLETE)) + m_putsx (cg->par_out, ARG_SUPPRESS); + dropgrab(errcg); + dropgrab(*foo); *foo = cg; + return NULL; } - if (cg->par_out != NULL && strchr(d->type, 'H') != NULL && !(cg->flags & F_OUTCOMPLETE)) - m_putsx (cg->par_out, ARG_SUPPRESS); - dropgrab(errcg); - dropgrab(*foo); *foo = cg; - return NULL; } /* No go. Remember the error, if appropriate. */ if(*errstr > *errstrx) { @@ -597,7 +651,7 @@ if(0)printf("%s.%s.!.",cg->site,cg->card); /* I hate debugging. */ /* Wrapper stuff. Take numbers out of the incoming argument vector, find the card, et al. */ char * -findit (conngrab *foo) +findit (conngrab *foo, int ignbusy) { ushort_t id; mblk_t *p; @@ -618,6 +672,7 @@ findit (conngrab *foo) streamchar *olds = p->b_rptr; char st[MAXNR + 2]; char *card; + long x; while (m_getsx (p, &id) == 0) { switch (id) { @@ -640,6 +695,10 @@ findit (conngrab *foo) return "CARD MISMATCH"; } break; + case ARG_SUBCARD: + if((m_geti(p,&x) == 0) && (x > 0)) + cg->mask = 1<<(x-1); + break; } } p->b_rptr = olds; @@ -651,41 +710,53 @@ findit (conngrab *foo) if(isdn4_card != NULL) { for(c = isdn4_card; (c != NULL) || (cardlim < cardidx); c = c->next) { - cf crd; - - cardlim++; - if(c == NULL) { /* Wraparound */ c = isdn4_card; if(cardlim < cardidx) - cardidx %= cardlim; + cardidx %= (cardlim+1); } - if(!wildmatch(card,c->name)) + if(!wildmatch(card,c->name)) { + cardlim += c->nrdchan; continue; + } + + cg->card = c->name; + cg->mask = 1; + redo: + cardlim++; if(cg->flags & F_INCOMING) /* never skip */ cardidx = 1; - if(cardlim < cardidx) - continue; - cg->card = c->name; - if ((errstrx = findsite (&cg)) == NULL) { /* Found it */ - cardidx++; - dropgrab(*foo); - *foo = cg; - cg->flags |= F_OUTCOMPLETE; - if(c->cap & CHM_INTELLIGENT) - return NULL; - for (crd = cf_CM; crd != NULL; crd = crd->next) { - if (!wildmatch (c->name, crd->card)) - continue; - return NULL; + if(cardlim >= cardidx) { + if ((errstrx = findsite (&cg,ignbusy)) == NULL) { /* Found it */ + cf crd; + cardidx++; + cg->flags |= F_OUTCOMPLETE; + if(c->cap & CHM_INTELLIGENT) { + dropgrab(*foo); + *foo = cg; + return NULL; + } + for (crd = cf_CM; crd != NULL; crd = crd->next) { + if (!wildmatch (c->name, crd->card)) + continue; + dropgrab(*foo); + *foo = cg; + return NULL; + } + errstrx = "0CM line missing"; + } + if(*errstrx < *errstr) { + errstr = errstrx; + dropgrab(errcg); errcg = cg; + errcg->refs++; } - errstrx = "0CM line missing"; - } - if(*errstrx < *errstr) { - errstr = errstrx; - dropgrab(errcg); errcg = cg; - errcg->refs++; } + cg->mask <<= 1; + if(cg->mask == 0) + continue; + if(!(c->mask & cg->mask)) + continue; + goto redo; } } else errstr = "0No card in the system"; diff --git a/isdn_4/stream.c b/isdn_4/stream.c index 3786c95..98adf0c 100644 --- a/isdn_4/stream.c +++ b/isdn_4/stream.c @@ -6,7 +6,7 @@ */ #include "master.h" - +#include void diff --git a/isdn_4/texts.c b/isdn_4/texts.c index f9524cc..331583f 100644 --- a/isdn_4/texts.c +++ b/isdn_4/texts.c @@ -6,6 +6,9 @@ */ #include "master.h" +#ifdef _capi_ +#include "../cards/capi/capi.h" +#endif /* Textual representation of a connection state */ char *state2str(CState state) { @@ -88,6 +91,65 @@ const char *CauseInfo(int cause, char *pri) case 0: return "OK"; case ID_priv_Busy: return "Local Busy"; case ID_priv_Print: if(isdigit(*pri)) return pri+1; else return pri; + +#ifdef _capi_ + case ID_E_REGISTER: return "application registration"; + case ID_E_APPLICATION: return "wrong application ID"; + case ID_E_MSGLENGTH: return "message error"; + case ID_E_COMMAND: return "wrong API command"; + case ID_E_QUEUEFULL: return "message queue full"; + case ID_E_NOMSG: return "message queue empty"; + case ID_E_MSGOVERFLOW: return "messages lost"; + case ID_E_DEINSTALL: return "error during deinstallation"; + case ID_E_CONTROLLER: return "wrong controller"; + case ID_E_PLCI: return "wrong PLCI"; + case ID_E_NCCI: return "wrong NCCI"; + case ID_E_TYPE: return "wrong type"; + case ID_E_BCHANNEL: return "wrong B channel"; + case ID_E_INFOMASK: return "wrong info mask"; + case ID_E_EAZMASK: return "wrong EAZ mask"; + case ID_E_SIMASK: return "wrong Service ID mask"; + case ID_E_B2PROTO: return "B2 protocol incorrect"; + case ID_E_DLPD: return "DLPD incorrect"; + case ID_E_B3PROTO: return "B3 protocol incorrect"; + case ID_E_NCPD: return "NCPD incorrect"; + case ID_E_NCPI: return "NCPI incorrect"; + case ID_E_DATAB3FLAGS: return "B3 flags incorrect"; + case ID_E_CONTROLLERFAILED: return "controller error"; + case ID_E_REGCONFLICT: return "registration conflict"; + case ID_E_CMDNOTSUPPORTED: return "command not supported"; + case ID_E_PLCIACT: return "PLCI not active"; + case ID_E_NCCIACT: return "NCCI not active"; + case ID_E_B2NOTSUPPORT: return "B2 protocol not supported"; + case ID_E_B2STATE: return "change of B2 protocol not possible"; + case ID_E_B3NOTSUPPORT: return "B3 protocol not supported"; + case ID_E_B3STATE: return "change of B3 protocol not possible"; + case ID_E_B2DLPDPARA: return "parameters not supported in DLPD"; + case ID_E_B3NCPDPARA: return "parameters not supported in NCPD"; + case ID_E_B3NCPIPARA: return "parameters not supported in NCPI"; + case ID_E_DATALEN: return "data length not supported"; + case ID_E_DTMF: return "DTMF problem"; + case ID_E_NOL1: return "L1 setup failed"; + case ID_E_NOL2: return "L2 setup failed"; + case ID_E_SETUPBCHANLAYER1: return "B1 setup failed"; + case ID_E_SETUPBCHANLAYER2: return "B2 setup failed"; + case ID_E_ABORTDCHANLAYER1: return "L1 D channel aborted"; + case ID_E_ABORTDCHANLAYER2: return "L2 D channel aborted"; + case ID_E_ABORTDCHANLAYER3: return "L3 D channel aborted"; + case ID_E_ABORTBCHANLAYER1: return "L1 B channel aborted"; + case ID_E_ABORTBCHANLAYER2: return "L2 B channel aborted"; + case ID_E_ABORTBCHANLAYER3: return "L3 B channel aborted"; + case ID_E_REBCHANLAYER2: return "L2 B channel reestablished"; + case ID_E_REBCHANLAYER3: return "L3 B channel reestablished"; + case ID_E_NOFAX: return "?Fax not supported"; + case ID_E_BADLINE: return "?Bad Line"; + case ID_E_NOANSWER: return "?Nobody answers"; + case ID_E_REMDISC: return "?Remote Disconnect"; + case ID_E_NOCMD: return "?No Command"; + case ID_E_INCOMPAT: return "?Incompatible"; + case ID_E_BADDATA: return "?Bad Data"; + case ID_E_PROTO: return "?Protocol"; +#endif case ID_ET_AccessInfoDiscard: return "Access info discarded"; case ID_N1_BearerNotImpl: return "Bearer Service not implemented"; case ID_N1_CIDinUse: return "CID in use"; diff --git a/isdn_4/unused.c b/isdn_4/unused.c index 8894c02..7018267 100644 --- a/isdn_4/unused.c +++ b/isdn_4/unused.c @@ -1,3 +1,4 @@ +#if 0 /* * This file is part of the ISDN master program. * @@ -26,6 +27,8 @@ getcards(conngrab cg, cf list) continue; if(!wildmatch(list->card,cg->card)) continue; + if(!maskmatch(list->mask,cg->mask)) + continue; if(!classmatch(list->cclass,cg->cclass)) continue; if(!matchflag(cg->flags,list->type)) @@ -114,3 +117,4 @@ getprot (char *protocol, char *site, char *cclass, char *suffix) } return mi; } +#endif diff --git a/isdn_4/util.c b/isdn_4/util.c index 37710c1..c70735b 100644 --- a/isdn_4/util.c +++ b/isdn_4/util.c @@ -119,6 +119,13 @@ pluscat(char *a, char *b) } } + +ulong_t +maskmatch(ulong_t a, ulong_t b) +{ + return a & b; +} + /* "abc" "bcd" -> "bc" */ /* "abc+bc" "bcd+b" -> "bc+bc+b" */ /* "abc+bc" "bcd+d" -> NULL */ diff --git a/isdn_4/work.c b/isdn_4/work.c index d4662d6..46f3ac4 100644 --- a/isdn_4/work.c +++ b/isdn_4/work.c @@ -19,7 +19,7 @@ deadkid (void) printf ("\n* PID %d died, %x\n", pid, val); chkall(); - for (conn = theconn; conn != NULL; conn = conn ? conn->next : NULL) { + for (conn = isdn4_conn; conn != NULL; conn = conn ? conn->next : NULL) { if(conn->ignore) continue; if (conn->pid == pid) { @@ -82,6 +82,7 @@ pushprot (conngrab cg, int minor, char update) if (!wildmatch (cg->site, prot->site)) continue; if (!wildmatch (cg->protocol, prot->protocol)) continue; if (!wildmatch (cg->card, prot->card)) continue; + if (!maskmatch (cg->mask, prot->mask)) continue; if (!classmatch (cg->cclass, prot->cclass)) continue; break; } @@ -146,6 +147,7 @@ pushprot (conngrab cg, int minor, char update) if (!wildmatch (cg->site, cm->site)) continue; if (!wildmatch (cg->protocol, cm->protocol)) continue; if (!wildmatch (cg->card, cm->card)) continue; + if (!maskmatch (cg->mask, cm->mask)) continue; if (!classmatch (cg->cclass, cm->cclass)) continue; if (!wildmatch (sp1, cm->arg)) continue; @@ -252,6 +254,7 @@ pushcardprot (conngrab cg, int minor) if (!wildmatch (cg->site, prot->site)) continue; if (!wildmatch (cg->protocol, prot->protocol)) continue; if (!wildmatch (cg->card, prot->card)) continue; + if (!maskmatch (cg->mask, prot->mask)) continue; if (!classmatch (cg->cclass, prot->cclass)) continue; if(card->cap & CHM_INTELLIGENT) { @@ -259,6 +262,7 @@ pushcardprot (conngrab cg, int minor) } else { for (cmod = cf_CM; cmod != NULL; cmod = cmod->next) { if (!wildmatch (cg->card, cmod->card)) continue; + if (!maskmatch (cg->mask, cmod->mask)) continue; if (!wildmatch(prot->arg,cmod->arg)) continue; break; } @@ -313,10 +317,14 @@ startconn(conngrab cg, int fminor, int connref, char **ret) if(ret == NULL) ret = &str; + if(cg->mask == 0) { + *ret = "Internal error: bad mask"; + return NULL; + } *ret = NULL; chkall(); cg->refs++; - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(conn->minor == 0) @@ -325,8 +333,9 @@ startconn(conngrab cg, int fminor, int connref, char **ret) break; } if(conn == NULL) { - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { char *sit,*pro,*car,*cla; + ulong_t sub; if(conn->ignore) continue; @@ -339,13 +348,15 @@ startconn(conngrab cg, int fminor, int connref, char **ret) if((sit = wildmatch(conn->cg->site,cg->site)) == NULL) continue; if((pro = wildmatch(conn->cg->protocol,cg->protocol)) == NULL) continue; if((car = wildmatch(conn->cg->card,cg->card)) == NULL) continue; + if((sub = maskmatch(conn->cg->mask,cg->mask)) == 0) continue; if((cla = classmatch(conn->cg->cclass,cg->cclass)) == NULL) continue; cg->site = sit; cg->protocol = pro; cg->card = car; cg->cclass = cla; + cg->mask = sub; break; } } if(conn == NULL) { - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { char *sit,*pro; if(conn->ignore) @@ -396,7 +407,7 @@ startconn(conngrab cg, int fminor, int connref, char **ret) } printf("Start: %s:%s #%s...",cg->site,cg->protocol,cg->nr); - if(((*ret) = findit (&cg)) != NULL) { + if(((*ret) = findit (&cg,0)) != NULL) { dropgrab(cg); chkall(); return NULL; @@ -428,7 +439,7 @@ printf("Start: %s:%s #%s...",cg->site,cg->protocol,cg->nr); *ret = "COLLISION 2"; return conn; } - /* setconnref(conn,connref); */ + setconnref(conn,connref); } m_putsx (&yy, ARG_MINOR); @@ -474,6 +485,13 @@ printf("Start: %s:%s #%s...",cg->site,cg->protocol,cg->nr); } m_putsx (&yy, ARG_CARD); m_putsz (&yy, cg->card); + { + ulong_t m; + int i; + for(i=1,m=1;(i < 33) && !(cg->mask & m);m<<=1,i++) ; + m_putsx (&yy, ARG_SUBCARD); + m_puti (&yy, i); + } #if 0 if (strchr (type, 'H') != NULL) m_putsx (&yy, ARG_SUPPRESS); @@ -574,7 +592,7 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) { char *err; - if((err = findit (foo)) != NULL) { + if((err = findit (foo,0)) != NULL) { if(conn != NULL) free(conn); return err; @@ -591,8 +609,7 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) conn->seqnum = ++connseq; conn->state = c_down; conn->cause = 999999; - conn->next = theconn; - theconn = conn; + conn->next = isdn4_conn; isdn4_conn = conn; } cg->refs++; dropgrab(conn->cg); @@ -995,9 +1012,7 @@ runprog (cf cfr, struct conninfo **rconn, conngrab *foo) else cg->delay = 0; } - if(startconn(conn->cg,0,0, &msg) == conn) - setconnstate(conn,c_going_up); - else { + if(startconn(conn->cg,0,0, &msg) != conn) { syslog(LOG_CRIT,"Bug in runprog->startconn (%s) for %s:%s",msg ? msg : "(unknown reason)", cg->site,cg->protocol); dropgrab(conn->cg); conn->cg = NULL; @@ -1055,6 +1070,7 @@ kill_rp(struct conninfo *conn, char whatnot) if(wildmatch(pro->site,conn->cg->site) == NULL) continue; if(wildmatch(pro->protocol,conn->cg->protocol) == NULL) continue; if(wildmatch(pro->card,conn->cg->card) == NULL) continue; + if(maskmatch(pro->mask,conn->cg->mask) == 0) continue; if(classmatch(pro->cclass,conn->cg->cclass) == NULL) continue; xconn = malloc(sizeof(*xconn)); @@ -1067,8 +1083,7 @@ kill_rp(struct conninfo *conn, char whatnot) conn->cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ xconn->cg = conn->cg; - xconn->next = theconn; - theconn = xconn; + xconn->next = isdn4_conn; isdn4_conn = xconn; dropconn(xconn); } if(strchr(pro->type,'s') == NULL) @@ -1085,20 +1100,23 @@ run_rp(struct conninfo *conn, char what) struct proginfo *pr; for(cfr = cf_RP; cfr != NULL; cfr = cfr->next) { char *sit,*pro,*car,*cla; + ulong_t sub; if(strchr(cfr->type,what) == NULL) continue; if((sit = wildmatch(conn->cg->site,cfr->site)) == NULL) continue; if((pro = wildmatch(conn->cg->protocol,cfr->protocol)) == NULL) continue; if((car = wildmatch(conn->cg->card,cfr->card)) == NULL) continue; + if((sub = maskmatch(conn->cg->mask,cfr->mask)) == 0) continue; if((cla = classmatch(conn->cg->cclass,cfr->cclass)) == NULL) continue; for(pr = conn->run; pr != NULL; pr = pr->next) { struct conninfo *xconn; if(strchr(pr->type,what) == NULL) continue; - if(wildmatch(pr->site,cfr->site) == NULL) continue; - if(wildmatch(pr->protocol,cfr->protocol) == NULL) continue; - if(wildmatch(pr->card,cfr->card) == NULL) continue; - if(classmatch(pr->cclass,cfr->cclass) == NULL) continue; + if(wildmatch(pr->site,sit) == NULL) continue; + if(wildmatch(pr->protocol,pro) == NULL) continue; + if(wildmatch(pr->card,car) == NULL) continue; + if(maskmatch(pr->mask,sub) == 0) continue; + if(classmatch(pr->cclass,cla) == NULL) continue; xconn = malloc(sizeof(*xconn)); if(xconn != NULL) { @@ -1110,8 +1128,7 @@ run_rp(struct conninfo *conn, char what) conn->cg->refs++; /* dropgrab(conn->cg; ** is new anyway */ xconn->cg = conn->cg; - xconn->next = theconn; - theconn = xconn; + xconn->next = isdn4_conn; isdn4_conn = xconn; dropconn(xconn); } if(strchr(pr->type,'s') == NULL) @@ -1156,7 +1173,7 @@ printf("StoredErr; "); if(strchr(what->type,'B') != NULL || strchr(what->type,'p') != NULL) { struct conninfo *conn; - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore || (conn->cg == NULL)) continue; if(strcmp(conn->cg->site,what->site)) @@ -1181,6 +1198,8 @@ printf("run %s:%s; ",what->site,what->protocol); cg->flags |= F_OUTGOING; err = runprog(what,&conn,&cg); if(conn != NULL) { + conn->cardname = what->card; + conn->classname = what->cclass; kill_rp(conn,'t'); run_rp(conn,'i'); } @@ -1219,7 +1238,7 @@ has_progs(void) struct conninfo *conn; if(!quitnow) return 1; - for(conn = theconn; conn != NULL; conn = conn->next) { + for(conn = isdn4_conn; conn != NULL; conn = conn->next) { if(conn->ignore) continue; if(conn->pid != 0) @@ -1237,7 +1256,7 @@ kill_progs(struct conninfo *xconn) struct conninfo *conn, *nconn; if(!quitnow) in_boot = 1; - for(conn = theconn; conn != NULL; conn = nconn) { + for(conn = isdn4_conn; conn != NULL; conn = nconn) { nconn = conn->next; if(conn->ignore) continue; diff --git a/ksupport/dump.c b/ksupport/dump.c index 732f419..9b2d229 100644 --- a/ksupport/dump.c +++ b/ksupport/dump.c @@ -231,7 +231,10 @@ dump_one_hdr (isdn23_hdr hdr) hdr->hdr_detach.error,hdr->hdr_detach.perm); break; case HDR_CARD: - printf ("Card %d online (%d B channels, flag 0%o)", hdr->hdr_card.card, hdr->hdr_card.bchans,hdr->hdr_card.flags); + printf ("Card %d online (%d D channels, %d B channels, flag 0%o)", + hdr->hdr_card.card, + hdr->hdr_card.dchans,hdr->hdr_card.bchans, + hdr->hdr_card.flags); break; case HDR_NOCARD: printf ("Card %d offline.", hdr->hdr_nocard.card); diff --git a/ksupport/log.c b/ksupport/log.c index 2e4dbd7..8dc6aff 100644 --- a/ksupport/log.c +++ b/ksupport/log.c @@ -274,7 +274,7 @@ log_printmsg (void *xlog, const char *text, mblk_t * mp, const char *prefix) printf ("%s%03x ",pprefix,i); #ifdef KERNEL - if(i >= 3*BLOCKSIZE && l > 4*BLOCKSIZE) { /* Skip the stuff in the middle */ + if(i >= 4*BLOCKSIZE && l > 4*BLOCKSIZE) { /* Skip the stuff in the middle */ l -= 3*BLOCKSIZE + (l % BLOCKSIZE); printf("[... %d bytes (0x%x) skipped ...]\n",l,l); dp += l; diff --git a/patches/biglog b/patches/biglog new file mode 100644 index 0000000..a300367 --- /dev/null +++ b/patches/biglog @@ -0,0 +1,20 @@ +Dieser Patch vergroessert den fuer printk verwendeten Puffer. + +Es empfiehlt sich ausserdem, in syslogd.c die ewigen sync-Aufrufe zu +entfernen oder zumindest intelligenter zu gestalten, zB via Timeout. + +Optional, zum ISDN-Debuggen aber notwendig. + +Only in ./kernel: panic.o +diff -rub /pub/src/linux/kernel/linux-1.1/kernel/printk.c ./kernel/printk.c +--- /pub/src/linux/kernel/linux-1.1/kernel/printk.c Fri Jan 6 07:29:39 1995 ++++ ./kernel/printk.c Thu Jan 12 15:48:46 1995 +@@ -20,7 +20,7 @@ + #include + #include + +-#define LOG_BUF_LEN 4096 ++#define LOG_BUF_LEN 40960 + + static char buf[1024]; + diff --git a/patches/debugmsg b/patches/debugmsg new file mode 100644 index 0000000..0edc0ce --- /dev/null +++ b/patches/debugmsg @@ -0,0 +1,158 @@ +Dieser Patch markiert die Debuggingmeldungen, die beim Drücken der mit +show_* belegten Tasten ausgespuckt werden, als EMERGency-Meldungen. Sie +werden dann auch ausgegeben, wenn der Kernel normale Ausgaben unterdrückt +(klogd -c N, 1<=N<=7). + +Optional aber sehr sinnvoll. + +diff -rub --unidir /pub/src/linux/kernel/linux/arch/i386/kernel/process.c ./arch/i386/kernel/process.c +--- /pub/src/linux/kernel/linux/arch/i386/kernel/process.c Wed Mar 1 07:43:07 1995 ++++ ./arch/i386/kernel/process.c Wed Mar 22 15:42:43 1995 +@@ -100,13 +100,13 @@ + void show_regs(struct pt_regs * regs) + { + printk("\n"); +- printk("EIP: %04x:%08lx",0xffff & regs->cs,regs->eip); ++ printk(KERN_EMERG "EIP: %04x:%08lx",0xffff & regs->cs,regs->eip); + if (regs->cs & 3) + printk(" ESP: %04x:%08lx",0xffff & regs->ss,regs->esp); + printk(" EFLAGS: %08lx\n",regs->eflags); +- printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", ++ printk(KERN_EMERG "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", + regs->eax,regs->ebx,regs->ecx,regs->edx); +- printk("ESI: %08lx EDI: %08lx EBP: %08lx", ++ printk(KERN_EMERG "ESI: %08lx EDI: %08lx EBP: %08lx", + regs->esi, regs->edi, regs->ebp); + printk(" DS: %04x ES: %04x FS: %04x GS: %04x\n", + 0xffff & regs->ds,0xffff & regs->es, +diff -rub --unidir /pub/src/linux/kernel/linux/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c +--- /pub/src/linux/kernel/linux/arch/i386/kernel/traps.c Wed Feb 8 12:54:00 1995 ++++ ./arch/i386/kernel/traps.c Wed Mar 22 15:33:47 1995 +@@ -191,9 +186,9 @@ + asmlinkage void do_nmi(struct pt_regs * regs, long error_code) + { + #ifndef CONFIG_IGNORE_NMI +- printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); +- printk("You probably have a hardware problem with your RAM chips or a\n"); +- printk("power saving mode enabled.\n"); ++ printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); ++ printk(KERN_EMERG "You probably have a hardware problem with your RAM chips or a\n"); ++ printk(KERN_EMERG "power saving mode enabled.\n"); + #endif + } + +@@ -293,8 +288,8 @@ + + asmlinkage void math_emulate(long arg) + { +- printk("math-emulation not enabled and no coprocessor found.\n"); +- printk("killing %s.\n",current->comm); ++ printk(KERN_EMERG "math-emulation not enabled and no coprocessor found.\n"); ++ printk(KERN_EMERG "killing %s.\n",current->comm); + send_sig(SIGFPE,current,1); + schedule(); + } +diff -rub --unidir /pub/src/linux/kernel/linux/arch/i386/mm/init.c ./arch/i386/mm/init.c +--- /pub/src/linux/kernel/linux/arch/i386/mm/init.c Tue Apr 4 15:17:07 1995 ++++ ./arch/i386/mm/init.c Tue Mar 28 19:02:46 1995 +@@ -79,9 +79,9 @@ + int i,free = 0,total = 0,reserved = 0; + int shared = 0; + +- printk("Mem-info:\n"); ++ printk(KERN_EMERG "Mem-info:\n"); + show_free_areas(); +- printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); ++ printk(KERN_EMERG "Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = high_memory >> PAGE_SHIFT; + while (i-- > 0) { + total++; +@@ -92,10 +92,10 @@ + else + shared += mem_map[i]-1; + } +- printk("%d pages of RAM\n",total); +- printk("%d free pages\n",free); +- printk("%d reserved pages\n",reserved); +- printk("%d pages shared\n",shared); ++ printk(KERN_EMERG "%d pages of RAM\n",total); ++ printk(KERN_EMERG "%d free pages\n",free); ++ printk(KERN_EMERG "%d reserved pages\n",reserved); ++ printk(KERN_EMERG "%d pages shared\n",shared); + show_buffers(); + #ifdef CONFIG_NET + show_net_buffers(); +diff -rub --unidir /pub/src/linux/kernel/linux/fs/buffer.c ./fs/buffer.c +--- /pub/src/linux/kernel/linux/fs/buffer.c Mon Mar 6 10:22:08 1995 ++++ ./fs/buffer.c Wed Mar 22 15:41:33 1995 +@@ -1400,9 +1400,9 @@ + int shared; + int nlist, isize; + +- printk("Buffer memory: %6dkB\n",buffermem>>10); +- printk("Buffer heads: %6d\n",nr_buffer_heads); +- printk("Buffer blocks: %6d\n",nr_buffers); ++ printk(KERN_EMERG "Buffer memory: %6dkB\n",buffermem>>10); ++ printk(KERN_EMERG "Buffer heads: %6d\n",nr_buffer_heads); ++ printk(KERN_EMERG "Buffer blocks: %6d\n",nr_buffers); + + for(nlist = 0; nlist < NR_LIST; nlist++) { + shared = found = locked = dirty = used = lastused = 0; +@@ -1419,10 +1419,10 @@ + used++, lastused = found; + bh = bh->b_next_free; + } while (bh != lru_list[nlist]); +- printk("Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n", ++ printk(KERN_EMERG "Buffer[%d] mem: %d buffers, %d used (last=%d), %d locked, %d dirty %d shrd\n", + nlist, found, used, lastused, locked, dirty, shared); + }; +- printk("Size [LAV] Free Clean Unshar Lck Lck1 Dirty Shared\n"); ++ printk(KERN_EMERG "Size [LAV] Free Clean Unshar Lck Lck1 Dirty Shared\n" KERN_EMERG); + for(isize = 0; isizecomm, (p == current) ? -nr : nr); ++ printk(KERN_EMERG "%-8s %3d ", p->comm, (p == current) ? -nr : nr); + if (((unsigned) p->state) < sizeof(stat_nam)/sizeof(char *)) + printk(stat_nam[p->state]); + else +@@ -763,8 +763,8 @@ + { + int i; + +- printk(" free sibling\n"); +- printk(" task PC stack pid father child younger older\n"); ++ printk(KERN_EMERG " free sibling\n"); ++ printk(KERN_EMERG " task PC stack pid father child younger older\n"); + for (i=0 ; i ++#include ++#else ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++#endif ++ + #include + #include + #include +@@ -80,11 +88,13 @@ + * should be after the IRQ has been active. + */ + +-static struct async_struct *IRQ_ports[16]; ++static struct async_struct *IRQ_ports[16] = {NULL,}; + static int IRQ_timeout[16]; ++#ifndef MODULE + static volatile int rs_irq_triggered; + static volatile int rs_triggered; + static int rs_wild_int_mask; ++#endif + + static void autoconfig(struct async_struct * info); + static void change_speed(struct async_struct *info); +@@ -343,6 +353,7 @@ + * ----------------------------------------------------------------------- + */ + ++#ifndef MODULE + /* + * This is the serial driver's interrupt routine while we are probing + * for submarines. +@@ -353,6 +364,7 @@ + rs_triggered |= 1 << irq; + return; + } ++#endif + + /* + * This routine is used by the interrupt handler to schedule +@@ -788,6 +804,7 @@ + * --------------------------------------------------------------- + */ + ++#ifndef MODULE + /* + * Grab all interrupts in preparation for doing an automatic irq + * detection. dontgrab is a mask of irq's _not_ to grab. Returns a +@@ -819,6 +836,7 @@ + free_irq(i); + } + } ++#endif + + /* + * This routine figures out the correct timeout for a particular IRQ. +@@ -1632,6 +1650,7 @@ + sti(); + } + ++#ifndef MODULE + /* + * This routine returns a bitfield of "wild interrupts". Basically, + * any unclaimed interrupts which is flapping around. +@@ -1675,6 +1694,7 @@ + restore_flags(flags); + return wild_interrupts; + } ++#endif + + static int rs_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +@@ -1745,6 +1765,7 @@ + case TIOCSERCONFIG: + return do_autoconfig(info); + ++#ifndef MODULE + case TIOCSERGWILD: + error = verify_area(VERIFY_WRITE, (void *) arg, + sizeof(int)); +@@ -1752,6 +1773,7 @@ + return error; + put_fs_long(rs_wild_int_mask, (unsigned long *) arg); + return 0; ++#endif + + case TIOCSERGETLSR: /* Get line status register */ + error = verify_area(VERIFY_WRITE, (void *) arg, +@@ -1761,6 +1783,7 @@ + else + return get_lsr_info(info, (unsigned int *) arg); + ++#ifndef MODULE + case TIOCSERSWILD: + if (!suser()) + return -EPERM; +@@ -1768,6 +1791,7 @@ + if (rs_wild_int_mask < 0) + rs_wild_int_mask = check_wild_interrupts(0); + return 0; ++#endif + + case TIOCSERGSTRUCT: + error = verify_area(VERIFY_WRITE, (void *) arg, +@@ -1835,6 +1859,7 @@ + + if (tty_hung_up_p(filp)) { + restore_flags(flags); ++ MOD_DEC_USE_COUNT; + return; + } + +@@ -1860,6 +1885,7 @@ + } + if (info->count) { + restore_flags(flags); ++ MOD_DEC_USE_COUNT; + return; + } + info->flags |= ASYNC_CLOSING; +@@ -1923,6 +1949,7 @@ + ASYNC_CLOSING); + wake_up_interruptible(&info->close_wait); + restore_flags(flags); ++ MOD_DEC_USE_COUNT; + } + + /* +@@ -2097,22 +2124,27 @@ + printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line, + info->count); + #endif ++ MOD_INC_USE_COUNT; + info->count++; + tty->driver_data = info; + info->tty = tty; + + if (!tmp_buf) { + tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL); +- if (!tmp_buf) ++ if (!tmp_buf) { ++ MOD_DEC_USE_COUNT; + return -ENOMEM; + } ++ } + + /* + * Start up serial port + */ + retval = startup(info); +- if (retval) ++ if (retval) { ++ MOD_DEC_USE_COUNT; + return retval; ++ } + + retval = block_til_ready(tty, filp, info); + if (retval) { +@@ -2120,6 +2152,7 @@ + printk("rs_open returning after block_til_ready with %d\n", + retval); + #endif ++ MOD_DEC_USE_COUNT; + return retval; + } + +@@ -2168,6 +2201,8 @@ + #undef SERIAL_OPT + } + ++ ++#ifndef MODULE + /* + * This routine is called by do_auto_irq(); it attempts to determine + * which interrupt a serial port is configured to use. It is not +@@ -2259,6 +2294,7 @@ + free_all_interrupts(irq_lines); + return (irq_try_1 == irq_try_2) ? irq_try_1 : 0; + } ++#endif /* CONFIG_SERIAL */ + + /* + * This routine is called by rs_init() to initialize a specific serial +@@ -2322,12 +2358,14 @@ + } + } + ++#ifndef MODULE + /* + * If the AUTO_IRQ flag is set, try to do the automatic IRQ + * detection. + */ + if (info->flags & ASYNC_AUTO_IRQ) + info->irq = do_auto_irq(info); ++#endif + + serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); + scratch = serial_in(info, UART_IIR) >> 6; +@@ -2382,15 +2420,31 @@ + /* + * The serial driver boot-time initialization code! + */ ++#ifdef MODULE ++ ++char kernel_version[]= UTS_RELEASE; ++ ++void cleanup_module(void) ++{ ++ tty_unregister_driver(&serial_driver); ++ tty_unregister_driver(&callout_driver); ++ bh_base[SERIAL_BH].routine = NULL; ++ timer_table[RS_TIMER].fn = NULL; ++} ++ ++int init_module(void) ++#else + long rs_init(long kmem_start) ++#endif + { +- int i; ++ int i, err; + struct async_struct * info; + + bh_base[SERIAL_BH].routine = do_serial_bh; ++ enable_bh(SERIAL_BH); + timer_table[RS_TIMER].fn = rs_timer; + timer_table[RS_TIMER].expires = 0; +-#ifdef CONFIG_AUTO_IRQ ++#if defined(CONFIG_AUTO_IRQ) && !defined(MODULE) + rs_wild_int_mask = check_wild_interrupts(1); + #endif + +@@ -2445,10 +2499,15 @@ + callout_driver.major = TTYAUX_MAJOR; + callout_driver.subtype = SERIAL_TYPE_CALLOUT; + +- if (tty_register_driver(&serial_driver)) +- panic("Couldn't register serial driver\n"); +- if (tty_register_driver(&callout_driver)) +- panic("Couldn't register callout driver\n"); ++ if ((err = tty_register_driver(&serial_driver)) < 0) { ++ printk("Couldn't register serial driver\n"); ++ return err; ++ } ++ if ((err = tty_register_driver(&callout_driver)) < 0) { ++ printk("Couldn't register callout driver\n"); ++ tty_unregister_driver(&serial_driver); ++ return err; ++ } + + for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) { + info->magic = SERIAL_MAGIC; +@@ -2471,6 +2530,7 @@ + info->prev_port = 0; + if (info->irq == 2) + info->irq = 9; ++#ifndef MODULE + if (!(info->flags & ASYNC_BOOT_AUTOCONF)) + continue; + autoconfig(info); +@@ -2496,8 +2556,13 @@ + printk("\n"); + break; + } ++#endif + } ++#ifndef MODULE + return kmem_start; ++#else ++ return 0; ++#endif + } + + /* +@@ -2533,12 +2598,14 @@ + "device already open\n", i, req->port, req->irq); + return -1; + } ++ MOD_INC_USE_COUNT; + info->irq = req->irq; + info->port = req->port; + autoconfig(info); + if (info->type == PORT_UNKNOWN) { + restore_flags(flags); + printk("register_serial(): autoconfig failed\n"); ++ MOD_DEC_USE_COUNT; + return -1; + } + printk("tty%02d at 0x%04x (irq = %d)", info->line, +@@ -2571,4 +2638,5 @@ + info->type = PORT_UNKNOWN; + printk("tty%02d unloaded\n", info->line); + restore_flags(flags); ++ MOD_DEC_USE_COUNT; + } diff --git a/patches/more_free b/patches/more_free new file mode 100644 index 0000000..5216d74 --- /dev/null +++ b/patches/more_free @@ -0,0 +1,18 @@ +Fuenf freie Seiten bei starkem NFS-Traffic ist fuer ISDN viel zu wenig. + +Notwendig, wenn der ISDN-Server als NFS-Client arbeitet. + +--- /pub/src/linux/kernel/linux-1.1/mm/swap.c Fri Jan 20 00:12:16 1995 ++++ mm/swap.c Sat Jan 21 08:35:01 1995 +@@ -646,8 +652,9 @@ + priority = GFP_ATOMIC; + } + } +- reserved_pages = 5; +- if (priority != GFP_NFS) ++ if (priority == GFP_NFS) ++ reserved_pages = min_free_pages>>1; ++ else + reserved_pages = min_free_pages; + save_flags(flags); + repeat: diff --git a/patches/nm.background b/patches/nm.background new file mode 100644 index 0000000..8d727d3 --- /dev/null +++ b/patches/nm.background @@ -0,0 +1,15 @@ +NM beim Kernelbauen kann ruhig im Hintergrund laufen, wenn man genug +Hauptspeicher hat... + +diff -rub --unidir /pub/src/linux/kernel/linux/Makefile ./Makefile +--- /pub/src/linux/kernel/linux/Makefile Tue Apr 4 15:19:12 1995 ++++ ./Makefile Tue Apr 4 11:34:33 1995 +@@ -125,7 +125,7 @@ + $(FILESYSTEMS) \ + $(DRIVERS) \ + $(LIBS) -o vmlinux +- $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map ++ $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map & + + symlinks: + rm -f include/asm diff --git a/patches/panicreboot b/patches/panicreboot new file mode 100644 index 0000000..1876400 --- /dev/null +++ b/patches/panicreboot @@ -0,0 +1,120 @@ +Dieser Patch loest eienen Reboot-nach-Panic aus, damit ein Server +unbeaufsichtigt neustarten kann. + +Optional. + + +diff -rub --unidir /pub/src/linux/kernel/linux/kernel/panic.c ./kernel/panic.c +--- /pub/src/linux/kernel/linux/kernel/panic.c Wed Mar 1 12:31:54 1995 ++++ ./kernel/panic.c Fri Mar 3 05:32:15 1995 +@@ -13,20 +13,38 @@ + #include + #include + ++#include ++ + asmlinkage void sys_sync(void); /* it's really int */ ++extern void hard_reset_now(void); ++ ++int in_panic = 0; + + NORET_TYPE void panic(const char * fmt, ...) + { + static char buf[1024]; + va_list args; + ++ cli(); ++ + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); ++ ++ if(!in_panic++) { + printk(KERN_EMERG "Kernel panic: %s\n",buf); ++ *((char *)0)=0; ++ } ++ ++#if 0 + if (current == task[0]) + printk(KERN_EMERG "In swapper task - not syncing\n"); + else + sys_sync(); +- for(;;); ++#endif ++ { ++ int i,j; ++ for(i=0;i<300;i++) for(j=0;j<1000;j++) udelay(1000); ++ } ++ hard_reset_now(); + } +diff -rub --unidir /pub/src/linux/kernel/linux/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c +--- /pub/src/linux/kernel/linux/arch/i386/kernel/traps.c Wed Feb 8 12:54:00 1995 ++++ ./arch/i386/kernel/traps.c Wed Mar 22 15:33:47 1995 +@@ -100,6 +100,7 @@ + unsigned short ss; + unsigned long *stack, addr, module_start, module_end; + extern char start_kernel, etext; ++ extern int in_panic; + + esp = (unsigned long) ®s->esp; + ss = KERNEL_DS; +@@ -109,29 +110,27 @@ + esp = regs->esp; + ss = regs->ss; + } +- console_verbose(); +- printk("%s: %04lx\n", str, err & 0xffff); +- printk("EIP: %04x:%08lx\nEFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); +- printk("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", ++ console_verbose(); cli(); ++ printk("\n" KERN_EMERG "%s: %04lx ", str, err & 0xffff); ++ printk(KERN_EMERG "EIP: %04x:%08lx EFLAGS: %08lx\n", 0xffff & regs->cs,regs->eip,regs->eflags); ++ printk(KERN_EMERG "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); +- printk("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", ++ printk(KERN_EMERG "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", + regs->esi, regs->edi, regs->ebp, esp); +- printk("ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", ++ printk(KERN_EMERG "ds: %04x es: %04x fs: %04x gs: %04x ss: %04x\n", + regs->ds, regs->es, regs->fs, regs->gs, ss); + store_TR(i); + if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) +- printk("Corrupted stack page\n"); +- printk("Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", ++ printk(KERN_EMERG "Corrupted stack page; "); ++ printk(KERN_EMERG "Process %s (pid: %d, process nr: %d, stackpage=%08lx)\nStack: ", + current->comm, current->pid, 0xffff & i, current->kernel_stack_page); + stack = (unsigned long *) esp; + for(i=0; i < kstack_depth_to_print; i++) { + if (((long) stack & 4095) == 0) + break; +- if (i && ((i % 8) == 0)) +- printk("\n "); +- printk("%08lx ", get_seg_long(ss,stack++)); ++ printk("%lx ", get_seg_long(ss,stack++)); + } +- printk("\nCall Trace: "); ++ printk("\n" KERN_EMERG "Call Trace: "); + stack = (unsigned long *) esp; + i = 1; + module_start = ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)); +@@ -149,16 +148,12 @@ + if (((addr >= (unsigned long) &start_kernel) && + (addr <= (unsigned long) &etext)) || + ((addr >= module_start) && (addr <= module_end))) { +- if (i && ((i % 8) == 0)) +- printk("\n "); +- printk("%08lx ", addr); ++ printk("%lx ", addr); + i++; + } + } +- printk("\nCode: "); +- for(i=0;i<20;i++) +- printk("%02x ",0xff & get_seg_byte(regs->cs,(i+(char *)regs->eip))); +- printk("\n"); ++ in_panic++; ++ panic("Crash"); + do_exit(SIGSEGV); + } + diff --git a/patches/setnoswap b/patches/setnoswap new file mode 100644 index 0000000..d618e7f --- /dev/null +++ b/patches/setnoswap @@ -0,0 +1,21 @@ +Dieser "Hack"-Patch ermoeglicht es einem Prozess, sich im Speicher zu +verewigen... + +Notwendig, wenn der ISDN-Server auch noch was anderes zu tun hat. +Das Standardinterface fuer solche Faelle (mlockall() oder so) existiert +leider noch nicht. + +diff -rub --unidir /pub/src/linux/kernel/linux/kernel/sys.c ./kernel/sys.c +--- /pub/src/linux/kernel/linux/kernel/sys.c Sat Mar 4 23:16:36 1995 ++++ ./kernel/sys.c Wed Mar 8 05:38:27 1995 +@@ -146,6 +146,10 @@ + { + if (!suser()) + return -EPERM; ++ if(magic == 0xfee1dead && magic_too == 0x17392634) { ++ current->mm->swappable = flag ? 0 : 1; ++ return 0; ++ } + if (magic != 0xfee1dead || magic_too != 672274793) + return -EINVAL; + if (flag == 0x01234567) diff --git a/patches/symbols b/patches/symbols new file mode 100644 index 0000000..4c7f058 --- /dev/null +++ b/patches/symbols @@ -0,0 +1,70 @@ +Einige zusaetzliche Symbole fuer kernel/swap.c. + +Notwendig. + +diff -rub --unidir /pub/src/linux/kernel/linux/include/linux/time.h ./include/linux/time.h +--- /pub/src/linux/kernel/linux/include/linux/time.h Wed Feb 1 08:19:36 1995 ++++ ./include/linux/time.h Fri Mar 3 05:32:13 1995 +@@ -43,4 +43,10 @@ + struct timeval it_value; /* current value */ + }; + ++#ifdef __KERNEL__ ++ ++void do_gettimeofday(struct timeval *tv); ++ ++#endif /* __KERNEL__ */ ++ + #endif +diff -rub --unidir /pub/src/linux/kernel/linux/include/linux/tty.h ./include/linux/tty.h +--- /pub/src/linux/kernel/linux/include/linux/tty.h Sun Feb 26 15:45:26 1995 ++++ ./include/linux/tty.h Fri Mar 3 05:32:13 1995 +@@ -293,6 +293,7 @@ + extern void stop_tty(struct tty_struct * tty); + extern void start_tty(struct tty_struct * tty); + extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); ++extern int tty_unregister_ldisc(int disc, struct tty_ldisc *new_ldisc); + extern int tty_register_driver(struct tty_driver *driver); + extern int tty_unregister_driver(struct tty_driver *driver); + extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, +diff -rub --unidir /pub/src/linux/kernel/linux/kernel/ksyms.c ./kernel/ksyms.c +--- /pub/src/linux/kernel/linux/kernel/ksyms.c Tue Apr 4 15:18:53 1995 ++++ ./kernel/ksyms.c Tue Mar 28 19:04:11 1995 +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -174,8 +181,13 @@ + X(get_blkfops), + + /* Module creation of serial units */ ++#ifdef CONFIG_SERIAL + X(register_serial), + X(unregister_serial), ++#endif ++ X(do_SAK), ++ X(ldiscs), ++ X(bh_base), + + /* tty routines */ + X(tty_hangup), +@@ -190,6 +202,7 @@ + /* executable format registration */ + X(register_binfmt), + X(unregister_binfmt), ++ X(start_thread), + + /* execution environment registration */ + X(lookup_exec_domain), +@@ -247,6 +260,7 @@ + X(simple_strtoul), + X(system_utsname), + X(sys_call_table), ++ X(do_gettimeofday), + + /* Signal interfaces */ + X(do_signal), diff --git a/str_if/str_linux.c b/str_if/str_linux.c index 5751bbf..583e9aa 100644 --- a/str_if/str_linux.c +++ b/str_if/str_linux.c @@ -138,6 +138,7 @@ static int strl_header(struct sk_buff *skb, struct device *dev, unsigned short type, void *daddr, void *saddr, unsigned len) { + skb->protocol = htons(type); return 0; } @@ -200,6 +201,7 @@ printk("Q NULL\n"); #if LINUX_VERSION_CODE >= 66304 /* 1.3.0 */ if(!lp->encap && (skb->protocol != lp->ethertype)) { +printk("%sprotocol %x, ethertype %x\n",KERN_DEBUG,skb->protocol,lp->ethertype); lp->stats.tx_dropped++; dev_kfree_skb (skb, FREE_WRITE); return 0; diff --git a/streams/streams_io.c b/streams/streams_io.c index 633d935..dd673c1 100644 --- a/streams/streams_io.c +++ b/streams/streams_io.c @@ -764,9 +764,8 @@ stream_rput (queue_t * p_queue, mblk_t * p_msg) if(p_stream == NULL) return; - if((tty = p_stream->tty) == NULL) - return; - tty_hangup(tty); + if((tty = p_stream->tty) != NULL) + tty_hangup(tty); return; } freemsg (p_msg); @@ -783,13 +782,8 @@ stream_rput (queue_t * p_queue, mblk_t * p_msg) wake_up (&p_stream->writing); wake_up (&p_stream->ioctling); - if((tty = p_stream->tty) == NULL) { -#ifdef CONFIG_DEBUG_STREAMS - printf("HUP: No stream!\n"); -#endif - return; - } - tty_hangup(tty); + if((tty = p_stream->tty) != NULL) + tty_hangup(tty); return; } case M_PCSIG: diff --git a/streams/streams_sys.c b/streams/streams_sys.c index 7d369c2..3465d71 100644 --- a/streams/streams_sys.c +++ b/streams/streams_sys.c @@ -2399,7 +2399,7 @@ int unregister_strdev (unsigned int major, struct streamtab *strtab, int nminor) if (err >= 0) { LESS_USE; } else - printf("Unregister: Driver %s not deleted: %d\n",KERN_WARNING ,name,err); + printf("%sUnregister: Driver %s not deleted: %d\n",KERN_WARNING ,name,err); #endif return err; } diff --git a/tools/isdn.conf b/tools/isdn.conf index 4a89f5e..4298352 100644 --- a/tools/isdn.conf +++ b/tools/isdn.conf @@ -116,7 +116,7 @@ CM ???? 14 frameb # Limit how many B channel connections may be opened. # Override the limit with :il in the P line. -CL * * 2 +CL * * * * 2 ## Load cards