



		    ocd_.pl1                        11/11/89  1104.3r w 11/11/89  0803.9      159957



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1983 *
        *                                                         *
        * Copyright (c) 1972 by Massachusetts Institute of        *
        * Technology and Honeywell Information Systems, Inc.      *
        *                                                         *
        *********************************************************** */

/* format: style4,indattr,inddcls,dclind5,idind30,struclvlind5,ifthenstmt,ifthendo,^inditerdo,^indnoniterend,case,^tree,^indproc,^indend,^delnl,^insnl,comcol81,indcom,linecom,^indcomtxt */

ocd_:
     procedure;
	return;

	/*	Outer module of the operator's console DIM.
   *	Recoded by  Bill Silver  on 06/26/73
   *	This procedure now calls the ring 0 operator's console DCM  "ocdcm_"
   *	instead of calling syserr_real.
   *	Modified June 1976 by Larry Johnson to support alarm order.
   *         Rearranged as a native iox_ module by Benson I. Margulies April 1981.
   *	Modified 830620 for new ocdcm_ calls... -E. A. Ranzenbach
   *	Modified 841101 for printer_(off on) control orders... -E. A. Ranzenbach
*/


/****^  HISTORY COMMENTS:
  1) change(86-10-23,Fawcett), approve(86-10-23,MCR7517),
     audit(86-10-30,Beattie), install(86-11-03,MR12.0-1206):
     Changed to remove the word BOS from message.
                                                   END HISTORY COMMENTS */


	/*		PARAMETERS		*/

	declare  (
	         IOCB_ptr		         pointer,
	         Attach_args	         (*) character (*) varying,
	         Com_err_sw		         bit (1) aligned,
	         Code		         fixed bin (35),
	         Buffer_ptr		         pointer,
	         Buffer_length	         fixed bin (21),
	         N_chars_read	         fixed bin (21),
	         Old_modes		         character (*),
	         New_modes		         character (*),
	         Mode		         fixed bin,
	         Obsolete		         bit (1) aligned,
	         Control_order_name	         character (*),
	         Order_info_ptr	         pointer
	         )		         parameter;

	/*		AUTOMATIC  DATA		*/

	declare  mask		         bit (36) aligned;
	dcl  code			     fixed bin (35),		/* Error code. */
	     alen			     fixed bin (21),		/* Length of an ASCII string.  */
	     ilen			     fixed bin,			/* Length of a console input string in
						   *  ASCII or BCD characters. */
	     olen			     fixed bin (19);		/* Length of a console output string in WORDS. */
	dcl  io_uid		     fixed bin (71);		/* UID of a queued I/O... */
	dcl  console_flags		     bit (36);			/* console state flags... */

	dcl  01 console_read	     aligned like console_io;
	dcl  01 console_write	     aligned like console_io;

	dcl  01 EWI		     aligned like event_wait_info;

	/*	These flags are used to coordinate the conversion and writing of an output
   *	string.
*/
	dcl  cont_flag		     bit (1) aligned;		/* Used by "oc_trans_output_" to indicate a
						   *  continuation line.  The oc_write entry just
						   *  has to initialize it each time it is called.  */


	/*	This buffer contains a converted output string  or  an unconverted input
   *	string.
*/
	dcl  buffer		     char (256),
	     buf_ptr		     ptr;


	/*		BASED  DATA 		*/


	declare  attach_data_ptr	         pointer;

	declare  1 attach_data	         based (attach_data_ptr),
		    2 device	         character (32) unaligned,
		    2 attach_description     character (72) varying,
		    2 open_description       character (64) varying,
		    2 wait_list	         aligned like event_wait_channel,
		    2 line_leng	         fixed binary,
		    2 alarm_flag	         bit (1) aligned;		/* Set if alarm pending for next write */


	/*		EXTERNAL ENTRIES CALLED	*/
	dcl  hphcs_$ocdcm_queue_io	     entry (ptr, fixed bin (71));
	dcl  hphcs_$ocdcm_get_input	     entry (char (256), fixed bin (17), fixed bin (35));
	dcl  hphcs_$ocdcm_console_info
				     entry (char (4), bit (36), char (8), fixed bin (17), fixed bin (17),
				     fixed bin (35));
	dcl  hphcs_$ocdcm_printer_off
				     entry ();
	dcl  hphcs_$ocdcm_printer_on
				     entry ();
	dcl  timer_manager_$sleep	     entry (fixed bin (71), bit (2));
	dcl  ipc_$block		     entry (ptr, ptr, fixed bin (35));
	dcl  ipc_$create_ev_chn	     entry (fixed bin (71), fixed bin (35));
	dcl  ipc_$delete_ev_chn	     entry (fixed bin (71), fixed bin (35));
	dcl  oc_trans_output_	     entry (ptr, fixed bin (21), fixed bin (21), ptr, fixed bin (19), fixed bin (17),
				     bit (1) aligned);
	dcl  oc_trans_input_	     entry (ptr, fixed bin, fixed bin, ptr, fixed bin);
	declare  (
	         hcs_$set_ips_mask,
	         hcs_$reset_ips_mask
	         )		         entry (bit (36) aligned, bit (36) aligned);

	declare  (
	         error_table_$noarg,
	         error_table_$bad_mode,
	         error_table_$undefined_order_request,
	         error_table_$too_many_args,
	         error_table_$null_info_ptr,
	         error_table_$bad_arg
	         )		         fixed bin (35) ext static;


	dcl  (addr, addcharno, hbound, lbound, substr, unspec, multiply, null)
				     builtin;
	dcl  any_other		     condition;
