



		    io_manager.alm                  11/11/89  1140.6r   11/11/89  0802.6       14319



" ***********************************************************
" *                                                         *
" * Copyright, (C) Honeywell Bull Inc., 1987                *
" *                                                         *
" * Copyright, (C) Honeywell Information Systems Inc., 1982 *
" *                                                         *
" * Copyright (c) 1972 by Massachusetts Institute of        *
" * Technology and Honeywell Information Systems, Inc.      *
" *                                                         *
" ***********************************************************
	name	io_manager

" Transfer vector for unwired I/O routines.
" Written January 1981 by C. Hornig
" Modified November 1981 by C. Hornig for MR10 interface changes.
" Modified January 1984 by Chris Jones for channel reconfiguration
" Modified March 1985 by Keith Loepere to remove unncessary getlp's (by virtue of binding).

	macro	tv
	segdef	&1
&1:	tra	&2
	&end


	tv	assign,iom_assign$iom_assign
	tv	assign_add,iom_assign$add_channel
	tv	unassign,iom_unassign$iom_unassign
	tv	unassign_delete,iom_unassign$delete_channel
	tv	connect,iom_connect$connect
	tv	connect_abs,iom_connect$connect_abs
	tv	connect_direct,iom_connect$connect_direct
	tv	mask,iom_connect$mask
	tv	data_tdcw,iom_connect$data_tdcw
	tv	workspace_tdcw,iom_connect$workspace_tdcw
	tv	get_status,iom_connect$get_status
"	tv	set_status_queue,iom_set_status_queue$iom_set_status_queue
	tv	reset,iom_reset$iom_reset
"	tv	run,iom_interrupt$run

	segdef	ignore_interrupt
ignore_interrupt:
	short_return

	end




		    iom_assign.pl1                  11/11/89  1140.6r w 11/11/89  0802.6       34101



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


/* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
iom_assign:
     procedure (Chx, Channel, Handler, Index, Statusp, Code);

/* iom_assign: Assign an IOM chanel. */
/* Taken from iom_manager November 1980 by C. Hornig */
/* Modified for channel reconfiguration January 1984 by Chris Jones */

dcl	(
	Chx		   fixed bin (35),
	Channel		   char (8) aligned,
	Index		   fixed bin (35),
	Handler		   entry,
	Statusp		   ptr,
	Code		   fixed bin (35)
	)		   parameter;

dcl	error_table_$bad_arg   fixed bin (35) ext static;
dcl	error_table_$io_no_permission
			   fixed bin (35) ext static;
dcl	error_table_$io_not_configured
			   fixed bin (35) ext static;
dcl	error_table_$noalloc   fixed bin (35) ext static;

dcl	add_entry		   bit (1) aligned;
dcl	chx		   fixed bin (35);
dcl	iom		   fixed bin (3);
dcl	channel		   fixed bin (7);
dcl	handler		   entry variable;
dcl	index		   fixed bin (35);

dcl	(addr, binary, bit, hbound, lbound, null, stac, substr)
			   builtin;

	add_entry = "0"b;
	goto common;

add_channel:
     entry (Chx, Channel, Handler, Index, Statusp, Code);

	add_entry = "1"b;
common:
	Chx, Code = 0;
	Statusp = null ();
	handler = Handler;
	index = Index;
	iom_data_ptr = addr (iom_data$);

	call io_chnl_util$name_to_iom (Channel, iom, channel, Code);
	if Code ^= 0 then
	     return;

/* validate IOM/channel */

	if (iom < lbound (iom_data.per_iom, 1)) | (iom > hbound (iom_data.per_iom, 1))
	     | (channel < lbound (iom_data.per_iom.chantab, 2)) | (channel > hbound (iom_data.per_iom.chantab, 2))
	then do;
	     Code = error_table_$bad_arg;
	     return;
	end;

	if ^iom_data.per_iom (iom).flags.on_line then
	     goto bad_dev;

	chx = iom_data.per_iom (iom).chantab (channel);

	if chx = 0 then do;				/* must assign new chx */
	     do chx = lbound (iom_data.per_device, 1) to hbound (iom_data.per_device, 1)
		while (^stac (addr (iom_data.per_device (chx).iom), bit (binary (iom, 36))));
	     end;
	     if chx > hbound (iom_data.per_device, 1) then do;
		Code = error_table_$noalloc;
		return;
	     end;

	     iom_data.per_iom (iom).chantab (channel) = chx;
						/* make the assignment */

	     iom_data.per_device (chx).iom = iom;
	     iom_data.per_device (chx).channel = channel;
	     iom_data.per_device (chx).on_line = "1"b;
	end;

	if iom_data.per_device (chx).flags.in_use then do;
	     Code = error_table_$io_no_permission;
	     return;
	end;

	if add_entry then
	     iom_data.per_device (chx).on_line = "1"b;
	else if ^iom_data.per_device (chx).on_line then do;
bad_dev:
	     Code = error_table_$io_not_configured;
	     return;
	end;

	iom_data.per_device (chx).handler = handler;
	iom_data.per_device (chx).index = index;
	iom_data.per_device (chx).pcw, iom_data.per_device (chx).lpw, iom_data.per_device (chx).status,
	     iom_data.per_device (chx).ext_status = ""b;
	substr (iom_data.per_device (chx).pcw, 40, 6) = bit (binary (channel, 6));
	iom_data.per_device (chx).flags.in_use = "1"b;

	Chx = chx;
	Statusp = addr (iom_data.per_device (chx).status);

	return;

%include iom_data;
%page;
%include io_chnl_util_dcls;

     end iom_assign;




		    iom_connect.alm                 11/11/89  1140.6rew 11/11/89  0800.0      195714



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

" HISTORY COMMENTS:
"  1) change(85-06-24,Farley), approve(85-08-30,MCR7299),
"     audit(85-08-30,CLJones), install(85-08-30,MR12.0-1001):
"     Changed
"      connect_abs to check for a special pcw that will tell it
"      to set the PGE & ^PTP in the second word of the PCW. This will cause
"      a system-fault if the channel trys to do a data-transfer. The default
"      pcw will be used for the first word of the of the PCW.
"  2) change(85-10-08,Farley), approve(85-10-08,MCR6979),
"     audit(85-12-02,CLJones), install(86-03-21,MR12.0-1033):
"     Add support for
"      IMU.
"  3) change(87-02-26,Farley), approve(87-04-15,MCR7661),
"     audit(87-04-21,Fawcett), install(87-04-28,MR12.1-1028):
"     Relocated the setting of iom_data.imw_lock and the checking of
"     iom_data.n_intr_procs prior to the setting of the iom_data.per_iom.lock
"     in the connect_and_identify entry.  This was done to correct a deadly
"     embrace that was occuring on these locks.
"  4) change(88-05-18,Farley), approve(88-06-30,MCR7912),
"     audit(88-06-30,Beattie), install(88-07-15,MR12.2-1057):
"     Added clearing of second per_device.status word at connect time.
"     Depending on the type of I/O, the word will either be overwritten at
"     status time or not set at all.  This will guarantee a "known" setting.
"                                                      END HISTORY COMMENTS


