74 #include <linux/capability.h>
75 #include <linux/module.h>
77 #include <linux/string.h>
80 #include <linux/hdlcdrv.h>
84 #include <asm/uaccess.h>
94 static const char bc_drvname[] =
"baycom_ser_fdx";
95 static const char bc_drvinfo[] =
KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
96 "baycom_ser_fdx: version 0.10\n";
106 #define RBR(iobase) (iobase+0)
107 #define THR(iobase) (iobase+0)
108 #define IER(iobase) (iobase+1)
109 #define IIR(iobase) (iobase+2)
110 #define FCR(iobase) (iobase+2)
111 #define LCR(iobase) (iobase+3)
112 #define MCR(iobase) (iobase+4)
113 #define LSR(iobase) (iobase+5)
114 #define MSR(iobase) (iobase+6)
115 #define SCR(iobase) (iobase+7)
116 #define DLL(iobase) (iobase+0)
117 #define DLM(iobase) (iobase+1)
119 #define SER12_EXTENT 8
162 unsigned long cur_jiffies =
jiffies;
208 static inline unsigned int hweight16(
unsigned int w)
210 static inline unsigned int hweight8(
unsigned int w)
213 static inline unsigned int hweight16(
unsigned int w)
215 unsigned short res = (w & 0x5555) + ((w >> 1) & 0x5555);
216 res = (res & 0x3333) + ((res >> 2) & 0x3333);
217 res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
218 return (res & 0x00FF) + ((res >> 8) & 0x00FF);
221 static inline unsigned int hweight8(
unsigned int w)
223 unsigned short res = (w & 0x55) + ((w >> 1) & 0x55);
224 res = (res & 0x33) + ((res >> 2) & 0x33);
225 return (res & 0x0F) + ((res >> 4) & 0x0F);
238 timediff = 1000000 + tv->
tv_usec - bc->
modem.ser12.pll_time;
239 while (timediff >= 500000)
241 while (timediff >= bdus2) {
244 bc->
modem.ser12.dcd_time--;
246 if (bc->
modem.shreg & 1) {
247 hdlcdrv_putbits(&bc->
hdrv, (bc->
modem.shreg >> 1) ^ 0xffff);
248 bc->
modem.shreg = 0x10000;
251 bc->
modem.shreg >>= 1;
253 if (bc->
modem.ser12.dcd_time <= 0) {
255 hdlcdrv_setdcd(&bc->
hdrv, (bc->
modem.ser12.dcd_sum0 +
256 bc->
modem.ser12.dcd_sum1 +
257 bc->
modem.ser12.dcd_sum2) < 0);
258 bc->
modem.ser12.dcd_sum2 = bc->
modem.ser12.dcd_sum1;
259 bc->
modem.ser12.dcd_sum1 = bc->
modem.ser12.dcd_sum0;
260 bc->
modem.ser12.dcd_sum0 = 2;
261 bc->
modem.ser12.dcd_time += 120;
263 if (bc->
modem.ser12.last_rxbit != curs) {
264 bc->
modem.ser12.last_rxbit = curs;
265 bc->
modem.shreg |= 0x10000;
268 bc->
modem.ser12.pll_time += bdus8;
270 bc->
modem.ser12.pll_time += 1000000 - bdus8;
272 if (
abs(timediff) > bdus4)
273 bc->
modem.ser12.dcd_sum0 += 4;
275 bc->
modem.ser12.dcd_sum0--;
280 while (bc->
modem.ser12.pll_time >= 1000000)
281 bc->
modem.ser12.pll_time -= 1000000;
291 unsigned char iir, msr;
292 unsigned int txcount = 0;
304 hdlcdrv_setdcd(&bc->
hdrv, !((msr ^ bc->
opt_dcd) & 0x80));
338 hdlcdrv_setdcd(&bc->
hdrv, !((msr ^ bc->
opt_dcd) & 0x80));
342 }
while (!(iir & 1));
343 ser12_rx(dev, bc, &tv, msr & 0x10);
344 if (bc->
modem.ptt && txcount) {
345 if (bc->
modem.ser12.txshreg <= 1) {
346 bc->
modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->
hdrv);
347 if (!hdlcdrv_ptt(&bc->
hdrv)) {
348 ser12_set_divisor(dev, 115200/100/8);
353 bc->
modem.ser12.tx_bit = !(bc->
modem.ser12.tx_bit ^ (bc->
modem.ser12.txshreg & 1));
354 bc->
modem.ser12.txshreg >>= 1;
358 if (!bc->
modem.ptt && txcount) {
360 if (hdlcdrv_ptt(&bc->
hdrv)) {
362 bc->
modem.ser12.txshreg = 1;
376 static const char *uart_str[] = {
377 "unknown",
"8250",
"16450",
"16550",
"16550A"
380 static enum uart ser12_check_uart(
unsigned int iobase)
382 unsigned char b1,b2,b3;
384 enum uart uart_tab[] =
391 b3 =
inb(
MSR(iobase)) & 0xf0;
399 u = uart_tab[(
inb(
IIR(iobase)) >> 6) & 3];
405 if ((b1 != 0x5a) || (b2 != 0xa5))
423 "or irq (2 <= irq <= %d)\n",
427 if (bc->
baud < 300 || bc->
baud > 4800) {
449 "baycom_ser_fdx", dev)) {
460 ser12_set_divisor(dev, 115200/100/8);
471 hdlcdrv_setdcd(&bc->
hdrv, 0);
472 printk(
KERN_INFO "%s: ser_fdx at iobase 0x%lx irq %u baud %u uart %s\n",
479 static int ser12_close(
struct net_device *dev)
510 .drvname = bc_drvname,
511 .drvinfo = bc_drvinfo,
513 .close = ser12_close,
519 static int baycom_setmode(
struct baycom_state *bc,
const char *modestr)
523 if (!
strncmp(modestr,
"ser", 3)) {
525 if (baud >= 3 && baud <= 48)
530 else if (
strchr(modestr,
'+'))
548 bc = netdev_priv(dev);
590 bi.data.dbg.debug1 = bc->
hdrv.ptt_keyed;
609 static int iobase[
NR_PORTS] = { 0x3f8, };
628 static int __init init_baycomserfdx(
void)
647 iobase[
i] = irq[
i] = 0;
651 ifname, iobase[i], irq[i], 0);
655 bc = netdev_priv(dev);
656 if (set_hw && baycom_setmode(bc, mode[i]))
660 baycom_device[
i] =
dev;
668 static void __exit cleanup_baycomserfdx(
void)
694 static int __init baycom_ser_fdx_setup(
char *
str)
696 static unsigned nr_dev;
699 if (nr_dev >= NR_PORTS)
705 iobase[nr_dev] = ints[1];
706 irq[nr_dev] = ints[2];
708 baud[nr_dev] = ints[3];
713 __setup(
"baycom_ser_fdx=", baycom_ser_fdx_setup);