home *** CD-ROM | disk | FTP | other *** search
- /*
- * net.c
- *****************************************************************************
- * *
- * part of: *
- * TCP/UDP/ICMP/IP Network kernel for NCSA Telnet *
- * by Tim Krauskopf *
- * *
- * National Center for Supercomputing Applications *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- * *
- *****************************************************************************
- *
- * those generic tool-type things that only work on PCs.
- * includes all hardware-level calls to Ethernet that are unique to the PC
- *
- * Function pointers for Ether calls
- */
-
- /*#define DEBUG*/
-
- #ifdef NETD
- # include <conio.h>
- #else
- #ifdef DEBUG
- # include <conio.h>
- #endif
- #endif
- #include "debug.h"
- #include <stdio.h>
- #include <string.h>
- #ifdef MEMORY_DEBUG
- #include "memdebug.h"
- #endif
- #include "protocol.h"
- #include "data.h"
- #include "hostform.h"
- #include "externs.h"
-
- int SQwait=0;
- int OKpackets=0;
-
- /*
- * defined in assembly language file for interrupt driven Ether buffering
- *
- */
-
- extern unsigned char rstat; /* last status from read */
- extern char *bufpt, /* current buffer pointer */
- *bufend, /* pointer to end of buffer */
- *bufread, /* pointer to where program is reading */
- *buforg; /* pointer to beginning of buffer */
-
- extern int bufbig, /* number of bytes currently in buffer */
- buflim; /* max number of bytes in buffer */
-
- struct config def;
-
- /*
- * Declare each and every Ethernet driver.
- * To add a driver, pick a unique 2 char prefix and declare your own
- * routines. I want to keep the same parameters for EVERY driver.
- * If your driver needs additional parameters, then see netconfig() below
- * for an indication of where to put custom board code.
- */
- extern int E1etopen(),E1getaddr(),E1setaddr(),E1recv(),E1xmit(),E1etupdate(),E1etclose();
- extern int E3etopen(),E3getaddr(),E3setaddr(),E3recv(),E3xmit(),E3etupdate(),E3etclose();
- extern int E5etopen(),E5getaddr(),E5setaddr(),E5recv(),E5xmit(),E5etupdate(),E5etclose(),E5etdma();
- extern int ATetopen(),ATgetaddr(),ATrecv(),ATxmit(),ATetupdate(),ATetclose();
- extern int M5etopen(),M5getaddr(),M5recv(),M5xmit(),M5etupdate(),M5etclose();
- extern int M9etopen(),M9getaddr(),M9recv(),M9xmit(),M9etupdate(),M9etclose();
- extern int U1etopen(),U1getaddr(),U1recv(),U1xmit(),U1etupdate(),U1etclose();
- extern int U2etopen(),U2getaddr(),U2recv(),U2xmit(),U2etupdate(),U2etclose();
- extern int WDetopen(),WDgetaddr(),WDrecv(),WDxmit(),WDetupdate(),WDetclose();
- extern int WAetopen(),WAgetaddr(),WArecv(),WAxmit(),WAetupdate(),WAetclose();
- extern int E2etopen(),E2getaddr(),E2recv(),E2xmit(),E2etupdate(),E2etclose();
- extern int LTopen(),LTgetaddr(),LTrecv(),LTxmit(),LTupdate(),LTclose();
- extern int pketopen(),pkgetaddr(),pkxmit(),pketclose();
- extern void pkrecv(),pketupdate();
- extern int E4etopen(),E4getaddr(),E4recv(),E4xmit(),E4etupdate(),E4etclose();
- extern int DNetopen(),DNgetaddr(),DNxmit(),DNetclose();
- extern void DNrecv(),DNetupdate();
- extern int ILetopen(),ILgetaddr(),ILxmit(),ILetclose();
- extern void ILrecv(),ILetupdate();
-
- #ifdef __WATCOMC__
- static int cdecl
- #else
- static int
- #endif /* __WATCOMC__ */
- (*etopen)(unsigned char *s,unsigned int irq,unsigned int addr,
- unsigned int ioaddr)=NULL, /* open the device */
- (*getaddr)(unsigned char *s,unsigned int addr,
- unsigned int ioaddr)=NULL, /* get the Ether address */
- (*setaddr)(char *s,int addr,int ioaddr)=NULL, /* set the Ether address */
- (*etclose)(void )=NULL, /* shut down network */
- (*xmit)(DLAYER *packet,int count)=NULL; /* transmit a packet */
- #ifdef __WATCOMC__
- static void cdecl
- #else
- static void
- #endif /* __WATCOMC__ */
- (*recv)(void )=NULL, /* load a packet from queue */
- (*etupdate)(void )=NULL; /* update pointers in buffer */
-
- /**********************************************************************/
- /* statcheck
- * look at the connection status of the memory buffers to see if the
- * allocation schemes are working. Only used as a debug tool.
- */
-
- void statcheck(void )
- {
- int i;
- struct port *p;
-
- for(i=0; i<20; i++) {
- printf("\n%d > ",i);
- p=portlist[i];
- if(p!=NULL)
- printf("state: %d %5u %5u %10ld %5d %5d",
- p->state,intswap(p->tcpout.t.source),
- intswap(p->tcpout.t.dest),p->out.lasttime,p->rto,
- p->out.contain);
- } /* end for */
- }
-
- /*************************************************************************/
- /* config network parameters
- * Set IRQ and DMA parameters for initialization of the 3com adaptor
- */
- static uint nnirq=3,nnaddr=0xd000,nnioaddr=0x300;
-
- int netparms(irq,address,ioaddr)
- uint irq,address,ioaddr;
- {
- BUG("netparms");
-
- nnirq=irq;
- nnaddr=address;
- nnioaddr=ioaddr;
- #ifdef DEBUG
- printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
- printf("press a key\n");
- getch();
- #endif
- return(0);
- }
-
- /**********************************************************************/
- /* netconfig
- * load the function pointers for network access
- * Currently setaddr() is not used, so it isn't loaded.
- *
- * Note that netparms is called BEFORE netconfig. So if you have any
- * really special variables to set for your board that involve
- * irq,address and ioaddr, you can add calls to your special routines
- * in this section.
- *
- * Some drivers will do the interrupt driver and board initialization
- * in etopen() and some will do it in getaddr().
- */
- void netconfig(s)
- char *s;
- {
-
- Sgetconfig(&def); /* get information provided in hosts file */
-
- if(!strncmp(s,"iso",3) || !strncmp(s,"bicc",4)) {
- etopen=ILetopen;
- xmit=ILxmit;
- recv=ILrecv;
- getaddr=ILgetaddr;
- etupdate=ILetupdate;
- etclose=ILetclose;
- } /* end if */
- else if(!strncmp(s,"3c505",5) || !strncmp(s,"505",3)) {
- etopen=E5etopen;
- xmit=E5xmit;
- recv=E5recv;
- getaddr=E5getaddr;
- etupdate=E5etupdate;
- etclose=E5etclose;
- } /* end if */
- else if(!strncmp(s,"decnet",6) || !strncmp(s,"dn",2)) {
- etopen=DNetopen;
- xmit=DNxmit;
- recv=DNrecv;
- getaddr=DNgetaddr;
- etupdate=DNetupdate;
- etclose=DNetclose;
- } /* end if */
- else if(!strncmp(s,"star10",6) || !strncmp(s,"starlan",7)) {
- etopen=ATetopen;
- xmit=ATxmit;
- recv=ATrecv;
- getaddr=ATgetaddr;
- etupdate=ATetupdate;
- etclose=ATetclose;
- } /* end if */
- else if(!strncmp(s,"packet",6)) {
- BUG("packetdriver - setting to pk funcs");
- etopen=pketopen;
- xmit=pkxmit;
- recv=pkrecv;
- getaddr=pkgetaddr;
- etupdate=pketupdate;
- etclose=pketclose;
- }
- else if(!strncmp(s,"ni9",3) || !strncmp(s,"92",2)) {
- etopen=M9etopen;
- xmit=M9xmit;
- recv=M9recv;
- getaddr=M9getaddr;
- etupdate=M9etupdate;
- etclose=M9etclose;
- }
- else if(!strncmp(s,"ni5",3) || !strncmp(s,"mi",2)) {
- etopen=M5etopen;
- xmit=M5xmit;
- recv=M5recv;
- getaddr=M5getaddr;
- etupdate=M5etupdate;
- etclose=M5etclose;
- /*
- * special initialization call would go here
- */
- }
- else if(!strncmp(s,"nicps",5)) {
- etopen=U2etopen;
- xmit=U2xmit;
- recv=U2recv;
- getaddr=U2getaddr;
- etupdate=U2etupdate;
- etclose=U2etclose;
- }
- else if(!strncmp(s,"nicpc",5) || !strncmp(s,"pcnic",5)) {
- etopen=U1etopen;
- xmit=U1xmit;
- recv=U1recv;
- getaddr=U1getaddr;
- etupdate=U1etupdate;
- etclose=U1etclose;
- }
- else if(!strncmp(s,"wd8003a",7) || !strncmp(s,"8003a",5)) {
- etopen=WAetopen;
- xmit=WAxmit;
- recv=WArecv;
- getaddr=WAgetaddr;
- etupdate=WAetupdate;
- etclose=WAetclose;
- }
- else if(!strncmp(s,"wd",2) || !strncmp(s,"800",3)) {
- etopen=WDetopen;
- xmit=WDxmit;
- recv=WDrecv;
- getaddr=WDgetaddr;
- etupdate=WDetupdate;
- etclose=WDetclose;
- }
- else if(!strncmp(s,"3c523",5) || !strncmp(s,"523",3)) {
- etopen=E2etopen;
- xmit=E2xmit;
- recv=E2recv;
- getaddr=E2getaddr;
- etupdate=E2etupdate;
- etclose=E2etclose;
- }
- else if( !strncmp(s,"3c503",5) || !strncmp(s,"503",3)) {
- etopen=E4etopen;
- xmit=E4xmit;
- recv=E4recv;
- getaddr=E4getaddr;
- etupdate=E4etupdate;
- etclose=E4etclose;
- E4setwire(def.wire*2);
- }
- else if(!strncmp(s,"ltalk",5) || !strncmp(s,"atalk",5) || !strncmp(s,"apple",5)) {
- extern unsigned int LTalk_vector;
-
- nnkip=1; /* turn kip arping on */
- LTalk_vector=nnirq;
- etopen=LTopen;
- xmit=LTxmit;
- recv=LTrecv;
- getaddr=LTgetaddr;
- etupdate=LTupdate;
- etclose=LTclose;
- }
- else if(!strncmp(s,"r501",4)) { /* special reserve driver */
- etopen=E3etopen;
- xmit=E3xmit;
- recv=E3recv;
- getaddr=E3getaddr;
- etupdate=E3etupdate;
- etclose=E3etclose;
- }
- else { /* default choice */
- etopen=E1etopen;
- xmit=E1xmit;
- recv=E1recv;
- getaddr=E1getaddr;
- etupdate=E1etupdate;
- etclose=E1etclose;
- }
- }
-
- /**********************************************************************/
- /* netarpme
- * send an arp to my address. arpinterpret will notice any response.
- * Checks for adapters which receive their own broadcast packets.
- */
- int netarpme(s)
- char *s;
- {
- if(etopen==U2etopen)
- return(0);
- if(etopen==U1etopen)
- return(0);
- if(etopen==LTopen) /* not needed for Local Talk */
- return(0);
- reqarp(s); /* send it */
- return(0);
- }
-
- /**********************************************************************/
- int initbuffer()
- {
- bufpt=bufread=buforg=raw; /* start at the beginning */
- BUG("initbuffer");
-
- bufbig=0;
- #ifdef _TURBOC_
- bufend=&raw[7500]; /* leave 2K breathing room, required */
- buflim=5000; /* another 2K breathing room */
- #else
- bufend=&raw[14500]; /* leave 2K breathing room, required */
- buflim=12000; /* another 2K breathing room */
- #endif
-
- BUG("before getaddr");
- #ifdef DEBUG
- printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
- printf("getaddr = %p\n",getaddr);
- printf("press a key\n");
- getch();
- #endif
-
- BUG("about to getaddr");
- /* QAK was if-def'ed out */
- (*getaddr)(nnmyaddr,nnaddr,nnioaddr);
- BUG("after getaddr");
-
- #ifdef NETD
- printf("Addr=%x.%x.%x.%x.%x.%x\n",nnmyaddr[0],nnmyaddr[1],nnmyaddr[2],
- nnmyaddr[3],nnmyaddr[4],nnmyaddr[5]);
- #endif
- return(0);
- }
-
- /**********************************************************************/
- /* demux
- * find the packets in the buffer, determine their lowest level
- * packet type and call the correct interpretation routines
- *
- * the 'all' parameter tells demux whether it should attempt to empty
- * the input packet buffer or return after the first packet is dealt with.
- *
- * returns the number of packets demuxed
- */
- int demux(all)
- int all;
- {
- uint16 getcode;
- int nmuxed;
- DLAYER *firstlook;
-
- nmuxed=0;
- if(!etupdate) /* check that network is hooked up */
- return(0);
- do { /* while all flag is on */
- (*recv)(); /* NULL operation for 3COM */
- #ifdef NETD
- printf("After Masking!\n");
- printf("pt->%p, read->%p, end->%p\n",bufpt,bufread,bufend);
- printf("\n HAHA \n");
- printf("bufbig = %d\n", bufbig);
- getch();
- #endif
- if(bufbig>0) {
- nmuxed++;
- firstlook=(DLAYER *)(bufread+2); /* where packet is */
- #ifdef NETD
- printf("dest=%x.%x.%x.%x.%x.%x, me=%x.%x.%x.%x.%x.%x, type=%d\n",
- (unsigned int)firstlook->dest[0],(unsigned int)firstlook->dest[1],(unsigned int)firstlook->dest[2],
- (unsigned int)firstlook->dest[3],(unsigned int)firstlook->dest[4],(unsigned int)firstlook->dest[5],
- (unsigned int)firstlook->me[0],(unsigned int)firstlook->me[1],(unsigned int)firstlook->me[2],
- (unsigned int)firstlook->me[3],(unsigned int)firstlook->me[4],(unsigned int)firstlook->me[5],
- firstlook->type);
- printf("big=%d, size=%d\n",bufbig,(int)(bufpt - bufread));
- getch();
-
- #endif
- getcode=firstlook->type; /* where does it belong? */
- switch(getcode) { /* what to do with it? */
- case EARP:
- case ERARP:
- #ifdef NETD
- printf("arp\n");
- #endif
- arpinterpret((ARPKT *)firstlook); /* handle ARP packet */
- break;
-
- case EIP:
- #ifdef NETD
- printf("ip\n");
- #endif
- ipinterpret((IPKT *)firstlook);
- break;
-
- default:
- #ifdef NETD
- printf("garbage\n");
- #endif
- break;
- } /* end switch */
- (*etupdate)(); /* update read pointers in buffer, free packet */
- } /* end if */
- else
- all=0;
- } while(all); /* should we look for more to deal with? */
- return(nmuxed); /* no packets anymore */
- }
-
- /************************************************************************/
- /* dlayersend
- *
- * usage: err=dlayersend(ptr,size)
- * err=0 for successful, non-zero error code otherwise
- * ptr is to a dlayer packet header
- * size is the number of bytes total
- *
- * This particular dlayer routine is for Ethernet. It will have to be
- * replaced for any other dlayer.
- *
- * Ethernet addresses are resolved at higher levels because they will only
- * need to be resolved once per logical connection, instead of once per
- * packet. Not too layer-like, but hopefully modular.
- *
- */
-
- int dlayersend(ptr,size)
- DLAYER *ptr;
- unsigned size;
- {
- int ret,i;
-
- #ifdef OLD_WAY
- if(size<60)
- size=60;
- if(size&0x01)
- size+=1;
- #else
- unsigned char *c;
-
- c=(unsigned char *)ptr;
- *(c+size++)=0; /* NULL pad last char */
- *(c+size++)=0; /* NULL pad last char */
- #endif
-
- for(i=0;i<SQwait;i++);
- if((++OKpackets)>10){
- SQwait -= 10;
- OKpackets = 0;
- }
- if (SQwait < 10) SQwait = 10;
-
- ret=(*xmit)((DLAYER *)ptr,size); /* send it out, pass back return code */
- /* xmit checks for size < 60 */
- /*
- * automatic, immediate retry once
- */
- if(ret) {
- if(ret == (*xmit)((DLAYER *)ptr,size))
- nnerror(100); /* post user error message */
- }
- return(ret);
- }
-
- /***************************************************************************/
- /* dlayerinit
- * Do machine dependent initializations of whatever hardware we have
- * (happens to be ethernet board here )
- */
- int dlayerinit(void )
- {
- int my_var;
- BUG("dlayerinit");
- #ifdef DEBUG
- printf("etopen = %p\n",etopen);
- #endif
- if(initbuffer() || !etopen)
- return(-10);
-
- #ifdef NETD
- printf("dlayerinit(): after initbuffer()\n");
- printf("etopen=%p\n",etopen);
- printf("nnirq=%x, nnaddr=%x, nnioaddr=%x\n",(uint16)nnirq,(uint16)nnaddr,(uint16)nnioaddr);
- getch();
- #endif
- /*
- * Call (*etopen) first to be sure any board/driver initializations are taken care of
- */
- my_var = ((*etopen)(nnmyaddr,nnirq,nnaddr,nnioaddr));
- #ifdef NETD
- printf("my_var is %d\n", my_var);
- getch();
- #endif
- return my_var;
- }
-
- void dlayershut(void )
- {
- if(etclose)
- (*etclose)();
- }
-
- /***************************************************************************/
- /* pcgetaddr
- * return results from indirect getaddr call.
- * This is a pc-specific request for the 48-bit address which was added
- * so that the user program could print the value.
- */
- void pcgetaddr(s,x,y)
- char *s;
- int x,y;
- {
- if(getaddr)
- (*getaddr)(s,x,y);
- }
-