From owner-freebsd-bugs Thu Jun 15 01:00:18 1995 Return-Path: bugs-owner Received: (from majordom@localhost) by freefall.cdrom.com (8.6.10/8.6.6) id BAA28928 for bugs-outgoing; Thu, 15 Jun 1995 01:00:18 -0700 Received: (from gnats@localhost) by freefall.cdrom.com (8.6.10/8.6.6) id BAA28918 ; Thu, 15 Jun 1995 01:00:17 -0700 Date: Thu, 15 Jun 1995 01:00:17 -0700 Message-Id: <199506150800.BAA28918@freefall.cdrom.com> From: tim@sarc.city.ac.uk Reply-To: tim@sarc.city.ac.uk To: freebsd-bugs Subject: kern/516: Crynwr compatibility mode for PLIP driver. In-Reply-To: Your message of Thu, 15 Jun 1995 08:52:53 +0100 <199506150752.IAA10916@cripplecock.sarc.city.ac.uk> Sender: bugs-owner@FreeBSD.org Precedence: bulk >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 #include #include *************** *** 132,137 **** --- 136,144 ---- #include #include #include + #ifdef CRYNWR_COMPAT + #include + #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: