DataMuseum.dk

Presents historical artifacts from the history of:

Christian Rovsing CR7, CR8 & CR16 CP/M

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Christian Rovsing CR7, CR8 & CR16 CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦665718c40⟧ TextFile

    Length: 46080 (0xb400)
    Types: TextFile
    Names: »DFDBIOS.A86«

Derivation

└─⟦be0857eee⟧ Bits:30004395 CP/M-86 files - CR8 Dual floppy
    └─ ⟦this⟧ »DFDBIOS.A86« 

TextFile


	TITLE 'CR8 - CP/M-86 BIOS VERS. 3.0'
	PAGESIZE 56
	PAGEWIDTH 111


;	AUTHOR:	LARS WINTHER			DATE: 841801
;	MODIFIED FOR DUAL FLOPPY ONLY BY Leif Neland
;******************************************************************************
;	CHRISTIAN ROVSING A/S, CP/M-86 BASIC I/O MODULE FOR MP2 BOARD
;	AND MINI FLOPPIES.
;******************************************************************************
;
;
;	THIS CP/M-86 BIOS IS SETUP FOR CP/M-86 ON A MP2 BOARD.
;	CONSOLE,PRINTER  AND FLOPPY DISK I/O IS HANDLED VIA Z80 BASED
;	DRIVERS USING THE ONBOARD FLOPPY AND SERIAL I/O CONTROLLER CHIPS.
;	
;
;	ACCESS AND CONTROL OF THE MINI FLOPPY WILL BE THROUGH 
;	THE DISK CONTROLLER CIRCUITRY OF THE MP2 BOARD USING Z80 BASED DRIVERS.
;	THIS BIOS CONFIGURATION WILL SUPPORT TWO MINI FLOPPY DRIVES.
;
;	MINI FLOPPY FORMAT IS AS FOLLOWS:
;
;		77 TRACKS
;		16 RECORDS PER TRACK
;		TWO HEADS/SIDES
;		256 BYTE RECORDS
;
;
;	BIOS ACCESS TO THE MINI FLOPPY IS DONE IN REAL PAIRS OF 256 BYTE
;	SECTORS TO AND FROM THE 512 BYTE HOST BUFFER.
;	REAL ACCESS TO THE SECTOR PAIRS IS AS FOLLOWS:
;
;	       1,2; 5,6; 9,10; 13,14; 3,4; 7,8; 11,12; 15,16;
;
;
;
	EJECT
;
;DEFINE TRUE AND FALSE ASSEMBLY PARAMETERS
;
TRUE	EQU	-1			;DEFINE TRUE
FALSE	EQU	NOT TRUE		;DEFINE FALSE
;
;
;CP/M-86 SYSTEM PARAMETERS
;
BDOS	EQU	0B06H			;BDOS ENTRY POINT
BIOS	EQU	2500H			;START OF BIOS JUMP VECTOR TABLE
SYSINT	EQU	224			;SYSTEM CALL INTERRUPT
;
;
;VERSION NUMBER AND DATE
;
VERSION	EQU	30			;VERSION NUMBER
MONTH	EQU	01			;MONTH
DAY	EQU	18
YEAR	EQU	84			;YEAR LAST TWO DIGITS
;
;
;ASCII CHARACTER DEFINITIONS
;
BS	EQU	008H			;ASCII BACK SPACE CHARACTER
LF	EQU	00AH			;ASCII LINE FEED CHARACTER
CR	EQU	00DH			;ASCII CARRIAGE RETURN CHARACTER
ESC	EQU	01BH			;ASCII ESCAPE CHARACTER
RUBOUT	EQU	07FH			;ASCII RUBOUT CHARACTER
;
;
;BDOS CONSTANTS ON ENTRY TO "WRITE"
;
WRALL	EQU	0			;WRITE TO ALLOCATED BLOCK
WRDIR	EQU	1			;WRITE TO DIRECTORY
WRUAL	EQU	2			;WRITE TO UNALLOCATED BLOCK
;
	EJECT
;******************************************************************************
;	INTER-CPU COMMUNICATION CONSTANTS
;******************************************************************************
;
;
IFTOFF	EQU	8020H			;INTERFACE TABLE OFFSET IN Z80 RAM
CHANNEL	EQU	40H			;NBR OF BYTES PR INTERFACE CHANNEL
QUEUE	EQU	10H			;NBR OF BYTES PR QUEUE
;
TXE	EQU	0*QUEUE			;OFFSET IN CHANNEL TO TX EMPTY QUEUE
TXF	EQU	1*QUEUE			;OFFSET IN CHANNEL TO TX FULL QUEUE
RXF	EQU	2*QUEUE			;OFFSET IN CHANNEL TO RX FULL QUEUE
RXE	EQU	3*QUEUE			;OFFSET IN CHANNEL TO RX EMPTY QUEUE
;
BC	EQU	01			;OFFSET IN QUEUE TO BUFFER COUNT
FB	EQU	02			;OFFSET IN QUEUE TO "FIRST" POINTER
LB	EQU	04			;OFFSET IN QUEUE TO "LAST" POINTER
SF	EQU	06			;OFFSET IN QUEUE TO SLAVE FLAG
MF	EQU	08			;OFFSET IN QUEUE TO MASTER FLAG
;
RETQ	EQU	-2			;OFFSET FROM BUFFER POINTER TO RETURN Q
CHAIN	EQU	00			;OFFSET FROM BUFFER POINTER TO CHAIN
BYTEC	EQU	02			;OFFSET FROM BUFFER POINTER TO BYTECNT
DPTR	EQU	04			;OFFSET FROM BUFFER POINTER TO DATAPTR
;
CONCHA	EQU	CHANNEL*2		;CONSOLE CHANNEL OFFSET IN I/F TABLE
CONOPC	EQU	0FFH			;CONSOLE DATA OPCODE
;
LPCHA	EQU	CHANNEL*3		;LINE PRINTER CH. OFFSET IN I/F TABLE 
LPOPC	EQU	0FFH			;LINE PRINTER DATA OPCODE
;
ENTDLDU	EQU	03H			;BUFFER TYPE FOR ENTIRE DATA LDU
ENTCLDU	EQU	07H			;BUFFER TYPE FOR COMMAND/STATUS LDU
;
OPENOPC	EQU	04H			;OPEN OPCODE
OPFORM	EQU	10H			;SERIAL OPEN PARAMETER FORMAT CODE
;
CBLENGTH	EQU	20H		;MAX BYTECOUNT IN SERIAL BUFFERS
LBLENGTH	EQU	20H		;...DEFINED IN SCRIMP/M
;
	EJECT
;
;******************************************************************************
;
;CP/M-86  TO HOST DISK CONSTANTS
;
BLKSIZ	EQU	2048			;CP/M-86 ALLOCATION SIZE
HSTSIZ	EQU	512			;HOST DISK SECTOR SIZE
;
;
HDSPT	EQU	18			;HOST HARD DISK SECTORS/TRACK
;
FDSPT	EQU	8			;HOST MINI FLOPPY DISK 256 BYTE SECTOR
					;PAIRS PER TRACK
HSTBLK	EQU	HSTSIZ/128		;CP/M-86 SECTS/HOST BUFF
;
;CPMSPT	EQU	HSTBLK * HSTSPT		;CP/M-86 SECTORS/TRACK
;					;THIS VALUE CHANGES ACCORDING TO
;					;MINI OR HARD DISK.
;
;
;SECTOR SKEW INTERLACE FACTOR
;
SKEW	EQU	00			;SECTOR SKEW FACTOR
;
SECMSK	EQU	03			;SECTOR MASK
SECSHF	EQU	02			;SECTOR SHIFT FACTOR (LOG2(SECMSK))
;	
	EJECT
;******************************************************************************
;	CP/M-86 BIOS DISK CONFIGURATION SELECTION OPTIONS
;******************************************************************************
;
DEFDSK	EQU	00H			;DEFAULT BOOTED DISK
					;  00=A:
					;  01=B:

MAXDISK	EQU	2			;  A: AND B:
;
RECSIZE	EQU	0200H			;512 BYTE RECORDS
;
;
;FLOPPY DISK INTERFACE DRIVER CONSTANTS
;
FDCHA	EQU	CHANNEL*4		;FLOPPY CHANNEL OFFSET IN I/F TABLE
COMOPC	EQU	09H			;COMMAND OPCODE
RESTORE	EQU	00H			;RESTORE COMMAND CODE
READFD	EQU	01H			;READ DISK COMMAND CODE
WRITEFD	EQU	02H			;WRITE DISK COMMAND CODE
WRTRACK	EQU	03H			;FORMAT TRACK COMMAND CODE 
;
CPUSYNC	EQU	0FDH			;FLOPPY DRIVER SYNCHRONIZATION ERROR
;
;
PIOB	EQU	09H			;CHANNEL B PIO DATA ADDRESS
;
TIMER	EQU	20H			;INT.CTLR BASE VECTOR TYPE
TICKI	EQU	2			;INT LEVEL USED FOR TICK INT
RTC	EQU	(TIMER+TICKI)*4		;RTC INT. VECTOR OFFSET
;
	EJECT
;HOST ADAPTER I/O PORT ADDRESSING PARAMETERS
;
IOBASE	EQU	090H			;BASE I/O PORT ADDRESS OF CONTROLLER
;
CSR	EQU	IOBASE			;CHANNEL STATUS REGISTER PORT
CCSR	EQU	IOBASE+1		;COMMAND COMPLETION STATUS REGISTER
DADDRL	EQU	IOBASE+2		;DATA BUFFER LOW ADDRESS PORT
DADDRM	EQU	IOBASE+3		;DATA BUFFER MID ADDRESS PORT
CADDRL	EQU	IOBASE+4		;COMMAND BUFFER LOW ADDRESS PORT
CADDRM	EQU	IOBASE+5		;COMMAND BUFFER MID ADDRESS PORT
DADDRH	EQU	IOBASE+6		;DATA BUFFER HIGH ADDRESS PORT
CADDRH	EQU	IOBASE+7		;COMMAND BUFFER HIGH ADDRESS PORT
;
	EJECT
;
	CSEG
