Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Jun 1995 01:00:17 -0700
From:      tim@sarc.city.ac.uk
To:        freebsd-bugs
Subject:   kern/516: Crynwr compatibility mode for PLIP driver.
Message-ID:  <199506150800.BAA28918@freefall.cdrom.com>
In-Reply-To: Your message of Thu, 15 Jun 1995 08:52:53 %2B0100 <199506150752.IAA10916@cripplecock.sarc.city.ac.uk>

next in thread | previous in thread | raw e-mail | index | archive | help

>Number:         516
>Category:       kern
>Synopsis:       Crynwr compatibility mode for PLIP driver.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs (FreeBSD bugs mailing list)
>State:          open
>Class:          support
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 15 01:00:01 1995
>Originator:     Tim Wilkinson
>Organization:
Systems Architecture Research Centre, City Uni. UK
>Release:        FreeBSD 2.0.5-RELEASE i386
>Environment:
>Description:

The PLIP driver (IP over the printer port) does not conform to the "standard"
used by Crynwr (and Linux I think).

>How-To-Repeat:
>Fix:
	
In the spirit of the comments in lpt.c, I've added a Crynwr compatibility
mode to enable PLIP to talk to DOS programs which use the Crynwr PLIP driver.
The mode is enabled using the link0 option to ifconfig otherwise the driver
remains compaitible with the old verion.  Find the patch enclosed.

*** lpt.orig	Wed Jun 14 08:44:11 1995
--- lpt.c	Wed Jun 14 15:38:41 1995
***************
*** 62,69 ****
   * This driver sends two bytes (0x08, 0x00) in front of each packet,
   * to allow us to distinguish another format later.
   *
   * 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
--- 62,71 ----
   * 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 HDLC/PPP mode, use IF_LLC1 to enable.
   *
   * Connect the two computers using a Laplink parallel cable to use this
***************
*** 102,107 ****
--- 104,111 ----
  #include "lpt.h"
  #if NLPT > 0
  
+ #define	CRYNWR_COMPAT		/* Include Crynwr compatible PLIP driver */
+ 
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/proc.h>
***************
*** 132,137 ****
--- 136,144 ----
  #include <netinet/in_systm.h>
  #include <netinet/in_var.h>
  #include <netinet/ip.h>
+ #ifdef	CRYNWR_COMPAT
+ #include <netinet/if_ether.h>
+ #endif
  #endif /* INET */
  
  #define	LPINITRDY	4	/* wait up to 4 seconds for a ready */
***************
*** 156,164 ****
  #define	LPMAXERRS	100
  #endif
  
  #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 */
  
  #endif /* INET */
  
--- 163,183 ----
  #define	LPMAXERRS	100
  #endif
  
+ #ifdef CRYNWR_COMPAT
+ 
+ #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
+ 
+ #endif /* CRYNWR_COMPAT */
+ 
  #define LPIPHDRLEN	2	/* We send 0x08, 0x00 in front of packet */
  #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 */
  
***************
*** 245,250 ****
--- 264,276 ----
  #define trecvh (txmith+(2*LPIPTBLSIZE))
  #define trecvl (txmith+(3*LPIPTBLSIZE))
  
+ #ifdef CRYNWR_COMPAT
+ static u_char *ctxmith;
+ #define ctxmitl (ctxmith+(1*LPIPTBLSIZE))
+ #define ctrecvh (ctxmith+(2*LPIPTBLSIZE))
+ #define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
+ #endif /* CRYNWR_COMPAT */
+ 
  /* Functions for the lp# interface */
  static void lpattach(struct lpt_softc *,int);
  static int lpinittables();
***************
*** 851,856 ****
--- 877,899 ----
      if (!txmith)
  	return 1;
  
+ #ifdef CRYNWR_COMPAT
+ 
+     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;
+     }
+ 
+ #endif /* CRYNWR_COMPAT */
+ 
      for (i=0; i < LPIPTBLSIZE; i++) {
  	txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
  	txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
***************
*** 892,898 ****
  	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,
  				  M_DEVBUF, M_WAITOK);
  	    if (!sc->sc_ifbuf)
  		return ENOBUFS;
--- 935,941 ----
  	if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
  	    if (lpinittables())
  		return ENOBUFS;
