[comp.protocols.tcp-ip.ibmpc] BICC 411x support for NCSA Telnet

ingea@IFI.UIO.NO (Inge Arnesen) (01/17/90)

This is some code that interfaces NCSA Telnet 2.2 with Microsoft C
extentions, as provided by Jyrki Kuoppala, with the BICC ISOLAN
411x cards.

Instead of taking over the whole card, the port is made to work through
the BICC Multi Protocol Software, enabling NCSA Telnet TCP/IP to
coexist with other network protocols, like Novells IPX.

This port was initially made for the Institute of Social Research and
the Institute of Applied Social Research for use on their Novell net,
but since others might have interrest in this, I decided to put it on
the net. The port has been in heavy use since the late spring of 1989
and should be fairly good. No known bugs at this point, but the code 
still has a flavour of an easy hack (it has not been changed due to
the good proverb : "If it ain't broke, don't fix it"). The code has
been written in a way so as if to make as few and as small changes to
NCSA TELNET as possible. The program has been run towards a HP9000/825
and a Interactive 386/ix.

Regarding the ownership of this code, it's still the authors property
and will remain so even after the code has been posted to the net.
But, the code can be used freely, as long as it's not being used
commersially and all changes to the code are reported to me, so I can
update and maintain this program. If somebody wants to use this code
in commersial programs or put them under another licence, I must be
consulted first. I'm not really opposed to this, but I won't let
anybody change the copyright as they please. Please note that this code
IS NOT A PART OF NCSA TELNET. If some people at NCSA finds it 
interresting, it might be at some point. This is written to indicate that
neither NCSA nor I would commit ourselves to supporting this port in
the future. But, when 2.3 appears, I will do my best to make this port
work there as well.