;
	ORG	0
CCP:
	ORG	BIOS			;START OF BIOS 
;
;******************************************************************************
;I/O JUMP VECTOR. THIS IS WHERE CP/M-86 CALLS WHENEVER IT NEEDS TO DO
;ANY INPUT/OUTPUT OPERATION. USER PROGRAMS MAY USE THESE ENTRY POINTS
;******************************************************************************
;
	JMP	INIT			;FROM COLD START LOADER 
	JMP	WBOOT			;FROM WARM BOOT 
	JMP	CONST			;CHECK CONSOLE KB STATUS 
	JMP	CONIN			;READ CONSOLE CHARACTER 
	JMP	CONOUT			;WRITE CONSOLE CHARACTER 
	JMP	LPTOUT			;WRITE LISTING CHAR 
	JMP	PUNCH			;WRITE PUNCH CHAR 
	JMP	READER			;READ READER CHAR 
	JMP	HOME			;MOVE DISK TO TRACK ZERO 
	JMP	SELDSK			;SELECT DISK DRIVE 
	JMP	SETTRK			;SEEK TO TRACK IN REG A 
	JMP	SETSEC			;SET SECTOR NUMBER 
	JMP	SETDMA			;SET DMA OFFSET ADDRESS
	JMP	READ			;READ SELECTED SECTOR
	JMP	WRITE			;WRITE SELECTED
	JMP	LPTSTAT			;RETURN LIST STATUS
	JMP	SECTRAN			;SECTOR TRANSLATE
	JMP	SETDMAB			;SET DMA SEGMENT ADDRESS
	JMP	GETSEGB			;GET MEM DESCRIB TABLE OFFSET
	JMP	GETIOB			;GET I/O MAPPING BYTE
	JMP	SETIOB			;SET I/O MAPPING BYTE
;
	EJECT
;******************************************************************************
;	ROUTINE TO CALL	SIMPLE I/O FUNCTIONS VIA VECTABLE JUMP VECTORS
;******************************************************************************
;
SIMPLEIO:
	PUSH	DS
	PUSH	CS
	POP	DS
	PUSH	DX
	MOV	DX,SI
	ADD	SI,DX
	ADD	SI,DX			;MULTIPLY SI BY 3
	ADD	SI,OFFSET VECTABLE
	POP	DX
	CALL	SI			;INDIRECT CALL THRU ADDRESS FIELDS OF
	PUSHF
	POP	SI			;RETURN FLAGS TO CALLER IN SI REG.
	POP	DS
	IRET				;...SIMPLE I/O VECTOR TABLE
;
	EJECT
;******************************************************************************
;	COLD BOOT INITIALIZATION ROUTINE
;******************************************************************************
;
INIT:
	CLI				;LOCK OUT INTERRUPTS
	MOV	AX,CS			;GET OS SEGMENT ADDRESS
	MOV	SS,AX			;INITIALIZE STACK SEGMENT
	MOV	SP,OFFSET STKBASE	;...AND INITIALIZATION STACK
	MOV	AX,0
	MOV	DS,AX			;PREPARE FOR INT VECTOR INIT
	MOV	ES,AX 
	MOV	INT0OFF,OFFSET TRAP	;SETUP INT0 TO ADDRESS TRAP ROUTINE
	MOV	INT0SEG,CS		;THIS IS 4-BYTE VECTORS
	MOV	DI,4
	MOV	SI,0
	MOV	CX,510			;SET REPEAT COUNTER
	CLD				;SET FORWARD DIRECTION
	REP	MOVS AX,AX		;PROPAGATE TRAP VECTOR TO ALL OF TABLE
	MOV	BDOSOFF,BDOS		;INIT SYSTEM CALL VECTOR
	MOV	RTCOFF,OFFSET RTCINT	;INIT REAL TIME CLOCK VECTOR
	MOV	BIOSOFF,OFFSET SIMPLEIO
;
;	*** INTERRUPT VECTORS INITIALIZED, NOW INIT SYSTEM WORKING STORAGE ***
;
	MOV	AX,CS			;GET OS SEGMENT ADDRESS
	MOV	DS,AX			;INITIALIZE DATA SEGMENT
	MOV	ES,AX			;...AND EXTRA SEGMENT
	MOV	IOERR,0			;START OF ZERO FILL AREA
	MOV	SI,OFFSET IOERR
	MOV	DI,OFFSET IOERR+1 
	MOV	CX,WORD PTR (ENDZ-STARTZ)-1
	CLD				;SET FORWARD DIRECTION
	REP	MOVS AL,AL		;DO THE ZERO FILL
;
;
;	*** INITIALIZE MEMMORY REGION TABLE ***
;
	IN	AL,PIOB			;GET SWITCH SETTING
	AND	AL,0CH			;LEAVE ONLY SWITCH 3 AND 4 BITS
	XOR	AL,0CH			;IF BOTH SWITCHES ARE OPEN
	JZ	NOEXTRAM		;THEN ASSUME NO RAM BOARD INSTALLED
	SHR	AL,1
	SHR	AL,1
	MOV	CL,AL			;COMPUTED SHIFT COUNT
	MOV	AH,10H			;COMPUTE MEMMORY SEGMENT SIZE
	SHL	AH,CL			;...IN PARAGRAPH UNITS
	MOV	AL,0
	MOV	WORD PTR MTR+7,AX	;SAVE IN TABLE
	MOV	WORD PTR MTR+5,4000H	;SAVE START OF EXTRA RAM BOARD
	MOV	BYTE PTR MTR,02		;ELSE ASSUME TWO RAM SEGMENTS
NOEXTRAM:
;
;	*** INITIALIZE INTERRUPT CONTROLER ***
;
	MOV	AL,13H
	OUT	0C0H,AL			;SEND ICW1
	MOV	AL,TIMER
	OUT	0C1H,AL			;SEND ICW2
	MOV	AL,03
	OUT	0C1H,AL			;SEND ICW4
	MOV	AL,0FBH
	OUT	0C1H,AL			;ENABLE PIT-0 INTERRUPTS
	STI				;LET IN REAL TIME CLOCK
;
;	*** PRINT HELLO MESSAGE ON CONSOLE ***
;
	MOV	BX,OFFSET SMSG		;PRINT OPENING MESSAGE 
	CALL	PRTMSG			;PRINT MESSAGE STRING
	MOV	CL,DEFDSK		;GIVE CP/M-86 "DISK SELECTED" NUMBER
	JMP	CCP			;JUMP TO CCP WITH MINI SET CODE
;
	EJECT
;******************************************************************************
;	WARM BOOT ROUTINE
;******************************************************************************
;
WBOOT:
	MOV	AL,0			;SELECT HEAD ZERO (SELECTED DISK = A:)
	MOV	SEKMHD,AL		;SET FLAGS TO HARD DISK FOR POSSIBLE ERROR
	MOV	HSTMHD,AL		;..ROUTINE SCAN
	MOV	HSTACT,AL		;SET HOST BUFFER INACTIVE
	MOV	UNACNT,AL		;CLEAR UNALLOCATED COUNT
	JMP	CCP+6			;GO BACK TO CP/M-86 
;
;
;
;******************************************************************************
;	CONSOLE STATUS ROUTINE
;		RETURNS AL=00H IF NO INPUT READY
;		RETURNS AL=FFH IF INPUT READY
;******************************************************************************
;
CONST:
	PUSH	ES
	TEST	PCIB,0FFFFH		;TEST IF CONSOLE INPUT BUFFER PENDING
	JNZ	PIB			;...FLAG INPUT READY IF SO
;
	MOV	AX,2000H		;INITIALIZE ES TO START
	MOV	ES,AX			;...OF MP2-Z80 RAM
	MOV	BX,IFTOFF+CONCHA+RXF	;QUEUE OFFSET
	CALL	LOOKQ			;GET NBR OF BUFFERS IN QUEUE
	AND	AL,AL
	JZ	CSEXIT			;EXIT IF QUEUE EMPTY
PIB:
	MOV	AL,0FFH			;FLAG QUEUE NOT EMPTY
CSEXIT:
	POP	ES
	RET
;
	EJECT
;******************************************************************************
;	CONSOLE INPUT ROUTINE
;	GETS CHAR TO (AL) REGISTER
;******************************************************************************
;
CONIN:
	PUSH	ES
	MOV	AX,2000H		;Z80 RAM BASE ADDRESS
	MOV	ES,AX
	TEST	PCIB,0FFFFH		;TEST IF BUFFER PENDING
	JNZ	CONIN3			;GO PICK NEXT CHARACTER THERE
;
;
;NO BUFFER PENDING, TRY TO GET ONE.
;
CONIN1:
	MOV	BX,IFTOFF+CONCHA+RXF	;QUEUE OFFSET
	CALL	DEQ			;GET BUFFER
	JNC	CONIN1			;WAIT IF NO BUFFER IN QUEUE
	XCHG	BX,DX			;GET BUFFER ADDRESS INTO BX
	MOV	DX,ES:ÆBXÅ+DPTR		;GET 1. DATA ADDR. FROM QHEAD
	XCHG	BX,DX
	CMP	ES:BYTE PTR ÆBXÅ,ENTDLDU;MUST BE ENTIRE DATA LDU
	JE	CONIN2			;GO GET DATA IF LDU TYPE OK
	MOV	BX,IFTOFF+CONCHA+RXE	;ELSE
	CALL	ENQ			;RELEASE BUFFER AND
	JMPS	CONIN1			;...GO TRY AGAIN
;
;
;INSTALL NEWLY RECEIVED BUFFER AS PENDING.
;
CONIN2:
	MOV	PCIB,DX			;SAVE BUFFER ADDRESS
	INC	BX
	INC	BX			;POINT TO DATABYTE
	MOV	CIBP,BX			;SAVE POINTER TO NEXT CHARACTER
	MOV	BX,DX
	DEC	ES:WORD PTR BYTECÆBXÅ	;DECREMENT BYTECOUNT BY TWO
	DEC	ES:WORD PTR BYTECÆBXÅ
;
	EJECT
