1 /* ***********************************************************
  2    *                                                         *
  3    * Copyright, (C) Honeywell Bull Inc., 1987                *
  4    *                                                         *
  5    * Copyright, (C) Honeywell Information Systems Inc., 1986 *
  6    *                                                         *
  7    *********************************************************** */
  8 
  9 /* HISTORY COMMENTS:
 10   1) change(86-05-06,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 11      install(87-08-07,MR12.1-1072):
 12      Created.
 13   2) change(86-05-12,Lee), approve(87-07-13,MCR7580), audit(87-07-13,Leskiw),
 14      install(87-08-07,MR12.1-1072):
 15      global variable holding address of application
 16      routine now replaced by field in mcb called application_entry.
 17   3) change(86-07-07,Westcott), approve(87-07-13,MCR7580),
 18      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 19      Support linked lists for inbuff and outbuff.
 20   4) change(86-11-14,Flegel), approve(87-07-13,MCR7580),
 21      audit(87-07-13,Leskiw), install(87-08-07,MR12.1-1072):
 22      Initialized the mcb_flag field.
 23                                                    END HISTORY COMMENTS */
 24 
 25 /* : PROCEDURE FUNCTION (cretinst)
 26 
 27 Register the calling routine with MOWSE by assigning it a major capability
 28 number and adding it to MOWSE's capability table. The calling routine must
 29 supply the name by which it is to be known to MOWSE, and a pointer to the
 30 function to be invoked when a message is received.
 31 
 32 Allocates and initializes the mcb in the caller's address space.
 33 
 34 Allocates and initializes the input and output buffers in the caller's
 35 address space.
 36 */
 37 
 38 /* : NOTES:
 39 
 40 All applications which expect to receive messages must have registered with
 41 MOWSE (through create_instance) in order to receive messages. A message is
 42 provided to the application when a the destination of the message specifies
 43 the major capability number of the application. The application will then be
 44 invoked at the entry name provided with the message (argument data), its
 45 length, and a pointer to the applications data_block as follows:
 46 
 47    process_event (minor_capability, major_sender, arg_ptr,
 48                   arg_length, mcb_ptr, data_block_ptr);
 49 
 50 The buffers inbuff and outbuff allow MOWSE to send and receive messages longer
 51 than one communications packet (defined by WSPAKSIZ) in a manner transparent
 52 to the capability.
 53 */
 54 
 55 #include <dos.h>
 56 #include <ws.h>
 57 #include <cat.h>
 58 #include <ws_dcls.h>
 59 #include <ws_error.h>
 60 #include <ws_func.h>
 61 
 62 #define NULL 0
 63 
 64 cretinst (capability_name, entry_name, inbuff_length, outbuff_length, data_block_ptr, mcb_ptr)
 65 
 66 char *capability_name;
 67 int  (*entry_name)();
 68 int  inbuff_length;                    /* Length of input buffer */
 69 int  outbuff_length;                   /* Length of output buffer */
 70 char *data_block_ptr;                  /* Application data to be saved */
 71 mcb  **mcb_ptr;                        /* Address of new mcb_ptr */
 72 {
 73 int  i;
 74 int  inbuff_size;
 75 int  outbuff_size;
 76 int  cap_num;
 77 int  code;
 78 mcb *lmcb_ptr;                         /* local mcb pointer */
 79 struct SREGS segregs;
 80 struct allocstr *allocp;
 81 struct cretinst_param_struct cips;
 82 
 83 int  pe_entry();                       /* pointer to function to receive messages */
 84 
 85    code = 0;
 86 
 87 /* : allocate and initialize the mcb */
 88 
 89    lmcb_ptr = (mcb *) malloc (sizeof (mcb));
 90    if (lmcb_ptr == NULL)
 91       return (WSCNTCRE);
 92 
 93 /* : initialize the capability name field of mcb with capability name passed */
 94 
 95    cips.mcb_ptr = lmcb_ptr;
 96    stccpy (lmcb_ptr -> capability_name, capability_name, CAPABILITY_NAME_LENGTH);
 97    i = stccpy (cips.capability_name, capability_name, CAPABILITY_NAME_LENGTH);
 98    for (i = i; i < CAPABILITY_NAME_LENGTH; i++)
 99    {  lmcb_ptr -> capability_name[i] = 0;
100       cips.capability_name[i] = 0;
101    }
102 
103 /* : store address of application routine (if it was NULL, then set the
104      appropriate mcb_flag) to be called and the application's data block
105      pointer in the mcb, clear the flags */
106 
107    lmcb_ptr -> data_block_ptr = data_block_ptr;
108    lmcb_ptr -> mcb_flag = 0;
109 
110    if (!((int)(entry_name)))
111    {  lmcb_ptr -> application_entry = NULL;
112       lmcb_ptr -> mcb_flag |= MCB_NULL_ROUTINE;
113    }
114    else
115       lmcb_ptr -> application_entry = entry_name;
116 
117 /* : determine the actual input buffer size. The input buffer size must be
118      at least as large as the minimum packet size.  We must also allow
119      space for the linked list overhead */
120 
121    if (inbuff_length < WSPAKSIZ)
122       inbuff_size = WSPAKSIZ;
123    else
124       inbuff_size = inbuff_length;
125 
126    inbuff_size += (sizeof (struct allocstr))*2;
127    inbuff_size += (sizeof (struct linklst))*2;
128    inbuff_size += WSPAKSIZ;
129 
130 /* : allocate the input buffer and initialize fields associated with the
131      input buffer.  If cant allocate, then clean up and return error */
132 
133    lmcb_ptr -> inbuff_length = inbuff_length;
134    allocp = (struct allocstr *) malloc (inbuff_size);
135    if (allocp != NULL)
136    {  lmcb_ptr -> inalloc = allocp;
137       allocp -> memory_used = 0;
138       allocp -> memory = (char *) ((int)allocp + sizeof (struct allocstr));
139       allocp -> m_allocp = NULL;
140       allocp -> memory_size = inbuff_size - sizeof (struct allocstr);
141       lmcb_ptr -> inbuff = NULL;
142    }
143    else
144    {  free (lmcb_ptr);
145       *mcb_ptr = NULL;
146       return (WSINVBUF);
147    }
148 
149 /* : determine the actual output buffer size. We must allow space for the
150      overhead required to store enough packets to save the requested number
151      of characters, plus space for the allocation structure. */
152 
153    outbuff_size = 1 + outbuff_length / WSPAKSIZ;
154    outbuff_size = outbuff_size * (WSPAKSIZ + sizeof(struct linklst));
155    outbuff_size += sizeof (struct allocstr);
156 
157 /* : allocate the output buffer and initialize the fields associated with
158      the output buffer.  If cant allocate it hten clean up and return error */
159 
160    lmcb_ptr -> outbuff_length = outbuff_length;
161    allocp = (struct allocstr  *) malloc (outbuff_size);
162    if (allocp != NULL) {
163       lmcb_ptr -> outalloc = allocp;
164       allocp -> memory_used = 0;
165       allocp -> memory = (char *) ((int)allocp + sizeof (struct allocstr));
166       allocp -> m_allocp = NULL;
167       allocp -> memory_size = outbuff_size - sizeof (struct allocstr);
168       lmcb_ptr -> outbuff = NULL;
169    }
170    else {
171       free (lmcb_ptr -> inalloc);
172       free (lmcb_ptr);
173       *mcb_ptr = NULL;
174       return (WSINVBUF);
175    }
176 
177 /* : set the low and high memory values get the segment register so we can
178      save it in the CAT store address of entry_pt routine in mowse
179      structure */
180 
181    segread(&segregs);
182    cips.cs_reg = segregs.cs;
183    cips.entry_pt = NULL;
184    if (!(lmcb_ptr -> mcb_flag & MCB_NULL_ROUTINE))
185       cips.entry_pt = pe_entry;
186 
187 /* : call the interrupt handler in mowse,  if an error occurred free up
188      allocated buffers and pass back NULL pointer to caller */
189 
190    if (code = call_mowse_int (I$CRETINST, &cips, sizeof(cips)))
191    {  if (lmcb_ptr -> inalloc != NULL)
192          free (lmcb_ptr -> inalloc);
193       if (lmcb_ptr -> outalloc != NULL)
194          free (lmcb_ptr -> outalloc);
195       free (lmcb_ptr);
196       *mcb_ptr = NULL;
197    }
198    else
199    {  lmcb_ptr -> major_capability = cips.major_capability;
200       lmcb_ptr -> system_id = cips.system_id;
201       *mcb_ptr = lmcb_ptr;
202    }
203    return (code);
204 }