The port consists of two new files, ISO.C and MULTI.ASM which together
make up the BICC support. I have also included PCTOOLS.C to show how
the BICC support is wedged into NCSA TELNET (I assume I've done it the
normal way). This program must be compiled with the symbol ISOLAN 
defined (all changes to the original code is #ifdef'ed). I've also
included the updated MAKEFILE, adapted to MS C by Jyrki Kuoppala and
changed by me to support the BICC port. I've used Microsoft C 5.1 for
the port, but I believe I've kept ANSI-specific stuff out of it, so
earlier versions should be able to compile it with few or no 
alterations.

BTW: I've also rewritten the 3COM 501 driver for NCSA in C to make it
easier to understand and maintain. With my crude tests, I cannot find
any notable changes in speed, but the tests were done on an PC AT and
maybe speed problems would be more appearant on a plain 4.77 MHz PC.
I would suggest that drivers should, as long as speed allows it, be
written in C, since this would also enhance portability of the drivers
themselves and maybe the system as a whole.

Please mail all questions and comments to: ingea@ifi.uio.no
or during holydays to:  inge%beatnix@ifi.uio.no

Happy hacking!

   Inge Arnesen, University of Oslo, Norway

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	iso.c
#	multi.asm
#	pctools.c
#	makefile
# This archive created: Wed Jan 17 14:14:32 1990
export PATH; PATH=/bin:$PATH
echo shar: extracting "'iso.c'" '(15525 characters)'
if test -f 'iso.c'
then
	echo shar: will not over-write existing file "'iso.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'iso.c'
	X/****************************************************************************
	X *  BICC 411x Multi Protocol Software code                                  *
	X *  Inge Arnesen 1989                                                       *
	X *                                                                          *
	X *  Module to interface NCSA Telnet to the BICC 411x cards through the      *
	X *  ISOLAN Multi Protocol Software. This enables NCSA Telnet to coexist     *
	X *  with Novell Netware.                                                    *
	X *                                                                          *
	X *  THIS IS NOT A PART OF NCSA TELNET                                       *
	X *                                                                          *
	X ****************************************************************************
	X *                                                                          *
	X *                                                                          *
	X *      (C) Inge Arnesen                                                    *
	X *      Institute of Social Research                                        *
	X *      Munthesgt. 31                                                       *
	X *      N-0260 Oslo, NORWAY                                                 *
	X *                                                                          *
	X *                                                                          *
	X *    DISCLAIMER: This code is not property of the institute, but of        *
	X *                the author himself. No responsibility is claimed          *
	X *                for anything whatsoever due to the use of this code!      *
	X *                                                                          *
	X ****************************************************************************
	X *                                                                          *
	X *    Created      : 89.05.27  by Inge Arnesen                              *
	X *    Last modified: 89.05.29  by Inge Arnesen                              *
	X *                                                                          *
	X *    History: 89.05.29 Initial alpha version                               *
	X *             89.07.01 Beta started - no changes                           *
	X *             89.10.06 Final release - no changes                          *
	X *                                                                          *
	X ****************************************************************************
	X
	X        ILrecv          - Polled receive (dummy)
	X        ILetopen        - Initialize Ethernet SW
	X        ILetclose       - Close down Ethernet SW
	X        ILgetaddr       - Get Ethernet cards address (must be initialized first)
	X        ILetaddr        - Set Ethernet cards address (dummy)
	X        ILxmit          - Send data across the Ethernet
	X        ILetupdate      - Update buffer pointers
	X
	X
	X        COMPILE:
	X                cl -Ze -Zp -Gs iso.c
	X        Options are:    Enable language extentions, pack structure members,
	X                        Remove calls to Stack probe routine
	X
	X */
	X/* Standard include files */
	X#include        <conio.h>       /* Microsoft 'C' Include file   */
	X#include        <ctype.h>       /* Microsoft 'C' Include file   */
	X#include        <dos.h>         /* Microsoft 'C' Include file   */
	X#include        <stdio.h>       /* Microsoft 'C' Include file   */
	X#include        <string.h>      /* Microsoft 'C' Include file   */
	X
	X/* NCSA include files */
	X#include        "protocol.h"
	X#include        "data.h"
	X
	X/*
	X *      Command codes for ISOLAN MPS SW
	X */
	X
	X#define STATUS                  0xB3    /* XPORT & SFB */
	X
	X#define FAST_TIMER              0xF0    /* XPORT & SFB */
	X#define L_ACTIVATE              0xF2    /* XPORT & SFB */
	X#define L_DEACTIVATE            0xF3    /* XPORT & SFB */
	X#define L_DATA_SEND             0xF4    /* XPORT & SFB */
	X#define M_ACTIVATE              0xFA    /* XPORT & SFB */
	X#define M_DEACTIVATE            0xFB    /* XPORT & SFB */
	X
	X#define L_ACTIVATE_CONF         0x03    /* Returned Event Code */
	X#define L_DEACTIVATE_CONF       0x05    /* Returned Event Code */
	X#define L_DATA_IND              0x08    /* Returned Event Code, LLC Data */
	X#define M_DATA_IND              0x0a    /* Returned Event Code, Blue Book MAC Data */
	X#define M_ACTIVATE_CONF         0x12    /* Returned Event Code */
	X#define M_DEACTIVATE_CONF       0x14    /* Returned Event Code */
	X
	X#define FALSE                   0
	X#define TRUE                    1
	X
	X#define BUF_SIZE                1504
	X#define MAX_VC                  32
	X
	X
	X/*
	X *      DATA STRUCTURES
	X */
	X
	Xunion adr_ptr
	X{
	X        char    far *pt;
	X        struct  
	X        {
	X                unsigned short  start_type;
	X                unsigned short  end_type;
	X        } type;
	X        struct mps_status *status;
	X};
	X
	Xstruct tcb         /* Transfer Control Block */
	X{
	X        unsigned char   tcbcommand;     /* command code                         */
	X        unsigned char   tcbcid;         /* command identity                     */
	X        unsigned char   tcbvcid;        /* virtual circuit id                   */
	X        unsigned short  tcblength;      /* buffer length                        */
	X        union adr_ptr   tcbbaddr;       /* address of data                      */
	X        unsigned char   tcbexpedited;   /* expedited data flag                  */
	X        unsigned char   tcbcancelable;  /* cancelable flag                      */
	X        unsigned char   tcbladdr[16];   /* local network address                */
	X        unsigned char   tcbraddr[16];   /* remote address                       */
	X        unsigned short  (far *tcbasync)(); /* address of async notification routine*/
	X        unsigned long   tcblnet;        /* local network number                 */
	X        unsigned long   tcbrnet;        /* remote network number                */
	X        unsigned char   tcbrto;         /* call timeout                         */
	X        unsigned char   tcbsto;         /* not used                             */
	X        unsigned char   tcbres2[8];     /* reserved                             */
	X        unsigned char   tcbcmdex;       /* command code extension               */
	X        unsigned short  tcbstatus;      /* Blue Book MAC type                   */
	X};
	X
	X
	Xstruct acb              /* Asynchronous Control Block */
	X{
	X        unsigned char   acbcid;         /* return cid from TCB          */
	X        unsigned char   acbvcid;        /* return vcid from TCB         */
	X        unsigned char   acberr;         /* error code                   */
	X        unsigned char   acbcmd;         /* return command from TCB      */
	X        unsigned short  acblen;         /* actual length of message     */
	X        unsigned char   acbraddr[16];   /* remote network address       */
	X        unsigned long   acbrnet;        /* remote network number        */
	X        unsigned char   acbladdr[16];   /* local network address        */
	X        unsigned long   acblnet;        /* local network number         */
	X        unsigned short  acbstatus;      /* Blue Book MAC type           */
	X        unsigned char   acbeventcode;   /* copy of board event code     */
	X        union adr_ptr   acbbaddr;       /* address of data              */
	X        unsigned char   acbexpedited;   /* expedited data flag          */
	X};
	X
	Xstruct recany_rec               /* receive any record */
	X{
	X        unsigned char   recany_count;   
	X        unsigned char   recany_list[MAX_VC];
	X};
	X
	X
	Xstruct mps_status       
	X{
	X        unsigned char address[16];
	X        unsigned long network;
	X        unsigned char status;
	X        unsigned char version;
	X        unsigned int  maxcon;
	X        unsigned int  maxcom;
	X        unsigned long pack_sent;
	X        unsigned long pack_rec;
	X        unsigned int  pack_lost;
	X        unsigned int  pack_abort;
	X        unsigned int  pack_frame;
	X        unsigned int  pack_crc;
	X        unsigned char address_mask[16];
	X        unsigned int  board_segment;
	X        unsigned int  board_offset;
	X        unsigned int  gen_tsel;
	X        unsigned int  broad_tsel;
	X        unsigned char reserved[0x3e];
	X};
	X
	Xextern void ANR_ENTRY();
	Xunsigned int anr_c();
	Xstruct mps_status stat_buf;
	X
	X
	Xextern unsigned char rstat;             /*  last status from read               */
	Xextern unsigned char *bufpt;            /*  current buffer pointer              */
	Xextern unsigned char *buforg;           /*  pointer to beginning of buffer      */
	Xextern unsigned char *bufend;           /*  pointer to end of buffer            */
	Xextern unsigned char *bufread;          /*  pointer to where program is reading */
	Xextern unsigned int bufbig;             /*  integer, how many bytes we have     */
	Xextern unsigned int buflim;             /*  integer, max bytes we can have      */
	X
	X
	XILgetaddr(ethaddr, memaddr, ioaddr)
	Xunsigned char ethaddr[DADDLEN];
	Xunsigned int memaddr, ioaddr;
	X{
	X        int i; 
	X        struct tcb t, *h;
	X        union REGS inregs, outregs;
	X        struct SREGS segregs;
	X
	X        /* Then send status request */
	X        t.tcbcommand = STATUS;
	X        t.tcbcid = STATUS;
	X        t.tcbbaddr.status= &stat_buf;
	X        t.tcblength    = sizeof(struct mps_status);
	X        t.tcblnet= 0xffffffff;
	X
	X        t.tcbasync= (void *)ANR_ENTRY;
	X
	X        /*
	X         *      now issue the int5b, es:bx point at the tcb
	X         *
	X         */
	X        h= &t; 
	X        segregs.es= FP_SEG(h);
	X        inregs.x.bx= FP_OFF(h);
	X        int86x(0x5B, &inregs, &outregs, &segregs);
	X
	X        for (i= 9; i < 15; i++)
	X                ethaddr[i - 9]= stat_buf.address[i];
	X}
	X
	XILrecv()
	X{
	X}
	X
	XILetupdate()
	X{
	X        /* Update all the pointers etc. */
	X        bufbig-= *((int *)bufread) + sizeof( int );
	X        bufread+= *((int *)bufread) + sizeof(int);
	X        if(bufread >= bufend)
	X                bufread= buforg;
	X}
	X
	X
	X
	Xint ILxmit(pack, size)
	XDLAYER *pack;
	Xint size;
	X{
	X        struct tcb t, *h;               
	X        int i;
	X        union REGS inregs, outregs;
	X        struct SREGS segregs;
	X
	X        t.tcbraddr[2] = 0;
	X        t.tcbraddr[3] = 0;
	X        t.tcbraddr[7] = 0;
	X        t.tcbraddr[8] = 0;   /* LSAP */
	X        t.tcbraddr[9] = pack->dest[0];     /* ETHADDR */
	X        t.tcbraddr[10] = pack->dest[1];
	X        t.tcbraddr[11] = pack->dest[2];
	X        t.tcbraddr[12] = pack->dest[3];
	X        t.tcbraddr[13] = pack->dest[4];
	X        t.tcbraddr[14] = pack->dest[5];      /*--to here--*/
	X        t.tcbraddr[15] = 0;
	X        t.tcbcommand = L_DATA_SEND;
	X
	X        t.tcbstatus = intswap(pack->type);
	X        for (i = 0; i < 16; ++i)
	X                t.tcbladdr[i] = 0;
	X
	X        t.tcbasync= 0;   /* No ANR */
	X
	X        /*      setup pointer to data buffer    */
	X        t.tcbbaddr.pt  = (char far *)pack + sizeof(DLAYER);
	X        t.tcblength    = size - sizeof(DLAYER);
	X        /*
	X         *      now issue the int5b, es:bx point at the tcb
	X         *
	X         */
	X        h= &t;
	X        segregs.es= FP_SEG(h);
	X        inregs.x.bx= FP_OFF(h);
	X        int86x(0x5B, &inregs, &outregs, &segregs);
	X        return(outregs.h.al);
	X}
	X
	XILetopen(ethaddr, ioirq, memaddr, ioaddr)
	Xunsigned char ethaddr[DADDLEN];
	Xunsigned int memaddr, ioaddr;
	X{
	X        struct tcb t, *h;
	X        int i;
	X        union REGS inregs, outregs;
	X        struct SREGS segregs;
	X
	X
	X        t.tcbcommand = L_ACTIVATE;
	X        t.tcbcid = L_ACTIVATE;
	X
	X        for (i = 0; i < 16; ++i)
	X                t.tcbladdr[i] = 0;
	X
	X        t.tcbasync= (void *)ANR_ENTRY;
	X
	X        /*
	X         *      now issue the int5b, es:bx point at the tcb
	X         *
	X         */
	X        h= &t; 
	X        segregs.es= FP_SEG(h);
	X        inregs.x.bx= FP_OFF(h);
	X        int86x(0x5B, &inregs, &outregs, &segregs);
	X
	X        return(outregs.h.al);
	X}
	X
	XILetclose()
	X{
	X        union REGS inregs, outregs;
	X        struct SREGS segregs;
	X        struct tcb t, *h;               
	X        int i;
	X
	X        t.tcbcommand = L_DEACTIVATE;
	X        t.tcbcid = 0; /* Not used */
	X
	X        for (i = 0; i < 16; ++i)
	X                t.tcbladdr[i] = 0;
	X
	X        /*
	X         *      now issue the int5b, es:bx point at the tcb
	X         *
	X         */
	X        h= &t; 
	X        segregs.es= FP_SEG(h);
	X        inregs.x.bx= FP_OFF(h);
	X        int86x(0x5B, &inregs, &outregs, &segregs);
	X        return(outregs.h.al);
	X}
	X
	X
	X/*
	X *      Note: anr_c returns zero to the Multi Protocol Handler
	X *
	X *      Inside the ANR, Operating System calls must not be made, nor must
	X *      space be grabbed from the Heap.  The use of Automatic variables
	X *      is allowed, but make sure the stack is large enough.
	X */
	X
	Xunsigned int anr_c(acb_ptr)
	Xstruct  acb     *acb_ptr;
	X{
	X        int i;
	X        int mine= TRUE;  /* We suspect all packets of coming from this card */
	X                        /* Loop back is supported on link level */      
	X                        /* If its mine, drop it like a hot potato */
	X
	X        char    far     *buffer_pt;     /* buffer pointer       */
	X
	X        if(acb_ptr->acbcmd != STATUS)
	X        {
	X                switch(acb_ptr->acbeventcode)
	X                {
	X                case L_ACTIVATE_CONF:
	X                        break;
	X                case L_DATA_IND:
	X                case M_DATA_IND:
	X                        /* If it is not one of mine, mark it as such */  
	X                        for(i= 0; i < 6 ; i++)
	X                                if(acb_ptr->acbraddr[i+9] != nnmyaddr[i])
	X                                {
	X                                        mine= FALSE; 
	X                                        break;
	X                                }       
	X                        if (!mine)
	X                        {
	X                        /* with llc and mac commands, it's neccessary to copy   */
	X                        /* the received data.                                   */
	X
	X                        buffer_pt = acb_ptr->acbbaddr.pt;
	X                        /* The above instruction in theory should not be needed */
	X                        /* but is in practise                                   */ 
	X
	X                        if(bufbig <= buflim) /* Enough room in the buffer ? */
	X                        {
	X                                if(bufpt >= bufend) /* Wrap around ? */
	X                                {
	X                                        bufpt= buforg;
	X                                }
	X                                /* Size of packet inc. DLAYER first in buffer */
	X                                *((int *)bufpt)= acb_ptr->acblen + sizeof(DLAYER);
	X                                bufpt+= 2;
	X                                ((DLAYER *)bufpt)->type= intswap(acb_ptr->acbstatus);
	X                                for(i= 0; i < 6 ; i++)
	X                                {
	X                                        ((DLAYER *)bufpt)->dest[i]= 
	X                                                acb_ptr->acbladdr[i+9];
	X                                        ((DLAYER *)bufpt)->me[i]= 
	X                                                acb_ptr->acbraddr[i+9];
	X                                }
	X                                bufpt+= sizeof(DLAYER);
	X                                movedata(FP_SEG( buffer_pt ), FP_OFF( buffer_pt ), 
	X                                        FP_SEG(bufpt), FP_OFF(bufpt), acb_ptr->acblen);
	X                                bufpt+= acb_ptr->acblen;
	X                                bufbig+= acb_ptr->acblen + sizeof(DLAYER) + sizeof(int);
	X                        }
	X                        /* else we are going to drop packets ! */
	X                        }
	X                        break;
	X                }
	X        }
	X        return(0);
	X}
	X
SHAR_EOF
if test 15525 -ne "`wc -c < 'iso.c'`"
then
	echo shar: error transmitting "'iso.c'" '(should have been 15525 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'multi.asm'" '(1909 characters)'
if test -f 'multi.asm'
then
	echo shar: will not over-write existing file "'multi.asm'"
else
sed 's/^	X//' << \SHAR_EOF > 'multi.asm'
	XTITLE 'MULTI.ASM'
	X;
	X;       These assembler routine provide an interface between the code
	X;       written in 'C' and the Multi Protocol Handler.
	X;
	X
	X.model large
	X
	X;
	X;       Data Structures
	X;
	X.data
	X
	X;
	X;       The Asynchronous Notification Routine Stack
	X;
	X;       Size of stack is
	XSTACK_SIZE      EQU     100h
	X;
	X                DW      STACK_SIZE      DUP     (?)
	XSTACK_START     DW      ?
	X
	X;
	X;       Area to save Multi Protocol Handler Stack Pointer
	X;
	XSS_SAVE         DW      ?
	XSP_SAVE         DW      ?
	X;
	X
	X;
	X;       Start of Code
	X;
	X
	X
	X.code
	X
	XEXTRN   _anr_c : FAR
	X
	XPUBLIC  _ANR_ENTRY
	X
	X_ANR_ENTRY      PROC    
	X
	X;
	X;       This routine is the ANR entry point.  It is called by the
	X;       Multi Protocol Handler, via a far call.  Before calling the main
	X;       ANR routine (written in 'C'), it sets up the Data Segment, saves
	X;       the Multi Protocol Handler's stack, and allocates a new stack.
	X;       Before returning to the Multi Protocol Handler, it restores its
	X;       stack.
	X;
	X;       The ANR routine (written in 'C') must not make use of the heap, 
	X;       nor should it try to access to access automatic variables declared
	X;       in main(), because the stack it has been allocated is NOT the same
	X;       as the standard 'C' stack.
	X;
	X
	X        MOV     AX, DGROUP      ; Get Data Segement
	X        MOV     DS, AX          ; Set up DS
	X
	X        MOV     SS_SAVE, SS     ; Save Stack Pointers
	X        MOV     SP_SAVE, SP     ;
	X
	X        MOV     SS, AX          ; Set up Stack Segment
	X        LEA     SP, STACK_START ; 
	X
	X        PUSH    ES              ; The address of the ACB is passed as
	X        PUSH    BX              ; a far pointer.
	X
	X        CLD
	X
	X        CALL    _anr_c          ; Call 'C' ANR routine
	X                                ; _ANR_C returns a parameter in AX
	X
	X        MOV     SS, SS_SAVE     ; Restore Stack Pointers
	X        MOV     SP, SP_SAVE
	X
	X        RET
	X_ANR_ENTRY      ENDP
	X
	X        END
	X
SHAR_EOF
if test 1909 -ne "`wc -c < 'multi.asm'`"
then
	echo shar: error transmitting "'multi.asm'" '(should have been 1909 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pctools.c'" '(11904 characters)'
if test -f 'pctools.c'
then
	echo shar: will not over-write existing file "'pctools.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'pctools.c'
	X/*
	X*  pctools.c
	X****************************************************************************
	X*                                                                          *
	X*      part of:                                                            *
	X*      TCP/UDP/ICMP/IP Network kernel for NCSA Telnet                      *
	X*      by Tim Krauskopf                                                    *
	X*                                                                          *
	X*      National Center for Supercomputing Applications                     *
	X*      152 Computing Applications Building                                 *
	X*      605 E. Springfield Ave.                                             *
	X*      Champaign, IL  61820                                                *
	X*                                                                          *
	X****************************************************************************
	X*
	X*  those generic tool-type things that only work on PCs.
	X*  includes all hardware-level calls to Ethernet that are unique to the PC
	X*
	X*  Function pointers for Ether calls
	X*/
	X#include "stdio.h"
	X#include "protocol.h"
	X#include "data.h"
	X
	X/*
	X*   defined in assembly language file for interrupt driven Ether buffering
	X*
	X*/
	X#ifdef MSC
	Xextern unsigned char rstat;                    /* status from last read */
	Xextern char *bufpt,*bufend,*bufread,*buforg;
	Xextern int bufbig,buflim;
	X#else
	Xunsigned char rstat;                    /* status from last read */
	Xchar *bufpt,*bufend,*bufread,*buforg;
	Xint bufbig,buflim;
	X#endif /* MSC */
	X
	X/*
	X*  Declare each and every Ethernet driver.
	X*  To add a driver, pick a unique 2 char prefix and declare your own
	X*  routines.  I want to keep the same parameters for EVERY driver.
	X*  If your driver needs additional parameters, then see netconfig() below 
	X*  for an indication of where to put custom board code.
	X*/
	Xextern int E1etopen(),E1getaddr(),E1setaddr(),E1recv(),E1xmit(),E1etupdate(),E1etclose();
	Xextern int E3etopen(),E3getaddr(),E3setaddr(),E3recv(),E3xmit(),E3etupdate(),E3etclose();
	Xextern int M5etopen(),M5getaddr(),M5recv(),M5xmit(),M5etupdate(),M5etclose();
	Xextern int U1etopen(),U1getaddr(),U1recv(),U1xmit(),U1etupdate(),U1etclose();
	Xextern int U2etopen(),U2getaddr(),U2recv(),U2xmit(),U2etupdate(),U2etclose();
	Xextern int WDetopen(),WDgetaddr(),WDrecv(),WDxmit(),WDetupdate(),WDetclose();
	Xextern int E2etopen(),E2getaddr(),E2recv(),E2xmit(),E2etupdate(),E2etclose();
	X#ifdef ISOLAN
	Xextern int ILetopen(),ILgetaddr(),ILrecv(),ILxmit(),ILetupdate(),ILetclose();
	X#endif
	X
	Xstatic int (*etopen)()=NULL,    /* open the device */
	X        (*getaddr)()=NULL,              /* get the Ether address */
	X        (*setaddr)()=NULL,                      /* set the Ether address to use */
	X        (*recv)()=NULL,                         /* load a packet from queue */
	X        (*etupdate)()=NULL,                     /* update pointers in buffer */
	X        (*etclose)()=NULL,                      /* shut down network */
	X        (*xmit)()=NULL;                         /* transmit a packet */
	X
	X
	X/**********************************************************************/
	X/*  statcheck
	X*   look at the connection status of the memory buffers to see if the
	X*   allocation schemes are working.  Only used as a debug tool.
	X*/
	Xstatcheck()
	X        {
	X        int i;
	X        struct port *p;
	X
	X        for (i=0; i<20; i++) {
	X                printf("\n%d > ",i);
	X                p = portlist[i];
	X                if (p != NULL) 
	X                        printf("state: %d  %5u  %5u  %10ld  %5d  %5d",
	X                                        p->state,intswap(p->tcpout.t.source),
	X                                        intswap(p->tcpout.t.dest),p->out.lasttime,p->rto,
	X                                        p->out.contain);
	X        }
	X}
	X
	X/*************************************************************************/
	X/*  config network parameters
	X*   Set IRQ and DMA parameters for initialization of the 3com adaptor
	X*/
	Xstatic int nnirq=3,nnaddr=0xd000,nnioaddr=0x300;
	X
	Xnetparms(irq,address,ioaddr)
	X        int irq,address,ioaddr;
	X        {
	X
	X        nnirq = irq;
	X        nnaddr = address;
	X        nnioaddr = ioaddr;
	X
	X        return(0);
	X}
	X
	X/**********************************************************************/
	X/* netconfig
	X*  load the function pointers for network access
	X*  Currently setaddr() is not used, so it isn't loaded.
	X*
	X*  Note that netparms is called BEFORE netconfig.  So if you have any
	X*  really special variables to set for your board that involve
	X*  irq,address and ioaddr, you can add calls to your special routines
	X*  in this section.
	X*
	X*  Some drivers will do the interrupt driver and board initialization
	X*  in etopen() and some will do it in getaddr().
	X*/
	Xnetconfig(s)
	X        char *s;
	X        {
	X
	X        if (!strncmp(s,"ni5",3) || !strncmp(s,"mi",2)) {
	X                etopen = M5etopen;
	X                xmit = M5xmit;
	X                recv = M5recv;
	X                getaddr = M5getaddr;
	X                etupdate = M5etupdate;
	X                etclose = M5etclose;
	X/*
	X*   special initialization call would go here
	X*/
	X        }
	X        else if (!strncmp(s,"nicps",5)) {
	X                etopen = U2etopen;
	X                xmit = U2xmit;
	X                recv = U2recv;
	X                getaddr = U2getaddr;
	X                etupdate = U2etupdate;
	X                etclose = U2etclose;
	X        }
	X        else if (!strncmp(s,"nicpc",5) || !strncmp(s,"pcnic",5)) {
	X                etopen = U1etopen;
	X                xmit = U1xmit;
	X                recv = U1recv;
	X                getaddr = U1getaddr;
	X                etupdate = U1etupdate;
	X                etclose = U1etclose;
	X        }
	X        else if (!strncmp(s,"wd",2) || !strncmp(s,"800",3)) {
	X                etopen = WDetopen;
	X                xmit = WDxmit;
	X                recv = WDrecv;
	X                getaddr = WDgetaddr;
	X                etupdate = WDetupdate;
	X                etclose = WDetclose;
	X        }
	X        else if (!strncmp(s,"3c523",5) || !strncmp(s,"523",3)) {
	X                etopen = E2etopen;
	X                xmit = E2xmit;
	X                recv = E2recv;
	X                getaddr = E2getaddr;
	X                etupdate = E2etupdate;
	X                etclose = E2etclose;
	X        }
	X        else if (!strncmp(s,"r501",4)) {                /* special reserve driver */
	X                etopen = E3etopen;
	X                xmit = E3xmit;
	X                recv = E3recv;
	X                getaddr = E3getaddr;
	X                etupdate = E3etupdate;
	X                etclose = E3etclose;
	X        }
	X#ifdef ISOLAN
	X        else if (!strncmp(s,"iso",3)) {
	X                etopen = ILetopen;
	X                xmit = ILxmit;
	X                recv = ILrecv;
	X                getaddr = ILgetaddr;
	X                etupdate = ILetupdate;
	X                etclose = ILetclose;
	X        }
	X#endif
	X        else if (!strncmp(s,"3c",2) || 1) {             /* default choice */
	X                etopen = E1etopen;
	X                xmit = E1xmit;
	X                recv = E1recv;
	X                getaddr = E1getaddr;
	X                etupdate = E1etupdate;
	X                etclose = E1etclose;
	X        }
	X
	X}
	X
	X/**********************************************************************/
	X/*  netarpme
	X*   send an arp to my address.  arpinterpret will notice any response.
	X*   Checks for adapters which receive their own broadcast packets.
	X*/
	Xnetarpme(s)
	X        char *s;
	X        {
	X
	X        if (etopen == U2etopen)
	X                return(0);
	X        if (etopen == U1etopen)
	X                return(0);
	X
	X        reqarp(s);              /* send it */
	X
	X        return(0);
	X}
	X
	X
	X/**********************************************************************/
	X
	Xinitbuffer()
	X        {
	X
	X        bufpt = bufread = buforg = raw; /*  start at the beginning */
	X
	X        bufend = &raw[14500];                   /* leave 2K breathing room, required */
	X        buflim = 12000;                      /* another 2K breathing room */
	X
	X        (*getaddr)(nnmyaddr,nnaddr,nnioaddr);
	X
	X        return(0);
	X}
	X
	X/**********************************************************************/
	X/*   demux
	X*      find the packets in the buffer, determine their lowest level
	X*  packet type and call the correct interpretation routines
	X*
	X*  the 'all' parameter tells demux whether it should attempt to empty
	X*  the input packet buffer or return after the first packet is dealt with.
	X*
	X*  returns the number of packets demuxed
	X*/
	Xdemux(all)
	X        int all;
	X        {
	X        uint16 getcode;
	X        int nmuxed;
	X        DLAYER *firstlook;
	X
	X        nmuxed = 0;
	X        if (!etupdate)                                  /* check that network is hooked up */
	X                return(0);
	X
	X        do {                                                    /* while all flag is on */
	X
	X                (*recv)();                                      /* NULL operation for 3COM */
	X
	X                if (bufbig > 0) {
	X
	X                        nmuxed++;
	X                        firstlook = (DLAYER *)(bufread+2);      /* where packet is */
	X
	X                        getcode = firstlook->type;                      /* where does it belong? */
	X
	X                        switch (getcode) {                                      /* what to do with it? */
	X                                case EARP:
	X                                case ERARP:
	X                                        arpinterpret(firstlook);        /* handle ARP packet */
	X                                        break;
	X                                case EIP:
	X                                        ipinterpret(firstlook);
	X                                        break;
	X                                default:
	X                                        break;
	X                        }
	X
	X                        (*etupdate)();                  /* update read pointers in buffer, free packet */
	X
	X                }
	X                else 
	X                        all = 0;
	X
	X
	X        } while (all);                  /* should we look for more to deal with? */
	X
	X
	X        return(nmuxed);          /* no packets anymore */
	X
	X}
	X
	X/************************************************************************/
	X/*  dlayersend
	X*
	X*  usage:   err = dlayersend(ptr,size)
	X*      err = 0 for successful, non-zero error code otherwise
	X*      ptr is to a dlayer packet header
	X*      size is the number of bytes total
	X*
	X*  This particular dlayer routine is for Ethernet.  It will have to be
	X*  replaced for any other dlayer.
	X*
	X*  Ethernet addresses are resolved at higher levels because they will only
	X*  need to be resolved once per logical connection, instead of once per
	X*  packet.  Not too layer-like, but hopefully modular.
	X*
	X*/
	X
	Xdlayersend(ptr,size)
	X        DLAYER *ptr;
	X        unsigned size;
	X        {
	X        int ret;
	X        
	X        ret = (*xmit)(ptr,size);        /* send it out, pass back return code */
	X                                                                /* xmit checks for size < 60 */
	X
	X/*
	X*   automatic, immediate retry once
	X*/
	X        if (ret) {
	X                if (ret == (*xmit)(ptr,size))
	X                        nnerror(100);           /* post user error message */
	X        }
	X
	X        return(ret);
	X}
	X
	X/***************************************************************************/
	X/* dlayerinit
	X*  Do machine dependent initializations of whatever hardware we have
	X*  (happens to be ethernet board here ) 
	X*/
	Xdlayerinit()
	X        {
	X
	X        if (initbuffer() || !etopen)
	X                return(-1);
	X
	X        return((*etopen)(nnmyaddr,nnirq,nnaddr,nnioaddr));
	X}
	X
	Xdlayershut()
	X        {
	X        if (etclose)
	X                (*etclose)();
	X}
	X
	X/***************************************************************************/
	X/*  pcgetaddr
	X*   return results from indirect getaddr call.
	X*   This is a pc-specific request for the 48-bit address which was added
	X*   so that the user program could print the value.
	X*/
	Xpcgetaddr(s,x,y)
	X        char *s;
	X        int x,y;
	X        {
	X        if (getaddr)
	X                (*getaddr)(s,x,y);
	X}
SHAR_EOF
if test 11904 -ne "`wc -c < 'pctools.c'`"
then
	echo shar: error transmitting "'pctools.c'" '(should have been 11904 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'makefile'" '(4342 characters)'
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'makefile'
	X# Makefile for NCSA telnet version 2.2S with added features by jkp@hutcs.hut.fi
	X# Author: Jyrki Kuoppala (jkp@hutcs.hut.fi)
	X# Last modified: 89.05.25 by Inge Arnesen (ingea@ifi.uio.no)
	X
	X# Assumes that you have LIB and INCLUDE environment variables
	X# set to proper values for your compiler
	X
	X# I haven't tested the lattice version of makefile.
	X# All knowledge I have about lattice is from the 'compile.bat'
	X# script, so you should probably study the flags and change them
	X# if necessary
	X
	X# Change the value of CC to lc if you have lattice, cl if msc.
	X# It should be enough, but probably you need to change lattice part
	X# Or, just say 'gmake CC=lc' or 'gmake CC=cl'
	X
	XCC=cl
	X#CC=lc
	X
	X# Use this if backspace mapping doesn't work with you.
	X# If you use it, however, ^H isn't ^H if mapping is on.
	X
	X#BUGSPACE=-DBugspace
	X
	X#ifeq ($(CC),cl)
	X#   Use this for MSC 5.0.  Stack-checking is suppressed ; the interrupt
	X#   routine setup doesn't work with it and I don't like the compiler generating
	X#   code I haven't asked for anyhow :-)
	XCFLAGS= -c -Otl -AL -DMSC -Itek -Ivs -Ienet -Iftp -I. -Gs -Zpi -DISOLAN
	XASFLAGS=-Itek -Ivs -Ienet -DMicrosoft $(BUGSPACE)
	X#else
	X#   For lattice, untested
	X#   remove -qd: if you don't have a ram disk called d:
	X#CFLAGS= -ml -qd:
	X#ASFLAGS=-Itek -Ivs -Ienet -DLattice $(BUGSPACE)
	X#endif
	X
	XVPATH=.\vs:.\tek:.\enet:.\ftp
	X
	XAS=masm
	XLIB=lib
	XLIBFLAGS=
	XLINK=link
	XSTACK=/stack:4096
	XLINKFLAGS=/CO
	XRM=command /c del
	X
	X#LDFLAGS=/Fencsa /AL
	X
	X#.SUFFIXES: .c .o .obj .exe .asm
	X
	X.c.obj:
	X        $(CC) $(CFLAGS) /Fo$*.obj $<
	X
	X.asm.obj:
	X        $(AS) $(ASFLAGS) $<, $*.obj  ;
	X
	Xall: minitel.exe telpass.exe telbin.exe finger.exe ftpbin.exe
	X
	Xtcp1m.lib : tcp.obj ip.obj dlayer.obj tools.obj multi.obj iso.obj pctools.obj enet\net8003.obj \
	X                enet\net3com.obj enet\net501.obj enet\net5210.obj enet\net523.obj \
	X                enet\netzyp.obj enet\netub.obj \
	X                protinit.obj user.obj ipasm.obj
	X        $(RM) tcp1m.lib
	X        $(LIB) $(LIBFLAGS) tcp1m.lib +tcp +ip +dlayer +tools +iso+multi+pctools ;
	X        $(LIB) $(LIBFLAGS) tcp1m.lib+protinit+user+ipasm+\
	X        enet\net8003+enet\net3com+enet\netzyp+enet\net501+enet\net5210+enet\net523+enet\netub ;
	X
	Xsessm.lib : util.obj pcutil.obj bkgr.obj confile.obj
	X        $(RM) sessm.lib
	X        $(LIB) $(LIBFLAGS) sessm.lib +util +pcutil +bkgr +confile ;
	X
	Xvs.lib: vs\vsinterf.obj vs\vsem.obj vs\vsintern.obj
	X        $(RM) vs.lib
	X        $(LIB) $(LIBFLAGS) vs.lib +vs\vsinterf +vs\vsintern +vs\vsem ;
	X
	Xtek.lib: tek\vgtek.obj tek\tekstor.obj tek\egaset.obj tek\rg0.obj tek\rge.obj tek\rgc.obj \
	X          tek\rgh.obj tek\rgp.obj tek\rghp.obj tek\rg9.obj 
	X        $(RM) tek.lib
	X        $(LIB) $(LIBFLAGS) tek.lib +tek\vgtek +tek\tekstor +tek\rg0 +tek\rge +tek\rgc \
	X         +tek\rgh +tek\rgp +tek\rghp +tek\rg9 +tek\egaset ;
	X
	Xtelbin.exe : look.obj ncsaio.obj rspc.obj tek.lib sessm.lib tcp1m.lib vs.lib
	X        $(LINK) $(LINKFLAGS) $(STACK) look+ncsaio+rspc,telbin,nul,tek+tcp1m+sessm+vs ;
	X
	Xtelpass.exe : telpass.obj ncsaio.obj
	X        $(LINK) $(LINKFLAGS) telpass+ncsaio,telpass,nul ;
	X
	Xftpbin.exe : ftp\ftpbin.obj ncsaio.obj tcp1m.lib sessm.lib
	X        $(LINK) $(LINKFLAGS) ftp\ftpbin+ncsaio,ftpbin,nul,tcp1m+sessm ;
	X
	Xminitel.exe : minitel.obj ncsaio.obj tcp1m.lib sessm.lib
	X        $(LINK) $(LINKFLAGS) minitel+ncsaio,minitel,nul,tcp1m+sessm ;
	X
	Xfinger.exe : finger.obj ncsaio.obj tcp1m.lib sessm.lib
	X        $(LINK) $(LINKFLAGS) finger+ncsaio,finger,nul,tcp1m+sessm ;
	X
	Xtar:
	X        (cd .. ; tar cf hackedsrc.tar source )
	X
	Xclean:
	X        $(RM) *.obj
	X        $(RM) make.out
	X        $(RM) *.exe
	X        $(RM) *.lib
	X        $(RM) *.bak
	X
	Xftpbin.obj : ftp\ftpbin.c ftp\ftppi.h
	X
	Xbkgr.obj: bkgr.c whatami.h hostform.h
	Xconfile.obj: confile.c whatami.h hostform.h
	Xdlayer.obj: dlayer.c protocol.h data.h
	Xfinger.obj: finger.c whatami.h hostform.h
	Xip.obj: ip.c protocol.h data.h
	Xlook.obj: look.c whatami.h nkeys.h windat.h hostform.h
	Xminitel.obj: minitel.c whatami.h hostform.h
	Xiso.obj: iso.c protocol.h data.h
	X
	Xmulti.obj: multi.asm
	X        masm -Zi -Ml multi.asm;
	X
	Xpctools.obj: pctools.c protocol.h data.h
	Xpcutil.obj: pcutil.c whatami.h
	Xprotinit.obj: protinit.c protocol.h data.h whatami.h
	Xrspc.obj: rspc.c whatami.h windat.h vskeys.h nkeys.h
	Xtcp.obj: tcp.c protocol.h data.h
	Xtools.obj: tools.c protocol.h data.h
	Xuser.obj: user.c protocol.h data.h
	Xutil.obj: util.c whatami.h hostform.h
SHAR_EOF
if test 4342 -ne "`wc -c < 'makefile'`"
then
	echo shar: error transmitting "'makefile'" '(should have been 4342 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0