! 	    sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
  				  M_DEVBUF, M_WAITOK);
  	    if (!sc->sc_ifbuf)
  		return ENOBUFS;
***************
*** 904,910 ****
  
      case SIOCSIFMTU:
  	ptr = sc->sc_ifbuf;
! 	sc->sc_ifbuf = malloc(ifr->ifr_metric+LPIPHDRLEN, M_DEVBUF, M_NOWAIT);
  	if (!sc->sc_ifbuf) {
  	    sc->sc_ifbuf = ptr;
  	    return ENOBUFS;
--- 947,953 ----
  
      case SIOCSIFMTU:
  	ptr = sc->sc_ifbuf;
! 	sc->sc_ifbuf = malloc(ifr->ifr_metric+MLPIPHDRLEN, M_DEVBUF, M_NOWAIT);
  	if (!sc->sc_ifbuf) {
  	    sc->sc_ifbuf = ptr;
  	    return ENOBUFS;
***************
*** 925,930 ****
--- 968,1015 ----
      return 0;
  }
  
+ #ifdef CRYNWR_COMPAT
+ 
+ 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]);
+ }
+ 
+ #endif /* CRYNWR_COMPAT */
+ 
  static void
  lpintr (int unit)
  {
***************
*** 939,944 ****
--- 1024,1084 ----
  
  	s = splhigh();
  
+ #ifdef CRYNWR_COMPAT
+ 
+ 	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;
+ 	}
+ #endif /* CRYNWR_COMPAT */
+ 
  	while ((inb(lpt_stat_port) & LPIP_SHAKE)) {
  	    len = sc->sc_if.if_mtu + LPIPHDRLEN;
  	    bp  = sc->sc_ifbuf;
***************
*** 1014,1029 ****
  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;
  }
  
  static int 
--- 1154,1168 ----
  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;
  }
  
  static int 
***************
*** 1037,1042 ****
--- 1176,1187 ----
      int s, err;
      struct mbuf *mm;
      u_char *cp = "\0\0";
+ #ifdef CRYNWR_COMPAT
+     u_char chksum = 0;
+     int count = 0;
+     int i;
+     int spin;
+ #endif /* CRYNWR_COMPAT */
  
      /* We need a sensible value if we abort */	
      cp++;
***************
*** 1049,1075 ****
      /* Suspend (on laptops) or receive-errors might have taken us offline */
      outb(lpt_ctrl_port, LPC_ENA);
  
      if (inb(lpt_stat_port) & LPIP_SHAKE) {
! 	lprintf("&");
! 	lptintr(ifp->if_unit);
      }
  
      if (lpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
! 	goto end;
      if (lpoutbyte(0x00, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
! 	goto end;
  
      mm = m;
      do {
! 	cp = mtod(mm,u_char *);
! 	while (mm->m_len--)
  	    if (lpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
! 		goto end;
      } while ((mm = mm->m_next));
  
      err = 0;				/* no errors were encountered */
  
! end:
      --cp;
      outb(lpt_data_port, txmitl[*cp] ^ 0x17);
  
--- 1194,1302 ----
      /* Suspend (on laptops) or receive-errors might have taken us offline */
      outb(lpt_ctrl_port, LPC_ENA);
  
+ #ifdef CRYNWR_COMPAT
+ 
+     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;
+     }
+ #endif /* CRYNWR_COMPAT */
+ 
      if (inb(lpt_stat_port) & LPIP_SHAKE) {
!         lprintf("&");
!         lptintr(ifp->if_unit);
      }
  
      if (lpoutbyte(0x08, LPMAXSPIN1, lpt_data_port, lpt_stat_port))
!         goto end;
      if (lpoutbyte(0x00, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
!         goto end;
  
      mm = m;
      do {
!         cp = mtod(mm,u_char *);
!         while (mm->m_len--)
  	    if (lpoutbyte(*cp++, LPMAXSPIN2, lpt_data_port, lpt_stat_port))
! 	        goto end;
      } while ((mm = mm->m_next));
  
      err = 0;				/* no errors were encountered */
  
!     end:
      --cp;
      outb(lpt_data_port, txmitl[*cp] ^ 0x17);
  
>Audit-Trail:
>Unformatted:





Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199506150800.BAA28918>