home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0020 - 0029 / ibm0020-0029 / ibm0028.tar / ibm0028 / GRLF-C-1.ZIP / GCOMM / ASIFIRST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-14  |  15.5 KB  |  379 lines

  1. /* asifirst.c
  2. *
  3. * The Greenleaf Comm Library
  4. *
  5. * Copyright (C) 1985-1990 Greenleaf Software Inc.  All Rights Reserved.
  6. *
  7. *  int asifirst( port, mode, rxlen, txlen)
  8. *  int port;            - Port 0..MAX_PORT-1
  9. *  unsigned mode;       - Operating Mode (see below)
  10. *  unsigned rxlen;      - Length Rx Buffer, bytes MIN_BUF_SIZE..MAX_BUF_SIZE
  11. *  unsigned txlen;      - Length Tx Buffer, bytes MIN_BUF_SIZE..MAX_BUF_SIZE
  12. *
  13. *  "mode" specifies five different kinds of operational parameters.
  14. *  Choose one from each of the following categories.  See documentation
  15. *  for further details:
  16. *       1.  Direction (ASIN, ASOUT, ASINOUT)
  17. *       2.  Data Type (BINARY, ASCII)
  18. *       3.  Receive Buffer Width (NORMALRX, WIDETRACKRX)
  19. *
  20. *  Example:
  21. *   asifirst( port,(ASINOUT | BINARY | NORMALRX ),4000,100 );
  22. *
  23. * DESCRIPTION
  24. *  Initializes a data structure that will be used to store the
  25. *  configuration for a port.  This function must be called before any
  26. *  other operations can be performed on a communications port.
  27. *
  28. * SIDE EFFECTS
  29. *  None.
  30. *
  31. * RETURNS
  32. *
  33. *       Value           Meaning
  34. *       -----           -------
  35. *       ASSUCCESS       No errors encountered
  36. *       ASNOMEMORY      Cannot allocate dynamic memory needed
  37. *       ASINVPORT       Requested logical port number too high or too low
  38. *       ASINUSE         port has already been setup with asifirst()
  39. *       ASINVBUFSIZE    Buffer size is out of range
  40. *       ASNO8250        No 8250 installed at requested i/o address
  41. *
  42. * MODIFICATIONS
  43. *
  44. *  10-25-85     ""
  45. *               Modified for new structure members, also moved static
  46. *               data items to this file.
  47. *
  48. *   03-FEB-1987  11:05:40.33
  49. *       Deleted static int first_time, replaced it with a global variable
  50. *       _asoprt which reflects the total number of open ports.  It is
  51. *       initialized to 0, gets incremented on every open and decremented
  52. *       on every close.
  53. *
  54. *   04-FEB-1987  16:32:21.71
  55. *       Added code to check _asmask and add its value to the structure
  56. *       member .as_mask if the port has a shared hardware port defined
  57. *       for it.  This will enable asishare() to be called before asifirst().
  58. *       Also added global variables for _comvers && _comrev.
  59. *
  60. *   25-MAY-1988  15:50:54.29  version 2.20
  61. *       Added code to check _asxorv, and add its value to the structure
  62. *       member .as_xorv if the port has a shared hardware port defined
  63. *       for it.  This will enable asinvert() to be called before asifirst().
  64. *       _asxorv is a new global variable set by asinvert.
  65. *
  66. *       Changed the order of parameters to calloc() per SAR # 84
  67. */
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <string.h>
  71. #include "gf.h"
  72. #define  MOD_ASIFIRST   1               /* For conditional in asiports.h */
  73. #include "asiports.h"
  74. #include "ibmkeys.h"
  75.  
  76. /************************************************************************
  77. *  POINTER TO STRUCTURE CONTAINING POINTERS TO STRUCTURES, AND OTHER    *
  78. *  THINGS:                                                              *
  79. *                                                                       *
  80. *  Elements of the array are:   ptb = ptr to PORT_TABLE (big) structure *
  81. *                               as_shport = status port address         *
  82. *                               as_shbits = status bitmask              *
  83. *                                                                       *
  84. *  First time asifirst() is called for any port, the memory is allocated*
  85. *  for this structure, and the address is placed in the code segment.   *
  86. ************************************************************************/
  87. struct TABLEPORT *as_chnl = NULL;
  88.  
  89.  
  90. /************************************************************************
  91. *  ABOUT THE ARRAYS BELOW..                                             *
  92. *                                                                       *
  93. *  The arrays in this file define parameters for the 16 possible ports. *
  94. *  Values are hard-coded in here for the first two (0 and 1, or COM1    *
  95. *  and COM2) for Category A (standard IBM-type) hardware.  The value    *
  96. *  for any port may be changed by calling asisetv() for the port.       *
  97. *  Values are transferred from these arrays to the large TABLEPORT      *
  98. *  structure (see asiports.h) for the port when asifirst() is called.   *
  99. *                                                                       *
  100. *  Don't change any of these unless you know what you are doing !       *
  101. ************************************************************************/
  102.  
  103.  
  104. /****  BASE I/O ADDRESSES FOR 8250 DEVICES.
  105. *
  106. *  0 in an element assures that asifirst() will not let you use that port,
  107. *  it will return ASNO8250 as a security measure.
  108. *
  109. *  See asisetv() documentation for explanation of "addr8250" argument.
  110. */
  111. unsigned as_8250port[MAX_PORT] = {
  112.         0x3f8,0x2f8,0x3220,0x3228,0x4220,0x4228,0x5220,0x5228,0,0,0,0,0,0,0,0 };
  113.  
  114.  
  115. /****  INTERRUPT NUMBERS for all ports.
  116. *
  117. *  See asisetv() documentation for explanation of "intn" argument.
  118. */
  119. int as_intnums[MAX_PORT] = {
  120.         12,11,11,11,11,11,11,11,0,0,0,0,0,0,0,0 };
  121.  
  122.  
  123. /****  I/O ADDRESSES OF 8259A INTERRUPT CONTROLLER.
  124. *
  125. *  See asisetv() documentation for explanation of "addr8259" argument.
  126. *
  127. */
  128. unsigned as_8259ports[MAX_PORT] = { 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0,0,0,0,0,0,0,0 };
  129.  
  130. /****  IRQ (INTERRUPT REQUEST) NUMBERS
  131. *
  132. *  See asisetv() documentation for explanation of "irq" argument.
  133. */
  134. int as_8259irq[MAX_PORT] = { 4,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0 };
  135.  
  136.  
  137. /****  BREAK SIGNAL DURATION in increments of 55 milliseconds.
  138. *
  139. *  See asisetv() documentation for explanation of "brkdly" argument.
  140. */
  141. int as_brkdly[MAX_PORT] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
  142.  
  143.  
  144. /****  WAIT FOR MODEM SIGNALS  (Polled Mode ONLY)
  145. *
  146. *  See asisetv() documentation for explanation of "wmodem" argument.
  147. */
  148. int as_wmodem[MAX_PORT] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  149.  
  150.  
  151. /****  POLLED MODE WRITE DELAY LIMIT for asputc()
  152. *
  153. *  See asisetv() documentation for explanation of "wtime" argument.
  154. */
  155. int as_wtime[MAX_PORT] = { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 };
  156.  
  157.  
  158. /****  POLLED MODE READ DELAY for asgetc()
  159. *
  160. *  See asisetv() documentation for explanation of "rtime" argument.
  161. */
  162. int as_rtime[MAX_PORT] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  163.  
  164.  
  165. /****  SHARED INTERRUPT HARDWARE - Status Port I/O Address
  166. *
  167. *  See asisetv() documentation for explanation of "sh_ioad" argument.
  168. */
  169. unsigned as_shioad[MAX_PORT] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  170.  
  171.  
  172. /****  SHARED INTERRUPT HARDWARE - Status Port BitMask
  173. *
  174. *  See asisetv() documentation for explanation of "sh_bmask" argument.
  175. */
  176. unsigned as_shbmask[MAX_PORT] = { 0xff00,0xff00,0xff00,0xff00,0xff00,
  177.         0xff00,0xff00,0xff00,0xff00,0xff00,0xff00,
  178.         0xff00,0xff00,0xff00,0xff00,0xff00 };
  179.  
  180.  
  181. /*  DO NOT TOUCH THE FOLLOWING DATA ARRAY FOR ANY REASON.
  182. *
  183. */
  184. char glcprt[]={ 0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,
  185.                 0x43,0x29,0x20,0x31,0x39,0x38,0x35,0x2C,0x20,0x31,0x39,
  186.                 0x38,0x36,0x2C,0x20,0x31,0x39,0x38,0x37,0x2C,0x20,0x31,
  187.                 0x39,0x38,0x38,0x2C,0x20,0x31,0x39,0x38,0x39,0x20,0x47,
  188.                 0x72,0x65,0x65,0x6E,0x6C,0x65,0x61,0x66,0x20,0x53,0x6F,
  189.                 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x49,0x6E,0x63,0x2E,
  190.                 0x0A,0x20,0x20,0x41,0x6C,0x6C,0x20,0x52,0x69,0x67,0x68,
  191.                 0x74,0x73,0x20,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,
  192.                 0x2E,0x00};
  193.  
  194.  
  195. /************************************************************************
  196. *  GLOBAL ERROR VARIABLE _aserror                                       *
  197. *                                                                       *
  198. *  See "Error Returns" section in documentation for explanation.        *
  199. *  This variable may be tested by the application to determine the      *
  200. *  cause of an error on the part of most functions in the library.      *
  201. ************************************************************************/
  202. int _aserror;
  203. int _asoprt=0;
  204. int _asmask=0;  /* This is set by asishare() */
  205. int _comvers = COMLIBVERSION, _comrev = COMLIBREVISION;
  206. int _asxorv=0;  /* Set by asinvert() */
  207.  
  208.  
  209. int GF_CONV asifirst(port,mode,size_rx_buf,size_tx_buf)
  210. int port;
  211. unsigned size_tx_buf,size_rx_buf,mode;
  212. {
  213.         int latch,i,j;
  214.         struct PORT_TABLE *p;
  215.         unsigned rx_alloc;
  216.  
  217.         /********************************************************
  218.         *  First time thru for any port, never again:           *
  219.         *                                                       *
  220.         *  1) Allocate memory for array of structures that will *
  221.         *     point to the big structures.                      *
  222.         *  2) put address of array of structures in code seg.   *
  223.         *  3) Initialize pointers to big structures to NULL     *
  224.         *  4) Shut down Ctrl-Break checking for rest of pgm.    *
  225.         ********************************************************/
  226.         for (j=0,i=0;j < (int)strlen(glcprt);j++) 
  227.               i+=(int)glcprt[j];
  228.         if (i!=6648) return (-30);
  229.         if(!_asoprt && !as_chnl) {
  230.                 if((as_chnl=(struct TABLEPORT *)
  231.                     calloc(1,sizeof( struct TABLEPORT )))==NULL)
  232.                         return(ASNOMEMORY);
  233.                 _asregister(as_chnl);
  234.                 (void) breakchk(OFF);
  235. #ifdef LATTICE
  236.                 onexit((int(*)())_asiexit_routine);
  237. #else
  238.                 atexit(_asiexit_routine);
  239. #endif
  240.                 for (i=0; i<MAX_PORT; i++) {
  241.                         as_chnl->tblport[i].ptb = NULL;
  242.                         if(as_shioad[i]) {
  243.                                 as_chnl->tblport[i].as_mask=_asmask;
  244.                                 as_chnl->tblport[i].as_xorv=_asxorv;
  245.                         }
  246.                 }
  247.         }
  248.  
  249.         /********************************************************
  250.         *  Determine sixe of Tx and Rx buffers                  *
  251.         ********************************************************/
  252.         if(mode&WIDETRACKRX) {
  253.                 if(size_rx_buf > MAX_BUF_SIZE/2)
  254.                         return(ASINVBUFSIZE);
  255.                 rx_alloc=size_rx_buf*2;
  256.         } else
  257.                 rx_alloc=size_rx_buf;
  258.         if (port < 0 || port > MAX_PORT-1)
  259.                 return (ASINVPORT);
  260.         if (as_chnl->tblport[port].ptb != NULL)
  261.                 return (ASINUSE);
  262.         if (rx_alloc < MIN_BUF_SIZE || size_tx_buf < MIN_BUF_SIZE ||
  263.             rx_alloc > MAX_BUF_SIZE || size_tx_buf > MAX_BUF_SIZE)
  264.                 return (ASINVBUFSIZE);
  265.  
  266.  
  267.         /********************************************************
  268.         *  Now allocate memory for the port's main parameter    *
  269.         *  structure.                                           *
  270.         ********************************************************/
  271.         if ((as_chnl->tblport[port].ptb = (struct PORT_TABLE *)
  272.             calloc(1,sizeof (struct PORT_TABLE)))==NULL)
  273.                 return (ASNOMEMORY);
  274.         p=as_chnl->tblport[port].ptb;
  275.  
  276.         /********************************************************
  277.         *  Transfer shared-hardware i/o addr and bitmask to     *
  278.         *  the array of structures TABLEPORT                    *
  279.         *                                                       *
  280.         *  If the port is NOT on a shared port, then the bitmask*
  281.         *  is set with high order 8 bits ones to cause          *
  282.         *  a non-recognition to occur in the interrupt.         *
  283.         ********************************************************/
  284.         as_chnl->tblport[port].as_shport = as_shioad[port];
  285.         if (!as_shioad[port])
  286.                 as_shbmask[port] |= 0xff00;
  287.         as_chnl->tblport[port].as_shbits = as_shbmask[port];
  288.  
  289.         /********************************************************
  290.         *  Allocate memory for Tx and Rx buffers for the port.  *
  291.         ********************************************************/
  292.         if ((p->tx_buffer=calloc(size_tx_buf,1))==NULL) {
  293.                 free((char *)p);
  294.                 as_chnl->tblport[port].ptb = NULL;
  295.                 return (ASNOMEMORY);
  296.         }
  297.         if ((p->rx_buffer=calloc(rx_alloc,1))==NULL) {
  298.                 free(p->tx_buffer);
  299.                 free((char *)p);
  300.                 as_chnl->tblport[port].ptb = NULL;
  301.                 return(ASNOMEMORY);
  302.         }
  303.         p->tx_size=size_tx_buf;
  304.         p->rx_size=size_rx_buf;
  305.  
  306.         /* Initialize all port status bits.
  307.          */
  308.         p->chst_bits.rxempty=p->chst_bits.txempty=1;
  309.         p->intrpt_num=as_intnums[port];
  310.         p->base_8250=as_8250port[port];
  311.         p->tx_cell=1;
  312.         if(mode&WIDETRACKRX) {
  313.                 p->rx_cell=2;
  314.                 p->chmode_bits.is_rxerror=1;
  315.         } else
  316.                 p->rx_cell=1;
  317.         if(mode&ASIN)
  318.                 p->chmode_bits.is_rxint=ON;
  319.         if(mode&ASOUT)
  320.                 p->chmode_bits.is_txint=ON;
  321.         if(mode&ASCII)
  322.                 p->chmode_bits.is_ascii=ON;
  323.  
  324.         p->chmode_bits.modem_status_changes_set_alert = ON;
  325.         p->chmode_bits.line_errors_set_alert = ON;
  326.         p->irq_8259=as_8259irq[port];
  327.         p->port_8259=as_8259ports[port];
  328.         p->break_delay=as_brkdly[port];
  329.         p->aswmodem=as_wmodem[port];
  330.         p->aswtime=as_wtime[port];
  331.         p->asrtime=as_rtime[port];
  332.  
  333.  
  334.         /****************************************************************
  335.         *  In support of shared-interrupt hardware, check to see        *
  336.         *  if any other port using this interrupt number has been setup *
  337.         *  already.  If it has not, the second argument to _asifirst()  *
  338.         *  will be a 1, in which case it will program the 8259A and     *
  339.         *  set the interrupt vector.                                    *
  340.         *  If one or more other ports setup prior to this with same     *
  341.         *  interrupt number, then pass a 0 as second arg to _asifirst() *
  342.         *  to tell it to avoid vector init and 8259A init.              *
  343.         *                                                               *
  344.         *  If there is another with same int num, check that it also    *
  345.         *  has same 8259A address and IRQ number.                       *
  346.         ****************************************************************/
  347.  
  348.         for(latch=1,i=0;i<MAX_PORT;i++) {
  349.           if((i!=port)&&(as_chnl->tblport[i].ptb!=NULL)) {
  350.             if(as_chnl->tblport[i].ptb->intrpt_num==as_intnums[port]) {
  351.               if((as_chnl->tblport[i].ptb->port_8259!=as_8259ports[port])
  352.                  ||(as_chnl->tblport[i].ptb->irq_8259!=as_8259irq[port])) {
  353.                     free(p->tx_buffer);
  354.                     free(p->rx_buffer);
  355.                     free((char *)p);
  356.                     as_chnl->tblport[port].ptb = NULL;
  357.                     return (ASCONFLICT);
  358.               }
  359.                 else latch = 0;
  360.             }
  361.           }
  362.         }  /* end for */
  363.  
  364.         /****************************************************************
  365.         *  If latch = 1 then no other port uses same intr number, so    *
  366.         *  the 8259A and vector will be initialized.                    *
  367.         ****************************************************************/
  368.         if((_aserror=_asifirst(port,latch,p))!=ASSUCCESS) {
  369.                 free(p->tx_buffer);
  370.                 free(p->rx_buffer);
  371.                 free((char *)p);
  372.                 as_chnl->tblport[port].ptb = NULL;
  373.                 return(_aserror);
  374.         }
  375.         ++_asoprt;
  376.         return(ASSUCCESS);
  377. }
  378.  
  379.