More support for hybrid modem (not working yet)

This commit is contained in:
Karsten Keil 1998-08-20 13:50:42 +00:00
parent 04d01efcbd
commit c160efa3bd
7 changed files with 279 additions and 69 deletions

View File

@ -7,6 +7,10 @@
*
*
* $Log$
* Revision 1.3 1998/05/25 12:57:38 keil
* HiSax golden code from certification, Don't use !!!
* No leased lines, no X75, but many changes.
*
* Revision 1.2 1998/04/15 16:47:16 keil
* new interface
*
@ -25,7 +29,7 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
u_char val;
char tmp[32];
long flags;
int cnt=50;
int cnt=30;
cs->mon_txp = 0;
cs->mon_txc = msg[0];
@ -51,11 +55,6 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
cnt--;
udelay(500);
#if 0
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + (10 * HZ) / 1000; /* Timeout 10ms */
schedule();
#endif
}
if (receive) {
while (cnt && !test_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
@ -64,8 +63,9 @@ send_arcofi(struct IsdnCardState *cs, const u_char *msg, int bc, int receive) {
}
}
restore_flags(flags);
sprintf(tmp, "arcofi tout %d", cnt);
debugl1(cs, tmp);
if (cnt <= 0) {
printk(KERN_WARNING"HiSax arcofi monitor timed out\n");
debugl1(cs, "HiSax arcofi monitor timed out");
}
return(cnt);
}

View File