" iom_connect.alm:  Routines to perform connects to IOM.
" Taken from iom_manager November 1980 by C. Hornig
" Modified by C. Hornig for paged IOM November 1980
" Modified November 1981 by C. Hornig for MR10 interface changes.
" Modified May 1982 by C. Hornig for idcw.ext_ctl write-around.
" Modified 07/19/82 by Chris Jones to fix DCW address residue reporting
"	(in expand_status) when on non-paged IOMs
" Modified 1984-07-27 BIM to set REL bit for paged direct channel connects.
"	and to reliably mask the right channel.
" Modified August 1984 by Chris Jones to decommit support for non-paged IOMs
" Modified November 1984 by M. Pandolf to add connect_and_identify
" Modified January 1985 by M. Pandolf to add IMW polling protocol
" Modified March 1985 by Chris Jones to forgo heroic measures when a connect
"	is lost
" Modified MAY 1985 by R. A. Fawcett to clear detail status
" Modified Sept 1985 by Paul Farley to fix connect_and_identify for IMUs.
" Modified Oct 1985 by Paul Farley to give IMUs extra time to answer connects.

	name	iom_connect

	entry	connect
	entry	connect_abs
	entry	connect_direct
	entry	connect_and_identify
	entry	mask
	entry	get_status
	entry	data_tdcw
	entry	workspace_tdcw

" Index register conventions:

"	X0 - internal subroutine calls.
"	X1 - index into per_device
"	X2 - index into channel_mailbox
"	X3 - index into per_iom
"	X7 - temporary data

" Pointer Register Conventions:

"	AP -> argument list
"	AB address temporary
"	BP -> <iom_data>|0
"	BB -> mailbox for this IOM.
"	LB -> io_manager_arg
"	SB -> iom_data.per_device for this device

" Macros for coding ease

	macro	loca		" Load One's Compliment into A
	lca	1,dl
	era	&F1
	&end

	macro	locq		" Load One's Compliment into Q
	lcq	1,dl
	erq	&F1
	&end

common_pcw:
	oct	400000720201	" read status and continue
direct_pcw:
	oct	000000700000	" for direct channels
mask_pcw:
	oct	000000740000	" mask and reset channel
rss_idcw:
	oct	400000700201	" for checking only
ptp_mask:
	oct	777777777377	" for masking out PTP flag
" 
"  call iom_connect$connect_abs (io_manager_arg);

" This entry is called each time the channel is started.

connect_abs:
	tsx0	setup
	tsx0	setup_pt

	ldq	lb|io_manager_arg.pcw
				" get user's PCW
	tze	load_common	" none given, use default
	cmpq	=o777777,dl	" check for special type
	tnz	save_pcw		" not special type, must be pcw

	eppab	lb|io_manager_arg.listp,*
	ldq	ab|0		" is idcw a reset-status type
	cmpq	rss_idcw
	tnz	load_common	" not reset-status

	ldq	sb|per_device.pcw+1
	anq	ptp_mask		" turn off PTP flag
	orq	=o200,dl		" turn on PGE flag
	stq	sb|per_device.pcw+1

load_common:
	ldq	common_pcw	" default PCW
save_pcw:
	stq	sb|per_device.pcw

	ldx7	lb|io_manager_arg.listp
				" check for null DCW list
	cmpx7	=o77777,du
	tze	connect_join	" no list
	absa	lb|io_manager_arg.listp,*
				" get address of DCW list
	arl	12		" stash it away
	stca	sb|per_device.pcw,10" high bits in PCW
	als	18
	sta	sb|per_device.lpw	" low bits in LPW
	tra	connect_join


"  call iom_connect$connect (io_manager_arg);

" This entry is called to start the channel in paged mode.

connect:
	tsx0	setup
	tsx0	setup_pt

	ldq	lb|io_manager_arg.pcw
				" get user's PCW
	tnz	2,ic
	ldq	common_pcw	" default PCW
	stq	sb|per_device.pcw

	lda	=o110000,dl	" get AE and REL bits in LPW
	sta	sb|per_device.lpw

	lxl7	lb|io_manager_arg.listx
	stx7	sb|per_device.lpw
	tra	connect_join


"  call iom_connect$connect_direct (io_manager_arg);

" This entry is used to connect to a direct channel.

connect_direct:
	tsx0	setup
	tsx0	setup_pt

	lda	direct_pcw
	sta	sb|per_device.pcw
	ldx7	lb|io_manager_arg.ptp
	cmpx7     =o777777,du		paged connect?
	tnz	connect_join		nope
	lda	=o100000,dl		get the AE bit
	orsa	sb|per_device.lpw		and turn it on.
	tra	connect_join


"  call iom_connect$mask (chx);

" This entry is used to mask a channel.

mask:
	tsx0	setup

	lda	mask_pcw		" mask the channel
	sta	sb|per_device.pcw
	lda	sb|per_device.channel
	als	27
          sta	sb|per_device.pcw+1 " there might be crap from previous
				" connects.

connect_join:
	ldx7	=o377777,du	" mark the status word
	stx7	sb|per_device.status" fill in channel mailbox
	stz	sb|per_device.status+1 " clear second status word
	mlr	(),(pr),fill(0)	" clear the extended status
	desc9a	0,0
	desc9a	sb|per_device.ext_status,4*8
	ldaq	sb|per_device.lpw
	staq	bb|channel_mailbox.lpw,x2
	lda	sb|per_device.scw
	sta	bb|channel_mailbox.scw,x2

" Now lock the connect channel mailbox.

	tsx0	lock_and_clear_mbx

	inhibit	on		" <+><+><+><+><+><+><+><+><+><+><+><+>

	ldq	bp|iom_data.per_iom+per_iom.connect_lpw,x3
	stq	bb|connect.lpw	" set up connect LPW
	ldaq	sb|per_device.pcw	" move PCW
	staq	bb|connect.pcw	" Store in correct place.
	cioc	bp|iom_data.per_iom+per_iom.cow,x3
				" DO IT!
	ldq	pds$process_id	" unlock the lock
	lda	0,du
	stacq	bp|iom_data.per_iom+per_iom.lock,x3
	inhibit	off		" <-><-><-><-><-><-><-><-><-><->

	rccl	sys_info$clock_,*	" stash time away
	staq	bp|iom_data.per_iom+per_iom.connect_time,x3
	staq	sb|per_device.connect_time

	ldaq	sb|per_device.connects
	adl	=1,dl
	staq	sb|per_device.connects

	epbpsb	sp|0		" restore stack base ptr
	short_return
" 

" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
"	connect_and_identify
"
"	call iom_connect$connect_and_identify (iom_number, code)
"
"
"	connect_and_identify is used to determine if an iom is who
"	its switches says it is.  it first locks all IOMs and waits
"	for their connects to clear.  it then stores an invalid (zero)
"	LPW in the connect mailbox and connects the IOM requested by
"	its only parameter.  after connecting, it loops checking
"	the sys_fault mailboxes for all the IOMs seeing which one
"	posts the fault.  it returns the number of the IOM mailbox
"	which contains the fault status.  note that only one IOM is
"	to be connected, and the status ought to appear in its mailbox.
"	if the status appears in another mailbox, this indicates to
"	the caller that the IOM has at least its mailbox switches set
"	incorrectly.  if we can't find any trace of connect action, we
"	return 0 as the iom number, wishing the caller luck, because
"	*somewhere* in memory are several stray bits...
"
"	In a multiprocessor system, a race condition can occur where
"	one of the other CPUs has received an interrupt and begins
"	processing it just as we store the invalid LPW.  There is a
"	good chance that it will swipe the system fault interrupt bit
"	from us, causing us to think the IOMs aren't responding and
"	thereby crash the system.  To prevent this, a lock has been
"	added in iom_data to delay IMW reading at interrupt time.
"	Named iom_data$imw_lock, it may be found in one of three states
"	at any given time, with 1 meaning OK to read IMW, -1 meaning
"	don't begin reading an IMW, and 0 meaning lock in transition.
"	This program alone can change the value of imw_lock to -1 or 1.
"	The other program to reference the lock, iom_interrupt, can only
"	set it to zero as it checks its value, and set it back to the
"	original value.  While holding the lock to 0, iom_interrupt can
"	increment iom_data$n_intr_procs to indicate that its agent
"	(a CPU) is running is processing an IMW.
"	As long as n_intr_procs is non-zero, connect_and_identify will
"	not proceed with the connect.  Given that iom_connect first sets
"	iom_data$imw_lock to -1 (stay out, everyone) and then loops
"	on n_intr_procs, and that processing an IMW by the other CPUs
"	will take a finite time, we are guarenteed to be able to set the
"	LPW without interference from other processors in the foreseeable
"	future.
"
"
"	Register usage is somewhat different than for the other entries:
"
"	X0 - internal subroutine call return ptr
"	X3 - index into per_iom
"	X4 - index into system_fault_status circular buffer
"	X5 - timeout loop counter
"	X6 - iom_number for various loops
"	X7 - number that IOM thinks it is
"
"	AP -> argument list
"	BP -> <iom_data>|0
"	BB -> various places in <iom_mailbox>
"	LB -> iom_number in argument list
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "

connect_and_identify:
	eppbp	iom_data$		" do our own setup here
	epplb	ap|2,*		" lb -> iom_number
	stz	ap|4,*		" initialize return code
	lxl7	lb|0		" initialize IOM identity

	lda	1,dl		" lower limit of iom_number
	ldq	4,dl		" upper limit of iom_number
	cwl	lb|0		" is arg within limits?
	tnz	inv_iom_range

	odd
	ldac	bp|iom_data.imw_lock
	tze	-1,ic		" loop while lock is in transition
	tmi	imw_already_locked	" we are supposed to be the only ones here!
	neg			" lock was 1, store -1
	sta	bp|iom_data.imw_lock
	odd
	lda	bp|iom_data.n_intr_procs
	tnz	-1,ic		" loop until all CPUs out of handler

	ldx6	4,du		" do iom_number = 4 to 1 by -1
lock_an_iom:
	eaq	0,x6		" qu = iom_number
	qrl	18		" q = iom_number
	mpy	per_iom_size,dl
	eax3	-per_iom_size,ql	" x3 = index into iom_data.per_iom

	eaq	0,x6		" qu = iom_number
	qrl	18		" q = iom_number
	mpy	iom_mailbox_size,dl
	eppbb	iom_mailbox$+iom_mailbox_seg.iom_mailbox-iom_mailbox_size,ql

	tsx0	lock_and_clear_mbx	" we don't inhibit here because we
				" are interested in locking all IOMs,
				" and this may take a lot of time.

	stz	bb|connect.lpw	" store LPW which will cause IOM fault

				" zero out interrupt bit for this
				" channel so we can see if the connect
				" took.  we will conditionally turn
				" it back on before returning

	eppbb	iom_mailbox$+iom_mailbox_seg.imw_array_word
	loca	sys_fault_channel_mask,du
	ansa	bb|level_1_interrupt-1,x6

	eax6	-1,x6		" iom_number = iom_number - 1
	tpnz	lock_an_iom

connect_for_fault:
	ldq	lb|0		" q = iom_number to be faulted
	mpy	per_iom_size,dl
	eax3	-per_iom_size,ql	" x3 = index into iom_data.per_iom

	cioc	bp|iom_data.per_iom+per_iom.cow,x3

	eppbb	iom_mailbox$+iom_mailbox_seg.imw_array_word

	ldx5	50,du		" do wait_loop = 50 to 1 by -1;
check_ioms:
	ldx6	4,du		" do iom_number = 4 to 1 by -1
check_an_iom:
	lda	bb|level_1_interrupt-1,x6  " if INTERRUPT_BIT_ON
	ana	sys_fault_channel_mask,du  " then goto connect_took
	tnz	connect_took

	eax6	-1,x6		" end check_ioms;
	tpnz	check_an_iom

	eax5	-1,x5		" end do_wait_loop;
	tnz	check_ioms

ioms_dont_respond:
	ldx7	0,du		" looks like connect was not recognized
	lda	error_table_$iom_connect_fatal
	sta	ap|4,*
	tra	unlock_ioms

connect_took:
	eaa	0,x6		" was this the requested IOM number?
	arl	18
	era	lb|0
	tze	find_status	" IOM number is OK
	lda	error_table_$iom_wrong_number
	sta	ap|4,*		" IOM number NOT OK
	eax7	0,x6		" remember what IOM thinks it is

find_status:
	ldx6	4,du		" do iom_number = 4 to 1 by -1;
status_this_iom:
	eaq	0,x6
	qrl	18
	mpy	sys_fault_list_size,dl
	eppbb	iom_mailbox$+iom_mailbox_seg.system_fault-sys_fault_list_size,ql

	ldx4	11,du		" do circ_buff_word = 11 to 0 by -1;
check_fault_status_code:
	lda	bb|0,x4		" if system_fault (iom_number, circ_buff_word) =
	locq	fault_code_mask,dl
	cmk	ill_tly_cont_mask,dl "    illegal_tally_contents
	tze	found_fault_status	" then goto found_fault_status

	cmk	zero_tly_mask,dl	"    zero_tally (IMU)
	tze	found_fault_status	" then goto found_fault_status

	eax4	-1,x4		" end do_circ_buff_word;
	tpl	check_fault_status_code

	eax6	-1,x6		" end find_status;
	tpnz	status_this_iom
	tra	*+2		" can't find mbx: skip next instruction

found_fault_status:
	stz	bb|0,x4		" don't bother anyone with the status
	eaa	0,x6
	arl	18
	era	lb|0		" did mailbox correspond to IOM number?
	tze	unlock_ioms	" yes - take no special action

	lda	error_table_$iom_wrong_mailbox
	sta	ap|4,*
	eax7	0,x6		" otherwise tell caller of error

unlock_ioms:
	odd
	sznc	bp|iom_data.imw_lock
	tze	-1,ic		" loop until lock untouched
	aos	bp|iom_data.imw_lock" was zero from sznc, is now 1
	ldx6	4,du		" do iom_number = 4 to 1 by -1;