%page;
%page;
%include iox_entries;
%page;
%include oc_data;
%page;
%include iox_modes;
%page;
%include iocb;
	declare  iocb_ptr		         pointer;
%page;
%include event_wait_info;
%page;
%include event_wait_channel;
%page;
%include oc_info;
%page;
%include sub_err_flags;

	declare  (to_write_ptr, to_read_ptr)
				         pointer;
	declare  to_write_length	         fixed bin (21);
	declare  to_read_length	         fixed bin;


ocd_attach:
     entry (IOCB_ptr, Attach_args, Com_err_sw, Code);


	/*	Entry to  ATTACH  Operator's Console. */

	Code = 0;
	iocb_ptr = IOCB_ptr;
	if hbound (Attach_args, 1) < 1
	then call attach_error (error_table_$noarg, "Usage: ocd_ DEVICE.");

	if hbound (Attach_args, 1) - lbound (Attach_args, 1) > 1
	then call attach_error (error_table_$too_many_args, "Usage: ocd_ DEVICE.");

	if Attach_args (1) ^= "otw_"
	then call attach_error (error_table_$bad_arg, "Only the BCE console, otw_, is supported.");


	/*	Set up event channel used to coordinate read and write operations with ocdcm_. */

	allocate attach_data set (attach_data_ptr);

	attach_data.wait_list.pad = ""b;

	attach_data.wait_list.n_channels = 1;

	call ipc_$create_ev_chn (attach_data.wait_list.channel_id (1), code);
	if code ^= 0
	then call attach_error (code, "Could not get an event channel.");

	attach_data.alarm_flag = "0"b;				/* No alarm pending.  */

	attach_data.attach_description = "ocd_ otw_";

	/*** okay, connect it up */

	on any_other go to RESET_IPS_MASK_1;

	call hcs_$set_ips_mask (""b, mask);
	iocb_ptr -> iocb.attach_data_ptr = attach_data_ptr;
	iocb_ptr -> iocb.attach_descrip_ptr = addr (attach_data.attach_description);
	iocb_ptr -> iocb.open = ocd_open;
	iocb_ptr -> iocb.detach_iocb = ocd_detach;

	call hphcs_$ocdcm_console_info ("", "0"b, "", 0, attach_data.line_leng, code);
	if code ^= 0 then do;					/* only update if info is good...	*/
	     call hcs_$reset_ips_mask (mask, mask);
	     call attach_error (code, "Could not get console info.");
	end;

	call iox_$propagate (iocb_ptr);
