	TITLE	CUSTOMIZED BIOS FOR M5B
	LIST	NOCOND
	LIST	OFF
;*********************************
;
;	ASSEMBLY PARAMETERS
;
;*********************************
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;======================================
;
;	CONDITIONAL ASSEMBLY FLAGS
;
;======================================
SHORT	EQU	TRUE		;SHORT BIOS (REMOVES UNESENTIAL CODE)
LSTINC	EQU	FALSE		;LIST INCLUDE FILES
HARDBT	EQU	FALSE		;HARD DISK BOOT (FALSE= FLOPPY BOOT)
USEMON	EQU	TRUE		;USE MONITOR ROM I/O ROUTINES IF TRUE
INTRPTS	EQU	FALSE		;ENABLE INTERRUPT PROCESSING WHISTLE
INTCPTS	EQU	FALSE		;ENABLE SYSTEM CALL INTERCEPT WHISTLE
	LIST	ON
;*************************************************************
;
;   (c) 1981   GRH Electronics, CUPERTINO, CA
;
;*************************************************************
;
;	CONFIGURATION:
;
; CPM	ISASI
; DRIVE	DRIVE	USAGE
   IF	HARDBT		;HARD DISK BOOT CONFIG.
;   A	  0	SIDE 0 & 1 OF HARD DISK PHYSICAL DRIVE 0
;   B	  1	SIDE 2 & 3 OF HARD DISK PHYSICAL DRIVE 0
;   C	  2	SIDE 0 & 1 OF HARD DISK PHYSICAL DRIVE 1
;   D	  3	SIDE 2 & 3 OF HARD DISK PHYSICAL DRIVE 1
;   E	  4	JADE FLOPPY PHYSICAL DRIVE 0
;   F	  5	JADE FLOPPY PHYSICAL DRIVE 1
;   	  6	JADE FLOPPY PHYSICAL DRIVE 2
;   	  7	JADE FLOPPY PHYSICAL DRIVE 3
   ELSE
;   A	  4	JADE FLOPPY PHYSICAL DRIVE 0
;   B	  5	JADE FLOPPY PHYSICAL DRIVE 1
;   	  6	JADE FLOPPY PHYSICAL DRIVE 2
;   	  7	JADE FLOPPY PHYSICAL DRIVE 3
;   C	  0	SIDE 0 & 1 OF HARD DISK PHYSICAL DRIVE 0
;   D	  1	SIDE 2 & 3 OF HARD DISK PHYSICAL DRIVE 0
;   E	  2	SIDE 0 & 1 OF HARD DISK PHYSICAL DRIVE 1
;   F	  3	SIDE 2 & 3 OF HARD DISK PHYSICAL DRIVE 1
   ENDIF
;
;*************************************************************
;   REVISIONS:
;
; 2.2.0 - RELEASE
;
; 2.2.3 - SWAPPED DCM & BIOS SECTORS ON DISK, ALLOWING A
;	    LARGER BIOS ALLOCATION ON THE DISK.
;
; 2.2.4 - ADDED NAKED TERMINAL DRIVERS & IOBYTE IN
;	    ANTICIPATION OF THE MONITOR. ALSO, ALL REFERENCES
;	    REQUIRING THE I/O PROMS TO BOOT HAS BEEN REMOVED.
;
; 2.2.5 - RECONFIGURE FOR 62K SYSTEM.
;
; 2.2.6 - 20 FEB 83
;	DOUBLE D REV C UPGRADE. CHANGE BOARD STATUS PORT BITS.
;
; 2.2.7 - 8 MAR 83 GRH
;	ADDED CLOCK/CALENDAR DRIVER, SYSTEM CALL INTERCEPT,
;	ILLEGAL SYSTEM CALL MESSAGE, CHANGED BIOS SIZE TO END
;	OF INITIALIZED DATA AREA. RESTRUCTURE MODULES.
;
; 2.28 - 22 APR 83   GRH
;	CHANGED DEFINITIONS TO ALLOW BIG DIRECTORIES.
;	DISALLOWED DRIVES C & D.
;
; 2.29 - 3 SEP 83   GRH
;	Changed Rev # for blocked DCM. Enables IBM system 34
;	256 bytes per sector disks to be read.
;
; 1.10 - 23 SEP 83   GRH
;	Move clock-calendar routines to ROM. Add Interrupt handler
;	(Mode 2). Change Revision display of sign-on (separate CBIOS rev).
;
; 2.00 - 24 MAR 84   GRH
;	Modify for hard disk
;
; 2.01 - 28 APR 84   GRH
;	Change hard disk DPB to reflect half size directory, but keep
;	allocation for 1k directory
;
; 2.02 - 2 JUN 84   GRH
;	Change floppy disk drivers to relate to ISASI control of JADE
;	   FDC.
;	Change IOPB sector value from physical sector (1..n) to logical
;	   sector value (0..n-1). This maintains more uniformity in
;	   parameter passing between hard disk & JADE floppy IOPBs.
;	Vector I/O routines to monitor rom routines.
;
; 2.03 - 4 JUN 84   GRH
;	Add bells & whistles again.
;	Move to 61k system.
;
; 2.04 - 30 MAR 85   GRH
;	Implemented hard disk drive 1 as C: & D:.
;	Implemented the Logon function for the hard disk.
;	Implemented user friendly disk error options: Abort, Retry, Ignore.
;	Solved warm boot hang problem by reseting host adapter if busy.
;
; 2.05 - 17 JAN 86   GRH
;	Changed floppy driver to new Rom version.
;	Changed disk I/O to allow drive driver change.
;	Optimize various routines.
;
VERSN	EQU	'05'
;
;*************************************************************************

	SUBTTL	SYSTEM DECLARATIONS
;============================================================================
;
;*INCLUDE COMIOPB.DEF
;*INCLUDE JDDCONT.DEF
;*INCLUDE JDDDISK.DEF
;*INCLUDE MONBOARD.DEF
;*INCLUDE IOBOARD.DEF
;*INCLUDE NAKEDT.DEF
;*INCLUDE ISHA.DEF
;*INCLUDE CLOCK.DEF
;
;============================================================================
	LIST	OFF
*INCLUDE COMIOPB.DEF
*INCLUDE JDDCONT.DEF
*INCLUDE JDDDISK.DEF
*INCLUDE MONBOARD.DEF
*INCLUDE IOBOARD.DEF
*INCLUDE NAKEDT.DEF
*INCLUDE ISHA.DEF
*INCLUDE CLOCK.DEF
	LIST	ON

;============================================================================
;
;			DISK OPERATING SYSTEM ADDRESSES
;
;============================================================================
NKSYS	EQU	61		;SYSTEM SIZE IN K BYTES
KBYTE	EQU	1024
CPMSZ	EQU	KBYTE*NKSYS
CPMBS	EQU	CPMSZ - (20 * KBYTE) ; CP/M BIAS VALUE
CCP	EQU	CPMBS+3400H	;ADDR OF CCP
BDOS	EQU	CPMBS+3C00H	;ADDRESS OF BDOS
BIOS	EQU	CPMBS+4A00H	;ADDRESS OF BDOS
BIOSR	EQU	1000H-BIOS
;
PAGE0	EQU	0		;START OF CP/M RAM
IOBYTE	EQU	PAGE0 + 3	;IOBYTE ADDR
DEFDRV	EQU	PAGE0 + 4	;DEFAULT DRIVE PARAM ADDR
DEFBFR	EQU	PAGE0 + 80H	;DEFAULT BUFFER
TPA	EQU	100H


;============================================================================
;
;			OTHER DECLARATIONS
;
;============================================================================
DEFIOB	EQU	80H		;INITIAL IOBYTE VALUE (LPT ON)
DFDRV	EQU	0		;INITIAL DEFAULT DRIVE
SECSZ	EQU	128
NDRVS	EQU	6
BTDIRS	EQU	3		;HARD DISK SYSTEM TRACKS DIRECTORY SECTOR
BTCCPO	EQU	3		;OFFSET TO CCP ENTRY IN SYS TRKS DIRECTORY
	IF	HARDBT
LASTSEC	EQU	47		;LAST BOOT SECTOR
	ELSE
LASTSEC	EQU	45		;LAST BOOT SECTOR
	ENDIF


;============================================================================
;
;	THE FOLLOWING 2 PARAMETERS MUST REFLECT THE MAX DISK SIZE &
; THE MAX DIRECTORY SIZE.
;
;============================================================================
ALLSIZ	EQU	33	;ALLOCATION BIT MAP SIZE (1 BYTE PER 8 CLUSTERS)
CHKSIZ	EQU	32    ;DIRECTORY CHECKSUMS ARRAY SIZE (1 BYTE PER DIR. SECTOR)


;============================================================================
;
;				ADDRESSES
;
;============================================================================
CALROM	EQU	7		;CALENDAR ROM SELECT #
;
;   CLOCK/CALENDAR ROM ENTRY POINTS
;
RDBENT	EQU	0F800H		;READ CLOCK BUFFER ENTRY
SETENT	EQU	RDBENT + 3	;SET CLOCK ENTRY
CALENT	EQU	RDBENT + 6	;RETURN CALENDAR ENTRY
TIMENT	EQU	RDBENT + 9	;RETURN TIME ENTRY
;
;   BOOT PROM ENTRY POINTS
;
DKBASE	EQU	0F800H		;BASE ADDRESS
JADEX	EQU	DKBASE + 000CH	;JADE CONTROLLER DRIVER
ISHAX	EQU	DKBASE + 000FH	;SASI HOST ADAPTOR DRIVER


;============================================================================
;
;				ASCII CHARS
;
;============================================================================
LF:	EQU	0AH
CR:	EQU	0DH
CTRLZ:	EQU	1AH

	SUBTTL	BIOS CODE
;----------------------------------------------------------------------------
;
;			   BIOS JUMP VECTOR TABLE
;
;----------------------------------------------------------------------------
	ORG	BIOS
;
	JP	INIT1		;COLD START ENTRY
	JP	WARM		;RELOAD CCP/BDOS
	JP	CNSCK		;GET CONSOLE STATUS
	JP	CI		;CONSOLE INPUT
	JP	COC		;CONSOLE OUTPUT
	JP	LO		;PRINTER OUTPUT
	JP	PUNCH
	JP	READER
	JP	HOME		;HOME SELECTED DRIVE
	JP	SELDSK		;SELECT DISK DRIVE
	JP	SETTRK		;SET TRACK #
	JP	SETSEC		;SET SECTOR #
	JP	SETDMA		;SET TRANSFER ADDR
	JP	DISKRD		;PERFORM DISK READ
	JP	DISKWR		;PERFORM DISK WRITE
	JP	LISTST		;RETURN LIST STATUS
	JP	SECTRN		;TRANSLATE SECTOR
   IF INTRPTS
	JP	ITRAP		;FORMAT VECTOR
   ENDIF


;**************************************************************************
;
;	THESE BOOT PARAMS MUST RESIDE AS DEFINED RIGHT BEFORE THE COLD
;  INIT ROUTINE START AND MUST BE IN THE 1ST SECTOR.
;  THESE 2 WORDS ARE REFERENCED BY THE BOOT CODE IN
;  ORDER TO FIND THE LOAD ADDRESS FOR THE BIOS & IT'S LENGTH.
;
;**************************************************************************
BIOSSZ:	DW	BIOSND - BIOS	;BIOS MODULE SIZE IN BYTES
BIOSST:	DW	BIOS		;BIOS MODULE LOAD ADDR FOR SBD
INIT1:	JR	INIT


;############################################################################
;
;	DIRECTORY SECTOR BUFFER STARTS HERE AFTER CRUNCHING COLD START
;  CODE. THIS BUFFER IS USED BY THE CP/M DIRECTORY CHECK ROUTINES THAT
;  CHECK FOR DISK CHANGE.
;
;############################################################################
DIRBF:	EQU	$		;BUFFER BEGINNING


;----------------------------------------------------------------------------
;
;    INIT  - COLD START ENTRY FROM BOOT MUST SET ALL BIOS PARAMS
;
;----------------------------------------------------------------------------
INIT:
;
;   INIT STACK
;
	LD	SP,DEFBFR	;USE PAGE 0 FOR STACK
;
;   SAVE BOOT PROM #
;
	IN	A,(ROMSEL)
	AND	A,ROMSMK
	LD	(DKPROM),A
;
;   SELECT MONITOR ROM FOR CONSOLE ROUTINES
;
	CALL	GETMON		;MAKE SURE BOOT ROM IS DISABLED
;
;   INIT IOBYTE
;
	LD	A,DEFIOB
	LD	(IOBYTE),A
;
;   INIT DEFAULT DRIVE
;
	LD	A,DFDRV
	LD	(DEFDRV),A
;
;   SEND SYSTEM SIGN-ON
;
	LD	HL,MSGSO
	CALL	EDITOR
;
;   CHANGE COLD START TO WARM START
;
	LD	HL,(BIOS+4)
	LD	(BIOS+1),HL
;
;   GO EXECUTE WARM START
;
	JP	WARM

;############################################################################
;
;			SIGN-ON MESSAGE
;
;############################################################################
MSGSO:	DB	CR,LF
	DB	CPMSZ / (KBYTE * 10) + '0'
	DB	(CPMSZ MOD (KBYTE * 10)) / KBYTE + '0'
	DB	'K CP/M-80  Vers 2.2',CR,LF
	DB	'M5b CBIOS    Vers 2.', HIGH VERSN , LOW VERSN
	DM	CR,LF
