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(85-09-09,Farley), approve(85-09-09,MCR6979),
 12      audit(86-01-16,CLJones), install(86-03-21,MR12.0-1033):
 13      Support FIPS and IMU.
 14                                                    END HISTORY COMMENTS */
 15 
 16 /* IOI_INIT - Initialization for the I/O Interfacer. */
 17 /* Rewritten March 1983 by Chris Jones. */
 18 /* Modified January 1984 by Chris Jones for io reconfiguration. */
 19 /* Modified May 1984 by Paul Farley for IPC cards (e.g. FIPS) */
 20 /* Modified April 1984 by Tom Oke for dynamic channel table. */
 21 /* Modified September 1984 by Chris Jones to init device_type for chnl cards */
 22 /* Modified 1984-08-10 BIM for direct channels (sort of) */
 23 /* Modified Nov 1984 by Paul Farley to be able to set the
 24    gte.detailed_status_cmd to "00"b3 when the IOM is a "imu" or "iioc".. */
 25 /* Modified Jan 1985 by Paul Farley to add MCA (found in IMUs) entries. */
 26 /* Modified Jan 1985 by Paul Farley to change IPC cards to FIPS cards. */
 27 /* Modified June 1985 by Paul Farley to make sure a dte is created for device
 28    "00" of a FIPS string, when no device "00" is configured. */
 29 /* Modified Sept 1985 by Paul Farley to add setting of a new dte.controller flag. */
 30 
 31 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
 32 ioi_init:
 33      procedure;
 34 
 35 dcl       adding_controller_dte  bit (1);
 36 dcl       chanid                 char (8) aligned;          /* the converted name of a channel */
 37 dcl       code                   fixed bin (35);            /* error code */
 38 dcl       ctx                    fixed bin;                 /* used to index thru ctes */
 39 dcl       device_number          fixed bin;
 40 dcl       device_type            char (4);                  /* e.g. "dsk", "tap", or "rdr" */
 41 dcl       gtx                    fixed bin;                 /* used to index thru gtes */
 42 dcl       itx                    fixed bin;                 /* used to index thru ites */
 43 dcl       high_ctx               fixed bin;                 /* index of the highest cte in use */
 44 dcl       high_dtx               fixed bin;                 /* index of the highest dte in use */
 45 dcl       high_gtx               fixed bin;                 /* index of the highest gte in use */
 46 dcl       high_itx               fixed bin;                 /* index of the highest ite in use */
 47 dcl       statusp                ptr;                       /* pointer to where io_manager stores status */
 48 dcl       iom_model_array        (8) char (4) aligned;      /* array of model numbers by TAG. */
 49 
 50 
 51 dcl       config_$find           entry (char (4) aligned, ptr);
 52 dcl       ioi_config$find_base_channel
 53                                  entry (char (8) aligned) returns (char (8) aligned);
 54 dcl       ioi_config$find_controller_card
 55                                  entry (char (8) aligned) returns (ptr);
 56 dcl       ioi_masked$interrupt   entry (fixed bin (35), fixed bin (3), bit (36) aligned);
 57 dcl       ioi_page_table$init    entry;
 58 dcl       syserr                 entry options (variable);
 59 dcl       syserr$error_code      entry options (variable);
 60 
 61 dcl       ME                     char (32) static options (constant) init ("ioi_init");
 62 
 63 dcl       (addr, bin, bit, divide, hbound, lbound, max, min, null, ptr, rel, string, substr, unspec)
 64                                  builtin;
 65 ^L
 66           idp = addr (ioi_data$);                           /* get pointer to data base */
 67           io_config_data_ptr = addr (io_config_data$);
 68           io_config_iom_table_ptr = ptr (io_config_data_ptr, io_config_data.iom_table_offset);
 69           io_config_controller_table_ptr = ptr (io_config_data_ptr, io_config_data.controller_table_offset);
 70           io_config_channel_table_ptr = ptr (io_config_data_ptr, io_config_data.channel_table_offset);
 71           io_config_device_table_ptr = ptr (io_config_data_ptr, io_config_data.device_table_offset);
 72           disksp = addr (disk_seg$);
 73 
 74           high_ctx, high_dtx, high_gtx, high_itx = 0;
 75 
 76           iom_model_array (*) = "";
 77           iom_cardp = null ();
 78           call config_$find (IOM_CARD_WORD, iom_cardp);     /* start looking for all IOMs */
 79           do while (iom_cardp ^= null ());
 80                high_itx = high_itx + 1;
 81                itep = addr (ioi_data.it (high_itx));
 82                unspec (ite) = ""b;
 83                ite.tag = iom_card.tag;
 84                ite.model = iom_card.model;
 85                iom_model_array (ite.tag) = iom_card.model;
 86                ite.deleted = (iom_card.state = "off");
 87                ite.iom_table_idx = iom_table_idx_from_tag (ite.tag);
 88                call config_$find (IOM_CARD_WORD, iom_cardp);/* on to the next one */
 89           end;
 90 
 91           prph_cardp = null ();
 92           call config_$find (PRPH_CARD_WORD, prph_cardp);   /* start looking for all devices */
 93           do while (prph_cardp ^= null ());
 94                device_type = substr (prph_card.name, 1, 3);
 95                prph_dsk_cardp, prph_tap_cardp = prph_cardp; /* base the special structures */
 96                call allocate_gte (prph_card.name);          /* set up a group entry */
 97 /**** At this point, all the constant information (that requiring none or little calculation) is set in the gte ****/
 98                if (device_type = "dsk") | (device_type = "tap") then
 99                     gte.mplex = "1"b;