;
;
;GET CHARACTER FROM PENDING BUFFER.
;
CONIN3:
	MOV	BX,CIBP			;GET DATAPOINTER
	MOV	AL,ES:ÆBXÅ		;GET DATA FROM BUFFER
	INC	BX			;UPDATE POINTER
	MOV	CIBP,BX			;SAVE NEW POINTER
	MOV	BX,PCIB			;GET BUFFER ADDRESS
	DEC	ES:WORD PTR BYTECÆBXÅ	;DECREMENT BYTECOUNT IN BUFFER
	JNZ	NOTMTY			;EXIT IF NOT EMPTY
;
;
;NO MORE JUICE IN THAT ONE, RELEASE IT.
;
	MOV	DX,PCIB			;GET BUFFER ADDRESS
	MOV	BX,IFTOFF+CONCHA+RXE	;EMPTY QUEUE OFFSET
	PUSH	AX			;SAVE CHARACTER
	CALL	ENQ			;RETURN BUFFER
	MOV	PCIB,0			;NO BUFFER PENDING
	POP	AX
;
;
;THAT'S ALL FOLKS, RETURN TO CALLER
;
NOTMTY:
	POP	ES
	AND	AL,7FH			;MASK OFF PARITYBIT
	RET
;
	EJECT
;
;
;CONSOLE OUTPUT ROUTINE 
;	SENDS CHAR IN (CL) REGISTER
;
CONOUT:
	MOV	AX,2000H		;Z80 RAM BASE ADDRESS
	MOV	CONSEMAP,AH		;LOCKOUT FORWARD TIMER
	PUSH	ES
	MOV	ES,AX
	MOV	BX,CONPTR		;GET CONSOLE BUFFER DATA POINTER
	OR	BX,BX			;IF OLD POINTER INVALID
	JZ	NEWCBUF			;...GO INITIATE NEW CONSOLE BUFFER
;
	MOV	ES:ÆBXÅ,CL		;ELSE SAVE CHARACTER IN PENDING BUFFER
	INC	CONPTR			;UPDATE POINTER
	MOV	BX,CONBUF		;GET BUFFER ADDRESS
	MOV	CL,ES:BYTECÆBXÅ		;GET OLD BYTECOUNT FROM BUFFERHEAD
	INC	CL
	MOV	ES:BYTECÆBXÅ,CL		;STORE NEW BYTECOUNT
	CMP	CL,CBLENGTH		;TEST IF BUFFER IS FULL
	JB	CONOEXIT		;...EXIT IF NOT
;
	MOV	CONPTR,0		;FLAG POINTER AS INVALID
	MOV	DX,IFTOFF+CONCHA+TXF	;QUEUE OFFSET
	XCHG	BX,DX
	CALL	ENQ			;SEND BUFFER TO Z80
	JMPS	CONOEXIT		;EXIT CONOUT
;
	EJECT
;
NEWCBUF:
	PUSH	CX			;SAVE CHARACTER IN CL
CONOUT1:
	MOV	BX,IFTOFF+CONCHA+TXE	;QUEUE OFFSET
	CALL	DEQ			;GET EMPTY BUFFER
	JNC	CONOUT1			;WAIT IF NO BUFFER IN QUEUE
;
	MOV	CONBUF,DX
	MOV	BX,0FH
	ADD	BX,DX			;COMPUTE NEXT-DATA POINTER
	MOV	CONPTR,BX		;SAVE TILL NEXT CONOUT OPERATION
	DEC	BX
	POP	AX			;RESTORE CHARACTER INTO AL
	MOV	ES:ÆBXÅ,AL		;SAVE CHARACTER IN BUFFER
	DEC	BX
	MOV	ES:BYTE PTR ÆBXÅ,CONOPC	;NO LDU NUMBERS
	DEC	BX
	MOV	ES:BYTE PTR ÆBXÅ,ENTDLDU;BUFFER IS ENTIRE DATA LDU
	XCHG	BX,DX
	MOV	ES:DPTRÆBXÅ,DX		;SAVE POINTER IN QHEAD
	MOV	ES:WORD PTR BYTECÆBXÅ,3	;SET BYTECOUNT
CONOEXIT:
	POP	ES			;RESTORE SEGMENT
	MOV	CONSEMAP,0		;LET IN FORWARD TIMER
	RET
;
	EJECT
;
;PUNCH PAPER TAPE, DEFAULT IS SERIAL PRINTER CHANNEL
;
PUNCH:
	JMP	LPTOUT			;SEND PUNCH TO SERIAL OUTPUT
					;RETURN THROUGH LPTOUT
;
;
;READ PAPER TAPE, DEFAULT IS SERIAL PRINTER CHANNEL
;
READER:
	JMP	LPTINP			;READ FROM SERIAL INPUT 
					;RETURN THROUGH LPTINP
;
;
;
;
;LINEPRINTER STATUS ROUTINE
;	RETURNS AL=00H IF LP NOT READY
;	RETURNS AL=FFH IF LP READY
LPTSTAT:
	PUSH	ES
	MOV	AX,2000H		;INITIALIZE ES TO START
	MOV	ES,AX			;...OF MP2-Z80 RAM
	MOV	BX,IFTOFF+LPCHA+TXE	;QUEUE OFFSET
	CALL	LOOKQ			;GET NBR OF BUFFERS IN QUEUE
	AND	AL,AL
	JZ	LPEXIT			;EXIT IF QUEUE EMPTY
	MOV	AL,0FFH			;FLAG QUEUE NOT EMPTY
LPEXIT:
	POP	ES
	RET
;
	EJECT
;
;LINEPRINTER OUTPUT ROUTINE
;	SEND CHARACTER IN (CL) REGISTER
;
LPTOUT:
	MOV	AX,2000H		;Z80 RAM BASE ADDRESS
	MOV	LPTSEMAP,AH		;LOCK OUT FORWARD TIMER
	PUSH	ES
	MOV	ES,AX
	MOV	BX,LPTPTR		;GET PRINTER BUFFER DATA POINTER
	OR	BX,BX			;IF OLD POINTER INVALID
	JZ	NEWPBUF			;...GO INITIATE NEW PRINTER BUFFER
;
	MOV	ES:ÆBXÅ,CL		;ELSE SAVE CHARACTER IN PENDING BUFFER
	INC	LPTPTR			;UPDATE POINTER
	MOV	BX,LPTBUF		;GET BUFFER ADDRESS
	MOV	CL,ES:BYTECÆBXÅ		;GET OLD BYTECOUNT FROM BUFFERHEAD
	INC	CL
	MOV	ES:BYTECÆBXÅ,CL		;STORE NEW BYTECOUNT
	CMP	CL,LBLENGTH		;TEST IF BUFFER IS FULL
	JB	LPTOEXIT		;...EXIT IF NOT	
;
	MOV	LPTPTR,0		;FLAG POINTER AS INVALID
	MOV	DX,IFTOFF+LPCHA+TXF	;QUEUE OFFSET
	XCHG	BX,DX
	CALL	ENQ			;SEND BUFFER TO Z80
	JMPS	LPTOEXIT		;EXIT LPTOUT
;
	EJECT
;
NEWPBUF:
	PUSH	CX			;SAVE CHARACTER IN CL
LPTOUT1:
	MOV	BX,IFTOFF+LPCHA+TXE	;QUEUE OFFSET
	CALL	DEQ			;GET EMPTY BUFFER
	JNC	LPTOUT1			;WAIT IF NO BUFFER IN QUEUE
;
	MOV	LPTBUF,DX
	MOV	BX,0FH
	ADD	BX,DX			;COMPUTE NEXT-DATA POINTER
	MOV	LPTPTR,BX		;SAVE TILL NEXT LPTOUT OPERATION
	DEC	BX
	POP	AX			;RESTORE CHARACTER INTO AL
	MOV	ES:ÆBXÅ,AL		;SAVE CHARACTER IN BUFFER
	DEC	BX
	MOV	ES:BYTE PTR ÆBXÅ,LPOPC	;NO LDU NUMBERS
	DEC	BX
	MOV	ES:BYTE PTR ÆBXÅ,ENTDLDU;BUFFER IS ENTIRE DATA LDU
	XCHG	BX,DX
	MOV	ES:DPTRÆBXÅ,DX		;SAVE POINTER IN QHEAD
	MOV	ES:WORD PTR BYTECÆBXÅ,3	;SET BYTECOUNT
LPTOEXIT:
	POP	ES			;RESTORE SEGMENT
	MOV	LPTSEMAP,0		;LET IN FORWARD TIMER
	RET
;
	EJECT
;
;SELECT DISK NUMBER ACCORDING TO (CL)
;
;	0=A:,1=B:
;
SELDSK:
	MOV	BX,0			;RETURN 0000 IN BX IF ERROR
	CMP	CL,MAXDISK		;IS SELECT MORE THAN MAX TABLE ENTRY
	JB	SEL1			;RETURN WITH ERROR, IF NOT VALID TABLE ENTRY
	RET
SEL1:
	PUSH	BX			;CHECK IF VALID FROM TABLE
	MOV	BL,CL
	SHL	BL,1			;MAKE UNIT SELECT TABLE INDEX
	SHL	BL,1
	ADD	BX,OFFSET DSTAB		;DRIVE SETUP TABLE BASE
	MOV	AL,ÆBXÅ			;GET VALIDITY BYTE THIS UNIT
	OR	AL,AL			;ZERO = ILLEGAL
	XCHG	BX,DX			;SAVE POINTER IF NO EXIT
	POP	BX			;GET BACK BX TO ZERO FOR ERROR EXIT
	JNZ	SEL2			;RETURN ON ILLEGAL UNIT
	RET
SEL2:
	MOV	SEKDSK,CL
;
	XCHG	BX,DX			;IS A LEGAL SELECT THEN PROCESS 
					;PARAMETERS
	INC	BX			;POINT TO DRIVE PHYSICAL UNIT NUMBER
					;DRIVE PHYSICAL UNIT NUMBER NOT USED
					;TILL I/O ROUTINES WHEN THE DRIVE IS USED
;
	INC	BX			;POINT TO MINI/HARD FLAG
	MOV	AL,ÆBXÅ
	MOV	SEKMHD,AL		;SET CURRENTLY SELECTED TYPE FLAG
