;BOOT.ASM  VERSION 2.02  REV 0   12/07/77

;
; IMDOS BOOTSTRAP ROUTINE
;

;8/26 - REWRITE FOR MULTIPLE (UP TO 18) DRIVES
;    1. ADD PARAMETER BLOCK LOCS 4B-72
;    2. # DIO'S PASSED TO BIOS IN D
;    3. PRESERVE TABLE ON WARM BOOT, POINTER PASSED @ LOC 1
;    4. BOOTDISK IS SET BY BOOT:
;          0 IF FROM IFM
;          4 IF FROM DIO SINGLE OR DUAL DENSITY
;          8 IF FROM DIO MINI
;    5. SIO INIT TAKES PLACE:
;          ONLY ON COLD BOOT
;          BEFORE SYSTEM IS READ IN
;    6. MEMORY INIT MOVED TO CCP
;    7. IF NO DISK IN DIO DRIVE 0, WILL BOOT IFM
;	IF DIO HAS BEEN INITIALIZED

;THIS PROGRAM RESIDES ON TRACK 0, SECTOR 1 AND 2 OF
;ALL IMDOS SYSTEM DISKS AND IS READ INTO RAM AT
;LOCATION 0 AND EXECUTED FOR BOTH COLD AND WARM
;START BOOTSTRAPS.

; COPYRIGHT (C) 1976, 1977
;	IMSAI MANUFACTURING CORP.
;	14860 WICKS BLVD, SAN LEANDRO, CA  94577, USA

	;PAGE

; *******************************************************
;
;	SYSTEM SIZE AND LOCATION EQUATES
;
	;MEMTOP, EMS, AND BIOSLEN ARE THE INDEPENDENT 
	;VARIABLES FROM WHICH A NUMBER OF OTHER QUANTITIES
	;ARE DERIVED. USERS WHO REASSEMBLE BOOT MUST
	;USUALLY CHANGE ONE OR MORE OF THESE.
	;"MEMTOP" AND "EMS" MUST BE SET TO MATCH MEMORY
	;SIZE AND NUMBER OF "M" OPTIONS GIVEN WHEN THE
	;SYSTEM INTO WHICH THE MODIFIED BOOT IS TO BE
	;INCORPORATED WAS RELOCATED WITH THE "RELOC" COMMAND.
	;VALUES IN FILE ON DISTRIBUTION DISKETTE
	;ARE FOR 16K SYSTEM WITH NO "M" OPTIONS (IE NO
	;EXTRA "MOUNT SPACE").
	;"BIOSLEN" MUST BE INCREASED IF "BIOS" IS MODIFIED
	;AND BECOMES LONGER THAN VALUE OF BIOSLEN.

MEMTOP	EQU 4000H
		;TOP OF MEMORY FOR WHICH THE SYSTEM HAS
		;BEEN RELOCATED WITH THE "RELOC" COMMAND.
		;EXAMPLES: MAKE MEMTOP 6000H FOR 24K,
		;8000H FOR 32K, 0E000H FOR 60K, 0 FOR 64K.

EMS	EQU 0
		;NUMBER OF "M" OPTIONS GIVEN IN "RELOC"
		;COMMAND.  EACH "M" ADDS 100H BYTES FOR
		;MOUNT SPACE AND/OR BIOS EXPANSION.
		;EXAMPLE VALUES: 1, 2.

BIOSLEN	EQU 200H
		;MAXIMUM LENGTH OF BIOS.  INCREASE
		;IF BIOS ADDITIONS MAKE IT LONGER THAN 
		;CURRENT VALUE.  SHOULD BE EVEN 100H.
		;IF NOT BIG ENOUGH, NOT ALL OF BIOS WILL
		;BE WRITTEN BY SYSGEN OR LOADED BY BOOT.
		;CAUTION: WHEN INCREASING BIOSLEN, ALSO
		;ADD TO "EMS" OR REDUCE "MEMTOP", SO
		;THAT THERE IS AT LEAST 100H BYTES OF 
		;PHYSICAL MEMORY ABOVE AREA LOADED BY
		;"BOOT" (IE ABOVE "SYSTOP" AS EQUATED
		;ON NEXT PAGE).
		;EXAMPLE VALUE: 300H.

	;PAGE