100                call io_chnl_util$iom_to_name (prph_card.iom, (prph_card.chan), chanid, code);
101                if code ^= 0 then
102                     call syserr$error_code (CRASH, code, "^a: Unable to get the name of iom ^d channel ^d.", ME,
103                          prph_card.iom, prph_card.chan);
104                gte.ipc = IS_ON_IMU (prph_card.iom);
105                mpc_cardp = ioi_config$find_controller_card (chanid);
106                if mpc_cardp ^= null () then do;             /* found the channel on a controller */
107                     gte.psia = "1"b;                        /* the only interface we currently know */
108                     ipc_cardp = mpc_cardp;
109                     gte.fips = (ipc_card.word = IPC_CARD_WORD) & (ipc_card.type = IPC_FIPS);
110                end;
111                gte.detailed_status_cmd = extended_status_command ();
112                gte.ascii_dtst = ascii_detailed_status ();
113                call setup_log_status_info;
114                call allocate_dtes_from_prph_card;
115                call allocate_ctes_from_prph_card;
116                call config_$find (PRPH_CARD_WORD, prph_cardp);
117                                                             /* get next card */
118           end;
119 
120 /**** Now pick up all the channels described via chnl cards ****/
121 
122           chnl_cardp = null ();
123           call config_$find (CHNL_CARD_WORD, chnl_cardp);
124           do while (chnl_cardp ^= null ());
125                device_type = substr (chnl_card.name, 1, 3);
126                if find_gte () then
127                     call allocate_ctes_from_chnl_card;
128                call config_$find (CHNL_CARD_WORD, chnl_cardp);
129           end;
130 
131 /**** Next, find the base logical channel for every channel (we had to wait until they're all allocated). ****/
132 
133           do ctx = lbound (ioi_data.ct, 1) to hbound (ioi_data.ct, 1);
134                ctep = addr (ioi_data.ct (ctx));
135                chanid = ioi_config$find_base_channel (cte.chanid);
136                cte.base_ctep = cte_offset (chanid);
137                if cte.base_ctep = ""b then
138                     cte.base_ctep = rel (ctep);
139           end;
140 
141 /**** Now find all the storage system channels, devices, and groups and mark them as such ****/
142 
143           do gtx = lbound (ioi_data.gt, 1) to hbound (ioi_data.gt, 1);
144                gtep = addr (ioi_data.gt (gtx));
145                device_type = substr (gte.name, 1, 3);
146                if device_type = "dsk" then                  /* found one */
147                     call setup_disk_sharing;
148           end;
149 
150 /**** Now assign all non-storage system channels which are multiplexed. ****/
151 
152           do gtx = lbound (ioi_data.gt, 1) to hbound (ioi_data.gt, 1);
153                gtep = addr (ioi_data.gt (gtx));
154                if gte.mplex & (gte.disk_data_subsystem_idx = 0) then do;
155                     do ctep = ptr (idp, gte.ctep) repeat ptr (idp, cte.next_ctep) while (rel (ctep));
156                          if ^cte.deleted then do;
157                               call io_manager$assign (cte.chx, cte.chanid, ioi_masked$interrupt, bin (rel (ctep)),
158                                    statusp, code);
159                               if code ^= 0 then
160                                    call syserr$error_code (CRASH, code, "^a: Unable to assign channel ^a.", ME,
161                                         cte.chanid);
162                               cte.statusp = statusp;
163                               cte.ioi_use = "1"b;
164                          end;
165                     end;
166                end;
167           end;
168 
169 /**** Now create entries for all configured MCAs (in the IMUs). ****/
170 
171           do itx = lbound (ioi_data.it, 1) to hbound (ioi_data.it, 1);
172                itep = addr (ioi_data.it (itx));
173                if ite.model = "imu" | ite.model = "iioc" then do;
174                     call allocate_gte ("mca" || substr ("abcd", ite.tag, 1));
175                     gte.psia = "1"b;                        /* works like psia */
176                     gte.n_devices = 1;
177                     call allocate_ctes (ite.tag, 3, 1);
178                     device_number = 1;
179                     adding_controller_dte = "0"b;
180                     call allocate_next_dte;
181                end;
182           end;
183 
184 /**** Set up the I/O page tables. ****/
185 
186           call ioi_page_table$init;
187 
188 /* Set up the reset status IDCW */
189 
190           idcwp = addr (ioi_data.rss_idcw);
191           string (idcw) = ""b;
192           idcw.command = "40"b3;                            /* reset status command */
193           idcw.code = "7"b3;                                /* identify this as an IDCW */
194           idcw.chan_cmd = "02"b3;                           /* non-data transfer type command */
195           idcw.count = "01"b3;                              /* only do this once at a time */
196 
197           ioi_data.setup = "1"b;                            /* OK for polling to run now. */
198           return;
199 %page;
200 
201 /* Routine to allocate a group table entry.  It checks for the existence for the gte first, and complains
202    if it already exists.  If not, it allocates one and fills in the easy stuff, returning with gtep
203    pointing to the relevant gte. */
204 
205 allocate_gte:
206      proc (prph_name);
207 
208 
209 dcl       current_gtx            fixed bin;
210 dcl       prph_name              char (4) aligned;
211 
212           do current_gtx = 1 to high_gtx;
213                gtep = addr (ioi_data.gt (current_gtx));
214                if gte.name = prph_name then
215                     call syserr (CRASH, "^a: Duplicate ""prph ^a"" card found.", ME, gte.name);
216           end;
217           high_gtx = high_gtx + 1;
218           gtep = addr (ioi_data.gt (high_gtx));
219           gte.lock = ""b;                                   /* not locked */
220           gte.name = prph_name;                             /* get name from prph card */
221           gte.dtep, gte.ctep = ""b;                         /* no devices or channels yet */
222           string (gte.flags) = ""b;                         /* default all flags to off */
223           gte.n_devices = 0;
224           gte.pending_connects = 0;                         /* no work to do yet */
225           gte.disk_data_subsystem_idx = 0;                  /* not necessarily a disk subsystem */
226 
227      end allocate_gte;
228 
229 /* Routine to find an already allocated gte (it uses the name from a chnl card, which are processed after all
230    prph cards).  Crashes if the gte not found.  In case we want to to something different, it pretends to carry on. */
231 
232 find_gte:
233      proc () returns (bit (1) aligned);
234 
235 dcl       current_gtx            fixed bin;
236 
237           do current_gtx = 1 to ioi_data.ngt;
238                gtep = addr (ioi_data.gt (current_gtx));
239                if chnl_card.name = gte.name then
240                     return ("1"b);                          /* found it */
241           end;
242           call syserr (CRASH, "^a: No matching ""prph ^a"" found for ""chnl ^a"".", ME, chnl_card.name, chnl_card.name);
243           return ("0"b);
244 
245      end find_gte;
246 ^L
247 /* Routine to return the extended status command to use for a given device type, if it knows it. */
248 
249 extended_status_command:
250      proc () returns (bit (6));
251 
252           if gte.fips then
253                return ("00"b3);
254           else if device_type = "dsk" then
255                return ("22"b3);
256           else if device_type = "tap" then
257                return ("50"b3);
258           else if (device_type = "prt") | (device_type = "rdr") | (device_type = "pun") | (device_type = "ccu") then
259                return ("03"b3);
260           else return ("00"b3);
261 
262      end extended_status_command;
263 
264 /* Routine to return true if the device in question returns its extended status with the channel in ASCII
265    mode.  If so, we re-pack it at interrupt side to resemble normal IOM channels.  Currently, EURCs
266    are the only controllers which behave this way. */
267 
268 ascii_detailed_status:
269      proc () returns (bit (1) aligned);
270 
271 dcl       i                      fixed bin;
272 
273           if mpc_cardp ^= null () then
274                if substr (mpc_card.name, 1, 3) = "urp" then /* a unit record mpc */
275                     do i = 1 to hbound (eurc_model_numbers, 1);
276                     if mpc_card.model = eurc_model_numbers (i) then
277                          return ("1"b);
278                end;
279           return ("0"b);
280 
281      end ascii_detailed_status;
282 ^L
283 /* Routine to setup the index to the log_status_info structure.  There is one of these per device type,
284    telling whether or not a particular status is to be logged in the syserr log.  If, for some reason,
285    there is no structure for this device type, the index is left at 0 and the interrupt side uses
286    a heuristic to decide whether or not to log. */
287 
288 setup_log_status_info:
289      proc;
290 
291 dcl       log_status_info_idx    fixed bin;
292 
293           io_log_infop = addr (io_log_status_info$io_log_status_info);
294           do log_status_info_idx = 1 to io_log_info.ndev;
295                logp = addr (io_log_info.log_entry (log_status_info_idx));
296                if log.dev_name = device_type then do;
297                     gte.io_log_info_index = log_status_info_idx;
298                     return;
299                end;
300           end;
301           gte.io_log_info_index = 0;
302 
303      end setup_log_status_info;
304 ^L
305 /* Routine which allocates the device table entries given a prph card and an already setup gte. */
306 
307 allocate_dtes_from_prph_card:
308      proc;
309 
310 dcl       group_idx              fixed bin;
311 
312           adding_controller_dte = "0"b;
313           if gte.fips then
314                device_number = 0;                           /* devices start at zero */
315           else device_number = 1;                           /* devices start at 1, controller at 0 */
316           if (device_type = "tap") | (device_type = "dsk") then do;
317                                                             /* NOTE THE ASSUMPTION THAT THE CARDS LOOK ALIKE */
318                do group_idx = lbound (prph_tap_card_array.group, 1) to hbound (prph_tap_card_array.group, 1);
319                     if prph_tap_card_array.group (group_idx).model ^= 0 then do;
320                          do device_number = device_number
321                               to device_number + prph_tap_card_array.group (group_idx).ndrives - 1;
322                               call allocate_next_dte;
323                          end;
324                     end;
325                     else device_number = device_number + prph_tap_card_array.group (group_idx).ndrives;
326                end;
327                adding_controller_dte = "1"b;
328                device_number = 0;                           /* make one for the controller */
329                call allocate_next_dte;
330           end;
331           else call allocate_next_dte;
332           return;
333 
334      end allocate_dtes_from_prph_card;
335 ^L
336 allocate_next_dte:
337      proc;
338 
339 dcl       device_name            char (32);
340 dcl       device_number_string   pic "99";
341 
342           if gte.mplex & ^(gte.fips & adding_controller_dte) then do;
343                device_number_string = device_number;
344                device_name = gte.name || "_" || device_number_string;
345           end;
346           else device_name = gte.name;
347           high_dtx = high_dtx + 1;
348           dtep = addr (ioi_data.dt (high_dtx));
349 /**** now fill in all of the info ****/
350           unspec (dte) = ""b;                               /* wipe it clean */
351           if gte.dtep = ""b then do;                        /* if this is the first device we've seen in this group */
352                gte.dtep = rel (dtep);                       /* nowhere else it could point */
353                dte.next_dtep = rel (dtep);                  /* circular list */
354           end;
355           else do;                                          /* link it into the circular list */
356                dte.next_dtep = ptr (dtep, gte.dtep) -> dte.next_dtep;
357                                                             /* thread it into the linked list */
358                ptr (dtep, gte.dtep) -> dte.next_dtep = rel (dtep);
359                gte.dtep = rel (dtep);                       /* this is the new head */
360           end;
361           dte.gtep = rel (gtep);                            /* remember our group */
362           dte.channel_required = "";                        /* no channel requirement by default */
363           dte.workspace_ptr = null ();
364           dte.workspace_astep = null ();
365           dte.ptp = null ();
366           dte.in_use = "1"b;                                /* assume it's available for IOI */
367           dte.device = bit (bin (device_number, 6), 6);     /* remember which device we are */
368           dte.lock.event = unspec (IOI_DEVICE_LOCK_EVENT_TEMPLATE) || rel (dtep);
369                                                             /* set event for locking and unlocking */
370           dte.device_table_idx = device_table_idx_from_name (device_name);
371           if dte.device_table_idx = 0 then
372                call syserr (CRASH, "^a: Couldn't find device_table_idx for device ""^a"".", ME, device_name);
373 
374           dte.deleted = ^device_table.device_entry (dte.device_table_idx).configured;
375           if device_type = "fnp" | device_type = "dia" then
376                dte.direct = "1"b;
377           dte.controller = adding_controller_dte;
378 
379 /**** Check for duplicate devices ****/
380           do dtep = ptr (idp, dte.next_dtep) repeat ptr (idp, dte.next_dtep) while (rel (dtep) ^= gte.dtep);
381                if bit (bin (device_number, 6), 6) = dte.device & ^adding_controller_dte then
382                     call syserr (CRASH, "^a: Multiple definitions of device ^a found.", ME, device_name);
383           end;
384 
385      end allocate_next_dte;
386 ^L
387 /* Routine to allocate the channel table entries described on a prph card */
388 
389 allocate_ctes_from_prph_card:
390      proc;
391 
392           if device_type = "tap" | device_type = "dsk" then /* NOTE THAT WE ASSUME THE CARDS ARE THE SAME FORMAT */
393                call allocate_ctes (prph_dsk_card.iom, prph_dsk_card.chan, prph_dsk_card.nchan);
394           else call allocate_ctes (prph_card.iom, prph_card.chan, 1);
395 
396      end allocate_ctes_from_prph_card;
397 
398 /* Routine to allocate the channel table entries described on a chnl card */
399 
400 allocate_ctes_from_chnl_card:
401      proc;
402 
403 dcl       group_idx              fixed bin;
404 
405           do group_idx = lbound (chnl_card_array.group, 1) to hbound (chnl_card_array.group, 1);
406                call allocate_ctes (chnl_card_array.group (group_idx).iom, chnl_card_array.group (group_idx).chan,
407                     chnl_card_array.group (group_idx).nchan);
408           end;
409 
410      end allocate_ctes_from_chnl_card;
411 
412 /* Routine which allocates the ctes.  gtep must be pointing at the group table entry for these channels. */
413 
414 allocate_ctes:
415      proc (iomno, channo, nchans);
416 
417 dcl       channo                 fixed bin (8) parameter;
418 dcl       iomno                  fixed bin (3) parameter;
419 dcl       nchans                 fixed bin parameter;
420 
421 dcl       ch_idx                 fixed bin;
422 dcl       iterp                  bit (18);
423 dcl       itx                    fixed bin;
424 dcl       this_channel           fixed bin (7);
425 
426 /**** Find the ite for this IOM. ****/
427 
428           do itx = 1 to high_itx while (ioi_data.it (itx).tag ^= iomno);
429           end;
430           if itx > high_itx then do;
431                call syserr (CRASH, "^a:  No iom card found for the ^a subsystem.", ME, gte.name);
432                iterp = ""b;                                 /* really won't help, but... */
433           end;
434           else iterp = rel (addr (ioi_data.it (itx)));
435 
436 /**** We loop through the channels in descending order.  This is so the channels will end up
437       on the queue in ascending order (we push them on one at a time).  This is necessary so
438       that we will use the base channel of a physical channel first.  We must do THAT to
439       ensure that it is unmasked when there is a possibility of a special interrupt happening. ****/
440 
441           do ch_idx = nchans - 1 to 0 by -1;
442                high_ctx = high_ctx + 1;                     /* use next cte */
443                ctep = addr (ioi_data.ct (high_ctx));
444                unspec (cte) = ""b;                          /* scrub it before using */
445                cte.next_ctep = gte.ctep;                    /* link this cte onto the gte's list */
446                cte.itep = iterp;
447                gte.ctep = rel (ctep);
448                cte.gtep = rel (gtep);                       /* remember our group */
449                this_channel = channo + ch_idx;
450                call io_chnl_util$iom_to_name (iomno, this_channel, cte.chanid, code);
451                if code ^= 0 then
452                     call syserr$error_code (CRASH, code, "^a: Unable to get the name of IOM ^d channel ^d.", ME, iomno,
453                          this_channel);
454                cte.channel_table_idx = channel_table_idx_from_name (cte.chanid);
455                cte.deleted = ^channel_table.channel_entry (cte.channel_table_idx).configured;
456                cte.direct = (device_type = "fnp") | (device_type = "dia");
457 
458 /**** Check for duplicate channels ****/
459                do ctep = ptr (idp, cte.next_ctep) repeat ptr (idp, cte.next_ctep) while (rel (ctep));
460                     if cte.chanid = ptr (idp, gte.ctep) -> cte.chanid then
461                          call syserr (CRASH, "^a: Multiple definitions of channel ^a found for subsystem ^a.", ME,
462                               cte.chanid, gte.name);
463                end;
464           end;
465 
466      end allocate_ctes;
467 
468 cte_offset:
469      proc (chanid) returns (bit (18));
470 
471 dcl       chanid                 char (8) aligned parameter;
472 
473 dcl       ctx                    fixed bin;
474 
475           do ctx = lbound (ioi_data.ct, 1) to hbound (ioi_data.ct, 1);
476                if (addr (ioi_data.ct (ctx)) -> cte.chanid) = chanid then
477                     return (rel (addr (ioi_data.ct (ctx))));
478           end;
479           return (""b);
480 
481      end cte_offset;
482 ^L
483 iom_table_idx_from_tag:
484      proc (tag) returns (fixed bin);
485 
486 dcl       tag                    fixed bin (3) parameter;
487 
488 dcl       name                   char (1);
489 dcl       i                      fixed bin;
490 
491           name = substr ("ABCD", tag, 1);
492           do i = lbound (iom_table.iom_entry, 1) to hbound (iom_table.iom_entry, 1);
493                if iom_table.iom_entry (i).name = name then
494                     return (i);
495           end;
496           return (lbound (iom_table.iom_entry, 1) - 1);
497 
498      end iom_table_idx_from_tag;
499 
500 device_table_idx_from_name:
501      proc (name) returns (fixed bin);
502 
503 dcl       name                   char (*) parameter;
504 
505 dcl       i                      fixed bin;
506 
507           do i = lbound (device_table.device_entry, 1) to hbound (device_table.device_entry, 1);
508                if device_table.device_entry (i).name = name then
509                     return (i);
510           end;
511           return (lbound (device_table.device_entry, 1) - 1);
512 
513      end device_table_idx_from_name;
514 
515 channel_table_idx_from_name:
516      proc (name) returns (fixed bin);
517 
518 dcl       name                   char (8) aligned parameter;
519 
520 dcl       i                      fixed bin;
521 
522           do i = lbound (channel_table.channel_entry, 1) to hbound (channel_table.channel_entry, 1);
523                if channel_table.channel_entry (i).name = name then
524                     return (i);
525           end;
526           return (lbound (channel_table.channel_entry, 1) - 1);
527 
528      end channel_table_idx_from_name;
529 
530 /* Routine which returns TRUE if the PRPH is on an IMU */
531 
532 IS_ON_IMU:
533      proc (iomno) returns (bit (1));
534 
535 dcl       iomno                  fixed bin (3) parameter;
536 dcl       itx                    fixed bin;
537 
538 /**** Find the ite for this IOM. ****/
539 
540           do itx = 1 to high_itx while (ioi_data.it (itx).tag ^= iomno);
541           end;
542           if itx > high_itx then
543                return ("0"b);
544           if ioi_data.it (itx).model = "imu" | ioi_data.it (itx).model = "iioc" then
545                return ("1"b);
546           else return ("0"b);
547      end IS_ON_IMU;
548 ^L
549 /* Routine which initializes the disk databases in ioi_data.  It assumes that disk_seg is already setup, and
550    that disk_control has assigned to itself all channels for all disks.  It sets up so that later we can usurp
551    any channels we need for udsk activity. gtep is assumed to be pointing to the gte for the disk subsystem */
552 
553 setup_disk_sharing:
554      proc;
555 
556 dcl       ctx                    fixed bin;
557 
558           call find_disktab;                                /* locate the disktab for this subsystem */
559           mpc_cardp = null ();
560           do ctx = lbound (null () -> disk_channel_table, 1) + disktab.nchan - 1
561                to lbound (null () -> disk_channel_table, 1) by -1;
562                                                             /* iterate in order of increasing priority */
563                cp = addr (ptr (diskp, disktab.channels) -> disk_channel_table (ctx));
564                if chantab.chanid ^= "" then do;             /* if the channel is known to disk_control */
565                     call find_matching_cte;                 /* get ctep pointing to the right place */
566                     cte.statusp = chantab.statusp;          /* copy this info */
567                     cte.chx = chantab.chx;
568                     cte.disktab_ctx = ctx;                  /* so we can find this later */
569                     chantab.ioi_ctx = bin (rel (ctep));     /* so disk_control can find us later */
570                     if mpc_cardp = null () then
571                          mpc_cardp = ioi_config$find_controller_card (cte.chanid);
572                     else if mpc_cardp ^= ioi_config$find_controller_card (cte.chanid) then
573                          gte.dual_controller = "1"b;
574                end;
575           end;
576 
577 find_disktab:
578           proc;
579 
580 dcl       dtx                    fixed bin;
581 
582                do dtx = lbound (disk_data.array, 1) to hbound (disk_data.array, 1);
583                     if disk_data.array (dtx).name = gte.name then do;
584                          gte.disk_data_subsystem_idx = dtx; /* so we can find this entry later */
585                          diskp = ptr (disksp, disk_data.array (dtx).offset);
586                          return;
587                     end;
588                end;
589                call syserr (CRASH, "^a: No entry for ^a found in disk_data.", ME, gte.name);
590 
591           end find_disktab;
592 
593 find_matching_cte:
594           proc;
595 
596                do ctep = ptr (idp, gte.ctep) repeat ptr (idp, cte.next_ctep) while (rel (ctep));
597                     if cte.chanid = chantab.chanid then
598                          return;
599                end;
600                call syserr (CRASH, "^a: No cte found for channel ^a.", ME, chantab.chanid);
601 
602           end find_matching_cte;
603 
604      end setup_disk_sharing;
605 ^L
606 %include ioi_data;
607 %page;
608 %include io_config_data;
609 %page;
610 %include config_iom_card;
611 %page;
612 %include config_mpc_card;
613 %page;
614 %include config_ipc_card;
615 %page;
616 %include config_prph_card;
617 %page;
618 %include config_prph_tap_card;
619 %page;
620 %include config_prph_dsk_card;
621 %page;
622 %include config_chnl_card;
623 %page;
624 %include dskdcl;
625 %page;
626 %include io_chnl_util_dcls;
627 %page;
628 %include io_manager_dcls;
629 %page;
630 %include io_log_status_info;
631 %page;
632 %include iom_pcw;
633 %page;
634 %include eurc_model_numbers;
635 %page;
636 %include syserr_constants;
637 ^L
638 /* BEGIN MESSAGE DOCUMENTATION
639 
640    Message:
641    ioi_init: ERROR_CODE  Unable to get the name of name of iom IOMNO channel CHANNO.
642 
643    S:     $crash
644 
645    T:     $init
646 
647    M:     An attempt to generate the name of logical channel CHANNO of iom
648    IOMNO failed.
649 
650    A:     $config
651 
652 
653    Message:
654    ioi_init: ERROR_CODE  Unable to assign channel CHANID.
655 
656    S:     $crash
657 
658    T:     $init
659 
660    M:     A logical channel could not be assigned to IOI.
661    $err
662 
663    A:     $contact
664 
665 
666    Message:
667    ioi_init: Duplicate "prph NAME" card found.
668 
669    S:     $crash
670 
671    T:     $init
672 
673    M:     $msg
674 
675    A:     $config
676 
677 
678    Message:
679    ioi_init: No matching "prph NAME" found for "chnl NAME".
680 
681    S:     $crash
682 
683    T:     $init
684 
685    M:     $msg
686 
687    A:     $config
688 
689 
690    Message:
691    ioi_init: Multiple definitions of device NAME found.
692 
693    S:     $crash
694 
695    T:     $init
696 
697    M:     $msg
698 
699    A:     $config
700 
701 
702    Message:
703    ioi_init: Multiple definitions of channel CHANID found for subsystem NAME.
704 
705    S:     $crash
706 
707    T:     $init
708 
709    M:     $msg
710 
711    A:     $config
712 
713 
714    Message:
715    ioi_init: No entry for NAME found in disk_data.
716 
717    S:     $crash
718 
719    T:     $init
720 
721    M:     $err
722 
723    A:     $contact
724 
725 
726    Message:
727    ioi_init: No cte found for channel CHANID.
728 
729    S:     $crash
730 
731    T:     $init
732 
733    M:     $err
734 
735    A:     $contact
736 
737 
738    END MESSAGE DOCUMENTATION */
739 
740      end ioi_init;