Return to BSD News archive
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.rmit.EDU.AU!news.unimelb.EDU.AU!munnari.OZ.AU!news.ecn.uoknor.edu!paladin.american.edu!gatech!newsfeed.internetmci.com!howland.reston.ans.net!Germany.EU.net!zib-berlin.de!irz401!uriah.heep!news
From: j@uriah.heep.sax.de (J Wunsch)
Newsgroups: comp.unix.bsd.freebsd.misc
Subject: Re: parallel line IP
Date: 8 Jan 1996 23:09:02 GMT
Organization: Private BSD site, Dresden
Lines: 399
Message-ID: <4cs86e$jst@uriah.heep.sax.de>
References: <30EC3B6D.169D0388@public.uni-hamburg.de> <4cmh8a$eli@uriah.heep.sax.de> <DKv546.8C3@news.tcd.ie>
Reply-To: joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch)
NNTP-Posting-Host: localhost.heep.sax.de
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Newsreader: knews 0.9.3
csdalton@tcd.ie (Colin Dalton) writes:
> >> does FreeBSD 2.1 support IP over the parallel printer
> >> port ?
>
> >Yes, it does.
>
> Where can I get more information on this? Is it the same as PLIP for the
> Amiga?
Originally, it has been a mode of its own, only compatible to itself.
The driver in FreeBSD-current does also support ``crynwr'' mode, that
is, the original IP-over-parallel protocol (meanwhile also back-
adopted by Linux). Here is the diff, though i don't have a clue if it
would fit into the 2.1 source tree. Give it a try if you like.
Index: /sys/i386/isa/lpt.c
===================================================================
RCS file: /home/cvs/src/sys/i386/isa/lpt.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- lpt.c 1995/11/29 14:39:44 1.42
+++ lpt.c 1995/12/02 20:33:40 1.43
@@ -46,7 +46,7 @@
* SUCH DAMAGE.
*
* from: unknown origin, 386BSD 0.1
- * $Id: lpt.c,v 1.42 1995/11/29 14:39:44 julian Exp $
+ * $Id: lpt.c,v 1.43 1995/12/02 20:33:40 phk Exp $
*/
/*
@@ -62,8 +62,10 @@
* This driver sends two bytes (0x08, 0x00) in front of each packet,
* to allow us to distinguish another format later.
*
+ * Now added an Linux/Crynwr compatibility mode which is enabled using
+ * IF_LINK0 - Tim Wilkinson.
+ *
* TODO:
- * Make Linux/Crynwr compatible mode, use IF_LLC0 to enable.
* Make HDLC/PPP mode, use IF_LLC1 to enable.
*
* Connect the two computers using a Laplink parallel cable to use this
@@ -96,7 +98,7 @@
* register int port asm("edx")
* the code would be cleaner
*
- * Poul-Henning Kamp <phk@login.dkuug.dk>
+ * Poul-Henning Kamp <phk@freebsd.org>
*/
#include "lpt.h"
@@ -131,6 +133,7 @@
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
+#include <netinet/if_ether.h>
#include "bpfilter.h"
#if NBPFILTER > 0
#include <net/bpf.h>
@@ -169,9 +172,17 @@
#define LPMAXERRS 100
#endif
+#define CLPIPHDRLEN 14 /* We send dummy ethernet addresses (two) + packet type in front of packet */
+#define CLPIP_SHAKE 0x80 /* This bit toggles between nibble reception */
+#define MLPIPHDRLEN CLPIPHDRLEN
+
#define LPIPHDRLEN 2 /* We send 0x08, 0x00 in front of packet */
-#define LPIPTBLSIZE 256 /* Size of octet translation table */
#define LPIP_SHAKE 0x40 /* This bit toggles between nibble reception */
+#if !defined(MLPIPHDRLEN) || LPIPHDRLEN > MLPIPHDRLEN
+#define MLPIPHDRLEN LPIPHDRLEN
+#endif
+
+#define LPIPTBLSIZE 256 /* Size of octet translation table */
#endif /* INET */
@@ -257,6 +268,11 @@
#define trecvh (txmith+(2*LPIPTBLSIZE))
#define trecvl (txmith+(3*LPIPTBLSIZE))
+static u_char *ctxmith;
+#define ctxmitl (ctxmith+(1*LPIPTBLSIZE))
+#define ctrecvh (ctxmith+(2*LPIPTBLSIZE))
+#define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
+
/* Functions for the lp# interface */
static void lpattach(struct lpt_softc *,int);
static int lpinittables(void);
@@ -868,6 +884,19 @@
if (!txmith)
return 1;
+ if (!ctxmith)
+ ctxmith = malloc(4*LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
+
+ if (!ctxmith)
+ return 1;
+
+ for (i=0; i < LPIPTBLSIZE; i++) {
+ ctxmith[i] = (i & 0xF0) >> 4;
+ ctxmitl[i] = 0x10 | (i & 0x0F);
+ ctrecvh[i] = (i & 0x78) << 1;
+ ctrecvl[i] = (i & 0x78) >> 3;
+ }
+
for (i=0; i < LPIPTBLSIZE; i++) {
txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
@@ -909,7 +938,7 @@
if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
if (lpinittables())
return ENOBUFS;
- sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + LPIPHDRLEN,
+ sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
M_DEVBUF, M_WAITOK);
if (!sc->sc_ifbuf)
return ENOBUFS;
@@ -921,7 +950,7 @@
case SIOCSIFMTU:
ptr = sc->sc_ifbuf;
- sc->sc_ifbuf = malloc(ifr->ifr_mtu+LPIPHDRLEN, M_DEVBUF, M_NOWAIT);
+ sc->sc_ifbuf = malloc(ifr->ifr_mtu+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT);
if (!sc->sc_ifbuf) {
sc->sc_ifbuf = ptr;
return ENOBUFS;
@@ -959,6 +988,44 @@
return 0;
}
+static inline int
+clpoutbyte (u_char byte, int spin, int data_port, int status_port)
+{
+ outb(data_port, ctxmitl[byte]);
+ while (inb(status_port) & CLPIP_SHAKE)
+ if (--spin == 0) {
+ return 1;
+ }
+ outb(data_port, ctxmith[byte]);
+ while (!(inb(status_port) & CLPIP_SHAKE))
+ if (--spin == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+static inline int
+clpinbyte (int spin, int data_port, int status_port)
+{
+ int c, cl;
+
+ while((inb(status_port) & CLPIP_SHAKE))
+ if(!--spin) {
+ return -1;
+ }
+ cl = inb(status_port);
+ outb(data_port, 0x10);
+
+ while(!(inb(status_port) & CLPIP_SHAKE))
+ if(!--spin) {
+ return -1;
+ }
+ c = inb(status_port);
+ outb(data_port, 0x00);
+
+ return (ctrecvl[cl] | ctrecvh[c]);
+}
+
static void
lpintr (int unit)
{
@@ -973,6 +1040,57 @@
s = splhigh();
+ if (sc->sc_if.if_flags & IFF_LINK0) {
+
+ /* Ack. the request */
+ outb(lpt_data_port, 0x01);
+
+ /* Get the packet length */
+ j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
+ if (j == -1)
+ goto err;
+ len = j;
+ j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
+ if (j == -1)
+ goto err;
+ len = len + (j << 8);
+
+ bp = sc->sc_ifbuf;
+
+ while (len--) {
+ j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
+ if (j == -1) {
+ goto err;
+ }
+ *bp++ = j;
+ }
+ /* Get and ignore checksum */
+ j = clpinbyte(LPMAXSPIN2, lpt_data_port, lpt_stat_port);
+ if (j == -1) {
+ goto err;
+ }
+
+ len = bp - sc->sc_ifbuf;
+ if (len <= CLPIPHDRLEN)
+ goto err;
+
+ sc->sc_iferrs = 0;
+
+ if (IF_QFULL(&ipintrq)) {
+ lprintf("DROP");
+ IF_DROP(&ipintrq);
+ goto done;
+ }
+ len -= CLPIPHDRLEN;
+ sc->sc_if.if_ipackets++;
+ sc->sc_if.if_ibytes += len;
+ top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, &sc->sc_if, 0);
+ if (top) {
+ IF_ENQUEUE(&ipintrq, top);
+ schednetisr(NETISR_IP);
+ }
+ goto done;
+ }
while ((inb(lpt_stat_port) & LPIP_SHAKE)) {
len = sc->sc_if.if_mtu + LPIPHDRLEN;
bp = sc->sc_ifbuf;
@@ -1053,16 +1171,15 @@
static inline int
lpoutbyte (u_char byte, int spin, int data_port, int status_port)
{
- outb(data_port, txmith[byte]);
- while (!(inb(status_port) & LPIP_SHAKE))
- if (--spin == 0)
- return 1;
- outb(data_port, txmitl[byte]);
- while (inb(status_port) & LPIP_SHAKE)
- if (--spin == 0)
- return 1;
-
- return 0;
+ outb(data_port, txmith[byte]);
+ while (!(inb(status_port) & LPIP_SHAKE))
+ if (--spin == 0)
+ return 1;
+ outb(data_port, txmitl[byte]);
+ while (inb(status_port) & LPIP_SHAKE)
+ if (--spin == 0)
+ return 1;
+ return 0;
}
static int
@@ -1076,6 +1193,10 @@
int s, err;
struct mbuf *mm;
u_char *cp = "\0\0";
+ u_char chksum = 0;
+ int count = 0;
+ int i;
+ int spin;
/* We need a sensible value if we abort */
cp++;
@@ -1088,27 +1209,106 @@
/* Suspend (on laptops) or receive-errors might have taken us offline */
outb(lpt_ctrl_port, LPC_ENA);
+ if (ifp->if_flags & IFF_LINK0) {
+
+ if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
+ lprintf("&");
+ lptintr(ifp->if_unit);
+ }
+
+ /* Alert other end to pending packet */
+ spin = LPMAXSPIN1;
+ outb(lpt_data_port, 0x08);
+ while ((inb(lpt_stat_port) & 0x08) == 0)
+ if (--spin == 0) {
+ goto nend;
+ }
+
+ /* Calculate length of packet, then send that */
+
+ count += 14; /* Ethernet header len */
+
+ mm = m;
+ for (mm = m; mm; mm = mm->m_next) {
+ count += mm->m_len;
+ }
+ if (clpoutbyte(count & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
+ goto nend;
+ if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
+ goto nend;
+
+ /* Send dummy ethernet header */
+ for (i = 0; i < 12; i++) {
+ if (clpoutbyte(i, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
+ goto nend;
+ chksum += i;
+ }
+
+ if (clpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
+ goto nend;
+ if (clpoutbyte(0x00, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
+ goto nend;
+ chksum += 0x08 + 0x00; /* Add into checksum */
+
+ mm = m;
+ do {
+ cp = mtod(mm, u_char *);
+ while (mm->m_len--) {
+ chksum += *cp;
+ if (clpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
+ goto nend;
+ }
+ } while ((mm = mm->m_next));
+
+ /* Send checksum */
+ if (clpoutbyte(chksum, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
+ goto nend;
+
+ /* Go quiescent */
+ outb(lpt_data_port, 0);
+
+ err = 0; /* No errors */
+
+ nend:
+ if (err) { /* if we didn't timeout... */
+ ifp->if_oerrors++;
+ lprintf("X");
+ } else {
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ }
+
+ m_freem(m);
+
+ if (!(inb(lpt_stat_port) & CLPIP_SHAKE)) {
+ lprintf("^");
+ lptintr(ifp->if_unit);
+ }
+ (void) splx(s);
+ return 0;
+ }
+
if (inb(lpt_stat_port) & LPIP_SHAKE) {
- lprintf("&");
- lptintr(ifp->if_unit);
+ lprintf("&");
+ lptintr(ifp->if_unit);
}
if (lpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
- goto end;
+ goto end;
if (lpoutbyte(0x00, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto end;
+ goto end;
mm = m;
do {
- cp = mtod(mm,u_char *);
- while (mm->m_len--)
+ cp = mtod(mm,u_char *);
+ while (mm->m_len--)
if (lpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
- goto end;
+ goto end;
} while ((mm = mm->m_next));
err = 0; /* no errors were encountered */
-end:
+ end:
--cp;
outb(lpt_data_port, txmitl[*cp] ^ 0x17);
@@ -1183,4 +1383,3 @@
SYSINIT(lptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,lpt_drvinit,NULL)
#endif /* JREMOD */
-
--
cheers, J"org
joerg_wunsch@uriah.heep.sax.de -- http://www.sax.de/~joerg/ -- NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)