📄 torisa.c
字号:
/* Calculate the transmit, and receive go thru all the chans */ oldn = -1; for(n1 = 0; n1 < channels_per_span; n1++) { n = chseq[n1]; txword[n] = 0; if (n < oldn) { /* We've circled around. Now we increment the passno and stuff */ if ((passno % ZT_CHUNKSIZE) == (ZT_CHUNKSIZE - 1)) { /* Swap buffers */ for (x = 0;x < (channels_per_span * 2);x++) { chans[x].readchunk = readdata[curread][x]; chans[x].writechunk = writedata[curread][x]; } /* Lets work with the others now which presumably have been filled */ curread = 1 - curread; if (!taskletpending) { taskletpending = 1; taskletsched++; tasklet_hi_schedule(&torisa_tlet); } else { txerrors++; } } passno++; } oldn = n; /* go thru both spans */ for(j = 0; j < 2; j++) { /* enter the transmit stuff with i being channel number, leaving with txc being character to transmit */ txc = writedata[curread][j * channels_per_span + n-1][passno % ZT_CHUNKSIZE]; txword[n] |= txc << (j * 8); /* receive side */ i = n + (j * channels_per_span); /* calc chan number */ rxc = (rxword[n] >> (j * 8)) & 0xff; readdata[curread][j * channels_per_span + n - 1][passno % ZT_CHUNKSIZE] = rxc; } } i = passno & 127; /* if an E1 card, do rx signalling for it */ if (i < 3 && (card_type == TYPE_E1)) { /* if an E1 card */ for(j = (i * 3); j < (i * 3) + 5; j++) { for(k = 1,x = j; k <= 2; k++,x += channels_per_span) { c = t1in(k,0x31 + j); rxc = c & 15; if (rxc != chans[x + 15].rxsig) { /* Check for changes in received bits */ if (!(chans[x + 15].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[x + 15], rxc); } rxc = c >> 4; if (rxc != chans[x].rxsig) { /* Check for changes in received bits */ if (!(chans[x].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[x], rxc); } } } } /* if a t1 card, do rx signalling for it */ if ((i < 6) && (card_type == TYPE_T1)) { k = (i / 3); /* get span */ n = (i % 3); /* get base */ abits = t1in(k + 1, 0x60 + n); bbits = t1in(k + 1, 0x63 + n); cbits = t1in(k + 1, 0x66 + n); dbits = t1in(k + 1, 0x69 + n); for (j=0; j< 8; j++) { /* Get channel number */ i = (k * 24) + (n * 8) + j; rxc = 0; if (abits & (1 << j)) rxc |= ZT_ABIT; if (bbits & (1 << j)) rxc |= ZT_BBIT; if (cbits & (1 << j)) rxc |= ZT_CBIT; if (dbits & (1 << j)) rxc |= ZT_DBIT; if (chans[i].rxsig != rxc) { /* Check for changes in received bits */ if (!(chans[i].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[i], rxc); } } } if (!(passno & 0x7)) { for(i = 0; i < 2; i++) { /* if alarm timer, and it's timed out */ if (alarmtimer[i]) { if (!--alarmtimer[i]) { /* clear recover status */ spans[i].alarms &= ~ZT_ALARM_RECOVER; if (card_type == TYPE_T1) t1out(i + 1,0x35,0x10); /* turn off yel */ else t1out(i + 1,0x21,0x5f); /* turn off remote alarm */ zt_alarm_notify(&spans[i]); /* let them know */ } } } } i = passno & 511; if ((i == 100) || (i == 101)) { j = 0; /* clear this alarm status */ i -= 100; if (card_type == TYPE_T1) { c = t1in(i + 1,0x31); /* get RIR2 */ spans[i].rxlevel = c >> 6; /* get rx level */ t1out(i + 1,0x20,0xff); c = t1in(i + 1,0x20); /* get the status */ /* detect the code, only if we are not sending one */ if ((!spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ { /* set into remote loop, if not there already */ if ((loopupcnt[i]++ > 80) && (spans[i].maintstat != ZT_MAINT_REMOTELOOP)) { t1out(i + 1,0x37,0x9c); /* remote loopback */ spans[i].maintstat = ZT_MAINT_REMOTELOOP; } } else loopupcnt[i] = 0; /* detect the code, only if we are not sending one */ if ((!spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ { /* if in remote loop, get out of it */ if ((loopdowncnt[i]++ > 80) && (spans[i].maintstat == ZT_MAINT_REMOTELOOP)) { t1out(i + 1,0x37,0x8c); /* normal */ spans[i].maintstat = ZT_MAINT_NONE; } } else loopdowncnt[i] = 0; if (c & 3) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 8) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } else { /* its an E1 card */ t1out(i + 1,6,0xff); c = t1in(i + 1,6); /* get the status */ if (c & 9) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 2) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } /* only consider previous carrier alarm state */ spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); n = 1; /* set to 1 so will not be in yellow alarm if we dont care about open channels */ /* if to have yellow alarm if nothing open */ if (spans[i].lineconfig & ZT_CONFIG_NOTOPEN) { /* go thru all chans, and count # open */ for(n = 0,k = (i * channels_per_span); k < (i * channels_per_span) + channels_per_span; k++) { if ((chans[k].flags & ZT_FLAG_OPEN) || (chans[k].flags & ZT_FLAG_NETDEV)) n++; } /* if none open, set alarm condition */ if (!n) j |= ZT_ALARM_NOTOPEN; } /* if no more alarms, and we had some */ if ((!j) && spans[i].alarms) { alarmtimer[i] = ZT_ALARMSETTLE_TIME; } if (alarmtimer[i]) j |= ZT_ALARM_RECOVER; /* if going into alarm state, set yellow (remote) alarm */ if ((j) && (!spans[i].alarms)) { if (card_type == TYPE_T1) t1out(i + 1,0x35,0x11); else t1out(i + 1,0x21,0x7f); } if (c & 4) /* if yellow alarm */ j |= ZT_ALARM_YELLOW; if (spans[i].maintstat || spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; spans[i].alarms = j; zt_alarm_notify(&spans[i]); } if (!(passno % 8000)) /* even second boundary */ { /* do both spans */ for(i = 1; i <= 2; i++) { if (card_type == TYPE_T1) { /* add this second's BPV count to total one */ spans[i - 1].bpvcount += t1in(i,0x24) + (t1in(i,0x23) << 8); } else { /* add this second's BPV count to total one */ spans[i - 1].bpvcount += t1in(i,1) + (t1in(i,0) << 8); } } } /* re-evaluate active sync src */ mysyncsrc = 0; /* if primary sync specified, see if we can use it */ if (syncs[0]) { /* if no alarms, use it */ if (!(spans[syncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[0]; } /* if we dont have one yet, and there is a secondary, see if we can use it */ if ((!mysyncsrc) && (syncs[1])) { /* if no alarms, use it */ if (!(spans[syncs[1] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[1]; } /* on the E1 card, the PLL takes a bit of time to lock going between internal and external clocking. There needs to be some settle time before actually changing the source, otherwise it will oscillate between in and out of sync */ if (card_type == TYPE_E1) { /* if stable, add to count */ if (lastsyncsrc == mysyncsrc) mysynccnt++; else mysynccnt = 0; lastsyncsrc = mysyncsrc; /* if stable sufficiently long, change it */ if (mysynccnt >= E1SYNCSTABLETHRESH) { mysynccnt = 0; syncsrc = mysyncsrc; } } else syncsrc = mysyncsrc; /* otherwise on a T1 card, just use current value */ /* update sync src info */ spans[0].syncsrc = spans[1].syncsrc = syncsrc; /* If this is the last pass, then prepare the next set */ /* clear outbit, restore interrupt enable */ setctlreg(clockvals[syncsrc] | INTENA);#ifdef LINUX26 return IRQ_RETVAL(1);#endif }static int torisa_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data){ struct torisa_debug td; switch(cmd) { case TORISA_GETDEBUG: td.txerrors = txerrors; td.irqcount = irqcount; td.taskletsched = taskletsched; td.taskletrun = taskletrun; td.taskletexec = taskletexec; td.span1flags = spans[0].flags; td.span2flags = spans[1].flags; if (copy_to_user((struct torisa_debug *)data, &td, sizeof(td))) return -EFAULT; return 0; default: return -ENOTTY; } return 0;}static int __init tor_init(void){ if (!base) { printk("Specify address with base=0xNNNNN\n"); return -EIO; } if (tor_probe()) { printk(KERN_ERR "No ISA tormenta card found at %05lx\n", base); return -EIO; } if (request_irq(irq, torisa_intr, SA_INTERRUPT, "torisa", NULL)) { printk(KERN_ERR "Unable to request tormenta IRQ %d\n", irq); return -EIO; } if (!request_mem_region(base, 4096, "Tormenta ISA")) { printk(KERN_ERR "Unable to request 4k memory window at %lx\n", base); free_irq(irq, NULL); return -EIO; } strcpy(spans[0].name, "TorISA/1"); strcpy(spans[0].desc, "ISA Tormenta Span 1"); spans[0].spanconfig = torisa_spanconfig; spans[0].chanconfig = torisa_chanconfig; spans[0].startup = torisa_startup; spans[0].shutdown = torisa_shutdown; spans[0].rbsbits = torisa_rbsbits; spans[0].maint = torisa_maint; spans[0].open = torisa_open; spans[0].close = torisa_close; spans[0].channels = channels_per_span; spans[0].chans = &chans[0]; spans[0].flags = ZT_FLAG_RBS; spans[0].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; spans[0].ioctl = torisa_ioctl; spans[0].irq = irq; init_waitqueue_head(&spans[0].maintq); strcpy(spans[1].name, "TorISA/2"); strcpy(spans[1].desc, "ISA Tormenta Span 2"); spans[1].spanconfig = torisa_spanconfig; spans[1].chanconfig = torisa_chanconfig; spans[1].startup = torisa_startup; spans[1].shutdown = torisa_shutdown; spans[1].rbsbits = torisa_rbsbits; spans[1].maint = torisa_maint; spans[1].open = torisa_open; spans[1].close = torisa_close; spans[1].channels = channels_per_span; spans[1].chans = &chans[channels_per_span]; spans[1].flags = ZT_FLAG_RBS; spans[1].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; spans[1].ioctl = torisa_ioctl; spans[1].irq = irq; if (card_type == TYPE_E1) { spans[0].deflaw = ZT_LAW_ALAW; spans[1].deflaw = ZT_LAW_ALAW; } else { spans[0].deflaw = ZT_LAW_MULAW; spans[1].deflaw = ZT_LAW_MULAW; } init_waitqueue_head(&spans[1].maintq); make_chans(); if (zt_register(&spans[0], prefmaster)) { printk(KERN_ERR "Unable to register span %s\n", spans[0].name); return -EIO; } if (zt_register(&spans[1], 0)) { printk(KERN_ERR "Unable to register span %s\n", spans[1].name); zt_unregister(&spans[0]); return -EIO; } tasklet_init(&torisa_tlet, torisa_tasklet, (long)0); printk("TORISA Loaded\n"); return 0;}static int __init set_tor_base(char *str){ base = simple_strtol(str, NULL, 0); return 1;}__setup("tor=", set_tor_base);static void __exit tor_exit(void){ free_irq(irq, NULL); release_mem_region(base, 4096); if (spans[0].flags & ZT_FLAG_REGISTERED) zt_unregister(&spans[0]); if (spans[1].flags & ZT_FLAG_REGISTERED) zt_unregister(&spans[1]);}MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");MODULE_DESCRIPTION("Tormenta ISA Zapata Telephony Driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif#ifdef LINUX26module_param(prefmaster, int, 0600);module_param(base, long, 0600);module_param(irq, int, 0600);module_param(syncsrc, int, 0600);module_param(debug, int, 0600);#elseMODULE_PARM(prefmaster, "i");MODULE_PARM(base, "i");MODULE_PARM(irq, "i");MODULE_PARM(syncsrc, "i");MODULE_PARM(debug, "i");#endifmodule_init(tor_init);module_exit(tor_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -