1 /****^  ******************************************************
  2         *                                                    *
  3         * Copyright (c) 1986 by Massachusetts Institute of   *
  4         * Technology and Honeywell Information Systems, Inc. *
  5         *                                                    *
  6         * Copyright (c) 1972 by Massachusetts Institute of   *
  7         * Technology and Honeywell Information Systems, Inc. *
  8         *                                                    *
  9         ****************************************************** */
 10 
 11 /****^  HISTORY COMMENTS:
 12   1) change(85-09-09,Farley), approve(85-09-09,MCR6979),
 13      audit(86-03-08,CLJones), install(86-07-18,MR12.0-1098):
 14      Support IMU.
 15   2) change(86-06-04,Hartogs), approve(86-06-04,MCR7383),
 16      audit(86-06-05,Coppola), install(86-07-18,MR12.0-1098):
 17      Changed to use version constant in rcp_printer_info.incl.pl1.
 18                                                    END HISTORY COMMENTS */
 19 /* format: style4 */
 20 /* PRTDIM_ATTACH - Attach/Detach module for the printer DIM.
 21    coded 10/30/74 by Noel I. Morris     */
 22 /* Modified: 27 November 1981 by G. Palter to clear new reload_vfc_train_when_ready flag */
 23 /* Modified September 1983 by E. N. Kittlitz for multi-record IDCWs */
 24 /* Modified October 1983 by E. N. Kittlitz for eurc/urmpc partitioning */
 25 /* Modified January 1985 by Paul Farley for UR-DAI&UR-PDSI IPCs to look like eurc. */
 26 
 27 prtdim_attach:                                              /* attach a printer */
 28      procedure (stream_name, prt, device, mode, iostatus, sdb_ptr);
 29 
 30 dcl  stream_name char (*);                                  /* name of IO stream */
 31 dcl  prt char (*);                                          /* name of DIM being attached */
 32 dcl  device char (*);                                       /* printer device name */
 33 dcl  mode char (*);                                         /* attachment mode */
 34 dcl  iostatus bit (72) aligned;                             /* IOS status */
 35 dcl  i fixed bin;
 36 dcl  area_ptr ptr;                                          /* pointer to system free area */
 37 dcl  listen_based_area area ((16374)) based (area_ptr);     /* area in which to allocate sdb */
 38 dcl  wksp_max fixed bin (19);                               /* max size of IOI workspace buffer */
 39 dcl  time_max fixed bin (52);                               /* max time for IOI connect to complete */
 40 dcl  rcp_state fixed bin;                                   /* state variable from check_attach */
 41 dcl  rcode fixed bin (35);                                  /* error code */
 42 dcl  char_cnt fixed bin (18);
 43 
 44 dcl  1 ipc_message aligned like event_call_info;
 45 dcl  1 rcp_info like printer_info aligned auto;             /* automatic copy of RCP info structure */
 46 
 47 dcl  CR char (1) init ("^M") int static options (constant);
 48 
 49 dcl  get_system_free_area_ entry (ptr);
 50 dcl  ipc_$create_ev_chn entry (fixed bin (71), fixed bin (35));
 51 dcl  ipc_$block entry (ptr, ptr, fixed bin (35));
 52 dcl  ipc_$delete_ev_chn entry (fixed bin (71), fixed bin (35));
 53 dcl  convert_ipc_code_ entry (fixed bin (35));
 54 dcl  rcp_$attach entry (char (*), ptr, fixed bin (71), char (*), bit (36) aligned, fixed bin (35));
 55 dcl  rcp_$check_attach entry (bit (36) aligned, ptr, char (*), fixed bin, fixed bin (19), fixed bin (52),
 56           fixed bin, fixed bin (35));
 57 dcl  init_printer_$reset entry (ptr);
 58 dcl  ioi_$set_status entry (fixed bin, fixed bin (18), fixed bin (8), fixed bin (35));
 59 dcl  ioi_$workspace entry (fixed bin, ptr, fixed bin (18), fixed bin (35));
 60 dcl  rcp_$detach entry (bit (36) aligned, bit (*), fixed bin, char (*), fixed bin (35));
 61 dcl  prt_conv_ entry (ptr, fixed bin (18), ptr, fixed bin (18), ptr);
 62 dcl  prtdim_util$init entry (ptr, fixed bin (35));
 63 dcl  prtdim_eurc_util$init entry (ptr, fixed bin (35));
 64 dcl  prtdim_eurc_util$initialize_workspace entry (ptr);
 65 dcl  prtdim_util$load_vfc entry (ptr, fixed bin (35));
 66 dcl  prtdim_eurc_util$load_vfc entry (ptr, fixed bin (35));
 67 dcl  timer_manager_$reset_alarm_wakeup entry (fixed bin (71));
 68 dcl  config_$find entry (char (4) aligned, ptr);
 69 dcl  config_$find_periph entry (char (4) aligned, ptr);
 70 
 71 dcl  error_table_$bigarg fixed bin (35) ext static;
 72 dcl  error_table_$ionmat fixed bin (35) ext;
 73 dcl  error_table_$no_room_for_dsb fixed bin (35) ext;
 74 dcl  error_table_$no_operation fixed bin (35) ext;
 75 dcl  config_deck$ ext;
 76 
 77 dcl  (addr, addrel, null, ptr, rel, substr, unspec) builtin;
 78 %page;
 79 
 80           iostatus = "0"b;                                  /* Clear returned status. */
 81           if sdb_ptr ^= null () then do;                    /* Check for multiple attachments */
 82                substr (iostatus, 1, 36) = unspec (error_table_$ionmat); /* If multiple attachment return code */
 83                go to exit;
 84           end;                                              /* End sdb_ptr not null do group */
 85 
 86           call get_system_free_area_ (area_ptr);            /* Get ptr to area in listen_ before alloc */
 87           allocate sdb in (listen_based_area) set (sdb_ptr);/* Create stream data block */
 88           if sdb_ptr = null then do;                        /* If this - then no room for sdb */
 89                substr (iostatus, 1, 36) = unspec (error_table_$no_room_for_dsb); /* Send message */
 90                go to exit;                                  /* Exit */
 91           end;                                              /* End sdb_ptr null do group */
 92 
 93           sdb.areap = area_ptr;                             /* Save pointer to free area. */
 94 
 95           outer_module_name = prt;                          /* Put name this outer module in sdb */
 96           device_name_list_ptr = addr (sdb.device_name);    /* Set pointer */
 97           next_device_ptr = null;                           /* Only one device allowed */
 98           name_size = 32;                                   /* Set name size */
 99           sdb.name = device;                                /* Put attached device name in sdb */