@ -7,6 +7,9 @@
* Fritz Elfert
*
* $Log$
* Revision 2.21 1998/08/13 23:36:15 keil
* HiSax 3.1 - don't work stable with current LinkLevel
*
* Revision 2.20 1998/06/26 15:13:05 fritz
* Added handling of STAT_ICALL with incomplete CPN.
* Added AT&L for ttyI emulator.
@ -1798,6 +1801,15 @@ HiSax_command(isdn_ctrl * ic)
}
chanp->l2_protocol = ic->arg >> 8;
break;
case (ISDN_CMD_SETL3):
chanp = csta->channel + (ic->arg & 0xff);
if (chanp->debug & 1) {
sprintf(tmp, "SETL3 card %d %ld", csta->cardnr + 1,
ic->arg >> 8);
link_debug(chanp, tmp, 1);
}
chanp->l3_protocol = ic->arg >> 8;
break;
case (ISDN_CMD_DIAL):
chanp = csta->channel + (ic->arg & 0xff);
if (chanp->debug & 1) {

View File

@ -11,6 +11,9 @@
*
*
* $Log$
* Revision 2.10 1998/08/13 23:36:22 keil
* HiSax 3.1 - don't work stable with current LinkLevel
*
* Revision 2.9 1998/05/25 12:57:48 keil
* HiSax golden code from certification, Don't use !!!
* No leased lines, no X75, but many changes.
@ -419,6 +422,16 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
if (!(val & ELSA_PCI_IRQ_MASK))
return;
#if ARCOFI_USE
if (cs->hw.elsa.MFlag) {
val = serial_inp(cs, UART_IIR);
if (!(val & UART_IIR_NO_INT)) {
sprintf(tmp,"IIR %02x", val);
debugl1(cs, tmp);
rs_interrupt_elsa(intno, cs);
}
}
#endif
ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
Start_IPAC:
if (cs->debug & L1_DEB_IPAC) {
@ -570,6 +583,8 @@ set_arcofi(struct IsdnCardState *cs, int bc) {
udelay(ARCDEL);
send_arcofi(cs, ARCOFI_XOP_F, bc, 0);
restore_flags(flags);
sprintf(tmp,"end set_arcofi bc=%d", bc);
debugl1(cs, tmp);
}
static int

View File

@ -10,11 +10,14 @@
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#define SERIAL_DEBUG_OPEN 1
#define SERIAL_DEBUG_INTR 1
#define SERIAL_DEBUG_FLOW 1
//#define SERIAL_DEBUG_OPEN 1
//#define SERIAL_DEBUG_INTR 1
//#define SERIAL_DEBUG_FLOW 1
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_INTR
#undef SERIAL_DEBUG_FLOW
#undef SERIAL_DEBUG_REG
//#define SERIAL_DEBUG_REG
//#define SERIAL_DEBUG_REG 1
#ifdef SERIAL_DEBUG_REG
static u_char deb[32];
@ -22,9 +25,18 @@ const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"};
const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
#endif
static char *MInit_1 = "AT &F &C1 E0 &D2 L2 M1 S64=13\n\0";
static char *MInit_2 = "AT+FCLASS=0 V1 S2=128 X1 \\V8\n\0";
static char *MInit_3 = "AT %G0 %B2400 L0 M0 &G0 %E1 %L1 %M0 %C3 \\N3\n\0";
static char *MInit_1 = "AT&F&C1E0&D2\r\0";
static char *MInit_2 = "ATL2M1S64=13\r\0";
static char *MInit_3 = "AT+FCLASS=0\r\0";
static char *MInit_4 = "ATV1S2=128X1\r\0";
static char *MInit_5 = "AT\\V8\\N3\r\0";
static char *MInit_6 = "ATL0M0&G0%E1\r\0";
static char *MInit_7 = "AT%L1%M0%C3\r\0";
static char *MInit_speed28800 = "AT%G0%B28800\r\0";
static char *MInit_dialout = "ATs7=60 x1 d\r\0";
static char *MInit_dialin = "ATs7=60 x1 a\r\0";
static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
@ -122,11 +134,13 @@ static void change_speed(struct IsdnCardState *cs, int baud)
sprintf(tmp,"modem quot=0x%x", quot);
debugl1(cs, tmp);
save_flags(flags); cli();
save_flags(flags);
cli();
serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */
serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */
serial_outp(cs, UART_LCR, cval); /* reset DLAB */
serial_inp(cs, UART_RX);
restore_flags(flags);
}
@ -190,7 +204,7 @@ static int mstartup(struct IsdnCardState *cs)
/*
* and set the speed of the serial port
*/
change_speed(cs, 57600*2);
change_speed(cs, BASE_BAUD);
cs->hw.elsa.MFlag = 1;
errout:
restore_flags(flags);
@ -256,19 +270,21 @@ write_modem(struct BCState *bcs) {
fp &= (MAX_MODEM_BUF -1);
count = MIN(len, MAX_MODEM_BUF - fp);
if (count < len) {
memcpy(cs->hw.elsa.transbuf + fp, skb_pull(bcs->tx_skb, count), count);
memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
skb_pull(bcs->tx_skb, count);
cs->hw.elsa.transcnt += count;
ret = count;
count = len - count;
fp = 0;
}
memcpy(cs->hw.elsa.transbuf + fp, skb_pull(bcs->tx_skb, count), count);
memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
skb_pull(bcs->tx_skb, count);
cs->hw.elsa.transcnt += count;
ret += count;
if (cs->hw.elsa.transcnt &&
!(cs->hw.elsa.IER & UART_IER_THRI)) {
cs->hw.elsa.IER |= UART_IER_THRI;
cs->hw.elsa.IER |= UART_IER_THRI;
serial_outp(cs, UART_IER, cs->hw.elsa.IER);
}
restore_flags(flags);
@ -352,12 +368,12 @@ static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
sprintf(tmp, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp,
cs->hw.elsa.transcnt);
debugl1(cs, tmp);
if (cs->hw.elsa.transcnt <= 0) {
cs->hw.elsa.IER &= ~UART_IER_THRI;
serial_out(cs, UART_IER, cs->hw.elsa.IER);
return;
}
count = 16;
do {
serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
@ -497,7 +513,7 @@ close_elsastate(struct BCState *bcs)
{
struct sk_buff *skb;
// modehscx(bcs, 0, 0);
modehscx(bcs, 0, bcs->channel);
if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
if (bcs->hw.hscx.rcvbuf) {
if (bcs->mode != L1_MODE_MODEM)
@ -518,39 +534,6 @@ close_elsastate(struct BCState *bcs)
}
}
void
modem_l2l1(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
long flags;
if (pr == (PH_DATA | REQUEST)) {
save_flags(flags);
cli();
if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
st->l1.bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
st->l1.bcs->hw.hscx.count = 0;
restore_flags(flags);
write_modem(st->l1.bcs);
}
} else if (pr == (PH_ACTIVATE | REQUEST)) {
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
set_arcofi(st->l1.bcs->cs, st->l1.bc);
st->l1.bcs->cs->hw.elsa.MFlag=2;
} else if (pr == (PH_DEACTIVATE | REQUEST)) {
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
st->l1.bcs->cs->hw.elsa.MFlag=1;
} else {
printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
}
}
void
modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
int count, fp;
@ -589,27 +572,126 @@ void
modem_set_init(struct IsdnCardState *cs) {
long flags;
int timeout;
u_char tmp[32];
#define RCV_DELAY 20000
save_flags(flags);
sti();
modem_write_cmd(cs, MInit_1, strlen(MInit_1));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
udelay(50000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_2, strlen(MInit_2));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
udelay(50000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_3, strlen(MInit_3));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
udelay(50000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_4, strlen(MInit_4));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY );
modem_write_cmd(cs, MInit_5, strlen(MInit_5));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_6, strlen(MInit_6));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
modem_write_cmd(cs, MInit_7, strlen(MInit_7));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
restore_flags(flags);
}
void
modem_set_dial(struct IsdnCardState *cs, int outgoing) {
long flags;
int timeout;
u_char tmp[32];
#define RCV_DELAY 20000
save_flags(flags);
sti();
modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
if (outgoing)
modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
else
modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
timeout = 1000;
while(timeout-- && cs->hw.elsa.transcnt)
udelay(1000);
sprintf(tmp, "msi tout=%d", timeout);
debugl1(cs, tmp);
udelay(RCV_DELAY);
restore_flags(flags);
}
void
modem_l2l1(struct PStack *st, int pr, void *arg)
{
struct sk_buff *skb = arg;
long flags;
if (pr == (PH_DATA | REQUEST)) {
save_flags(flags);
cli();
if (st->l1.bcs->tx_skb) {
skb_queue_tail(&st->l1.bcs->squeue, skb);
restore_flags(flags);
} else {
st->l1.bcs->tx_skb = skb;
test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
st->l1.bcs->hw.hscx.count = 0;
restore_flags(flags);
write_modem(st->l1.bcs);
}
} else if (pr == (PH_ACTIVATE | REQUEST)) {
test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
set_arcofi(st->l1.bcs->cs, st->l1.bc);
mstartup(st->l1.bcs->cs);
modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
st->l1.bcs->cs->hw.elsa.MFlag=2;
} else if (pr == (PH_DEACTIVATE | REQUEST)) {
test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
send_arcofi(st->l1.bcs->cs, ARCOFI_XOP_0, st->l1.bc, 0);
st->l1.bcs->cs->hw.elsa.MFlag=1;
} else {
printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
}
}
int
setstack_elsa(struct PStack *st, struct BCState *bcs)
{
@ -669,7 +751,7 @@ init_modem(struct IsdnCardState *cs) {
if (mstartup(cs)) {
printk(KERN_WARNING "Elsa: problem startup modem\n");
}
// modem_set_init(cs);
modem_set_init(cs);
}
void

View File

@ -3,6 +3,9 @@
* Basic declarations, defines and prototypes
*
* $Log$
* Revision 2.23 1998/08/13 23:36:31 keil
* HiSax 3.1 - don't work stable with current LinkLevel
*
* Revision 2.22 1998/07/15 15:01:28 calle
* Support for AVM passive PCMCIA cards:
* A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
@ -467,6 +470,7 @@ struct Channel {
struct FsmTimer drel_timer, dial_timer;
int debug;
int l2_protocol, l2_active_protocol;
int l3_protocol;
int data_open;
struct l3_process *proc;
setup_parm setup; /* from isdnif.h numbers and Serviceindicator */

View File

@ -6,6 +6,9 @@
*
*
* $Log$
* Revision 1.14 1998/08/13 23:36:33 keil
* HiSax 3.1 - don't work stable with current LinkLevel
*
* Revision 1.13 1998/06/26 22:03:28 keil
* send flags between hdlc frames
*
@ -113,8 +116,8 @@ modehscx(struct BCState *bcs, int mode, int bc)
}
switch (mode) {
case (L1_MODE_NULL):
cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff);
cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff);
cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
break;
case (L1_MODE_TRANS):

