1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

Parallel-port TCP/IP interface can now take any MTU.

This commit is contained in:
Poul-Henning Kamp 1994-09-18 06:12:45 +00:00
parent 240baf2f68
commit 0999b624b0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=2847

View File

@ -46,7 +46,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: unknown origin, 386BSD 0.1 * from: unknown origin, 386BSD 0.1
* $Id: lpt.c,v 1.17 1994/09/03 22:47:02 csgr Exp $ * $Id: lpt.c,v 1.18 1994/09/15 02:37:11 phk Exp $
*/ */
/* /*
@ -155,6 +155,7 @@
#endif #endif
#define LPHDR 2 /* We send 0x08, 0x00 in front of packet */ #define LPHDR 2 /* We send 0x08, 0x00 in front of packet */
#endif /* INET */ #endif /* INET */
/* BIOS printer list - used by BIOS probe*/ /* BIOS printer list - used by BIOS probe*/
@ -197,7 +198,7 @@ struct lpt_softc {
#ifdef INET #ifdef INET
struct ifnet sc_if; struct ifnet sc_if;
u_char sc_ifbuf[LPMTU+LPHDR]; u_char *sc_ifbuf;
int sc_iferrs; int sc_iferrs;
#endif /* ENDIF */ #endif /* ENDIF */
@ -234,14 +235,14 @@ void lptintr (int unit);
#ifdef INET #ifdef INET
/* Tables for the lp# interface */ /* Tables for the lp# interface */
static unsigned char txmith[1024]; static u_char *txmith;
#define txmitl (txmith+256) #define txmitl (txmith+256)
#define trecvh (txmith+512) #define trecvh (txmith+512)
#define trecvl (txmith+768) #define trecvl (txmith+768)
/* Functions for the lp# interface */ /* Functions for the lp# interface */
static void lpattach(struct lpt_softc *,int); static void lpattach(struct lpt_softc *,int);
static void lpinittables(); static int lpinittables();
static int lpioctl(struct ifnet *, int, caddr_t); static int lpioctl(struct ifnet *, int, caddr_t);
static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *, static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *); struct rtentry *);
@ -808,23 +809,29 @@ lpattach(struct lpt_softc *sc,int unit)
ifp->if_addrlen = 0; ifp->if_addrlen = 0;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
if_attach(ifp); if_attach(ifp);
printf("lp%d: TCP/IP interface, MTU=%d.\n",unit,LPMTU); printf("lp%d: TCP/IP interface\n",unit);
} }
/* /*
* We don't want to calculate these nasties in our tight loop, so we * We don't want to calculate these nasties in our tight loop, so we
* precalculate them when we initialize. * precalculate them when we initialize.
*/ */
static void static int
lpinittables() lpinittables()
{ {
int i; int i;
if(!txmith)
txmith = malloc(1024,M_DEVBUF,M_NOWAIT);
if(!txmith)
return 1;
for(i=0;i<256;i++) { for(i=0;i<256;i++) {
txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08; txmith[i] = ((i & 0x80) >> 3) | ((i & 0x70) >> 4) | 0x08;
txmitl[i] = ((i & 0x08) << 1) | (i & 0x07); txmitl[i] = ((i & 0x08) << 1) | (i & 0x07);
trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1); trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3); trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
} }
return 0;
} }
/* /*
@ -834,59 +841,59 @@ lpinittables()
static int static int
lpioctl(struct ifnet *ifp, int cmd, caddr_t data) lpioctl(struct ifnet *ifp, int cmd, caddr_t data)
{ {
struct proc *p = curproc; struct proc *p = curproc;
struct lpt_softc *sc = lpt_sc + ifp->if_unit; struct lpt_softc *sc = lpt_sc + ifp->if_unit;
struct ifaddr *ifa = (struct ifaddr *)data; struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data; struct ifreq *ifr = (struct ifreq *)data;
u_char *ptr;
int error = 0; switch (cmd) {
switch (cmd) { case SIOCSIFDSTADDR:
case SIOCAIFADDR:
case SIOCSIFFLAGS: case SIOCSIFADDR:
if (((ifp->if_flags & IFF_UP) == 0) && if (ifa->ifa_addr->sa_family != AF_INET)
(ifp->if_flags & IFF_RUNNING)) { return EAFNOSUPPORT;
outb(sc->sc_port+2, 0x00); ifp->if_flags |= IFF_UP;
ifp->if_flags &= ~IFF_RUNNING; /* FALLTHROUGH */
} case SIOCSIFFLAGS:
if (((ifp->if_flags & IFF_UP)) && if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {
((ifp->if_flags & IFF_RUNNING) == 0)) { outb(sc->sc_port+2, 0x00);
lpinittables(); ifp->if_flags &= ~IFF_RUNNING;
outb(sc->sc_port+2, 0x10); break;
ifp->if_flags |= IFF_RUNNING;
}
break;
case SIOCAIFADDR:
case SIOCSIFADDR:
if (ifa->ifa_addr->sa_family != AF_INET)
error = EAFNOSUPPORT;
lpinittables();
outb(sc->sc_port+2, 0x10);
ifp->if_flags |= IFF_RUNNING | IFF_UP;
break;
case SIOCSIFDSTADDR:
if (ifa->ifa_addr->sa_family != AF_INET)
error = EAFNOSUPPORT;
break;
case SIOCSIFMTU:
if ((error = suser(p->p_ucred, &p->p_acflag)))
return (error);
if(ifr->ifr_metric > LPMTU)
error = EINVAL;
sc->sc_if.if_mtu = ifr->ifr_metric;
break;
case SIOCGIFMTU:
ifr->ifr_metric = sc->sc_if.if_mtu;
break;
default:
lprintf("LP:ioctl%x\n",cmd);
error = EINVAL;
} }
return (error); if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
if(lpinittables())
return ENOBUFS;
sc->sc_ifbuf = malloc(ifr->ifr_metric+LPHDR,M_DEVBUF,M_NOWAIT);
if(!sc->sc_ifbuf)
return ENOBUFS;
outb(sc->sc_port+2, 0x10);
ifp->if_flags |= IFF_RUNNING;
}
break;
case SIOCSIFMTU:
ptr = sc->sc_ifbuf;
sc->sc_ifbuf = malloc(ifr->ifr_metric+LPHDR,M_DEVBUF,M_NOWAIT);
if(!sc->sc_ifbuf) {
sc->sc_ifbuf = ptr;
return ENOBUFS;
}
free(ptr,M_DEVBUF);
sc->sc_if.if_mtu = ifr->ifr_metric;
break;
case SIOCGIFMTU:
ifr->ifr_metric = sc->sc_if.if_mtu;
break;
default:
lprintf("LP:ioctl%x\n",cmd);
return EINVAL;
}
return 0;
} }
static void static void
@ -894,13 +901,16 @@ lpintr(int unit)
{ {
struct lpt_softc *sc = lpt_sc + unit; struct lpt_softc *sc = lpt_sc + unit;
int len,s,j; int len,s,j;
register const int port = sc->sc_port+1; const int port = sc->sc_port+1;
u_char *bp;
s = splimp(); s = splimp();
while((inb(port)&0x40)) { while((inb(port)&0x40)) {
{ {
u_long c, cl; u_long c, cl;
for(len=0;len<LPMTU+LPHDR;) { len = sc->sc_if.if_mtu + LPHDR;
bp = sc->sc_ifbuf;
while(len--) {
__asm __volatile(" __asm __volatile("
inb %%dx,%%al inb %%dx,%%al
movzbl %%al,%0 movzbl %%al,%0
@ -922,7 +932,7 @@ lpintr(int unit)
outb %%al,%%dx outb %%al,%%dx
incl %%edx incl %%edx
" : "=b" (c) : "d" (port) : "a"); " : "=b" (c) : "d" (port) : "a");
sc->sc_ifbuf[len++] = trecvh[cl] | trecvl[c]; *bp++= trecvh[cl] | trecvl[c];
{ {
j = LPMAXSPIN2; j = LPMAXSPIN2;
while(!((cl=inb(port)) & 0x40)) { while(!((cl=inb(port)) & 0x40)) {
@ -934,6 +944,7 @@ lpintr(int unit)
} }
} }
end: end:
len = bp - sc->sc_ifbuf;
if(len <= LPHDR) if(len <= LPHDR)
goto err; goto err;
@ -948,8 +959,8 @@ lpintr(int unit)
sc->sc_if.if_ipackets++; sc->sc_if.if_ipackets++;
sc->sc_if.if_ibytes += len; sc->sc_if.if_ibytes += len;
{ {
u_char *p = sc->sc_ifbuf+LPHDR;
struct mbuf *top, *m, *m2; struct mbuf *top, *m, *m2;
bp = sc->sc_ifbuf+LPHDR;
MGETHDR(m, M_DONTWAIT, MT_DATA); MGETHDR(m, M_DONTWAIT, MT_DATA);
top = m; top = m;
m->m_len=0; m->m_len=0;
@ -964,10 +975,10 @@ lpintr(int unit)
m->m_len=0; m->m_len=0;
m2->m_next = m; m2->m_next = m;
j = min(len,M_TRAILINGSPACE(m)); j = min(len,M_TRAILINGSPACE(m));
bcopy(p, mtod(m, caddr_t), j); bcopy(bp, mtod(m, caddr_t), j);
m->m_len=j; m->m_len=j;
len -= j; len -= j;
p += j; bp += j;
} }
IF_ENQUEUE(&ipintrq, top); IF_ENQUEUE(&ipintrq, top);
schednetisr(NETISR_IP); schednetisr(NETISR_IP);