100           sdb.stream_name = stream_name;                    /* record the name of this attachment */
101 
102           call ipc_$create_ev_chn (sdb.evchan, rcode);      /* Create event channel so that the supervisor
103                                                                knows who to wake when we are blocked */
104           if rcode ^= 0 then do;
105                call convert_ipc_code_ (rcode);
106                go to free1;
107           end;
108           ev_list.count = 1;                                /* Set count in event list. */
109 
110           pip = addr (sdb.info);                            /* Get pointer to printer info. */
111           prt_info.devname = substr (sdb.name, 1, 4);       /* Set device name in structure. */
112 
113           printer_info_ptr = addr (rcp_info);               /* Get pointer to RCP info for printer. */
114           rcp_info.version_num = PRINTER_INFO_VERSION_1;                        /* Set up the RCP info structure. */
115           rcp_info.usage_time = 0;                          /* Don't know how long we'll use printer. */
116           rcp_info.wait_time = 0;                           /* We are not willing to wait. */
117           rcp_info.system_flag = "0"b;                      /* Not system process. */
118           rcp_info.device_name = substr (sdb.name, 1, 8);   /* Set device name. */
119 
120           call rcp_$attach ("printer", printer_info_ptr, sdb.evchan, "", rcp_id, rcode);
121           if rcode ^= 0 then go to free;                    /* Attempt to attach the printer. */
122 
123 check:    call rcp_$check_attach (rcp_id, printer_info_ptr, "", prt_info.devx, wksp_max, time_max,
124                rcp_state, rcode);                           /* Check on progress of attachment. */
125           if rcode ^= 0 then go to free;
126 
127           go to attach_state (rcp_state);                   /* Dispatch on state variable. */
128 
129 attach_state (1):                                           /* Short wait needed */
130           call ipc_$block (addr (sdb.ev_list), addr (ipc_message), rcode);
131           if rcode ^= 0 then do;                            /* Wait for attachment to complete. */
132                call convert_ipc_code_ (rcode);
133                go to free;
134           end;
135           go to check;                                      /* Perform check again. */
136 
137 attach_state (2):                                           /* long wait */
138 attach_state (3):                                           /* error occurrence */
139           go to free;                                       /* This is an error condition. */
140 
141 attach_state (0):                                           /* Successful attachment */
142           prt_info.model = rcp_info.model;                  /* Extract info from RCP info structure. */
143           prt_info.train = rcp_info.print_train;
144           prt_info.line_length = rcp_info.line_length;
145 
146           call set_mpc_type;
147           if ^sdb.flags.eurc then wksp_max = 1024;          /* old URMPC dim */
148           else wksp_max = min (2048, wksp_max);             /* biggest we'll ever want */
149           sdb.data_end = wksp_max;                          /* first approximation of circular dataspace end */
150           call ioi_$workspace (prt_info.devx, sdb.wsegp, (wksp_max), rcode); /* To wire down space for DCW list */
151           if rcode ^= 0 then go to free;                    /* Check error code */
152 
153           if sdb.flags.eurc then do;                        /* fancy dim, more initializing */
154                sdb.max_dcw_size = 65;                       /* should calculate what prt_conv_ would do */
155                if wksp_max < 2048 then sdb.max_dcws, sdb.n_dcws = 32; /* about 2 seconds/buffer at 1000LPM */
156                else sdb.max_dcws, sdb.n_dcws = 62;          /* 1 less than idcw max */
157                sdb.max_buffers, sdb.n_buffers = 3;
158                prt_bufferp = addr (prt_buffers (0));
159                sdb.data_end = sdb.data_end - size (null () -> istat);
160                call ioi_$set_status (prt_info.devx, (sdb.data_end), 1, rcode);
161                if rcode ^= 0 then go to free;
162                sdb.status_ptr = ptr (wsegp, sdb.data_end);
163                sdb.data_end = sdb.data_end - 1;             /* keep one word for prtdim_eurc_util$finish_abort */
164                sdb.data_begin, sdb.bgin, sdb.stop = size (prt_buffers);
165                sdb.b_begin, sdb.b_stop = 0;
166                call prtdim_eurc_util$init (sdb_ptr, rcode); /* Initialize printer information. */
167                if rcode ^= 0 then go to free;               /* If unable to initialize printer ... */
168                pcip = addr (sdb.conv_info);
169                call prt_conv_ (addr (CR), 1, wsegp, char_cnt, pcip); /* for prtdim_eurc_util$finish_abort */
170                if char_cnt > 4 then do;                     /* we only have 1 word to spare for this */
171                     rcode = error_table_$bigarg;
172                     go to free;
173                end;
174                sdb.null_line_data = wseg (0);               /* remember it, always */
175                dcwp = addr (sdb.null_line_dcw);             /* make the 'null' dcw */
176                string (dcw) = ""b;
177                dcw.address = bit (sdb.data_end);            /* 1 word between end of data and ioi status area */
178                dcw.tally = bit (bin (1, 12), 12);           /* 1 word, that is to say 1 */
179                call init_printer_$reset (pcip);             /* clear any line/page count caused by above */
180                if mode ^= "save_vfc" then do;
181                     call prtdim_eurc_util$load_vfc (sdb_ptr, rcode);
182                     if rcode = error_table_$no_operation then rcode = 0;
183                     else if rcode ^= 0 then go to free;     /* load error */
184                end;
185           end;                                              /* EURC */
186           else do;
187                sdb.data_begin, sdb.bgin, sdb.stop = 0;
188                call prtdim_util$init (sdb_ptr, rcode);      /* Initialize printer information. */
189                if rcode ^= 0 then go to free;               /* If unable to initialize printer ... */
190                if mode ^= "save_vfc" then do;               /* are we to load a vfc now? */
191                     call prtdim_util$load_vfc (sdb_ptr, rcode); /* data is in  sdb.conv_info */
192                     if rcode = error_table_$no_operation then rcode = 0;
193                     else if rcode ^= 0 then go to free;     /* load error */
194                end;
195           end;
196 
197           idcwp = addr (prt_info.print_idcw);               /* Get pointer to IDCW for printing. */
198           if sdb.flags.eurc then idcw.control = "00"b;      /* no continue or marker in IDCW. */
199           else idcw.control = "10"b;                        /* continue */
200 
201           sdb.prev = 0;                                     /* Initialize DCW list pointers. */
202           sdb.wait_flag = "0"b;                             /* Reset waiting for special flag. */
203           sdb.running = "0"b;                               /* Indicate channel not running. */
204           sdb.marker_count = 0;                             /* Clear the marker status counter. */
205           sdb.paper_low = "0"b;                             /* Reset paper low flag. */
206           sdb.error_count = 0;                              /* Clear the error counter. */
207           sdb.reload_vfc_train_after_special = "0"b;        /* Reset request to reload VFC/train after a special */
208           sdb.chars_printed = 0;
209           sdb.aborting = "0"b;
210           sdb.version = 1;
211 
212           if sdb.flags.eurc then
213                call prtdim_eurc_util$initialize_workspace (sdb_ptr); /* setup buffer headers, etc. */
214 
215           return;                                           /* All finished. */
216 
217 %page;
218 
219 free:
220 free1:    substr (iostatus, 1, 36) = unspec (rcode);        /* Return error code. */
221 
222           go to detach;                                     /* try to clean up, but retain this error code */
223                                                             /* Drop into normal detach code. */
224 
225 
226 prtdim_detach: entry (sdb_ptr, device, mode, iostatus);     /* Detach entry point */
227 
228           iostatus = "0"b;                                  /* clear the status code */
229 
230 detach:   call timer_manager_$reset_alarm_wakeup (sdb.evchan);
231           call ipc_$delete_ev_chn (sdb.evchan, rcode);      /* Delete event channel */
232           if rcode ^= 0 then if substr (iostatus, 1, 36) = "0"b then do;
233                     call convert_ipc_code_ (rcode);
234                     substr (iostatus, 1, 36) = unspec (rcode);
235                end;
236 
237           pip = addr (sdb.info);                            /* Get pointer to info structure. */
238 
239           call rcp_$detach (rcp_id, "0"b, error_count, "", rcode);
240           if rcode ^= 0 then                                /* Attempt to detach the device. */
241                if substr (iostatus, 1, 36) = "0"b then      /* report error if none exists */
242                     substr (iostatus, 1, 36) = unspec (rcode); /* Put error code in return status */
243 
244           area_ptr = sdb.areap;                             /* Get pointer to area. */
245           free sdb in (listen_based_area);                  /* Free-up allocated sdb */
246 
247 exit:     substr (iostatus, 52, 1) = "1"b;                  /* Set ioname detached bit */
248           substr (iostatus, 41, 1) = "1"b;                  /* Set transaction terminated bit */
249           return;
250 
251 %page;
252 /* determine the type of MPC through which we are talking.  */
253 
254 set_mpc_type: proc;
255 
256           call config_$find_periph (substr (sdb.name, 1, 4), prph_prt_cardp);
257           if prph_prt_cardp = null then return;             /* oh, well */
258           mpc_cardp = null;
259           do while ("1"b);
260                call config_$find ("mpc", mpc_cardp);        /* next MPC card */
261                if mpc_cardp = null then do;
262 
263 /* If no MPC card found for this device, assume that it is connected to
264    a IPC controller, that works like the EURC. */
265 
266                     sdb.flags.eurc = "1"b;
267                     return;
268                end;
269                if mpc_card.port (1).iom = prph_prt_card.iom & /* an eurc only has one port... */
270                     mpc_card.port (1).chan <= prph_prt_card.chan &
271                     prph_prt_card.chan < mpc_card.port (1).chan + mpc_card.port (1).nchan then do;
272                     do i = 1 to hbound (eurc_model_numbers, 1);
273                          if mpc_card.model = eurc_model_numbers (i) then do;
274                               sdb.flags.eurc = "1"b;
275                               return;
276                          end;                               /* it's an eurc */
277                     end;                                    /* checking model number */
278                     return;
279                end;                                         /* channel belongs to this MPC */
280           end;                                              /* while "1"b */
281 
282      end set_mpc_type;
283 
284 /* format: off */
285 %page; %include config_mpc_card;
286 %page; %include config_prph_prt_card;
287 %page; %include eurc_model_numbers;
288 %page; %include event_call_info;
289 %page; %include ioi_stat;
290 %page; %include iom_dcw;
291 %page; %include iom_pcw;
292 %page; %include prt_sdb;
293 %page; %include prt_info;
294 %page; %include prt_conv_info;
295 %page; %include rcp_printer_info;
296 
297      end prtdim_attach;