;
	DS	DIRBF+SECSZ-$	;FILL OUT DIRECTORY BUFFER TO 1 SECTOR SIZE


;----------------------------------------------------------------------------
;
;	WARM REBOOT ENTRY LOADS CCP,BDOS FROM DISK & SETS UP VARIABLES
;
;----------------------------------------------------------------------------
WARM:
  IF	INTRPTS
	LD	A,HIGH INTABL	;INIT INTERRUPT VECTORS
	LD	I,A
	IM	2		;USE MODE 2

	IN	A,INTMSK
	AND	7FH		;ENABLE INT 7
	OUT	INTMSK,A

	IN	A,MONSTS	;ENABLE MONITOR BOARD INTERRUPTS
	OR	MONIE
	OUT	MONSTS,A
	EI
  ENDIF

	LD	SP,DEFBFR	;SELECT TEMPORARY STACK

	CALL	GETMON		;SELECT MONITOR ROM

	LD	A,0		;SET DRIVE 0
	LD	(IOPB + PBDRVO),A

   IF	HARDBT
	IN	A,(HSTATUS)	;IF HOST ADAPTER BUSY THEN
	BIT	HBUSYB,A
	JR	Z,NTHUNG

	LD	A,1 SHL HRESET	;  RESET HOST ADAPTER TO CLEAR HANG
	OUT	(HCMD),A
	XOR	A
	OUT	(HCMD),A

	EX	(SP),HL		;  DELAY FOR HOST ADAPTER TO CATCH UP
	EX	(SP),HL

WARM1:	IN	A,(HSTATUS)	;  WHILE BUSY THEN WAIT
	BIT	HBUSYB,A
	JR	NZ,WARM1

NTHUNG:	LD	BC,DEFBFR	;READ BOOT DIRECTORY
	CALL	SETDMA
	LD	C,BTDIRS
	CALL	SETSEC
	LD	C,0
   ELSE
	LD	C,1
   ENDIF
	CALL	SETTRK

   IF	HARDBT
	CALL	DISKRD
	JR	NZ,WEROR

   ENDIF
	LD	BC,CCP		;SET LOAD ADDR
	CALL	SETDMA

   IF	HARDBT
	LD	A,(DEFBFR + BTCCPO) ;PICK UP START OF CP/M IMAGE FROM DIRECTORY
	INC	A		;OFFSET FOR READ DECRIMENT
	LD	C,A
   ELSE
	LD	C,2		;START WITH SECTOR #2
   ENDIF
	CALL	SETSEC
;
;   READ CCP/BDOS
;
WREAD:	CALL	DISKRD
	JR	NZ,WEROR	;IF ERROR THEN EXIT

	LD	A,(IOPB + PBSECO)	;IF LAST SECTOR THEN DONE
	CP	LASTSEC
	JR	NC,WZRPG

	INC	A		;NEXT SECTOR
	LD	(IOPB + PBSECO),A
	LD	DE,SECSZ	;DMA := DMA + SECTOR SIZE
	LD	HL,(IOPB + PBDMAO)
	ADD	HL,DE
	LD	(IOPB + PBDMAO),HL
	JR	WREAD
;
;   WARM BOOT ERROR, OUTPUT MSG & HALT
;
WEROR:	LD	HL,MSGLE	;OUTPUT ERROR MESSAGE
	CALL	EDITOR
	HALT
;
;   BOOT OK, INIT PAGE 0
;
WZRPG:	LD	A,0C3H		;INITIALIZE BIOS WARM START VECTOR
	LD	HL,BIOS + 3
	LD	(PAGE0),A
	LD	(PAGE0 + 1),HL

	LD	HL,BDOS + 6	;INIT BDOS CALL VECTOR
	LD	(PAGE0 + 5),A
	LD	(PAGE0 + 6),HL

	LD	HL,DEFBFR	;SET DEFAULT SECTOR BUFFER
	LD	(IOPB + PBDMAO),HL

  IF	INTCPTS
	LD	HL,(BDOS + 7)	;GET BDOS VECTOR
	LD	(BDOSV),HL	;PUT IN INTERCEPT CODE
	LD	HL,INTCPT	;NOW PUT INTERCEPT VECTOR INTO BDOS VECTOR
	LD	(BDOS + 7),HL

	IN	A,(CLKDAT)    ;IF CLOCK NOT PRESENT THEN TURN OFF CLOCK DRIVE
	AND	11000000B      ;TEST UNUSED BUT DRIVEN BITS (1S IF NOT THERE)
	LD	A,38H		;COND. JR (ON)
	JR	Z,CLKON
	LD	A,18H		;UNCOND. JR (OFF) (CAUSES JUMP TO ILLEGAL)
CLKON:	LD	(INHCLK),A

  ENDIF
	LD	A,(DEFDRV)	;PASS IN DEFAULT DISK TO CCP
	LD	C,A
	JP	CCP

	SUBTTL	DISK ROUTINES
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;   READ A DISK SECTOR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DISKRD:	LD	IY,IOPB		;SELECT READ OP
	LD	(IY + PBCMDO),DDRDS
	JR	DRDCNT


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;   WRITE A DISK SECTOR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DISKWR:
	LD	IY,IOPB			;SELECT WRITE OP
	LD	(IY + PBCMDO),DDWRS

DRDCNT:	LD	A,(IY + PBDRVO)
	CP	NDRVS			;IF RANGE ERROR THEN ABORT
	JR	NC,FDSKER

	LD	(IY + PBFLGO),0		;NO FLAGS FOR NOW

RWOPR:	CALL	DISKEX			; DO OP
	RET	Z			;IF NO_ERROR THEN RETURN

	LD	A,(IY + PBSTATO)	;PASS STATUS BYTE TO DISK_ERROR()
	CALL	DSKER
	JR	RWOPR			;SINCE RETURNED, DO RETRY

DISKEX:	LD	IX,(DPHPTR)		;FETCH DRIVER ADDRESS
	LD	H,(IX + (-1))
	LD	L,(IX + (-2))
	JP	(HL)			;RETURNS TO CALLER


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	DISK ERROR SUBR.
; QUERIES USER FOR ABORT (REBOOT), IGNORE (RETURN OK TO BDOS),
;   RETRY (RETURNS TO CALLER) OR NORMAL BDOS ERROR (DEFAULT).
;	ENTRY-	A= ERROR CODE
;	EXIT -	A= FFH (DEFAULT), CHAR OTHERWISE
;		HL= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DSKER:
	LD	HL,DSKEB	;POINT TO ERROR BYTE
	CALL	PRHEX		;LOAD ERROR CODE INTO MESSAGE

	LD	HL,DSKEM	;OUTPUT ERROR MESSAGE
	CALL	EDITOR

	CALL	CI		;GET USER RESPONSE

	PUSH	AF		;SAVE CHAR
	LD	C,A		;ECHO CHAR
	CALL	COC
	POP	AF

	AND	5FH		;INSURE UPPER CASE

	CP	'R'		;IF RETRY THEN RETURN TO CALLER
	RET	Z

	POP	HL		;NOT RETURNING, WASTE ADDRESS TO CALLER

	CP	'A'		;IF ABORT THEN RE-BOOT
	JP	Z,0

	SUB	'I'		;IF IGNORE THEN RETURN NO ERROR
	RET	Z