RESET_IPS_MASK_1:
	call hcs_$reset_ips_mask (mask, mask);

	return;

attach_error:
     procedure (code, reason);
	declare  code		         fixed bin (35);
	declare  reason		         character (*);
	declare  sub_err_		         entry () options (variable);
	declare  com_err_		         entry () options (variable);
	declare  ME		         character (32) init ("ocd_") internal static static options (constant);

	if Com_err_sw
	then call com_err_ (code, ME, "^a", reason);

	else call sub_err_ (code, "odc_ attach", ACTION_DEFAULT_RESTART, null (), (0), "^a", reason);
	Code = code;
	go to RETURN;
     end attach_error;

RETURN:
	return;

ocd_detach:
     entry (IOCB_ptr, Code);
	call setup;
	call ipc_$delete_ev_chn (attach_data.wait_list.channel_id (1), (0));
	IOCB_ptr -> iocb.attach_descrip_ptr = null ();
	call iox_$propagate (IOCB_ptr);
	free attach_data;

	return;

ocd_open:
     entry (IOCB_ptr, Mode, Obsolete, Code);
	call setup;

	if Mode ^= Stream_input & Mode ^= Stream_output & Mode ^= Stream_input_output
	then do;
	     Code = error_table_$bad_mode;
	     return;
	end;

	on any_other go to RESET_IPS_MASK_2;

	call hcs_$set_ips_mask (""b, mask);
	if Mode = Stream_input | Mode = Stream_input_output
	then do;
	     iocb_ptr -> iocb.get_chars = ocd_get_chars;
	     iocb_ptr -> iocb.get_line = ocd_get_line;
	end;
	if Mode = Stream_output | Mode = Stream_input_output
	then iocb_ptr -> iocb.put_chars = ocd_put_chars;
	iocb_ptr -> iocb.close = ocd_close;
	iocb_ptr -> iocb.modes = ocd_modes;
	iocb_ptr -> iocb.control = ocd_control;
	iocb_ptr -> iocb.open_descrip_ptr = addr (attach_data.open_description);
	attach_data.open_description = iox_modes (Mode);
	call iox_$propagate (iocb_ptr);
RESET_IPS_MASK_2:
	call hcs_$reset_ips_mask (mask, mask);
	return;

ocd_close:
     entry (IOCB_ptr, Code);

	call setup;

	on any_other go to RESET_IPS_MASK_3;

	call hcs_$set_ips_mask (""b, mask);
	iocb_ptr -> iocb.modes = iox_$err_not_open;
	iocb_ptr -> iocb.control = iox_$err_not_open;
	iocb_ptr -> iocb.detach_iocb = ocd_detach;
	iocb_ptr -> iocb.open = ocd_open;
	call iox_$propagate (iocb_ptr);
RESET_IPS_MASK_3:
	call hcs_$reset_ips_mask (mask, mask);
	return;

ocd_put_chars:
     entry (IOCB_ptr, Buffer_ptr, Buffer_length, Code);


	/*	This entry is called to write one string.  This string may be up to a segment
   *	long and consist of many lines.  Any lines that are too long to be printed on
   *	the operator's console will be broken up via continuation lines.
*/

	call setup;

	if Buffer_length <= 0
	then do;
	     attach_data.alarm_flag = "0"b;
	     return;
	end;

	/*	Now initialize the indexes needed for the workspace overlay and initialize the
   *	flags that control the write operation.
*/

	buf_ptr = addr (buffer);
	cont_flag = "0"b;

