1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
 10 
 11 ioi_assignment:
 12      proc;
 13 
 14 /* Module which handles devices assignments and unassignments for IOI */
 15 /* Rewritten February 1983 by Chris Jones. */
 16 /* Modified January 1984 by Chris Jones to add (add delete)_device entries. */
 17 /* Modified May 1984 by Paul Farley to check for IPC flag. */
 18 /* Modified Jan 1985 by Paul Farley to change IPC to FIPS. */
 19 /* Modified Sept 1985 by Paul Farley to add "controller" checking. */
 20 
 21 /****^  HISTORY COMMENTS:
 22   1) change(85-09-09,Farley), approve(85-09-09,MCR6979),
 23      audit(85-11-26,CLJones), install(86-03-21,MR12.0-1033):
 24      Support FIPS.
 25   2) change(86-05-16,Kissel), approve(86-07-30,MCR7461), audit(86-07-31,Coren),
 26      install(86-08-19,MR12.0-1120):
 27      Recompiled because of change in ioi_data.incl.pl1 to the constant
 28      IOI_DEFAULT_MAX_BOUND.
 29   3) change(86-06-03,Farley), approve(86-07-18,MCR7439),
 30      audit(86-08-18,Fawcett), install(86-10-20,MR12.0-1189):
 31      Changed to execute in the BCE environment.
 32                                                    END HISTORY COMMENTS */
 33 
 34 dcl       p_dtx                  fixed bin parameter;       /* device table index (O) */
 35 dcl       p_name                 char (*) parameter;        /* device name (I) */
 36 dcl       p_priv                 bit (1) aligned parameter; /* privileged assign flag (I) */
 37 dcl       p_eventid              fixed bin (71) parameter;  /* IPC event ID for wakeups (I) */
 38 dcl       p_code                 fixed bin (35) parameter;  /* error code (O) */
 39 
 40 dcl       code                   fixed bin (35);            /* local error code */
 41 dcl       controller             bit (1) aligned;           /* set if device = controller */
 42 dcl       device                 bit (6) aligned;           /* physical device address */
 43 dcl       dtx                    fixed bin;                 /* device table index */
 44 dcl       eventid                fixed bin (71);            /* IPC event ID */
 45 dcl       locked_for_reconfig    bit (1) aligned;           /* set if we hold the reconfig lock */
 46 dcl       must_be_deleted        bit (1) aligned;           /* set if the device must be in the deleted state */
 47 dcl       name                   char (32) var;             /* device name */
 48 dcl       no_path                bit (1) aligned;           /* set if we haven't found a path to the device */
 49 dcl       priv                   bit (1) aligned;           /* "1"b if privileged user */
 50 dcl       statusp                ptr;                       /* pointer to where io_manager stuffs status */
 51 dcl       subsys_name            char (4) aligned;          /* subsystem name */
 52 
 53 dcl       cleanup                cond;
 54 
 55 dcl       error_table_$invalid_device
 56                                  fixed bin (35) ext;
 57 dcl       error_table_$io_configured
 58                                  fixed bin (35) ext static;
 59 dcl       error_table_$io_no_path
 60                                  fixed bin (35) ext static;
 61 dcl       error_table_$io_not_configured
 62                                  fixed bin (35) ext static;
 63 
 64 dcl       pds$process_id         bit (36) aligned external;
 65 dcl       pds$validation_level   fixed bin (3) external;
 66 
 67 dcl       sys_info$service_system
 68                                  bit (1) aligned external static;
 69 
 70 dcl       ioi_device$assign      entry (ptr, bit (6) aligned, bit (1) aligned, fixed bin, fixed bin (35));
 71 dcl       ioi_device$get_dtep    entry (fixed bin, ptr, fixed bin (35));
 72 dcl       ioi_device$get_dtep_force
 73                                  entry (fixed bin, ptr, fixed bin (35));
 74 dcl       ioi_device$unassign    entry (ptr);
 75 dcl       ioi_device$unlock      entry (ptr);
 76 dcl       ioi_masked$flush_status
 77                                  entry (ptr);
 78 dcl       ioi_masked$interrupt   entry (fixed bin (35), fixed bin (3), bit (36) aligned);
 79 dcl       ioi_masked$reset_device
 80                                  entry (ptr);
 81 dcl       ioi_page_table$put     entry (fixed bin, fixed bin (35));
 82 dcl       ioi_usurp_channels$assign
 83                                  entry (ptr, fixed bin (35));
 84 dcl       ioi_usurp_channels$unassign
 85                                  entry (ptr, fixed bin (35));
 86 dcl       ioi_wire$unwire        entry (ptr);
 87 dcl       ioi_workspace$create   entry (ptr, fixed bin (35));
 88 dcl       ioi_workspace$destroy  entry (ptr, fixed bin (35));
 89 dcl       ioi_workspace$release_aste
 90                                  entry (ptr);
 91 
 92 dcl       (addr, after, before, bin, bit, index, null, ptr, rel, rtrim)
 93                                  builtin;
 94 ^L
 95 assign_deleted:
 96      entry (p_dtx, p_name, p_eventid, p_priv, p_code);
 97 
 98           must_be_deleted = "1"b;
 99           goto ASSIGN_COMMON;
