1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 
 10 /****^  HISTORY COMMENTS:
 11   1) change(86-03-04,CLJones), approve(86-07-30,MCR7461),
 12      audit(86-07-31,Coren), install(86-08-19,MR12.0-1120):
 13      Allow workspace size to be changed when direct channels aren't active;
 14      allow a status queue for devices attached to direct channels.
 15   2) change(86-11-17,Farley), approve(86-11-20,MECR0002),
 16      audit(86-11-19,Fawcett), install(86-11-20,MR12.0-1222):
 17      Added check for channel being deleted or already deleted to the
 18      channel_required entry. It will now return a non-zero error code for these
 19      cases.
 20   3) change(86-12-19,Farley), approve(86-12-19,MCR7587),
 21      audit(86-12-19,Fawcett), install(87-01-05,MR12.0-1253):
 22      Formal installation to close out above MECR0002.
 23                                                    END HISTORY COMMENTS */
 24 
 25 
 26 /* Entries to set various IOI parameters (timeout, event channel, etc.) */
 27 /* Started by Charlie Hornig, finished by Chris Jones. */
 28 /* Modified 1984-08-09 BIM for direct channel support */
 29 /* Modified March 1985 by Keith Loepere to properly copy arguments. */
 30 
 31 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
 32 ioi_set:
 33      procedure;
 34 
 35 dcl       p_channel              fixed bin (7) parameter;
 36 dcl       p_code                 fixed bin (35) parameter;
 37 dcl       p_devx                 fixed bin parameter;
 38 dcl       p_evchn                fixed bin (71) parameter;
 39 dcl       p_iom                  fixed bin (3) parameter;
 40 dcl       p_count                fixed bin parameter;
 41 dcl       p_offset               fixed bin (18) parameter;
 42 dcl       p_ring                 fixed bin (3) parameter;
 43 dcl       p_time                 fixed bin (71) parameter;
 44 dcl       p_workspace_ptr        ptr parameter;
 45 dcl       p_workspace_size       fixed bin (19) parameter;
 46 
 47 dcl       chanid                 char (8) aligned;
 48 dcl       channel                fixed bin (7);
 49 dcl       code                   fixed bin (35);
 50 dcl       devx                   fixed bin;
 51 dcl       evchn                  fixed bin (71);
 52 dcl       iom                    fixed bin (3);
 53 dcl       n_entries              fixed bin;
 54 dcl       offset                 fixed bin (18);
 55 dcl       ring                   fixed bin (3);
 56 dcl       time                   fixed bin (71);
 57 dcl       workspace_ptr          ptr;
 58 dcl       workspace_size         fixed bin (19);
 59 
 60 dcl       error_table_$bad_channel
 61                                  fixed bin (35) ext static;
 62 dcl       error_table_$bad_ring_brackets
 63                                  fixed bin (35) ext static;
 64 dcl       error_table_$buffer_big
 65                                  fixed bin (35) ext static;
 66 dcl       error_table_$chnl_already_deleted
 67                                  fixed bin (35) ext static;
 68 dcl       error_table_$chnl_being_deleted
 69                                  fixed bin (35) ext static;
 70 dcl       error_table_$dev_offset_out_of_bounds
 71                                  fixed bin (35) ext static;
 72 dcl       error_table_$device_active
 73                                  fixed bin (35) ext static;
 74 dcl       error_table_$no_operation
 75                                  fixed bin (35) ext static;
 76 dcl       error_table_$time_too_long
 77                                  fixed bin (35) ext static;
 78 
 79 dcl       pds$validation_level   fixed bin (3) external;
 80 dcl       sys_info$page_size     fixed bin external;
 81 dcl       sys_info$seg_size_256K fixed bin external;
 82 
 83 dcl       ioi_page_table$get     entry (fixed bin (19), fixed bin, fixed bin (35));
 84 dcl       ioi_page_table$ptx_to_ptp
 85                                  entry (fixed bin) returns (ptr);
 86 dcl       ioi_page_table$put     entry (fixed bin, fixed bin (35));
 87 dcl       ioi_device$get_dtep    entry (fixed bin, ptr, fixed bin (35));
 88 dcl       ioi_device$unlock      entry (ptr);
 89 dcl       ioi_usurp_channels$required
 90                                  entry (ptr, fixed bin (35));
 91 dcl       ioi_wire$unwire        entry (ptr);
 92 dcl       ioi_workspace$set_rb   entry (ptr, fixed bin (35));
 93 dcl       ioi_workspace$set_max_size
 94                                  entry (ptr, fixed bin (35));
 95 
 96 dcl       (divide, null, ptr, rel, size)
 97                                  builtin;
 98 ^L
 99           return;
