0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 #include <linux/capability.h>
0060 #include <linux/module.h>
0061 #include <linux/ioport.h>
0062 #include <linux/string.h>
0063 #include <linux/init.h>
0064 #include <linux/interrupt.h>
0065 #include <linux/hdlcdrv.h>
0066 #include <linux/baycom.h>
0067 #include <linux/jiffies.h>
0068 #include <linux/time64.h>
0069
0070 #include <linux/uaccess.h>
0071 #include <asm/io.h>
0072 #include <asm/irq.h>
0073
0074
0075
0076 #define BAYCOM_DEBUG
0077
0078
0079
0080 static const char bc_drvname[] = "baycom_ser_fdx";
0081 static const char bc_drvinfo[] = KERN_INFO "baycom_ser_fdx: (C) 1996-2000 Thomas Sailer, HB9JNX/AE4WA\n"
0082 "baycom_ser_fdx: version 0.10\n";
0083
0084
0085
0086 #define NR_PORTS 4
0087
0088 static struct net_device *baycom_device[NR_PORTS];
0089
0090
0091
0092 #define RBR(iobase) (iobase+0)
0093 #define THR(iobase) (iobase+0)
0094 #define IER(iobase) (iobase+1)
0095 #define IIR(iobase) (iobase+2)
0096 #define FCR(iobase) (iobase+2)
0097 #define LCR(iobase) (iobase+3)
0098 #define MCR(iobase) (iobase+4)
0099 #define LSR(iobase) (iobase+5)
0100 #define MSR(iobase) (iobase+6)
0101 #define SCR(iobase) (iobase+7)
0102 #define DLL(iobase) (iobase+0)
0103 #define DLM(iobase) (iobase+1)
0104
0105 #define SER12_EXTENT 8
0106
0107
0108
0109
0110
0111
0112 struct baycom_state {
0113 struct hdlcdrv_state hdrv;
0114
0115 unsigned int baud, baud_us, baud_arbdiv, baud_uartdiv, baud_dcdtimeout;
0116 int opt_dcd;
0117
0118 struct modem_state {
0119 unsigned char flags;
0120 unsigned char ptt;
0121 unsigned int shreg;
0122 struct modem_state_ser12 {
0123 unsigned char tx_bit;
0124 unsigned char last_rxbit;
0125 int dcd_sum0, dcd_sum1, dcd_sum2;
0126 int dcd_time;
0127 unsigned int pll_time;
0128 unsigned int txshreg;
0129 } ser12;
0130 } modem;
0131
0132 #ifdef BAYCOM_DEBUG
0133 struct debug_vals {
0134 unsigned long last_jiffies;
0135 unsigned cur_intcnt;
0136 unsigned last_intcnt;
0137 int cur_pllcorr;
0138 int last_pllcorr;
0139 } debug_vals;
0140 #endif
0141 };
0142
0143
0144
0145 static inline void baycom_int_freq(struct baycom_state *bc)
0146 {
0147 #ifdef BAYCOM_DEBUG
0148 unsigned long cur_jiffies = jiffies;
0149
0150
0151
0152 bc->debug_vals.cur_intcnt++;
0153 if (time_after_eq(cur_jiffies, bc->debug_vals.last_jiffies + HZ)) {
0154 bc->debug_vals.last_jiffies = cur_jiffies;
0155 bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
0156 bc->debug_vals.cur_intcnt = 0;
0157 bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
0158 bc->debug_vals.cur_pllcorr = 0;
0159 }
0160 #endif
0161 }
0162
0163
0164
0165
0166
0167
0168
0169
0170 static inline void ser12_set_divisor(struct net_device *dev,
0171 unsigned int divisor)
0172 {
0173 outb(0x81, LCR(dev->base_addr));
0174 outb(divisor, DLL(dev->base_addr));
0175 outb(divisor >> 8, DLM(dev->base_addr));
0176 outb(0x01, LCR(dev->base_addr));
0177
0178
0179
0180
0181
0182 outb(0x00, THR(dev->base_addr));
0183
0184
0185
0186
0187
0188
0189 }
0190
0191 static __inline__ void ser12_rx(struct net_device *dev, struct baycom_state *bc, struct timespec64 *ts, unsigned char curs)
0192 {
0193 int timediff;
0194 int bdus8 = bc->baud_us >> 3;
0195 int bdus4 = bc->baud_us >> 2;
0196 int bdus2 = bc->baud_us >> 1;
0197
0198 timediff = 1000000 + ts->tv_nsec / NSEC_PER_USEC -
0199 bc->modem.ser12.pll_time;
0200 while (timediff >= 500000)
0201 timediff -= 1000000;
0202 while (timediff >= bdus2) {
0203 timediff -= bc->baud_us;
0204 bc->modem.ser12.pll_time += bc->baud_us;
0205 bc->modem.ser12.dcd_time--;
0206
0207 if (bc->modem.shreg & 1) {
0208 hdlcdrv_putbits(&bc->hdrv, (bc->modem.shreg >> 1) ^ 0xffff);
0209 bc->modem.shreg = 0x10000;
0210 }
0211
0212 bc->modem.shreg >>= 1;
0213 }
0214 if (bc->modem.ser12.dcd_time <= 0) {
0215 if (!bc->opt_dcd)
0216 hdlcdrv_setdcd(&bc->hdrv, (bc->modem.ser12.dcd_sum0 +
0217 bc->modem.ser12.dcd_sum1 +
0218 bc->modem.ser12.dcd_sum2) < 0);
0219 bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
0220 bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
0221 bc->modem.ser12.dcd_sum0 = 2;
0222 bc->modem.ser12.dcd_time += 120;
0223 }
0224 if (bc->modem.ser12.last_rxbit != curs) {
0225 bc->modem.ser12.last_rxbit = curs;
0226 bc->modem.shreg |= 0x10000;
0227
0228 if (timediff > 0)
0229 bc->modem.ser12.pll_time += bdus8;
0230 else
0231 bc->modem.ser12.pll_time += 1000000 - bdus8;
0232
0233 if (abs(timediff) > bdus4)
0234 bc->modem.ser12.dcd_sum0 += 4;
0235 else
0236 bc->modem.ser12.dcd_sum0--;
0237 #ifdef BAYCOM_DEBUG
0238 bc->debug_vals.cur_pllcorr = timediff;
0239 #endif
0240 }
0241 while (bc->modem.ser12.pll_time >= 1000000)
0242 bc->modem.ser12.pll_time -= 1000000;
0243 }
0244
0245
0246
0247 static irqreturn_t ser12_interrupt(int irq, void *dev_id)
0248 {
0249 struct net_device *dev = (struct net_device *)dev_id;
0250 struct baycom_state *bc = netdev_priv(dev);
0251 struct timespec64 ts;
0252 unsigned char iir, msr;
0253 unsigned int txcount = 0;
0254
0255 if (!bc || bc->hdrv.magic != HDLCDRV_MAGIC)
0256 return IRQ_NONE;
0257
0258 if ((iir = inb(IIR(dev->base_addr))) & 1)
0259 return IRQ_NONE;
0260
0261 ktime_get_ts64(&ts);
0262 msr = inb(MSR(dev->base_addr));
0263
0264 if ((msr & 8) && bc->opt_dcd)
0265 hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));
0266 do {
0267 switch (iir & 6) {
0268 case 6:
0269 inb(LSR(dev->base_addr));
0270 break;
0271
0272 case 4:
0273 inb(RBR(dev->base_addr));
0274 break;
0275
0276 case 2:
0277
0278
0279
0280
0281
0282 outb(0x00, THR(dev->base_addr));
0283 baycom_int_freq(bc);
0284 txcount++;
0285
0286
0287
0288
0289 if (bc->modem.ptt)
0290 outb(0x0e | (!!bc->modem.ser12.tx_bit), MCR(dev->base_addr));
0291 else
0292 outb(0x0d, MCR(dev->base_addr));
0293 break;
0294
0295 default:
0296 msr = inb(MSR(dev->base_addr));
0297
0298 if ((msr & 8) && bc->opt_dcd)
0299 hdlcdrv_setdcd(&bc->hdrv, !((msr ^ bc->opt_dcd) & 0x80));
0300 break;
0301 }
0302 iir = inb(IIR(dev->base_addr));
0303 } while (!(iir & 1));
0304 ser12_rx(dev, bc, &ts, msr & 0x10);
0305 if (bc->modem.ptt && txcount) {
0306 if (bc->modem.ser12.txshreg <= 1) {
0307 bc->modem.ser12.txshreg = 0x10000 | hdlcdrv_getbits(&bc->hdrv);
0308 if (!hdlcdrv_ptt(&bc->hdrv)) {
0309 ser12_set_divisor(dev, 115200/100/8);
0310 bc->modem.ptt = 0;
0311 goto end_transmit;
0312 }
0313 }
0314 bc->modem.ser12.tx_bit = !(bc->modem.ser12.tx_bit ^ (bc->modem.ser12.txshreg & 1));
0315 bc->modem.ser12.txshreg >>= 1;
0316 }
0317 end_transmit:
0318 local_irq_enable();
0319 if (!bc->modem.ptt && txcount) {
0320 hdlcdrv_arbitrate(dev, &bc->hdrv);
0321 if (hdlcdrv_ptt(&bc->hdrv)) {
0322 ser12_set_divisor(dev, bc->baud_uartdiv);
0323 bc->modem.ser12.txshreg = 1;
0324 bc->modem.ptt = 1;
0325 }
0326 }
0327 hdlcdrv_transmitter(dev, &bc->hdrv);
0328 hdlcdrv_receiver(dev, &bc->hdrv);
0329 local_irq_disable();
0330 return IRQ_HANDLED;
0331 }
0332
0333
0334
0335 enum uart { c_uart_unknown, c_uart_8250,
0336 c_uart_16450, c_uart_16550, c_uart_16550A};
0337 static const char *uart_str[] = {
0338 "unknown", "8250", "16450", "16550", "16550A"
0339 };
0340
0341 static enum uart ser12_check_uart(unsigned int iobase)
0342 {
0343 unsigned char b1,b2,b3;
0344 enum uart u;
0345 enum uart uart_tab[] =
0346 { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
0347
0348 b1 = inb(MCR(iobase));
0349 outb(b1 | 0x10, MCR(iobase));
0350 b2 = inb(MSR(iobase));
0351 outb(0x1a, MCR(iobase));
0352 b3 = inb(MSR(iobase)) & 0xf0;
0353 outb(b1, MCR(iobase));
0354 outb(b2, MSR(iobase));
0355 if (b3 != 0x90)
0356 return c_uart_unknown;
0357 inb(RBR(iobase));
0358 inb(RBR(iobase));
0359 outb(0x01, FCR(iobase));
0360 u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
0361 if (u == c_uart_16450) {
0362 outb(0x5a, SCR(iobase));
0363 b1 = inb(SCR(iobase));
0364 outb(0xa5, SCR(iobase));
0365 b2 = inb(SCR(iobase));
0366 if ((b1 != 0x5a) || (b2 != 0xa5))
0367 u = c_uart_8250;
0368 }
0369 return u;
0370 }
0371
0372
0373
0374 static int ser12_open(struct net_device *dev)
0375 {
0376 struct baycom_state *bc = netdev_priv(dev);
0377 enum uart u;
0378
0379 if (!dev || !bc)
0380 return -ENXIO;
0381 if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
0382 dev->irq < 2 || dev->irq > nr_irqs) {
0383 printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
0384 "or irq (2 <= irq <= %d)\n",
0385 0xffff-SER12_EXTENT, nr_irqs);
0386 return -ENXIO;
0387 }
0388 if (bc->baud < 300 || bc->baud > 4800) {
0389 printk(KERN_INFO "baycom_ser_fdx: invalid baudrate "
0390 "(300...4800)\n");
0391 return -EINVAL;
0392 }
0393 if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser_fdx")) {
0394 printk(KERN_WARNING "BAYCOM_SER_FSX: I/O port 0x%04lx busy\n",
0395 dev->base_addr);
0396 return -EACCES;
0397 }
0398 memset(&bc->modem, 0, sizeof(bc->modem));
0399 bc->hdrv.par.bitrate = bc->baud;
0400 bc->baud_us = 1000000/bc->baud;
0401 bc->baud_uartdiv = (115200/8)/bc->baud;
0402 if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown){
0403 release_region(dev->base_addr, SER12_EXTENT);
0404 return -EIO;
0405 }
0406 outb(0, FCR(dev->base_addr));
0407 outb(0x0d, MCR(dev->base_addr));
0408 outb(0, IER(dev->base_addr));
0409 if (request_irq(dev->irq, ser12_interrupt, IRQF_SHARED,
0410 "baycom_ser_fdx", dev)) {
0411 release_region(dev->base_addr, SER12_EXTENT);
0412 return -EBUSY;
0413 }
0414
0415
0416
0417
0418
0419
0420
0421 ser12_set_divisor(dev, 115200/100/8);
0422
0423
0424
0425 outb(0x0a, IER(dev->base_addr));
0426
0427
0428
0429
0430
0431 outb(0x00, THR(dev->base_addr));
0432 hdlcdrv_setdcd(&bc->hdrv, 0);
0433 printk(KERN_INFO "%s: ser_fdx at iobase 0x%lx irq %u baud %u uart %s\n",
0434 bc_drvname, dev->base_addr, dev->irq, bc->baud, uart_str[u]);
0435 return 0;
0436 }
0437
0438
0439
0440 static int ser12_close(struct net_device *dev)
0441 {
0442 struct baycom_state *bc = netdev_priv(dev);
0443
0444 if (!dev || !bc)
0445 return -EINVAL;
0446
0447
0448
0449 outb(0, IER(dev->base_addr));
0450 outb(1, MCR(dev->base_addr));
0451 free_irq(dev->irq, dev);
0452 release_region(dev->base_addr, SER12_EXTENT);
0453 printk(KERN_INFO "%s: close ser_fdx at iobase 0x%lx irq %u\n",
0454 bc_drvname, dev->base_addr, dev->irq);
0455 return 0;
0456 }
0457
0458
0459
0460
0461
0462
0463
0464
0465 static int baycom_ioctl(struct net_device *dev, void __user *data,
0466 struct hdlcdrv_ioctl *hi, int cmd);
0467
0468
0469
0470 static const struct hdlcdrv_ops ser12_ops = {
0471 .drvname = bc_drvname,
0472 .drvinfo = bc_drvinfo,
0473 .open = ser12_open,
0474 .close = ser12_close,
0475 .ioctl = baycom_ioctl,
0476 };
0477
0478
0479
0480 static int baycom_setmode(struct baycom_state *bc, const char *modestr)
0481 {
0482 unsigned int baud;
0483
0484 if (!strncmp(modestr, "ser", 3)) {
0485 baud = simple_strtoul(modestr+3, NULL, 10);
0486 if (baud >= 3 && baud <= 48)
0487 bc->baud = baud*100;
0488 }
0489 if (strchr(modestr, '*'))
0490 bc->opt_dcd = 0;
0491 else if (strchr(modestr, '+'))
0492 bc->opt_dcd = -1;
0493 else
0494 bc->opt_dcd = 1;
0495 return 0;
0496 }
0497
0498
0499
0500 static int baycom_ioctl(struct net_device *dev, void __user *data,
0501 struct hdlcdrv_ioctl *hi, int cmd)
0502 {
0503 struct baycom_state *bc;
0504 struct baycom_ioctl bi;
0505
0506 if (!dev)
0507 return -EINVAL;
0508
0509 bc = netdev_priv(dev);
0510 BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
0511
0512 if (cmd != SIOCDEVPRIVATE)
0513 return -ENOIOCTLCMD;
0514 switch (hi->cmd) {
0515 default:
0516 break;
0517
0518 case HDLCDRVCTL_GETMODE:
0519 sprintf(hi->data.modename, "ser%u", bc->baud / 100);
0520 if (bc->opt_dcd <= 0)
0521 strcat(hi->data.modename, (!bc->opt_dcd) ? "*" : "+");
0522 if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))
0523 return -EFAULT;
0524 return 0;
0525
0526 case HDLCDRVCTL_SETMODE:
0527 if (netif_running(dev) || !capable(CAP_NET_ADMIN))
0528 return -EACCES;
0529 hi->data.modename[sizeof(hi->data.modename)-1] = '\0';
0530 return baycom_setmode(bc, hi->data.modename);
0531
0532 case HDLCDRVCTL_MODELIST:
0533 strcpy(hi->data.modename, "ser12,ser3,ser24");
0534 if (copy_to_user(data, hi, sizeof(struct hdlcdrv_ioctl)))
0535 return -EFAULT;
0536 return 0;
0537
0538 case HDLCDRVCTL_MODEMPARMASK:
0539 return HDLCDRV_PARMASK_IOBASE | HDLCDRV_PARMASK_IRQ;
0540
0541 }
0542
0543 if (copy_from_user(&bi, data, sizeof(bi)))
0544 return -EFAULT;
0545 switch (bi.cmd) {
0546 default:
0547 return -ENOIOCTLCMD;
0548
0549 #ifdef BAYCOM_DEBUG
0550 case BAYCOMCTL_GETDEBUG:
0551 bi.data.dbg.debug1 = bc->hdrv.ptt_keyed;
0552 bi.data.dbg.debug2 = bc->debug_vals.last_intcnt;
0553 bi.data.dbg.debug3 = bc->debug_vals.last_pllcorr;
0554 break;
0555 #endif
0556
0557 }
0558 if (copy_to_user(data, &bi, sizeof(bi)))
0559 return -EFAULT;
0560 return 0;
0561
0562 }
0563
0564
0565
0566
0567
0568
0569 static char *mode[NR_PORTS] = { "ser12*", };
0570 static int iobase[NR_PORTS] = { 0x3f8, };
0571 static int irq[NR_PORTS] = { 4, };
0572 static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 };
0573
0574 module_param_array(mode, charp, NULL, 0);
0575 MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");
0576 module_param_hw_array(iobase, int, ioport, NULL, 0);
0577 MODULE_PARM_DESC(iobase, "baycom io base address");
0578 module_param_hw_array(irq, int, irq, NULL, 0);
0579 MODULE_PARM_DESC(irq, "baycom irq number");
0580 module_param_array(baud, int, NULL, 0);
0581 MODULE_PARM_DESC(baud, "baycom baud rate (300 to 4800)");
0582
0583 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
0584 MODULE_DESCRIPTION("Baycom ser12 full duplex amateur radio modem driver");
0585 MODULE_LICENSE("GPL");
0586
0587
0588
0589 static int __init init_baycomserfdx(void)
0590 {
0591 int i, found = 0;
0592 char set_hw = 1;
0593
0594 printk(bc_drvinfo);
0595
0596
0597
0598 for (i = 0; i < NR_PORTS; i++) {
0599 struct net_device *dev;
0600 struct baycom_state *bc;
0601 char ifname[IFNAMSIZ];
0602
0603 sprintf(ifname, "bcsf%d", i);
0604
0605 if (!mode[i])
0606 set_hw = 0;
0607 if (!set_hw)
0608 iobase[i] = irq[i] = 0;
0609
0610 dev = hdlcdrv_register(&ser12_ops,
0611 sizeof(struct baycom_state),
0612 ifname, iobase[i], irq[i], 0);
0613 if (IS_ERR(dev))
0614 break;
0615
0616 bc = netdev_priv(dev);
0617 if (set_hw && baycom_setmode(bc, mode[i]))
0618 set_hw = 0;
0619 bc->baud = baud[i];
0620 found++;
0621 baycom_device[i] = dev;
0622 }
0623
0624 if (!found)
0625 return -ENXIO;
0626 return 0;
0627 }
0628
0629 static void __exit cleanup_baycomserfdx(void)
0630 {
0631 int i;
0632
0633 for(i = 0; i < NR_PORTS; i++) {
0634 struct net_device *dev = baycom_device[i];
0635 if (dev)
0636 hdlcdrv_unregister(dev);
0637 }
0638 }
0639
0640 module_init(init_baycomserfdx);
0641 module_exit(cleanup_baycomserfdx);
0642
0643
0644
0645 #ifndef MODULE
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655 static int __init baycom_ser_fdx_setup(char *str)
0656 {
0657 static unsigned nr_dev;
0658 int ints[4];
0659
0660 if (nr_dev >= NR_PORTS)
0661 return 0;
0662 str = get_options(str, 4, ints);
0663 if (ints[0] < 2)
0664 return 0;
0665 mode[nr_dev] = str;
0666 iobase[nr_dev] = ints[1];
0667 irq[nr_dev] = ints[2];
0668 if (ints[0] >= 3)
0669 baud[nr_dev] = ints[3];
0670 nr_dev++;
0671 return 1;
0672 }
0673
0674 __setup("baycom_ser_fdx=", baycom_ser_fdx_setup);
0675
0676 #endif
0677