;
	INC	BX			;POINT TO CP/M-86 DISK PARAMETER TABLE INDEX
	MOV	BL,ÆBXÅ			;MAKE DOUBLE TABLE INDEX*16
	MOV	BH,00H
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	ADD	BX,OFFSET DPBASE	;BX=POINTER TO DRIVE PARAMETER TABLE
	RET
;
;
;
;
;SUBROUTINE TO GET THE PHYSICAL DRIVE NUMBER OUT OF THE DRIVE
;SELECT PARAMETER TABLE INTO (CL)
;
GETDRNO:
	MOV	BL,HSTDSK		;GET UNIT CP/M-86 THINKS WE HAVE
	SHL	BL,1			;SETUP INDEX INTO FOUR BYTE TABLE
	SHL	BL,1			;ENTRIES
	MOV	BH,0
	MOV	CL,OFFSET DSTAB+1ÆBXÅ	;GET PHYSICAL NUMBER INTO (CL)
	RET
;
	EJECT
;******************************************************************************
;	SELECT TRACK ZERO FOR NEXT DISK ACCESS (HOME DISK)
;******************************************************************************
;
HOME:
	MOV	AL,HSTWRT		;CHECK FOR PENDING WRITE
	OR	AL,AL
	JNZ	HOMEIT
	MOV	HSTACT,AL		;CLEAR HOST ACTIVE FLAG
HOMEIT:
	MOV	SEKTRK,0000H		;ITS LIKE WE ARE GOING TO TRACK 0
	XOR	AL,AL
	RET				;RETURN FROM HOME, O.K. 
;
;
;SET TRACK NUMBER SPECIFIED BY CX REG.
;
SETTRK:
	MOV	SEKTRK,CX		;TRACK TO SEEK
	RET
;
;
;
;TRANSLATE THE SECTOR GIVEN BY CX REG.
;
;	NO TRANSLATE DONE AT THIS TIME. 
;	WE WILL TRANSLATE THE MINI FLOPPY AT THE PHYSICAL SECTOR
;	BASIS IN THE MINI FLOPPY READ/WRITE SETUP ROUTINE.
;
SECTRAN:
	MOV	BX,CX
	RET				;RETURN FROM SECTRAN
;
;
;
;
;SET DISK SECTOR NUMBER 
;
SETSEC:
	MOV	SEKSEC,CL		;SECTOR TO SEEK
	RET				;RETURN FROM SETSEC
	EJECT
;
;
;SET DISK DMA OFFSET
;
SETDMA:
	MOV	DMAADR,CX		;PUT AT DMA ADR ADDRESS
	RET				;RETURN FROM SETDMA
;
;
;
;SET DMA SEGMENT
;
SETDMAB:
	MOV	DEFDMASG,CX
	RET
;
;
;
;GET MEMMORY REGION TABLE OFFSET
;
GETSEGB:
	MOV	BX,OFFSET MTR
	RET
;
;
;
;GET IOBYTE
;
GETIOB:
	MOV	AL,IOBYTE
	RET
;
;
;
;SET IOBYTE
;
SETIOB:
	MOV	IOBYTE,CL
	RET
;
	EJECT
;
;	***  READ THE SELECTED CP/M-86  SECTOR  ***
;
READ:
	XOR	AL,AL
	MOV	UNACNT,AL		;CLEAR UNALLOCATED COUNT
	INC	AL
	MOV	READOP,AL		;READ OPERATION
	MOV	RSFLAG,AL		;MUST READ DATA
	MOV	AL,WRUAL
	MOV	WRTYPE,AL		;TREAT AS UNALLOCCATED
	JMP	RWOPER			;TO PERFORM THE READ
;
;
;	***  WRITE THE SELECTED CP/M-86  SECTOR  ***
;
WRITE:
	MOV	READOP,0		;NOT A READ OPERATION
	MOV	WRTYPE,CL
	CMP	CL,WRUAL		;WRITE UNALLOCATED?
	JNE	CHKUNA			;CHECK FOR UNALLOCATED
;
;WRITE TO UNALLOCATED, SET PARAMETERS
;
	MOV	UNACNT,BLKSIZ/128	;NEXT UNALLOCATED RECORDS
	MOV	AL,SEKDSK		;DISK TO SEEK
	MOV	UNADSK,AL		;UNADSK = SEKDSK
	MOV	BX,SEKTRK
	MOV	UNATRK,BX		;UNATRK = SECTRK
	MOV	AL,SEKSEC
	MOV	UNASEC,AL		;UNASEC = SEKSEC
;
;CHECK FOR WRITE TO UNALLOCATED SECTOR
;
CHKUNA:
	MOV	AL,UNACNT		;ANY UNALLOCATED REMAINING?
	OR	AL,AL
	JZ	ALLOC			;SKIP IF NOT
;
	EJECT
;
;MORE UNALLOCATED RECORDS REMAIN
;
	DEC	AL			;UNACNT = UNACNT-1
	MOV	UNACNT,AL
	MOV	AL,SEKDSK		;SAME DISK?
	CMP	AL,UNADSK		;SEKDSK = UNADSK?
	JNE	ALLOC			;SKIP IF NOT
;
;
;DISKS ARE THE SAME
;
	MOV	BX,UNATRK
	CMP	BX,SEKTRK		;SEKTRK = UNATRK?
	JNE	ALLOC			;SKIP IF NOT
;
;
;TRACKS ARE THE SAME
;
	MOV	AL,SEKSEC		;SAME SECTOR?
	MOV	BX,OFFSET UNASEC
	CMP	AL,ÆBXÅ			;SEKSEC = UNASEC?
	JNE	ALLOC			;SKIP IF NOT
;
	EJECT
;
;MATCH, MOVE TO NEXT SECTOR FOR FUTURE REFERENCE
;
	INC	AL
	MOV	ÆBXÅ,AL			;UNASEC=UNASEC+1
	MOV	AH,HDSPT		;USE HARD DISK SECTORS PER TRACK
	TEST	SEKMHD,0FFH		;CHECK KIND OF DISK
	JZ	MTCHCMP			;HARD DISK MATCH
	MOV	AH,FDSPT		;USE MINI DISK SPT
MTCHCMP:
	CMP	AL,AH
	JB	NOOVF			;SKIP IF NO OVERFLOW
;
;
;OVERFLOW TO NEXT TRACK
;
	MOV	BYTE PTR ÆBXÅ,0		;UNASEC = 0
	INC	WORD PTR UNATRK		;UNATRK = UNATRK+1
;
;
;MATCH FOUND, MARK AS UNNECESSARY READ
;
NOOVF:
	MOV	RSFLAG,0		;RSFLAG = 0
	JMPS	RWOPER			;TO PERFORM THE WRITE
;
;
;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
;
ALLOC:
	XOR	AL,AL			;0 TO A REG.
	MOV	UNACNT,AL		;UNACNT = 0
	INC	AL			;1 TO A REG.
	MOV	RSFLAG,AL		;RSFLAG = 1
;
	EJECT
;******************************************************************************
;	COMMON CODE FOR READ AND WRITE OPERATIONS
;******************************************************************************
;
RWOPER:					;ENTER HERE TO PERFORM THE READ/WRITE
	MOV	ERFLAG,0		;NO ERRORS (YET)
	MOV	AL,SEKSEC		;COMPUTE HOST SECTOR
	MOV	CL,SECSHF
	SHR	AL,CL
;
;
;OUR DISK CONTROLLER NUMBERS ITS RECORDS FROM 1 AND NOT ZERO
;SO FIXUP THE "SEKHST" SECTOR NUMBER
;
	INC	AL
	MOV	SEKHST,AL		;HOST SECTOR TO SEEK
;
;
;ACTIVE HOST SECTOR?
;
	MOV	BX,OFFSET HSTACT	;HOST ACTIVE FLAG
	MOV	AL,ÆBXÅ
	MOV	BYTE PTR ÆBXÅ,1		;ALWAYS BECOMES 1
	OR	AL,AL			;WAS IT ALREADY?
	JZ	FILHST			;FILL HOST IF NOT
;
;
;HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
;
	MOV	AL,SEKDSK
	CMP	AL,HSTDSK		;SAME DISK?
	JNE	NOMATCH
;
;
;SAME DISK, SAME TRACK?
;
	MOV	BX,HSTTRK
	CMP	BX,SEKTRK		;SEKTRK = HSTTRK?
	JNE	NOMATCH
;
	EJECT
;
;SAME DISK, SAME TRACK, SAME BUFFER?
;
	MOV	AL,SEKHST
	CMP	AL,HSTSEC		;SEKHST = HSTSEC?
	JE	MATCH			;SKIP IF MATCH
;
;
;PROPER DISK, BUT NOT CORRECT SECTOR
;
NOMATCH:
	TEST	HSTWRT,0FFH		;HOST WRITTEN?
	JZ	FILHST
	CALL	WRITEHST		;CLEAR HOST BUFF
	OR	AL,AL			;CHECK FOR WRITE ERRORS
	JZ	FILHST
	RET				;BALE OUT TO BDOS IF ERROR
;
;
;MAY HAVE TO FILL THE HOST BUFFER
;
FILHST:
	MOV	AL,SEKMHD		;COPY SELECTED TYPE TO OPERATION TYPE
	MOV	HSTMHD,AL
	MOV	AL,SEKDSK		;COPY SELECTED DISK TO OPERATION DISK
	MOV	HSTDSK,AL
	MOV	BX,SEKTRK		;COPY SELECTED TRACK TO OPERATION TRACK
	MOV	HSTTRK,BX
	MOV	AL,SEKHST		;COPY SELECTED PHYS SECTOR TO OPERATION SECTOR
	MOV	HSTSEC,AL
	TEST	RSFLAG,0FFH		;NEED TO READ?
	JZ	MATCH			;SKIP PREREAD
;
	CALL	READHST			;YES, IF 1
	MOV	HSTWRT,0		;NO PENDING WRITE
	OR	AL,AL			;CHECK ERROR ON PREREAD?
	JZ	MATCH
	RET				;BACK TO BDOS IF ERROR IN READING
;
	EJECT
