64 #include <linux/capability.h>
65 #include <linux/module.h>
67 #include <linux/string.h>
70 #include <asm/uaccess.h>
72 #include <linux/hdlcdrv.h>
82 static const char bc_drvname[] =
"baycom_ser_hdx";
83 static const char bc_drvinfo[] =
KERN_INFO "baycom_ser_hdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
84 "baycom_ser_hdx: version 0.10\n";
94 #define RBR(iobase) (iobase+0)
95 #define THR(iobase) (iobase+0)
96 #define IER(iobase) (iobase+1)
97 #define IIR(iobase) (iobase+2)
98 #define FCR(iobase) (iobase+2)
99 #define LCR(iobase) (iobase+3)
100 #define MCR(iobase) (iobase+4)
101 #define LSR(iobase) (iobase+5)
102 #define MSR(iobase) (iobase+6)
103 #define SCR(iobase) (iobase+7)
104 #define DLL(iobase) (iobase+0)
105 #define DLM(iobase) (iobase+1)
107 #define SER12_EXTENT 8
123 struct modem_state_ser12 {
151 unsigned long cur_jiffies =
jiffies;
197 #define SER12_ARB_DIVIDER(bc) (bc->opt_dcd ? 24 : 36)
199 #define SER12_DCD_INTERVAL(bc) (bc->opt_dcd ? 12 : 240)
204 ser12_set_divisor(dev, 12);
210 if (bc->
modem.shreg <= 1)
211 bc->
modem.shreg = 0x10000 | hdlcdrv_getbits(&bc->
hdrv);
212 bc->
modem.ser12.tx_bit = !(bc->
modem.ser12.tx_bit ^
213 (bc->
modem.shreg & 1));
214 bc->
modem.shreg >>= 1;
226 hdlcdrv_channelbit(&bc->
hdrv, cur_s);
227 bc->
modem.ser12.dcd_shreg = (bc->
modem.ser12.dcd_shreg << 1) |
228 (cur_s != bc->
modem.ser12.last_sample);
229 bc->
modem.ser12.last_sample = cur_s;
230 if(bc->
modem.ser12.dcd_shreg & 1) {
232 unsigned int dcdspos, dcdsneg;
234 dcdspos = dcdsneg = 0;
235 dcdspos += ((bc->
modem.ser12.dcd_shreg >> 1) & 1);
236 if (!(bc->
modem.ser12.dcd_shreg & 0x7ffffffe))
238 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 2) & 1);
239 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 3) & 1);
240 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 4) & 1);
242 bc->
modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
244 bc->
modem.ser12.dcd_sum0--;
246 if(!bc->
modem.ser12.dcd_time) {
247 hdlcdrv_setdcd(&bc->
hdrv, (bc->
modem.ser12.dcd_sum0 +
248 bc->
modem.ser12.dcd_sum1 +
249 bc->
modem.ser12.dcd_sum2) < 0);
250 bc->
modem.ser12.dcd_sum2 = bc->
modem.ser12.dcd_sum1;
251 bc->
modem.ser12.dcd_sum1 = bc->
modem.ser12.dcd_sum0;
253 bc->
modem.ser12.dcd_sum0 = 2;
256 bc->
modem.ser12.dcd_time--;
261 if (bc->
modem.ser12.interm_sample) {
265 ser12_set_divisor(dev, 4);
270 switch (bc->
modem.ser12.dcd_shreg & 7) {
272 ser12_set_divisor(dev, 5);
278 ser12_set_divisor(dev, 3);
284 ser12_set_divisor(dev, 4);
287 bc->
modem.shreg >>= 1;
288 if (bc->
modem.ser12.last_sample ==
289 bc->
modem.ser12.last_rxbit)
290 bc->
modem.shreg |= 0x10000;
291 bc->
modem.ser12.last_rxbit =
292 bc->
modem.ser12.last_sample;
294 if (++bc->
modem.ser12.interm_sample >= 3)
295 bc->
modem.ser12.interm_sample = 0;
299 if (bc->
modem.ser12.dcd_shreg & 1) {
300 unsigned int dcdspos, dcdsneg;
302 dcdspos = dcdsneg = 0;
303 dcdspos += ((bc->
modem.ser12.dcd_shreg >> 1) & 1);
304 dcdspos += (!(bc->
modem.ser12.dcd_shreg & 0x7ffffffe))
306 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 2) & 1);
307 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 3) & 1);
308 dcdsneg += ((bc->
modem.ser12.dcd_shreg >> 4) & 1);
310 bc->
modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
316 if (bc->
modem.ser12.interm_sample) {
320 ser12_set_divisor(dev, 6);
325 switch (bc->
modem.ser12.dcd_shreg & 3) {
327 ser12_set_divisor(dev, 7);
333 ser12_set_divisor(dev, 5);
339 ser12_set_divisor(dev, 6);
342 bc->
modem.shreg >>= 1;
343 if (bc->
modem.ser12.last_sample ==
344 bc->
modem.ser12.last_rxbit)
345 bc->
modem.shreg |= 0x10000;
346 bc->
modem.ser12.last_rxbit =
347 bc->
modem.ser12.last_sample;
349 bc->
modem.ser12.interm_sample = !bc->
modem.ser12.interm_sample;
353 bc->
modem.ser12.dcd_sum0 -= (bc->
modem.ser12.dcd_shreg & 1);
356 if (bc->
modem.shreg & 1) {
357 hdlcdrv_putbits(&bc->
hdrv, bc->
modem.shreg >> 1);
358 bc->
modem.shreg = 0x10000;
360 if(!bc->
modem.ser12.dcd_time) {
364 hdlcdrv_setdcd(&bc->
hdrv, (bc->
modem.ser12.dcd_sum0 +
365 bc->
modem.ser12.dcd_sum1 +
366 bc->
modem.ser12.dcd_sum2) < 0);
367 bc->
modem.ser12.dcd_sum2 = bc->
modem.ser12.dcd_sum1;
368 bc->
modem.ser12.dcd_sum1 = bc->
modem.ser12.dcd_sum0;
370 bc->
modem.ser12.dcd_sum0 = 2;
373 bc->
modem.ser12.dcd_time--;
404 if (hdlcdrv_ptt(&bc->
hdrv))
408 bc->
modem.arb_divider--;
418 }
while (!(iir & 1));
419 if (bc->
modem.arb_divider <= 0) {
435 static const char *uart_str[] = {
436 "unknown",
"8250",
"16450",
"16550",
"16550A"
439 static enum uart ser12_check_uart(
unsigned int iobase)
441 unsigned char b1,b2,b3;
443 enum uart uart_tab[] =
450 b3 =
inb(
MSR(iobase)) & 0xf0;
458 u = uart_tab[(
inb(
IIR(iobase)) >> 6) & 3];
464 if ((b1 != 0x5a) || (b2 != 0xa5))
480 dev->
irq < 2 || dev->
irq > 15)
485 bc->
hdrv.par.bitrate = 1200;
494 "baycom_ser12", dev)) {
507 ser12_set_divisor(dev, bc->
opt_dcd ? 6 : 4);
515 static int ser12_close(
struct net_device *dev)
546 .drvname = bc_drvname,
547 .drvinfo = bc_drvinfo,
549 .close = ser12_close,
555 static int baycom_setmode(
struct baycom_state *bc,
const char *modestr)
559 else if (
strchr(modestr,
'+'))
561 else if (
strchr(modestr,
'@'))
579 bc = netdev_priv(dev);
621 bi.data.dbg.debug1 = bc->
hdrv.ptt_keyed;
640 static int iobase[
NR_PORTS] = { 0x3f8, };
656 static int __init init_baycomserhdx(
void)
675 iobase[
i] = irq[
i] = 0;
679 ifname, iobase[i], irq[i], 0);
683 bc = netdev_priv(dev);
684 if (set_hw && baycom_setmode(bc, mode[i]))
687 baycom_device[
i] =
dev;
695 static void __exit cleanup_baycomserhdx(
void)
723 static int __init baycom_ser_hdx_setup(
char *
str)
725 static unsigned nr_dev;
728 if (nr_dev >= NR_PORTS)
734 iobase[nr_dev] = ints[1];
735 irq[nr_dev] = ints[2];
740 __setup(
"baycom_ser_hdx=", baycom_ser_hdx_setup);