100 
101 /* * * * * * * * * * TIMEOUT * * * * * * * * * */
102 
103 /* Entry to set the time allowed for an I/O operation to complete on this device.  If the device runs longer
104    than this, it is stopped and the caller receives a timeout status. */
105 
106 timeout:
107      entry (p_devx, p_time, p_code);
108 
109           time = p_time;
110           call check_devx;
111 
112           if dte.direct then do;
113                call unlock;
114                p_code = error_table_$no_operation;
115                return;
116           end;
117 
118           if (time > dte.max_timeout) & ^dte.priv then do;
119                call unlock;
120                p_code = error_table_$time_too_long;
121                return;
122           end;
123 
124           dte.timeout = time;
125           call unlock;
126           p_code = code;
127           return;
128 
129 /* * * * * * * * * * MAX_TIMEOUT * * * * ** * * * */
130 
131 /* Privileged entry to set the maximum the timeout value is allowed to be set to. */
132 
133 max_timeout:
134      entry (p_devx, p_time, p_code);
135 
136           time = p_time;
137           call check_devx;
138 
139           dte.max_timeout = time;
140           call unlock;
141           p_code = code;
142           return;
143 
144 /* * * * * * * * * * EVENT * * * * * * * * * */
145 
146 /* Entry to set the event channel over which status events are signalled for a device. */
147 
148 event:
149      entry (p_devx, p_evchn, p_code);
150 
151           evchn = p_evchn;
152           call check_devx;
153 
154           dte.ev_chn = evchn;
155           call unlock;
156           p_code = code;
157           return;
158 
159 /* * * * * * * * * WORKSPACE * * * * * * * * * */
160 
161 /* Entry to set the current size of the workspace. */
162 
163 workspace:
164      entry (p_devx, p_workspace_ptr, p_workspace_size, p_code);
165 
166           workspace_size =
167                divide (p_workspace_size + sys_info$page_size - 1, sys_info$page_size, 17) * sys_info$page_size;
168           p_workspace_ptr, workspace_ptr = null ();
169           call check_devx;
170 
171           if dte.active then do;
172                call unlock;
173                p_code = error_table_$device_active;
174                return;
175           end;
176 
177           if (workspace_size <= 0) | (workspace_size > dte.max_bound) then do;
178                call unlock;
179                p_code = error_table_$buffer_big;
180                return;
181           end;
182 
183           if workspace_size < dte.status_offset + dte.status_entries * size (istat) then do;
184                call unlock;
185                p_code = error_table_$dev_offset_out_of_bounds;
186                return;
187           end;
188 
189 
190           if dte.workspace_wired then
191                call ioi_wire$unwire (dtep);                 /* can't be wired */
192 
193           dte.bound = workspace_size;
194           if dte.ptx ^= 0 then do;
195                call ioi_page_table$put (dte.ptx, code);
196                dte.ptx = 0;                                 /* so we won't try again */
197                call quit_if_error;
198           end;
199 
200           if dte.direct then
201                call ioi_page_table$get ((sys_info$seg_size_256K), dte.ptx, code);
202           else call ioi_page_table$get (dte.bound, dte.ptx, code);
203           call quit_if_error;
204           dte.ptp = ioi_page_table$ptx_to_ptp (dte.ptx);
205           workspace_ptr = dte.workspace_ptr;
206           call unlock;
207 
208           p_workspace_ptr = workspace_ptr;
209           p_code = code;
210           return;
211 
212 /* * * * * * * * * * MAX_WORKSPACE * * * * * * * * * */
213 
214 /* Privileged entry to set the maximum workspace size allowed for a device. */
215 
216 max_workspace:
217      entry (p_devx, p_workspace_size, p_code);
218 
219           workspace_size =
220                divide (p_workspace_size + sys_info$page_size - 1, sys_info$page_size, 17) * sys_info$page_size;
221           call check_devx;
222 
223           dte.max_bound = workspace_size;
224           call ioi_workspace$set_max_size (dtep, code);
225           call quit_if_error;
226           call unlock;
227           p_code = code;
228           return;
229 
230 /* * * * * * * * * * * LEVEL * * * * * * * * * */
231 
232 /* Privileged entry to set the highest ring allowed to make IOI calls for a device. */
233 
234 level:
235      entry (p_devx, p_ring, p_code);
236 
237           ring = p_ring;
238           call check_devx;
239 
240           if ring < pds$validation_level then do;
241                call unlock;
242                p_code = error_table_$bad_ring_brackets;
243                return;
244           end;
245 
246           dte.ring = ring;
247           call ioi_workspace$set_rb (dtep, code);
248           call quit_if_error;
249           call unlock;
250           p_code = code;
251           return;
252 
253 /* * * * * * * * * * CHANNEL_REQUIRED * * * * * * * * * */
254 
255 /* Privileged entry called to set a required channel for a device.  This will restrict the device
256    to running on that channel. */
257 
258 channel_required:
259      entry (p_devx, p_iom, p_channel, p_code);
260 
261           iom = p_iom;
262           channel = p_channel;
263           call check_devx;
264 
265           if ^dte.priv then do;                             /* must have a privileged assignment */
266                call unlock;
267                p_code = error_table_$no_operation;
268                return;
269           end;
270 
271           if (iom = 0) & (channel = 0) then do;             /* special case, clear requirement */
272                dte.channel_required = "";
273                call unlock;
274                p_code = code;
275                return;
276           end;
277 
278           call io_chnl_util$iom_to_name (iom, channel, chanid, code);
279           if code ^= 0 then do;                             /* bogus channel */
280                call unlock;
281                p_code = error_table_$bad_channel;
282                return;
283           end;
284 
285           if dte.active then do;                            /* device must not be running now */
286                call unlock;
287                p_code = error_table_$device_active;
288                return;
289           end;
290 
291           gtep = ptr (dtep, dte.gtep);
292           do ctep = ptr (gtep, gte.ctep) repeat ptr (ctep, cte.next_ctep) while (rel (ctep) ^= ""b);
293                if cte.chanid = chanid then do;              /* found it */
294 
295                     if cte.deleted then do;                 /* can't have a deleted channel */
296                          call unlock;
297                          p_code = error_table_$chnl_already_deleted;
298                          return;
299                     end;
300 
301                     if cte.deleting then do;                /* can't have this either */
302                          call unlock;
303                          p_code = error_table_$chnl_being_deleted;
304                          return;
305                     end;
306 
307                     if (gte.disk_data_subsystem_idx ^= 0) & ^cte.ioi_use then
308                                                             /* must grab channel from disk_control */
309                          if ^gte.suspend_devices then do;   /* can't usurp if we're suspended */
310                               call ioi_usurp_channels$required (ctep, code);
311                               if code ^= 0 then do;
312                                    call unlock;
313                                    p_code = code;
314                                    return;
315                               end;
316                          end;
317                          else do;
318                               call unlock;
319                               p_code = error_table_$no_operation;
320                               return;
321                          end;
322 
323                     dte.channel_required = chanid;
324                     call unlock;
325                     p_code = code;
326                     return;
327                end;
328           end;
329 
330           call unlock;
331           p_code = error_table_$bad_channel;
332           return;
333 
334 /* * * * * * * * * * STATUS * * * * * * * * * */
335 
336 /* Entry to set the offset (in the workspace) and number of entries in the circular status queue */
337 
338 status:
339      entry (p_devx, p_offset, p_count, p_code);
340 
341           offset = p_offset;
342           n_entries = p_count;
343           call check_devx;
344 
345           if (offset < 0) | (n_entries < 0) | (offset + (n_entries * size (istat)) > dte.bound) then do;
346                call unlock;
347                p_code = error_table_$dev_offset_out_of_bounds;
348                return;
349           end;
350 
351           dte.status_control.status_offset = offset;
352           dte.status_control.status_entries = n_entries;
353           dte.status_control.status_entry_idx = 0;
354           call unlock;
355           p_code = code;
356           return;
357 ^L
358 /* Routine to get the dtep given the devx.  It returns with dtep set and the dte locked.  If it cannot do both,
359    it does not return, but passes the error code back to this program's caller. */
360 
361 check_devx:
362      procedure;
363 
364           p_code, code = 0;
365           devx = p_devx;
366           call ioi_device$get_dtep (devx, dtep, code);      /* cleverly setting p_code to 0 if all is cool. */
367           if code ^= 0 then
368                goto QUIT;
369 
370      end check_devx;
371 
372 /* Routine to unlock the dte */
373 
374 unlock:
375      procedure;
376 
377           call ioi_device$unlock (dtep);
378 
379      end unlock;
380 
381 quit_if_error:
382      proc;
383 
384           if code ^= 0 then do;
385                call unlock;
386                goto QUIT;
387           end;
388 
389      end quit_if_error;
390 
391 QUIT:
392           p_code = code;
393           return;
394 ^L
395 %include ioi_data;
396 %page;
397 %include ioi_stat;
398 %page;
399 %include io_chnl_util_dcls;
400 
401      end ioi_set;