100 
101 assign:
102      entry (p_dtx, p_name, p_eventid, p_priv, p_code);
103 
104           must_be_deleted = "0"b;
105 ASSIGN_COMMON:
106           name = rtrim (p_name);                            /* Copy the device name. */
107           priv = p_priv;                                    /* Copy privileged assign switch. */
108           eventid = p_eventid;                              /* Grab the event ID. */
109 
110           idp = addr (ioi_data$);                           /* Get data base pointer. */
111           p_code = 0;                                       /* Clear error code. */
112           subsys_name = before (name, "_");
113 
114           call find_gte (subsys_name);
115           if gtep = null () then do;
116                p_code = error_table_$invalid_device;
117                return;
118           end;
119 
120           controller = "0"b;                                /* start by saying its not */
121           if index (name, "_") = 0 then                     /* no device given */
122                if gte.fips then do;
123                     device = "00"b3;                        /* devices start at zero */
124                     controller = "1"b;                      /* and this is the controller */
125                end;
126                else device = "01"b3;                        /* otherwise start at one */
127           else device = bit (bin (after (name, "_"), 6, 0));
128           if device = "00"b3 & ^gte.fips then
129                controller = "1"b;                           /* old style controller */
130 
131           dtep = null ();
132           on cleanup call cleanup_assign;                   /* Establish cleanup handler to undo whatever. */
133 
134           call ioi_device$assign (gtep, device, controller, dtx, code);
135           if code ^= 0 then do;
136                p_code = code;
137                return;
138           end;
139           gte.n_devices = gte.n_devices + 1;
140           call ioi_device$get_dtep (dtx, dtep, code);       /* lock it to us too */
141           if code ^= 0 then do;                             /* except if there's an error */
142                call cleanup_assign;
143                p_code = code;
144                return;
145           end;
146 
147           if dte.deleted & ^must_be_deleted then do;
148                call cleanup_assign;
149                p_code = error_table_$io_not_configured;
150                return;
151           end;
152           if ^dte.deleted & must_be_deleted then do;
153                call cleanup_assign;
154                p_code = error_table_$io_configured;
155                return;
156           end;
157 
158           if gte.disk_data_subsystem_idx ^= 0 then do;      /* If channels to be taken from page control ... */
159                call ioi_usurp_channels$assign (gtep, code); /* ...get channels for our use. */
160                if code ^= 0 then do;
161                     call cleanup_assign;
162                     p_code = code;
163                     return;
164                end;
165           end;
166           else if ^gte.mplex then do;                       /* channels aren't assigned yet */
167                ctep = ptr (gtep, gte.ctep);                 /* there's only one channel */
168                if ^cte.ioi_use then do;
169                     call io_manager$assign (cte.chx, cte.chanid, ioi_masked$interrupt, bin (rel (ctep)), statusp, code);
170                     if code = 0 then do;
171                          cte.ioi_use = "1"b;
172                          cte.statusp = statusp;
173                     end;
174                     else do;
175                          call cleanup_assign;
176                          p_code = code;
177                          return;
178                     end;
179                end;
180           end;
181 
182 /**** Fill in the dte ****/
183           dte.cur_ctep = ""b;                               /* no channel in use */
184           dte.channel_required = "";                        /* no channel required */
185           dte.ev_chn = eventid;                             /* use caller supplied event channel */
186           dte.max_bound = IOI_DEFAULT_MAX_BOUND;            /* use defaults */
187           dte.max_timeout = IOI_DEFAULT_MAX_TIMEOUT;
188           dte.timeout = IOI_DEFAULT_TIMEOUT;
189           dte.unwire_time = 0;
190           dte.bound = 0;
191 /****^    dte.process_id...                                 ...has already been set */
192           dte.priv = priv;                                  /* use caller supplied value */
193           dte.connected = "0"b;                             /* no channel ready to run this device */
194           dte.active = "0"b;                                /* no I/O to be done yet */
195           dte.workspace_wired = "0"b;                       /* workspace is not wired yet */
196           dte.special_interrupt = "0"b;                     /* no special interrupt received */
197           dte.log_status_cnt = "0"b;                        /* status information not valid yet */
198           dte.reading_detailed_status = "0"b;
199           dte.detailed_status_valid = "0"b;
200 
201 /**** Build the workspace ****/
202           dte.ring = pds$validation_level;
203           dte.ptx = 0;                                      /* no page table yet */
204           dte.status_offset = 0;                            /* clear status queue information */
205           dte.status_entries = 0;
206           dte.status_entry_idx = 0;
207           call ioi_workspace$create (dtep, code);
208           if code ^= 0 then do;
209                call cleanup_assign;
210                p_code = code;
211                return;
212           end;
213 
214           call unlock;
215           p_dtx = dtx;                                      /* return the device table index */
216           return;
217 ^L
218 unassign:
219      entry (p_dtx, p_code);
220 
221           dtx = p_dtx;
222           p_code = 0;
223           call ioi_device$get_dtep_force (dtx, dtep, code);
224           if code ^= 0 then do;
225                p_code = code;
226                return;
227           end;
228 
229           idp = addr (ioi_data$);
230           gtep = ptr (idp, dte.gtep);
231           if dte.active then do;                            /* if device has unfinished business */
232                call ioi_masked$reset_device (dtep);         /* stop it */
233                do while (dte.active);                       /* it will stop eventually */
234                end;
235           end;
236 
237           if dte.ptx ^= 0 then do;
238                call ioi_page_table$put (dte.ptx, code);
239                dte.ptx = 0;
240                if code ^= 0 then do;
241                     call unlock;
242                     p_code = code;
243                     return;
244                end;
245           end;
246 
247 /**** Destroy the workspace if the process which owns this device is doing the call.  Otherwise, simply unwire it.
248       In this case the process is about to go away, and either its process directory is going to be destroyed,
249       which will take the workspace with it, or it will be saved in a dead pdir, in which case it may be
250       interesting to whoever owned it. ****/
251 
252           if dte.process_id = pds$process_id then
253                call ioi_workspace$destroy (dtep, code);     /* get rid of the workspace */
254           else do;
255                call ioi_wire$unwire (dtep);                 /* unwire it */
256                call ioi_workspace$release_aste (dtep);      /* and let go of its aste */
257           end;
258           if code ^= 0 then do;
259                call unlock;
260                p_code = code;
261                return;
262           end;
263 
264           dte.ev_chn = 0;                                   /* stop notifications */
265           dte.channel_required = "";
266           call ioi_masked$flush_status (dtep);
267           call channel_unassign;
268           call ioi_device$unassign (dtep);
269           call unlock;
270           p_code = 0;
271           return;
272 ^L
273 add_device:
274      entry (p_name, p_code);
275 
276           dtx = 0;
277           locked_for_reconfig = "0"b;
278           on cleanup call cleanup_reconfigure;
279 
280           call assign_deleted (dtx, p_name, 0, "0"b, code);
281           if code ^= 0 then do;
282                p_code = code;
283                return;
284           end;
285 
286           call ioi_device$get_dtep (dtx, dtep, code);
287           if code ^= 0 then do;
288                call cleanup_reconfigure;
289                p_code = code;
290                return;
291           end;
292 
293           call lock_for_reconfig_proc;
294           no_path = "1"b;
295           gtep = ptr (dtep, dte.gtep);
296           do ctep = ptr (gtep, gte.ctep) repeat ptr (ctep, cte.next_ctep) while (rel (ctep) ^= ""b & no_path);
297                no_path = cte.deleted | cte.deleting;
298           end;
299           if no_path then do;
300                call cleanup_reconfigure;
301                p_code = error_table_$io_no_path;
302                return;
303           end;
304 
305           dte.deleted = "0"b;
306           io_config_data_ptr = addr (io_config_data$);
307           io_config_device_table_ptr = ptr (io_config_data_ptr, io_config_data.device_table_offset);
308           device_table.device_entry (dte.device_table_idx).configured = "1"b;
309           call cleanup_reconfigure;
310           p_code = 0;
311           return;
312 ^L
313 delete_device:
314      entry (p_name, p_code);
315 
316           dtx = 0;
317           locked_for_reconfig = "0"b;
318           on cleanup call cleanup_reconfigure;
319 
320           call assign (dtx, p_name, 0, "0"b, code);
321           if code ^= 0 then do;
322                p_code = code;
323                return;
324           end;
325 
326           call ioi_device$get_dtep (dtx, dtep, code);
327           if code ^= 0 then do;
328                call cleanup_reconfigure;
329                p_code = code;
330                return;
331           end;
332 
333           if dte.deleted then do;
334                call cleanup_reconfigure;
335                p_code = error_table_$io_not_configured;
336                return;
337           end;
338 
339           dte.deleted = "1"b;
340           io_config_data_ptr = addr (io_config_data$);
341           io_config_device_table_ptr = ptr (io_config_data_ptr, io_config_data.device_table_offset);
342           device_table.device_entry (dte.device_table_idx).configured = "0"b;
343           call cleanup_reconfigure;
344           p_code = 0;
345           return;
346 ^L
347 lock_for_reconfig:
348      entry;
349 
350           call lock_for_reconfig_proc;
351           return;
352 
353 unlock_for_reconfig:
354      entry;
355 
356           call unlock_for_reconfig_proc;
357           return;
358 ^L
359 cleanup_reconfigure:
360      proc;
361 
362           if locked_for_reconfig then
363                call unlock_for_reconfig_proc;
364           if dtx ^= 0 then do;
365                call ioi_device$unlock (dtep);
366                call unassign (dtx, (0));
367           end;
368 
369      end cleanup_reconfigure;
370 
371 lock_for_reconfig_proc:
372      proc;
373 
374 dcl       lock$lock_fast         entry (ptr);
375 
376           idp = addr (ioi_data$);
377           if sys_info$service_system then
378                call lock$lock_fast (addr (ioi_data.reconfig_lock));
379           locked_for_reconfig = "1"b;
380 
381      end lock_for_reconfig_proc;
382 
383 unlock_for_reconfig_proc:
384      proc;
385 
386 dcl       lock$unlock_fast       entry (ptr);
387 
388           idp = addr (ioi_data$);
389           if sys_info$service_system then
390                call lock$unlock_fast (addr (ioi_data.reconfig_lock));
391           locked_for_reconfig = "0"b;
392 
393      end unlock_for_reconfig_proc;
394 ^L
395 find_gte:
396      proc (name);
397 
398 dcl       name                   char (4) aligned parameter;
399 
400 dcl       gtx                    fixed bin;
401 
402 
403           do gtx = 1 to ioi_data.ngt;                       /* Search for channel name. */
404                gtep = addr (ioi_data.gt (gtx));             /* Get pointer to group table entry. */
405                if gte.name = subsys_name then               /* if this is the one */
406                     return;
407           end;
408           gtep = null ();
409 
410      end find_gte;
411 
412 cleanup_assign:
413      proc;
414 
415           if dtep ^= null () then do;                       /* if we've gotten the device */
416                call unlock;
417                call channel_unassign;
418                call ioi_device$unassign (dtep);
419           end;
420 
421      end cleanup_assign;
422 
423 channel_unassign:
424      proc;
425 
426           gte.n_devices = gte.n_devices - 1;
427           if gte.disk_data_subsystem_idx ^= 0 then
428                call ioi_usurp_channels$unassign (gtep, (0));
429           else if ^gte.mplex then do;
430                ctep = ptr (gtep, gte.ctep);
431                if cte.ioi_use then do;
432                     call io_manager$unassign (cte.chx, code);
433                     if code = 0 then
434                          cte.ioi_use = "0"b;
435                end;
436           end;
437 
438      end channel_unassign;
439 
440 unlock:
441      proc;
442 
443           call ioi_device$unlock (dtep);
444 
445      end unlock;
446 ^L
447 %include ioi_data;
448 %page;
449 %include io_config_data;
450 %page;
451 %include io_manager_dcls;
452 
453      end ioi_assignment;