unlock_an_iom:
	eaq	0,x6		" qu = iom_number
	qrl	18		" q = iom_number
	mpy	per_iom_size,dl
	eax3	-per_iom_size,ql	" x3 = index into iom_data.per_iom

	ldq	pds$process_id	" unlock the lock
	lda	0,du
	stacq	bp|iom_data.per_iom+per_iom.lock,x3

	eaq	0,x6
	qrl	18
	mpy	sys_fault_list_size,dl
	eppbb	iom_mailbox$+iom_mailbox_seg.system_fault-sys_fault_list_size,ql

	ldx4	11,du		" do circ_buffer_word = 11 to 0 by -1;
check_for_fault:
	szn	bb|0,x4		"      if system_fault (iom_number, circ_buffer_word) ^= 0
	tnz	set_imw_bit	"      then SET_IMW_BIT (iom)
	eax4	-1,x4		" end do_circ_buffer_word;
	tpl	check_for_fault
	tra	next_iom
set_imw_bit:
	eppbb	iom_mailbox$+iom_mailbox_seg.imw_array_word
	lda	sys_fault_channel_mask,du
	orsa	bb|level_1_interrupt-1,x6
next_iom:
	eax6	-1,x6		" end unlock_ioms;
	tpnz	unlock_an_iom

	szn	ap|4,*		" if we return a nonzero status,
	tze	*+2		" tell the caller what the IOM
	sxl7	lb|0		" thought it was.

	short_return

inv_iom_range:			" iom number was not between 1 and 4
	stz	lb|0
	lda	error_table_$bad_arg
	sta	ap|4,*

	short_return

imw_already_locked:			" imw_lock found to be -1
	sta	bp|iom_data.imw_lock
	stz	lb|0
	lda	error_table_$mylock
	sta ap|4,*

	short_return

" 
" Copy out long status information.
"
" call iom_connect$get_status (chx, sqep);

get_status:
	tsx0	setup

	epplb	ap|4,*		" get queue entry ptr
	epplb	lb|0,*

	mrl	(pr),(pr),fill(000) " clear the queue entry
	desc9a	sb|per_device.ext_status,4*8
	desc9a	lb|0,4*16		" and copy the extended status

	ldac	sb|per_device.status
	ldq	sb|per_device.status+1
	sta	lb|0		" word 1
	stq	lb|3		" word 4

	lda	bb|channel_mailbox.dcw,x2
	sta	lb|4

	lda	bb|channel_mailbox.lpw,x2
	sta	lb|1		" word 2

	epbpsb	sp|0		" restore stack base ptr
	short_return
"
"
" call iom_connect$data_tdcw (io_manager_arg);
"
data_tdcw:
	tsx0	setup
	tsx0	tdcw

	absa	lb|io_manager_arg.listp,*
	arl	12		" get absolute address
	stca	ab|0,10		" store high bits
	als	18
	stca	ab|1,70		" and low bits

	epbpsb	sp|0		" restore stack base ptr
	short_return
"
"
" call iom_connect$workspace_tdcw (io_manager_arg);
"
workspace_tdcw:
	tsx0	setup
	tsx0	tdcw
	lda	4,dl		" set tdcw.ec
	orsa	ab|1

	lxl7	lb|io_manager_arg.listx
	stx7	ab|1

	epbpsb	sp|0		" restore stack base ptr
	short_return
" 
"
"	SUPPORT SUBROUTINES
"

" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
"	setup
"
"	INPUT:	ap|2 - pointer to index into iom_data.per_device
"		x0   - return address
"	OUTPUT:	bp   - pointer to iom_data
"		bb   - pointer to iom_mailbox for referenced IOM
"		lb   - pointer to io_manager_arg
"		sb   - pointer to iom_data.per_device
"		x2   - logical channel offset in IOM's mailbox
"		x3   - index into iom_data.per_iom
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "

setup:
	eppbp	iom_data$		" establish addressability
	epplb	ap|2,*		" LB -> io_manager_arg

	ldq	lb|io_manager_arg.chx
	tmoz	chx_err		" check it
	cmpq	bp|iom_data.n_devices
	tpnz	chx_err
	mpy	per_device_size,dl	" chx index into per_device
	eax1	-per_device_size,ql	" into X1 and SB
	eppsb	bp|iom_data.per_device,x1

	ldq	sb|per_device.flags	" is it assigned?
	canq	per_device.in_use,du
	tze	chx_err		" no

	ldq	sb|per_device.channel
				" get channel number from per_device
	qls	2		" channel * 4 index into mailbox
	eax2	0,ql		" into X2

	ldq	sb|per_device.iom	" get IOM number (1 - 4)
	mpy	per_iom_size,dl	" IOM index into per_iom
	eax3	-per_iom_size,ql	" into X3

	ldq	sb|per_device.iom	" get IOM number (1 - 4)
	mpy	iom_mailbox_size,dl	" IOM index into iom_mailbox
	eppbb	iom_mailbox$+iom_mailbox_seg.iom_mailbox-iom_mailbox_size,ql
				" bb -> IOM mailbox
	tra	0,x0		" return
"
" " " " " " " " " " " " " " " " " " " " " " "
"
"		setup_pt
"
setup_pt:
	stz	sb|per_device.lpw+1
	lda	sb|per_device.channel
	als	27
	sta	sb|per_device.pcw+1

	ldx7	lb|io_manager_arg.ptp
	cmpx7	=o77777,du	" check for null ptr
	tze	0,x0		" no page table

	absa	lb|io_manager_arg.ptp,*
				" get address of page table
	arl	9		" in middle two bytes
	ora	=o600,dl		" set PTP & PGE
	stba	sb|per_device.pcw+1,34

	lda	lb|io_manager_arg.bound
				" get bound
	sta	sb|per_device.lpw+1	" in LPWX
	tra	0,x0


tdcw:
	eppab	lb|io_manager_arg.dcw_pair_ptr,*
	szn	ab|0		" AB -> dcw_pair
	tnz	idcw_given	" IDCW is there
	lda	common_pcw	" give him the default
	sta	ab|0
idcw_given:
"
" At this point we would normally set idcw.ext_ctl.  This would allow IOM's
" to transfer to DCW lists which do not reside in the low 256K.
" Unfortunately, the PSIA does not handle this bit properly.
" As a result, we do not set the bit and put a kludge in pc_abs so that
" contiguous I/O buffers are always in the low 256K.
"
"	lda	=o040000,dl	" set extension control in IDCW
"	orsa	ab|0
"
	lda	=o020001,dl	" set default TDCW
	sta	ab|1
	tra	0,x0		" return


" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
"	lock_and_clear_mbx
"
"	INPUT:	bp - pointer to iom_data
"		bb - pointer to iom_mailbox
"		x3 - index into iom_data.per_iom
"	OUTPUT:	per_iom.lock = our process_id
"		IOM - all previous connects have completed
"
"		THE INTERRUPT INHIBITED CODE SHOULD BE CONTINUED
"		BY THE CALLER UNTIL THE IOM LOCK IS UNLOCKED
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " 


lock_and_clear_mbx:
	ldq	0,dl		" show this is the first try