;ADDITIONAL SYSTEM LOCATION EQUATES, DERIVED FROM
;	MEMTOP, EMS, AND BIOSLEN.
;
; THESE NORMALLY SHOULD NOT BE ALTERED.

SYSBOTTOM  EQU  MEMTOP - 1800H - 100H*(EMS+1)
	;LOWEST ADDRESS OF SYSTEM: MEMORY TOP, LESS
	;LENGTH OF SYSTEM CODE, LESS MOUNT SPACE.

BIOS	EQU	SYSBOTTOM+1600H
	;LOCATION OF BASIC I/O SYSTEM

SYSTOP	EQU	BIOS+BIOSLEN
	;HIGHEST ADDRESS, +1, OF AREA LOADED WHEN SYSTEM
	;IS BOOTED OFF DISK.  NOTE THAT SYSTOP INCREASES
	;IF BIOS IS LENGTHENED.  NOTE THAT THERE MUST
	;BE AT LEAST 100H BYTES OF PHYSICAL MEMORY ABOVE
	;SYSTOP FOR "PRESERVE TABLE" TRANSMISSION DURING
	;WARM BOOT, AND THERE MUST BE A SUITABLE
	;AMOUNT OF SPACE FOR MOUNT SPACE BETWEEN THE
	;ACTUAL END OF CODE IN BIOS (THIS CAN BE LESS
	;THAN SYSTOP) AND THE ACTUAL END OF REAL MEMORY
	;(WHICH CAN BE GREATER THAN MEMTOP).

PRESERVE  EQU SYSTOP	;WHERE BOOT SAVES "PRESERVE TABLE"

BOOTR	EQU  BIOS+0	;WHERE BOOT EXITS TO

;LOCATIONS IN SYSTEM PARAMETERS AREA
BOOTDISK EQU  0		;WHERE BOOT PASSES DRIVE NUMBER
			;OF DISK BOOTED FROM TO BDOS
OLDTABLE EQU  1		;LOCATION WHERE BOOT RECIEVES
			;POINTER TO TABLE TO PRESERVE
IOBYTE	 EQU  3		;LOCATION OF IO STATUS BYTE
LOGDISK	 EQU  4		;LOC OF CCP'S CURRENT LOGGED DISK
	;PAGE
;
; SYSTEM DISK LAYOUT EQUATES
;
FTRK	EQU  0		;FIRST TRACK TO READ
NSECTB4SYSTEM EQU 2	;NUMBER OF SECTORS TO SKIP
			;BEFORE READING SYSTEM
;
; I/O DEVICE EQUATES
;
DISK	EQU  0FDH	;IFM FLOPPY DISK INTRFC PORT
;
;"DIO" FLOPPY DISK INTERFACE FIRMWARE:
DIOBASE	EQU	0E000H	     ;LOCATION OF DIO
DIOADR	EQU	DIOBASE+6    ;CALL ADDR, REG DISKS
DIOMINIADR EQU	DIOBASE+9    ;CALL ADDR, MINIFLOPPIES
DIOTSTADR EQU	DIOBASE+7FDH ;ADDRESS FOR PRESENCE TEST
DIOTST	EQU	'D'	     ;TEST FOR THIS IN ROM
DIOPORT1 EQU	0DEH	     ;PRIMARY DIO
DIOPORT2 EQU	0EEH	     ;SECONDARY
;
;SPTR	EQU	0	;DISK COMMAND STRING POINTER #
	;INCORPORATED IN CODE IN A NON-SYMBOLIC MANNER