FDSKER:	LD	HL,0		;RETURN DPB_PTR = 0 FOR SELECT FUNCTION
	LD	A,-1		;RETURN -1 TO BDOS
	OR	A
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;			SELECT DRIVE FUNCTION
;	LOG-ON - SET DISK PARAMETER BLOCK
;	ENTRY-	C= DRIVE #
;		E= 0 IF NEVER LOGGED BEFORE
;	EXIT -	HL= PTR TO DPT OR 0 FOR ERROR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SELDSK:
;
;   IF REQUESTED DRIVE NOT VALID THEN RETURN 0
;
	LD	HL,0		;ASSUME INVALID
;
	LD	A,C		;SET DRIVE #
	CP	NDRVS		;IF NOT 0..(NUMBER_OF_DRIVES -1) THEN ERROR
	RET	NC
;
;   SAVE DRIVE AND LOGON FLAG
;
	LD	(IOPB + PBDRVO),A	;STORE DRIVE #
;
	LD	A,E		;SET LOG REQUEST VECTOR
	LD	(LOGRQ),A
;
;   COMPUTE TABLE PTRS FOR RETURN
;
RETDSK:	LD	L,C		;COMPUTE TABLE PTR (C STILL HAS DRIVE)
	LD	H,0
	PUSH	HL		;SAVE *1
	POP	DE
	ADD	HL,HL		;DISK # * 8
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,DE		;* 9
	ADD	HL,HL		;* 18
	LD	DE,D0DPH
	ADD	HL,DE
	LD	(DPHPTR),HL	;SAVE POINTER FOR SUBSEQUENT OPS
;
	CALL	DPBAD
	LD	HL,(DPHPTR)	;RETURN THE NEW PTR
;
;   IF NOT 1ST SELECT FOR THIS DRIVE THEN RETURN NEW PTR
;
	LD	A,(LOGRQ)	;IF NOT_1ST_LOG_ON THEN RETURN TABLE PTR
	AND	1
	RET	NZ