" Note, if we fall into this code (i.e. we haven't tried to reconnect), the
" q register is zero.  If we come here after reconnecting, the q register is
" non-zero, and we use this distinction to determine whether or not to
" reconnect (we'll only retry once). We let someone upstairs handle any
" connects that are lost this way.  This allows ESD to succeed even in the case
" when an IOM completely stops responding as long as there are alternate paths.

	odd			" to cause fetching of two Y-pairs during
				" this tight loop so we won't lock-up
lock_mailbox:
	szn	bp|iom_data.per_iom+per_iom.lock,x3
	tnz	-1,ic		" loop until mailbox is free

	inhibit	on		" <+><+><+><+><+><+><+><+><+><+>

	lda	pds$process_id
	stac	bp|iom_data.per_iom+per_iom.lock,x3
	tnz	lock_mailbox	" someone beat us to the lock

check_for_connect:

	lda	bp|iom_data.per_iom+per_iom.connect_lpw,x3
	cmpa	bb|connect.lpw	" if the same, then there is a connect
	tnz	locked_and_cleared  " pending from the process before us.

	ldx7	200,du		" we will wait until it completes
				" and possibly restart it
wait_for_connect:
	cmpa	bb|connect.lpw
	tnz	locked_and_cleared	" ah, the IOM finished the connect
	adx7	-1,du		" decrement loop counter
	tpl	wait_for_connect	" and continue looping until negative

	cmpq	0,dl		" is q clear?
	tze	reconnect		" yes, give it one shot.
				" no, forget it
	aos	bp|iom_data.per_iom+per_iom.abandoned_connects,x3
	tra	locked_and_cleared

reconnect:
	cioc	bp|iom_data.per_iom+per_iom.cow,x3
				" iom seems to have forgotten about
				"  the connect, so reissue it
	aos	bp|iom_data.per_iom+per_iom.reconnects,x3 " meter
	ldq	pds$process_id	" Note, this is the non-zero q value
	lda	0,du		"  that prevents us from trying again
	stacq	bp|iom_data.per_iom+per_iom.lock,x3 " start this over again
	tra	lock_mailbox

locked_and_cleared:
	tra	0,x0

	inhibit	off		" <-><-><-><-><-><-><-><-><-><->

" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
"	chx_err, addr_err
"
" " " " " " " " " " " " " " "	" " " " " " " " " " " " " " " " " " " " "

chx_err:
	epbpsb	sp|0		" restore stack base ptr
	push			" bad channel index
	short_call io_error$bad_chx	" report it
	return

addr_err:
	epbpsb	sp|0		" restore stack base ptr
	push
	short_call io_error$bad_addr
	return
" 
	include	io_manager_dcls;
	include	iom_data

	equ	connect.pcw,connect_channel*channel_mailbox_size+channel_mailbox.scw
	equ	connect.lpw,connect_channel*channel_mailbox_size+channel_mailbox.lpw
	equ	sys_fault.lpw,system_fault_channel*channel_mailbox_size+channel_mailbox.lpw
	equ	level_1_interrupt,4
	equ	sys_fault_list_size,12
	bool	sys_fault_channel_mask,200000
	bool	ill_tly_cont_mask,000013
	bool	zero_tly_mask,000005
	bool	fault_code_mask,000077

	end




		    iom_error.pl1                   11/11/89  1140.6rew 11/11/89  0802.6       29529



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

/* format: off */

/* Written 1st quarter 1981 by Charles Hornig */


/****^  HISTORY COMMENTS:
  1) change(87-11-13,Farley), approve(88-03-01,MCR7814),
     audit(88-03-01,Parisek), install(88-03-08,MR12.2-1032):
     Changed invalid_overhead entry point to recognize the data word passed to
     it and to change the syserr message to contain this word when non-zero.
                                                   END HISTORY COMMENTS */


iom_error$invalid_interrupt:
     procedure (Channel, Level, Dummy);

dcl  Iom fixed bin (3) parameter;
dcl  Channel fixed bin (35) parameter;
dcl  Level fixed bin (3) parameter;
dcl  Data_word bit (36) aligned parameter;
dcl  Dummy bit (36) aligned parameter;

dcl  syserr entry options (variable);

dcl  data_word bit (36) aligned;
dcl  iom_no fixed bin (3);
dcl  chan_no fixed bin (7);
dcl  chan_id char (8) aligned;
dcl  code fixed bin (35);

dcl (divide, mod, size) builtin;

dcl  Max_Channel fixed bin (17) internal static options (constant) init (64);
dcl  Max_Iom fixed bin (17) internal static options (constant) init (4);

/* * * * * * * * * * INVALID_INTERRUPT * * * * * * * * * */

	iom_no = 1 + divide (Channel, Max_Iom * size (per_iom), 3, 0);
	chan_no = mod (Channel, Max_Channel);
	data_word = "0"b;
	goto common;

/* * * * * * * * * * INVALID_OVERHEAD * * * * * * * * * */

invalid_overhead:
	entry (Iom, Channel, Level, Data_word);

	iom_no = Iom;
	chan_no = Channel;
	data_word = Data_word;

common:
	call io_chnl_util$iom_to_name (iom_no, chan_no, chan_id, code);
	if code ^= 0 then chan_id = "?";
	call syserr (JUST_LOG, "iom_error: Unexpected level ^d interrupt from channel ^a^[ (iom ^d, chan ^d)^;^2s^].^[^/^- Status word - ^12.3b^;^s^]", Level, chan_id, (chan_id = "?"), iom_no, chan_no, (data_word ^= "0"b), data_word);
	return;
%page;
%include iom_data;
%include io_chnl_util_dcls;
%include syserr_constants;
%page;
/* BEGIN MESSAGE DOCUMENTATION


   Message:
   iom_error: Unexpected level LEVEL_NUM interrupt from channel CHNL
   [Status word - OOOOOOOOOOOO]

   S: $info

   T: $run

   M: The specified level interrupt has occured on channel CHNL, either no
   channel assignment was found for the specified channel or there was no
   handler specified for the channel.  If CHNL is a "?", this indicates an
   error occured converting the iom and channel numbers, which are displayed
   in parenthesis "(iom N, chan_no N)" after the question mark.  The status
   word associated with the interrupt will be displayed when non-zero.

   A: $notify

   END MESSAGE DOCUMENTATION */

     end iom_error$invalid_interrupt;




		    iom_overhead.pl1                11/11/89  1140.6r w 11/11/89  0802.6       83304



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

/* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
iom_overhead:
     procedure;

/* iom_overhead: Process interrupts on IOM overhead channels */
/* Written December 1980 by C. Hornig */
/* init entry moved in April 1984 by Chris Jones */
/* init_without_assign added in November 1984 by M. Pandolf */

dcl	Iom		   fixed bin (35) parameter;
dcl	Level		   fixed bin (3) parameter;
dcl	Data_word		   bit (36) aligned parameter;

dcl	Code		   fixed bin (35) parameter;

dcl	absadr		   entry (ptr, fixed bin (35)) returns (fixed bin (26));
dcl	iom_error$invalid_overhead
			   entry (fixed bin (3), fixed bin (6), fixed bin (3), bit (36) aligned);
dcl	iom_overhead$system_fault
			   entry (fixed bin (35), fixed bin (3), bit (36) aligned);