;
;EQUATES FOR IMSAI "SIO" DUAL SERIAL INTERFACE BOARD,
; ALSO WORK FOR IMSAI "MIO" (ONE PORT ONLY, SERIAL
; OR PARALLEL DEPENDING ON BOARD CONFIGURATION),
; AND FOR SUITABLY JUMPERED "MPU-B" (BOTH SERIAL
; AND PARALLEL PORTS CAN BE ACCESSED)
SIOBD	EQU  0		;BASE PORT # OF SIO BOARD
SIOS1	EQU  SIOBD+3	;STATUS PORT
SIOS2	EQU  SIOBD+5	;OTHER STATUS PORT
SIOC	EQU  SIOBD+8	;CONTROL PORT FOR SIO BOARD
			;IGNORED BY OTHER INTERFACES
SIOCNTL EQU  22H	;COMMAND TO TURN OFF INTERUPTS
			;AND TURN ON CARRIER DETECT
			;FOR SIO, IGNORED BY OTHER
			;INTERFACES
;
; IMSAI "VIO" VIDEO INTERFACE
VIOTSTADR EQU	0FFFDH	;PRESENCE TEST ADDRESS
VIOTST	EQU	'V'	;CONTENTS IN ROM
VIOINIT EQU	0F800H	;INITIALIZE FIRMWARE CALL ADDR
;
; ASSEMBLY OPTION
;
SIOINIT	EQU	-1	;0 TO OMIT CODE TO INITIALIZE
			;IMSAI "SIO" SERIAL INTERFACE
			;"SIO" INITIALIZATION CODE IS NOT
			;NEEDED FOR OTHER INTERFACES, BUT
			;DOES NO HARM.
	;PAGE
;
;     THE BOOTSTRAP PORTION OF THIS PROGRAM READS
;EVERY "SKEW"TH SECTOR ON ONE DISK REVOLUTION FOR SPEED,
;BECAUSE IMSAI "IFM" DISK INTERFACE WILL NOT READ
;ADJACENT SECTORS WITHOUT DROPPING A REVOLUTION,
;INTO APPROPRIATE MEMORY LOCATIONS.  DISC CONTAINS
;DIRECT MEMORY IMAGE.
;	TO MAKE ITS ADDRESS INCREMENTING SCHEME WORK,
;THE PROGRAM MUST LOOP OVER AN INTEGRAL NUMBER OF TRACKS.
;	HOWEVER, THE PROGRAM DOES NO IO FOR SECTORS
;CORRESPONDING TO MEMORY ADDRESSES BELOW "FSTRDMA"
;OR ABOVE "LSTDMA".
;	THE ADDRESSES INTO WHICH THE SYSTEM IS LOADED
; ARE CHANGED FOR OTHER MEMORY SIZES AS FOLLOWS:
;	1) IF UNMODIFIED SYSTEM IS RELOCATED WITH "RELOC"
;	   CONSOLE COMMAND, THE RELEVANT CODE IS
;	   AUTOMATICALLY CHANGED.
;	2) IF USER MODIFIES "BOOT", HE MUST CHANGE THE
;	   EQUATES ON PAGE 2, AS EXPLAINED BY
;	   COMMENTS THERE, TO MATCH THE SYSTEM INTO
;	   WHICH THE MODIFIED BOOT WILL BE INSTALLED.
;NOTE: THE CODE TO WHICH THESE COMMENTS APPLY, AND
; WHICH USES THE FOLLOWING ASSEMBLY PARAMETERS,
; IS ON PAGE 11 OF THIS LISTING.

FSTDMA	EQU  SYSBOTTOM-NSECTB4SYSTEM*128
		;WHERE 1ST SECTOR WOULD BE READ
		;IF IT WERE TO BE READ - BUT IT ISN'T
		;READ BY MAIN LOOP OF BOOT BECAUSE
		;IT CONTAINS PART OF BOOT, NOT PART
		;OF THE REST OF THE SYSTEM.
