patch-2.3.12 linux/drivers/net/hamradio/baycom_epp.c
Next file: linux/drivers/parport/BUGS-parport
Previous file: linux/drivers/misc/parport_share.c
Back to the patch index
Back to the overall index
- Lines: 536
- Date:
Mon Jul 26 14:11:37 1999
- Orig file:
v2.3.11/linux/drivers/net/hamradio/baycom_epp.c
- Orig date:
Fri Mar 26 13:57:41 1999
diff -u --recursive --new-file v2.3.11/linux/drivers/net/hamradio/baycom_epp.c linux/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,7 @@
* 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
*
*/
@@ -148,7 +149,7 @@
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";
+KERN_INFO "baycom_epp: version 0.4 compiled " __TIME__ " " __DATE__ "\n";
/* --------------------------------------------------------------------- */
@@ -264,7 +265,8 @@
struct {
unsigned int intclk;
- unsigned int divider;
+ unsigned int fclk;
+ unsigned int bps;
unsigned int extmodem;
unsigned int loopback;
} cfg;
@@ -433,7 +435,7 @@
* eppconfig_path should be setable via /proc/sys.
*/
-char eppconfig_path[256] = "/sbin/eppfpga";
+char eppconfig_path[256] = "/usr/sbin/eppfpga";
static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL };
@@ -448,9 +450,10 @@
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 +658,11 @@
/* ---------------------------------------------------------------------- */
-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 +670,17 @@
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 +696,13 @@
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 +717,9 @@
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,22 +732,33 @@
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;
}
/* ---------------------------------------------------------------------- */
@@ -800,57 +821,68 @@
goto enditer##j; \
})
-static void receive(struct device *dev, int cnt)
+static int receive(struct 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;
}
/* --------------------------------------------------------------------- */
@@ -870,6 +902,7 @@
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 +913,40 @@
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 +966,8 @@
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 +984,9 @@
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 +995,11 @@
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 +1007,6 @@
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:
@@ -1040,6 +1088,7 @@
0, 0, (void *)(void *)epp_bh, dev
};
unsigned int i, j;
+ unsigned char tmp[128];
unsigned char stat;
unsigned long tstart;
@@ -1071,8 +1120,8 @@
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",
+ if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
+ printk(KERN_ERR "%s: parport at 0x%lx does not support bidirectional data transfer\n",
bc_drvname, pp->base);
parport_release(bc->pdev);
parport_unregister_device(bc->pdev);
@@ -1081,11 +1130,6 @@
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 +1137,33 @@
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 +1176,9 @@
}
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,12 +1196,12 @@
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
}
/* --------------------------------------------------------------------- */
@@ -1158,6 +1211,7 @@
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 +1223,8 @@
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,12 +1255,19 @@
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;
}
@@ -1316,9 +1378,9 @@
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;
@@ -1441,6 +1503,8 @@
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
*/
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)