;
;COPY DATA TO OR FROM BUFFER
;
MATCH:
	MOV	BL,SEKSEC		;MASK BUFFER NUMBER
	AND	BL,SECMSK		;LEAST SIGNIF BITS
	MOV	BH,0
;
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1
	SHL	BX,1			;SHIFT INTO HOST BUFFER OFFSET
;
;
;BX HAS RELATIVE HOST BUFFER ADDRESS
;
	MOV	SI,OFFSET HSTBUF
	ADD	SI,BX			;SI = HOST ADDRESS
	MOV	DI,DMAADR		;GET DESTIGNATION OFFSET  FOR READ
	MOV	ES,DEFDMASG		;GET DESTIGNATION SEGMENT FOR READ
	MOV	CX,128			;LENGTH OF MOVE (CP/M-86 SECTOR SIZE)
	TEST	READOP,0FFH		;WHICH WAY?
	JNZ	RWMOVE			;SKIP IF READ
;
;
;WRITE OPERATION, MARK AND SWITCH DIRECTION
;
	MOV	HSTWRT,1		;HSTWRT = 1
	XCHG	SI,DI			;SOURCE/DESTINATION SWAP
	MOV	AX,ES
	PUSH	DS
	POP	ES
	MOV	DS,AX			;SWAP ALSO INVOLVED SEGMENTS
;
	EJECT
;
;CX INITIALLY 128, DX IS SOURCE, BX IS DESTINATION
;
RWMOVE:
	CLD				;SET FORWARD DIRECTION
	REP	MOVS AL,AL		;MOVE IT
	MOV	AX,CS
	MOV	DS,AX
	MOV	ES,AX			;RESTORE SEGMENT REGISTERS
;
;DATA HAS BEEN MOVED TO/FROM HOST BUFFER
;
	MOV	AL,WRTYPE		;WRITE TYPE
	CMP	AL,WRDIR		;TO DIRECTORY?
	MOV	AL,ERFLAG		;IN CASE OF ERRORS
	JZ	CHB
	RET				;NO FURTHER PROCESSING
;
;
;CLEAR HOST BUFFER FOR DIRECTORY WRITE
;
CHB:
	OR	AL,AL			;ERRORS?
	JZ	CHB1
	RET				;SKIP IF SO
CHB1:
	MOV	HSTWRT,0		;BUFFER WRITTEN
	CALL	WRITEHST
	RET
;
	EJECT
;PERFORMS THE PHYSICAL WRITE TO THE HOST DISK.
;HSTDSK = HOST DISK NUMBER, HSTTRK = HOST TRACK NUMBER,
;HSTSEC = HOST SECT NUMBER. WRITE "HSTSIZ" BYTES
;FROM HSTBUF AND RETURN ERROR FLAG IN ERFLAG.
;RETURN: AL = ERFLAG = NON-ZERO IF ERROR
;
WRITEHST:
	CALL	MIOPB			;SET MINI FLOPPY IOPB
	CALL	MWRIT			;GO WRITE MINI FLOPPY SECTOR
	OR	AL,AL
	JNZ	WRTERR			;EXIT FOR WRITE ERROR
	MOV	ERFLAG,AL		;RESET ERROR FLAG
	RET				;RETURN FROM "WRITEHST", IF O.K. 
WRTERR:
	CALL	EREXIT			;PRINT BIOS ERROR MESSAGE
	MOV	AL,01H			;SET ERROR FLAG
	MOV	ERFLAG,AL
	RET
;
;
;HSTDSK = HOST DISK NUMBER, HSTTRK = HOST TRACK NUMBER,
;HSTSEC = HOST SECT NUMBER. READ "HSTSIZ" BYTES
;INTO HSTBUF AND RETURN ERROR FLAG IN ERFLAG AND AL.
;
READHST:
	CALL	MIOPB			;SETUP MINI FLOPPY IOPB
	CALL	MREAD			;GO READ MINI FLOPPY SECTOR
	OR	AL,AL
	JNZ	RDERR			;EXIT FOR READ ERROR
	MOV	ERFLAG,AL
	RET
RDERR:
	CALL	EREXIT			;PRINT BIOS ERROR MESSAGE
	MOV	AL,01H			;SET ERROR FLAG
	MOV	ERFLAG,AL
	RET

	EJECT
;READ/WRITE BIOS ERROR PRINT ROUTINE
;WAITS FOR USER RESPONSE ON CONSOLE AFTER PRINTING MESSAGE
;AND THEN RETURNS TO THE CALLER
;
EREXIT:
	MOV	IOERR,AL		;SAVE ERROR STATUS
	MOV	BX,OFFSET ERRMSF	;MINI FLOPPY ERROR MESSAGE 
	CALL	PRTMSG
	MOV	AL,IOERR		;PRINT ERROR CODE
	PUSH	AX
	MOV	CL,4
	SHR	AL,CL
	CALL	HEXOUT
	POP	AX
	CALL	HEXOUT
	MOV	BX,OFFSET ERRMS2	;PRINT REST OF MESSAGE
	CALL	PRTMSG
	MOV	AL,HSTDSK		;PRINT CP/M-86 DRIVE DESIGNATOR WITH ERROR
	ADD	AL,'A'
	MOV	CL,AL
	CALL	CONOUT
	MOV	BX,OFFSET ERRMS3	;PRINT MESSAGE CLOSE
	CALL	PRTMSG
	CALL	CONIN			;WAIT FOR OPERATOR RESPONSE
	CMP	AL,03			;IF CTL-C THEN GO DO WARM BOOT
	JNZ	ERR1
	JMP	WBOOT
ERR1:
	MOV	BX,OFFSET ERRMS4
	CALL	PRTMSG
	RET				;BACK TO CP/M-86
	EJECT
;
;SUBROUTINE TO SEND A HEX CHAR TO THE CONSOLE
;
HEXOUT:
	AND	AL,0FH			;LOW NIBBLE ONLY
	CMP	AL,0AH			;GREATER THAN 9?
	JB	HEX1
	ADD	AL,07H			;ADD OFFSET FOR A-F
HEX1:
	ADD	AL,030H			;ADD IN ASCII OFFSET
	MOV	CL,AL			;PRINT RESULT
	CALL	CONOUT
	RET
;
;MINI FLOPPY I/O PARAMETER BLOCK SET UP ROUTINE
;
MIOPB:
	CALL	GETDRNO			;GET PHYSICAL DRIVE NUMBER FROM
	CALL	MUNIT			;..FROM DRIVE SELECT TABLE
	MOV	CX,HSTTRK		;GET TRACK NUMBER
	AND	CL,01H			;FIND OUT WHAT THE SIDE NUMBER IS
	CALL	MSURF			;SET MINI HEAD NUMBER
	MOV	CX,HSTTRK		;GET TRACK NUMBER
	SHR	CX,1			;DIVIDE TRACK BY 2
	CALL	MCYL
	MOV	CL,00H			;SET SIZE CODE TO 256 BYTES
	CALL	MSIZE
	MOV	CL,02H			;SET SECTOR COUNT TO 2
	CALL	MCNT
	MOV	BL,HSTSEC		;CONVERT SECTOR NUMBER TO PROPER SKEW
	DEC	BL			;NOW ZERO BASED FOR INDEXING
	XOR	BH,BH			;DOUBLE BYTE INDEX WORD
	MOV	CL,MFSTRANÆBXÅ
	CALL	MREC			;SET ACTUAL SECTOR TO START READ UPON
	MOV	CX,OFFSET HSTBUF	;SET FLOPPY BUFFER ADDRESS
	CALL	MBADDR
	MOV	CX,1040H		;GLOBAL SEGMENT TO HOST BUFFER
	CALL	MSEG
	RET
	EJECT
;******************************************************************************
;
;
;PRINT THE MESSAGE AT BX UNTIL A ZERO 
;
;
PRTMSG:
	MOV	CL,ÆBXÅ			;GET CHARACTER TO PRINT
	OR	CL,CL			;SET FLAGS
	JZ	PRTDONE			;RETURN, IF END OF STRING FLAG
	PUSH	BX			;SAVE MESSAGE POINTER
	CALL	CONOUT			;PRINT CHARACTER, CONSOLE OUTPUT
	POP	BX			;GET POINTER BACK
	INC	BX			;BUMP MESSAGE POINTER
	JMPS	PRTMSG
PRTDONE:
	RET
;
;
;
;
;
;******************************************************************************
;
;DUMMY INTERRUPT TRAP ROUTINE
;
TRAP:
	IRET
;
	EJECT
