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. ;-)