FSTRDMA EQU SYSBOTTOM	;FIRST LOCATION TO REALLY READ
		;ASSUMED TO BE EVEN 100H BY CODE BELOW
LSTDMA  EQU  SYSTOP	;FIRST LOCATION NOT READ
			;ASSUMED TO BE EVEN 100 BELOW.
SKEW	EQU  5		;READ EVERY 5TH SECTOR.
	;"SKEW" MUST HAVE NO COMMON FACTORS WITH THE
	;NUMBER OF SECTORS PER TRACK FOR ANY OF THE
	;DISK TYPES USED.
	;PAGE

; *******************************************************
;
;EXECUTABLE CODE BEGINS HERE

	ORG	0
;
; ENTRY POINTS: 0 FOR COLD BOOT, 3 FOR WARM REBOOT
;
	LXI B,0FFFFH  ;COLD START ENTRY FOR HARDWARE BOOT
	   ;NOTE: ON WARM BOOT BIOS STORES LOCATION OF
	   ;PRESERVE TABLE INTO LOCATIONS 1 AND 2 BEFORE
	   ;JMP'ING TO 3.  FF'S REMAINING IN 1,2 INDICATE
	   ;NO PRESERVE TABLE TRANSMITTED (COLD BOOT,
	   ;OR CROSS-BOOT FROM OLD CPM VERSION).

	ORG	3
	   ;WARM BOOT ENTRY: BIOS READS THIS PROG
	   ;FROM TK 0, SCTR 1, THEN JMPS HERE WITH
	   ;CURRENT LOGGED DISK IN C, IOBYTE IN B.

	MOV H,C! MOV L,B! SHLD IOBYTE	;RESTORE IOBYTE
			;AND LOGDISK ON WARM BOOT, STORE
			;HARMLESS GARBAGE ON COLD BOOT.

	   ;NOW "FALL IN TO" RST-1 SUBROUTINE. NOTE THAT
	   ;STACK IS INITIALIZED WITH APPROPRIATE RETURN.
;
; SUBROUTINES ACCESSED BY RST-1 THROUGH RST-5
;

	ORG	8H
; SUBROUTINE TO SEE IF DIO IS THERE
; STACK POINTER MUST BE SET TO STACK+2 BEFORE USING
; RST 1 TO CALL. NOTE THAT FALL THROUGH HAS JUST THE
; RIGHT VALUE AT STACK TO "RETURN" TO CONTINUATION POINT
	LXI SP,STACK	;INIT STACK
	LXI H,DIOTSTADR	;LOCATION TO TEST
	MVI A,DIOTST	;VALUE

	ORG	10H
; SUBROUTINE TO CHECK FOR VALUE IN ACC @HL IN ROM
; RETURNS B= 00 IF THERE IN ROM, Z-BIT SET ACCORDINGLY
; ACC IS DESTROYED.  USE RST 2 TO CALL
	MOV B,M		;SAVE MEMORY VALUE
	CMA! MOV M,A	;TRY TO COMPLEMENT MEMORY
	XRA M		;IF PROPER VALUE IN ROM,
			;ACC IS NOW 0FFH
	MOV M,B		;RESTORE MEMORY IN CASE RAM
	MOV B,A		;PUT FLAG IN B
	INR B		;TEST & SET TO ZERO IF TRUE
	RET
	;PAGE

;BOOTSTRAP RST SUBROUTINES CONTINUED

	ORG	18H
; SUBROUTINE TO OUTPUT ACC TO DISK. USE RST 3 TO CALL.

	INR B		;IF B IS ZERO ON ENTRY, USE IFM
	DCR B		;RESTORE & TEST
	JZ OUTDISK	;BR TO DISK DEPENDENT SECTION
	OUT DISK	;SEND TO IFM
	RET


	ORG	20H
; SUBROUTINE TO SET STRING POINTER AND FALL THRU
; FOR 1ST DISK READ. CALL WITH RST 4

