1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
  6         *                                                         *
  7         *********************************************************** */
  8 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
  9 ioi_connect:
 10      procedure (p_devx, p_offset, p_code);
 11 
 12 /* Rewritten by C. Hornig, June 1982 */
 13 /* Rewrite finished August 1982 by Chris Jones */
 14 /* Modified 1984-08-10 BIM for direct channel support (ignore pcw and offset) */
 15 
 16 dcl       p_devx                 fixed bin parameter;       /* (I) device index */
 17 dcl       p_offset               fixed bin (18) parameter;  /* (I) offset in workspace of DCW list */
 18 dcl       p_pcw                  bit (36) aligned parameter;/* (I) PCW to be used for connect */
 19 dcl       p_code                 fixed bin (35) parameter;  /* (O) status code */
 20 
 21 dcl       ioi_device$get_dtep    entry (fixed bin, ptr, fixed bin (35));
 22 dcl       ioi_device$unlock      entry (ptr);
 23 dcl       ioi_masked$getwork_device
 24                                  entry (ptr);
 25 dcl       ioi_wire$wire          entry (ptr);
 26 
 27 dcl       error_table_$dev_offset_out_of_bounds
 28                                  fixed bin (35) ext static;
 29 dcl       error_table_$device_active
 30                                  fixed bin (35) ext static;
 31 dcl       error_table_$no_operation
 32                                  fixed bin (35) ext static;
 33 dcl       error_table_$out_of_main_memory
 34                                  fixed bin (35) ext static;
 35 dcl       error_table_$out_of_sequence
 36                                  fixed bin (35) ext static;
 37 dcl       code                   fixed bin (35);
 38 dcl       auto_pcw               bit (36) aligned;
 39 dcl       devx                   fixed bin;
 40 dcl       offset                 fixed bin (18);
 41 
 42 dcl       (addr, binary, pointer)
 43                                  builtin;
 44 ^L
 45           auto_pcw = ""b;                                   /* default PCW */
 46           goto common;
 47 
 48 
 49 ioi_connect_pcw:
 50      entry (p_devx, p_offset, p_pcw, p_code);
 51 
 52           auto_pcw = p_pcw;                                 /* user-supplied PCW */
 53           goto common;
 54 
 55 
 56 common:
 57           devx = p_devx;
 58           offset = p_offset;
 59           idp = addr (ioi_data$);                           /* find databases */
 60           call ioi_device$get_dtep (devx, dtep, code);      /* lock the device */
 61           if code ^= 0 then do;
 62                p_code = code;
 63                return;
 64           end;
 65 
 66           if dte.active & ^dte.direct then do;              /* already connecting */
 67                call unlock;
 68                p_code = error_table_$device_active;
 69                return;
 70           end;
 71 
 72           if ^dte.direct then do;
 73                if (offset < 0) | (offset >= dte.bound) then do;
 74                                                             /* offset is patently ridiculous */
 75 BOUNDS_ERR:
 76                     call unlock;
 77                     p_code = error_table_$dev_offset_out_of_bounds;
 78                     return;
 79                end;
 80 
 81                gtep = pointer (idp, dte.gtep);
 82                if gte.psia then do;                         /* must do special checks for PSIA */
 83                     if (auto_pcw ^= ""b) & ^dte.priv then do;
 84                                                             /* no PCW unless privileged */
 85                          call unlock;
 86                          p_code = error_table_$no_operation;
 87                          return;
 88                     end;
 89 
 90                     call chase_tdcw;                        /* skip leading TDCW's */
 91                     dte.idcw_listx = offset;                /* remember where is IDCW */
 92                     idcwp = addr (dte.idcw);
 93                     idcw = pointer (dte.workspace_ptr, offset) -> idcw;
 94                                                             /* get first IDCW */
 95                     if idcw.code ^= "111"b then do;         /* no valid IDCW */
 96                          call unlock;
 97                          p_code = error_table_$no_operation;
 98                          return;
 99                     end;
100 
101 /**** Here would be a good place to check for weird device commands which should only be allowed if the controller
102       has been attached or the caller is privileged.  However, the MPCs insist that the device code be 0 in this
103       case, and the check below will take care of that.  In the case of IPCs, there are currently no such
104       commands defined. */
105 
106                     if ^dte.priv then
107                          idcw.device = dte.device;
108                     else if idcw.device then
109                          idcw.device = dte.device;
110 
111                     offset = offset + 1;                    /* now find the next DCW */
112                     call chase_tdcw;                        /* keeping track of TDCW's */
113                end;
114           end;                                              /* direct channels have no control words to check out */
115 
116           if dte.ptx = 0 then do;
117                call unlock;
118                p_code = error_table_$out_of_sequence;
119           end;
120           call ioi_wire$wire (dtep);                        /* Wire the buffer */
121           if ^dte.workspace_wired then do;                  /* couldn't wire it */
122                call unlock;
123                p_code = error_table_$out_of_main_memory;
124                return;
125           end;
126 
127           if ^dte.direct then
128                dte.listx = offset;                          /* where to start in DCW list */
129           dte.pcw = auto_pcw;
130 
131           call ioi_masked$getwork_device (dtep);            /* find a channel */
132 
133           call unlock;                                      /* release the device */
134           p_code = 0;
135           return;
136 
137 /* * * * * * * * * CHASE_TDCW * * * * * * * * * */
138 
139 chase_tdcw:
140      procedure;
141 
142           tdcwp = pointer (dte.workspace_ptr, offset);
143           if (tdcw.type = "10"b) & (tdcwp -> idcw.code ^= "111"b) then do;
144                                                             /* is it a TDCW? */
145                offset = binary (tdcw.address, 18);          /* yes, chase it */
146                if (offset < 0) | (offset >= dte.bound) then
147                     goto BOUNDS_ERR;
148           end;
149 
150      end chase_tdcw;
151 
152 
153 unlock:
154      procedure;
155 
156           call ioi_device$unlock (dtep);
157 
158      end unlock;
159 ^L
160 %include ioi_data;
161 %page;
162 %include iom_pcw;
163 %include iom_dcw;
164 
165      end ioi_connect;