/**** This flag  (cont_flag) is used by  oc_trans_output_ to decide
      *  whether or not to add a continuation character ("\c")
      *  to the beginning of the line. */


	/*	The output message will be written line by line.  We must translate the caller's
   *	ASCII line into an output line acceptable to the operator's console.   The
   *	procedure which does this will break up the line if the translated output line
   *	is too long for the operator's console carriage.   It returns the number of ASCII
   *	characters that have been processed  and  the WORD size of the translated
   *	output string.
*/

	to_write_ptr = Buffer_ptr;
	to_write_length = Buffer_length;

	console_write.event_chan = 0;
	unspec (console_write.flags) = "0"b;
	console_write.console = "";
	console_write.sequence_no = 0;

	alen = 0;

	do while (to_write_length > 0);
	     call oc_trans_output_ (to_write_ptr, to_write_length, alen, buf_ptr, olen, attach_data.line_leng,
		cont_flag);
	     console_write.alert = attach_data.alarm_flag;		/* set by "alarm" control order...	*/
	     console_write.leng = olen;				/* setup the write as translated...	*/
	     console_write.text = substr (buffer, 1, multiply (olen, 4, 17));
	     io_uid = 0;
	     do while (io_uid = 0);
		call hphcs_$ocdcm_queue_io (addr (console_write), io_uid);
								/* queue the write...		*/
		if io_uid = 0
		then do;						/* write queue is full...		*/
		     call timer_manager_$sleep (3, "11"b);
								/* wait 3 seconds for room in the queue. */
		end;
	     end;
	     attach_data.alarm_flag = "0"b;
	     to_write_ptr = addcharno (to_write_ptr, (alen));
	     to_write_length = to_write_length - alen;
	end;

	/*	We know that this line has been written by ocdcm_.
   *	Now we must move the window on the caller's workspace - skipping the line
   *	that was just written.  We don't have to worry about continuation lines.
*/

	/*	We have finished processing all of the data in the user's workspace.  We will
   *	return status indicating that everything was completed OK.
*/

	return;


	/* Noone in the initializer calls get_chars, at least unless
   get_line returns long record. We could save up leftover input
   in the attach data for later return, but the old IOS dim
   got away without it, so we can presumably as well. Thus
   we assume that the callers buffer is always long enough
   (256 characters) and don't even try to return long_record. */

ocd_get_chars:
ocd_get_line:
     entry (IOCB_ptr, Buffer_ptr, Buffer_length, N_chars_read, Code);


	/*	This entry is called to read a line from the operator's console.  Note, when there
   *	is no input to read we will go blocked.  We will be waked up when the input string
   *	arrives.
*/

	call setup;
	N_chars_read = 0;
	to_read_ptr = Buffer_ptr;
	to_read_length = Buffer_length;

	if Buffer_length <= 0					/* Make sure caller really wants something. */
	then return;


	/*	Now initialize the indexes needed for the workspace overlay.  We need them so we
   *	can get a pointer to the area where the  ASCII input string will be placed.
*/
	buf_ptr = addr (buffer);


	/*	Now we will call into the ring 0 DIM to read.  If there is no input message then
   *	we will block ourselves.   ocdcm_ will wake us up when the input string arrives.
*/

	console_read.event_chan = attach_data.wait_list.channel_id (1);
	unspec (console_read.flags) = "0"b;
	console_read.sequence_no = 0;
	console_read.console = "";
	console_read.read = "1"b;
	console_read.leng = 0;
	console_read.text = "";

READ_LOOP:
	call hphcs_$ocdcm_queue_io (addr (console_read), io_uid);
								/* queue the I/O...			*/

	ilen = 0;

	do while (ilen = 0);
	     call BLOCK;						/* go blocked awaiting completion...	*/
	     if code ^= 0
	     then do;
		Code = code;
		return;
	     end;

	     /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
	     /*										*/
	     /* At this point ocdcm_ has sent a wakeup bring us out of the blocked state and informing us that	*/
	     /* the read has completed. We must now call down into ocdcm_ to retrieve the input from oc_data.	*/
	     /*										*/
	     /*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

	     call hphcs_$ocdcm_get_input (buffer, ilen, code);
								/* retrieve the input...		*/
	     if code ^= 0
	     then do;
		Code = code;
		return;
	     end;
	end;

	/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
	/*										*/
	/* Now we call oc_trans_input_ to translate the input string and do canonicalization.		*/
	/*										*/
	/*  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  *  */

	begin;
	     declare  fb_n_read		    fixed bin;
	     call oc_trans_input_ (to_read_ptr, to_read_length, fb_n_read, buf_ptr, ilen);
	     N_chars_read = fb_n_read;
	end;

	return;