RST4:	MVI A,10H! RST 3
	MVI A,BCMD AND 0FFH! RST 3
	XRA A
RREAD:	RST 3	;SET POINTER TO 40H AND FALL THROUGH


	ORG	28H
; SUBROUTINE TO READ SECTOR
;  CLOBBERS HL, A.  REPEATS ERRORS FOREVER
; USE RST 5 TO CALL
; RETURNS WITH CARRY SET WHEN DONE,
;   ELSE CY CLEAR IF DRIVE NOT READY

RDSCT:	LXI H,BSTAT	;POINT AT STATUS BYTE
	XRA A		;GET A ZERO
	MOV M,A		;ZERO COMMAND STRING STATUS
	;0 IS DISK COMMAND TO EXECUTE POINTER 0
	RST 3		;OUTPUT COMMAND TO DISK
WAIT:	XRA A! SUB M	;SET CARRY, -STAT->ACC IF DONE
	JZ  WAIT	;..
	DCR M		;TEST STATUS FOR 1
	RZ		;RETURN WITH CARRY SET IF OK
; MUST BE ERROR, PUT CODE IN THE LIGHTS
	DCR A		;CMPLEMENT STATUS->ACC
	OUT 0FFH
; IF NOT READY ERROR (0A1H), RETURN WITH CARRY  AND ACC CLEAR
	SUI 5EH		;0A1H COMPLEMENTED
	RZ
;RESTORE DRIVE - IT HELPS
	MVI A,21H	;COMMAND TO RESTORE DRIVE 0
	JMP RREAD		;DO IT AGAIN
;	PAGE

	ORG	40H
;
; COMMAND STRING FOR DISK INTERFACE, PRE-INITIALIZED
;  TO READ THE SECTOR THAT CONTAINS REST OF BOOT
;
BCMD:	DB 21H		;READ, UNIT 0
BSTAT:	DB 0		;STATUS
BTRK:	DB 0,FTRK	;TRACK 0
BSECT:	DB 2		;SECTOR
BBUFAD: DW 80H		;RAM BUFFER ADDRESS

; ************* DISK DEPENDENT STUFF FROM HERE TO "STACK"

;	VALUES SHOWN ARE TYPICAL. ACTUAL VALUES FOR THE
;	DISK ON WHICH THE SYSTEM RESIDES ARE INSERTED BY
;	"SYSGEN" WHEN SYSTEM IS WRITTEN ON DISK.
;	THUS, BE SURE TO KEEP FOLLOWING AT SAME ADDRESSES

DISKN:	DB	4	;DIO BOOT DISK #, 4=REG, 8=MINI
OUTDISK:JMP DIOADR	;JMP DIOMINIADR FOR MINI

; PROTOTYPE VOLUME CONTROL BLOCK
;    ACTUAL VCB IS PUT ONTO DISK WITH "FORMAT" AND
;    INSERTED INTO SYSTEM IMAGE AT THIS POINT BY "SYSGEN".

P$CRC:	DB    68H    ;DATA CHECK BYTE
P$NAM:	DB 'DIANE  ' ;VOLUME NAME
P$FLG:	DB    1      ;FLAG, BIT 0 ON => NEW SYSTEM
P$NHD:	DB    1      ;NUMBER HEADS/DISK
P$NTK:	DW    77     ;NUMBER TRACKS/SURFACE
P$NSC:	DW    26     ;NUMBER SECTORS/TRACK
P$SKW:	DB    6      ;SKEW FOR SECTOR TRANSLATE TABLE
P$ADD:	DB    13     ;P$NSC/ GCD OF P$NSC & P$SKW
P$SYS:	DW    52     ;NUMBER OF SCTRS RESERVED FOR SYSTEM
P$UNU:	DW 0,0,0,0,0,0,0   ;UNUSED
P$DOF:	DW    0      ;OFFSET IN FILE AREA OF DIRECTORY
P$DLN:	DW    64     ;# DIRECTORY ENTRIES
P$MSK:	DB    07H    ;MASK FOR SECTOR WITHIN ALLOC UNIT
P$SFT:	DB    3      ;# BITS TO SHIFT
P$SIZ:	DW  243      ;NUMBER ALLOCATION UNITS ON THE DISK