;
;   FIRST SELECT FOR THIS DRIVE, READ IDENTITY SECTOR FIRST
;
	LD	IY,LOGIOPB
	LD	(IY + PBDRVO),C	;PERFORM DCM LOG-ON (C STILL HAS DRIVE #)
;
	LD	(IY + PBSECO),0	;START WITH SECTOR 0
;
FDLOGR:	CALL	DRDCNT		;LOG ON DRIVE & RETURN IDENTITY SECTOR DATA
	JR	Z,LOGCK
;
;   ERROR ENCOUNTERED, ASK USER FOR ACTION
;
	LD	A,(IY + PBSTATO)	;PASS ERROR CODE TO DISK_ERROR()
	CALL	DSKER
	JR	FDLOGR		;RETURN HERE MEANS TO RETRY
;
;
;  CHECK FOR ID SECTOR
;
LOGCK:	LD	A,(IY + PBST2O)	;FETCH IDENTITY SECTOR FLAG
	OR	A,A
	JR	Z,NOID
;
;   DISK CONTAINS ID.
;
	LD	DE,(DPBPTR)		;MOVE DISK DPB TO BIOS DPB
	LD	HL,DEFBFR + IDDPBO
	LD	BC,IDDPBSZ
	LDIR
;
	LD	HL,DEFBFR + IDFLGO	;MOVE FLAGS TO DPB
	LD	BC,IDFSIZE - 1
	LDIR
;
;   IF EXTENDED DATA THEN ALREADY GOT IT
;
	LD	A,(IY + PBST2O)	;CHECK FOR EXTENDED DATA
	INC	A
	JR	NZ,CKTRAN	;TRUE IF EXTENDED DATA ALREADY STORED
;
;   RECREATE EXTENDED DISK DATA
;
	DEC	DE			;BACK UP TO TRACK 0 SECTOR COUNT
	DEC	DE
	DEC	DE
	EX	DE,HL			;HL POINTS TO TRACK 0
;
	LD	A,(DEFBFR + IDFLGO)	;TEST FOR HARD DISK
	BIT	DFHARDB,A
	JR	NZ,LOGHARD
;
;   DO FLOPPY TRACK SIZES ACCORDING TO TRACK FLAGS
;
	CALL	SETSPT
	INC	HL
	RRCA
	CALL	SETSPT
	INC	HL
	RRCA
	CALL	SETSPT
	JR	CKTRAN
;
;   DO HARD DISK
;
LOGHARD:
	EX	DE,HL
	LD	HL,HDDPB + DPBSPT0O
	LD	BC,3
	LDIR
	JR	CKTRAN
;
;
;   NO ID SECTOR EXISTS, ASSUME DEFAULTS
;
NOID:	LD	E,(IY + PBDRVO)	;COMPUTE TABLE ADDRESS
	LD	D,0
	LD	HL,DDPBT
	ADD	HL,DE
	ADD	HL,DE
	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A
	LD	DE,(DPBPTR)
	LD	BC,DPBSZ
	LDIR
;
;   IF FLOPPY THEN TRANSLATE
;
CKTRAN:	CALL	TRNONE			;ASSUME NO TRANSLATE
	LD	IY,(DPBPTR)		;FETCH PTR
	LD	A,(IY + [DPBDSMO + 1])	;FETCH DISK SIZE HIGH BYTE
	OR	A,A			;IF SIZE < 256K THEN MUST BE IBM 3740
	CALL	Z,TR3740
;
;   LOGON DONE, RETURN PTR
;
	LD	HL,(DPHPTR)	;ELSE RETURN PTR TO TABLE
	RET
;
;
;   TABLE OF DEFAULT DPB PTRS FOR EACH DRIVE
;
DDPBT:
   IF	HARDBT
	REPT	4
	DW	HDDPB
 	ENDM
	REPT	2
	DW	FDDPB
	ENDM
   ELSE
	REPT	2
	DW	FDDPB
	ENDM
	REPT	4
	DW	HDDPB
	ENDM
   ENDIF


;****************************************************************************
;
;	COMPUTE FLOPPY SECTORS PER TRACK SUBR
;	ENTRY-	HL= PTR TO PUT DATA
;		A= BIT 0= 0: 26 SPT, 1: 48 SPT
;
;****************************************************************************
SETSPT:	LD	(HL),48		;ASSUME DOUBLE DENSITY
	BIT	0,A
	RET	NZ
	LD	(HL),26
	RET


;****************************************************************************
;
;   SET 3740 SECTOR TRANSLATION
;	EXIT -	DE, HL= ?
;
;****************************************************************************
TR3740:	LD	DE,SDTRAN
SETTR	LD	HL,(DPHPTR)
	LD	(HL),E
	INC	HL
	LD	(HL),D
	RET


;****************************************************************************
;
;	SET NO SECTOR TRANSLATION
;	EXIT -	HL, DE= ?
;
;****************************************************************************
TRNONE:	LD	DE,0
	JR	SETTR


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;   GET DRIVE PARAMETER BLOCK ADDR
;	EXIT -	DE= DPB PTR
;		HL= (DPHPTR) + 11
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DPBAD:	LD	HL,(DPHPTR)	;FETCH BASE ADDR
	LD	DE,10		;ADD OFFSET OF DPB PTR
	ADD	HL,DE
	LD	E,(HL)		;FETCH DPB PTR
	INC	HL
	LD	D,(HL)
	LD	(DPBPTR),DE	;SAVE FOR FUTURE USE
	RET


;****************************************************************************
;
;   HOME DRIVE - TREAT AS SEEK TRK 0
;
;****************************************************************************
HOME:	LD	C,0


;****************************************************************************
;
;	SET TRACK #
;	ENTRY-	C= TRACK #
;	EXIT -	A= C= TRACK #
;
;****************************************************************************
SETTRK:	LD	A,C
	LD	(IOPB + PBTRKO),A
	RET


;****************************************************************************
;
;	SET SECTOR
;	ENTRY-	C= SECTOR #
;	EXIT -	A= C= SECTOR #
;
;****************************************************************************
SETSEC:	LD	A,C
	LD	(IOPB + PBSECO),A
	RET


;****************************************************************************
;
;	SET TRANSFER ADDR
;	ENTRY-	BC= ADDRESS
;	EXIT -	HL= BC= ADDRESS
;
;****************************************************************************
SETDMA:	LD	(IOPB + PBDMAO),BC
	XOR	A,A
	LD	(IOPB + PBDMAXO),A
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	SECTOR TRANSLATION FUNCTION
;	ENTRY-	DE= 0: NO XLATE, ELSE PTR TO XLATE TABLE
;		BC= SECTOR # TO XLATE
;	EXIT -	HL= XLATED SECTOR OR (BC) + 1
;		BC= UNCHANGED
;		A, DE= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SECTRN:	LD	A,D	;IF TABLE ADDR = 0 THEN NO TRANSLATION
	OR	E
	JR	Z,NOTRAN

	EX	DE,HL
	ADD	HL,BC
	LD	L,(HL)

	LD	H,0
	RET
;
NOTRAN:	LD	HL,1
	ADD	HL,BC
	RET


;****************************************************************************
;
;	LOAD HEX DATA INTO MEMORY SUBR
;	ENTRY-	A= DATA
;		HL= PTR TO MEMORY
;	EXIT -	A= DATA
;		HL= HL + 2
;
;****************************************************************************
PRHEX:	CALL	PRDIG		;DO HIGH NIBBLE

PRDIG:	RLCA			;POSITION NIBBLE INTO LOW 4 BITS
	RLCA
	RLCA
	RLCA

	PUSH	AF		;SAVE DATA

	AND	0FH		;MASK OFF OTHER NIBBLE

	ADD	A,90H		;USE THE UBIQUITOUS DAA ROUTINE
	DAA
	ADC	A,40H
	DAA

	LD	(HL),A		;STORE CHAR
	POP	AF		;DATA
	INC	HL		;NEXT CHAR
	RET

	SUBTTL	DISK DRIVERS
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	FLOPPY DISK EXECUTE DRIVER FUNCTION
;	ENTRY-	IY= IOPB PTR (MUST BE PRESERVED)
;	EXIT -	A,FLAGS= 0: NO ERRORS, -1= ERROR
;		HL,DE,BC= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   IF	HARDBT
D4XADR:
D5XADR:
;
;   CONVERT LOGICAL DRIVE TO PHYSICAL DRIVE
;
	LD	A,(IY + PBDRVO)		;BIAS DOWN
	SUB	A,4
	LD	(IY + PBDRVO),A
   ELSE
D0XADR:
D1XADR:
   ENDIF
;
;   SELECT SIDE
;
	LD	IX,(DPBPTR)		;COMPUTE DISPLACEMENT TO SPT VALUE
	LD	A,(IY + PBTRKO)
	CP	2			;IF TRACK 0 OR 1 THEN OK
	JR	C,FD01
;
	LD	A,2			;DATA TRACKS ALLWAYS 2
;
FD01:	ADD	A,DPBSPT0O
;
	LD	(FDOFF),A		;MODIFY INSTRUCTION OPERAND
;
	LD	A,(IY + PBSECO)		;DETERMINE IF 2ND SIDE
	DEC	A			;CONVERT 1..N TO 0..N-1
FDOFF	EQU	$ + 2
	SUB	A,(IX + DPBSPT0O)
	JP	C,FDSECOK
;
	INC	A			;CONVERT BACK TO 1..N
	SET	7,A			;2ND SIDE
	LD	(IY + PBSECO),A
;
;   IOPB MASSAGED, CALL THE PROM CODE
;
FDSECOK:
	LD	A,(DKPROM)	;FETCH PROM #
	OUT	(ROMSEL),A
;
	LD	BC,IOPB		;PASS THE IOPB ARGUMENT
	CALL	JADEX
;
;   RESTORE MONITOR ROM
;
CHKERR:	PUSH	AF		;SAVE STATUS
	CALL	GETMON
	POP	AF
;
;   COMMAND COMPLETED, CHECK STATUS
;
	OR	A
	RET	Z
;
	LD	A,-1
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	H                                                                                                                                ,BC= ?
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   IF	HARDBT
D0XADR:
D1XADR:
D2XADR:
D3XADR:
   ELSE
D2XADR:
D3XADR:
D4XADR:
D5XADR:
   ENDIF
;
;   CONVERT LOGICAL DRIVE TO PHYSICAL DRIVE
;
	LD	A,(IY + PBDRVO)		;FETCH LOGICAL DRIVE
	SRL	A			;0/1= DRIVE 0, 2/3= DRIVE 1
	LD	(IY + PBDRVO),A
;
;   CONVERT LOGICAL SECTOR TO PHYSICAL SECTOR
;
	LD	D,0
	RR	D			;DRIVE BIT 0 -> SECTOR BIT 7
	LD	A,(IY + PBSECO)
	DEC	A			;CHANGE TO LOGICAL SECTOR {0..127}
	AND	7FH			;MASK BIT 7
	OR	D			;ADD IN LOGICAL DRIVE
	LD	(IY + PBSECO),A
;
;   OUTPUT IOPB ADDRESS
;
	LD	A,(DKPROM)
	OUT	(ROMSEL),A
;
	LD	BC,IOPB
	CALL	ISHAX
	JR	CHKERR


  IF	INTCPTS
	SUBTTL	CP/M UNSUPPORTED SYSTEM CALLS
;----------------------------------------------------------------------------
;
;	SYSTEM CALL INTERCEPT ROUTINE CHECKS FOR ILLEGAL BDOS CALLS &
;  PRINTS MESSAGE IF ILLEGAL. ALSO IMPLEMENTS CDOS CLOCK/CALENDAR
;  SYSTEM CALLS FOR ASMB.
;
;----------------------------------------------------------------------------
INTCPT:	LD	A,C		;CHECK CALL VALIDITY
	CP	41		;IF <= 40 THEN OK

BDOSV	EQU	$ + 1
	JP	C,BDOS + 11H	;THIS ADDR MODIFIED BY WARM BOOT RTN
;
;  THE FOLLOWING CONDITIONAL JUMP IS MODIFIED TO AN UNCONDITIONAL JUMP BY
;  THE WARM BOOT ROUTINE IF THE CLOCK/CALENDAR BOARD IS NOT PRESENT
;  IF NOT MODIFIED, THEN IT IS ALLWAYS FALSE (NOP).
;
INHCLK:	JR	C,ILLEGC
;
;  NOW CHECK FOR EXTENDED CALLS
;
	CP	8DH		;IF RETURN VERSION THEN RETURN IT
	JR	Z,RETVER

	CP	90H		;IF NOT CLOCK THEN ERR
	JR	C,ILLEGC

	JR	Z,CLKCAL	;IF CALENDAR THEN GET IT

	CP	92H
	JR	C,CLKSET	;IF SET FUNCTION THEN SET CLOCK

	JR	Z,CLKTIM	;IF TIME THEN GET IT

	CP	93H
	JR	Z,CLKRDC	;IF READ CLOCK THEN GET IT
;
;  ILLEGAL SYSTEM CALL
;
ILLEGC:	LD	HL,ISCMSG	;OUTPUT WARNING
	CALL	EDITOR
	XOR	A		;BC = HL = A = 0
	LD	L,A
	LD	H,A
	LD	C,A
	LD	B,A
	RET


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	CDOS RETURN VERSION SYSTEM CALL
;  MAKES CLOCK/CALENDAR WORK.
;	EXIT -	B= 1
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
RETVER:	LD	B,1
	RET

	SUBTTL	MISC I/O DRIVERS
;*****************************************
;
;	CLOCK ROUTINES
;
;*****************************************
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN CALENDAR FUNCTION 90H
;	EXIT -	A= DAY
;		B= MONTH
;		C= YEAR
;		L= DAY OF WEEK
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CLKCAL:	LD	HL,CALENT	;ROM ENTRY POINT

CLK1:	LD	BC,CLKBFR	;READ CLOCK
	JR	CLK2


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN TIME FUNCTION 92H
;	EXIT -	A= SECONDS
;		B= MINUTES
;		C= HOURS
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CLKTIM:	LD	HL,TIMENT
	JR	CLK1


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	READ CLOCK TIME FUNCTION 93H
;	ENTRY-	DE= PTR TO 13 BYTE BUFFER FOR CLOCK DATA
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CLKRDC:	LD	C,E		;SET UP PARAMETERS
	LD	B,D
	LD	HL,RDBENT
	JR	CLK2


;****************************************************************************
;
;	CLOCK SET FUNCTION 91H
;	ENTRY-	DE= CLOCK IMAGE BUFR PTR (13 BYTES LONG)
;
;****************************************************************************
CLKSET:
	LD	C,E		;SET UP PARAMETERS
	LD	B,D
	LD	HL,SETENT
CLK2:	LD	A,CALROM


;****************************************************************************
;
;	EXECUTE ROM ROUTINE
;	ENTRY-	HL= ENTRY ADDRESS
;		A= ROM #
;	EXIT -	ENTRY ROM RE-SELECTED
;
;****************************************************************************
EXROM:	PUSH	AF		;SAVE NEW ROM

	IN	A,ROMSEL	;SAVE CURRENT ROM
	LD	(ROMSAV),A

	POP	AF		;SELECT NEW ROM
	AND	ROMSMK
	OUT	ROMSEL,A

	PUSH	HL		;SAVE ENTRY

	LD	HL,EXROMR	;PUT RETURN ADDR ON STACK
	EX	(SP),HL
	JP	(HL)		;EXECUTE ROM

EXROMR:	PUSH	AF		;SAVE RETURN VALUE
	LD	A,(ROMSAV)	;RESELECT ORIGINAL ROM
	OUT	ROMSEL,A

	POP	AF		;RETURN VALUE
	RET

  ENDIF
	
	SUBTTL	CHAR I/O ROUTINES
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	CONSOLE INPUT
;	EXIT -	A= CHAR
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CI:
   IF	USEMON
	CALL	GETMON		;SWITCH IN MONITOR ROM
	JP	0F803H		;USE MONITOR
   ELSE
	CALL	CNSCK		;IF NO CHAR RDY THEN WAIT
	JR	Z,CI
	IN	A,NTD		;ELSE RETURN CHAR
	RET
   ENDIF


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN CONSOLE STATUS
;	EXIT -	A= 0: NOT READY
;		   FFH: CHAR READY
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CNSCK:
   IF	USEMON
	CALL	GETMON
	JP	0F812H
   ELSE
	IN	A,NTS		;IF DATA NOT READY THEN RETURN 0
	AND	1 SHL NTRDY
TTOST1:	RET	Z
	LD	A,-1		;ELSE RETURN -1
	RET
   ENDIF


;****************************************************************************
;
;	CONSOLE OUTPUT
;	ENTRY-	C= CHAR TO OUTPUT
;
;****************************************************************************
COC:
   IF	USEMON
	CALL	GETMON
	JP	0F809H
   ELSE
	CALL	NTOST		;IF BUSY THEN WAIT
	OR	A
	JR	Z,COC

	LD	A,C
	OUT	NTD,A
	RET

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	RETURN CONSOLE OUTPUT READY STATUS
;	EXIT -	A= 0: BUSY, FFH: READY
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
NTOST:	IN	A,NTS
	CPL			;REVERSE SENSE
	AND	1 SHL NTBSY
	JR	TTOST1
   ENDIF


;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
;	READER DRIVER - DUMMY
;	EXIT -	A= CTRL-Z
;
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
READER:	LD	A,CTRLZ		;FAKE EOF
;	FALL THROUGH TO PUNCH RETURN


;****************************************************************************
;
;	PUNCH DRIVER
;	ENTRY-	C= CHAR TO OUTPUT
;
;****************************************************************************
PUNCH:	RET


;****************************************************************************
;
;	PRINTER DRIVER
;	ENTRY-	C= CHAR TO OUTPUT
;
;****************************************************************************
LO:
   IF	USEMON
	CALL	GETMON
	JP	0F80FH
   ELSE
	CALL	LISTST		;IF BUSY THEN WAIT
	JR	Z,LO

	LD	A,C		;OUTPUT CHAR
	SET	7,A
	OUT	CENTOUT,A

	RES	7,A		;OUTPUT LOW TRUE STROBE
	OUT	CENTOUT,A
	SET	7,A
	OUT	CENTOUT,A
	RET
   ENDIF


;****************************************************************************
;
;	RETURN LIST DEVICE STATUS
;	EXIT -	A= 0: BUSY, FFH:READY
;
;****************************************************************************
LISTST:
   IF	USEMON
	CALL	GETMON
	JP	0F827H
   ELSE
	IN	A,CENTS		;IF BUSY THEN RETURN 0
	CPL			;INVERT THE SENSE
	AND	1 SHL CENTBSY
	RET	Z

	LD	A,0FFH		;ELSE RETURN -1
	RET
   ENDIF


;****************************************************************************
;
;	GET MONITOR PROM SUBR
;	EXIT -	A= ?
;
;****************************************************************************
GETMON:	LD	A,XMONROM
	OUT	(ROMSEL),A
	RET


;****************************************************************************
;
;	MESSAGE EDITOR
;	ENTRY-	HL= TEXT PTR (BIT 7= 1: TERMINATOR)
;	EXIT -	REGS= ?
;
;****************************************************************************
EDITOR:	LD	C,(HL)		;MESSAGE EDIT LOOP
	PUSH	HL		;SAVE PTR
	RES	7,C		;CLEAR BIT 7 FOR OUTPUT
	CALL	COC

	POP	HL
	BIT	7,(HL)		;IF BIT 7 SET THEN RETURN
	RET	NZ

	INC	HL		;ELSE PRINT NEXT CHAR
	JR	EDITOR

  IF	INTRPTS
	SUBTTL	INTERRUPTS
;----------------------------------------------------------------------------
;
;				USER INTERRUPT
;
;----------------------------------------------------------------------------
ITRAP:	PUSH	AF		;SAVE USED REGISTERS
	PUSH	HL
	PUSH	BC

	LD	HL,ITMSG	;NOTIFY USER
IQCONT:	CALL	EDITOR

	LD	HL,IQMSG	;QUERY USER
	CALL	EDITOR
	CALL	CI
	CP	3		;IF CTRL-C THEN WARM BOOT
	JP	Z,PAGE0

	AND	5FH		;IGNORE CASE

	CP	'Y'		;IF YES THEN ABORT
	JP	Z,PAGE0

	CP	'I'
	JR	NZ,ITRAP1

	POP	BC		;ELSE RESTORE & GOTO MONITOR TRAP
	POP	HL
	POP	AF
	JP	0038H

ITRAP1:	CP	'M'		;IF MONITOR THEN GOTO MONITOR TRAP
	JR	NZ,ITRAPR

	CALL	GETMON		;INSURE MONITOR THERE
	POP	BC
	POP	HL
	POP	AF
	JP	0F824H

ITRAPR:	POP	BC		;IF CONTINUE THEN RESTORE & RETURN
	POP	HL
	POP	AF
	EI			;RE-ENABLE INTERRUPTS
	RET


;**************************************
;
;	UNSUPPORTED INTERRUPT
;
;**************************************
ILLINT:
	PUSH	AF		;SAVE ALL 8080 REGS
	PUSH	HL
	PUSH	BC
	LD	HL,ILLIM	;NOTIFY USER OF INT
	JR	IQCONT


	SUBTTL	DATA CONSTANTS
;############################################################################
;
;			MODE 2 INTERRUPT VECTOR TABLE
;
;############################################################################
   IF	$ AND 0FFH	;START ON EVEN PAGE BOUNDARY
	DS	100H - ($ AND 0FFH)
   ENDIF
INTABL:	REPT	7		;1ST 7 ARE UNSUPPORTED
	DW	ILLINT
	ENDM
	DW	ITRAP		;INT 8 IS USER INTERRUPT
  ENDIF


;############################################################################
;
;			3740 SECTOR TRANSLATION TABLE
;			**** CP/M SINGLE DENSITY ****
;
;############################################################################
SDTRAN:	DB	1,7,13,19,25,5,11,17,23,3,9,15
	DB	21,2,8,14,20,26,6,12,18,24,4,10
	DB	16,22


;############################################################################
;
;		DISK PARAMETER BLOCK STRUCTURE
;
;############################################################################
	STRUCT	0
DPBSPTO	DS	2	;SPT- LOGICAL SECTORS/TRACK
DPBBSHO	DS	1	;BSH- BLOCK SHIFT FACTOR DETERMINED BY CLUSTER SIZE
			;	1K= 3, 2K= 4, 4K= 5, 8K= 6, 16K= 7
DPBBLMO	DS	1	;BLM- BLOCK MASK
			;	1K = 7, 2K= 15, 4K= 31, 8K= 63, 16K= 127
DPBEXMO	DS	1	;EXM- EXTENT MASK
			;	DSM < 256 : 1K= 0, 2K= 1, 4K= 3, 8K= 7, 16K= 15
			;	DSM > 255 : 2K= 0, 4K= 1, 8K= 3, 16K= 7
DPBDSMO	DS	2	;DSM- DRIVE STORAGE SIZE (IN CLUSTERS)
	;  INT(((#_TRACKS - OFF) * SPT * BYTES PER SECTOR) / CLUSTER SIZE) -1
DPBDRMO	DS	2	;DRM- DIRECTORY SIZE -1
DPBAL0O	DS	2	;AL0,1- DIRECTORY ALLOCATION
			;	1 MSB PER DIRECTORY CLUSTER ALLOCATED
DPBCKSO	DS	2	;CKS- # DIRECTORY SECTORS CHECKED
			;	(DRM +1) / 4
DPBOFFO DS	2	;OFF- # RESERVED TRACKS AT BEGINNING OF DISK
;
;   NEW DATA
;
DPBFLGO	DS	1	;DISK FLAGS FROM DISK
DPBSPT0O DS	1	;TRACK 0 PHYSICAL SECTORS PER TRACK
DPBSPT1O DS	1	;TRACK 1 PHYSICAL SECTORS PER TRACK
DPBDSPTO DS	1	;DATA TRACKS SECTORS PER TRACK
DPBSZ	DS	0	;SIZE OF DPB
	ENDM


;############################################################################
;
;   DEFAULT FLOPPY PARAMETER BLOCK FOR IBM 3740 FORMAT
; 
;############################################################################
FDDPB:	DW	26		;SECTORS PER TRACK
	DB	3		;BLOCK SHIFT FACTOR
	DB	7		;BLOCK MASK
	DB	0		;NULL MASK
	DW	242		;DISK SIZE -1
	DW	63		;DIRECTORY MAX
	DB	11000000B	;ALLOC 0
	DB	0		;ALLOC 1
	DW	16		;CHECK SIZE
	DW	2		;TRACK OFFSET
;
;   THE FOLLOWING ARE NEW PARAMETERS
;
	DB	0		;DISK FLAGS
	DB	26		;TRACK 0 SECTORS PER TRACK
	DB	26		;TRACK 1 SECTORS PER TRACK
	DB	26		;DATA TRACKS SECTORS PER TRACK


;############################################################################
;
;		DEFAULT HARD DISK PARAMETER BLOCK
;
;############################################################################
HDDPB:	DW	128		;SECTORS PER TRACK (LOGICAL)	(SPT)
	DB	5		;BLOCK SHIFT FACTOR		(BSH)
	DB	31		;BLOCK MASK			(BLM)
	DB	1		;NULL MASK			(EXM)
	DW	1015		;DISK SIZE (CLUSTERS -1)	(DSM)
	DW	1152 / 2	;DIRECTORY MAX			(DRM)
	DB	0FFH		;ALLOCATION 0			(AL0)
	DB	10000000B	;ALLOCATION 1			(AL1)
	DW	0		;CHECK SIZE			(CKS)
	DW	2		;TRACK OFFSET			(OFF)
;
;   NEW PARAMETERS
;
	DB	00100000B	;DISK FLAGS
	DB	128		;TRACK 0 SECTORS PER TRACK
	DB	128		;TRACK 1 SECTORS PER TRACK
	DB	128		;DATA TRACKS SECTORS PER TRACK


;############################################################################
;
;			COMMON IO PARAMETER BLOCK
;
;############################################################################
IOPB:	REPT	IOPBSZ
	DB	0
	ENDM


;############################################################################
;
;				LOGON IOPB
;
;############################################################################
LOGIOPB:
	DB	DDLOG		;LOGON COMMAND
	DB	0		;DRIVE
	DW	0		;TRACK
	DW	0		;SECTOR
	DB	0		;FLAGS (LOGON)
	DW	DEFBFR		;DMA ADDR
	DB	0		;BANK ADDR
	REPT	IOPBSZ - ($ - LOGIOPB)
	LIST	OFF
	DB	0
	LIST	ON
	ENDM


;############################################################################
;
;				MESSAGES
;
;############################################################################
MSGLE:	DM	CR,LF,'LOAD ERROR'
DSKEM:	DB	CR,LF,'Disk Error Status: '
DSKEB:	DB	'00H',CR,LF
	DM	'Abort, Ignore, Retry, (BDOS) - '
   IF	INTCPTS
ISCMSG:	DM	CR,LF,'ILL. SYS. CALL',CR,LF
   ENDIF
   IF	INTRPTS
ITMSG	DM	CR,LF,'User'
ILLIM	DM	CR,LF,'Unsupported'
IQMSG	DM	' Interrupt: Abort? (Y/N) - '
   ENDIF


;############################################################################
;
;			DRIVE PARAMETER HEADER AREA
;				1 PER DRIVE
;
;############################################################################
ALLDPH:	MACRO	#D
	LIST	ON
;
;   DRIVE PARAMETER HEADER FOR DRIVE #D(DD)
;
	DW	D#D(DD)XADR	;DRIVER EXECUTION ADDRESS
D#D(DD)DPH:
	DW	0		;SECTOR TRAN TBL (OR 0 IF NO XLATE)
	DW	0		;SCRATCH AREA
	DW	0		;"
	DW	0		;"
	DW	DIRBF		;DIRECTORY BUFFER PTR
	DW	D#D(DD)DPB		;DRIVE PARAMETER BLK PTR
   IF	(HARDBT AND (DD < 5)) OR (NOT HARDBT AND (DD > 2))
	DW	0		;NO CHECKS ON HARD DISK
   ELSE
	DW	D#D(DD)CHK		;DRIVE DISK CHECKSUMS ARRAY PTR
   ENDIF
	DW	D#D(DD)ALL		;DRIVE CLUSTER ALLOCATION BIT MAP PTR
	LIST	OFF
	ENDM
;
DD	DL	1
	REPT	NDRVS
	LIST	OFF
	ALLDPH	0123456789ABCDEF
DD	DL	DD + 1
	LIST	ON
	ENDM

BIOSND	EQU	$

	SUBTTL	DATA AREA
;############################################################################
;
;			UNINITIALIZED DATA AREA
;	THE REMAINING AREA DOES NOT HAVE TO BELONG ON THE DISK.
;
;############################################################################
   IF	INTCPTS
CLKBFR:	DS	13	;CLOCK BUFFER
ROMSAV	DS	1	;ROM SWAP SAVE OF ORIGINAL ROM
   ENDIF
DPHPTR	DS	2	;DRIVE TABLE PTR
DPBPTR	DS	2	;DRIVE PARAMETER BLOCK PTR
LOGRQ	DS	1	;LOG ON REQUEST REG.
DKPROM	DS	1	;DISK BOOT PROM NUMBER


;############################################################################
;
;			DRIVE ALLOCATION AREAS DECLARED
; ALLOCATION REQUIRES 1 BIT PER CLUSTER ON DISK.
; CHECKSUMS REQUIRE 1 BYTE PER DIRECTORY SECTOR
;
;############################################################################
ALLDAL:	MACRO	#D
	LIST	ON
   IF	(HARDBT AND (DD < 5)) OR (NOT HARDBT AND (DD > 2))
;
;   CLUSTER ALLOCATION BIT MAP FOR DRIVE #D(DD)
;
D#D(DD)ALL:	DS	128
   ELSE
;
;   CLUSTER ALLOCATION BIT MAP & DIRECTORY CHECKSUMS STORAGE FOR DRIVE #D(DD)
;
D#D(DD)ALL:	DS	ALLSIZ
D#D(DD)CHK	DS	CHKSIZ
   ENDIF
	LIST	OFF
	ENDM
;
DD	DL	1
	REPT	NDRVS
	LIST	OFF
	ALLDAL	0123456789ABCDEF
DD	DL	DD + 1
	LIST	ON
	ENDM


;############################################################################
;
;			RESERVE DRIVE PARAMETER BLOCKS
;
;############################################################################
ALLDPB:	MACRO	#D
	LIST	ON
;
;   DRIVE PARAMETER BLOCK FOR DRIVE #D(DD)
;
D#D(DD)DPB:
	DS	DPBSZ
	LIST	OFF
	ENDM
;
DD	DL	1
	REPT	NDRVS
	LIST	OFF
	ALLDPB	0123456789ABCDEF
DD	DL	DD + 1
	LIST	ON
	ENDM

   IF	($ > 0F800H) OR ($ < 8000H)
;
;   WARN IF BIOS TOO BIG
;
	CONMSG	BIOS TOO BIG
   ENDIF

	END