;******************************************************************************
;
;	FIXED ADDRESS I/O ROUTINES TO BE UTILIZED BY CP/M-86 ON MINI FLOPPY,
;	HARD DISK, CONSOLE I/O, LINE PRINTER I/O. THESE ROUTINES ARE USED BY
;	UTILITIES, SUCH AS DISK FORMATTING AND SYSTEM TRACK ACCESS UTILITIES.
;	AN EXTRA ENTRY IN THE BIOS JUMP VECTOR TABLE (CS:253FH) HAS BEEN
;	ADDED. THIS ROUTINE WILL RETURN BX = OFFSET VECTABLE
;
VECTABLE:				;VECTOR TABLE BASE OFFSET
;
LPTINP:	JMP	LPIN			;GET CHARACTER FROM LINEPRINTER
LOOKQ:	JMP	LQ			;GET QUEUE STATUS
DEQ:	JMP	DQ			;GET BUFFER FROM QUEUE
ENQ:	JMP	NQ			;PUT BUFFER INTO QUEUE
HUNIT:	JMP	HDUMMY			;SELECT HARD DISK UNIT NUMBER
HPLAT:	JMP	HDUMMY			;SELECT HARD DISK PLATTER NUMBER 
HSURF:	JMP	HDUMMY			;SELECT HARD DISK SURFACE(HEAD) NUMBER
HCYL:	JMP	HDUMMY			;SELECT HARD DISK CYLINDER NUMBER
HREC:	JMP	HDUMMY			;SELECT HARD DISK RECORD NUMBER
HCNT:	JMP	HDUMMY			;SELECT HARD DISK SECTOR COUNT
HBADDR:	JMP	HDUMMY			;SET DATA BUFFER OFFSET
HSEG:	JMP	HDUMMY			;SET DATA BUFFER SEGMENT
HREST:	JMP	HDUMMY			;RESTORE SELECTED HARD DISK UNIT
HREAD:	JMP	HDUMMY			;READ SELECTED SECTOR(S)
HVERF:	JMP	HDUMMY			;VERIFY SELECTED SECTOR(S)
HWRIT:	JMP	HDUMMY			;WRITE SELECTED SECTOR(S);
HEXEC:	JMP	HDUMMY			;EXECUTE SPECIAL COMMAND OF DTC
HRESET:	JMP	HDUMMY			;RESTART HARD DISK CONTROLLER
MUNIT:	JMP	MSETUNIT		;SELECT MINI FLOPPY UNIT NUMBER
MSURF:	JMP	MSETSUR			;SELECT MINI FLOPPY SURFACE(HEAD) NUMBER
MCYL:	JMP	MSETCYL			;SELECT MINI FLOPPY CYLINDER (TRACK) NUMBER
MREC:	JMP	MSETREC			;SELECT MINI FLOPPY RECORD NUMBER
MCNT:	JMP	MSETCNT			;SELECT MINI FLOPPY PHYSICAL SECTOR COUNT
MSIZE:	JMP	MSETSIZE		;SET MINI FLOPPY SECTOR SIZE (00=256 BYTES)
MBADDR:	JMP	MSETBUF			;SET FLOPPY DISK DATA BUFFER ADDRESS
MSEG:	JMP	MSETSEG			;SET FLOPPY DISK DATA BUFFER SEGMENT
MREST:	JMP	FRESTR			;RESTORE SELECTED MINI FLOPPY UNIT
MVERF:	JMP	MVERSEC			;VERIFY (READ) SELECTED SECTOR
MWRIT:	JMP	MPUTSEC			;WRITE SELECTED SECTOR
MREAD:	JMP	MGETSEC			;READ SELECTED SECTOR
MWTRK:	JMP	MWRTTRK			;WRITE SELECTED FLOPPY TRACK
;
HDUMMY:	MOV	AL,01			;RETURN ERROR FOR CALLS TO
	RET				;HARD DISK ROUTINES.
					;(NOT AVAILABLE)
;  
;******************************************************************************
;	LINEPRINTER INPUT ROUTINE
;	GETS CHAR TO (AL) REGISTER
;******************************************************************************
;
LPIN:
	PUSH	ES
	MOV	AX,2000H		;Z80 RAM BASE ADDRESS
	MOV	ES,AX
	TEST	PLIB,0FFFFH		;TEST IF BUFFER PENDING
	JNZ	LPIN3			;GO PICK NEXT CHARACTER THERE
;
;NO BUFFER PENDING, TRY TO GET ONE.
;
LPIN1:
	MOV	BX,IFTOFF+LPCHA+RXF	;QUEUE OFFSET
	CALL	DEQ			;GET BUFFER
	JNC	LPIN1			;WAIT IF NO BUFFER IN QUEUE
	XCHG	BX,DX			;GET BUFFER ADDRESS INTO BX
	MOV	DX,ES:ÆBXÅ+DPTR		;GET 1. DATA ADDR. FROM QHEAD
	XCHG	BX,DX
	CMP	ES:BYTE PTR ÆBXÅ,ENTDLDU;MUST BE ENTIRE DATA LDU
	JE	LPIN2			;GO GET DATA IF LDU TYPE OK
	MOV	BX,IFTOFF+LPCHA+RXE	;ELSE
	CALL	ENQ			;RELEASE BUFFER AND
	JMPS	LPIN1			;...GO TRY AGAIN
;
;INSTALL NEWLY RECEIVED BUFFER AS PENDING.
;
LPIN2:
	MOV	PLIB,DX			;SAVE BUFFER ADDRESS
	INC	BX
	INC	BX			;POINT TO DATABYTE
	MOV	LIBP,BX			;SAVE POINTER TO NEXT CHARACTER
	MOV	BX,DX
	DEC	ES:WORD PTR BYTECÆBXÅ	;DECREMENT BYTECOUNT BY TWO
	DEC	ES:WORD PTR BYTECÆBXÅ
	EJECT
;
;
;GET CHARACTER FROM PENDING BUFFER.
;
LPIN3:
	MOV	BX,LIBP			;GET DATAPOINTER
	MOV	AL,ES:ÆBXÅ		;GET DATA FROM BUFFER
	INC	BX			;UPDATE POINTER
	MOV	LIBP,BX			;SAVE NEW POINTER
	MOV	BX,PLIB			;GET BUFFER ADDRESS
	DEC	ES:WORD PTR BYTECÆBXÅ	;DECREMENT BYTECOUNT IN BUFFER
	JNZ	LBNMTY			;EXIT IF NOT EMPTY
;
;
;NO MORE JUICE IN THAT ONE, RELEASE IT.
;
	MOV	DX,PLIB			;GET BUFFER ADDRESS
	MOV	BX,IFTOFF+LPCHA+RXE	;EMPTY QUEUE OFFSET
	PUSH	AX			;SAVE CHARACTER
	CALL	ENQ			;RETURN BUFFER
	MOV	PLIB,0			;NO BUFFER PENDING
	POP	AX
;
;
;THAT'S ALL FOLKS, RETURN TO CALLER
;
LBNMTY:
	POP	ES
	AND	AL,7FH			;MASK OFF PARITYBIT
	RET
;
	EJECT
;
;******************************************************************************
;	THIS MODULE CONTAINS THE INTERFACE ROUTINES NESSESARY FOR
;	INTER-CPU COMMUNICATION VIA THE CHRISTIAN ROVSING A/S CR80 -
;	LTU STANDARD QUEUE INTERFACE.
;******************************************************************************
;
;
;	THE MODULE CONSISTS OF THE FOLLOWING ROUTINES:
;
;		LOOKQ:	RETURNS AL = NBR. OF BUFFERS IN QUEUE
;
;		DEQ:	POLL DESIRED QUEUE
;
;		ENQ:	SEND BUFFER TO DESIRED QUEUE
;
;	ALL ROUTINES EXPECTS REG. ES TO CONTAIN THE BASE ADDRESS OF THE
;	BOARD IN WHICH THE QUEUE EXISTS. WHEN COMMUNICATING WITH A
;	SCI BOARD THIS BASE MUST BE COMPENSATED BECAUSE THE SCI RAM
;	HAS DIFFERENT BASE ADDRESS SEEN FROM THE MULTIBUS THAN SEEN
;	FROM THE ONBOARD CPU, WHILE THE Z80 RAM ON THE MP2-BOARD HAS
;	GOT SAME BASE ADDRESS SEEN FROM BOTH SIDES (LOWER 16 BITS).
;	THIS STATES THE FOLLOWING VALUES FOR ES:
;		MP2: ES=2000	SCI: ES=BOARD ADR.-200H
;
;
;******************************************************************************
	EJECT
;******************************************************************************
;
;	THIS ROUTINE WILL POLL THE SPECIFIED QUEUE FOR A BUFFER COUNT.
;
;	ENTRY:
;		ES = BOARD/RAM BASE ADDRESS
;		BX = QUEUE OFFSET FROM BASE
;
;	EXIT:
;		AL = NBR OF BUFFERS IN QUEUE
;
LQ:
	MOV	ES:BYTE PTR ÆBXÅ+SF,01	;SET SLAVE FLAG
	TEST	ES:BYTE PTR ÆBXÅ+MF,01	;TEST MASTER FLAG
	JZ	LOOKACC			;JUMP IF ACCESS GRANDED
	MOV	ES:BYTE PTR ÆBXÅ+SF,00	;CLEAR SLAVE FLAG
LOOKBSY:
	CALL	QDELAY			;DON'T USE ALL OF HIS BUS TIME
	TEST	ES:BYTE PTR ÆBXÅ+MF,01	;SEE IF MASTER ACCESS COMPLETED
	JNZ	LOOKBSY			;WAIT IF NOT
	JMPS	LQ			;GO TRY TO GET GRAND AGAIN
LOOKACC:
	MOV	AL,ES:ÆBXÅ+BC		;GET BUFFERCOUNT FROM QUEUE
	MOV	ES:BYTE PTR ÆBXÅ+SF,00	;CLEAR SLAVE FLAG
	RET
;
;
;
;
QDELAY:
	NOP
	NOP
	RET
;
	EJECT
;******************************************************************************
;
;	THIS ROUTINE WILL POLL THE SPECIFIED QUEUE FOR A BUFFER.
;
;	ENTRY:
;		ES = BOARD/RAM BASE ADDRESS
;		BX = QUEUE OFFSET FROM BASE
;
;	EXIT:
;		IF CARRY=1, DX=POINTER TO BUFFER
;		IF CARRY=0, DX UNDEFINED
;
DQ:
	MOV	ES:BYTE PTR ÆBXÅ+SF,01	;SET SLAVE FLAG
	TEST	ES:BYTE PTR ÆBXÅ+MF,01	;TEST MASTER FLAG
	JZ	DEQACC			;JUMP IF ACCESS GRANDED
	MOV	ES:BYTE PTR ÆBXÅ+SF,00	;CLEAR SLAVE FLAG
DEQBSY:
	CALL	QDELAY			;DON'T USE ALL OF HIS BUS TIME
	TEST	ES:BYTE PTR ÆBXÅ+MF,01	;SEE IF MASTER ACCESS COMPLETED
	JNZ	DEQBSY			;WAIT IF NOT
	JMPS	DQ			;GO TRY TO GET GRAND AGAIN
DEQACC:
	TEST	ES:BYTE PTR ÆBXÅ+BC,0FFH;TEST IF QUEUE IS EMPTY (+CY:=0)
	JZ	DEQMTY			;EXIT IF NO BUFFERS IN QUEUE
	DEC	ES:BYTE PTR ÆBXÅ+BC	;DECREMENT BUFFERCOUNT
	MOV	DX,ES:ÆBXÅ+FB		;GET BUFFER ADDRESS FROM QUEUE
	XCHG	BX,DX
	MOV	AX,ES:ÆBXÅ		;GET POINTER TO NEXT BUFFER IN QUEUE
	XCHG	BX,DX
	MOV	ES:ÆBXÅ+FB,AX		;INSERT AS FIRST BUFFER IN QUEUE
	STC				;FLAG BUFFER RECEIVED