dcl	iom_overhead$special_status
			   entry (fixed bin (35), fixed bin (3), bit (36) aligned);
dcl	ldac		   entry (ptr) returns (bit (36) aligned);
dcl	syserr		   entry options (variable);

dcl	errcode		   fixed bin (35);
dcl	i		   fixed bin;
dcl	iom		   fixed bin (3);
dcl	1 iom_special_status   aligned like io_special_status;
dcl	1 iom_fault_status	   aligned,
	( 2 mbz1		   bit (9),
	  2 channel	   bit (9),		/* channel number */
	  2 serv_req	   bit (5),		/* service request */
	  2 mbz2		   bit (3),
	  2 controller_fault   bit (4),		/* system controller fault code */
	  2 io_fault	   bit (6)
	  )		   unaligned;		/* I/O fault code */

dcl	IOMS		   char (4) internal static options (constant) init ("ABCD");

dcl	error_table_$dev_offset_out_of_bounds
			   fixed bin (35) ext static;

dcl	(addr, binary, bit, dimension, hbound, lbound, null, string, substr)
			   builtin;

init:
     entry (Iom, Code);

	iom = Iom;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);
	call set_overhead_channel (system_fault_channel, iom_overhead$system_fault,
	     addr (iom_mailbox_seg.system_fault (iom)));

/* Set up the handler and mailbox for the special status channel. */

	call set_overhead_channel (special_status_channel, iom_overhead$special_status,
	     addr (iom_mailbox_seg.special_status (iom)));

	errcode = 0;
INIT_RETURN:
	Code = errcode;
	return;

init_without_assign:
     entry (Iom, Code);

	iom = Iom;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);

	call set_dcw_lpw (iom, system_fault_channel,
	     addr (iom_mailbox_seg.system_fault (iom)),
	     dimension (addr (iom_mailbox_seg.system_fault (iom)) -> status_queue.status, 1));

	Code = 0;
	return;

release:
     entry (Iom, Code);


	iom = Iom;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);
	call io_manager$unassign (iom_data.per_iom (iom).special_chx, (0));
	call io_manager$unassign (iom_data.per_iom (iom).fault_chx, (0));
	Code = 0;
	return;

/* SET_OVERHEAD_CHANNEL - Internal Procedure to Set up Mailbox and Interrupt Handler for Overhead Channels.

   An LPW is set up with tally update suppressed so that it keeps refreshing the DCW for the same location.
   The refresh DCW is stored in the SCW slot of the channel, since overhead channels don't use their SCW.
   This scheme provides a circular continuous queue.	*/

set_overhead_channel:
     procedure (channo, intp, qp);

dcl	channo		   fixed bin (6),		/* overhead channel number */
	intp		   entry,			/* interrupt handler procedure */
	qp		   ptr;			/* ptr to queue for overhead channel */

dcl	tally		   fixed bin (12);		/* tally for overhead channel DCW */
dcl	tempx		   fixed bin (35);

	call io_manager$assign (tempx, substr ("ABCD", iom, 1) || substr ("1234567", channo, 1), intp, (iom), (null ()),
	     errcode);
	if errcode ^= 0 then
	     goto INIT_RETURN;

	tally = dimension (qp -> status_queue.status, 1);
	if channo = special_status_channel		/* If special status channel ... */
	then do;
	     iom_data.per_iom (iom).special_chx = tempx;
	     tally = tally - 2;			/* Allow two extra words for spillover.
						   See IOM EPS-1 Section on Special Status
						   for a discussion of spillover considerations. */
	end;
	else iom_data.per_iom (iom).fault_chx = tempx;
	call set_dcw_lpw (iom, channo, qp, tally);

	return;
     end set_overhead_channel;

/* * * * * * * * * * ABS_ADDR_18 * * * * * * * * * */

abs_addr_18:
     procedure (P) returns (bit (18) aligned);
dcl	P		   ptr parameter;

dcl	address		   fixed bin (26);

	address = absadr (P, errcode);
	if errcode ^= 0 then
	     goto INIT_RETURN;
	if address > (262144 - 4096) then do;
	     errcode = error_table_$dev_offset_out_of_bounds;
	     goto INIT_RETURN;
	end;
	return (bit (binary (address, 18)));
     end abs_addr_18;

/* * * * * * * * * * SYSTEM_FAULT * * * * * * * * * */

system_fault:
     entry (Iom, Level, Data_word);

	iom = Iom;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);

	status_queue_ptr = addr (iom_mailbox_seg.system_fault (iom));

	do i = lbound (status_queue.status, 1) to hbound (status_queue.status, 1);
	     string (iom_fault_status) = ldac (addr (status_queue.status (i)));
	     if string (iom_fault_status) ^= ""b then do;
		call syserr (0, "iom_overhead: IOM ^a System fault status ^w.", substr (IOMS, iom, 1),
		     string (iom_fault_status));
		if iom_fault_status.channel ^= ""b then
		     call report (binary (iom_fault_status.channel, 9), string (iom_fault_status));
	     end;
	end;

	call check_dcw (system_fault_channel);

	return;

/* * * * * * * * * * SPECIAL_STATUS * * * * * * * * * */

special_status:
     entry (Iom, Level, Data_word);

	iom = Iom;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);

	status_queue_ptr = addr (iom_mailbox_seg.special_status (iom));

	do i = lbound (status_queue.status, 1) to hbound (status_queue.status, 1);
	     string (iom_special_status) = ldac (addr (status_queue.status (i)));
	     if iom_special_status.t then
		call report (binary (iom_special_status.channel, 9), string (iom_special_status));
	end;

	call check_dcw (special_status_channel);

	return;

/* * * * * * * * * * REPORT * * * * * * * * * */

report:
     procedure (Channel, Data_word);
dcl	Channel		   uns fixed bin (9) parameter;
dcl	Data_word		   bit (36) aligned parameter;
dcl	chx		   fixed bin;

	chx = 0;

	if (Channel >= lbound (iom_data.per_iom.chantab, 2)) & (Channel <= hbound (iom_data.per_iom.chantab, 2)) then
	     chx = iom_data.per_iom (iom).chantab (Channel);

	if chx > 0 then
	     if iom_data.per_device (chx).flags.in_use then do;
		call iom_data.per_device (chx).handler (iom_data.per_device (chx).index, Level, Data_word);
		return;
	     end;

	call iom_error$invalid_overhead (iom, (Channel), Level, Data_word);

     end report;


check_dcw:
     procedure (Channel);
dcl	Channel		   fixed bin (6);
dcl	rdcwp		   ptr;

	dcwp = addr (iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (Channel).dcw);
	rdcwp = addr (iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (Channel).scw);
	if (dcwp -> dcw.tally) > (rdcwp -> dcw.tally) then
	     call syserr ("iom_overhead: Status queue overrun for IOM ^a channel ^d.", substr (IOMS, iom, 1), Channel);

	string (dcwp -> dcw) = string (rdcwp -> dcw);

     end check_dcw;

set_dcw_lpw:
     procedure (iom, chan, qp, tly);

