	.IF	LIST3
	.LIST
	.PAGE
	.ELSE
	.NOLIST
	.ENDC
;****************************************************************************
;
;	BIOS Entry and Foreground Structure.
;
;	File:	SAGE.BIOS3.TEXT
;	Date:	 8-Sep-83
;	Issue:	2E
;
;
;	COPYRIGHT (c) 1982, 1983 SAGE Computer Technology
;	All Rights Reserved
;
;****************************************************************************
;
;	History:
;
;	1     13-Jun-82 Initial release.
;	1A    11-Jul-82 Added delay on exit to Debugger.
;	1B    30-Jul-82 Revised LB_LOAD.  Don't save D3 in LB_RCLK.
;			Added WTCH129 and TIMBIAS scheme.
;	1C    15-Aug-82 Added LB_IOCA (function #18.).
;	1D    17-Aug-82 Added Time adjustment.
;	1E    23-Aug-82 Added WTCH131 for scheduled events.
;	1F    30-Aug-82 Fixed Time adjustment.
;	1G     4-Sep-82 Added p-System address readback (UNITSTATUS to 130)
;			and function to set into supervisor mode (#19).
;	1H     2-Oct-82 Removed UNITSTATUS to 130.
;	1K     8-Nov-82 Fixed bugs in LB_LOAD.
;	2     23-Mar-83 Initial SAGE IV release.
;	2A    16-May-83 Fixed bug in RCFCH0.
;	2B    17-May-83 Added new Long BIOS calls.
;	2C    31-May-83 Added Long BIOS calls to set up direct SIGEVENT
;			routine.
;	2D    14-Jul-83 Fixed LB_ESCH, LB_CSCH, LB_RCLK, and LB_RC60 to
;			not enable foreground if already disabled.
;	2E    12-Aug-83 Added high LBN to LB_LOAD.
;			Changed INCH131 to RDCH131.
;
;****************************************************************************



;****************************************************************************
;
;	Master interrupt to 8259
;
;****************************************************************************

INT8259
	MOVE.W	D0,-(A7)	;Save a data register
	MOVE.B	#0CH,P8259	;Set up to read vector
	MOVE.B	P8259,D0	;Get vector from 8259
	BPL.S	$10		;Did not have interrupt
	MOVE.B	#20H,P8259	;Indicate end of interrupt
	ANDI.W	#7,D0		;Mask for interrupt channel
	LSL.B	#1,D0		;Multiply by 2
	MOVE.W	INTTBL(D0.W),D0 ;Get address of routine
	JMP	INTTBL(D0.W)	;Jump to interrupt process

;	No actual interrupt
$10	MOVE.B	#20H,P8259	;Indicate end of interrupt
	MOVE.W	(A7)+,D0	;Restore working register
	RTE

;	Interrupt encode vector table
INTTBL	.WORD	SCHINT-INTTBL	; 0 - Scheduler timer interrupt
	.WORD	RININT0-INTTBL	; 1 - Remote input (aux serial) interrupt
	.WORD	TRMINT-INTTBL	; 2 - Terminal transmit interrupt
	.WORD	ROTINT0-INTTBL	; 3 - Remote output (aux serial) interrupt
	.WORD	RDINT-INTTBL	; 4 - Ringing detector interrupt
	.WORD	PRTINT-INTTBL	; 5 - Centronics port interrupt
	.WORD	RTINT-INTTBL	; 6 - Real time clock interrupt
	.WORD	FGINT-INTTBL	; 7 - Foreground interrupt

.PAGE
;****************************************************************************
;
;	Interrupt to 8259 for extra Serial Channels
;
;****************************************************************************

I8259SER
	MOVE.W	D0,-(A7)	;Save a data register
	MOVE.B	#0CH,SER8259	;Set up to read vector
	MOVE.B	SER8259,D0	;Get vector from 8259
	BPL.S	$10		;Did not have serial interrupt
	MOVE.B	#20H,SER8259	;Indicate end of interrupt
	ANDI.W	#7,D0		;Mask for interrupt channel
	LSL.B	#1,D0		;Multiply by 2
	MOVE.W	SINTTBL(D0.W),D0 ;Get address of routine
	JMP	SINTTBL(D0.W)	 ;Jump to interrupt process

;	No serial interrupt
$10	MOVE.B	#20H,SER8259	;Indicate end of interrupt
	BTST	#1,WP_2B	;Check if winchester interrupt enabled
	BEQ.S	$20		;Not expecting interrupt
	BTST	#WB_INDEX,WP_1A ;Check for winchester transfer completion
	BEQ.S	$20		;No disk completion
	ST	WG_IODN		;Set up the I/O done flag
	BSET	#FGWIN_B,FGTASKS+1 ;Set up winchester foreground request
	MOVE.B	#5,SI8255	;Cause foreground interrupt
$20	BCLR	#1,WP_2B	;Disable winchester interrupt
	MOVE.W	(A7)+,D0	;Restore working register
	RTE

;	Serial Channel Interrupt encode vector table
SINTTBL .WORD	RININT1-SINTTBL	  ; 0 - Serial channel #1 input
	.WORD	RININT2-SINTTBL	  ; 1 - Serial channel #2 input
	.WORD	RININT3-SINTTBL	  ; 2 - Serial channel #3 input
	.WORD	RININT4-SINTTBL	  ; 3 - Serial channel #4 input
	.WORD	ROTINT1-SINTTBL	  ; 4 - Serial channel #1 output
	.WORD	ROTINT2-SINTTBL	  ; 5 - Serial channel #2 output
	.WORD	ROTINT3-SINTTBL	  ; 6 - Serial channel #3 output
	.WORD	ROTINT4-SINTTBL	  ; 7 - Serial channel #4 output

.PAGE
;****************************************************************************
;
;	Foreground entry and exit processes
;
;****************************************************************************

FGINT	BSET	#7,P8259+2	;Disable future foreground interrupts
FGEXIT	MOVE.W	FGTASKS,D0	;Check for anything to do
	BNE.S	$10		;Have another task
	MOVE	#2100H,SR	;Prevent foreground interrupts
	MOVE.B	#4,SI8255	;Disable foreground (software) interrupt
	BCLR	#7,P8259+2	;Enable foreground lockout
	TST.W	FGTASKS		;Check again in case of window
	BNE.S	FGINT		;Had an activation in the window
	MOVE.W	(A7)+,D0	;Restore the working register
	RTE

$10	MOVE	#2000H,SR	;Enable interrupts
	LSR.W	#1,D0
	BCS	SCHEDTO		;Scheduler timeout
	LSR.W	#1,D0
	BCS	EVNTHAND	;Event Handler
	LSR.W	#1,D0
	BCS	FDDISP		;Floppy driver dispatcher
	LSR.W	#1,D0
	BCS	RMTTDLY		;Remote transmit delay setup
	LSR.W	#1,D0
	BCS	KEYLOKD		;Keyboard lockout delay setup
	LSR.W	#1,D0
	BCS	RMTLOKD		;Remote lockout delay setup
	LSR.W	#1,D0
	BCS	WDDISP		;Winchester driver dispatcher

;	LSR.W	#1,D0
;	BCS	FGTASK7		;Foreground task #7
;	LSR.W	#1,D0
;	BCS	FGTASK8		;Foreground task #8
;	LSR.W	#1,D0
;	BCS	FGTASK9		;Foreground task #9
;	LSR.W	#1,D0
;	BCS	FGTASKA		;Foreground task #10
;	LSR.W	#1,D0
;	BCS	FGTASKB		;Foreground task #11
;	LSR.W	#1,D0
;	BCS	FGTASKC		;Foreground task #12
;	LSR.W	#1,D0
;	BCS	FGTASKD		;Foreground task #13
;	LSR.W	#1,D0
;	BCS	FGTASKE		;Foreground task #14
;	LSR.W	#1,D0
;	BCS	FGTASKF		;Foreground task #15
	
;	Should not get here but clear stray flags in case.
	ANDI.W	#FGMASK,FGTASKS
	BRA	FGEXIT

.PAGE
;****************************************************************************
;
;	BIOS Long Sequence Entry Point
;
;	Entered via TRAP 14.
;
;	D0 contains function code in low word.
;	A0 points to base of argument block (if required).
;
;	All registers are preserved (including status register).
;
;****************************************************************************

BIOS_L	MOVE.L	D0,-(A7)	;Save D0
	CMPI.W	#BIOSLIM,D0	;Check against function limit
	BGT.S	$10		;Ignore undefined functions
	LSL.W	#1,D0
	MOVE.W	LTABLE(D0.W),D0 ;Get routine offset from LTABLE
	JSR	LTABLE(D0.W)	;Call routine

;	BIOS Long Sequence Exit
$10	MOVE.L	(A7)+,D0	;Restore D0
	RTE



;	Table of long sequence routines
LTABLE	.WORD	LB_DBUG-LTABLE	; 0 - Exit back to the Debugger
	.WORD	LB_INIT-LTABLE	; 1 - Reinitialize the BIOS
	.WORD	LB_TMEM-LTABLE	; 2 - Return top of memory
	.WORD	LB_INDB-LTABLE	; 3 - Install BIOS I/O in Debugger
	.WORD	LB_DSDB-LTABLE	; 4 - Disable BIOS I/O in Debugger
	.WORD	LB_RCLK-LTABLE	; 5 - Read system clock
	.WORD	LB_RC60-LTABLE	; 6 - Read system clock in 1/60 ths second
	.WORD	LB_ESCH-LTABLE	; 7 - Enter schedule of an event
	.WORD	LB_CSCH-LTABLE	; 8 - Cancel schedule of an event
	.WORD	LB_LOAD-LTABLE	; 9 - Load 68000 object program
	.WORD	LB_ICHN-LTABLE	;10 - Initialize a channel
	.WORD	LB_RCHN-LTABLE	;11 - Read data from a channel
	.WORD	LB_WCHN-LTABLE	;12 - Write data to a channel
	.WORD	LB_SCHN-LTABLE	;13 - Get Status of a channel
	.WORD	LB_QUIE-LTABLE	;14 - Quiet (for Events)
	.WORD	LB_ENAB-LTABLE	;15 - Enable (for Events)
	.WORD	LB_ATCH-LTABLE	;16 - Attach (for Events)
	.WORD	LB_EVNT-LTABLE	;17 - Event Routine Address Init
	.WORD	LB_IOCA-LTABLE	;18 - I/O Configuration Address Init
	.WORD	LB_SUPV-LTABLE	;19 - Enter Supervisor mode
	.WORD	LB_RHOK-LTABLE	;20 - Restore user hooks
	.WORD	LB_DBUG-LTABLE	;21 - Exit Multi-User environment
	.WORD	LB_GBOT-LTABLE	;22 - Get base of memory
	.WORD	LB_GTOP-LTABLE	;23 - Get top of memory
	.WORD	LB_GBDV-LTABLE	;24 - Get boot device (Multi-User only)
	.WORD	LB_PTRP-LTABLE	;25 - Put TRAP vector
	.WORD	LB_GTRP-LTABLE	;26 - Get TRAP vector
	.WORD	LB_PHYD-LTABLE	;27 - Translate to Physical device
	.WORD	LB_GOPS-LTABLE	;28 - Get operating system data address
	.WORD	LB_SETE-LTABLE	;29 - Set up direct event address
	.WORD	LB_CLRE-LTABLE	;30 - Clear direct event address


;	Reinitialize the BIOS
LB_INIT BRA	INITBIOS
	;This routine will do return


;	Return the top of memory
LB_GTOP MOVE.L	RDISKB,D0	;Get base of Ram Disk
	BEQ.S	LB_TMEM		;No RamDisk defined, return BIOSBASE
	MOVEA.L D0,A0
	RTS

LB_TMEM MOVEA.L BIOSBASE,A0
	
LB_GBDV				;NOP
	RTS

;	Return the bottom of memory
LB_GBOT
	LEA	400H,A0
	RTS


;	Install BIOS I/O into Debugger
LB_INDB MOVE.B	#1,BUGBIOS
	RTS


;	Disable BIOS I/O in Debugger
LB_DSDB CLR.B	BUGBIOS
	RTS


;	Initialize I/O Configuration Routine Address
LB_IOCA MOVE.L	A0,IOCONFA
	BSR	PIOCONF		;Initialize printer configuration
	RTS


;	Enter Supervisor mode
LB_SUPV BSET	#5,8(A7)	;Set Supervisor bit in saved SR
	RTS


;	Enter schedule of an event
LB_ESCH BSET	#7,P8259+2	;Disable foreground interrupts
	MOVE	SR,-(SP)
	BSR	ESCHED		;Enter the schedule
	MOVE	(SP)+,CCR
	BNE.S	$10		;Don't enable foreground if disabled
	BCLR	#7,P8259+2	;Enable foreground interrupts
$10	RTS

;	Cancel schedule of an event
LB_CSCH BSET	#7,P8259+2	;Disable foreground interrupts
	MOVE	SR,-(SP)
	BSR	CSCHED		;Cancel the schedule
	MOVE	(SP)+,CCR
	BNE.S	$10		;Don't enable foreground if disabled
	BCLR	#7,P8259+2	;Enable foreground interrupts
$10	RTS
	

;	Load a 68000 object program
LB_LOAD LEA	22.(A0),A0	;Move parameters to stack
	MOVE.W	-(A0),D0	;Get high LBN word
	MOVE.L	-(A0),-(A7)	;This is start address
	MOVE.W	D0,-(A7)	;Store high LBN word
	MOVE.L	-(A0),-(A7)
	MOVE.L	-(A0),-(A7)
	MOVE.L	-(A0),-(A7)
	MOVE.L	-(A0),-(A7)
	MOVE.L	A0,-(A7)	;Save original A0
	LEA	4(A7),A0	;Set up argument address to stack
	MOVEQ	#11.,D0		;Set up Read of assembly code
	TRAP	#14.
	MOVE.W	2(A0),D0	;Check for an error
	BNE.S	$10		;Found a transfer error
	MOVE.L	18.(A0),36.(A7) ;Set new return address from starting addr
	LEA	26.(A7),A7	;Get rid of everything on stack
	RTS
	
;	Had Program load error
$10	MOVEA.L (A7)+,A0	;Restore original A0
	MOVE.W	D0,2(A0)	;Set up error code in original args
	LEA	22.(A7),A7	;Get rid of arguments on stack
	RTS			;Normal return from BIOS
	

;	Restore user hooks to defaults
LB_RHOK MOVE.L	A0,-(SP)
	LEA	BREAKDF,A0
	MOVE.L	A0,BREAKV	;Break vector
	MOVE.L	A0,EVENTA	;Event vector
	MOVE.L	A0,IOCONFA	;Configuration vector
	LEA	SPECCHDF,A0
	MOVE.L	A0,SPECCHAR	;Set up special character table
	ADDQ.L	#1,A0
	MOVE.L	A0,NOBREAKP	;No break flag pointer
	LEA	SIGNAL,A0	;Get rid of direct event routine
	MOVE.L	A0,SIGEVENT+2
	MOVEA.L (SP)+,A0
	RTS
	

;	Exit back to the Debugger
LB_DBUG MOVEQ	#13.-1,D1	;Delay about 1 second to let I/O settle
$10	MOVEQ	#-1,D0
$20	DBF	D0,$20
	DBF	D1,$10
	MOVE	#2700H,SR	;Disable interrupts
	MOVE.B	#38H,F8255-2	;Turn off floppies
	MOVE.B	#25H,TERM_C	;Turn on transmit
	CLR.B	BUGBIOS		;Disable BIOS I/O for Debugger
	MOVE.L	(A7)+,D0	;Restore register D0
	LEA	10.(A7),A7	;Bypass return status & address
	LJMP	DEBUG		;Return control to Debugger


;	Read system clock
LB_RCLK MOVEM.L D1-D2,-(A7)	;Save registers
	BSET	#7,P8259+2	;Disable foreground interrupts
	MOVE	SR,-(SP)
	BSR	RDREAL
	MOVE.L	D2,(A0)		;Save seconds
	MOVE.W	D1,4(A0)	;Save 1/64000 ths
	MOVE	(SP)+,CCR
	BNE.S	$10		;Don't enable foreground if disabled
	BCLR	#7,P8259+2	;Enable foreground interrupts
$10	MOVEM.L (A7)+,D1-D2	;Restore registers
	RTS

;	Read system clock in 1/60ths of a second
LB_RC60 MOVEM.L D1-D3,-(A7)	;Save registers
	BSET	#7,P8259+2	;Disable foreground interrupts
	MOVE	SR,-(SP)
	BSR	RDT60
	MOVE.L	D1,(A0)		;Save 1/60 ths second
	MOVE	(SP)+,CCR
	BNE.S	$10		;Don't enable foreground if disabled
	BCLR	#7,P8259+2	;Enable foreground interrupts
$10	MOVEM.L (A7)+,D1-D3	;Restore registers
	RTS


;	Initialize a channel
LB_ICHN MOVE.W	(A0),D0		;Get channel number
	BSR.S	GETCHAN		;Convert channel number
	MOVE.W	INTABLE(D0.W),D0 ;Get offset
	JMP	INTABLE(D0.W)	;Jump to routine (which will do return)

INTABLE .WORD	NOCHAN-INTABLE	; 0 System is not a device
	.WORD	INCHAN1-INTABLE ; 1 Keyboard input
	.WORD	INCHAN2-INTABLE ; 2 Terminal output
	.WORD	NOCHAN-INTABLE	; 3 Channel 3 is not equipped
	.WORD	INCHAN4-INTABLE ; 4 Floppy drive #0
	.WORD	INCHAN5-INTABLE ; 5 Floppy drive #1
	.WORD	INCHAN6-INTABLE ; 6 Printer
	.WORD	INCHAN7-INTABLE ; 7 Auxillary input channel
	.WORD	INCHAN8-INTABLE ; 8 Auxillary output channel
	.WORD	INCHAN9-INTABLE ; 9 Winchester disk
	.WORD	NOCHAN-INTABLE	;10 GPIB Network - temporarily disabled
	.WORD	INCHN11-INTABLE ;11 RAM disk
	.WORD	NOCHAN-INTABLE	;12 Channel 12 is not equipped
	.WORD	INCHN13-INTABLE ;13 Extra serial channel #1
	.WORD	INCHN14-INTABLE ;14 Extra serial channel #2
	.WORD	INCHN15-INTABLE ;15 Extra serial channel #3
	.WORD	INCHN16-INTABLE ;16 Extra serial channel #4

;	Following are User Channels
	.WORD	NOCHAN-INTABLE	;128
	.WORD	NOCHAN-INTABLE	;129
	.WORD	NOCHAN-INTABLE	;130
	.WORD	NOCHAN-INTABLE	;131


;	Read a channel
LB_RCHN MOVE.W	(A0),D0		;Get channel number
	BSR.S	GETCHAN		;Convert channel number
	MOVE.W	RDTABLE(D0.W),D0 ;Get offset
	JMP	RDTABLE(D0.W)	;Jump to routine (which will do return)

RDTABLE .WORD	NOCHAN-RDTABLE	; 0 System is not a device
	.WORD	RDCHAN1-RDTABLE ; 1 Keyboard input
	.WORD	BCHDIR-RDTABLE	; 2 Terminal output only
	.WORD	NOCHAN-RDTABLE	; 3 Channel 3 is not equipped
	.WORD	RDCHAN4-RDTABLE ; 4 Floppy drive #0
	.WORD	RDCHAN5-RDTABLE ; 5 Floppy drive #1
	.WORD	BCHDIR-RDTABLE	; 6 Printer only has output
	.WORD	RDCHAN7-RDTABLE ; 7 Auxillary input channel
	.WORD	BCHDIR-RDTABLE	; 8 Auxillary output only
	.WORD	RDCHAN9-RDTABLE ; 9 Winchester disk
	.WORD	NOCHAN-RDTABLE	;10 GPIB Network - temporarily disabled
	.WORD	RDCHN11-RDTABLE ;11 RAM disk
	.WORD	NOCHAN-RDTABLE	;12 Channel 12 is not equipped
	.WORD	RDCHN13-RDTABLE ;13 Extra serial channel #1
	.WORD	RDCHN14-RDTABLE ;14 Extra serial channel #2
	.WORD	RDCHN15-RDTABLE ;15 Extra serial channel #3
	.WORD	RDCHN16-RDTABLE ;16 Extra serial channel #4

;	Following are User Channels
	.WORD	RDCH128-RDTABLE ;128 Read device configurations
	.WORD	RDCH129-RDTABLE ;129 Read System Clock
	.WORD	RDCH130-RDTABLE ;130 Read from Memory
	.WORD	RDCH131-RDTABLE ;131


;	Process channel number
GETCHAN CLR.W	2(A0)		;Clear error code
	CMPI.W	#31.,D0
	BGT.S	$50		;Possibly user channel number
	MOVE.L	A1,-(SP)
	LEA	BIOSMAP,A1
	LSL.W	#1,D0
	ADDA.W	D0,A1
	MOVEQ	#0,D0
	MOVE.B	(A1)+,D0	;Get subdevice number
	SWAP	D0
	MOVE.B	(A1)+,D0	;Get main device number
	MOVEA.L (SP)+,A1
	CMPI.W	#CHANLIM,D0
	BGT.S	$100		;Too big
	BRA.S	$60
	
;	Channel number larger than normal devices
$50	CMPI.W	#128.,D0
	BLT.S	$100		;Not a User channel either
	CMPI.W	#USERLIM,D0
	BGT.S	$100		;Beyond User Channels
	SUBI.W	#128.-CHANLIM-1,D0 ;Form table address
$60	LSL.W	#1,D0		;Make word offset
	RTS

$100	ADDQ.L	#4,A7		;Get rid of return address
	BRA	NOCHAN		;Process as no channel


;	Write a channel
LB_WCHN MOVE.W	(A0),D0		;Get channel number
	BSR.S	GETCHAN		;Convert channel number
	MOVE.W	WTTABLE(D0.W),D0 ;Get offset
	JMP	WTTABLE(D0.W)	;Jump to routine (which will do return)

WTTABLE .WORD	NOCHAN-WTTABLE	; 0 System is not device
	.WORD	BCHDIR-WTTABLE	; 1 Keyboard input only
	.WORD	WTCHAN2-WTTABLE ; 2 Terminal output
	.WORD	NOCHAN-WTTABLE	; 3 Channel 3 is not equipped
	.WORD	WTCHAN4-WTTABLE ; 4 Floppy drive #0
	.WORD	WTCHAN5-WTTABLE ; 5 Floppy drive #1
	.WORD	WTCHAN6-WTTABLE ; 6 Printer output
	.WORD	BCHDIR-WTTABLE	; 7 Auxillary input only
	.WORD	WTCHAN8-WTTABLE ; 8 Auxillary output
	.WORD	WTCHAN9-WTTABLE ; 9 Winchester disk
	.WORD	NOCHAN-WTTABLE	;10 GPIB Network - temporarily disabled
	.WORD	WTCHN11-WTTABLE ;11 RAM disk
	.WORD	NOCHAN-WTTABLE	;12 Channel 12 is not equipped
	.WORD	WTCHN13-WTTABLE ;13 Extra serial channel #1
	.WORD	WTCHN14-WTTABLE ;14 Extra serial channel #2
	.WORD	WTCHN15-WTTABLE ;15 Extra serial channel #3
	.WORD	WTCHN16-WTTABLE ;16 Extra serial channel #4

;	Following are User Channels
	.WORD	WTCH128-WTTABLE ;128 Write device configurations
	.WORD	WTCH129-WTTABLE ;129 Set Time
	.WORD	WTCH130-WTTABLE ;130 Write to Memory
	.WORD	WTCH131-WTTABLE ;131 Set up scheduled event



;	Get Channel Status
LB_SCHN MOVE.W	(A0),D0		;Get channel number
	BSR.S	GETCHAN		;Convert channel number
	MOVE.W	STTABLE(D0.W),D0 ;Get offset
	MOVE.L	A1,-(A7)	;Save a register
	MOVEA.L 6(A0),A1	;Get address of status area
	JSR	STTABLE(D0.W)	;Jump to routine
	MOVEA.L (A7)+,A1	;Restore register
	RTS

STTABLE .WORD	NOCHAN-STTABLE	; 0 System is not a device
	.WORD	STCHAN1-STTABLE ; 1 Keyboard input
	.WORD	STCHAN2-STTABLE ; 2 Terminal output
	.WORD	NOCHAN-STTABLE	; 3 Channel 3 is not equipped
	.WORD	STCHAN4-STTABLE ; 4 Floppy drive #0
	.WORD	STCHAN5-STTABLE ; 5 Floppy drive #1
	.WORD	STCHAN6-STTABLE ; 6 Printer output
	.WORD	STCHAN7-STTABLE ; 7 Auxillary input channel
	.WORD	STCHAN8-STTABLE ; 8 Auxillary output channel
	.WORD	STCHAN9-STTABLE ; 9 Winchester disk
	.WORD	NOCHAN-STTABLE	;10 GPIB Network - temporarily disabled
	.WORD	STCHN11-STTABLE ;11 RAM disk
	.WORD	NOCHAN-STTABLE	;12 Channel 12 is not equipped
	.WORD	STCHN13-STTABLE ;13 Extra serial channel #1
	.WORD	STCHN14-STTABLE ;14 Extra serial channel #2
	.WORD	STCHN15-STTABLE ;15 Extra serial channel #3
	.WORD	STCHN16-STTABLE ;16 Extra serial channel #4

;	Following are User Channels
	.WORD	NOCHAN-STTABLE	;128
	.WORD	NOCHAN-STTABLE	;129
	.WORD	NOCHAN-STTABLE	;130
	.WORD	NOCHAN-STTABLE	;131


;	Process no channel defined
NOCHAN	MOVE.W	#-14.,2(A0)	;Set up error code for bad device number
	RTS

;	Process bad direction
BCHDIR	MOVE.W	#-15.,2(A0)	;Set up error code for illegal request
	RTS



;	Read Device configuration
RDCH128
	MOVE.W	14.(A0),D0
	BSR	GETCHAN
	CMPI.W	#CHANLIM*2,D0
	BGT.S	NO128		;Channel number too large
	MOVE.L	A1,-(A7)
	MOVEA.L 8(A0),A1	;Get buffer address
	MOVE.W	RCTABLE(D0.W),D0 ;Get offset
	JSR	RCTABLE(D0.W)	;Call routine
	MOVEA.L (A7)+,A1
	RTS
	
NO128	MOVE.W	#-14.,2(A0)
	RTS
	
;	Read configuration table
RCTABLE .WORD	RCFCH0-RCTABLE	; 0 System configuration
	.WORD	RCFCH1-RCTABLE	; 1 Keyboard input
	.WORD	RCFCH2-RCTABLE	; 2 Terminal output
	.WORD	NO128-RCTABLE	; 3 Channel 3 is not equipped
	.WORD	RCFCH4-RCTABLE	; 4 Floppy drive #0
	.WORD	RCFCH5-RCTABLE	; 5 Floppy drive #1
	.WORD	RCFCH6-RCTABLE	; 6 Printer
	.WORD	RCFCH7-RCTABLE	; 7 Remote input
	.WORD	RCFCH8-RCTABLE	; 8 Remote output
	.WORD	RCFCH9-RCTABLE	; 9 Winchester disk
	.WORD	NO128-RCTABLE	;10 GPIB Network
	.WORD	RCFCH11-RCTABLE ;11 RAM Disk
	.WORD	NO128-RCTABLE	;12 Channel 12 is not equipped
	.WORD	RCFCH13-RCTABLE ;13 Extra serial channel #1
	.WORD	RCFCH14-RCTABLE ;14 Extra serial channel #2
	.WORD	RCFCH15-RCTABLE ;15 Extra serial channel #3
	.WORD	RCFCH16-RCTABLE ;16 Extra serial channel #4
	
	
;	Write Device configuration
WTCH128
	MOVE.W	14.(A0),D0
	BSR	GETCHAN
	CMPI.W	#CHANLIM*2,D0
	BGT.S	NO128		;Channel number too large
	MOVE.L	A1,-(A7)
	MOVEA.L 8(A0),A1	;Get buffer address
	MOVE.W	WCTABLE(D0.W),D0 ;Get offset
	JSR	WCTABLE(D0.W)	;Call routine
	MOVEA.L (A7)+,A1
	RTS
	
;	Write configuration table
WCTABLE .WORD	WCFCH0-WCTABLE	; 0 System configuration
	.WORD	WCFCH1-WCTABLE	; 1 Keyboard input
	.WORD	WCFCH2-WCTABLE	; 2 Terminal output
	.WORD	NO128-WCTABLE	; 3 Channel 3 is not equipped
	.WORD	WCFCH4-WCTABLE	; 4 Floppy drive #0
	.WORD	WCFCH5-WCTABLE	; 5 Floppy drive #1
	.WORD	WCFCH6-WCTABLE	; 6 Printer
	.WORD	WCFCH7-WCTABLE	; 7 Remote input
	.WORD	WCFCH8-WCTABLE	; 8 Remote output
	.WORD	WCFCH9-WCTABLE	; 9 Winchester disk
	.WORD	NO128-WCTABLE	;10 GPIB Network
	.WORD	WCFCH11-WCTABLE ;11 RAM Disk
	.WORD	NO128-WCTABLE	;12 Channel 12 is not equipped
	.WORD	WCFCH13-WCTABLE ;13 Extra serial channel #1
	.WORD	WCFCH14-WCTABLE ;14 Extra serial channel #2
	.WORD	WCFCH15-WCTABLE ;15 Extra serial channel #3
	.WORD	WCFCH16-WCTABLE ;16 Extra serial channel #4


;	Read System configuration
RCFCH0
	MOVE.L	A0,-(SP)
	MOVE.W	12.(A0),D0	;Get block to isolate type of info
	BNE.S	$10		;Not time adjustment
	MOVE.W	TIMADJD,(A1)
	BRA.S	$200

$10	SUBQ.W	#1,D0
	BNE.S	$20		;Not BIOSMAP
	LEA	BIOSMAP,A0
	MOVEQ	#16-1,D0
$15	MOVE.L	(A0)+,(A1)+
	DBF	D0,$15
	BRA.S	$200

$20	SUBQ.W	#1,D0
	BNE.S	$30		;Not OPSYS
	LEA	OPSYS,A0
	MOVEQ	#8-1,D0
	BRA	$15
	
$30	SUBQ.W	#1,D0
	BNE.S	$40		;Not SAGE IV status

;	Block number 3 - SAGE IV status
	MOVEQ	#0,D0
	MOVE.B	SAGE4,D0
	MOVE.W	D0,(A1)
	BRA.S	$200
	
$40	SUBQ.W	#1,D0
	BNE.S	$50		;Not Version number
	
;	Block number 4 - BIOS Version number
	MOVE.W	VERSION,(A1)
	BRA.S	$200
	
$50	SUBQ.W	#1,D0
	BNE.S	$60		;Not Device Info
	
;	Block number 5 - Device Information Table
	LEA	DEVINFO,A0
	MOVEQ	#8-1,D0
	BRA	$15
	
$60	SUBQ.W	#1,D0
	BNE.S	$200		;Now Winchester Device Info
	
;	Block number 6 - Winchester Device Information Table
	LEA	WDEVINFO,A0
	MOVEQ	#32.-1,D0
	BRA	$15
	
$200	MOVEA.L (SP)+,A0
	RTS
	
;	Write System configuration
WCFCH0
	MOVE.L	A0,-(SP)
	MOVE.W	12.(A0),D0	;Get block to isolate type of info
	BNE.S	$10		;Not time adjustment

;	Block number 0
	MOVE.W	(A1),TIMADJD
	BRA.S	$200

$10	SUBQ.W	#1,D0
	BNE.S	$20		;Not BIOSMAP

;	Block number 1 - BIOSMAP
	LEA	BIOSMAP,A0
	MOVEQ	#16-1,D0
$15	MOVE.L	(A1)+,(A0)+
	DBF	D0,$15
	BSR	INSTALLTP	;Install traps
	BRA.S	$200

$20	SUBQ.W	#1,D0
	BNE.S	$30		;Not OPSYS

;	Block number 2 - Operating System Data
	LEA	OPSYS,A0
	MOVEQ	#8-1,D0
	BRA	$15
	
$30	SUBQ.W	#3,D0
	BNE.S	$40		;Not Device Info
	
;	Block number 5 - Device Info
	LEA	DEVINFO,A0
	MOVEQ	#8-1,D0
	BRA	$15
	
$40	SUBQ.W	#1,D0
	BNE.S	$200		;Now Winchester Device Info
	
;	Block number 6 - Winchester Device Info
	LEA	WDEVINFO,A0
	MOVEQ	#32.-1,D0
	BRA	$15
	
$200	MOVEA.L (SP)+,A0
	RTS
	


;	Read System Clock
RDCH129
	MOVEM.L D1-D3/A0,-(A7)
	MOVE.W	14.(A0),D3	;Get Control word
	MOVEA.L 8(A0),A0	;Buffer address
	CMPI.W	#1,D3
	BHI.S	$20		;Bias or system clock when set
	BEQ.S	$30		;Read Real Time
	BSR	LB_RCLK		;Read the System Clock
$10	MOVEM.L (A7)+,D1-D3/A0
	RTS
	
$20	CMPI.W	#2,D3
	BHI.S	$25		;Return system clock when time set
	MOVE.L	TIMBIAS,(A0)	;Just get Time Bias
	BRA	$10

$25	MOVE.L	TIMLAST,(A0)	;System clock when time set
	BRA	$10

$30	MOVE.L	A0,-(A7)
	SUBQ.L	#6,A7
	MOVEA.L A7,A0
	BSR	LB_RCLK		;Get the System Clock
	MOVE.L	(A0),D3
	ADDQ.L	#6,A7
	MOVEA.L (A7)+,A0
	SUB.L	TIMLAST,D3	;Find time change
	TST.B	TIMADJD		;Check if any time adjustment factor
	BEQ.S	$40		;No adjustment
	SWAP	D3
	MOVE.W	D3,D1		;Calculate number of days
	DIVU	#120.,D1
	MOVE.W	D3,D2
	MULU	#3,D2
	DIVU	#4,D2
	ADD.W	D2,D1		;Number of days
	MOVE.B	TIMADJS,D2	;Seconds per x days adjustment
	EXT.W	D2
	MULS	D2,D1
	MOVEQ	#0,D2
	MOVE.B	TIMADJD,D2	;x days
	DIVS	D2,D1		;Number of seconds adjustment
	EXT.L	D1
	SWAP	D3
	ADD.L	D1,D3		;Make final adjustment
$40	ADD.L	TIMBIAS,D3	;Add in the Time Bias
	MOVE.L	D3,(A0)
	BRA	$10

;	Set System Clock (Time Bias)
WTCH129 MOVE.L	A0,-(A7)
	MOVEA.L 8(A0),A0	;Buffer address
	MOVE.L	(A0),TIMBIAS	;Save the time set value
	SUBQ.L	#6,A7		;Make room on stack
	MOVEA.L A7,A0
	BSR	LB_RCLK		;Get system clock
	MOVE.L	(A0),TIMLAST	;Save system clock when set
	ADDQ.L	#6,A7		;Remove args from stack
	MOVEA.L (A7)+,A0
	RTS


;	Routine to Disable SAGE 4 channels on a SAGE II
NOSAGE4
	LEA	INTABLE,A0
	MOVE.W	#NOCHAN-INTABLE,D0
	BSR	DISSAGE4
	LEA	RDTABLE,A0
	MOVE.W	#NOCHAN-RDTABLE,D0
	BSR	DISSAGE4
	LEA	WTTABLE,A0
	MOVE.W	#NOCHAN-WTTABLE,D0
	BSR	DISSAGE4
	LEA	STTABLE,A0
	MOVE.W	#NOCHAN-STTABLE,D0
	BSR	DISSAGE4
	LEA	RCTABLE,A0
	MOVE.W	#NO128-RCTABLE,D0
	BSR	DISSAGE4
	LEA	WCTABLE,A0
	MOVE.W	#NO128-WCTABLE,D0
	BSR	DISSAGE4
	RTS
	
;	Disable SAGE 4 devices
DISSAGE4
	MOVE.W	D0,18.(A0)	;Disable Winchester
	MOVE.W	D0,26.(A0)	;Disable Extra Serial Channel 1
	MOVE.W	D0,28.(A0)	;Disable Extra Serial Channel 2
	MOVE.W	D0,30.(A0)	;Disable Extra Serial Channel 3
	MOVE.W	D0,32.(A0)	;Disable Extra Serial Channel 4
	RTS
	
	
;	Install TRAP vector
LB_PTRP
	MOVE.L	A1,-(SP)
	MOVEA.L D1,A1
	MOVE.L	A0,(A1)
	MOVEA.L (SP)+,A1
	RTS
	
;	Get TRAP vector
LB_GTRP
	MOVE.L	A1,-(SP)
	MOVEA.L D1,A1
	MOVEA.L (A1),A0
	MOVEA.L (SP)+,A1
	RTS
	
;	Get Physical Device & DEVINFO word from logical device
LB_PHYD
	MOVE.L	A0,-(SP)
	LSL.W	#1,D1
	LEA	BIOSMAP,A0
	MOVE.W	0(A0,D1.W),D2
	MOVE.W	D2,D1
	ANDI.W	#0FFH,D1
	CMPI.W	#9,D1
	BEQ.S	$10		;Found Winchester
	SUBQ.W	#1,D1
	LSL.W	#1,D1
	LEA	DEVINFO,A0
$5	MOVE.W	0(A0,D1.W),D1
	MOVEA.L (SP)+,A0
	RTS
	
;	Handle Winchester table
$10	MOVE.W	D2,D1
	LSR.W	#7,D1
	LEA	WDEVINFO,A0
	BRA	$5
	
;	Get operating system data address
LB_GOPS
	LEA	OPSYS,A0
	RTS
	
	
;	Set up direct Event routine address
LB_SETE
	MOVE.L	A0,SIGEVENT+2
	RTS
	
;	Clear the direct Event routine address
LB_CLRE
	PEA	SIGNAL
	MOVE.L	(SP)+,SIGEVENT+2
	RTS
	
                                                                                                                                                                                                                                                                                                                                                        