; ************** END DISK DEPENDENT STUFF

STACK:	DW	CONTINUE ;SET SO FIRST RETURN BRANCHES 
			 ;AROUND SUBROUTINES & DISK
			 ; DEPENDANT STUFF
	;PAGE

;*********************************************************
;
; READ SECOND SECTOR OF BOOT
;
;
;AFTER ENTRY AND EXECTION OF RST-1 SUBROUTINE TO SET B=0
;IF DIO IS PRESENT, CONTROL COMES TO "CONTINUE", WHICH READS
;THE SECOND SECTOR OF "BOOT", FROM DIO (MINI OR REGULAR
;DEPENDING ON "OUTDISK" (PREVIOUS PAGE)) IF B=0, OR FROM
;IFM IF B<>0.  IF DIO IS NOT READY, CONTROL TRANSFERS TO
;"NOTDIO" TO READ FROM IFM.  "NOT READY" ERROR ON IFM IS
;RETRIED FOREVER.

NOTDIO:	MOV B,L		;SET B NZ TO SWITCH TO IFM
	XRA A
	STA DISKN	;SET BOOT DISK TO ZERO FOR BDOS


; CONTINUE PROCESSING HERE FROM ENTRY AT 0000 OR 0003
; THERE ARE 3 CASES:
;	1. BOOTING OFF DIO - THE DIO WILL BE INSTALLED
;	   AND THE Z-BIT SET.  WE CALL THE ROUTINE AT
;	   RST 4 IMMEDIATELY.
;	2. BOOTING OFF FIF, DIO NOT INSTALLED - THE
;	   Z-BIT WILL BE CLEAR, WE DO NOT CALL THE
;	   RST 4 ROUTINE UNTIL "DISKN" HAS BEEN ZEROED.
;	3. BOOTING OFF FIF, DIO INSTALLED - THE Z-BIT
;	   WILL BE SET AND THE RST 4 CALL MUST PRODUCE
;	   A NO CARRY RETURN IN ORDER TO SET THE B REG
;	   FLAG AND CLEAR THE BOOT DISK.


CONTINUE:
	CZ RST4		;TRY TO READ SECOND SECTOR IF DIO
			;PRESENT OR SECOND TIME THROUGH
	JNC NOTDIO	;BRIF DRIVE NOT READY


;EVERYTHING ABOVE HERE MUST FIT ABOVE 80H, AS IT
;IS NEEDED TO READ IN REST OF THIS PROGRAM.
;(THE FIRST SECTOR OF BOOT IS READ BY EXTERNAL MEANS.)

;****************************************************
	;PAGE

;
;	INIT BOTH CHANNELS OF IMSAI
;	SERIAL INTERFACE BOARD
;
; PUT HERE TO ALLOW OPERATOR TO HIT SPACE BAR ON CONSOLE
; DEVICE WITHOUT HAVING TO WAIT FOR SYSTEM TO READ IN
;
	PUSH B		;SAVE WARM/COLD FLAG

	IF SIOINIT
	INR C		;TEST FOR COLD START
	CZ DOSIO	;INIT ON COLD START ONLY

; **** FOLLOWING STRING IS CHANGED WITH CARE.
; **** IT'S PROPERTIES ARE:
; ****	 IT EXECUTES LIKE NOPS (AE=XRA M,37=STC,40=MOV B,B)
; ****	 ALL BYTES ARE EVEN EXCEPT THE LAST

	DB 0AEH,040H,0AEH,037H
	ENDIF