View File

@ -20,6 +20,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log$
* Revision 1.58 1998/07/26 18:48:45 armin
* Added silence detection in voice receive mode.
*
* Revision 1.57 1998/06/26 15:12:36 fritz
* Added handling of STAT_ICALL with incomplete CPN.
* Added AT&L for ttyI emulator.
@ -901,7 +904,7 @@ isdn_tty_dial(char *n, modem_info * info, atemu * m)
break;
}
#ifdef CONFIG_ISDN_AUDIO
if (si == 1) {
if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@ -1096,7 +1099,7 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
break;
}
#ifdef CONFIG_ISDN_AUDIO
if (si == 1) {
if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
@ -1148,7 +1151,90 @@ isdn_tty_resume(char *id, modem_info * info, atemu * m)
cmd.parm.cmsg.para[4] = 0;
cmd.parm.cmsg.para[5] = l;
strncpy(&cmd.parm.cmsg.para[6], id, l);
cmd.command = CAPI_PUT_MESSAGE;
cmd.command =CAPI_PUT_MESSAGE;
/* info->dialing = 1;
strcpy(dev->num[i], n);
isdn_info_update();
*/
isdn_command(&cmd);
}
}
/* isdn_tty_send_msg() sends a message to a HL driver
* This is used for hybrid modem cards to send AT commands to it
*/
static void
isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
{
int usg = ISDN_USAGE_MODEM;
int si = 7;
int l2 = m->mdmreg[REG_L2PROT];
isdn_ctrl cmd;
ulong flags;
int i;
int j;
int l;
l = strlen(msg);
if (!l) {
isdn_tty_modem_result(4, info);
return;
}
for (j = 7; j >= 0; j--)
if (m->mdmreg[REG_SI1] & (1 << j)) {
si = bit2si[j];
break;
}
#ifdef CONFIG_ISDN_AUDIO
if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
l2 = ISDN_PROTO_L2_TRANS;
usg = ISDN_USAGE_VOICE;
}
#endif
m->mdmreg[REG_SI1I] = si2bit[si];
save_flags(flags);
cli();
i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
if (i < 0) {
restore_flags(flags);
isdn_tty_modem_result(6, info);
} else {
info->isdn_driver = dev->drvmap[i];
info->isdn_channel = dev->chanmap[i];
info->drv_index = i;
dev->m_idx[i] = info->line;
dev->usage[i] |= ISDN_USAGE_OUTGOING;
info->last_dir = 1;
isdn_info_update();
restore_flags(flags);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.command = ISDN_CMD_CLREAZ;
isdn_command(&cmd);
strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETEAZ;
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL2;
info->last_l2 = l2;
cmd.arg = info->isdn_channel + (l2 << 8);
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.command = ISDN_CMD_SETL3;
cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
isdn_command(&cmd);
cmd.driver = info->isdn_driver;
cmd.arg = info->isdn_channel;
cmd.parm.cmsg.Length = l+14;
cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
cmd.parm.cmsg.Subcommand = CAPI_REQ;
cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
cmd.parm.cmsg.para[0] = l+1;
strncpy(&cmd.parm.cmsg.para[1], msg, l);
cmd.parm.cmsg.para[l+1] = 0xd;
cmd.command =CAPI_PUT_MESSAGE;
/* info->dialing = 1;
strcpy(dev->num[i], n);
isdn_info_update();
@ -2860,6 +2946,9 @@ isdn_tty_report(modem_info * info)
case ISDN_PROTO_L2_TRANS:
isdn_tty_at_cout("transparent", info);
break;
case ISDN_PROTO_L2_MODEM:
isdn_tty_at_cout("modem", info);
break;
default:
isdn_tty_at_cout("unknown", info);
break;
@ -3189,9 +3278,10 @@ isdn_tty_cmd_ATA(modem_info * info)
#ifdef CONFIG_ISDN_AUDIO
/* If more than one bit set in reg18, autoselect Layer2 */
if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
if (m->mdmreg[REG_SI1I] == 1)
l2 = ISDN_PROTO_L2_TRANS;
else
if (m->mdmreg[REG_SI1I] == 1) {
if (l2 != ISDN_PROTO_L2_MODEM)
l2 = ISDN_PROTO_L2_TRANS;
} else
l2 = ISDN_PROTO_L2_X75I;
}
#endif
@ -3763,6 +3853,10 @@ isdn_tty_parse_at(modem_info * info)
break;
case 'R': /* RESUME */
isdn_tty_get_msnstr(ds, &p);
isdn_tty_resume(ds, info, m);
case 'M': /* MESSAGE */
p++;
isdn_tty_send_msg(info, m, p);
break;
default:
PARSE_ERROR;