summaryrefslogtreecommitdiffstats
path: root/drivers/net/hamradio/baycom_epp.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /drivers/net/hamradio/baycom_epp.c
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'drivers/net/hamradio/baycom_epp.c')
-rw-r--r--drivers/net/hamradio/baycom_epp.c488
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 */
/* --------------------------------------------------------------------- */