1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1984 *
  6         *                                                         *
  7         *********************************************************** */
  8 bce_fwload: proc (p_ss_info_ptr);
  9 
 10 /* bce routine to load, upon command, a given mpc.
 11 Keith Loepere, January 1984. */
 12 
 13 /* modified October of 1984 to add -channel argument - Allen Ball. */
 14 
 15 /* format: style4,initcol1,indattr,declareind8,dclind4,idind36,ifthenstmt,ifthen,^indproc,delnl,insnl */
 16 
 17 dcl addr                                builtin;
 18 dcl arg                                 char (arg_len) based (arg_ptr);
 19 dcl arg_count                           fixed bin;          /* number of mpcs */
 20 dcl arg_len                             fixed bin (21);
 21 dcl arg_num                             fixed bin;          /* loop counter */
 22 dcl arg_ptr                             ptr;
 23 dcl baseno                              builtin;
 24 dcl bin                                 builtin;
 25 dcl character                           builtin;
 26 dcl code                                fixed bin (35);
 27 dcl com_err_                            entry () options (variable);
 28 dcl config_$find                        entry (char (4) aligned, ptr);
 29 dcl config_$find_2                      entry (char (4) aligned, char (4) aligned, ptr);
 30 dcl cu_$arg_count_rel                   entry (fixed bin, ptr, fixed bin (35));
 31 dcl cu_$arg_ptr_rel                     entry (fixed bin, ptr, fixed bin (21), fixed bin (35), ptr);
 32 dcl cv_dec_check_                       entry (char (*), fixed bin (35)) returns (fixed bin (35));
 33 dcl dimension                           builtin;
 34 dcl divide                              builtin;
 35 dcl fw_modules                          (16) char (8);      /* names of fw modules to load */
 36 dcl fw_module_count                     fixed bin;          /* number of modules */
 37 dcl hc_load_mpc                         entry (char (8) aligned, ptr, fixed bin (18), char (*), fixed bin (35));
 38 dcl hc_load_mpc$urc                     entry (char (8) aligned, (*) ptr, (*) fixed bin (18), char (*), fixed bin (35));
 39 dcl increment                           fixed bin;
 40 dcl index                               builtin;
 41 dcl ioa_                                entry () options (variable);
 42 dcl ltrim                               builtin;
 43 dcl max                                 builtin;
 44 dcl me                                  char (6) static options (constant) init ("fwload");
 45 dcl mpc_chanid                          char (8) aligned;   /* iom/channel name */
 46 dcl mpc_name                            char (4) aligned;   /* as in mspa */
 47 dcl null                                builtin;
 48 dcl p_ss_info_ptr                       ptr parameter;
 49 dcl preferred_mpc_chanid                char (8) aligned;
 50 dcl slt$                                external;
 51 dcl slt_manager$get_seg_ptr             entry (char (32) aligned) returns (ptr);
 52 dcl substr                              builtin;
 53 dcl translate                           builtin;
 54 %page;
 55           ss_info_ptr = p_ss_info_ptr;
 56           call cu_$arg_count_rel (arg_count, ss_info.arg_list_ptr, code);
 57           if code ^= 0 | arg_count < 1 then do;
 58 usage:
 59                call com_err_ (code, me, "Usage: fwload mpc_names {args}");
 60                return;
 61           end;
 62           do arg_num = 1 repeat arg_num + increment while (arg_num <= arg_count);
 63                preferred_mpc_chanid = "";
 64                increment = 1;
 65                call cu_$arg_ptr_rel (arg_num, arg_ptr, arg_len, code, ss_info.arg_list_ptr);
 66                mpc_name = arg;
 67                if arg_num + 2 <= arg_count then do;
 68                     call cu_$arg_ptr_rel (arg_num + 1, arg_ptr, arg_len, code, ss_info.arg_list_ptr);
 69                     if substr (arg, 1, 1) = "-" then do;    /* It must be a control argument. */
 70                          if arg = "-channel" | arg = "-chnl" then do;
 71                               call cu_$arg_ptr_rel (arg_num + 2, arg_ptr, arg_len, code, ss_info.arg_list_ptr);
 72                               if code = 0 then do;
 73                                    preferred_mpc_chanid = arg;
 74                                    increment = 3;
 75                               end;
 76                               else do;
 77                                    call ioa_ ("^a: A channel must be specified.", me);
 78                                    return;
 79                               end;
 80                          end;
 81                          else do;
 82                               call ioa_ ("^a: ^a is not a recognized option.", me, arg);
 83                               return;
 84                          end;
 85                     end;
 86                end;
 87                if find_mpc (mpc_chanid, mpc_name, fw_modules, fw_module_count, mpc_cardp) then do;
 88                     if preferred_mpc_chanid ^= "" then do;
 89                          if validate_primary_channel (preferred_mpc_chanid, mpc_cardp) then
 90                               call load_mpc (preferred_mpc_chanid, mpc_name, fw_modules, fw_module_count);
 91                          else do;
 92                               call ioa_ ("^a: Channel ^a is not a primary channel for ^a.", me, preferred_mpc_chanid,
 93                                    mpc_name);
 94                               return;
 95                          end;
 96                     end;
 97                     else call load_mpc (mpc_chanid, mpc_name, fw_modules, fw_module_count);
 98                end;
 99                else do;