DEQMTY:
	MOV	ES:BYTE PTR ÆBXÅ+SF,00	;CLEAR SLAVE FLAG
	RET
;
	EJECT
;******************************************************************************
;
;	THIS ROUTINE WILL APPEND A BUFFER TO THE SPECIFIED QUEUE.
;
;	ENTRY:
;		BX = POINTER TO QUEUE
;		DX = POINTER TO BUFFER
;		ES = BOARD/RAM BASE ADDRESS
;
;	EXIT:
;		ES UNCHANGED, NO PARAMETERS
;
NQ:
	MOV	ES:BYTE PTR ÆBXÅ+MF,01	;SET MASTER FLAG
ENQBSY:
	TEST	ES:BYTE PTR ÆBXÅ+SF,01	;SEE IF SLAVE IS IN THERE
	JZ	ENQACC			;PROCEED IF NOT
	CALL	QDELAY			;DON'T USE ALL OF HIS BUS TIME
	JMPS	ENQBSY			;WAIT UNTIL HE COMES OUT
ENQACC:
	MOV	AX,ES:ÆBXÅ+LB		;GET OLD LAST BUFFER
	MOV	ES:ÆBXÅ+LB,DX		;SAVE NEW LAST BUFFER
	TEST	ES:BYTE PTR ÆBXÅ+BC,0FFH;TEST BUFFERCOUNT IN QUEUE
	JZ	ENQMTY			;JUMP IF QUEUE WAS EMPTY
;
	XCHG	BX,AX
	MOV	ES:ÆBXÅ,DX		;UPDATE ITS CHAIN ELEMENT
	XCHG	BX,AX
	JMPS	ENQXIT
ENQMTY:
	MOV	ES:ÆBXÅ+FB,DX		;UPDATE ALSO FIRST BUFFER POINTER
ENQXIT:
	INC	ES:BYTE PTR ÆBXÅ+BC	;INCREMENT BUFFER COUNT IN QUEUE
	MOV	ES:BYTE PTR ÆBXÅ+MF,00	;CLEAR MASTER FLAG
	RET
;
	EJECT
;******************************************************************************
;
;	SHORT DELAY ROUTINE FOR TIME DELAYS OF (AL) X 1 MSEC
;
;
SDLY:
	MOV	CX,250			;ONE MILLISECOND TIME FACTOR
SDLOP:
	LOOP	SDLOP
	DEC	AL
	JNZ	SDLY
	RET
;

	EJECT
;******************************************************************************
;	MINI FLOPPY DISK CONTROLLER I/O ROUTINES
;******************************************************************************
;
;
;
;SELECT MINI FLOPPY UNIT NUMBER
;(CL)=FLOPPY PHYSICAL UNIT NUMBER
;
MSETUNIT:
	MOV	FUNIT,CL
	RET
;
;
;
;SELECT MINI FLOPPY SURFACE(HEAD) NUMBER
;(CL)=FLOPPY SIDE NUMBER
;
MSETSUR:
	MOV	FSIDE,CL
	RET
;
;
;
;SELECT MINI FLOPPY CYLINDER (TRACK) NUMBER
;(CL)=FLOPPY TRACK NUMBER
;
MSETCYL:
	MOV	FTRK,CL
	RET
;
;
;
;SELECT MINI FLOPPY RECORD NUMBER
;(CL)=FLOPPY SECTOR NUMBER
;
MSETREC:
	MOV	FSEC,CL
	RET
;
	EJECT
;
;
;
;SELECT MINI FLOPPY PHYSICAL SECTOR COUNT
;(CL)=MINI FLOPPY SECTOR COUNT
;
MSETCNT:
	MOV	FCNT,CL
	RET
;
;
;
;SET FLOPPY SECTOR SIZE SELECT
;(CL)=SECTOR SIZE IN BYTES UP TO (00)=256 BYTES
;
MSETSIZE:
	MOV	FSIZE,CL
	RET
;
;
;
;SET FLOPPY DISK DATA BUFFER OFFSET
;(CX)=FLOPPY BUFFER OFFSET
;
MSETBUF:
	MOV	XFRPNT,CX	;STORE FLOPPY DATA BUFFER OFFSET
	RET
;
;
;
;SET FLOPPY DISK DATA BUFFER SEGMENT
;(CX)=FLOPPY BUFFER SEGMENT
;
MSETSEG:
	MOV	XFRSEG,CX	;STORE FLOPPY DATA BUFFER SEGMENT
	RET
;
	EJECT
;
;
;
FRESTR:
	MOV	AL,RESTORE
	CALL	FDCMD		;GO EXECUTE RESTORE
	RET
;
;
;
MVERSEC:
	MOV	AL,0FFH
	RET
;
;
;
MPUTSEC:
	MOV	AL,WRITEFD
	CALL	FDCMD		;GO EXECUTE FLOPPY WRITE
	RET
;
;
;
MGETSEC:
	MOV	AL,READFD
	CALL	FDCMD		;GO EXECUTE FLOPPY READ
	RET
;
;
;
MWRTTRK:
	MOV	AL,WRTRACK
	CALL	FDCMD		;GO FORMAT TRACK
	RET
;
	EJECT
;******************************************************************************
;
;	THIS ROUTINE WILL EXECUTE THE FLOPPY COMMAND IN (AL), USING THE
;	THE PARAMETERS STORED IN THE FLOPPY PARAMETER I/O BLOCK.
;
;	ENTRY:	AL = FLOPPY COMMAND
;	EXIT:	IF COMMAND SUCCESSFULL, AL = 0
;		IF COMMAND FAILED, AL = ERROR STATUS
;
FDCMD:
	MOV	FINST,AL		;SAVE COMMAND TYPE
	PUSH	ES
	MOV	AX,2000H		;Z80 RAM BASE ADDRESS
	MOV	ES,AX
FDCMD1:
	MOV	BX,IFTOFF+FDCHA+TXE	;QUEUE OFFSET
	CALL	DEQ			;GET EMPTY BUFFER
	JNC	FDCMD1			;WAIT IF NO BUFFER IN QUEUE
;
	MOV	BX,12
	ADD	BX,DX			;COMPUTE 1. DATA POINTER
	MOV	DI,BX
	MOV	SI,OFFSET FDIOPB	;GET PARAMETER BLOCK ADDRESS
	MOV	CX,ENDFDIO-FDIOPB	;GET NBR.OF BYTES TO MOVE
	REP	MOVS AL,AL		;MOVE PARAMETERS INTO BUFFER
	XCHG	BX,DX
	MOV	ES:ÆBXÅ+DPTR,DX		;SAVE POINTER IN QHEAD
	MOV	ES:WORD PTR ÆBXÅ+BYTEC,ENDFDIO-FDIOPB	;SET BYTECOUNT
	XCHG	BX,DX
	MOV	BX,IFTOFF+FDCHA+TXF	;QUEUE OFFSET
	CALL	ENQ			;SEND BUFFER TO Z80
;
	EJECT
;
;COMMAND SEND, NOW WAIT FOR RESPONCE
;
FDWAIT:
	MOV	BX,IFTOFF+FDCHA+RXF	;QUEUE OFFSET
	CALL	DEQ			;GET BUFFER
	JNC	FDWAIT			;WAIT IF NO BUFFER IN QUEUE
	XCHG	BX,DX			;GET BUFFER ADDRESS INTO BX
	MOV	DX,ES:ÆBXÅ+DPTR		;GET 1. DATA ADDR. FROM QHEAD
	XCHG	BX,DX
	CMP	ES:BYTE PTR ÆBXÅ,ENTCLDU;MUST BE ENTIRE COMMAND LDU
	JE	FDW1			;GO GET STATUS TYPE IF LDU TYPE OK
FDERR:
	MOV	AL,CPUSYNC		;FLAG ERROR
	JMPS	FDEXIT
FDW1:
	INC	BX
	INC	BX			;POINT TO STATUS TYPE
	MOV	AL,ES:ÆBXÅ		;GET STATUS TYPE FROM BUFFER
	CMP	AL,FINST		;MUST MATCH COMMAND TYPE
	JNE	FDERR			;ERROR EXIT IF NOT
;
	INC	BX			;POINT TO STATUS BYTE
	MOV	AL,ES:ÆBXÅ		;GET DATA FROM BUFFER
FDEXIT:
	MOV	BX,IFTOFF+FDCHA+RXE	;EMPTY QUEUE OFFSET
	PUSH	AX			;SAVE CHARACTER
	CALL	ENQ			;RETURN BUFFER
	POP	AX
	POP	ES			;RESTORE SEGMENT
	RET
;
	EJECT
;******************************************************************************
;	REAL TIME CLOCK INTERRUPT SERVICE ROUTINE
;******************************************************************************
;
RTCINT:
	PUSH	DS			;SAVE DATA SEGMENT
	PUSH	ES
	PUSH	AX
	PUSH	BX
	PUSH	DX
	PUSH	CS
	POP	DS
	TEST	CONSEMAP,0FFH		;IF SEMAPHORE SET
	JNZ	TESTLPT			;...GO LOOK AT PRINTER
	TEST	CONPTR,0FFFFH		;TEST IF BUFFER PENDING
	JZ	TESTLPT			;DON'T FORGET THE PRINTER
	MOV	CONPTR,0		;REMOVE PENDING BUFFER
	MOV	AX,2000H
	MOV	ES,AX			;GET Z80-RAM BASE ADDRESS
	MOV	BX,IFTOFF+CONCHA+TXF	;GET QUEUE OFFSET
	MOV	DX,CONBUF		;GET BUFFER ADDRESS
	CALL	ENQ			;FORWARD BUFFER
