home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / NETWORK / SLFP123.ZIP / SLFP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-05  |  36.4 KB  |  1,895 lines

  1. /****************************************************************
  2.  *                                                                *
  3.  *                SLFP packet driver                                *
  4.  *                                                                *
  5.  *    Glenn H McGregor, Merit Computer Network                    *
  6.  *    William A Simpson, Computer Systems Consulting Services        *
  7.  *                                                                *
  8.  ****************************************************************/
  9.  
  10. #define SLFP_VERSION    "1.23"
  11.  
  12. /*
  13.  *  trace
  14.  */
  15.  
  16. #undef  DEBUG
  17. #define SCREEN_EGA
  18. #define TRACE_HEX
  19. #define TRACE_ALL_HEX
  20.  
  21. #ifdef DEBUG
  22. #define trace(ch,color) Trace(ch,color)
  23. #else
  24. #define trace(ch,color)
  25. #endif
  26.  
  27. /*
  28.  *  Includes
  29.  */
  30.  
  31. #include    <stdio.h>
  32. #include    <stdlib.h>
  33. #include    <conio.h>
  34. #include    <dos.h>
  35. #include    <mem.h>
  36. #include    <graphics.h>
  37. #include    <string.h>
  38.  
  39. #include    "getopt.h"
  40. #include    "gen.h"
  41.  
  42. /*
  43.  *  Memory layout
  44.  */
  45.  
  46. word    _stklen        =    256;
  47. word    _heaplen    =    256;
  48.  
  49. /*
  50.  *  Configuration options & defaults
  51.  */
  52.  
  53. byte    ConfPackInt        =    0x60;
  54. byte    ConfSerialIrq    =    4;
  55. word    ConfSerialBase    =    0x3F8;
  56. word    ConfSerialSpeed    =    2400;
  57. char    ConfSerialDial[40] =    "";
  58. word    ConfInitTime    =    60;
  59. byte    ConfHandshake    =    1;
  60. byte    ConfFifoCheck    =    1;
  61.  
  62. /*
  63.  *  Error level returns
  64.  */
  65.  
  66. enum
  67.     {
  68.     ERL_none,
  69.     ERL_parse,
  70.     ERL_packet,
  71.     ERL_break,
  72.     ERL_handshake
  73.     };
  74.  
  75. /*
  76.  *  SLFP characters
  77.  */
  78.  
  79. enum
  80.     {
  81.     SLFP_ESC    =    0xF2,    /* next character substitution */
  82.     SLFP_REQ    =    0xF3,    /* request transmit oportunity */
  83.     SLFP_ACK    =    0xF4,    /* transmit request acknowledged */
  84.     SLFP_END    =    0xF5,    /* end of transmission block */
  85.     };
  86.  
  87. /*
  88.  *  Interrupt events
  89.  */
  90.  
  91. enum
  92.     {
  93.     RECV_RDA,
  94.     RECV_GOT_REQ
  95.     };
  96.  
  97. enum
  98.     {
  99.     XMIT_MESSAGE,
  100.     XMIT_GOT_REQ,
  101.     XMIT_GOT_ACK,
  102.     XMIT_THRE,
  103.     XMIT_LOOP,
  104.     XMIT_TIMEOUT
  105.     };
  106.  
  107. /*
  108.  *  I/O queues
  109.  */
  110.  
  111. #define    QLEN    0x1000
  112.  
  113. word        RecvQHead    =    0;
  114. word        RecvQTail    =    0;
  115. int            RecvQSize    =    0;
  116. byte        RecvQ[QLEN];
  117.  
  118. word        XmitQHead    =    0;
  119. word        XmitQTail    =    0;
  120. int            XmitQSize    =    0;
  121. byte        XmitQ[QLEN];
  122.  
  123. /*
  124.  *  8250 I/O base offsets
  125.  */
  126.  
  127. enum
  128.     {
  129.     IOO_THR        =    0,        /* transmitter holding register */
  130.     IOO_RBR        =    0,        /* receiver buffer register */
  131.     IOO_DLL        =    0,        /* divisor latch LSB */
  132.     IOO_DLM        =    1,        /* divisor latch MSB */
  133.     IOO_IER        =    1,        /* interrupt enable register */
  134.     IOO_IIR        =    2,        /* interrupt ident register */
  135.     IOO_FCR        =    2,        /* fifo control register */
  136.     IOO_LCR        =    3,        /* line control register */
  137.     IOO_MCR        =    4,        /* modem control register */
  138.     IOO_LSR        =    5,        /* line status register */
  139.     IOO_MSR        =    6        /* modem status register */
  140.     };
  141.  
  142. /*
  143.  *  8250 line control register
  144.  */
  145.  
  146. enum
  147.     {
  148.     LCR_5BITS    =    0x00,    /* five bit words */
  149.     LCR_6BITS    =    0x01,    /* six bit words */
  150.     LCR_7BITS    =    0x02,    /* seven bit words */
  151.     LCR_8BITS    =    0x03,    /* eight bit words */
  152.     LCR_NSB        =    0x04,    /* number of stop bits */
  153.     LCR_PEN        =    0x08,    /* parity enable */
  154.     LCR_EPS        =    0x10,    /* even parity select */
  155.     LCR_SP        =    0x20,    /* stick parity */
  156.     LCR_SB        =    0x40,    /* set break */
  157.     LCR_DLAB    =    0x80    /* divisor latch access bit */
  158.     };
  159.  
  160. /*
  161.  *  8250 line status register
  162.  */
  163.  
  164. enum
  165.     {
  166.     LSR_DR        =    0x01,    /* data ready */
  167.     LSR_OE        =    0x02,    /* overrun error */
  168.     LSR_PE        =    0x04,    /* parity error */
  169.     LSR_FE        =    0x08,    /* framing error */
  170.     LSR_BI        =    0x10,    /* break interrupt */
  171.     LSR_THRE    =    0x20,    /* transmitter line holding register empty */
  172.     LSR_TSRE    =    0x40,    /* transmitter shift register empty */
  173.     };
  174.  
  175. /*
  176.  *  8250 interrupt identification register
  177.  */
  178.  
  179. enum
  180.     {
  181.     IIR_IP        =    0x01,    /* not interrupt pending */
  182.     IIR_ID        =    0x06,    /* mask for interrupt id */
  183.     IIR_RLS        =    0x06,    /* receive line status interrupt */
  184.     IIR_RDA        =    0x04,    /* receive data available interrupt */
  185.     IIR_THRE    =    0x02,    /* transmit holding reg empty interrupt */
  186.     IIR_MSTAT    =    0x00,    /* modem status interrupt */
  187.  
  188.     IIR_FIFO_TO    =    0x08,    /* fifo timeout interrupt pending (16550A only */
  189.     IIR_FIFO_ENB=    0xC0    /* fifo enabled (16550A only) */
  190.     };
  191.  
  192. /*
  193.  *  8250 interrupt enable register bits
  194.  */
  195.  
  196. enum
  197.     {
  198.     IER_DAV        =    0x01,    /* data available interrupt */
  199.     IER_TXE        =    0x02,    /* transmit buffer empty interrupt */
  200.     IER_RLS        =    0x04,    /* receive line status interrupt */
  201.     IER_MS        =    0x08    /* modem status interrupt */
  202.     };
  203.  
  204. /*
  205.  *  8250 modem control register
  206.  */
  207.  
  208. enum
  209.     {
  210.     MCR_DTR        =    0x01,    /* data terminal ready */
  211.     MCR_RTS        =    0x02,    /* request to send */
  212.     MCR_OUT1    =    0x04,    /* out 1 (not used) */
  213.     MCR_OUT2    =    0x08,    /* out 2 (master interrupt enable) */
  214.     MCR_LOOP    =    0x10    /* loopback test mode */
  215.     };
  216.  
  217. /*
  218.  *  8250 modem status register
  219.  */
  220.  
  221. enum
  222.     {
  223.     MSR_DCTS    =    0x01,    /* delta clear-to-send */
  224.     MSR_DDSR    =    0x02,    /* delta data-set-ready */
  225.     MSR_TERI    =    0x04,    /* trailing edge ring indicator */
  226.     MSR_DRLSD    =    0x08,    /* delta rx line signal detect */
  227.     MSR_CTS        =    0x10,    /* clear-to-send */
  228.     MSR_DSR        =    0x20,    /* data-set-ready */
  229.     MSR_RI        =    0x40,    /* ring indicator */
  230.     MSR_RLSD    =    0x80    /* received line signal detect */
  231.     };
  232. /*
  233.  *  16550 fifo control register
  234.  */
  235.  
  236. enum
  237.     {
  238.     FCR_RESET    =    0x00,    /* disable TX & RX fifo */
  239.     FCR_ENABLE    =    0x01,    /* enable TX & RX fifo */
  240.     FCR_CLR_RX    =    0x02,    /* clear receive fifo */
  241.     FCR_CLR_TX    =    0x04,    /* clear transmit fifo */
  242.     FCR_ST_DMA    =    0x08,    /* enable TXRDY/RXRDY pin DMA handshake */
  243.  
  244.     FCR_RXT_1    =    0x00,    /* RX fifo trigger levels */
  245.     FCR_RXT_4    =    0x40,
  246.     FCR_RXT_8    =    0x80,
  247.     FCR_RXT_14    =    0xC0,
  248.  
  249.     FCR_SETUP    =    FCR_ENABLE|FCR_CLR_RX|FCR_CLR_TX|FCR_RXT_4
  250.     };
  251.  
  252. /*
  253.  *  Serial global data
  254.  */
  255.  
  256. word        Serial_IOBase;    /* I/O address of 8250 chip */
  257. byte        Serial_IRQ;        /* Interrupt number of 8250 chip */
  258. dword        Serial_Speed;    /* Line speed of interface */
  259. InterruptPtrType
  260.             SaveSerialInt;    /* Old serial ISR */
  261.  
  262. dword        RealIP_Address;
  263. BOOLEAN        Serial_16550A = FALSE;    /* UART is a 16550A */
  264. byte        XmitCount = 1;            /* number of bytes to transmit */
  265. BOOLEAN        Serial_Handshake = FALSE;    /* REQ/ACK handshake has occurred */
  266.  
  267. word        IOA_THR        =    IOO_THR;
  268. word        IOA_RBR        =    IOO_RBR;
  269. word        IOA_DLL        =    IOO_DLL;
  270. word        IOA_DLM        =    IOO_DLM;
  271. word        IOA_IER        =    IOO_IER;
  272. word        IOA_IIR        =    IOO_IIR;
  273. word        IOA_FCR        =    IOO_FCR;
  274. word        IOA_LCR        =    IOO_LCR;
  275. word        IOA_MCR        =    IOO_MCR;
  276. word        IOA_LSR        =    IOO_LSR;
  277. word        IOA_MSR        =    IOO_MSR;
  278.  
  279. #define    IOA_First    IOA_THR
  280. #define    IOA_Count    11
  281.  
  282. dword        IOE_LostTHRE=    0;
  283. dword        IOE_OverRun    =    0;
  284. dword        IOE_Parity    =    0;
  285. dword        IOE_Framing    =    0;
  286. dword        IOE_Break    =    0;
  287. dword        IOE_ReqTO    =    0;
  288. dword        IOE_IntrIn    =    0;
  289. dword        IOE_IntrOut    =    0;
  290. dword        IOE_FifoHi    =    0;
  291. dword        IOE_FifoTO    =    0;
  292. #define    IOE_Table    IOE_LostTHRE
  293.  
  294. dword        IOS_PktIn    =    0;
  295. dword        IOS_PktOut    =    0;
  296. dword        IOS_ByteIn    =    0;
  297. dword        IOS_ByteOut    =    0;
  298. dword        IOS_ErrIn    =    0;
  299. dword        IOS_ErrOut    =    0;
  300. dword        IOS_PktDrop    =    0;
  301. #define    IOS_Table    IOS_PktIn
  302.  
  303. /*
  304.  *  Timer support
  305.  */
  306.  
  307. #define    SECONDS        18
  308. InterruptPtrType
  309.             SaveTimerInt;
  310. word        InitTimer    =    0;
  311. word        XmitTimer    =    0;
  312.  
  313. /*
  314.  *  Packet Driver Hook
  315.  */
  316.  
  317. char                    PacketDriverHook[17];
  318. InterruptPtrType        SavePacketInt;
  319.  
  320. /*
  321.  *  Handle Table
  322.  */
  323.  
  324. typedef void (far *RecvType)(void);
  325.  
  326. typedef    struct
  327.     {
  328.     byte        Hand_InUse;
  329.     byte        Hand_TypeLen;
  330.     RecvType    Hand_Receiver;
  331.     word        Hand_TypeVal;
  332.     }    HandleType;
  333.  
  334. HandleType        HandleTable;
  335.  
  336. /*
  337.  *  Packet Driver values
  338.  */
  339.  
  340. #define        PD_version        0x0010
  341. #define        PDV_basic        1
  342. #define        PDV_extended    2
  343. #define        PDT_Merit        1
  344. #define        PDT_any            0xFFFF
  345. char        PDN_slfp[]    =    "SLFP8250";
  346.  
  347. /*
  348.  *  Packet Driver Classes
  349.  */
  350.  
  351. enum    PD_Classes
  352.     {
  353.     PDC_Ethernet    =    1,
  354.     PDC_Pronet_10,
  355.     PDC_IEEE_8025,
  356.     PDC_Omninet,
  357.     PDC_Appletalk,
  358.     PDC_SerialLine,
  359.     PDC_Starlan,
  360.     PDC_Arcnet,
  361.     PDC_AX25,
  362.     PDC_KISS,
  363.     PDC_IEEE_8023,
  364.     PDC_FDDI,
  365.     PDC_Internet_X25,
  366.     PDC_LANSTAR,
  367.     PDC_SLFP
  368.     };
  369.  
  370. /*
  371.  *  Function calls
  372.  */
  373.  
  374. enum    PD_Functions
  375.     {
  376.     PDF_DriverInfo            =    1,
  377.     PDF_AccessType,
  378.     PDF_ReleaseType,
  379.     PDF_SendPkt,
  380.     PDF_Terminate,
  381.     PDF_GetAddress,
  382.     PDF_ResetInterface,
  383.     PDF_SetRcvMode,
  384.     PDF_GetRcvMode,
  385.     PDF_SetMulticastList    =    22,
  386.     PDF_GetMulticastList,
  387.     PDF_GetStatistics,
  388.     PDF_GetErrors
  389.     };
  390.  
  391. /*
  392.  *  Error codes
  393.  */
  394.  
  395. enum    PD_Errors
  396.     {
  397.     PDE_BadHandle            =    1,
  398.     PDE_NoClass,
  399.     PDE_NoType,
  400.     PDE_NoNumber,
  401.     PDE_BadType,
  402.     PDE_NoMulticast,
  403.     PDE_CantTerminate,
  404.     PDE_BadMode,
  405.     PDE_NoSpace,
  406.     PDE_TypeInUse,
  407.     PDE_BadCommand,
  408.     PDE_CantSend,
  409.     PDE_CantSet,
  410.     PDE_BadAddress
  411.     };
  412.  
  413. /*
  414.  *  Forward declarations
  415.  */
  416.  
  417. void PassUp ( void *buf, word len );
  418.  
  419. /****************************************************************
  420.  *                                                                *
  421.  *                Trace                                            *
  422.  *                                                                *
  423.  ****************************************************************/
  424.  
  425. #ifdef DEBUG
  426.  
  427. #ifdef SCREEN_EGA
  428. #define SCREEN_BASE    0xB800
  429. #define SCREEN_WRAP 4000
  430. #else
  431. #define SCREEN_BASE    0xB000
  432. #define SCREEN_WRAP 2560    /* leave some room at bottom of screen */
  433. #endif
  434.  
  435. void Trace ( byte val, byte color )
  436. {
  437.     static int    BufOfs    =    0;
  438. #ifdef TRACE_HEX
  439.     static char    HexRep[] = "0123456789ABCDEF";
  440. #ifdef TRACE_ALL_HEX
  441.     static all_hex = TRUE;
  442. #else
  443.     static all_hex = FALSE;
  444. #endif
  445.  
  446.     if ( all_hex || val <= ' ' || val >= '\x7f' )
  447.     {
  448.         *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = HexRep[val>>4];
  449.         BufOfs %= SCREEN_WRAP;
  450.         *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = color;
  451.         BufOfs %= SCREEN_WRAP;
  452.         *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = HexRep[val&0xF];
  453.         BufOfs %= SCREEN_WRAP;
  454.         *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = color;
  455.         BufOfs %= SCREEN_WRAP;
  456.     }
  457. #endif
  458.  
  459.     *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = val;
  460.     BufOfs %= SCREEN_WRAP;
  461.     *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = color;
  462.     BufOfs %= SCREEN_WRAP;
  463.  
  464. #ifdef TRACE_HEX
  465.     *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = ' ';
  466.     BufOfs %= SCREEN_WRAP;
  467.     *(byte *)MK_FP ( SCREEN_BASE, BufOfs++ ) = color;
  468.     BufOfs %= SCREEN_WRAP;
  469. #endif
  470. }
  471. #endif
  472.  
  473.  
  474. /****************************************************************
  475.  *                                                                *
  476.  *                N u m e r i c   R o u t i n e s                    *
  477.  *                                                                *
  478.  ****************************************************************/
  479.  
  480. byte
  481. GetDig ( char ch )
  482. {
  483.     if ( ( ch >= '0' ) && ( ch <= '9' ) )
  484.         return ch - '0';
  485.     else if ( ( ch >= 'A' ) && ( ch <= 'F' ) )
  486.         return ch - 'A' + 10;
  487.     else if ( ( ch >= 'a' ) && ( ch <= 'f' ) )
  488.         return ch - 'a' + 10;
  489.     else if ( ( ch == 'x' ) || ( ch == 'X' ) )
  490.         return 'x';
  491.     else if ( ch == '#' )
  492.         return '#';
  493.     else if ( ch == 0 )
  494.         return '0';
  495.     else
  496.         return '?';
  497. }
  498.  
  499. dword
  500. GetNum(void)
  501. {
  502.     byte        state;
  503.     dword        base;
  504.     dword        num;
  505.     char        ch;
  506.     byte        digit;
  507.  
  508.     num = 0;
  509.     state = 0;
  510.  
  511.     for (;;)
  512.     {
  513.         ch = *optarg++;
  514.         digit = GetDig ( ch );
  515.         switch ( state )
  516.         {
  517.         case 0:
  518.             if ( digit == 0 )
  519.             {
  520.                 base = 8;
  521.                 state = 1;
  522.             }
  523.             else if ( digit == '#' )
  524.             {
  525.                 base = 16;
  526.                 state = 3;
  527.             }
  528.             else if ( digit <= 9 )
  529.             {
  530.                 base = 10;
  531.                 num = digit;
  532.                 state = 2;
  533.             }
  534.             else
  535.             {
  536.                 return ErrInt;
  537.             }
  538.             break;
  539.  
  540.         case 1:
  541.             if ( digit == 'x' )
  542.             {
  543.                 if ( num == 0 )
  544.                 {
  545.                     base = 16;
  546.                     state = 3;
  547.                 }
  548.             else
  549.                 {
  550.                 return ErrInt;
  551.                 }
  552.             }
  553.             else if ( digit <= 9 )
  554.             {
  555.                 num = num * base + digit;
  556.             }
  557.             else if ( digit == '0' )
  558.             {
  559.                 return num;
  560.             }
  561.             else
  562.             {
  563.                 return ErrInt;
  564.             }
  565.             break;
  566.  
  567.         case 2:
  568.             if ( digit == '#' )
  569.             {
  570.                 base = num;
  571.                 num = 0;
  572.                 if ( ( base < 2 ) || ( base > 16 ) )
  573.                     return ErrInt;
  574.                 state = 3;
  575.             }
  576.             else if ( digit <= 9 )
  577.             {
  578.                 num = num * base + digit;
  579.             }
  580.             else if ( digit == '0' )
  581.             {
  582.                 return num;
  583.             }
  584.             else
  585.             {
  586.                 return ErrInt;
  587.             }
  588.             break;
  589.  
  590.         case 3:
  591.             if ( digit < base )
  592.             {
  593.                 num = num * base + digit;
  594.             }
  595.             else if ( digit == '0' )
  596.             {
  597.                 return num;
  598.             }
  599.             else
  600.             {
  601.                 return ErrInt;
  602.             }
  603.             break;
  604.  
  605.         }
  606.     }
  607. }
  608.  
  609. /****************************************************************
  610.  *                                                                *
  611.  *                S e r i a l   U t i l i t i e s                    *
  612.  *                                                                *
  613.  ****************************************************************/
  614.  
  615. void setportb ( word Port, byte Mask )
  616. {
  617.     outportb ( Port, inportb ( Port ) | Mask );
  618. }
  619.  
  620. void clrportb ( word Port, byte Mask )
  621. {
  622.     outportb ( Port, inportb ( Port ) & ~Mask );
  623. }
  624.  
  625. /****************************************************************
  626.  *                                                                *
  627.  *                R e c v P r o c                                    *
  628.  *                                                                *
  629.  ****************************************************************/
  630.  
  631. void RecvProc ( byte *buf, word len )
  632. {
  633.     switch ( *(dword *) (buf) )
  634.     {
  635.     case 0x0102:    /* IP datagram */
  636.         PassUp ( buf+4, len-4 );
  637.         IOS_PktIn++;
  638.         IOS_ByteIn += len-4;
  639.         break;
  640.  
  641.     case 0x0302:    /* Address reply */
  642.         RealIP_Address = ((dword)buf[4] << 24) | ((dword)buf[5] << 16)
  643.                        | ((dword)buf[6] << 8)  | ((dword)buf[7]);
  644.         InitTimer = 0;
  645.         break;
  646.  
  647.     default:
  648.         break;
  649.     }
  650. }
  651.  
  652. /****************************************************************
  653.  *                                                                *
  654.  *                R e c v F S M                                    *
  655.  *                                                                *
  656.  ****************************************************************/
  657.  
  658. void RecvFSM ( byte RecvEvent, byte value )
  659. {
  660.     static byte        RecvState = 0;
  661.     static byte        *RecvPtr = (byte *)&RecvQ;
  662.  
  663.     switch ( RecvState )
  664.     {
  665.  
  666.     /* state 0 -- dialing */
  667.  
  668.     case 0:
  669.         switch ( RecvEvent )
  670.         {
  671.         case RECV_GOT_REQ:
  672.             RecvState = 2;
  673.             break;
  674.  
  675.         case RECV_RDA:
  676.             if ( RecvQSize != QLEN )
  677.             {
  678.                 RecvQ[RecvQTail++] = value;
  679.                 RecvQTail &= (QLEN-1);
  680.                 RecvQSize++;
  681.             }
  682.             break;
  683.         }
  684.         break;
  685.  
  686.     /* state 1 -- receiver idle */
  687.  
  688.     case 1:
  689.         switch ( RecvEvent )
  690.         {
  691.         case RECV_GOT_REQ:
  692.             RecvPtr = (byte *)&RecvQ;
  693.             RecvState = 2;
  694.             break;
  695.  
  696.         case RECV_RDA:
  697.             break;
  698.         }
  699.         break;
  700.  
  701.     /* state 2 -- REQ has been received, receiving chars */
  702.  
  703.     case 2:
  704.         switch ( RecvEvent )
  705.         {
  706.         case RECV_RDA:
  707.             switch ( value )
  708.             {
  709.             case SLFP_ESC:
  710.                 RecvState = 3;
  711.                 break;
  712.  
  713.             case SLFP_END:
  714.                 RecvProc ( (byte *)&RecvQ, RecvPtr - (byte *)&RecvQ );
  715.                 RecvPtr = (byte *)&RecvQ;
  716.                 RecvState = 1;
  717.                 break;
  718.  
  719.             default:
  720.                 *RecvPtr++ = value;
  721.                 break;
  722.             }
  723.             break;
  724.  
  725.         case RECV_GOT_REQ:
  726.             RecvPtr = (byte *)&RecvQ;
  727.             break;
  728.         }
  729.         break;
  730.  
  731.     /* state 3 -- ESC received, waiting second char */
  732.  
  733.     case 3:
  734.         switch ( RecvEvent )
  735.         {
  736.         case RECV_RDA:
  737.             if ( value <= 3 )
  738.             {
  739.                 *RecvPtr++ = SLFP_ESC + value;
  740.                 RecvState = 2;
  741.             }
  742.             else
  743.             {
  744.                 RecvPtr = (byte *)&RecvQ;
  745.                 RecvState = 1;
  746.             }
  747.             break;
  748.  
  749.         case RECV_GOT_REQ:
  750.             RecvState = 2;
  751.             RecvPtr = (byte *)&RecvQ;
  752.             break;
  753.  
  754.         }
  755.         break;
  756.  
  757.     default:
  758.         break;
  759.     }
  760. }
  761.  
  762. /****************************************************************
  763.  *                                                                *
  764.  *                X m i t F S M                                    *
  765.  *                                                                *
  766.  ****************************************************************/
  767.  
  768. void
  769. XmitFSM ( byte event )
  770. {
  771.     typedef enum
  772.         {
  773.         s_Idle,                    /* wait for anything (DI) */
  774.         s_Idle_Ack,                /* after sending Ack in Idle */
  775.         s_Check,                /* pseudo state to combine code */
  776.         s_Sent_Req,                /* after sending Req */
  777.         s_Wait,                    /* wait for Ack (DI) */
  778.         s_Wait_Ack,                /* after sending Ack in Wait */
  779.         s_Message,                /* sending message */
  780.         s_Sent_End                /* after sending End */
  781.         } s_t;
  782.     static s_t state = s_Idle;
  783.  
  784.     static word Qcount;
  785.     static byte Qvalue;
  786.  
  787.     static BOOLEAN Framing = FALSE;
  788.     static BOOLEAN SendAck = FALSE;
  789.     static BOOLEAN SentEsc = FALSE;
  790.  
  791.     int counter = XmitCount;
  792.  
  793.     do
  794.     {
  795.         switch ( event )
  796.         {
  797.         case XMIT_MESSAGE:
  798.             if ( state == s_Idle )
  799.             {
  800.                 setportb ( IOA_IER, IER_TXE );
  801.                 state = s_Check;
  802.                 event = XMIT_THRE;                /* fake interrupt */
  803.             }
  804.             break;
  805.  
  806.         case XMIT_GOT_REQ:
  807.             switch ( state )
  808.             {
  809.             case s_Idle:
  810.             case s_Wait:
  811.                 setportb ( IOA_IER, IER_TXE );
  812.                 XmitTimer = 1 * SECONDS;
  813.                 SendAck = FALSE;                /* paranoia */
  814.                 trace ( SLFP_ACK, LIGHTBLUE );
  815.                 outportb ( IOA_THR, SLFP_ACK );
  816.                 state++;                        /* _Ack state */
  817.                 break;
  818.             default:
  819.                 SendAck = TRUE;
  820.                 break;
  821.             };
  822.             Serial_Handshake = TRUE;
  823.             break;
  824.  
  825.         case XMIT_GOT_ACK:
  826.             switch ( state )
  827.             {
  828.             case s_Wait:                    /* tx interrupt is off */
  829.                 setportb ( IOA_IER, IER_TXE );
  830.                 /* fallthru */
  831.  
  832.             case s_Sent_Req:                /* must have missed THRE */
  833.                 event = XMIT_THRE;            /* fake interrupt */
  834.                 /* fallthru */
  835.  
  836.             case s_Wait_Ack:                /* must wait for ACK THRE */
  837.                 XmitQHead += 2;                /* skip count */
  838.                 XmitQHead &= (QLEN-1);
  839.                 XmitQSize -= 2;
  840.                 state = s_Message;
  841.                 break;
  842.  
  843.             default:
  844.                 /* ignore spurious Ack */
  845.                 break;
  846.             };
  847.             break;
  848.  
  849.         case XMIT_THRE:
  850.         case XMIT_LOOP:
  851.             XmitTimer = 1 * SECONDS;
  852.  
  853.             if ( SentEsc )
  854.             {
  855.                 SentEsc = FALSE;
  856.                 trace ( Qvalue - SLFP_ESC, MAGENTA );
  857.                 outportb ( IOA_THR, Qvalue - SLFP_ESC );
  858.                 event = XMIT_LOOP;
  859.                 counter--;
  860.             }
  861.             else if ( SendAck )
  862.             {
  863.                 SendAck = FALSE;
  864.                 trace ( SLFP_ACK, LIGHTBLUE );
  865.                 outportb ( IOA_THR, SLFP_ACK );
  866.                 counter = 0;    /* wait for real THRE */
  867.             }
  868.             else
  869.             {
  870.                 switch ( state )
  871.                 {
  872.                 case s_Sent_End:
  873.                 case s_Idle_Ack:
  874.                 case s_Check:
  875.                     if ( XmitQSize < 2 )
  876.                     {
  877.                         if ( XmitQSize != 0 )
  878.                         {
  879.                             XmitQHead =
  880.                             XmitQTail =
  881.                             XmitQSize = 0;
  882.                         }
  883.                         if ( event == XMIT_THRE )
  884.                         {
  885.                             clrportb ( IOA_IER, IER_TXE );
  886.                             XmitTimer = 0;
  887.                             state = s_Idle;
  888.                         }
  889.                         counter = 0;    /* wait for event */
  890.                     }
  891.                     else
  892.                     {
  893.                         word Qindex;
  894.  
  895.                         Qindex = XmitQHead;
  896.                         Qcount = XmitQ[Qindex++];
  897.                         Qindex &= (QLEN-1);
  898.                         Qcount |= (word)(XmitQ[Qindex++]) << 8;
  899.                         Qindex &= (QLEN-1);
  900.  
  901.                         if ( Qcount > 0  &&  Framing )
  902.                         {
  903.                             trace ( SLFP_REQ, LIGHTRED );
  904.                             outportb ( IOA_THR, SLFP_REQ );
  905.                             counter = 0;    /* wait for real THRE */
  906.                             state = s_Sent_Req;
  907.                         }
  908.                         else
  909.                         {
  910.                             XmitQHead += 2;        /* skip count, just like Ack */
  911.                             XmitQHead &= (QLEN-1);
  912.                             XmitQSize -= 2;
  913.  
  914.                             if ( !Framing )
  915.                             {
  916.                                 state = s_Message;
  917.                             }
  918.                         }
  919.                     }
  920.                     break;
  921.  
  922.                 case s_Sent_Req:
  923.                 case s_Wait_Ack:
  924.                     clrportb ( IOA_IER, IER_TXE );
  925.                     XmitTimer = 3 * SECONDS;
  926.                     counter = 0;    /* wait for event or timer */
  927.                     state = s_Wait;
  928.                     break;
  929.  
  930.                 case s_Message:
  931.                     if ( Qcount-- > 0 )
  932.                     {
  933.                         Qvalue = XmitQ[XmitQHead++];
  934.                         XmitQHead &= (QLEN-1);
  935.                         XmitQSize--;
  936.  
  937.                         if ( Qvalue >= SLFP_ESC && Qvalue <= SLFP_END )
  938.                         {
  939.                             SentEsc = TRUE;
  940.                             trace ( SLFP_ESC, LIGHTMAGENTA );
  941.                             outportb ( IOA_THR, SLFP_ESC );
  942.                         }
  943.                         else
  944.                         {
  945.                             trace ( Qvalue, LIGHTGREEN );
  946.                             outportb ( IOA_THR, Qvalue );
  947.                         }
  948.                         event = XMIT_LOOP;
  949.                         counter--;
  950.                     }
  951.                     else
  952.                     {
  953.                         if ( Framing )
  954.                         {
  955.                             trace ( SLFP_END, LIGHTCYAN );
  956.                             outportb ( IOA_THR, SLFP_END );
  957.                             event = XMIT_LOOP;
  958.                             counter--;
  959.                         }
  960.                         else
  961.                         {
  962.                             Framing = TRUE;
  963.                         }
  964.                         state = s_Sent_End;
  965.                     }
  966.                     break;
  967.  
  968.                 default:
  969.                     /* spurious interrupt */
  970.                     clrportb ( IOA_IER, IER_TXE );
  971.                     counter = 0;    /* wait for external event */
  972.                     break;
  973.                 };
  974.             }
  975.             break;
  976.  
  977.         case XMIT_TIMEOUT:
  978.             switch ( state )
  979.             {
  980.             case s_Wait:
  981.                 IOE_ReqTO++;
  982.                 setportb ( IOA_IER, IER_TXE );
  983.                 state = s_Check;            /* try again */
  984.                 event = XMIT_THRE;            /* fake interrupt */
  985.                 break;
  986.  
  987.             case s_Idle_Ack:
  988.             case s_Sent_Req:
  989.             case s_Wait_Ack:
  990.             case s_Message:
  991.             case s_Sent_End:
  992.                 IOE_LostTHRE++;
  993.                 event = XMIT_THRE;            /* fake interrupt */
  994.  
  995.             default:
  996.                 /* ignore spurious timeout */
  997.                 break;
  998.             };
  999.             XmitTimer = 0;                    /* should already be zero */
  1000.             break;
  1001.  
  1002.         default:
  1003.             /* unknown event */
  1004.             break;
  1005.         }
  1006.     } while ( (event == XMIT_THRE || event == XMIT_LOOP) && counter > 0 );
  1007. }
  1008.  
  1009.  
  1010. void
  1011. XmitQput ( char *header, byte *buffer, word buffer_size )
  1012. {
  1013.     register word count;
  1014.     register word Qindex;
  1015.  
  1016.     if ( header != NULL )
  1017.         buffer_size += 4;
  1018.  
  1019.     Qindex = XmitQTail;
  1020.     XmitQ[Qindex++] = (byte)(buffer_size);
  1021.     Qindex &= (QLEN-1);
  1022.     XmitQ[Qindex++] = (byte)(buffer_size >> 8);
  1023.     Qindex &= (QLEN-1);
  1024.  
  1025.     count = 0;
  1026.  
  1027.     if ( header != NULL )
  1028.     {
  1029.         for ( ; count < 4; count++ )
  1030.         {
  1031.             XmitQ[Qindex++] = *header++;
  1032.             Qindex &= (QLEN-1);
  1033.         }
  1034.     }
  1035.  
  1036.     while ( count++ < buffer_size )
  1037.     {
  1038.         XmitQ[Qindex++] = *buffer++;
  1039.         Qindex &= (QLEN-1);
  1040.     }
  1041.  
  1042.     disable();
  1043.     XmitQTail = Qindex;
  1044.     XmitQSize += buffer_size + 2;
  1045.     XmitFSM ( XMIT_MESSAGE );
  1046.     enable();
  1047. }
  1048.  
  1049.  
  1050. /****************************************************************
  1051.  *                                                                *
  1052.  *                S e r i a l I S R                                *
  1053.  *                                                                *
  1054.  ****************************************************************/
  1055.  
  1056. void interrupt SerialISR ( )
  1057. {
  1058.     byte        IntrIdent;
  1059.     byte        ch;
  1060.     byte        ErrMask;
  1061.     int            HighWater    =    0;
  1062.  
  1063.     outportb ( 0x20, 0x20 );
  1064.     while ( ( ( IntrIdent = inportb ( IOA_IIR ) ) & IIR_IP ) == 0 )
  1065.     {
  1066.         switch ( IntrIdent & IIR_ID )
  1067.         {
  1068.         case IIR_RDA:
  1069.             for (;;)
  1070.             {
  1071.                 ErrMask = inportb ( IOA_LSR );
  1072.                 if ( ErrMask & LSR_OE )
  1073.                     IOE_OverRun++;
  1074.                 if ( ErrMask & LSR_PE )
  1075.                     IOE_Parity++;
  1076.                 if ( ErrMask & LSR_FE )
  1077.                     IOE_Framing++;
  1078.                 if ( ErrMask & LSR_BI )
  1079.                     IOE_Break++;
  1080.  
  1081.                 if ( (ErrMask & LSR_DR) == 0 )
  1082.                     break;
  1083.  
  1084.                 HighWater++;
  1085.                 ch = inportb ( IOA_RBR );
  1086.                 trace ( ch, BROWN );
  1087.  
  1088.                 switch ( ch )
  1089.                 {
  1090.                 case SLFP_REQ:
  1091.                     RecvFSM ( RECV_GOT_REQ, 0 );
  1092.                     XmitFSM ( XMIT_GOT_REQ );
  1093.                     break;
  1094.                 case SLFP_ACK:
  1095.                     XmitFSM ( XMIT_GOT_ACK );
  1096.                     break;
  1097.                 default:
  1098.                     RecvFSM ( RECV_RDA, ch );
  1099.                     break;
  1100.                 }
  1101.             }
  1102.             IOE_IntrIn++;
  1103.             IOE_FifoHi = max ( IOE_FifoHi, HighWater );
  1104.             break;
  1105.  
  1106.         case IIR_THRE:
  1107.             XmitFSM ( XMIT_THRE );
  1108.             IOE_IntrOut++;
  1109.             break;
  1110.  
  1111.         case IIR_MSTAT:
  1112.             break;
  1113.  
  1114.         case IIR_RLS:
  1115.             ErrMask = inportb ( IOA_LSR );
  1116.             if ( ErrMask & LSR_OE )
  1117.                 IOE_OverRun++;
  1118.             if ( ErrMask & LSR_PE )
  1119.                 IOE_Parity++;
  1120.             if ( ErrMask & LSR_FE )
  1121.                 IOE_Framing++;
  1122.             if ( ErrMask & LSR_BI )
  1123.                 IOE_Break++;
  1124.             break;
  1125.         }
  1126.         if ( IntrIdent & IIR_FIFO_TO )
  1127.             IOE_FifoTO++;
  1128.     }
  1129. }
  1130.  
  1131. /****************************************************************
  1132.  *                                                                *
  1133.  *                S e r i a l I n i t                                *
  1134.  *                                                                *
  1135.  ****************************************************************/
  1136.  
  1137. BOOLEAN SerialInit ( word IOBase, byte IRQ, word Speed )
  1138. {
  1139.     word        *IOA_ptr;
  1140.     word        ClockRate;
  1141.     int            ind;
  1142.  
  1143.     /* check parameters for consistancy */
  1144.  
  1145.     if ( ( IOBase == 0x3F8 ) && ( IRQ != 4 ) )
  1146.     {
  1147.         printf ( "Warning: COM1 usually uses IRQ 4\n" );
  1148.     }
  1149.  
  1150.     if ( ( IOBase == 0x2F8 ) && ( IRQ != 3 ) )
  1151.     {
  1152.         printf ( "Warning: COM2 usually uses IRQ 3\n" );
  1153.     }
  1154.  
  1155.     if ( ( IRQ < 1 ) || ( IRQ > 7 ) )
  1156.     {
  1157.         printf ( "Error: Only first interrupt controller supported\n" );
  1158.         return FALSE;
  1159.     }
  1160.  
  1161.     if ( ( 115200L % Speed ) != 0 )
  1162.     {
  1163.         printf ( "Warning: Line speed can only be approximated\n" );
  1164.     }
  1165.  
  1166.     /* save parameters */
  1167.  
  1168.     IOA_ptr = &IOA_First;
  1169.     for ( ind=0; ind<IOA_Count; ind++ )
  1170.     {
  1171.         *IOA_ptr++ += IOBase;
  1172.     }
  1173.     Serial_IRQ = IRQ;
  1174.     Serial_Speed = Speed;
  1175.  
  1176.     /*
  1177.      *  Initialize 8250
  1178.      */
  1179.  
  1180.     /* disable interrupts */
  1181.  
  1182.     disable();
  1183.  
  1184.     /* empty receiver buffer */
  1185.  
  1186.     (void) inportb ( IOA_RBR );
  1187.  
  1188.     /* set 8 bits, no parity, one stop bit */
  1189.  
  1190.     outportb ( IOA_LCR, LCR_8BITS );
  1191.  
  1192.     /* check for 16550A and enable fifo */
  1193.  
  1194.     if ( ConfFifoCheck )
  1195.     {
  1196.         outportb ( IOA_FCR, FCR_ENABLE );
  1197.  
  1198.         if ( ( inportb ( IOA_IIR ) & IIR_FIFO_ENB ) == IIR_FIFO_ENB )
  1199.         {
  1200.             /* Chip is a 16550A. Setup the FIFOs
  1201.              */
  1202.             Serial_16550A = TRUE;
  1203.             XmitCount = 16;
  1204.             outportb ( IOA_FCR, FCR_SETUP);
  1205.             printf ( "16650A detected\n" );
  1206.         }
  1207.         else
  1208.         {
  1209.             /* Chip is not a 16550A. In case it's a 16550 (which has a
  1210.              * broken FIFO), turn off the FIFO bit.
  1211.              */
  1212.             outportb ( IOA_FCR, FCR_RESET );
  1213.         }
  1214.     }
  1215.  
  1216.     /* enable receiver interrupts */
  1217.  
  1218.     outportb ( IOA_IER, IER_DAV|IER_RLS );
  1219.  
  1220.     /* raise DTR, RTS & enable master interrupts */
  1221.  
  1222.     outportb ( IOA_MCR, MCR_DTR | MCR_RTS | MCR_OUT2 );
  1223.  
  1224.     /* set up clock rate */
  1225.  
  1226.     ClockRate = 115200L / Speed;
  1227.     setportb ( IOA_LCR, LCR_DLAB );
  1228.     outportb ( IOA_DLL, (byte)( ClockRate ) );
  1229.     outportb ( IOA_DLM, (byte)( ClockRate >> 8 ) );
  1230.     clrportb ( IOA_LCR, LCR_DLAB );
  1231.  
  1232.     /* set up serial ISR */
  1233.  
  1234.     SaveSerialInt = getvect ( IRQ+8 );
  1235.     setvect ( IRQ+8, SerialISR );
  1236.  
  1237.     /* enable interrupt on 8259 */
  1238.  
  1239.     outportb ( 0x21, inportb ( 0x21 ) & ~ ( 1 << IRQ ) );
  1240.  
  1241.     /* transmit state machine */
  1242.  
  1243.     enable();
  1244.     delay ( 1000 );
  1245.     disable();
  1246.  
  1247.     /* all done */
  1248.  
  1249.     enable();
  1250.     return TRUE;
  1251. }
  1252.  
  1253. /****************************************************************
  1254.  *                                                                *
  1255.  *                S e r i a l I n i t                                *
  1256.  *                                                                *
  1257.  ****************************************************************/
  1258.  
  1259. void SerialTerm ( void )
  1260. {
  1261.     /* disable 8250 interrupts */
  1262.  
  1263.     outportb ( IOA_IER, 0 );
  1264.     outportb ( IOA_MCR, 0 );
  1265.     outportb ( 0x21, inportb ( 0x21 ) | ( 1 << Serial_IRQ ) );
  1266.  
  1267.     /* restore interrupt vector */
  1268.  
  1269.     setvect ( Serial_IRQ+8, SaveSerialInt );
  1270. }
  1271.  
  1272. /****************************************************************
  1273.  *                                                                *
  1274.  *                Timer Tick                                        *
  1275.  *                                                                *
  1276.  ****************************************************************/
  1277.  
  1278. void interrupt TimerTick ( )
  1279. {
  1280.     /* handle tick */
  1281.  
  1282.     if ( XmitTimer != 0 && --XmitTimer == 0 )
  1283.     {
  1284.         XmitFSM ( XMIT_TIMEOUT );
  1285.     }
  1286.  
  1287.     if ( InitTimer != 0 && --InitTimer == 0 )
  1288.     {
  1289.     }
  1290.  
  1291.     /* chain on old interrupt handler */
  1292.  
  1293.     (*SaveTimerInt)();
  1294.  
  1295. }
  1296.  
  1297. /****************************************************************
  1298.  *                                                                *
  1299.  *                Pass Up                                            *
  1300.  *                                                                *
  1301.  ****************************************************************/
  1302.  
  1303. void PassUp ( void * buf, word len )
  1304. {
  1305.     RecvType    TempRecv;
  1306.     void        *TempPtr;
  1307.  
  1308.     /* ensure a handle to return message on */
  1309.  
  1310.     if ( !HandleTable.Hand_InUse )
  1311.     {
  1312.         IOS_PktDrop++;
  1313.         return;
  1314.     }
  1315.  
  1316.     /* ensure receiver hasn't asked for a specific type */
  1317.  
  1318.     if ( HandleTable.Hand_TypeLen != 0 )
  1319.     {
  1320.         IOS_PktDrop++;
  1321.         return;
  1322.     }
  1323.  
  1324.     /* get buffer */
  1325.  
  1326.     TempRecv = HandleTable.Hand_Receiver;
  1327.     if ( TempRecv == NULL )
  1328.     {
  1329.         IOS_PktDrop++;
  1330.         return;
  1331.     }
  1332.  
  1333.     _AX = 0;
  1334.     _CX = len;
  1335.     _BX = 1;
  1336.     TempRecv();
  1337.     TempPtr = (void *) MK_FP ( _ES, _DI );
  1338.  
  1339.     if ( TempPtr == NULL )
  1340.     {
  1341.         IOS_PktDrop++;
  1342.         return;
  1343.     }
  1344.  
  1345.     /* move data into buffer */
  1346.  
  1347.     memcpy ( TempPtr, buf, len );
  1348.  
  1349.     /* pass up to receiver */
  1350.  
  1351.     __emit__ ( 0x1E );            /* push ds */
  1352.     _DS = FP_SEG ( TempPtr );
  1353.     _SI = FP_OFF ( TempPtr );
  1354.     _AX = 1;
  1355.     _CX = len;
  1356.     _BX = 1;
  1357.     TempRecv();
  1358.     __emit__ ( 0x1F );            /* pop ds */
  1359.  
  1360. }
  1361.  
  1362. /****************************************************************
  1363.  *                                                                *
  1364.  *                PDF Driver Info                                    *
  1365.  *                                                                *
  1366.  ****************************************************************/
  1367.  
  1368. void DriverInfo ( IntrRegsType *IntrRegs )
  1369.  
  1370. {
  1371.     /* ensure real function */
  1372.  
  1373.     if ( IntrRegs->b.al != 0xFF )
  1374.     {
  1375.         IntrRegs->w.fl |= FL_CARRY;
  1376.         IntrRegs->b.dh = PDE_BadCommand;
  1377.         return;
  1378.     }
  1379.  
  1380.     /* return driver info */
  1381.  
  1382.     IntrRegs->w.fl &= ~FL_CARRY;
  1383.     IntrRegs->w.bx = PD_version;
  1384.     IntrRegs->b.ch = PDC_SLFP;
  1385.     IntrRegs->w.dx = PDT_Merit;
  1386.     IntrRegs->b.cl = 0;        /* number */
  1387.     IntrRegs->w.ds = FP_SEG(PDN_slfp);
  1388.     IntrRegs->w.si = FP_OFF(PDN_slfp);
  1389.     IntrRegs->b.al = PDV_extended;
  1390. }
  1391.  
  1392. /****************************************************************
  1393.  *                                                                *
  1394.  *                PDF Access Type                                    *
  1395.  *                                                                *
  1396.  ****************************************************************/
  1397.  
  1398. void AccessType ( IntrRegsType *IntrRegs )
  1399.  
  1400. {
  1401.     /* assume error */
  1402.  
  1403.     IntrRegs->w.fl |= FL_CARRY;
  1404.  
  1405.     /* ensure SLFP class request */
  1406.  
  1407.     if ( IntrRegs->b.al != PDC_SLFP )
  1408.     {
  1409.         IntrRegs->b.dh = PDE_NoClass;
  1410.         return;
  1411.     }
  1412.  
  1413.     /* ensure proper type request */
  1414.  
  1415.     if ( ( IntrRegs->w.bx != PDT_any ) && ( IntrRegs->w.bx != PDT_Merit ) )
  1416.     {
  1417.         IntrRegs->b.dh = PDE_NoType;
  1418.         return;
  1419.     }
  1420.  
  1421.     /* ensure proper number request */
  1422.  
  1423.     if ( ( IntrRegs->b.dl != 0 ) && ( IntrRegs->b.dl != 1 ) )
  1424.     {
  1425.         IntrRegs->b.dh = PDE_NoNumber;
  1426.         return;
  1427.     }
  1428.  
  1429.     /* ensure already not in use */
  1430.  
  1431.     if ( HandleTable.Hand_InUse )
  1432.     {
  1433.         IntrRegs->b.dh = PDE_TypeInUse;
  1434.         return;
  1435.     }
  1436.  
  1437.     /* type value length must be <= 8 */
  1438.  
  1439.     if ( IntrRegs->w.cx > 8 )
  1440.     {
  1441.         IntrRegs->b.dh = PDE_BadType;
  1442.         return;
  1443.     }
  1444.  
  1445.     /* enter info into handler table entry */
  1446.  
  1447.     HandleTable.Hand_InUse = TRUE;
  1448.     HandleTable.Hand_Receiver =
  1449.         (RecvType) MK_FP ( IntrRegs->w.es, IntrRegs->w.di );
  1450.     HandleTable.Hand_TypeLen = IntrRegs->w.cx;
  1451.  
  1452.     /* all done */
  1453.  
  1454.     IntrRegs->w.fl &= ~FL_CARRY;
  1455.     IntrRegs->w.ax = 1;
  1456.  
  1457. }
  1458.  
  1459. /****************************************************************
  1460.  *                                                                *
  1461.  *                PDF Release Type                                *
  1462.  *                                                                *
  1463.  ****************************************************************/
  1464.  
  1465. void ReleaseType ( IntrRegsType *IntrRegs )
  1466. {
  1467.     word        hand;
  1468.  
  1469.     hand = IntrRegs->w.bx;
  1470.  
  1471.     /* ensure good handle */
  1472.  
  1473.     if ( hand != 1 )
  1474.     {
  1475.         IntrRegs->w.fl |= FL_CARRY;
  1476.         IntrRegs->b.dh = PDE_BadHandle;
  1477.         return;
  1478.     }
  1479.  
  1480.     /* clear table entry */
  1481.  
  1482.     HandleTable.Hand_InUse = FALSE;
  1483.     HandleTable.Hand_Receiver = (RecvType) NULL;
  1484.  
  1485.     /* all done */
  1486.  
  1487.     IntrRegs->w.fl &= ~FL_CARRY;
  1488.  
  1489. }
  1490.  
  1491. /****************************************************************
  1492.  *                                                                *
  1493.  *                PDF SendPkt                                        *
  1494.  *                                                                *
  1495.  ****************************************************************/
  1496.  
  1497. void SendPkt ( IntrRegsType *IntrRegs )
  1498. {
  1499.     word        TotalLen;
  1500.     byte        *BufPtr;
  1501.  
  1502.     /* set up */
  1503.  
  1504.     IntrRegs->w.fl |= FL_CARRY;
  1505.     IntrRegs->b.dh = PDE_CantSend;
  1506.  
  1507.     TotalLen = IntrRegs->w.cx;
  1508.     if ( TotalLen + 2 + 4 > QLEN - XmitQSize )
  1509.     {
  1510.         IOS_ErrOut++;
  1511.         return;
  1512.     }
  1513.  
  1514.     /* put message on transmit queue */
  1515.  
  1516.     BufPtr = (byte *) MK_FP ( IntrRegs->w.ds, IntrRegs->w.si );
  1517.     XmitQput( "\x2\x1\x0\x0", BufPtr, TotalLen );
  1518.  
  1519.     /* record stats */
  1520.  
  1521.     IOS_PktOut++;
  1522.     IOS_ByteOut += IntrRegs->w.cx;
  1523.  
  1524.     /* all done */
  1525.  
  1526.     IntrRegs->w.fl &= ~FL_CARRY;
  1527. }
  1528.  
  1529. /****************************************************************
  1530.  *                                                                *
  1531.  *                PDF Terminate                                    *
  1532.  *                                                                *
  1533.  ****************************************************************/
  1534.  
  1535. void Terminate ( IntrRegsType *IntrRegs )
  1536. {
  1537.     union    REGS    regs;
  1538.     struct    SREGS    sregs;
  1539.  
  1540.     /* restore hardware and interrupts */
  1541.  
  1542.     disable();
  1543.     SerialTerm();
  1544.     setvect ( 0x08, SaveTimerInt );
  1545.     setvect ( ConfPackInt, SavePacketInt );
  1546.     enable();
  1547.  
  1548.     /* assume failure */
  1549.  
  1550.     IntrRegs->w.fl |= FL_CARRY;
  1551.     IntrRegs->b.dh = PDE_CantTerminate;
  1552.  
  1553.     /* return program block */
  1554.  
  1555.     regs.h.ah = 0x49;
  1556.     sregs.es = _psp;
  1557.     intdosx ( ®s, ®s, &sregs );
  1558.     if ( regs.x.cflag != 0 )
  1559.         return;
  1560.  
  1561.     /* return environment block */
  1562.  
  1563.     regs.h.ah = 0x49;
  1564.     sregs.es = ( (PSP_Ptr) MK_FP ( _psp, 0 ) ) -> PSP_Environment;
  1565.     intdosx ( ®s, ®s, &sregs );
  1566.     if ( regs.x.cflag != 0 )
  1567.         return;
  1568.  
  1569.     /* all OK */
  1570.  
  1571.     IntrRegs->w.fl &= ~FL_CARRY;
  1572. }
  1573.  
  1574. /****************************************************************
  1575.  *                                                                *
  1576.  *                PDF Get Address                                    *
  1577.  *                                                                *
  1578.  ****************************************************************/
  1579.  
  1580. void GetAddress ( IntrRegsType *IntrRegs )
  1581. {
  1582.     word        hand;
  1583.  
  1584.     /* set up */
  1585.  
  1586.     hand = IntrRegs->w.bx;
  1587.     IntrRegs->w.fl |= FL_CARRY;
  1588.  
  1589.     /* ensure a good handle */
  1590.  
  1591.     if ( hand > 1 )
  1592.         {
  1593.         IntrRegs->b.dh = PDE_BadHandle;
  1594.         return;
  1595.         }
  1596.  
  1597.     /* make sure enough space to return address */
  1598.  
  1599.     if ( IntrRegs->w.cx < 4 )
  1600.         {
  1601.         IntrRegs->b.dh = PDE_NoSpace;
  1602.         return;
  1603.         }
  1604.  
  1605.     /* return address */
  1606.  
  1607.     IntrRegs->w.fl &= ~FL_CARRY;
  1608.     IntrRegs->w.cx = 4;
  1609.     memcpy ( MK_FP(IntrRegs->w.es,IntrRegs->w.di),
  1610.         (const void *) &RealIP_Address, 4 );
  1611. }
  1612.  
  1613. /****************************************************************
  1614.  *                                                                *
  1615.  *                Packet Driver Interrupt Handler                *
  1616.  *                                                                *
  1617.  ****************************************************************/
  1618.  
  1619. void interrupt PacketDriver ( IntrRegsType IntrRegs )
  1620.  
  1621. {
  1622.     enable();
  1623.  
  1624.     switch ( IntrRegs.b.ah )
  1625.     {
  1626.  
  1627.     case PDF_DriverInfo:
  1628.         DriverInfo ( &IntrRegs );
  1629.         break;
  1630.  
  1631.     case PDF_AccessType:
  1632.         AccessType ( &IntrRegs );
  1633.         break;
  1634.  
  1635.     case PDF_ReleaseType:
  1636.         ReleaseType ( &IntrRegs );
  1637.         break;
  1638.  
  1639.     case PDF_SendPkt:
  1640.         SendPkt ( &IntrRegs );
  1641.         break;
  1642.  
  1643.     case PDF_Terminate:
  1644.         Terminate ( &IntrRegs );
  1645.         break;
  1646.  
  1647.     case PDF_GetAddress:
  1648.         while ( InitTimer )
  1649.             ;
  1650.         GetAddress ( &IntrRegs );
  1651.         break;
  1652.  
  1653.     case PDF_GetStatistics:
  1654.         IntrRegs.w.fl &= ~FL_CARRY;
  1655.         IntrRegs.w.ds = FP_SEG ( &IOS_Table );
  1656.         IntrRegs.w.si = FP_OFF ( &IOS_Table );
  1657.         break;
  1658.  
  1659.     case PDF_GetErrors:
  1660.         IntrRegs.w.fl &= ~FL_CARRY;
  1661.         IntrRegs.w.ds = FP_SEG ( &IOE_Table );
  1662.         IntrRegs.w.si = FP_OFF ( &IOE_Table );
  1663.         break;
  1664.  
  1665.     default:
  1666.         IntrRegs.w.fl |= FL_CARRY;
  1667.         IntrRegs.b.dh = PDE_BadCommand;
  1668.     }
  1669. }
  1670.  
  1671. /****************************************************************
  1672.  *                                                                *
  1673.  *                Ctl-C(break) handler                            *
  1674.  *                                                                *
  1675.  ****************************************************************/
  1676.  
  1677. int BreakHandler ( void )
  1678. {
  1679.     printf ( "SLFP aborted\n" );
  1680.  
  1681.     /* restore hardware and interrupts */
  1682.  
  1683.     disable();
  1684.     SerialTerm();
  1685.     setvect ( 0x08, SaveTimerInt );
  1686.     setvect ( ConfPackInt, SavePacketInt );
  1687.     enable();
  1688.     exit ( ERL_break );
  1689.     return 0;
  1690. }
  1691.  
  1692. /****************************************************************
  1693.  *                                                                *
  1694.  *                Process echo                                    *
  1695.  *                                                                *
  1696.  ****************************************************************/
  1697.  
  1698. void
  1699. proc_echo ( void )
  1700. {
  1701.     char        ch;
  1702.  
  1703.     if ( RecvQSize )
  1704.     {
  1705.         disable();
  1706.         ch = RecvQ[RecvQHead++];
  1707.         RecvQHead &= (QLEN-1);
  1708.         RecvQSize--;
  1709.         enable();
  1710.         putchar ( ch );
  1711.     }
  1712. }
  1713.  
  1714. /****************************************************************
  1715.  *                                                                *
  1716.  *                Main routine                                    *
  1717.  *                                                                *
  1718.  ****************************************************************/
  1719.  
  1720. void main ( int argc, char **argv )
  1721. {
  1722.     void        *HookPtr;
  1723.     dword        PSize;
  1724.     int            opt;
  1725.     BOOLEAN        err;
  1726.     InterruptPtrType
  1727.                 OldPackInt;
  1728.     char        PDSig[8];
  1729.  
  1730.  
  1731. /* give version message */
  1732.  
  1733. printf ( "SLFP: version " SLFP_VERSION "\n" );
  1734.  
  1735. /* parse command image */
  1736.  
  1737. err = FALSE;
  1738.  
  1739. do
  1740. {
  1741.     opt = getopt ( argc, argv, "p:i:b:s:d:t:h:f:" );
  1742.  
  1743.     switch ( opt )
  1744.     {
  1745.     case 'p':
  1746.         ConfPackInt = GetNum();
  1747.         break;
  1748.  
  1749.     case 'i':
  1750.         ConfSerialIrq = GetNum();
  1751.         break;
  1752.  
  1753.     case 'b':
  1754.         ConfSerialBase = GetNum();
  1755.         break;
  1756.  
  1757.     case 's':
  1758.         ConfSerialSpeed = GetNum();
  1759.         break;
  1760.  
  1761.     case 'd':
  1762.         strcpy ( ConfSerialDial, optarg );
  1763.         break;
  1764.  
  1765.     case 't':
  1766.         ConfInitTime = GetNum();
  1767.         break;
  1768.  
  1769.     case 'h':
  1770.         ConfHandshake = GetNum();
  1771.         break;
  1772.  
  1773.     case 'f':
  1774.         ConfFifoCheck = GetNum();
  1775.         break;
  1776.  
  1777.     case EOF:
  1778.         break;
  1779.  
  1780.     default:
  1781.         err = TRUE;
  1782.         break;
  1783.     }
  1784. }
  1785. while ( opt != EOF );
  1786.  
  1787. if ( err )
  1788. {
  1789.     printf ( "Usage: slfp [/p PacketIntNo] [/i SerialIntNo]"
  1790.         " [/b SerialBase] [/s SerialSpeed] [/d DialCmd] /t [InitTime]"
  1791.         " [/h Handshake] [/f FifoCheck]\n" );
  1792.     exit ( ERL_parse );
  1793. }
  1794.  
  1795. /* check for packet driver already loaded */
  1796.  
  1797. OldPackInt = getvect ( ConfPackInt );
  1798.  
  1799. movedata ( FP_SEG(OldPackInt), FP_OFF(OldPackInt)+3,
  1800.     FP_SEG(PDSig), FP_OFF(PDSig), 8 );
  1801.  
  1802. if ( strncmp ( PDSig, "PKT DRVR", 8 ) == 0 )
  1803. {
  1804.     printf ( "Packet driver already loaded at 0x%X\n", ConfPackInt );
  1805.     exit ( ERL_packet );
  1806. }
  1807.  
  1808. /* output parameters */
  1809.  
  1810. printf ( "slfp /p 0x%X /i %d /b 0x%X /s %d /t %d /h %d /f %d /d %s\n",
  1811.     ConfPackInt, ConfSerialIrq, ConfSerialBase, ConfSerialSpeed,
  1812.     ConfInitTime, ConfHandshake, ConfFifoCheck, ConfSerialDial );
  1813.  
  1814. strcat ( ConfSerialDial, "\r" );
  1815. InitTimer = ConfInitTime * SECONDS;
  1816.  
  1817. /* set up ctl-C handler */
  1818.  
  1819. ctrlbrk ( BreakHandler );
  1820.  
  1821. /* clear Handle table */
  1822.  
  1823. HandleTable.Hand_InUse = FALSE;
  1824. HandleTable.Hand_Receiver = (RecvType) NULL;
  1825.  
  1826. /* build driver hook */
  1827.  
  1828. memcpy ( PacketDriverHook, "\xEB\x0A\x90PKT DRVR\0\xEA", 13 );
  1829. HookPtr = (void *)PacketDriver;
  1830. memcpy ( &PacketDriverHook[13], &HookPtr, 4 );
  1831.  
  1832. /* set up packet driver vector */
  1833.  
  1834. SavePacketInt = getvect ( ConfPackInt );
  1835. setvect ( ConfPackInt, (InterruptPtrType) PacketDriverHook );
  1836.  
  1837. /* set up Timer routine */
  1838.  
  1839. SaveTimerInt = getvect ( 0x08 );
  1840. setvect ( 0x08, TimerTick );
  1841.  
  1842. /* initialize serial link */
  1843.  
  1844. SerialInit ( ConfSerialBase, ConfSerialIrq, ConfSerialSpeed );
  1845.  
  1846. /* dial modem, wait for initial handshake */
  1847.  
  1848. XmitQput( NULL, (byte *)ConfSerialDial, strlen( ConfSerialDial ) );
  1849.  
  1850. while ( InitTimer && ConfHandshake && !Serial_Handshake )
  1851. {
  1852.     proc_echo();
  1853.     (void) kbhit();
  1854. }
  1855.  
  1856. /* send IP address request, wait for IP address */
  1857.  
  1858. XmitQput( "\x2\x3\x0\x0", NULL, 0 );
  1859.  
  1860. while ( InitTimer  &&  RealIP_Address == 0L )
  1861. {
  1862.     proc_echo();
  1863.     (void) kbhit();
  1864. }
  1865.  
  1866. if ( RealIP_Address != 0L )
  1867. {
  1868.     printf ( "\nIP address set to %d.%d.%d.%d\n",
  1869.         (byte)( RealIP_Address >> 24 ),
  1870.         (byte)( RealIP_Address >> 16 ),
  1871.         (byte)( RealIP_Address >>  8 ),
  1872.         (byte)( RealIP_Address       ) );
  1873. }
  1874. else
  1875. {
  1876.     printf ( "\nUnable to establish IP address. SLFP aborted\n" );
  1877.  
  1878.     /* restore hardware and interrupts */
  1879.  
  1880.     disable();
  1881.     SerialTerm();
  1882.     setvect ( 0x08, SaveTimerInt );
  1883.     setvect ( ConfPackInt, SavePacketInt );
  1884.     enable();
  1885.  
  1886.     exit ( ERL_handshake );
  1887. }
  1888.  
  1889. /* terminate, stay resident */
  1890.  
  1891. PSize = ( (byte huge *)MK_FP(_SS,_SP+15) - (byte huge *)MK_FP(_CS,0) ) / 16;
  1892. keep ( ERL_none, PSize );
  1893.  
  1894. }
  1895.