dcl	iom		fixed bin (3),		/* IOM number */
	chan		fixed bin (6),		/* logical channel number */
	qp		ptr,			/* pointer to queue for channel */
	tly		fixed bin (12);		/* tally for DCW */

	dcwp = addr (iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (chan).scw);
	dcwp -> dcw.address = abs_addr_18 (qp);
	dcwp -> dcw.tally = bit (tly);
	dcwp -> dcw.type = "01"b;			/* IOTP */

	iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (chan).dcw =
	     iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (chan).scw;

	lpwp = addr (iom_mailbox_seg.iom_mailbox (iom).channel_mailbox (chan).lpw);
	lpwp -> lpw.dcw_addr = abs_addr_18 (dcwp);
	lpwp -> lpw.nc = "1"b;			/* LPW ADDR and TALLY fields update inhibit */

	return;
     end set_dcw_lpw;

%include io_manager_dcls;
%page;
%include iom_data;
%page;
%include io_special_status;
%page;
%include iom_dcw;
%page;
%include iom_lpw;

/* BEGIN MESSAGE DOCUMENTATION


   Message:
   iom_overhead: IOM TAG System fault status STATUS.

   S: $info

   T: $run

   M: An IOM system fault has occurred.
   This indicates a problem in either hardware or system software.

   A: $notify


   Message:
   iom_overhead: Status queue overrun for IOM TAG channel CHANNEL.

   S: $info

   T: $run

   M: The IOM has failed to refresh the DCW for an overhead channel.
   This indicates a hardware problem.

   A: $notify


   END MESSAGE DOCUMENTATION */

     end iom_overhead;




		    iom_reset.pl1                   11/11/89  1140.6r w 11/11/89  0802.6       12060



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


/* format: style4,delnl,insnl,tree,ifthenstmt,indnoniterend */
iom_reset:
     procedure;

/* This procedure is called during ESD to clean things up. */
/* Written by C. Hornig November 1980 */

dcl  i fixed bin;

dcl  (addr, hbound, lbound, unspec) builtin;

/* * * * * * * * * * * * * * * * * */

	iom_mailbox_seg_ptr = addr (iom_mailbox$);
	unspec (iom_mailbox_seg.imw_array) = ""b;	/* clear out all IMW's */

	iom_data_ptr = addr (iom_data$);
	do i = lbound (iom_data.per_iom, 1) to hbound (iom_data.per_iom, 1);
	     iom_data.per_iom (i).lock = ""b;		/* unlock all the channel locks */
	end;

	return;
%page;
%include iom_data;

     end iom_reset;




		    iom_switches.pl1                11/11/89  1140.6r w 11/11/89  0802.6       73791



/****^  ***********************************************************
        *                                                         *
        * Copyright, (C) Honeywell Bull Inc., 1987                *
        *                                                         *
        * Copyright, (C) Honeywell Information Systems Inc., 1984 *
        *                                                         *
        *********************************************************** */



/****^  HISTORY COMMENTS:
  1) change(87-02-26,Farley), approve(87-04-15,MCR7661),
     audit(87-04-21,Fawcett), install(87-04-28,MR12.1-1028):
     Removed the manipulation of fgbx.shut and fgbx.ssenb in favor of a new
     flag, fgbx.io_reconfig, that will still inhibit ESDs but will allow
     crashes to appear as crashes at BCE.
                                                   END HISTORY COMMENTS */


/* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
iom_switches$validate:
     procedure (p_iom_index, p_code);

/* iom_switches - program to play with switches on an IOM.  Originally written to check settings of IOM switches. */
/* Written May 1984 by M. Pandolf */
/* Modified November 1984 by M. Pandolf to check for PARM card field */
/* Modified April 1985 by Chris Jones to lower-case parm name and to remove calls to mask interrupt processors. */

	parm_ptr = null ();
	call config$find_parm ("dris", parm_ptr);	/* is DRIS parameter present? */
	if parm_ptr ^= null () then do;		/* yes, so don't check IOM switches */
	     p_code = 0;
	     return;
	end;

	iom_number = p_iom_index - 1;

	call DEL_256K_BLOCKS ();			/* free up places where */
						/* IOM may write status */

	call tc_util$suspend_tc ();			/* run me only */

	call pc$flush_core ();			/* perform a partial */
						/* shutdown of the file system */

	fgbxp = addr (flagbox$);			/* give esd no reason to run, */
	fgbx.io_reconfig = YES;			/* and have salvaging fix */
						/* things up when we boot again */

test_loop:
	call privileged_mode_ut$wire_and_mask (pmut_mask, pmut_ptr);
						/* enter critical chunk of code */

	iom_id = iom_number + 1;
	call iom_connect$connect_and_identify (iom_id, status);

	call privileged_mode_ut$unwire_unmask (pmut_mask, pmut_ptr);

	if status ^= 0				/* analyze IOM tracks */
	then do;

	     if iom_id > 0 then do;
		call FIX_DAMAGE ();
		goto test_loop;
	     end;
	     else p_code = status;
	end;
	else do;					/* everything was as expected */

	     fgbx.io_reconfig = NO;
	     call tc_util$resume_tc ();
	     call ADD_256K_BLOCKS ();

	end;

	return;

/* INTERNAL PROCEDURES */

DEL_256K_BLOCKS:
     procedure ();

	astep = null ();
	curr_mem_base = 0;
	frames_deleted (*) = 0;

	found_256k = YES;				/* lie to get the loop started */
	do while (found_256k);

	     found_256k = NO;
	     do ctlr = 0 to 7 while (^found_256k);

		if scs$controller_data (ctlr).info.online then
		     if scs$controller_data (ctlr).size > 0 then
			if scs$controller_data (ctlr).base = curr_mem_base then do;

			     frames_deleted (ctlr) = min (scs$controller_data (ctlr).size, 256);
			     call reconfig$del_main (curr_mem_base, frames_deleted (ctlr), status);
			     if status = 0 then do;
				found_256k = YES;
				deleted_256k (ctlr) = YES;
				curr_mem_base = curr_mem_base + frames_deleted (ctlr);
			     end;
			     else frames_deleted (ctlr) = 0;

			end;

	     end;

	end;

	if unspec (deleted_256k) ^= ""b then do;

	     call lock$lock_ast ();
	     astep = get_aste (256);
	     call thread$out (astep, sst$level.ausedp (3));
	     call lock$unlock_ast ();
	     if astep ^= null () then do;
		call get_ptrs_$given_astep (astep, tsdw);
		ptp = addrel (astep, sst$astsize);
	     end;

	end;

	return;

     end DEL_256K_BLOCKS;

ADD_256K_BLOCKS:
     procedure ();

	do ctlr = 0 to 7;

	     if frames_deleted (ctlr) > 0 then
		call reconfig$add_main ((scs$controller_data (ctlr).base), frames_deleted (ctlr), status);

	end;

	if astep ^= null () then do;

	     call lock$lock_ast ();
	     call thread$cin (astep, sst$level.ausedp (3));
	     call put_aste (astep);
	     call lock$unlock_ast ();

	end;

     end ADD_256K_BLOCKS;