; MOVE PRESERVE TABLE.  THE "PRESERVE TABLE" IS A TABLE
; IN BDOS OF INFORMATION SUCH AS DISK ASSIGNMENTS
; WHICH MUST BE PRESERVED THRU A WARM BOOT.  AT THIS
; POINT WE MOVE IT TO MEMORY JUST ABOVE WHERE THE SYSTEM
; IS TO BE LOADED.  IT MUST BE MOVED FOR TWO REASONS:
;  1) IT IS IN THE MIDDLE OF THE AREA TO BE LOADED
;  FROM DISK; 2) LOCATION IN SYSTEM BEING BOOTED MAY BE
;  DIFFERENT DUE TO DIFFERENT SIZE SYSTEMS OR DIFFERENT
;  VERSION SYSTEMS.
; IF THIS IS A WARM BOOT AND THERE IS A PRESERVE TABLE TO
; PRESERVE, BDOS WILL HAVE STORED ITS LOCATION AT 1,2
; BEFORE STARTING BOOT. IF THAT DIDN'T HAPPEN, THE FOLLOWING
; LOOP MOVES GARBAGE, WHICH DOES NO HARM.
; LATER (IN BDOS IN THE NEWLY LOADED SYSTEM) THIS TABLE
; WILL BE COPIED BACK INTO THE NEW SYSTEM IF LOCATIONS
; 1 & 2 ARE NOT 'FFFF'.

	LXI	D,PRESERVE ;WHERE TO STASH TABLE DURING BOOT
	LHLD	OLDTABLE   ;GET POINTER TRANSMITTED BY BDOS
	MOV	C,M	   ;GET LENGTH FROM TABLE BYTE 0
WSAVE:	MOV	A,M	   ;DO THE MOVE
	STAX	D
	INX	H
	INX	D
	DCR	C
	JNZ	WSAVE

	;PAGE

;*******************************************************
;
; ROUTINE TO READ SYSTEM IMAGE, WITH "SKEWED"
; ADDRESS INCREMENT AND MULTIPLE PASSES OVER EACH TRACK
; REGISTER USE:
;	B	ZERO IF DIO IS THERE
;	C	UNUSED
;	D	HIGH ORDER RAM ADDRESS OF TRACK START
;	A,L	SECTOR NUMBER
;	E	TEMP
;
	MVI D,FSTDMA SHR 8 AND 0FFH

;TOP OF TRACKS LOOP
R0:	MOV A,M		;KLUDGE TO MAKE SUB M PRODUCE ZERO

;LOOP FOR ANOTHER PASS THROUGH THIS TRACK
R1:	SUB M		;SUBTRACT #SCTRS/TRACK OR GET ZERO

;TOP OF READ SECTORS LOOP
R2:	MOV L,A		;SAVE SECTOR NUMBER
	RRC		;CONVERT TO RAM ADDRESS
	ANI 80H		;LO ORDER IS 80 OR 00
	MOV H,A		;LO ORDER ADDR -> H
	MOV A,L		;RESTORE SECTOR NUMBER
	RAR		;CONVERT TO RAM ADDRESS
	ADD D		;ADD ADDRESS OF TRACK START
	STA BBUFAD+1	;HI ORDER ADDR -> DISK CMD STRING
	INR L		;GET ACTUAL SECTOR NUMBER
	SHLD BSECT	;SECTOR, LO ORDER ADR -> CMD STRING
	MOV E,L		;RDSCT CLOBBERS HL

;READ SECTOR UNLESS RAM ADDRESS OUT OF RANGE TO READ
	SUI FSTRDMA SHR 8 AND 0FFH
	JC NO		;JIF ADDRESS TOO LO
	SUI (LSTDMA-FSTRDMA) SHR 8 AND 0FFH
	CC RDSCT	;READ UNLESS ADDR TOO HI

;COME HERE TO SKIP READ
;CALCULATE NEXT SECTOR TO READ
NO:	MOV A,E		;RESTORE SECTOR
	ADI SKEW-1	;NEXT SECTOR
	LXI H,P$NSC	;POINT # SECTORS/TRACK
	CMP M! JM R2	;BRIF WITHIN TRACK
	JNZ R1		;MAKE ANOTHER PASS THROUGH TRACK