100                     call ioa_ ("^a: ^a is not a valid mpc.", me, mpc_name);
101                     return;
102                end;
103           end;
104           return;
105 %page;
106 find_mpc:
107      proc (mpc_chanid, mpc_name, fw_modules, fw_module_count, p_mpc_cardp) returns (bit (1) aligned);
108 
109 /* search the config deck for an mpc so as to know what channel and module is
110    needed - also find peripherals for urcs */
111 
112 dcl code                                fixed bin (35);
113 dcl fw_modules                          (16) char (8) parameter;
114 dcl fw_module_count                     fixed bin parameter;
115 dcl fw_module_num                       fixed bin;          /* loop counter */
116 dcl mpc_chanid                          char (8) aligned parameter;
117                                                             /* iom/channel */
118 dcl mpc_name                            char (4) aligned parameter;
119                                                             /* as in mspa */
120 dcl mpc_type_letter                     char (1);           /* code letter for mpc type, d t or u */
121 dcl overlay_name                        char (4);           /* firmware module type to overlay */
122 dcl p_mpc_cardp                         ptr parameter;
123 
124 /* find the mpc */
125 
126           mpc_cardp = null;
127           call config_$find_2 (MPC_CARD_WORD, mpc_name, mpc_cardp);
128           if mpc_cardp = null then go to mpc_error;
129           p_mpc_cardp = mpc_cardp;
130 
131           call io_chnl_util$iom_to_name ((mpc_card.port (1).iom), (mpc_card.port (1).chan), mpc_chanid, code);
132           if code ^= 0 then do;
133 mpc_error:
134                call com_err_ (0, me, "No such mpc ^a.", mpc_name);
135                return ("0"b);
136           end;
137 
138 /* find the firmware type */
139 
140           fw_module_count = 1;
141           if substr (mpc_name, 1, 3) = "msp" then mpc_type_letter = "d";
142           else if substr (mpc_name, 1, 3) = "mtp" then mpc_type_letter = "t";
143           else if substr (mpc_name, 1, 3) = "urp" then mpc_type_letter = "u";
144           else do;
145                call com_err_ (0, me, "Unrecognizable mpc type for mpc ^a", mpc_name);
146                return ("0"b);
147           end;
148           fw_modules (1) = mpc_type_letter || ltrim (character (mpc_card.model));
149           if mpc_type_letter ^= "u" then return ("1"b);     /* non urcs have just the main firmware */
150 
151 /* urc - we must find peripherals on it */
152 
153           fw_module_count = 1 + mpc_card.port (1).nchan;
154           do fw_module_num = 2 to fw_module_count;
155                fw_modules (fw_module_num) = "none";         /* for now */
156           end;
157 
158           prph_cardp = null;
159           call config_$find ("prph", prph_cardp);
160           do while (prph_cardp ^= null);
161                if (prph_card.iom = mpc_card.port (1).iom) &
162                     ((mpc_card.port (1).chan <= prph_card.chan)
163                     & (prph_card.chan < mpc_card.port (1).chan + mpc_card.port (1).nchan)) then do;
164                                                             /* prph on this mpc */
165                     if substr (prph_card.name, 1, 3) = "prt" then overlay_name = "pr4";
166                     else if substr (prph_card.name, 1, 3) = "rdr" then overlay_name = "crz";
167                     else if substr (prph_card.name, 1, 3) = "pun" then overlay_name = "cpz";
168                     else if substr (prph_card.name, 1, 3) = "ccu" then overlay_name = "crp";
169                     else overlay_name = "none";
170                     fw_module_num = prph_card.chan - mpc_card.port (1).chan + 2;
171                     if fw_modules (fw_module_num) ^= "ccu" then fw_modules (fw_module_num) = overlay_name;
172                                                             /* ccu over-rides crz crp */
173                end;
174                call config_$find ("prph", prph_cardp);
175           end;
176           return ("1"b);
177      end;
178 %page;
179 load_mpc:
180      proc (mpc_chanid, mpc_name, fw_modules, fw_module_count);
181 
182 dcl controller_fwid                     char (32) aligned;  /* name of firmware object */
183 dcl fw_module_count                     fixed bin parameter;
184 dcl fw_modules                          (16) char (8) parameter;
185 dcl fw_seg_lengths                      (16) fixed bin (18);/* argument to hc_load_mpc of firmware object lengths */
186 dcl fw_seg_num                          fixed bin;          /* loop counter */
187 dcl fw_seg_ptrs                         (16) ptr;           /* arg to hc_load_mpc */
188 dcl mpc_chanid                          char (8) aligned parameter;
189                                                             /* iom/channel */
190 dcl mpc_model                           fixed bin;          /* decimal mpc type */
191 dcl mpc_name                            char (4) aligned parameter;
192                                                             /* as in mspa */
193 dcl mpc_overlay                         char (8);           /* firmware code for overlay */
194 dcl mpc_type                            char (8);           /* model in ascii, with model and type letter code */
195 dcl mpc_type_index                      fixed bin;          /* loop counter */
196 dcl problem                             char (64);          /* load failure message */
197 dcl var_fw_seg_lengths                  (fw_module_count) fixed bin (18) based (addr (fw_seg_lengths));
198                                                             /* arrays so as to pass (*) dim to hc_load_mpc */
199 dcl var_fw_seg_ptrs                     (fw_module_count) ptr based (addr (fw_seg_ptrs));
200 
201 /* find the real firmware objects */
202 
203           do fw_seg_num = 1 to fw_module_count;
204                if fw_seg_num = 1 then do;                   /* main firmware */
205                     mpc_type = fw_modules (1);
206                     mpc_model = cv_dec_check_ (substr (mpc_type, 2), code);
207                     if code ^= 0 then go to bad_mpc;
208                     if substr (mpc_type, 1, 1) = "d" then do;
209                          do mpc_type_index = 1 to config_data_$mpc_msp_model_names.count
210                               while (mpc_model ^= config_data_$mpc_msp_model_names.names (mpc_type_index).model);
211                          end;
212                          if mpc_type_index > config_data_$mpc_msp_model_names.count then go to bad_mpc;
213                          controller_fwid = "fw." || config_data_$mpc_msp_model_names.names (mpc_type_index).fw_tag;
214                     end;
215                     else if substr (mpc_type, 1, 1) = "t" then do;
216                          do mpc_type_index = 1 to config_data_$mpc_mtp_model_names.count
217                               while (mpc_model ^= config_data_$mpc_mtp_model_names.names (mpc_type_index).model);
218                          end;
219                          if mpc_type_index > config_data_$mpc_mtp_model_names.count then go to bad_mpc;
220                          controller_fwid = "fw." || config_data_$mpc_mtp_model_names.names (mpc_type_index).fw_tag;
221                     end;
222                     else if substr (mpc_type, 1, 1) = "u" then do;
223                          do mpc_type_index = 1 to config_data_$mpc_urp_model_names.count
224                               while (mpc_model ^= config_data_$mpc_urp_model_names.names (mpc_type_index).model);
225                          end;
226                          if mpc_type_index > config_data_$mpc_urp_model_names.count then go to bad_mpc;
227                          controller_fwid = "fw." || config_data_$mpc_urp_model_names.names (mpc_type_index).fw_tag;
228                     end;
229                     else do;
230 bad_mpc:
231                          call com_err_ (0, me, "Unrecognizable mpc type ^a for mpc ^a", mpc_type, mpc_name);
232                          return;
233                     end;
234                end;
235                else do;                                     /* urc overlay */
236                     mpc_overlay = fw_modules (fw_seg_num);
237                     if mpc_overlay = "none" then
238                          controller_fwid = "none";
239                     else do;
240                          if mpc_overlay = "pr4" then controller_fwid = "fw.urcmpc.u400";
241                          else if mpc_overlay = "crp" | mpc_overlay = "crz" | mpc_overlay = "cpz" then
242                               controller_fwid = "fw.urcmpc.ucrp";
243                          else do;
244                               call com_err_ (0, me, "Unrecogniable overlay name ^a for mpc ^a", mpc_overlay, mpc_name);
245                               return;
246                          end;
247                     end;
248                end;
249 
250 /* name found, find object */
251 
252                if controller_fwid ^= "none" then do;
253                     fw_seg_ptrs (fw_seg_num) = slt_manager$get_seg_ptr (controller_fwid);
254                     if fw_seg_ptrs (fw_seg_num) = null then do;
255                          call com_err_ (0, me, "Firmware ^a not available for model ^a mpc.", controller_fwid, mpc_type);
256                          return;
257                     end;
258                     sltp = addr (slt$);
259                     sltep = addr (slt.seg (bin (baseno (fw_seg_ptrs (fw_seg_num)), 18)));
260                     fw_seg_lengths (fw_seg_num) = divide (slte_uns.bit_count, 36, 24, 0) - 1;
261                end;
262                else do;
263                     fw_seg_ptrs (fw_seg_num) = null;
264                     fw_seg_lengths (fw_seg_num) = 0;
265                end;
266           end;
267 
268 /* load it! */
269 
270           if fw_module_count = 1 then
271                call hc_load_mpc (mpc_chanid, fw_seg_ptrs (1), fw_seg_lengths (1), problem, code);
272           else call hc_load_mpc$urc (mpc_chanid, var_fw_seg_ptrs, var_fw_seg_lengths, problem, code);
273           if code ^= 0 then call com_err_ (code, me, "^a booting mpc ^a", problem, mpc_name);
274           return;
275      end;
276 %page;
277 validate_primary_channel:
278      proc (p_mpc_chanid, p_mpc_cardp) returns (bit (1));
279 
280 dcl channel                             fixed bin (8);
281 dcl code                                fixed bin (35);
282 dcl iom                                 fixed bin (3);
283 dcl mpc_chanid                          char (8) aligned;
284 dcl mpc_port_index                      fixed bin;
285 dcl p_mpc_chanid                        char (8) aligned parameter;
286 dcl p_mpc_cardp                         ptr parameter;
287 
288           mpc_chanid = p_mpc_chanid;
289           mpc_cardp = p_mpc_cardp;
290           iom = index ("ABCD", translate (substr (mpc_chanid, 1, 1), "ABCD", "abcd"));
291           channel = cv_dec_check_ (substr (mpc_chanid, 2), code);
292           if code ^= 0 then return ("0"b);
293           do mpc_port_index = 1 to dimension (mpc_card_array.port, 1);
294                if (mpc_card_array.port (mpc_port_index).iom = iom) &
295                     (mpc_card_array.port (mpc_port_index).chan = channel) then return ("1"b);
296           end;
297           return ("0"b);
298      end;
299 %page;
300 %include bce_subsystem_info_;
301 %page;
302 %include config_data_dcls;
303 %page;
304 %include config_mpc_card;
305 %page;
306 %include config_prph_card;
307 %page;
308 %include io_chnl_util_dcls;
309 %page;
310 %include slt;
311 %page;
312 %include slte;
313      end;
314