1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         * Copyright (c) 1972 by Massachusetts Institute of        *
  8         * Technology and Honeywell Information Systems, Inc.      *
  9         *                                                         *
 10         *********************************************************** */
 11 
 12 
 13 
 14 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
 15 disk_init:
 16      procedure (pvtx, confp);                               /* here to init disk routines */
 17 
 18 /* DISK_INIT - Initialize Data Bases for Disk DIMs.
 19    recoded 6/19/70 - Noel I. Morris
 20    revised 8/17/73 by N. I. Morris for DSU-191 and RSR feature
 21    revised 3/27/75 by Noel I. Morris for new storage system
 22    revised 4/79 by Michael R. Jordan for MSS0500/1.
 23    revised 4/80 by Michael R. Jordan for dual controller MSU0500/1 subsystems.
 24    modified June 1981 by C. Hornig for new I/O.
 25    Modified February 1982 by C. Hornig for MR10 io_manager.
 26    modified March 1982 by J. Bongiovanni for better config card validation
 27    modified October 1983 by E. N. Kittlitz to not read off end of dsk card
 28 
 29    Modified March 1984 by T. Oke to initialize system wide free_q.
 30    Modified April 1984 by T. Oke to change channel table initialization
 31    algorithm and permit up to dskdcl_chans_per_subsys channels per
 32    sub-system.
 33    Modified April 1984 by T. Oke to add use of syserr_constants include file.
 34 
 35    Modified May 1984 by T. Oke to add adaptive optimization initialization.
 36    Modified September 1984 by Chris Jones to correct error message.
 37    Modified Nov 26, 1984 by Fawcett to support dev 0 and fips.
 38    Modified Jan 1985 by Paul Farley to correct a bug in channel counting.
 39    Modified Jun 1985 by Paul Farley to correct a bug in checking for
 40    shared spindle when dev_array(i) is zero.
 41    Modified July 1985 by Paul Farley to include a fix for the channel pick loop
 42    done by Tom Oke.
 43 */
 44 
 45 /****^  HISTORY COMMENTS:
 46   1) change(85-09-09,Fawcett), approve(85-09-09,MCR6979),
 47      audit(86-01-17,CLJones), install(86-03-21,MR12.0-1033):
 48      Device zero support
 49      for FIPS.
 50   2) change(86-01-20,Fawcett), approve(86-04-11,MCR7383),
 51      audit(86-07-07,GDixon), install(86-07-17,MR12.0-1097):
 52      Add support for 512_WORD_IO devices, 3380 and 3390.
 53   3) change(86-06-05,GJohnson), approve(86-06-05,MCR7387),
 54      audit(86-06-10,Martinson), install(86-07-17,MR12.0-1091):
 55      Correct error message documentation.
 56                                                    END HISTORY COMMENTS */
 57 
 58 dcl       pvtx                   fixed bin parameter;       /* index to PVT entry for device */
 59 dcl       confp                  ptr parameter;             /* config card ptr */
 60 
 61 dcl       sx                     fixed bin;                 /* disk subsystem index */
 62 dcl       type                   fixed bin (8);             /* disk device type */
 63 dcl       name                   char (4) aligned;          /* disk device name */
 64 dcl       chx                    fixed bin (35);            /* io_manager index for channel */
 65 dcl       idx                    fixed bin (12);            /* channel ID index for disk_interrupt */
 66 dcl       i                      fixed bin;                 /* logical unit number index */
 67 dcl       j                      fixed bin;                 /* configuration card unit index */
 68 dcl       k                      fixed bin;                 /* .. */
 69 dcl       ci                     fixed bin;
 70 dcl       devt                   fixed bin;                 /* device type for this model number */
 71 dcl       dev_array              (0:63) fixed bin;          /* device types indexed by device # */
 72 dcl       rcode                  fixed bin (35);            /* error code */
 73 dcl       base                   bit (24) aligned;          /* absolute address of DCW list */
 74 dcl       fips_disk              bit (1);
 75 dcl       chan_array             (dskdcl_chans_per_subsys) char (8) aligned;
 76                                                             /* names of channels */
 77 
 78 /* Channel table.  Indicates start channel and count on each adaptor. */
 79 
 80 dcl       adaptor_index          fixed bin;
 81 dcl       adaptor_count          fixed bin;
 82 
 83 dcl       1 adaptor              (4),                       /* Can be 4 LA's */
 84             2 channel_start      fixed bin,
 85             2 chantab_index      fixed bin,
 86             2 channel_count      fixed bin,
 87             2 channels_used      fixed bin;
 88 
 89 dcl       1 d                    like devtab;
 90 
 91 /* as dskdcl's number of IO types is increased - so increase the hbound */
 92 
 93 dcl       response               (0:6) float bin (27) static options (constant) initial (
 94                                                             /* */
 95                                  100.0,                     /* PAGE_READ */
 96                                  50000.0,                   /* PAGE_WRITE */
 97                                  20.0,                      /* VTOC_READ */
 98                                  50.0,                      /* VTOC_WRITE */
 99                                  1.0,                       /* TEST */
100                                  200.0,                     /* BOOTLOAD_READ */
101                                  100000.0                   /* BOOTLOAD_WRITE */
102                                  );
103 
104 dcl       ME                     char (16) static options (constant) init ("disk_init");
105 
106 dcl       absadr                 ext entry (ptr, fixed bin (35)) returns (fixed bin (24));
107 dcl       config_$find_2         entry (char (4), char (4) aligned, pointer);
108 dcl       dctl$disk_inter        entry (bit (36) aligned, fixed bin (3), bit (36) aligned);
109 dcl       syserr                 ext entry options (variable);
110 
111 dcl       error_table_$io_not_configured
112                                  fixed bin (35) ext static;
113 
114 dcl       (addr, addrel, bin, bit, clock, currentsize, divide, float, hbound, mod, null, ptr, rel, size,
115           substr, unspec)        builtin;
116 ^L
117           prph_dsk_cardp = confp;
118           disksp = addr (disk_seg$);                        /* Get pointer to disk segment. */
119 
120           if disk_data.free_offset = "0"b then do;          /* If never initialized ... */
121                disk_data.free_offset = bit (bin (currentsize (disk_data), 18));
122                                                             /* Set offset of first disktab structure. */
123                statp = addr (disksp -> disk_data.status_mask);
124                                                             /* Get pointer to mask for disk status. */
125                status.power = "1"b;                         /* Set up mask to detect error conditions. */
126                status.major = "1111"b;
127                status.channel_stat = "111"b;
128                status.central_stat = "111"b;
129 
130 /* Thread all queue entries into the free list. */
131 
132                unspec (disk_data.free_q) = "0"b;            /* clear stats */
133                do i = 1 to disk_data.free_q_size - 1;       /* Step through all queue entries. */
134                     disk_data.free_q_entries (i).next = rel (addr (disk_data.free_q_entries (i + 1)));
135                     disk_data.free_q_entries (i + 1).prev = rel (addr (disk_data.free_q_entries (i)));
136                end;                                         /* Make each entry point to the next one. */
137 
138                disk_data.free_q.head = rel (addr (disk_data.free_q_entries (1)));
139                                                             /* The head of the list is the first entry. */
140                disk_data.free_q.tail = rel (addr (disk_data.free_q_entries (disk_data.free_q_size)));
141                                                             /* The tail of the list is the last entry. */
142                disk_data.lock = ""b;                        /* clear the lock */
143 
144 /* Initialize system wide loading information. */
145 
146                unspec (disk_data.sys_info) = "0"b;
147                disk_data.sys_info (PAGE_READ).max_depth = 6.0;
148                disk_data.sys_info (PAGE_READ).depth_map = rel (addr (disk_data.sys_info (PAGE_READ).depth));
149 
150                disk_data.sys_info (PAGE_WRITE).max_depth = float (disk_data.free_q_size) * 0.75;
151                disk_data.sys_info (PAGE_WRITE).depth_map = rel (addr (disk_data.sys_info (PAGE_WRITE).depth));
152 
153                disk_data.sys_info (VTOC_READ).max_depth = 6.0;
154                disk_data.sys_info (VTOC_READ).depth_map = rel (addr (disk_data.sys_info (VTOC_READ).depth));
155 
156                disk_data.sys_info (VTOC_WRITE).max_depth = 12.0;
157                disk_data.sys_info (VTOC_WRITE).depth_map = rel (addr (disk_data.sys_info (VTOC_WRITE).depth));
158 
159                disk_data.sys_info (BOOTLOAD_READ).max_depth = 6.0;
160                disk_data.sys_info (BOOTLOAD_READ).depth_map = rel (addr (disk_data.sys_info (BOOTLOAD_READ).depth));
161 
162                disk_data.sys_info (BOOTLOAD_WRITE).max_depth = 12.0;
163                disk_data.sys_info (BOOTLOAD_WRITE).depth_map = rel (addr (disk_data.sys_info (BOOTLOAD_WRITE).depth));
164 
165                disk_data.sys_info (TEST).max_depth = 1.0;
166                disk_data.sys_info (TEST).depth_map = rel (addr (disk_data.sys_info (TEST).depth));
167 
168 /* Initialize stagnation time limit for optimizer */
169 
170                disk_data.stagnate_time = 5000000;           /* 5 seconds */
171                disk_data.max_depth_reset_time = clock ();
172           end;
173 ^L
174 /* Initialize sub-system information. */
175 
176           pvt_arrayp = addr (pvt$array);                    /* Get pointer to PVT array */
177           pvtep = addr (pvt_array (pvtx));                  /* Get pointer to PVT entry for this device. */
178 
179           type = pvte.device_type;                          /* Extract device type from PVT entry. */
180           name = pvte.devname;                              /* Get name of disk subsytem. */
181 
182           do sx = 1 to disk_data.subsystems while (name ^= disk_data.name (sx));
183           end;                                              /* Look for this subsystem already initialized. */
184 
185           pvtdip = addr (pvte.dim_info);                    /* Get pointer to dim_info in PVT entry. */
186           pvtdi.sx = sx;                                    /* Put sx where disk dim can find it */
187 
188           pvtdi.usable_sect_per_cyl = divide (sect_per_cyl (type), sect_per_rec (type), 17, 0) * sect_per_rec (type);
189                                                             /* Compute # of usable sectors on disk cylinder. */
190           pvtdi.unused_sect_per_cyl = sect_per_cyl (type) - pvtdi.usable_sect_per_cyl;
191                                                             /* Compute # of unused sectors at end of cylinder. */
192 
193           if sx > disk_data.subsystems then do;             /* If not already initialized ... */
194                disk_data.subsystems = sx;                   /* Update count of subsystems. */
195                disk_data.name (sx) = name;
196                disk_data.offset (sx) = disk_data.free_offset;
197                                                             /* Set pointer to place for disk data base. */
198 
199                diskp = ptr (disksp, disk_data.free_offset); /* Get pointer to disk data base. */
200                call init_disk_database;                     /* Set up disktab structure. */
201 
202                disk_data.free_offset = rel (addrel (diskp, currentsize (disktab) + disktab.nchan * size (chantab)));
203           end;                                              /* Update first unused location in segment. */
204 
205           else                                              /* If already initialized ... */
206                diskp = ptr (disksp, disk_data.offset (sx)); /* Get pointer to disk data base. */
207 
208           disktab.pvtx (pvte.logical_area_number) = pvtx;   /* Save PVT entry index in device table. */
209 
210           return;
211 ^L
212 IS_FIPS:
213      procedure () returns (bit (1));
214 dcl       groupx                 fixed bin;
215 dcl       i                      fixed bin;
216 
217           do groupx = 1 to hbound (prph_dsk_card.group, 1) while (prph_dsk_card.group (groupx).model ^= -1);
218                if prph_dsk_card.group (groupx).model ^= 0 then do;
219                     do i = 1 to config_data_$disk_drive_model_names.count;
220                          if config_data_$disk_drive_model_names.names (i).model = prph_dsk_card.group (groupx).model then
221                               return (config_data_$disk_drive_model_names.names (i).device_0_valid);
222                     end;
223                     call syserr (CRASH, "^a: Disk model ^d not found in config_data_.", ME,
224                          prph_dsk_card.group (groupx).model);
225                end;
226           end;
227           call syserr (CRASH, "^a: No valid disk models found on PRPH ^a card.", ME, prph_dsk_card.name);
228      end IS_FIPS;
229 ^L
230 init_disk_database:
231      procedure;
232 
233           disktab.abs_mem_addr = absadr (addr (disktab), rcode);
234           if rcode ^= 0 then
235                goto absadr_error;
236 
237 /* Find maximum number of devices in disk subsystem. */
238 
239           call check_config_fields (prph_dsk_cardp, addr (prph_dsk_card.group));
240 
241           fips_disk = IS_FIPS ();
242           if fips_disk then
243                disktab.first_dev = 0;
244           else disktab.first_dev = 1;
245 
246           j = disktab.first_dev;
247 
248           do i = 1 to hbound (prph_dsk_card.group, 1) while (prph_dsk_card.group (i).model ^= -1);
249                                                             /* Count disk drives. */
250                call check_config_fields (prph_dsk_cardp, addr (prph_dsk_card.group (i).ndrives));
251                                                             /* Make sure fields are there */
252                if (j + prph_dsk_card.group (i).ndrives - disktab.first_dev) > hbound (dev_array, 1) then
253                                                             /* Too many drives. */
254                     call syserr (CRASH, "^a: Too many devices configured for ^a.  Max device is ^d.", ME, name,
255                          hbound (dev_array, 1));
256                devt = prph_dsk_card.group (i).model;
257                if devt ^= 0 then do;
258                     do devt = 1 to hbound (MODEL, 1) while (MODEL (devt) ^= prph_dsk_card.group (i).model);
259                     end;
260                     if devt > hbound (MODEL, 1) then        /* Bad device model number. */
261                          call syserr (CRASH, "^a: Unknown model number ^d on PRPH ^a", ME, prph_dsk_card.group (i).model,
262                               name);
263                     devt = MODELX (devt);                   /* Get device type. */
264                end;
265                do k = j to j + prph_dsk_card.group (i).ndrives - 1;
266                     dev_array (k) = devt;                   /* This can be zero! => no device present. */
267                end;
268                j = j + prph_dsk_card.group (i).ndrives;
269           end;
270 
271           disktab.last_dev, disktab.dev_index = j - 1;      /* set max drive and scan index */
272 
273 /* Setup master optimization information. */
274 
275           unspec (d.opt_info) = "0"b;
276           do i = 0 to MAX_IO_TYPE;
277                sysp = addr (disk_data.sys_info (i));
278                d.opt_info (i).sys_info = rel (addr (sys_info.fraction));
279                if sys_info.max_depth > 1.0 then do;
280                     d.opt_info (i).slope = (response (i) - 1.0) / (sys_info.max_depth - 1.0);
281                     d.opt_info (i).intercept = ((response (i) * sys_info.max_depth) - 1.0) / (sys_info.max_depth - 1.0);
282                end;
283                else do;
284                     d.opt_info (i).slope = 0.0;
285                     d.opt_info (i).intercept = 1.0e10;
286                end;
287           end;
288 
289 /* Analyze device configuration for errors. */
290 
291           do i = disktab.first_dev to disktab.last_dev;     /* Look at each device configured. */
292                dp = addr (disktab.devtab (i));
293                if dev_array (i) > 0 then
294                     if shared_spindle (dev_array (i)) then  /* This guy has a buddy. */
295                          if mod (i, 2) ^= 0 then do;        /* First of a pair. */
296                               if i >= disktab.last_dev then do;
297                                                             /* If this is the last one, the next is missing. */
298 MISSING_BUDDY:
299                                    call syserr (CRASH, "^a: ^a ^[^d^s^;^s^d^] must be configured if ^a ^d is configured.",
300                                         ME, name, mod (i, 2) = 0, i - 1, i + 1, name, i);
301                               end;
302                               if dev_array (i + 1) ^= dev_array (i) then do;
303                                                             /* Buddies must be the same type. */
304 BAD_BUDDY:
305                                    call syserr (CRASH, "^a: Devices ^d and ^d of ^a must have the same model number.", ME,
306                                         i - 1 + mod (i, 2), i + mod (i, 2), name);
307                               end;
308                               devtab.buddy = i + 1;         /* Next guy has to be buddy. */
309                               devtab.pdi = i;               /* Set primary device index. */
310                          end;
311                          else do;                           /* The second of a pair. */
312                               if i <= 1 then
313                                    goto MISSING_BUDDY;
314                               if dev_array (i - 1) ^= dev_array (i) then
315                                    goto BAD_BUDDY;
316                               devtab.buddy,                 /* Last one is the buddy ... */
317                                    devtab.pdi = i - 1;      /* ... and the primary device. */
318                          end;
319                     else do;                                /* Not a shared spindle. */
320 
321                          devtab.buddy = 0;                  /* No buddy */
322                          devtab.pdi = i;                    /* This is the primary device */
323                     end;
324                else ;
325 
326 /* setup optimization and queues. */
327 
328                unspec (devtab.opt_info) = unspec (d.opt_info);
329                unspec (devtab.wq) = "0"b;
330           end;
331 ^L
332 /* Analyze channel information for disk subsystem. */
333 
334           if prph_dsk_card.nchan > dskdcl_chans_per_subsys then
335 TOO_MANY_CHANNELS:
336                call syserr (CRASH, "^a: Too many channels configured for ^a.  Limit is ^d.", ME, name,
337                     dskdcl_chans_per_subsys);
338 
339           do j = 1 to prph_dsk_card.nchan;                  /* Determine the channels defined on disk card. */
340                call io_chnl_util$iom_to_name ((prph_dsk_card.iom), (prph_dsk_card.chan + j - 1), chan_array (j), rcode);
341                if rcode ^= 0 then
342                     call syserr (CRASH, "^a: Invalid channel on PRPH ^a card.", ME, prph_dsk_card.name);
343           end;
344 
345 /* Store adaptor information. */
346 
347           adaptor_index = 1;
348           adaptor (1).channel_start = 1;
349           adaptor (1).channel_count = prph_dsk_card.nchan;
350           adaptor (1).channels_used = 0;
351           adaptor (1).chantab_index = 1;
352 
353           chnl_cardp = null ();
354           call config_$find_2 ("chnl", name, chnl_cardp);   /* Look for chnl card for this subsystem. */
355           if chnl_cardp ^= null () then                     /* If chnl card found ... */
356                do i = 1 to 3 while (chnl_card.group (i).iom > 0);
357                                                             /* Look at 3 possible channel groups. */
358                call check_config_fields (chnl_cardp, addr (chnl_card.group (i).nchan));
359                                                             /* Make sure fields are all there */
360 
361                adaptor_index = adaptor_index + 1;
362                adaptor (adaptor_index).channel_start = j;
363                adaptor (adaptor_index).channel_count = chnl_card.group (i).nchan;
364                adaptor (adaptor_index).channels_used = 0;
365                adaptor (adaptor_index).chantab_index = j;   /* note start */
366 
367                do k = 0 to chnl_card.group (i).nchan - 1;   /* Determine channels in each group. */
368                     if j > dskdcl_chans_per_subsys then
369                          goto TOO_MANY_CHANNELS;
370                     call io_chnl_util$iom_to_name ((chnl_card.group (i).iom), (chnl_card.group (i).chan + k),
371                          chan_array (j), rcode);
372                     if rcode ^= 0 then
373                          call syserr (CRASH, "^a: Invalid channel on CHNL ^a card", ME, chnl_card.name);
374                     j = j + 1;                              /* Step channel index. */
375                end;
376           end;
377 
378           disktab.nchan = j - 1;                            /* Set total number of channels. */
379 
380 
381 /* Calculate start of channel table */
382 
383           disktab.channels = rel (addrel (diskp, currentsize (disktab)));
384 ^L
385 /* Tell the iom manager about the disk. */
386 
387           ci = 0;                                           /* No channel entries filled yet. */
388           adaptor_count = adaptor_index;
389           adaptor_index = 0;
390           do i = 1 to disktab.nchan;                        /* Iterate for all channels. */
391 re_scan_adaptor:
392                adaptor_index = mod (adaptor_index, adaptor_count) + 1;
393                if adaptor (adaptor_index).channel_count <= 0 then
394                     goto re_scan_adaptor;                   /* skip empty slot */
395                else do;
396                     adaptor (adaptor_index).channel_count = adaptor (adaptor_index).channel_count - 1;
397                     k = adaptor (adaptor_index).channel_start + adaptor (adaptor_index).channels_used;
398                     adaptor (adaptor_index).channels_used = adaptor (adaptor_index).channels_used + 1;
399                     ci = ci + 1;
400                     idx = (sx * dskdcl_chans_per_subsys) + ci - 1;
401                                                             /* Compute channel identification index */
402                     cp = addr (ptr (disksp, disktab.channels) -> disk_channel_table (ci));
403                                                             /* get pointer to channel info */
404                     chantab.chanid = chan_array (k);        /* Save channel name */
405 
406                     call io_manager$assign (chx, chan_array (k), dctl$disk_inter, (idx), chantab.statusp, rcode);
407                     if rcode ^= 0 then                      /* If error ... */
408                          if rcode ^= error_table_$io_not_configured then
409                               call syserr (CRASH, "^a: Unable to assign ^a for ^a.", ME, chan_array (k),
410                                    disk_data.name (sx));
411                          else ;
412                     else do;
413                          chantab.chx = chx;                 /* Save io_manager index in channel table. */
414                          chantab.in_use = "1"b;             /* Indicate it's in use. */
415                          disktab.channels_online = disktab.channels_online + 1;
416                     end;
417 ^L
418 /* Fill in all constant information in the DCW list. */
419 
420                     base = bit (absadr (addr (cp -> chantab.select_data.limit), rcode));
421                     if rcode ^= 0 then                      /* Get absolute address of base of DCW list. */
422 absadr_error:
423                          call syserr (CRASH, "^a: error ^w from absadr for ^a ^a", ME, rcode, disk_data.name (sx),
424                               chan_array (k));
425 
426                     idcwp = addr (chantab.rstdcw);          /* Get pointer to restore IDCW. */
427                     idcw.command = "42"b3;                  /* command = 42 (restore access arm) */
428                     idcw.code = "111"b;                     /* command dcw */
429                     idcw.control = "10"b;                   /* set control to "proceed" */
430                     idcw.chan_cmd = "02"b3;                 /* non-data transfer */
431                     idcw.count = "01"b3;                    /* count of 1 */
432 
433                     idcwp = addr (chantab.scdcw);           /* Get pointer to seek IDCW. */
434                     idcw.command = seek_command (devt);     /* set the correct seek type for the devices on this channel */
435                     idcw.ext = substr (base, 1, 6);         /* address extension */
436                     idcw.code = "111"b;                     /* command dcw */
437                     idcw.ext_ctl = "1"b;                    /* Turn on address extension bit. */
438                     idcw.control = "10"b;                   /* set control to proceed */
439 
440                     dcwp = addr (chantab.sddcw);            /* Get pointer to seek data xfer DCW. */
441                     dcw.address = substr (base, 7);
442                     dcw.tally = "0001"b3;
443 
444                     idcwp = addr (chantab.dcdcw);           /* Get pointer to disk read/write IDCW. */
445                     idcw.code = "111"b;                     /* command dcw */
446                     idcw.ext_ctl = "1"b;                    /* Turn on address extension bit. */
447 
448                     dcwp = addr (chantab.dddcw);            /* Get pointer to disk data xfer DCW. */
449 
450                     base = bit (absadr (addr (cp -> chantab.detailed_status), rcode));
451                     if rcode ^= 0 then
452                          go to absadr_error;                /* Get absolute address for detailed status. */
453 
454                     idcwp = addr (chantab.dscdcw);          /* Get pointer to read status IDCW. */
455                     idcw.command = "22"b3;                  /* Read Status Register command */
456                     idcw.ext = substr (base, 1, 6);
457                     idcw.code = "111"b;
458                     idcw.ext_ctl = "1"b;
459 
460                     dcwp = addr (chantab.dsddcw);           /* Get pointer to status data xfer DCW. */
461                     dcw.address = substr (base, 7);
462                     dcw.tally = "0004"b3;
463 
464                     idcwp = addr (chantab.rssdcw);          /* Get pointer to reset status IDCW. */
465                     idcw.command = "00"b3;                  /* Request Status command */
466                     idcw.ext = substr (base, 1, 6);
467                     idcw.code = "111"b;
468                     idcw.ext_ctl = "1"b;
469                end;
470           end;
471 
472           return;
473 
474 
475      end init_disk_database;
476 ^L
477 /* Check that specified fields exist on config card */
478 
479 check_config_fields:
480      proc (cardp, fieldp);
481 
482 dcl       cardp                  ptr;                       /* Pointer to config card */
483 dcl       fieldp                 ptr;                       /* Pointer to field within that card */
484 
485 dcl       field_inx              fixed bin;                 /* Index of field */
486 
487           field_inx = bin (rel (fieldp)) - bin (rel (cardp));
488           if field_inx > cardp -> config_card.type_word.n_fields then
489                                                             /* Not there */
490                call syserr (CRASH, "^a: Invalid format for ^a^[ ^a^;^1s^] card.", ME, cardp -> config_card.word,
491                     (cardp -> config_card.type_word.field_type (1) = CONFIG_STRING_TYPE
492                     | cardp -> config_card.type_word.field_type (1) = CONFIG_SINGLE_CHAR_TYPE), cardp -> chnl_card.name);
493 
494      end check_config_fields;
495 ^L
496 %include config_chnl_card;
497 %page;
498 %include config_data_dcls;
499 %page;
500 %include config_deck;
501 %page;
502 %include config_prph_dsk_card;
503 %page;
504 %include dskdcl;
505 %page;
506 %include fs_dev_types;
507 %page;
508 %include io_chnl_util_dcls;
509 %page;
510 %include io_manager_dcls;
511 %page;
512 %include iom_dcw;
513 %page;
514 %include iom_pcw;
515 %page;
516 %include iom_stat;
517 %page;
518 %include pvte;
519 %page;
520 %include syserr_constants;
521 ^L
522 /* BEGIN MESSAGE DOCUMENTATION
523 
524    Message:
525    disk_init: Invalid channel on PRPH DSKx card.
526 
527    S:     $crash
528 
529    T:     $init
530 
531    M:     An invalid channel specification was found on the PRPH DSKx card.
532 
533 
534 
535    Message:
536    disk_init: Invalid channel on CHNL DSKx card.
537 
538    S:     $crash
539 
540    T:     $init
541 
542    M:     An invalid channel specification was found on the CHNL card for DSKx.
543 
544 
545 
546    Message:
547    disk_init: Unable to assign CCCC for DSKx.
548 
549    S:     $crash
550 
551    T:     $init
552 
553    M:     An error has occurred trying to assign an IOM channel
554    for the disk subsystem DSKX.
555 
556    A:     $recover
557    Check the configuration deck and the operability of the hardware before rebooting.
558 
559 
560    Message:
561    disk_init: error WWWW from absadr for DSKX iom N, ch ZZ.
562 
563    S:     $crash
564 
565    T:     $init
566 
567    M:     $err
568 
569    A:     $recover
570    $boot_tape
571 
572 
573    Message:
574    disk_init: Too many devices configured for DSKn.  Max device is N.
575 
576    S:     $crash
577 
578    T:     $init
579 
580    M:     The software limit for devices per subsystem has been exceeded.
581 
582    A:     Fix the config deck and reboot.
583 
584 
585    Message:
586    disk_init: Unknown model number NNNN on PRPH dskN.
587 
588    S: $crash
589 
590    T: $init
591 
592    M: The model number NNNN on the prph card for disk subsystem N is invalid.
593 
594    A: Correct the config deck and reboot.
595 
596 
597    Message:
598    disk_init: DSKn D1 must be configured if DSKn D2 is configured.
599 
600    S:     $crash
601 
602    T:     $init
603 
604    M:     Only one of a pair of devices that share a common spindle has been
605    configured.
606 
607    A:     Change the config deck to include the missing device and reboot.
608 
609 
610    Message:
611    disk_init: Devices D1 and D2 of DSKn must have the same model number.
612 
613    S:     $crash
614 
615    T:     $init
616 
617    M:     Two devices that share a common spindle have been configured
618    with different model numbers.
619 
620    A:     Correct the config deck and reboot.
621 
622 
623    Message:
624    disk_init: Too many channels configured for DSKn.  Limit is N.
625 
626    S:     $crash
627 
628    T:     $init
629 
630    M:     The per subsystem software limit for logical channels has been exceeded.
631 
632    A:     Fix the config deck and reboot.  If more channels are needed, split
633    the configuration into more subsystems in the config deck.
634 
635 
636    Message:
637    disk_init: Invalid format for XXXX card.
638 
639    S:     $crash
640 
641    T:     $init
642 
643    M:     A required field on the XXXX card is not present.
644 
645    A:     $recover
646    Fix the configuration deck and reboot.
647 
648 
649    Message:
650    disk_init: Disk model XXXX not found in config_data_.
651 
652    S:     $crash
653 
654    T:     $init
655 
656    M:     $err
657 
658    A:     $recover
659    Fix the configuration deck and reboot.
660 
661 
662    Message:
663    disk_init: No valid disk models found on PRPH DSKx card.
664 
665    S:     $crash
666 
667    T:     $init
668 
669    M:     All disk model fields were found to be zero.
670 
671    A:     Fix the configuration deck and reboot.
672 
673 
674    END MESSAGE DOCUMENTATION */
675 
676      end disk_init;