home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / NCSA / TEL2307S.ZIP / NET / ENET / NET.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-19  |  17.4 KB  |  662 lines

  1. /*
  2. *  net.c
  3. *****************************************************************************
  4. *                                                                              *
  5. *      part of:                                                                *
  6. *      TCP/UDP/ICMP/IP Network kernel for NCSA Telnet                        *
  7. *      by Tim Krauskopf                                                        *
  8. *                                                                              *
  9. *      National Center for Supercomputing Applications                         *
  10. *      152 Computing Applications Building                                     *
  11. *      605 E. Springfield Ave.                                                 *
  12. *      Champaign, IL  61820                                                    *
  13. *                                                                              *
  14. *****************************************************************************
  15. *
  16. *   Revision History:
  17. *   9/91    Add SLIP support    Nelson B. Bolyard
  18. *
  19. *  those generic tool-type things that only work on PCs.
  20. *  includes all hardware-level calls to Ethernet that are unique to the PC
  21. *
  22. *  Function pointers for Ether calls
  23. */
  24.  
  25. /*#define DEBUG*/
  26.  
  27. #ifdef NETD
  28. # include <conio.h>
  29. #else
  30. #ifdef DEBUG
  31. # include <conio.h>
  32. #endif
  33. #endif
  34. #include "debug.h"
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include "protocol.h"
  38. #include "data.h"
  39. #include "hostform.h"
  40. #include "externs.h"
  41.  
  42. int SQwait=0;
  43. int OKpackets=0;
  44.  
  45. /*
  46. *   defined in assembly language file for interrupt driven Ether buffering
  47. *
  48. */
  49.  
  50. extern unsigned char rstat;        /* last status from read */
  51. extern char *bufpt,                /* current buffer pointer */
  52.     *bufend,                    /* pointer to end of buffer */
  53.     *bufread,                    /* pointer to where program is reading */
  54.     *buforg;                    /* pointer to beginning of buffer */
  55.  
  56. extern int bufbig,                /* number of bytes currently in buffer */
  57.     buflim;                        /* max number of bytes in buffer */
  58.  
  59. struct config def;
  60.  
  61. /*
  62. *  Declare each and every Ethernet driver.
  63. *  To add a driver, pick a unique 2 char prefix and declare your own
  64. *  routines.  I want to keep the same parameters for EVERY driver.
  65. *  If your driver needs additional parameters, then see netconfig() below 
  66. *  for an indication of where to put custom board code.
  67. */
  68. #ifndef PKT_ONLY /* save 20K by compiling packet driver only  rmg 931100 */
  69. extern int CDECL E1etopen(),
  70.     CDECL E1getaddr(),
  71.     CDECL E1setaddr(),
  72.     CDECL E1recv(),
  73.     CDECL E1xmit(),
  74.     CDECL E1etupdate(),
  75.     CDECL E1etclose();
  76. extern int CDECL E3etopen(),
  77.     CDECL E3getaddr(),
  78.     CDECL E3setaddr(),
  79.     CDECL E3recv(),
  80.     CDECL E3xmit(),
  81.     CDECL E3etupdate(),
  82.     CDECL E3etclose();
  83. extern int CDECL E5etopen(),
  84.     CDECL E5getaddr(),
  85.     CDECL E5setaddr(),
  86.     CDECL E5recv(),
  87.     CDECL E5xmit(),
  88.     CDECL E5etupdate(),
  89.     CDECL E5etclose(),
  90.     CDECL E5etdma();
  91. extern int CDECL ATetopen(),
  92.     CDECL ATgetaddr(),
  93.     CDECL ATrecv(),
  94.     CDECL ATxmit(),
  95.     CDECL ATetupdate(),
  96.     CDECL ATetclose();
  97. extern int CDECL M5etopen(),
  98.     CDECL M5getaddr(),
  99.     CDECL M5recv(),
  100.     CDECL M5xmit(),
  101.     CDECL M5etupdate(),
  102.     CDECL M5etclose();
  103. extern int CDECL M9etopen(),
  104.     CDECL M9getaddr(),
  105.     CDECL M9recv(),
  106.     CDECL M9xmit(),
  107.     CDECL M9etupdate(),
  108.     CDECL M9etclose();
  109. extern int CDECL U1etopen(),
  110.     CDECL U1getaddr(),
  111.     CDECL U1recv(),
  112.     CDECL U1xmit(),
  113.     CDECL U1etupdate(),
  114.     CDECL U1etclose();
  115. extern int CDECL U2etopen(),
  116.     CDECL U2getaddr(),
  117.     CDECL U2recv(),
  118.     CDECL U2xmit(),
  119.     CDECL U2etupdate(),
  120.     CDECL U2etclose();
  121. extern int CDECL WDetopen(),
  122.     CDECL WDgetaddr(),
  123.     CDECL WDrecv(),
  124.     CDECL WDxmit(),
  125.     CDECL WDetupdate(),
  126.     CDECL WDetclose();
  127. extern int CDECL WAetopen(),
  128.     CDECL WAgetaddr(),
  129.     CDECL WArecv(),
  130.     CDECL WAxmit(),
  131.     CDECL WAetupdate(),
  132.     CDECL WAetclose();
  133. extern int CDECL E2etopen(),
  134.     CDECL E2getaddr(),
  135.     CDECL E2recv(),
  136.     CDECL E2xmit(),
  137.     CDECL E2etupdate(),
  138.     CDECL E2etclose();
  139. extern int CDECL E4etopen(),
  140.     CDECL E4getaddr(),
  141.     CDECL E4recv(),
  142.     CDECL E4xmit(),
  143.     CDECL E4etupdate(),
  144.     CDECL E4etclose();
  145. #endif /* PKT_ONLY */
  146.  
  147. #ifndef EXTERNS_H
  148. extern int CDECL LTopen(),
  149.     CDECL LTgetaddr(),
  150.     CDECL LTxmit(),
  151.     CDECL LTclose();
  152.     extern void CDECL LTrecv(),
  153.         CDECL LTupdate();
  154. extern int CDECL pketopen(),
  155.     CDECL pkgetaddr(),
  156.     CDECL pkxmit(),
  157.     CDECL pketclose();
  158.     extern void CDECL pkrecv(),
  159.         CDECL pketupdate();
  160. extern int CDECL DNetopen(),
  161.     CDECL DNgetaddr(),
  162.     CDECL DNxmit(),
  163.     CDECL DNetclose();
  164.     extern void CDECL DNrecv(),
  165.         CDECL DNetupdate();
  166. extern int CDECL ILetopen(),
  167.     CDECL ILgetaddr(),
  168.     CDECL ILxmit(),
  169.     CDECL ILetclose();
  170.     extern void CDECL ILrecv(),
  171.         CDECL ILetupdate();
  172. #endif
  173.  
  174. static int CDECL (*etopen)(unsigned char *s,unsigned int irq,unsigned int addr,unsigned int ioaddr)=NULL,       /* open the device */
  175.     CDECL (*getaddr)(unsigned char *s,unsigned int addr,unsigned int ioaddr)=NULL,                    /* get the Ether address */
  176.     CDECL (*setaddr)(char *s,int addr,int ioaddr)=NULL,     /* set the Ether address */
  177.     CDECL (*etclose)(void )=NULL,                           /* shut down network */
  178.     CDECL (*xmit)(DLAYER *packet,unsigned int count)=NULL;    /* transmit a packet */
  179. static void CDECL (*recv)(void )=NULL,                      /* load a packet from queue  */
  180.     CDECL (*etupdate)(void )=NULL;                          /* update pointers in buffer */
  181.  
  182. #ifndef NET14
  183. #ifdef NOT_USED
  184. /**********************************************************************/
  185. /*  statcheck
  186. *   look at the connection status of the memory buffers to see if the
  187. *   allocation schemes are working.  Only used as a debug tool.
  188. */
  189.  
  190. void statcheck(void )
  191. {
  192.     int i;
  193.     struct port *p;
  194.  
  195.     for(i=0; i<20; i++) {
  196.         printf("\n%d > ",i);
  197.         p=portlist[i];
  198.         if(p!=NULL) 
  199.             printf("state: %d  %5u  %5u  %10ld  %5d  %5d",
  200.                     p->state,intswap(p->tcpout.t.source),
  201.                     intswap(p->tcpout.t.dest),p->out.lasttime,p->rto,
  202.                     p->out.contain);
  203.       }    /* end for */
  204. }
  205. #endif
  206. #endif
  207.  
  208. /*************************************************************************/
  209. /*  config network parameters
  210. *   Set IRQ and DMA parameters for initialization of the 3com adaptor
  211. */
  212. static uint nnirq=3,nnaddr=0xd000,nnioaddr=0x300;
  213.  
  214. int netparms(uint irq,uint address,uint ioaddr)
  215. {
  216.     BUG("netparms");
  217.  
  218.     nnirq=irq;
  219.     nnaddr=address;
  220.     nnioaddr=ioaddr;
  221. #ifdef DEBUG
  222.     printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
  223.     printf("press a key\n");
  224.     getch();
  225. #endif
  226.     return(0);
  227. }
  228.  
  229. /**********************************************************************/
  230. /* netconfig
  231. *  load the function pointers for network access
  232. *  Currently setaddr() is not used, so it isn't loaded.
  233. *
  234. *  Note that netparms is called BEFORE netconfig.  So if you have any
  235. *  really special variables to set for your board that involve
  236. *  irq,address and ioaddr, you can add calls to your special routines
  237. *  in this section.
  238. *
  239. *  Some drivers will do the interrupt driver and board initialization
  240. *  in etopen() and some will do it in getaddr().
  241. */
  242. void netconfig(char *s)
  243. {
  244.  
  245.     Sgetconfig(&def);                /* get information provided in hosts file */
  246.  
  247. #ifndef PKT_ONLY
  248.     if(!strncmp(s,"iso",3) || !strncmp(s,"bicc",4)) {
  249.         etopen=ILetopen;
  250.         xmit=ILxmit;
  251.         recv=ILrecv;
  252.         getaddr=ILgetaddr;
  253.         etupdate=ILetupdate;
  254.         etclose=ILetclose;
  255.       } /* end if */
  256.     else if(!strncmp(s,"3c505",5) || !strncmp(s,"505",3)) {
  257.         etopen=E5etopen;
  258.         xmit=E5xmit;
  259.         recv=E5recv;
  260.         getaddr=E5getaddr;
  261.         etupdate=E5etupdate;
  262.         etclose=E5etclose;
  263.       } /* end if */
  264.     else if(!strncmp(s,"decnet",6) || !strncmp(s,"dn",2)) {
  265.         etopen=DNetopen;
  266.         xmit=DNxmit;
  267.         recv=DNrecv;
  268.         getaddr=DNgetaddr;
  269.         etupdate=DNetupdate;
  270.         etclose=DNetclose;
  271.       }    /* end if */
  272.     else if(!strncmp(s,"star10",6) || !strncmp(s,"starlan",7)) {
  273.         etopen=ATetopen;
  274.         xmit=ATxmit;
  275.         recv=ATrecv;
  276.         getaddr=ATgetaddr;
  277.         etupdate=ATetupdate;
  278.         etclose=ATetclose;
  279.       }    /* end if */
  280.   else if(!strncmp(s,"packet",6)) {
  281. #else
  282.   if(!strncmp(s,"packet",6)) {
  283. #endif /* PKT_ONLY */
  284.         etopen=pketopen;
  285.         xmit=pkxmit;
  286.         recv=pkrecv;
  287.         getaddr=pkgetaddr;
  288.         etupdate=pketupdate;
  289.         etclose=pketclose;
  290.       }
  291. #ifndef PLT_ONLY
  292.     else if(!strncmp(s,"ni9",3) || !strncmp(s,"92",2)) {
  293.         etopen=M9etopen;
  294.         xmit=M9xmit;
  295.         recv=M9recv;
  296.         getaddr=M9getaddr;
  297.         etupdate=M9etupdate;
  298.         etclose=M9etclose;
  299.     }
  300.     else if(!strncmp(s,"ni5",3) || !strncmp(s,"mi",2)) {
  301.         etopen=M5etopen;
  302.         xmit=M5xmit;
  303.         recv=M5recv;
  304.         getaddr=M5getaddr;
  305.         etupdate=M5etupdate;
  306.         etclose=M5etclose;
  307. /*
  308. *   special initialization call would go here
  309. */
  310.     }
  311.     else if(!strncmp(s,"nicps",5)) {
  312.         etopen=U2etopen;
  313.         xmit=U2xmit;
  314.         recv=U2recv;
  315.         getaddr=U2getaddr;
  316.         etupdate=U2etupdate;
  317.         etclose=U2etclose;
  318.     }
  319.     else if(!strncmp(s,"nicpc",5) || !strncmp(s,"pcnic",5)) {
  320.         etopen=U1etopen;
  321.         xmit=U1xmit;
  322.         recv=U1recv;
  323.         getaddr=U1getaddr;
  324.         etupdate=U1etupdate;
  325.         etclose=U1etclose;
  326.     }
  327.     else if(!strncmp(s,"wd8003a",7) || !strncmp(s,"8003a",5)) {
  328.         etopen=WAetopen;
  329.         xmit=WAxmit;
  330.         recv=WArecv;
  331.         getaddr=WAgetaddr;
  332.         etupdate=WAetupdate;
  333.         etclose=WAetclose;
  334.     }
  335.     else if(!strncmp(s,"wd",2) || !strncmp(s,"800",3)) {
  336.         etopen=WDetopen;
  337.         xmit=WDxmit;
  338.         recv=WDrecv;
  339.         getaddr=WDgetaddr;
  340.         etupdate=WDetupdate;
  341.         etclose=WDetclose;
  342.     }
  343.     else if(!strncmp(s,"3c523",5) || !strncmp(s,"523",3)) {
  344.         etopen=E2etopen;
  345.         xmit=E2xmit;
  346.         recv=E2recv;
  347.         getaddr=E2getaddr;
  348.         etupdate=E2etupdate;
  349.         etclose=E2etclose;
  350.     }
  351.     else if( !strncmp(s,"3c503",5) || !strncmp(s,"503",3)) {
  352.         etopen=E4etopen;
  353.         xmit=E4xmit;
  354.         recv=E4recv;
  355.         getaddr=E4getaddr;
  356.         etupdate=E4etupdate;
  357.         etclose=E4etclose;
  358.         E4setwire(def.wire*2);
  359.     }
  360.     else if(!strncmp(s,"ltalk",5) || !strncmp(s,"atalk",5) || !strncmp(s,"apple",5)) {
  361.         extern unsigned int LTalk_vector;
  362.  
  363.         nnkip=1;                    /* turn kip arping on */
  364.         LTalk_vector=nnirq;
  365. #ifdef __WATCOMC__
  366.         etopen=(void *)LTopen;
  367. #else
  368.         etopen=LTopen;
  369. #endif
  370.         xmit=LTxmit;
  371.         recv=LTrecv;
  372. #ifdef __WATCOMC__
  373.         getaddr=(void *)LTgetaddr;
  374. #else
  375.         getaddr=LTgetaddr;
  376. #endif
  377.         etupdate=LTupdate;
  378.         etclose=LTclose;
  379.     }
  380.     else if(!strncmp(s,"r501",4)) {        /* special reserve driver */
  381.         etopen=E3etopen;
  382.         xmit=E3xmit;
  383.         recv=E3recv;
  384.         getaddr=E3getaddr;
  385.         etupdate=E3etupdate;
  386.         etclose=E3etclose;
  387.     }
  388.     else {        /* default choice */
  389.         etopen=E1etopen;
  390.         xmit=E1xmit;
  391.         recv=E1recv;
  392.         getaddr=E1getaddr;
  393.         etupdate=E1etupdate;
  394.         etclose=E1etclose;
  395.     }
  396. #else
  397.   else {    /* default choice */
  398.     fprintf(stdout,"You are using the PACKET DRIVER ONLY version of Telnet\n");
  399. #ifdef AUX
  400.     fprintf(stdaux," packet driver version ");
  401. #endif
  402.     }
  403. #endif
  404. }   /* end netconfig() */
  405.  
  406. /**********************************************************************/
  407. /*  netarpme
  408. *   send an arp to my address.  arpinterpret will notice any response.
  409. *   Checks for adapters which receive their own broadcast packets.
  410. */
  411. int netarpme(char *s)
  412. {
  413. #ifndef PKT_ONLY
  414.     if(etopen==U2etopen)
  415.         return(0);
  416.     if(etopen==U1etopen)
  417.         return(0);
  418. #endif
  419. #ifdef __WATCOMC__
  420.     if(etopen==(void *)LTopen)      /* not needed for Local Talk */
  421.         return(0);
  422. #else
  423.     if(etopen==LTopen)      /* not needed for Local Talk */
  424.         return(0);
  425. #endif
  426.     reqarp(s);        /* send it */
  427.     return(0);
  428. }   /* end netarpme() */
  429.  
  430. /**********************************************************************/
  431. int initbuffer(void)
  432. {
  433.     bufpt=bufread=buforg=raw;    /*  start at the beginning */
  434.     BUG("initbuffer");
  435.  
  436.     bufbig=0;
  437. #if defined(NET14)
  438.     bufend=&raw[4500];          /* leave 2K breathing room, required */
  439.     buflim=2000;                /* another 2K breathing room */
  440. #elif defined(__TURBOC__) || defined(__WATCOMC__)
  441.     bufend=&raw[7500];            /* leave 2K breathing room, required */
  442.     buflim=5000;                /* another 2K breathing room */
  443. #else
  444.     bufend=&raw[14500];            /* leave 2K breathing room, required */
  445.     buflim=12000;                /* another 2K breathing room */
  446. #endif
  447.  
  448.     BUG("before getaddr");
  449. #ifdef DEBUG
  450.     printf("nnmyaddr=%X;nnaddr=%X;nnioaddr=%X\n",nnmyaddr,nnaddr,nnioaddr);
  451.     printf("getaddr = %p\n",getaddr);
  452.     printf("press a key\n");
  453.     getch();
  454. #endif
  455.  
  456. BUG("about to getaddr");
  457. /* QAK was if-def'ed out */
  458.     (*getaddr)(nnmyaddr,nnaddr,nnioaddr);
  459. BUG("after getaddr");
  460.  
  461. #ifdef NETD
  462.     printf("Addr=%x.%x.%x.%x.%x.%x\n",nnmyaddr[0],nnmyaddr[1],nnmyaddr[2],
  463.         nnmyaddr[3],nnmyaddr[4],nnmyaddr[5]);
  464. #endif
  465.     return(0);
  466. }
  467.  
  468. /**********************************************************************/
  469. /*   demux
  470. *      find the packets in the buffer, determine their lowest level
  471. *  packet type and call the correct interpretation routines
  472. *
  473. *  the 'all' parameter tells demux whether it should attempt to empty
  474. *  the input packet buffer or return after the first packet is dealt with.
  475. *
  476. *  returns the number of packets demuxed
  477. */
  478. int demux(int all)
  479. {
  480.     uint16 getcode;
  481.     int nmuxed;
  482.     DLAYER *firstlook;
  483.  
  484.     nmuxed=0;
  485.     if(!etupdate)                    /* check that network is hooked up */
  486.         return(0);
  487.     do {                            /* while all flag is on */
  488.         (*recv)();                    /* NULL operation for 3COM */
  489. #ifdef NETD
  490. printf("After Masking!\n");
  491. printf("bufpt->%p, bufread->%p, bufend->%p\n",bufpt,bufread,bufend);
  492. printf("bufbig = %d\n", bufbig);
  493. getch();
  494. #endif
  495.         if(bufbig>0) {
  496.             nmuxed++;
  497.             firstlook=(DLAYER *)(bufread+2);     /* where packet is */
  498. #ifdef CHECKRARP
  499. fprintf(stderr,"dest=%x.%x.%x.%x.%x.%x, me=%x.%x.%x.%x.%x.%x, type=0x%X\r\n",
  500.         (unsigned int)firstlook->dest[0],(unsigned int)firstlook->dest[1],(unsigned int)firstlook->dest[2],
  501.         (unsigned int)firstlook->dest[3],(unsigned int)firstlook->dest[4],(unsigned int)firstlook->dest[5],
  502.         (unsigned int)firstlook->me[0],(unsigned int)firstlook->me[1],(unsigned int)firstlook->me[2],
  503.         (unsigned int)firstlook->me[3],(unsigned int)firstlook->me[4],(unsigned int)firstlook->me[5],
  504.         firstlook->type);
  505. fprintf(stderr,"big=%d, size=%d\r\n",bufbig,(int)(bufpt-bufread));
  506. #endif
  507.  
  508.             getcode=firstlook->type;        /* where does it belong? */
  509.             switch(getcode) {                /* what to do with it? */
  510.                 case EARP:
  511.                 case ERARP:
  512. #ifdef CHECKRARP
  513. fprintf(stderr,"arp\r\n");
  514. #endif
  515.                     arpinterpret((ARPKT *)firstlook);    /* handle ARP packet */
  516.                     break;
  517.  
  518.                 case EIP:
  519. #ifdef CHECKRARP
  520. fprintf(stderr,"ip\r\n");
  521. #endif
  522.                     ipinterpret((IPKT *)firstlook);
  523.                     break;
  524.  
  525.                 default:
  526. #ifdef CHECKRARP
  527. fprintf(stderr,"garbage\r\n");
  528. #endif
  529.                     break;
  530.               }    /* end switch */
  531.             (*etupdate)();        /* update read pointers in buffer, free packet */
  532.           }    /* end if */
  533.         else 
  534.             all=0;
  535.       }    while(all);        /* should we look for more to deal with? */
  536.     return(nmuxed);        /* no packets anymore */
  537. }   /* end demux() */
  538.  
  539. /************************************************************************/
  540. /*  dlayersend
  541. *
  542. *  usage:   err=dlayersend(ptr,size)
  543. *      err=0 for successful, non-zero error code otherwise
  544. *      ptr is to a dlayer packet header
  545. *      size is the number of bytes total
  546. *
  547. *  This particular dlayer routine is for Ethernet.  It will have to be
  548. *  replaced for any other dlayer.
  549. *
  550. *  Ethernet addresses are resolved at higher levels because they will only
  551. *  need to be resolved once per logical connection, instead of once per
  552. *  packet.  Not too layer-like, but hopefully modular.
  553. *
  554. */
  555. int dlayersend(DLAYER *ptr,unsigned int size)
  556. {
  557.     int ret,i;
  558.  
  559. #ifndef OLD_WAY
  560.     if(size<60)
  561.         size=60;
  562.     if(size&0x01)
  563.         size+=1;
  564. #else
  565. #ifdef NEW_WAY
  566.     unsigned char *c;
  567.  
  568.     c=(unsigned char *)ptr;
  569.     *(c+size++)=0;        /* NULL pad last char */
  570.     *(c+size++)=0;        /* NULL pad last char */
  571. #else
  572.     unsigned char *c;
  573.     unsigned int u;
  574.  
  575.     /* This code is sort of a synthesis of the previous two pieces of code, let's see if it works */
  576.     c=(unsigned char *)ptr;
  577.     if(size<60) {
  578.         for(u=size,c+=size; u<60; u++)
  579.             *c++=0;     /* NULL pad added chars */
  580.         size=60;
  581.       } /* end if */
  582. #ifdef QAK
  583.     if(size&0x01)
  584.         *(c+size++)=0;  /* NULL pad last char */
  585. #endif
  586. #endif
  587. #endif
  588.  
  589.     for(i=0; i<SQwait; i++);
  590.  
  591.     if((++OKpackets)>10) {
  592.         SQwait-=10;
  593.         OKpackets=0;
  594.       } /* end if */
  595.  
  596.     if(SQwait<10)
  597.         SQwait=10;
  598.  
  599.     ret=(*xmit)((DLAYER *)ptr,size);    /* send it out, pass back return code */
  600.                                     /* xmit checks for size < 60 */
  601. /*
  602. *   automatic, immediate retry once
  603. */
  604.     if(ret) {
  605.         if(ret==(*xmit)((DLAYER *)ptr,size))
  606.             nnerror(100);        /* post user error message */
  607.       } /* end if */
  608.     return(ret);
  609. }   /* end dlayersend() */
  610.  
  611. /***************************************************************************/
  612. /* dlayerinit
  613. *  Do machine dependent initializations of whatever hardware we have
  614. *  (happens to be ethernet board here ) 
  615. */
  616. int dlayerinit(void )
  617. {
  618.     int my_var;
  619.  
  620.     BUG("dlayerinit");
  621. #ifdef DEBUG    
  622.     printf("etopen = %p\n",etopen);
  623. #endif
  624.     if(initbuffer() || !etopen)
  625.         return(-10);
  626.  
  627. #ifdef QAK
  628. printf("dlayerinit(): after initbuffer()\n");
  629. printf("etopen=%p\n",etopen);
  630. printf("nnmyaddr=%p\n",nnmyaddr);
  631. printf("nnirq=%x, nnaddr=%x, nnioaddr=%x\n",(uint16)nnirq,(uint16)nnaddr,(uint16)nnioaddr);
  632. getch();
  633. #endif
  634. /*
  635.  * Call (*etopen) first to be sure any board/driver initializations are taken care of
  636.  */
  637.     my_var = ((*etopen)(nnmyaddr,nnirq,nnaddr,nnioaddr));
  638. #ifdef QAK
  639. printf("my_var is %d\n", my_var);
  640. getch();
  641. #endif
  642.     return(my_var);
  643. }
  644.  
  645. void dlayershut(void )
  646. {
  647.     if(etclose)
  648.         (*etclose)();
  649. }
  650.  
  651. /***************************************************************************/
  652. /*  pcgetaddr
  653. *   return results from indirect getaddr call.
  654. *   This is a pc-specific request for the 48-bit address which was added
  655. *   so that the user program could print the value.
  656. */
  657. void pcgetaddr(char *s,int x,int y)
  658. {
  659.     if(getaddr)
  660.         (*getaddr)(s,x,y);
  661. }
  662.