TESTLPT:
	TEST	LPTSEMAP,0FFH		;IF SEMAPHORE SET
	JNZ	RTCEXIT			;...EXIT INTERRUPT
	TEST	LPTPTR,0FFFFH		;TEST IF BUFFER PENDING
	JZ	RTCEXIT			;...EXIT IF NOT
	MOV	LPTPTR,0		;REMOVE PENDING BUFFER
	MOV	AX,2000H
	MOV	ES,AX			;GET Z80-RAM BASE ADDRESS
	MOV	BX,IFTOFF+LPCHA+TXF	;GET QUEUE OFFSET
	MOV	DX,LPTBUF		;GET BUFFER ADDRESS
	CALL	ENQ			;FORWARD BUFFER
RTCEXIT:
	POP	DX
	POP	BX
	POP	AX
	POP	ES	
	POP	DS			;RESTORE DATA SEGMENT
	IRET
;
	EJECT
;
DATAOFF	EQU	OFFSET $
	DSEG
	ORG	DATAOFF
;
	INCLUDE FDDISK.LIB
;
;VALID DISK DRIVE SELECT TABLES
;
;	TABLE ENTRIES CONTAIN VALUES FOR VARIOUS DISK CONFIGURATIONS
;	AND ALLOW QUICK INDEXING TO THE DRIVE SELECT CODE PARAMETERS.
;       EACH ENTRY CONSISTS OF:
;	FIRST BYTE:      LEGAL/ILLEGAL 0=ILLEGAL, 0FFH=LEGAL
;	SECOND BYTE:     PHYSICAL UNIT SELECT CODE 00 TO 03
;	THIRD BYTE:      MINI/HARD FLAG 0=HARD UNIT, 0FFH=MINI FLOPPY
;	FOURTH BYTE:     DISK PARAMETER TABLE INDEX (FROM DISKDEF)
;
DSTAB:
	DB	0FFH,000H,0FFH,000H	;FLOPPY DISK DRIVE 0
	DB	0FFH,001H,0FFH,001H	;FLOPPY DISK DRIVE 1
	DB	000H,000H,000H,000H
	DB	000H,000H,000H,000H
	DB	000H,000H,000H,000H
	DB	000H,000H,000H,000H
;
	EJECT
;
;HDBIOS SIGNON MESSAGE
;
SMSG	DB	CR,LF,ESC,'Æ7m'
	DB	'CHRISTIAN ROVSING A/S  CR8 - CP/M-86 Vers. 1.1  '
	DB	YEAR/10+'0',YEAR MOD 10+'0'
	DB	MONTH/10+'0',MONTH MOD 10+'0'
	DB	DAY/10+'0',DAY MOD 10+'0'
	DB	CR,LF,ESC,'Æm'
	DB	'DUAL 5 1/4 INCH MINI FLOPPY BIOS  Version  '
	DB	VERSION/10+'0','.',VERSION MOD 10+'0','  '
	DB	YEAR/10+'0',YEAR MOD 10+'0'
	DB	MONTH/10+'0',MONTH MOD 10+'0'
	DB	DAY/10+'0',DAY MOD 10+'0'
	DB	0
;
	EJECT
;
;ERROR ROUTINE MESSAGES
;
;
ERRMSF	DB	CR,LF,CR,LF,' *** MINI FLOPPY DISK ERROR (#',0
ERRMS2	DB	') - DRIVE ',0
ERRMS3	DB	': ***  ',0
ERRMS4	DB	CR,LF,0
;
	EJECT
;****************************************************************************
;
;	STORAGE AREA FOR VARIABLES BEGINS HERE...
;
;		THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND
;		ENDZ, ARE SET TO ZERO AT COLD BOOT TIME 
;
STARTZ	EQU	OFFSET $		;START OF ZEROED AREA 
;
;
;NOTE:	THIS LOCATION STORES THE DISK CONTROLLER
;I/O ERROR CODE FOR DEBUGGING PURPOSES.
;
IOERR	RB	1			;DISK I/O ERROR TYPE
;
;
;
;
;HOST DISK BLOCKING/DE-BLOCKING DATA AREA
;
;
;(FOLLOWING TWO VARIABLES MUST BE KEPT TOGETHER HERE TO PERMIT WORD
; REFERENCE TO THEM DURING THE DISK HOME ROUTINE)
;
TEMPMHD	RB	1			;TEMP STORAGE FOR CURRENT TYPE OF DRIVE;
TEMPDSK	RB	1			;TEMPORARY STORAGE FOR LOGGED DISK
;
MINIHARD RB	1			;FLAG FOR MINI OR HARD DISK SELECTED
;
SEKMHD	RB	1			;FLAG FOR SELECTED DRIVE TYPE FLAG
SEKDSK	RB	1			;SEEK DISK NUMBER
SEKTRK	RW	1			;SEEK TRACK NUMBER
SEKSEC	RB	1			;SEEK SECTOR NUMBER
;
	EJECT
;(FOLLOWING TWO VARIABLES MUST BE KEPT TOGETHER HERE TO PERMIT WORD
; REFERENCE TO THEM DURING THE DISK HOME ROUTINE)
;
HSTMHD	RB	1			;HOST DISK TYPE FLAG
HSTDSK	RB	1			;HOST DISK NUMBER
HSTTRK	RW	1			;HOST TRACK NUMBER
HSTSEC	RB	1			;HOST SECTOR NUMBER
;
SEKHST	RB	1			;SEEK SHR SECSHF
HSTACT	RB	1			;HOST ACTIVE FLAG
HSTWRT	RB	1			;HOST WRITTEN FLAG
;
UNACNT	RB	1			;UNALLOCATED RECORD COUNT
UNADSK	RB	1			;LAST UNALLOCATED DISK
UNATRK	RW	1			;LAST UNALLOCATED TRACK
UNASEC	RB	1			;LAST UNALLOCATED SECTOR
;
ERFLAG	RB	1			;ERROR REPORTING
RSFLAG	RB	1			;READ SECTOR FLAG
READOP	RB	1			;1 IF READ OPERATION
WRTYPE	RB	1			;WRITE OPERATION TYPE
DMAADR	RW	1			;DISK DMA TRANSFER ADDRESS
;
DEFDMASG	RW	1		;STORAGE FOR DMA SEGMENT VALUE
IOBYTE		RB	1		;STORAGE FOR IOBYTE
;
CONPTR		RW	1		;CONSOLE BUFFER FILLING POINTER
CONBUF		RW	1		;CONSOLE BUFFER ADDRESS STORAGE
CONSEMAP	RB	1		;CONSOLE BUFFER ACCESS SEMAPHORE
;
LPTPTR		RW	1		;PRINTER BUFFER FILLING POINTER
LPTBUF		RW	1		;PRINTER BUFFER ADDRESS STORAGE
LPTSEMAP	RB	1		;PRINTER BUFFER ACCESS SEMAPHORE
;
ENDZ	EQU	OFFSET $		;END OF ZEROED AREA
;
CIBP		DW	0		;PENDING BUFFER DATA POINTER
PCIB		DW	0		;PENDING BUFFER VALID, BUFFER ADDRESS
;
	EJECT
;******************************************************************************
;	MEMORY REGION TABLE (MAX 5 MEMORY BLOCKS)
;******************************************************************************
;
MTR		DB	01		;NBR OF MEMMORY REGIONS
		DW	STARTTPA	;START OF FIXED SEGMENT
		DW	1000H-STARTTPA	;LENGTH OF FIXED SEGMENT
		RW	4*2		;MAX 4 EXTRA SEGMENTS MAY BE SPECIFIED
;
;
;
;HOST DATA BUFFER  MEMORY AREA MUST BE ACCESSABLE VIA
;DMA AND BY THE HARD DISK CONTROLLER BOARD.
;
;
HSTBUF	RB	HSTSIZ			;HOST BUFFER
;
;
;
;SCRATCH RAM AREA FOR BDOS USE
;
;	ENDEF				;LET DISKDEF FIXUP BDOS BUFFERS
;
;
;
;
;
;
;MINI FLOPPY PHYSICAL SECTOR TRANSLATE TABLE
;
MFSTRAN	DB	1,5,9,13,3,7,11,15
;
LIBP		DW	0		;PENDING BUFFER DATA POINTER
PLIB		DW	0		;PENDING BUFFER VALID, BUFFER ADDRESS
;

	EJECT
;******************************************************************************
;	MINI FLOPPY DRIVE ACCESS PARAMETER BLOCK
;******************************************************************************
;
FDIOPB	EQU	OFFSET $
;
	DB	ENTCLDU			;ENTIRE COMMAND LDU
	DB	COMOPC			;COMMAND BUFFER FLAG
FINST	DB	0			;DISK ACCESS INSTRUCTION BYTE 
FUNIT	DB	0			;SELECTED UNIT NUMBER
FSIDE	DB	0			;SELECTED SIDE NUMBER
FTRK	DB	0			;SELECTED TRACK NUMBER
FSEC	DB	1			;SELECTED SECTOR NUMBER
FCNT	DB	2			;SELECTED 256 BYTE SECTOR COUNT
XFRPNT	DW	OFFSET HSTBUF		;READ/WRITE BUFFER OFFSET
XFRSEG	DW	1040H			;READ/WRITE BUFFER SEGMENT BASE
;
ENDFDIO	EQU	OFFSET $
;
FSIZE	DB	00			;SECTOR SIZE DEFAULT TO 256 BYTES
;
;
;
	RW	32			;INITIALIZATION STACK
STKBASE	DB	0			; ***** END OF OS *****
;
;
;
;DEFINE TPA SEGMENT START ADDRESS
;
STARTTPA	EQU	((OFFSET STKBASE)+15+400H)/16
	EJECT
;
;	DEFINE INTERRUPT VECTORS
;
	DSEG	0
	ORG	0
;
INT0OFF	RW	1
INT0SEG	RW	1
STEPOFF	RW	1
STEPSEG	RW	1
NMIOFF	RW	1
NMISEG	RW	1
TYP3OFF	RW	1
TYP3SEG	RW	1
OVRFOFF	RW	1
OWRFSEG	RW	1
;
	ORG	RTC
RTCOFF	RW	1
;
	ORG	378H
BIOSOFF	RW	1
;
	ORG	380H
BDOSOFF	RW	1
BDOSSEG	RW	1
;
	END
«eof»