FIX_DAMAGE:
     procedure ();

	if status = error_table_$iom_wrong_number then
	     call syserr (BEEP, "iom_switches: IOM number is set to ^i, but should be ^i.", iom_id - 1, iom_number);
	else if status = error_table_$iom_wrong_mailbox then
	     call syserr (BEEP, "iom_switches: IOM mailbox switches are ^a, but should be ^a.",
		EXPECTED_SWITCHES (iom_id - 1), EXPECTED_SWITCHES (iom_number));
	else call syserr (BEEP, "iom_switches: IOM switches are incorrect.");

	call syserr (ANNOUNCE, "iom_switches: Reset switches and press RETURN.");

	recheck_time = clock () + 10 * 1000000;
	do while (clock () < recheck_time);
	     temp_iom_id = iom_number + 1;		/* just to waste some time */
	end;

wait_for_return:
	unspec (my_console_io) = ""b;
	my_console_io.flags.read = "1"b;
	my_console_io.sequence_no = 0;

	call ocdcm_$priority_io (addr (my_console_io));
	if ^my_console_io.completed then
	     goto wait_for_return;

	return;

     end FIX_DAMAGE;

/* DECLARATIONS */

/* Parameter */

dcl	p_iom_index	   fixed bin (3) parameter;
dcl	p_code		   fixed bin (35) parameter;

/* Automatic */

dcl	parm_ptr		   pointer;		/* pointer to PARM card field */
dcl	iom_number	   fixed bin (3);		/* 0-3, correspones to switch settings */
dcl	status		   fixed bin (35);		/* standard system status code */
dcl	iom_id		   fixed bin;		/* 1-4, indexes IOM information arrays */
dcl	temp_iom_id	   fixed bin;		/* used in a calculation to waste time */
dcl	curr_mem_base	   fixed bin;		/* frame number of start of next configured SC */
dcl	ctlr		   fixed bin (3);		/* SC number */
dcl	frames_deleted	   dim (0:7) fixed bin;	/* number of frames deleted per SC */
dcl	found_256k	   bit (1) aligned;		/* indicates when we have found the correct mem block */
dcl	deleted_256k	   dim (0:7) bit (1);	/* TRUE if we have deleted mem from this SC */
dcl	tsdw		   fixed bin (71);		/* TempSDW */
dcl	ptp		   pointer;		/* PageTable Pointer */
dcl	pmut_mask		   fixed bin (71);		/* former processor mask, to be restored after critical code */
dcl	pmut_ptr		   pointer;		/* return ptr from pmut, used by it later */
dcl	recheck_time	   fixed bin (71);		/* the time at which we will check for fixed switches */

dcl	1 my_console_io	   aligned like console_io;

/* Static, External */

dcl	error_table_$iom_wrong_number
			   fixed bin (35) external static;
dcl	error_table_$iom_wrong_mailbox
			   fixed bin (35) external static;
dcl	sst$astsize	   fixed bin external static;

dcl	1 sst$level	   (0:3) aligned external static,
	  2 ausedp	   bit (18) unaligned,
	  2 no_aste	   bit (18) unaligned;


/* Static, Constant */

dcl	(
	NO		   init ("0"b),
	YES		   init ("1"b)
	)		   bit (1) aligned internal static options (constant);
dcl	EXPECTED_SWITCHES	   dim (0:3) char (4) init ("1400", "2000", "2400", "3000");

/* Entry */

dcl	syserr		   entry () options (variable);
dcl	tc_util$suspend_tc	   entry ();
dcl	pc$flush_core	   entry ();
dcl	iom_connect$connect_and_identify
			   entry (fixed bin, fixed bin (35));
dcl	tc_util$resume_tc	   entry ();
dcl	reconfig$del_main	   entry (fixed bin, fixed bin, fixed bin (35));
dcl	lock$lock_ast	   entry ();
dcl	get_aste		   entry (fixed bin) returns (ptr);
dcl	thread$out	   entry (ptr, bit (18));
dcl	lock$unlock_ast	   entry ();
dcl	get_ptrs_$given_astep  entry (ptr, fixed bin (71));
dcl	reconfig$add_main	   entry (fixed bin, fixed bin, fixed bin (35));
dcl	thread$cin	   entry (ptr, bit (18));
dcl	put_aste		   entry (ptr);
dcl	privileged_mode_ut$wire_and_mask
			   entry (fixed bin (71), ptr);
dcl	privileged_mode_ut$unwire_unmask
			   entry (fixed bin (71), ptr);
dcl	ocdcm_$priority_io	   entry (ptr);
dcl	config$find_parm	   entry (char (4) aligned, ptr);

/* Builtin */

dcl	addr		   builtin;
dcl	addrel		   builtin;
dcl	clock		   builtin;
dcl	min		   builtin;
dcl	null		   builtin;
dcl	unspec		   builtin;

/* Include Files */

%include aste;
%page;
%include syserr_constants;
%page;
%include sdw;
%page;
%include flagbox;
%page;
%include scs;
%page;
%include oc_data;

     end iom_switches$validate;




		    iom_unassign.pl1                11/11/89  1140.6rew 11/11/89  0802.6       22338



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


/* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
iom_unassign:
     procedure (Chx, Code);

/* Unassign an IOM channel. */
/* Stolen from iom_manager November 1980 by C. Hornig */
/* Modified for channel reconfiguration January 1984 by Chris Jones */
/* Modified to not mask overhead channels, February 1985 by Chris Jones */

dcl	Chx		   fixed bin (35) parameter;
dcl	Code		   fixed bin (35) parameter;


dcl	chx		   fixed bin (35);
dcl	delete_entry	   bit (1) aligned;

dcl	(addr, hbound, lbound) builtin;

/* * * * * * * * * * * * * * * * * * * */

	delete_entry = "0"b;
	goto common;

delete_channel:
     entry (Chx, Code);

	delete_entry = "1"b;
common:
	Code = 0;
	iom_data_ptr = addr (iom_data$);
	iom_mailbox_seg_ptr = addr (iom_mailbox$);

	chx = Chx;				/* copy argument */
	if (chx < lbound (iom_data.per_device, 1)) | (chx > hbound (iom_data.per_device, 1)) then do;
bad_chx:
	     Code = 1;				/* called on PRDS during ESD */
	     return;
	end;

	if ^iom_data.per_device (chx).flags.in_use then
	     goto bad_chx;

	if (iom_data.per_device (chx).channel ^= system_fault_channel)
	     & (iom_data.per_device (chx).channel ^= special_status_channel) then do;
	     call io_manager$mask (chx);		/* reset and mask channel */

	     iom_mailbox_seg.iom_mailbox (iom_data.per_device (chx).iom)
		.channel_mailbox (iom_data.per_device (chx).channel).scw = iom_data.stop_scw;
						/* reset for status processing */
	     iom_mailbox_seg.iom_mailbox (iom_data.per_device (chx).iom)
		.channel_mailbox (iom_data.per_device (chx).channel).lpw = iom_data.stop_lpw;
	end;

	if delete_entry then
	     iom_data.per_device (chx).flags.on_line = "0"b;
	iom_data.per_device (chx).flags.in_use = "0"b;
	return;

%include iom_data;
%page;
%include io_manager_dcls;

     end iom_unassign;





		    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
