diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /drivers/net/hamradio/baycom_epp.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'drivers/net/hamradio/baycom_epp.c')
-rw-r--r-- | drivers/net/hamradio/baycom_epp.c | 488 |
1 files changed, 236 insertions, 252 deletions
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index d72719e5c..d4191258d 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -3,7 +3,7 @@ /* * baycom_epp.c -- baycom epp radio modem driver. * - * Copyright (C) 1998 + * Copyright (C) 1998-1999 * Thomas Sailer (sailer@ife.ee.ethz.ch) * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,10 @@ * 0.2 21.04.98 Massive rework by Thomas Sailer * Integrated FPGA EPP modem configuration routines * 0.3 11.05.98 Took FPGA config out and moved it into a separate program + * 0.4 26.07.99 Adapted to new lowlevel parport driver interface + * 0.5 03.08.99 adapt to Linus' new __setup/__initcall + * removed some pre-2.2 kernel compatibility cruft + * 0.6 10.08.99 Check if parport can do SPP and is safe to access during interrupt contexts * */ @@ -38,25 +42,13 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> -#include <linux/types.h> -#include <linux/ptrace.h> -#include <linux/socket.h> -#include <linux/sched.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/in.h> +#include <linux/init.h> #include <linux/string.h> +#include <linux/tqueue.h> +#include <linux/fs.h> #include <linux/parport.h> -#include <linux/bitops.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/netdevice.h> +#include <asm/uaccess.h> #include <linux/if_arp.h> -//#include <net/ax25dev.h> -#include <linux/kmod.h> #include <linux/hdlcdrv.h> #include <linux/baycom.h> #include <linux/soundmodem.h> @@ -70,56 +62,6 @@ /* --------------------------------------------------------------------- */ -/* - * currently this module is supposed to support both module styles, i.e. - * the old one present up to about 2.1.9, and the new one functioning - * starting with 2.1.21. The reason is I have a kit allowing to compile - * this module also under 2.0.x which was requested by several people. - * This will go in 2.2 - */ -#include <linux/version.h> - -#if LINUX_VERSION_CODE >= 0x20100 -#include <asm/uaccess.h> -#else -#include <asm/segment.h> -#include <linux/mm.h> - -#undef put_user -#undef get_user - -#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; }) -#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; }) - -extern inline int copy_from_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_READ, from, n); - if (i) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -extern inline int copy_to_user(void *to, const void *from, unsigned long n) -{ - int i = verify_area(VERIFY_WRITE, to, n); - if (i) - return i; - memcpy_tofs(to, from, n); - return 0; -} -#endif - -#if LINUX_VERSION_CODE >= 0x20123 -#include <linux/init.h> -#else -#define __init -#define __initdata -#define __initfunc(x) x -#endif - -/* --------------------------------------------------------------------- */ - #define BAYCOM_DEBUG #define BAYCOM_MAGIC 19730510 @@ -147,19 +89,14 @@ static const char paranoia_str[] = KERN_ERR /* --------------------------------------------------------------------- */ static const char bc_drvname[] = "baycom_epp"; -static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998 Thomas Sailer, HB9JNX/AE4WA\n" -KERN_INFO "baycom_epp: version 0.3 compiled " __TIME__ " " __DATE__ "\n"; +static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-1999 Thomas Sailer, HB9JNX/AE4WA\n" +KERN_INFO "baycom_epp: version 0.5 compiled " __TIME__ " " __DATE__ "\n"; /* --------------------------------------------------------------------- */ #define NR_PORTS 4 -static struct device baycom_device[NR_PORTS]; - -static struct { - const char *mode; - int iobase; -} baycom_ports[NR_PORTS] = { { NULL, 0 }, }; +static struct net_device baycom_device[NR_PORTS]; /* --------------------------------------------------------------------- */ @@ -264,7 +201,8 @@ struct baycom_state { struct { unsigned int intclk; - unsigned int divider; + unsigned int fclk; + unsigned int bps; unsigned int extmodem; unsigned int loopback; } cfg; @@ -433,7 +371,7 @@ static void inline baycom_int_freq(struct baycom_state *bc) * eppconfig_path should be setable via /proc/sys. */ -char eppconfig_path[256] = "/sbin/eppfpga"; +static char eppconfig_path[256] = "/usr/sbin/eppfpga"; static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; @@ -448,9 +386,10 @@ static int exec_eppfpga(void *b) int i; /* set up arguments */ - sprintf(modearg, "%sclk,%smodem,divider=%d%s,extstat", + sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat", bc->cfg.intclk ? "int" : "ext", - bc->cfg.extmodem ? "ext" : "int", bc->cfg.divider, + bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps, + (bc->cfg.fclk + 8 * bc->cfg.bps) / (16 * bc->cfg.bps), bc->cfg.loopback ? ",loopback" : ""); sprintf(portarg, "%ld", bc->pdev->port->base); printk(KERN_DEBUG "%s: %s -s -p %s -m %s\n", bc_drvname, eppconfig_path, portarg, modearg); @@ -655,10 +594,11 @@ static inline unsigned short random_num(void) /* ---------------------------------------------------------------------- */ -static void transmit(struct baycom_state *bc, int cnt, unsigned char stat) +static int transmit(struct baycom_state *bc, int cnt, unsigned char stat) { struct parport *pp = bc->pdev->port; - int i; + unsigned char tmp[128]; + int i, j; if (bc->hdlctx.state == tx_tail && !(stat & EPP_PTTBIT)) bc->hdlctx.state = tx_idle; @@ -666,17 +606,17 @@ static void transmit(struct baycom_state *bc, int cnt, unsigned char stat) if (bc->hdlctx.bufcnt <= 0) encode_hdlc(bc); if (bc->hdlctx.bufcnt <= 0) - return; + return 0; if (!bc->ch_params.fulldup) { if (!(stat & EPP_DCDBIT)) { bc->hdlctx.slotcnt = bc->ch_params.slottime; - return; + return 0; } if ((--bc->hdlctx.slotcnt) > 0) - return; + return 0; bc->hdlctx.slotcnt = bc->ch_params.slottime; if ((random_num() % 256) > bc->ch_params.ppersist) - return; + return 0; } } if (bc->hdlctx.state == tx_idle && bc->hdlctx.bufcnt > 0) { @@ -692,8 +632,13 @@ static void transmit(struct baycom_state *bc, int cnt, unsigned char stat) bc->hdlctx.flags -= i; if (bc->hdlctx.flags <= 0) bc->hdlctx.state = tx_data; - for (; i > 0; i--) - parport_epp_write_data(pp, 0x7e); + memset(tmp, 0x7e, sizeof(tmp)); + while (i > 0) { + j = (i > sizeof(tmp)) ? sizeof(tmp) : i; + if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) + return -1; + i -= j; + } break; case tx_data: @@ -708,8 +653,9 @@ static void transmit(struct baycom_state *bc, int cnt, unsigned char stat) i = min(cnt, bc->hdlctx.bufcnt); bc->hdlctx.bufcnt -= i; cnt -= i; - for (; i > 0; i--) - parport_epp_write_data(pp, *(bc->hdlctx.bufptr)++); + if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0)) + return -1; + bc->hdlctx.bufptr += i; break; case tx_tail: @@ -722,27 +668,38 @@ static void transmit(struct baycom_state *bc, int cnt, unsigned char stat) if (i) { cnt -= i; bc->hdlctx.flags -= i; - for (; i > 0; i--) - parport_epp_write_data(pp, 0x7e); + memset(tmp, 0x7e, sizeof(tmp)); + while (i > 0) { + j = (i > sizeof(tmp)) ? sizeof(tmp) : i; + if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) + return -1; + i -= j; + } break; } default: /* fall through */ if (bc->hdlctx.calibrate <= 0) - return; + return 0; i = min(cnt, bc->hdlctx.calibrate); cnt -= i; bc->hdlctx.calibrate -= i; - for (; i > 0; i--) - parport_epp_write_data(pp, 0); + memset(tmp, 0, sizeof(tmp)); + while (i > 0) { + j = (i > sizeof(tmp)) ? sizeof(tmp) : i; + if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) + return -1; + i -= j; + } break; } } + return 0; } /* ---------------------------------------------------------------------- */ -static void do_rxpacket(struct device *dev) +static void do_rxpacket(struct net_device *dev) { struct baycom_state *bc = (struct baycom_state *)dev->priv; struct sk_buff *skb; @@ -800,57 +757,68 @@ static void do_rxpacket(struct device *dev) goto enditer##j; \ }) -static void receive(struct device *dev, int cnt) +static int receive(struct net_device *dev, int cnt) { struct baycom_state *bc = (struct baycom_state *)dev->priv; struct parport *pp = bc->pdev->port; unsigned int bitbuf, notbitstream, bitstream, numbits, state; - unsigned char ch; + unsigned char tmp[128]; + unsigned char *cp; + int cnt2, ret = 0; numbits = bc->hdlcrx.numbits; state = bc->hdlcrx.state; bitstream = bc->hdlcrx.bitstream; bitbuf = bc->hdlcrx.bitbuf; - for (; cnt > 0; cnt--) { - ch = parport_epp_read_data(pp); - bitstream >>= 8; - bitstream |= ch << 8; - bitbuf >>= 8; - bitbuf |= ch << 8; - numbits += 8; - notbitstream = ~bitstream; - DECODEITERA(0); - DECODEITERA(1); - DECODEITERA(2); - DECODEITERA(3); - DECODEITERA(4); - DECODEITERA(5); - DECODEITERA(6); - DECODEITERA(7); - goto enddec; - DECODEITERB(0); - DECODEITERB(1); - DECODEITERB(2); - DECODEITERB(3); - DECODEITERB(4); - DECODEITERB(5); - DECODEITERB(6); - DECODEITERB(7); - enddec: - while (state && numbits >= 8) { - if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) { - state = 0; - } else { - *(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits); - bc->hdlcrx.bufcnt++; - numbits -= 8; + while (cnt > 0) { + cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt; + cnt -= cnt2; + if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) { + ret = -1; + break; + } + cp = tmp; + for (; cnt2 > 0; cnt2--, cp++) { + bitstream >>= 8; + bitstream |= (*cp) << 8; + bitbuf >>= 8; + bitbuf |= (*cp) << 8; + numbits += 8; + notbitstream = ~bitstream; + DECODEITERA(0); + DECODEITERA(1); + DECODEITERA(2); + DECODEITERA(3); + DECODEITERA(4); + DECODEITERA(5); + DECODEITERA(6); + DECODEITERA(7); + goto enddec; + DECODEITERB(0); + DECODEITERB(1); + DECODEITERB(2); + DECODEITERB(3); + DECODEITERB(4); + DECODEITERB(5); + DECODEITERB(6); + DECODEITERB(7); + enddec: + while (state && numbits >= 8) { + if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) { + state = 0; + } else { + *(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits); + bc->hdlcrx.bufcnt++; + numbits -= 8; + } } } - } + } bc->hdlcrx.numbits = numbits; bc->hdlcrx.state = state; bc->hdlcrx.bitstream = bitstream; bc->hdlcrx.bitbuf = bitbuf; + return ret; } /* --------------------------------------------------------------------- */ @@ -865,11 +833,12 @@ static void receive(struct device *dev, int cnt) #define GETTICK(x) #endif /* __i386__ */ -static void epp_bh(struct device *dev) +static void epp_bh(struct net_device *dev) { struct baycom_state *bc; struct parport *pp; unsigned char stat; + unsigned char tmp[2]; unsigned int time1 = 0, time2 = 0, time3 = 0; int cnt, cnt2; @@ -880,26 +849,40 @@ static void epp_bh(struct device *dev) baycom_int_freq(bc); pp = bc->pdev->port; /* update status */ - bc->stat = stat = parport_epp_read_addr(pp); + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) + goto epptimeout; + bc->stat = stat; bc->debug_vals.last_pllcorr = stat; GETTICK(time1); if (bc->modem == EPP_FPGAEXTSTATUS) { /* get input count */ - parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1); - cnt = parport_epp_read_addr(pp); - cnt |= parport_epp_read_addr(pp) << 8; + tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1; + if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) + goto epptimeout; + if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) + goto epptimeout; + cnt = tmp[0] | (tmp[1] << 8); cnt &= 0x7fff; /* get output count */ - parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2); - cnt2 = parport_epp_read_addr(pp); - cnt2 |= parport_epp_read_addr(pp) << 8; + tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2; + if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) + goto epptimeout; + if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) + goto epptimeout; + cnt2 = tmp[0] | (tmp[1] << 8); cnt2 = 16384 - (cnt2 & 0x7fff); /* return to normal */ - parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE); - transmit(bc, cnt2, stat); + tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE; + if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) + goto epptimeout; + if (transmit(bc, cnt2, stat)) + goto epptimeout; GETTICK(time2); - receive(dev, cnt); - bc->stat = stat = parport_epp_read_addr(pp); + if (receive(dev, cnt)) + goto epptimeout; + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) + goto epptimeout; + bc->stat = stat; } else { /* try to tx */ switch (stat & (EPP_NTAEF|EPP_NTHF)) { @@ -919,7 +902,8 @@ static void epp_bh(struct device *dev) cnt = 2048 - 1025; break; } - transmit(bc, cnt, stat); + if (transmit(bc, cnt, stat)) + goto epptimeout; GETTICK(time2); /* do receiver */ while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) { @@ -936,9 +920,9 @@ static void epp_bh(struct device *dev) cnt = 256; break; } - receive(dev, cnt); - stat = parport_epp_read_addr(pp); - if (parport_epp_check_timeout(pp)) + if (receive(dev, cnt)) + goto epptimeout; + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; } cnt = 0; @@ -947,9 +931,11 @@ static void epp_bh(struct device *dev) else if (bc->bitrate < 100000) cnt = 128; while (cnt > 0 && stat & EPP_NREF) { - receive(dev, 1); + if (receive(dev, 1)) + goto epptimeout; cnt--; - stat = parport_epp_read_addr(pp); + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) + goto epptimeout; } } GETTICK(time3); @@ -957,8 +943,6 @@ static void epp_bh(struct device *dev) bc->debug_vals.mod_cycles = time2 - time1; bc->debug_vals.demod_cycles = time3 - time2; #endif /* BAYCOM_DEBUG */ - if (parport_epp_check_timeout(pp)) - goto epptimeout; queue_task(&bc->run_bh, &tq_timer); return; epptimeout: @@ -970,7 +954,7 @@ static void epp_bh(struct device *dev) * ===================== network driver interface ========================= */ -static int baycom_send_packet(struct sk_buff *skb, struct device *dev) +static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev) { struct baycom_state *bc; @@ -983,7 +967,7 @@ static int baycom_send_packet(struct sk_buff *skb, struct device *dev) /* --------------------------------------------------------------------- */ -static int baycom_set_mac_address(struct device *dev, void *addr) +static int baycom_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *sa = (struct sockaddr *)addr; @@ -994,7 +978,7 @@ static int baycom_set_mac_address(struct device *dev, void *addr) /* --------------------------------------------------------------------- */ -static struct net_device_stats *baycom_get_stats(struct device *dev) +static struct net_device_stats *baycom_get_stats(struct net_device *dev) { struct baycom_state *bc; @@ -1011,7 +995,7 @@ static struct net_device_stats *baycom_get_stats(struct device *dev) static void epp_wakeup(void *handle) { - struct device *dev = (struct device *)handle; + struct net_device *dev = (struct net_device *)handle; struct baycom_state *bc; baycom_paranoia_check_void(dev, "epp_wakeup"); @@ -1032,7 +1016,7 @@ static void epp_wakeup(void *handle) * there is non-reboot way to recover if something goes wrong. */ -static int epp_open(struct device *dev) +static int epp_open(struct net_device *dev) { struct baycom_state *bc; struct parport *pp; @@ -1040,6 +1024,7 @@ static int epp_open(struct device *dev) 0, 0, (void *)(void *)epp_bh, dev }; unsigned int i, j; + unsigned char tmp[128]; unsigned char stat; unsigned long tstart; @@ -1060,6 +1045,11 @@ static int epp_open(struct device *dev) return -ENXIO; } #endif + if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) { + printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n", + bc_drvname, pp->base); + return -EIO; + } memset(&bc->modem, 0, sizeof(bc->modem)); if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup, epp_interrupt, PARPORT_DEV_EXCL, dev))) { @@ -1071,21 +1061,9 @@ static int epp_open(struct device *dev) parport_unregister_device(bc->pdev); return -EBUSY; } - if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) { - printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n", - bc_drvname, pp->base); - parport_release(bc->pdev); - parport_unregister_device(bc->pdev); - return -EIO; - } dev->irq = /*pp->irq*/ 0; bc->run_bh = run_bh; bc->bh_running = 1; - if (pp->modes & PARPORT_MODE_PCECPEPP) { - printk(KERN_INFO "%s: trying to enable EPP mode\n", bc_drvname); - parport_frob_econtrol(pp, 0xe0, 0x80); - } - /* bc->pdev->port->ops->change_mode(bc->pdev->port, PARPORT_MODE_PCEPP); not yet implemented */ bc->modem = EPP_CONVENTIONAL; if (eppconfig(bc)) printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n", bc_drvname); @@ -1093,26 +1071,33 @@ static int epp_open(struct device *dev) bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS; parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we aren't using interrupts */ /* reset the modem */ - parport_epp_write_addr(pp, 0); - parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE); + tmp[0] = 0; + tmp[1] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE; + if (pp->ops->epp_write_addr(pp, tmp, 2, 0) != 2) + goto epptimeout; /* autoprobe baud rate */ tstart = jiffies; i = 0; while ((signed)(jiffies-tstart-HZ/3) < 0) { - stat = parport_epp_read_addr(pp); + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) + goto epptimeout; if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) { schedule(); continue; } - for (j = 0; j < 256; j++) - parport_epp_read_data(pp); + if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128) + goto epptimeout; + if (pp->ops->epp_read_data(pp, tmp, 128, 0) != 128) + goto epptimeout; i += 256; } for (j = 0; j < 256; j++) { - stat = parport_epp_read_addr(pp); + if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) + goto epptimeout; if (!(stat & EPP_NREF)) break; - parport_epp_read_data(pp); + if (pp->ops->epp_read_data(pp, tmp, 1, 0) != 1) + goto epptimeout; i++; } tstart = jiffies - tstart; @@ -1125,7 +1110,9 @@ static int epp_open(struct device *dev) } printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int rate: %d\n", bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2)); - parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/); + tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/; + if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) + goto epptimeout; /* * initialise hdlc variables */ @@ -1143,21 +1130,22 @@ static int epp_open(struct device *dev) MOD_INC_USE_COUNT; return 0; -#if 0 - errreturn: + epptimeout: + printk(KERN_ERR "%s: epp timeout during bitrate probe\n", bc_drvname); + parport_write_control(pp, 0); /* reset the adapter */ parport_release(bc->pdev); parport_unregister_device(bc->pdev); return -EIO; -#endif } /* --------------------------------------------------------------------- */ -static int epp_close(struct device *dev) +static int epp_close(struct net_device *dev) { struct baycom_state *bc; struct parport *pp; struct sk_buff *skb; + unsigned char tmp[1]; baycom_paranoia_check(dev, "epp_close", -EINVAL); if (!dev->start) @@ -1169,7 +1157,8 @@ static int epp_close(struct device *dev) dev->tbusy = 1; run_task_queue(&tq_timer); /* dequeue bottom half */ bc->stat = EPP_DCDBIT; - parport_epp_write_addr(pp, 0); + tmp[0] = 0; + pp->ops->epp_write_addr(pp, tmp, 1, 0); parport_write_control(pp, 0); /* reset the adapter */ parport_release(bc->pdev); parport_unregister_device(bc->pdev); @@ -1200,19 +1189,26 @@ static int baycom_setmode(struct baycom_state *bc, const char *modestr) bc->cfg.loopback = 0; if (strstr(modestr,"loopback")) bc->cfg.loopback = 1; - if ((cp = strstr(modestr,"divider="))) { - bc->cfg.divider = simple_strtoul(cp+8, NULL, 0); - if (bc->cfg.divider < 1) - bc->cfg.divider = 1; - if (bc->cfg.divider > 1023) - bc->cfg.divider = 1023; + if ((cp = strstr(modestr,"fclk="))) { + bc->cfg.fclk = simple_strtoul(cp+5, NULL, 0); + if (bc->cfg.fclk < 1000000) + bc->cfg.fclk = 1000000; + if (bc->cfg.fclk > 25000000) + bc->cfg.fclk = 25000000; + } + if ((cp = strstr(modestr,"bps="))) { + bc->cfg.bps = simple_strtoul(cp+4, NULL, 0); + if (bc->cfg.bps < 1000) + bc->cfg.bps = 1000; + if (bc->cfg.bps > 1500000) + bc->cfg.bps = 1500000; } return 0; } /* --------------------------------------------------------------------- */ -static int baycom_ioctl(struct device *dev, struct ifreq *ifr, int cmd) +static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct baycom_state *bc; struct baycom_ioctl bi; @@ -1316,9 +1312,9 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr, int cmd) break; case HDLCDRVCTL_GETMODE: - sprintf(hi.data.modename, "%sclk,%smodem,divider=%d%s", + sprintf(hi.data.modename, "%sclk,%smodem,fclk=%d,bps=%d%s", bc->cfg.intclk ? "int" : "ext", - bc->cfg.extmodem ? "ext" : "int", bc->cfg.divider, + bc->cfg.extmodem ? "ext" : "int", bc->cfg.fclk, bc->cfg.bps, bc->cfg.loopback ? ",loopback" : ""); break; @@ -1351,7 +1347,7 @@ static int baycom_ioctl(struct device *dev, struct ifreq *ifr, int cmd) * If dev->base_addr == 2, allocate space for the device and return success * (detachable devices only). */ -static int baycom_probe(struct device *dev) +static int baycom_probe(struct net_device *dev) { static char ax25_bcast[AX25_ADDR_LEN] = { 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1 @@ -1415,9 +1411,25 @@ static int baycom_probe(struct device *dev) /* --------------------------------------------------------------------- */ -__initfunc(int baycom_epp_init(void)) +/* + * command line settable parameters + */ +static const char *mode[NR_PORTS] = { "", }; +static int iobase[NR_PORTS] = { 0x378, }; + +MODULE_PARM(mode, "1-" __MODULE_STRING(NR_PORTS) "s"); +MODULE_PARM_DESC(mode, "baycom operating mode"); +MODULE_PARM(iobase, "1-" __MODULE_STRING(NR_PORTS) "i"); +MODULE_PARM_DESC(iobase, "baycom io base address"); + +MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); +MODULE_DESCRIPTION("Baycom epp amateur radio modem driver"); + +/* --------------------------------------------------------------------- */ + +static int __init init_baycomepp(void) { - struct device *dev; + struct net_device *dev; int i, found = 0; char set_hw = 1; struct baycom_state *bc; @@ -1428,11 +1440,11 @@ __initfunc(int baycom_epp_init(void)) */ for (i = 0; i < NR_PORTS; i++) { dev = baycom_device+i; - if (!baycom_ports[i].mode) + if (!mode[i]) set_hw = 0; if (!set_hw) - baycom_ports[i].iobase = 0; - memset(dev, 0, sizeof(struct device)); + iobase[i] = 0; + memset(dev, 0, sizeof(struct net_device)); if (!(bc = dev->priv = kmalloc(sizeof(struct baycom_state), GFP_KERNEL))) return -ENOMEM; /* @@ -1441,6 +1453,8 @@ __initfunc(int baycom_epp_init(void)) memset(bc, 0, sizeof(struct baycom_state)); bc->magic = BAYCOM_MAGIC; sprintf(bc->ifname, "bce%d", i); + bc->cfg.fclk = 19666600; + bc->cfg.bps = 9600; /* * initialize part of the device struct */ @@ -1449,7 +1463,7 @@ __initfunc(int baycom_epp_init(void)) dev->init = baycom_probe; dev->start = 0; dev->tbusy = 1; - dev->base_addr = baycom_ports[i].iobase; + dev->base_addr = iobase[i]; dev->irq = 0; dev->dma = 0; if (register_netdev(dev)) { @@ -1457,7 +1471,7 @@ __initfunc(int baycom_epp_init(void)) kfree(dev->priv); return -ENXIO; } - if (set_hw && baycom_setmode(bc, baycom_ports[i].mode)) + if (set_hw && baycom_setmode(bc, mode[i])) set_hw = 0; found++; } @@ -1466,46 +1480,9 @@ __initfunc(int baycom_epp_init(void)) return 0; } -/* --------------------------------------------------------------------- */ - -#ifdef MODULE - -/* - * command line settable parameters - */ -static const char *mode[NR_PORTS] = { "epp", }; -static int iobase[NR_PORTS] = { 0x378, }; - -#if LINUX_VERSION_CODE >= 0x20115 - -MODULE_PARM(mode, "s"); -MODULE_PARM_DESC(mode, "baycom operating mode; epp"); -MODULE_PARM(iobase, "i"); -MODULE_PARM_DESC(iobase, "baycom io base address"); - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("Baycom epp amateur radio modem driver"); - -#endif - -__initfunc(int init_module(void)) -{ - int i; - - for (i = 0; (i < NR_PORTS) && (mode[i]); i++) { - baycom_ports[i].mode = mode[i]; - baycom_ports[i].iobase = iobase[i]; - } - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; - return baycom_epp_init(); -} - -/* --------------------------------------------------------------------- */ - -void cleanup_module(void) +static void __exit cleanup_baycomepp(void) { - struct device *dev; + struct net_device *dev; struct baycom_state *bc; int i; @@ -1522,28 +1499,35 @@ void cleanup_module(void) } } -#else /* MODULE */ +module_init(init_baycomepp); +module_exit(cleanup_baycomepp); + /* --------------------------------------------------------------------- */ + +#ifndef MODULE + /* - * format: baycom=io,mode - * mode: epp + * format: baycom_epp=io,mode + * mode: fpga config options */ -__initfunc(void baycom_epp_setup(char *str, int *ints)) +static int __init baycom_epp_setup(char *str) { - int i; + static unsigned __initdata nr_dev = 0; + int ints[2]; - for (i = 0; (i < NR_PORTS) && (baycom_ports[i].mode); i++); - if ((i >= NR_PORTS) || (ints[0] < 1)) { - printk(KERN_INFO "%s: too many or invalid interface " - "specifications\n", bc_drvname); - return; - } - baycom_ports[i].mode = str; - baycom_ports[i].iobase = ints[1]; - if (i < NR_PORTS-1) - baycom_ports[i+1].mode = NULL; + if (nr_dev >= NR_PORTS) + return 0; + str = get_options(str, 2, ints); + if (ints[0] < 1) + return 0; + mode[nr_dev] = str; + iobase[nr_dev] = ints[1]; + nr_dev++; + return 1; } +__setup("baycom_epp=", baycom_epp_setup); + #endif /* MODULE */ /* --------------------------------------------------------------------- */ |