ocd_control:
     entry (IOCB_ptr, Control_order_name, Order_info_ptr, Code);

	call setup;

	/*	This entry supports the following order calls:
   start
   alarm
   console_info
   update_attach_data
   printer_off
   printer_on

   The reset_read and reset_write orders are ignored but provided for
   compatibility.

   The error code error_table_$undefined_order_request is returned for all others.
*/

	if Control_order_name = "start"				/* simulated START actutally does nothing... */
	then do;
	     return;
	end;
	else if Control_order_name = "alarm"
	then do;
	     attach_data.alarm_flag = "1"b;
	     return;
	end;
	else if Control_order_name = "resetread"			/** **/
		| Control_order_name = "resetwrite"
	then do;
	     Code = 0;
	     return;
	end;

	else if Control_order_name = "console_info"
	then do;
	     if Order_info_ptr = null
	     then do;						/* got to provide a ptr...		*/
		code = error_table_$null_info_ptr;
		return;
	     end;
	     oc_info_ptr = Order_info_ptr;				/* overlay the order info structure...	*/
	     call hphcs_$ocdcm_console_info ((oc_info.name), console_flags, (oc_info.channel),
		(oc_info.device_idx), (oc_info.line_leng), code);
	     unspec (oc_info.flags) = unspec (console_flags);
	     return;
	end;

	if Control_order_name = "update_attach_data"
	then do;							/* called during reconfig...		*/
	     call hphcs_$ocdcm_console_info ("", "0"b, "", 0, attach_data.line_leng, code);
	     Code = code;
	     return;
	end;

	else if Control_order_name = "printer_off"
	then do;
	     allocate oc_info set (oc_info_ptr);
	     call hphcs_$ocdcm_console_info ("", console_flags, "", 0, attach_data.line_leng, code);
	     if code = 0
	     then do;						/* only update if info is good...	*/
		unspec (oc_info.flags) = unspec (console_flags);
		if ^oc_info.flags.read_unechoed_option then Code = error_table_$undefined_order_request;
		else call hphcs_$ocdcm_printer_off ();
	     end;
	     free oc_info;
	     return;
	end;
	else if Control_order_name = "printer_on"
	then do;
	     call hphcs_$ocdcm_printer_on ();
	     return;
	end;

	else Code = error_table_$undefined_order_request;
	return;

ocd_modes:
     entry (IOCB_ptr, Old_modes, New_modes, Code);			/* MODES are ignored...										*/
	Code = 0;
	return;



BLOCK:
     procedure;


	/*	This internal procedure is called when we must go blocked in order to
   *	wait for an I/O operation to complete.
*/

	call ipc_$block (addr (attach_data.wait_list), addr (EWI), code);

     end BLOCK;

setup:
     procedure;

	iocb_ptr = IOCB_ptr -> iocb.actual_iocb_ptr;
	attach_data_ptr = iocb_ptr -> iocb.attach_data_ptr;
	Code = 0;
     end setup;

     end ocd_;






		    bull_copyright_notice.txt       08/30/05  1008.4r   08/30/05  1007.3    00020025

                                          -----------------------------------------------------------


Historical Background

This edition of the Multics software materials and documentation is provided and donated
to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. 
as a contribution to computer science knowledge.  
This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology,
Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull
and Bull HN Information Systems Inc. to the development of this operating system. 
Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970),
renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership
of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for 
managing computer hardware properly and for executing programs. Many subsequent operating systems
incorporated Multics principles.
Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., 
as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. .

                                          -----------------------------------------------------------

Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without
fee is hereby granted,provided that the below copyright notice and historical background appear in all copies
and that both the copyright notice and historical background and this permission notice appear in supporting
documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining
to distribution of the programs without specific prior written permission.
    Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc.
    Copyright 2006 by Bull HN Information Systems Inc.
    Copyright 2006 by Bull SAS
    All Rights Reserved