;NEXT TRACK
	MVI L,BTRK+1	;CHANGE PTR TO TRACK NUMBER
	INR M		;NEXT TRACK
	RRC		;# SECTORS PER TRACK/2 -> ACC
	ADD D		;RAM ADDRESS OF NEXT TRACK
	MOV D,A
	JNC R0		;LOOP UNLESS WE WRAPPED MEMORY
;PAGE
;****************************************************
;
; SYSTEM INITIALIZATION
;     AS MUCH AS FITS, CONTINUED IN BIOS.
;

; GET # DIO'S (0,1,2) &
; DRIVE NUMBER OF BOOT DISK (0,4,8)
;
	MOV D,H		;CLEAR D
	POP B		;RESTORE WARM/COLD FLAG
			;STACK MUST BE AT ZERO FOR RST 1
	OUT DIOPORT1+1	;INSTALL 1ST DIIO
	RST 1		;SET DIO FLAG
	OUT DIOPORT1	;REMOVE 1ST DIO
	JNZ NODIO	;BRIF NOT DIO
	INR D		;BUMP COUNT
	OUT DIOPORT2+1	;INSTALL DIO 2
	RST 1		;SEE IF DIO THERE
	OUT DIOPORT2	;REMOVE SECOND DIO
	JNZ NODIO	;BRIF NO SECOND DIO
	INR D
NODIO:	LDA DISKN	;GET DISK NUMBER, (0,4,8)
	STA BOOTDISK	;TRANSMIT BOOT DISK TO BDOS


; TEST FOR PRESENCE OF IMSAI "VIO" VIDEO DISPLAY BOARD

	MVI A,VIOTST		;TEST FOR THIS VALUE AT
	MVI H,VIOTSTADR SHR 8	;THIS ADDRESS IN ROM
	RST 2
	JMP BOOTR

; EXIT TO BIOS TO CONTINUE
;	Z-BIT SET IF VIO IS THERE
;	B = ZERO IF VIO IS THERE
;	C = FF IF COLD START
;	D = NUMBER OF DIO'S
				;PAGE

	IF SIOINIT
;    INIT BOTH CHANNELS OF IMSAI 
;	SERIAL INTERFACE (SIO) BOARD
;
;IF SIO HAS JUST BEEN RESET, IT EXPECTS A "MODE",
;THEN A "COMMAND".  BUT IF IT HASN'T BEEN RESET
;(AS ON A WARM START), IT IS NOT EXPECTING A "MODE", SO
;WE SEND IT A DUMMY THAT LEAVES IT EXPECTING A "COMMAND"
;REGARDLESS, THEN SEND IT A "RESET" COMMAND (40H), WHICH
;LEAVES IT EXPECTING A MODE, THEN WE SEND IT THE
;DESIRED  DESIRED MODE AND COMMAND.
;
DOSIO:	POP H		;GET STRING PTR
SIOLUP:	MOV A,M
	OUT  SIOS1
	OUT  SIOS2
	INX  H
	RAR		;LAST BYTE ONLY MUST BE ODD
	JNC  SIOLUP
	MVI  A,SIOCNTL	;TURN OFF INTERUPTS AND TURN ON
	OUT  SIOC	;...CARRIER DETECT, BOTH CHANNELS
	PCHL		;RETURN
	ENDIF


	ORG 0FFH

;LENGTH OF SYSTEM IMAGE (NUMBER OF SECTORS FOR
; SYSGEN TO WRITE WHEN PUTTING SYSTEM) IS AT FIXED
; LOCATION 0FFH.  VALUE AUTOMATICALLY CHANGES IF
; "BIOSLEN" EQUATE (PAGE 2) IS CHANGED.

	DB    ((SYSTOP-SYSBOTTOM) SHR 7 AND 0FFH) + 2
	END
