DataMuseum.dk

Presents historical artifacts from the history of:

CP/M

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

See our Wiki for more about CP/M

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦7697936b8⟧ TextFile

    Length: 38016 (0x9480)
    Types: TextFile
    Names: »MP5BIOS.ASM«

Derivation

└─⟦5c3c43fd1⟧ Bits:30004391 CP/M-80 rel. 1 sources
    └─ ⟦this⟧ »MP5BIOS.ASM« 

TextFile


	TITLE 'MP2 HARD DISK / MINI FLOPPY BIOS VERS. 0.4. DATE: 820920'
	PAGE	43

;***************************************************************************
;	CHRISTIAN ROVSING A/S, CP/M I/O MODULE FOR MP2 BOARD, USING
;	  SEAGATE ST506 DRIVE AND TANDON MINI FLOPPY DISK DRIVES.
;***************************************************************************
;
;
;	THIS CP/M BIOS IS SETUP FOR VERSION 2.2 CP/M ON A MP2 BOARD
;	CONSOLE AND PRINTER I/O IS HANDLED VIA ONE ON BOARD Z80-SIO
;	USART CHIPS AND A 8253 COUNTER/TIMER CHIP THAT IS PROGRAMMED
;	TO PROVIDE THE BAUD RATE CLOCK. HARD DISK I/O IS OBTAINED THROUGH
;	A MICRO COMPUTER SYSTEMS MSC 9205 5 1/4 INCH WINCHESTER HARD 
;	DISK CONTROLLER THAT CONNECTS TO A 5 MEGABYTE SEAGATE ST-506
;	WINCHESTER DRIVE.
;
;	THE WINCHESTER DISK CONTROLLER FIRMWARE SUPPORTS A PARAMETER
;	BLOCK FORMAT SIMILAR TO AN INTEL SBC 206 DISK CONTROLLER WITH 
;	A MODIFIED SET OF PARAMETERS THAT MAP TO THE CHARACTERISTICS OF
;	THE SEAGATE 5 1/4 INCH WINCHESTER DRIVE. THE CONTROLLER / DRIVE
;	CHARACTERISTICS ARE MAPPED AS FOLLOWS:
;
;		153 CYLINDERS
;		17 RECORDS PER CYLINDER
;		FOUR HEADS/SURFACES
;		512 BYTE RECORDS
;		CP/M MAPS LOGICAL DRIVES A: TO D: TO THE FOUR HEADS
;
;	THE INCLUSION OF THE MINI FLOPPY DRIVERS WITHIN THE BIOS IS 
;	ALWAYS ENABLED. ACCESS AND CONTROL OF THE MINI FLOPPY WILL 
;	BE THROUGH THE DISK CONTROLLER CIRCUITRY OF THE MP2 BOARD. 
;	THIS BIOS CONFIGURATION WILL SUPPORT ONE AND OPTIONALLY TWO
;	MINI FLOPPY DRIVES. MINI FLOPPY FORMAT IS AS FOLLOWS:
;
;		77 TRACKS
;		16 RECORDS PER TRACK
;		TWO HEADS/SIDES
;		256 BYTE RECORDS
;		CP/M MAPS LOGICAL DRIVE E: TO THE MINI FLOPPY WITH
;
;
;
;	BIOS ACCESS TO THE MINI FLOPPY IS DONE IN REAL PAIRS OF 256 BYTE
;	SECTORS TO AND FROM THE 512 BYTE HOST BUFFER. MULTIPLE SECTOR
;	READ AND WRITE COMMANDS OF THE 1793 CONTROLLER ARE USED. 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;
;
;	MAPPING OF THE HARD DISK IS DONE TO ALLOW THE FIRST TWO TRACKS OF
;	EACH DISK SURFACE TO BE SYSTEM TRACKS. THIS ALLOWS HARD DISK 
;	BOOTING FROM ANY SURFACE SHOULD ANOTHER SURFACE GET "WIPED OUT"
;	FOR SOME STRANGE REASON. THE FIRST SECTOR OF TRACK 0 CONTAINS
;	BOOT TIME CONFIGURATION INFORMATION INCLUDING THE BASE ADDRESS OF 
;	THE CCP, THE LENGTH OF CP/M + BIOS IN BYTES, THE COLD START CONSOLE
;	BAUD RATE AND THE COLD START LINE PRINTER BAUD RATE. SECTOR SIZE 
;	ON THE HARD DISK IS 512 BYTES SO THIS BIOS DOES SECTOR DEBLOCKING
;	TO THE 128 BYTE LOGICAL BLOCK SIZE REQUIRED BY CP/M
;
;
;	MAPPING OF THE MINI FLOPPY ALLOWS THE FIRST TWO TRACKS TO BE
;	SYSTEM TRACKS ALSO. NOTE THAT THIS BIOS WILL NEVER, IN GENERAL,
;	ACCESS THESE TRACKS FOR NORMAL OPERATIONS. THE SYSTEM CONTAINED
;	ON THOSE TRACKS WOULD BE ANOTHER "MINI-FLOPPY ONLY"  BIOS THAT
;	OPERATES MINI FLOPPY DISKS ONLY. IN EITHER CASE BOTH HARD DISK AND
;	THE MINI FLOPPY ONLY BIOS'S WOULD RETAIN THE SAME DISK FORMAT
;	CONFIGURATION FOR THE DATA TRACKS.
;
;
;	THE FOLLOWING INFORMATION IS USEFUL IN "SYSGENING" CP/M 2.2 ONTO
;	HARD DISK.
;
	PAGE
;	GETPUT LOAD ADDRESSES ARE SHOWN BELOW:
;
;
;	IF MSIZE=32K USE A PATCHED MOVCPM.COM TO MAKE A 29K SYSTEM IMAGE.
;		BASE ADDRESS OF CCP =05800H
;		BASE ADDRESS OF BIOS=06E00H
;		TRACK 0 SECTOR 1 AT GETPUT=03480H
;		CCP AT GETPUT POSITION    =03680H
;		BIOS AT GETPUT POSITION   =04C80H
;		OFFSET TO READ MBIOS30.HEX
;		    ...INTO GETPUT POSITION=0DE80H
;
;	IF MSIZE=48K USE A PATCHED MOVCPM.COM TO MAKE A 45K SYSTEM IMAGE.
;		BASE ADDRESS OF CCP =09800H
;		BASE ADDRESS OF BIOS=0AE00H
;		TRACK 0 SECTOR 1 AT GETPUT=03480H
;		CCP AT GETPUT POSITION    =03680H
;		BIOS AT GETPUT POSITION   =04C80H
;		OFFSET TO READ MBIOS45.HEX
;		    ...INTO GETPUT POSITION=09E80H
;
;	IF MSIZE=64K USE A PATCHED MOVCPM.COM TO MAKE A 61K SYSTEM IMAGE.
;		BASE ADDRESS OF CCP =0D800H
;		BASE ADDRESS OF BIOS=0EE00H
;		TRACK 0 SECTOR 1 AT GETPUT=03480H
;		CCP AT GETPUT POSITION    =03680H
;		BIOS AT GETPUT POSITION   =04C80H
;		OFFSET TO READ MBIOS61.HEX
;		    ...INTO GETPUT POSITION=05E80H
;
	PAGE
;	NOTE THAT CP/M 2.2 MOVCPM MAY REQUIRE PATCHING TO FIX THE BDOS
;	DEBLOCKING ALGORITHM IN THE RELOCATABLE COPY OF CP/M 2.2. USE DDT
;	TO LOOK AT THE OLD MOVCPM TO SEE IF PATCHING IS REQUIRED. IT USED
;	TO LOOK LIKE THIS:
;
;		HEX CONTENTS OF ADDRESS        INSTRUCTION CODE
;
;		1CC0				CALL 0BB8
;						POP  B
;						LDA  15E3
;						LXI  H,15E3
;						CMP  M
;						JC   12D2
;						MOV  M,A
;						INR  M
;						MVI  C,02
;		1CD2     0D                     DCR  C
;		1CD3     0D			DCR  C
;		1CD4     C2			JNZ  12DF
;		1CD5     DF
;		1CD6     12
;		1CD7				PUSH PSW
;
;
;	PATCH USING DDT'S ASSEMBLE COMMAND AS FOLLOWS:
;
;		A1CD2
;		1CD2  NOP
;		1CD3  NOP
;		1CD4  LXI  H,0000
;
;	SAVE PATCHED MOVCPM AS "MOVCPMP.COM". REMEMBER TO USE A BIG
;	ENOUGH "SAVE" COMMAND.
;
;						LARS WINTHER
;
;*****************************************************************************
;
	PAGE
;
;DEFINE TRUE AND FALSE ASSEMBLY PARAMETERS
;
TRUE	EQU	-1		;DEFINE TRUE
FALSE	EQU	NOT TRUE	;DEFINE FALSE
;
;
;CP/M VERSION 2.2 SYSTEM PARAMETERS
;
MSIZE	EQU	61		;MEMORY SIZE IN DECIMAL KILO-BYTES
BIAS	EQU	(MSIZE-20)*1024	;BIAS FOR LARGER THAN 20K 
OFFSET	EQU	0D580H-BIAS	;OFFSET VALUE FOR SYSGEN POSITION 1F80H
CCP	EQU	BIAS+3400H	;START OF CCP 2.2 
BDOS	EQU	CCP+806H	;START OF BDOS 2.2 
CPML	EQU	1600H		;LENGTH OF CP/M SYSTEM MINUS BIOS 
NSECTS	EQU	CPML/512	;NUMBER OF SECTORS IN IT 
;
;
;VERSION NUMBER AND DATE
;
VERSION	EQU	04		;VERSION NUMBER
MONTH	EQU	11		;MONTH
DAY	EQU	11		;DAY
YEAR	EQU	81		;YEAR LAST TWO DIGITS
;
;
;CP/M SYSTEM BASE ADDRESS, STACK ADDRESS, DEFAULT DMA ADDRESS
;
BASE	EQU	000H		;CP/M SYSTEM BASE ADDRESS
IOBYTE	EQU	003H		;ADDRESS OF I/O BYTE 
STACK	EQU	080H		;LOCAL STACK POINTER ADDRESS
DFDMA	EQU	080H		;DEFAULT DMA ADDRESS
LOGDSK	EQU	004H		;CP/M'S ADDRESS OF CURRENTLY LOGGED
				;...DISK
;
DELBS	EQU	FALSE		;SET TRUE IF CONIN ROUTINE TO CONVERT
				;DELETE CHAR TO BACKSPACE
;
	PAGE
;
;DEFINE MEMORY BASED I/O MODULE ENTRY POINTS
;
MODBASE EQU	0F800H		;SET JUMP TABLE EQUIVALENT ADDRESSES
;
INITSER EQU	MODBASE+00	;INITIALIZE MP2 SERIAL I/O PORTS
;				;(NO PARAMETERS)
SETCBAUD EQU	MODBASE+03	;SET CONSOLE I/O BAUD RATE FACTOR
;				;(HL) = COUNTER TIMER PARAMETER VALUE
SETLBAUD EQU	MODBASE+06	;SET LINE PRINTER I/O BAUD RATE FACTOR
;				;(HL) = COUNTER TIMER VALUE
SETLRMSK EQU	MODBASE+09	;SET LINE PRINTER SIO RECEIVER MASK VALUE
				;(A) = LINE PRINTER SIO MASK BYTE
SETLRVAL EQU	MODBASE+012	;SET LINE PRINTER SIO RECEIVER POLL VALUE
;				;(A) = LINE PRINTER POLL VALUE
SETLTMSK EQU	MODBASE+015	;SET LINE PRINTER SIO TRANSMITTER MASK VALUE
;				;(A) = LINE PRINTER SIO MASK BYTE
SETLTVAL EQU	MODBASE+018	;SET LINE PRINTER SIO TRANSMITTER POLL VALUE
;				;(A) = LINE PRINTER SIO POLL VALUE BYTE
CONSTAT EQU	MODBASE+021	;GET CONSOLE STATUS
;				;RETURN (A)=00 FOR NOT READY INPUT
;				;	(A)=FF FOR READY INPUT
CONIN	EQU	MODBASE+024	;GO GET CONSOLE INPUT CHARACTER
;				;(A)=INPUT CONSOLE CHARACTER
CONOUT	EQU	MODBASE+027	;PUT OUT CONSOLE CHAR
;				;(C)=CHARACTER TO OUTPUT
LPTSTAT EQU	MODBASE+030	;GET LINE PRINTER STATUS
;				;RETURN (A)=00 FOR NOT NEXT OUTPUT
;				;	(A)=FF FOR READY OUTPUT
LPTIN	EQU	MODBASE+033	;GO GET LINE PRINTER INPUT CHARACTER
;				;(A)=INPUT LPT SERIAL PORT CHARACTER
LPTOUT	EQU	MODBASE+036	;PUT OUT LINE PRINTER CHARACTER
;				;(C)=LPT SERIAL OUTPUT CHARACTER
HUNIT	EQU	MODBASE+039	;SELECT HARD DISK UNIT NUMBER
;				;(C)=UNIT NUMBER ON MSC 9205 CONTROLLER
HPLAT	EQU	MODBASE+042	;SELECT HARD DISK PLATTER (HEAD) NUMBER 
;				;(C)=HEAD SELECT NUMBER
HSURF	EQU	MODBASE+045	;SELECT HARD DISK SURFACE(HEAD 2^2) NUMBER
;				;(C)=MSB OF HEAD NUMBER
HCYL	EQU	MODBASE+048	;SELECT HARD DISK CYLINDER NUMBER
;				;(BC)=CYLINDER NUMBER
HREC	EQU	MODBASE+051	;SELECT HARD DISK RECORD NUMBER
;				;(C)=RECORD NUMBER
HCNT	EQU	MODBASE+054	;SELECT HARD DISK SECTOR COUNT
;				;(C)=RECORD COUNT
HBADDR	EQU	MODBASE+057	;SET 9205 CONTROLLER DMA ADDRESS
;				;(BC)=16 BIT DATA BUFFER ADDRESS
HREST	EQU	MODBASE+060	;RESTORE SELECTED HARD DISK UNIT
;				;(A) RETURNS ERROR CODE
HREAD	EQU	MODBASE+063	;READ SELECTED SECTOR(S)
;				;(A) RETURNS ERROR CODE
HVERF	EQU	MODBASE+066	;VERIFY SELECTED SECTOR(S)
;				;(A) RETURNS ERROR CODE
HWRIT	EQU	MODBASE+069	;WRITE SELECTED SECTOR(S);
;				;(A) RETURNS ERROR CODE
HEXEC	EQU	MODBASE+072	;EXECUTE SPECIAL COMMAND OF MSC 9205
;				;(C) ENTRY WITH MSC 9205 COMMAND
;				;(A) RETURNS ERROR CODE
HRESET	EQU	MODBASE+075	;RESET HARD DISK CONTROLLER MSC 9205
;				;NO PARAMETERS
MUNIT	EQU	MODBASE+078	;SELECT MINI FLOPPY UNIT NUMBER
;				;(C)=FLOPPY PHYSICAL UNIT NUMBER
MSURF	EQU	MODBASE+081	;SELECT MINI FLOPPY SURFACE(HEAD) NUMBER
;				;(C)=FLOPPY SIDE NUMBER
MCYL	EQU	MODBASE+084	;SELECT MINI FLOPPY CYLINDER(TRACK) NUMBER
;				;(C)=FLOPPY TRACK NUMBER
MREC	EQU	MODBASE+087	;SELECT MINI FLOPPY RECORD NUMBER
;				;(C)=FLOPPY SECTOR NUMBER
MCNT	EQU	MODBASE+090	;SELECT MINI FLOPPY PHYSICAL SECTOR COUNT
;				;(C)=MINI FLOPPY SECTOR COUNT
MSSIZE	EQU	MODBASE+093	;SELECT FLOPPY SECTOR SIZE (00)=256 BYTES
;				;(C)=MINI FLOPPY TRACK NUMBER
MBADDR	EQU	MODBASE+096	;SET FLOPPY DISK DATA BUFFER ADDRESS
;				;(BC)=FLOPPY BUFFER ADDRESS
MREST	EQU	MODBASE+099	;RESTORE SELECTED MINI FLOPPY UNIT
;				;(A)=RETURNS ERROR STATUS
MVERF	EQU	MODBASE+102	;VERIFY (READ) SELECTED SECTOR
;				;(A)=RETURNS STATUS
MWRIT	EQU	MODBASE+105	;WRITE SELECTED SECTOR
;				;(A)=RETURNED STATUS
MREAD	EQU	MODBASE+108	;READ SELECTED SECTOR
;				;(A)=RETURNED STATUS
MWTRK	EQU	MODBASE+111	;WRITE SELECTED FLOPPY TRACK
;				;(A)=RETURNED STATUS
MMODE	EQU	MODBASE+114	;SET FLOPPY OPERATION MODE
;				;(C)=STANDARD MODE DEFINITION
MINST	EQU	MODBASE+117	;FETCH CURRENT INSTRUCTION CODE
;				;(A)=RETURNED INSTRUCTION PATTERN
MMOFF	EQU	MODBASE+120	;CHECK MINI FLOPPY MOTOR ON COUNT
;				;OUT TIMER
	PAGE
;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
;
;
;	UNIT/MODE REGISTER FOR DISK DRIVES SELECT
;
;	BIT 7 - COMPENSATION    "1" ENABLES FLOPPY WRITE PRECOMPENSATION
;	BIT 6 - DRIVE TYPE      "1" SELECTS CLOCKING FOR A 5 1/4 DRIVE
;			        "0" SELECTS FOR AN 8 INCH UNIT
;	BIT 5 - DENSITY         "1" SETS FOR MFM DOUBLE DENSITY
;				"0" SELECTS FM SINGLE DENSITY
COMPEN	EQU	080H		;WRITE COMPENSATION ENABLE
MINIEN	EQU	040H		;MINI DRIVE ENABLE
DENSEL	EQU	020H		;BIT MASK FOR DENSITY SELECT
;
;
;DEFINE MP2 BOOT PROM MAPPING CONTROL PORT
;
RAMCTL	EQU	0AH		;PORT ADDRESS
RAMMAP	EQU	20H		;PORT MASK
;
;CP/M BIOS DISK CONFIGURATION SELECTION OPTIONS
;
DEFDSK	EQU	01H		;DEFAULT BOOTED DISK
				;  00=A:
				;  01=B:
				;  02=C:
				;  03=D:
				; *** ONLY HARD DISK SYSTEM TRACKS CAN BE
				; *** BOOTED FROM THIS BIOS
;
MINISEL	EQU	04H		;DRIVE SELECT DESIGNATOR FOR THE FIRST
				;MINI FLOPPY DISK DRIVE. 04=E:, 05=F: ETC.
;
ONEMINI	EQU	TRUE		;TRUE IF ONLY ONE MINI FLOPPY SELECTED AND
				;..FALSE IF TWO MINI'S DESIRED
	PAGE
;
;SECTOR DEBLOCKING ALGORITHMS FOR CP/M 2.2
;
	MACLIB	DISKDEF
;
SMASK	MACRO	HBLK		;UTILITY MACRO TO COMPUTE SECTOR MASK
;
;	COMPUTE LOG2(HBLK), RETURN @X AS RESULT
;	(2 ** @X = HBLK ON RETURN)
;
@Y	SET	HBLK
@X	SET	0
;
;	COUNT RIGHT SHIFTS OF @Y UNTIL = 1
;
	REPT	8
	IF	@Y = 1
	EXITM
	ENDIF
;
;	@Y IS NOT 1, SHIFT RIGHT ONE POSITION
;
@Y	SET	@Y SHR 1
@X	SET	@X + 1
	ENDM
	ENDM
;
;
;MACRO DEFINITIONS FOR Z-80 BLOCK MOVE INSTRUCTIONS REQUIRED FOR DISK
;DATA INTERFACE ON THE MP2 BOARD
;
OUTIR	MACRO
	DB	0EDH,0B3H	;Z80 OUTPUT BLOCK MOVE
	ENDM
;
INIR	MACRO
	DB	0EDH,0B2H	;Z80 INPUT BLOCK MOVE
	ENDM
;
	PAGE
;CP/M 2.2 TO HOST DISK CONSTANTS
;
BLKSIZ	EQU	2048		;CP/M ALLOCATION SIZE
HSTSIZ	EQU	512		;HOST DISK SECTOR SIZE
;
HDSPT	EQU	17		;HOST HARD DISK SECTORS/TRACK
;
FDSPT	EQU	8		;HOST MINI FLOPPY DISK 256 BYTE SECTOR PAIRS
				;PER TRACK
HSTBLK	EQU	HSTSIZ/128	;CP/M SECTS/HOST BUFF
;
;CPMSPT	EQU	HSTBLK * HSTSPT	;CP/M SECTORS/TRACK
;				;THIS VALUE CHANGES ACCORDING TO
;				;MINI OR HARD DISK.
;
SECMSK	EQU	HSTBLK-1	;SECTOR MASK
	SMASK	HSTBLK		;COMPUTE SECTOR MASK
SECSHF	EQU	@X		;LOG2(HSTBLK)
;
;SECTOR SKEW INTERLACE FACTOR
;
SKEW	EQU	00		;SECTOR SKEW FACTOR
;
;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
;
;
;
	ORG	CCP+1600H	;START OF BIOS 
;
	PAGE
;
;I/O JUMP VECTOR
;THIS IS WHERE CP/M CALLS WHENEVER IT NEEDS
;TO DO ANY INPUT/OUTPUT OPERATION 
;USER PROGRAMS MAY USE THESE ENTRY POINTS
;ALSO, BUT NOTE THAT THE LOCATION OF THIS
;VECTOR CHANGES WITH THE MEMORY SIZE 
;
;
	JMP	BOOT		;FROM COLD START LOADER 
WBOOTE:
	JMP	WBOOT		;FROM WARM BOOT 
	JMP	CSTS		;CHECK CONSOLE KB STATUS 
	JMP	CI		;READ CONSOLE CHARACTER 
	JMP	CO		;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 DISK STARTING ADR 
	JMP	READ		;READ SELECTED SECTOR
	JMP	WRITE		;WRITE SELECTED
	JMP	LPTSTAT		;RETURN LIST STATUS
	JMP	SECTRAN		;SECTOR TRANSLATE
;
;
;ADDITIONAL JUMPS INSTALLED BY CHRISTIAN ROVSING A/S FOR SPECIAL ENHANCEMENTS
;TO THE HARD DISK CP/M SYSTEM SOFTWARE
;
	JMP	CBCPMIN		;PROM/FLOPPY BASED ENTRY POINT
				;WHEN THAT LOADER BROUGHT IN CP/M
	JMP	LPTIN		;GET CHARACTER FROM LIST SERIAL PORT
;
	PAGE
;PARAMETER TABLES FOR SEGATE ST-506 5 MEGABYTE HARD DISK
;AND TANDON 5 1/4 DOUBLE DENSITY DOUBLE SIDED MINI FLOPPY
;
	IF	ONEMINI		;TELL DSKDEF OF NUMBER OF DISKS
	DISKS	5
	ENDIF
;
	IF 	NOT ONEMINI
	DISKS	6
	ENDIF 
;
	PAGE
	DISKDEF	0,1,68,,2048,641,1024,0,2	;A: HARD HEAD 0
	DISKDEF	1,0				;B: HARD HEAD 1
	DISKDEF	2,0				;C: HARD HEAD 2
	DISKDEF	3,0				;D: HARD HEAD 3
	DISKDEF	4,1,32,,2048,304,128,128,2	;E: MINI DRIVE
	IF	NOT ONEMINI			;TWO MINI'S ENABLED
	DISKDEF 5,0
	ENDIF
;
	PAGE
;
;COLD BOOT ENTRY POINT READS IN ALL OF CP/M INCLUDING BIOS
;BOOT USES THE POWER ON COLD BOOT PROM IN THE ALTERNATE MEMORY MAP
;
BOOT:
	IN	RAMCTL
	ORI	RAMMAP		;CLEAR THE MEMORY MAP TO ENABLE
	OUT	RAMCTL		;..THE POWERON PROM
	JMP	0000H		;TO BASE OF PROM LOADER
;
;
;SOFT COLD BOOT ENTRY POINT
;
CBCPMIN:			;PROM BOOTED CP/M ENTRY POINT
	LXI	B,ENDZ-STARTZ	;GET LENGTH OF ZERO AREA 
	LXI	H,STARTZ	;GET SCRATCH ADDRESS 
BOOTL:
	XRA	A		;MAKE ZERO FILL
	MOV	M,A		;PUT ZERO IN MEMORY 
	INX	H		;INCREMENT POINTER 
	DCX	B		;DECREMENT COUNTER 
	MOV	A,B
	ORA	C
	JNZ	BOOTL		;LOOP TILL DONE 
;
	MVI	A,DEFDSK	;SET UP DEFAULT BOOT DISK
	STA	SEKDSK
	STA	TEMPDSK		;SAVE TEMPORARY DISK LOCATION
	XRA	A
	STA	IOBYTE		;CLEAR I/O BYTE 
	STA	SEKMHD		;SET MINI/HARD DISK FLAG TO HARD DISK
	STA	HSTMHD
;
	LXI	H,SMSG		;PRINT OPENING MESSAGE 
	CALL	PRTMSG		;PRINT MESSAGE STRING
;
	PAGE
GOCPM:
	MVI	A,0C3H		;PUT JMP TO WBOOT
	STA	BASE		;ADR AT ZERO 
	LXI	H,WBOOTE
	SHLD	BASE+1
	STA	BASE+5
	LXI	H,BDOS		;PUT JUMP TO BDOS
	SHLD	BASE+6
	LXI	H,DFDMA		;SET DEFAULT DMA ADDRESS 
	SHLD	DMAADR
;
	MVI	C,COMPEN+MINIEN+DENSEL
	CALL	MMODE		;SETUP I/O CONFIG FOR MINI FLOPPYS
;
	MVI	C,00H		;SET HARD DISK UNIT 00
	CALL	HUNIT
;
	LDA	TEMPDSK		;GIVE CP/M "DISK SELECTED" NUMBER
	MOV	C,A		;PASS TO CCP IN C 
	CPI	MINISEL		;SEE IF DESIRED DISK TO LOG IS THE MINI
	JZ	MFLOPS		;LEAVE FLAG AT "HARD" DISK IF NOT MINI
;
	IF	NOT ONEMINI	;CHECK IF THERE ARE TWO MINI DRIVES
	CPI	MINISEL+1
	JZ	MFLOPS		;SEE IF DESIRED DISK TO LOG IS 2'ND MINI
	ENDIF
;
	JMP	CCP		;MUST BE HARD DISK SO OFF TO CCP
;
MFLOPS:
	PUSH	PSW
	MVI	A,0FFH		;SET FLAG TO MINI IF TO LOG MINI DRIVE
	STA	SEKMHD
	STA	HSTMHD
	POP	PSW
	JMP	CCP		;JUMP TO CCP WITH MINI SET CODE
;
	PAGE
;READ ALL OF CP/M BACK IN EXCEPT BIOS, THEN JUMP TO CCP 
;
WBOOT:
	LXI	SP,STACK	;SET STACK POINTER 
	LDA	LOGDSK		;SAVE CURRENT "LOGGED DISK SELECT"
	STA	TEMPDSK
	XRA	A		;SELECT HEAD ZERO ("SELECTED DISK = A:")
	STA	SEKMHD		;SET FLAGS TO HARD DISK FOR POSSIBLE ERROR
	STA	HSTMHD		;..ROUTINE SCAN
	STA	HSTACT		;SET HOST BUFFER INACTIVE
	STA	UNACNT		;CLEAR UNALLOCATED COUNT
	MVI	E,NSECTS	;GET NUMBER SECTORS FOR CP/M READ 
	CALL	GETSYS		;GO READ ALL EXCEPT BIOS
	ORA	A
	PUSH	PSW
	CNZ	EREXIT		;TAKE CARE OF ERROR
	POP	PSW
	JNZ	WBOOT		;TRY WARM BOOT AGAIN IF BAD LOAD
	JMP	GOCPM		;GO BACK TO CP/M 
;
;CONSOLE STATUS ROUTINE
;	CHECKS MINI FLOPPY MOTOR ON STATUS
;	RETURNS A=00H IF NO INPUT READY
;	RETURNS A=FFH IF INPUT READY
CSTS:
	CALL	MMOFF		;SEE IF MINI MOTORS NEED SHUTOFF
	JMP	CONSTAT		;GET INPUT STATUS
				;RETURN THROUGH I/O ROUTINE
;CONSOLE INPUT ROUTINE
;	GETS CHAR TO (A) REGISTER
CI:
	CALL	CSTS		;CHECK CONSOLE STATUS
	ORA	A		;SET FLAGS
	JZ	CI		;WAIT TILL READY
	CALL	CONIN		;GO GET READY CHARACTER
	IF	DELBS		;SELECTED DELETE SUBSTITUTE TO BS?
	CPI	RUBOUT		;CHECK IF INPUT WAS A DELETE
	RNZ
	MVI	A,BS		;SUBSTITUTE THE BACK SPACE IF SO
	ENDIF
	RET
	PAGE
;
;CONSOLE OUTPUT ROUTINE 
;	SENDS CHAR IN (C) REGISTER
;
CO:
	MOV	A,C		;STRIP PARITY BIT
	ANI	07FH
	MOV	C,A
	CALL	CONOUT		;GO SEND CHARACTER OUT
	JMP	MMOFF		;SEE IF MINI FLOPPY MOTORS NEED SHUTOFF
				;RETURN THROUGH MMOFF
;
;PUNCH PAPER TAPE, DEFAULT IS CONSOLE
;
PUNCH:
	JMP	LPTOUT		;SEND PUNCH TO CONSOLE 
				;RETURN THROUGH CONOUT 
;
;
;READ PAPER TAPE, DEFAULT IS CONSOLE
;
READER:
	JMP	LPTIN		;READ FROM CONSOLE 
				;RETURN THROUGH CONIN
;
;
	PAGE
;
;SELECT HEAD/SURFACE (CP/M THINKS THIS IS DISK) NUMBER ACCORDING TO REGISTER C 
;
;	  00 = HEAD 0 (DISK A:)
;	  01 = HEAD 1 (DISK B:)
;	  02 = HEAD 2 (DISK C:)
;	  03 = HEAD 3 (DISK D:)
;	  04 = MINI FLOPPY (DISK E:)
;	  05 = OPTIONAL MINI FLOPPY (DISK F:)
;
SELDSK:
	MOV	A,C		;GET NEW UNIT NUMBER
	LXI	H,0		;RETURN 0000 IN H&L REGS., IF ERROR
	CPI	MINISEL+1	;IS SELECT MORE THAN MAX TABLE ENTRY
	RNC			;RETURN WITH ERROR, IF NOT VALID TABLE ENTRY
;
	PUSH	H		;CHECK IF VALID FROM TABLE
	ADD	A		;MAKE UNIT SELECT TABLE INDEX
	ADD	A
	MOV	L,A
	LXI	D,DSTAB		;DRIVE SETUP TABLE BASE
	DAD	D		;(HL) = SELECTED DRIVE POINTER
	MOV	A,M		;GET VALIDITY BYTE THIS UNIT
	ORA	A		;ZERO = ILLEGAL
	XCHG			;SAVE POINTER IF NO EXIT
	POP	H		;GET BACK H&L TO ZERO FOR ERROR EXIT
	RZ			;RETURN ON ILLEGAL UNIT
;
	MOV	A,C		;SET SEKDSK TO CP/M UNIT SELECT CODE
	STA	SEKDSK
;
	XCHG			;IS A LEGAL SELECT THEN PROCESS 
				;PARAMETERS
	INX	H		;POINT TO DRIVE PHYSICAL UNIT NUMBER
				;DRIVE PHYSICAL UNIT NUMBER NOT USED
				;TILL I/O ROUTINES WHEN THE DRIVE IS USED
;
	INX	H		;POINT TO MINI/HARD FLAG
	MOV	A,M
	STA	SEKMHD		;SET CURRENTLY SELECTED TYPE FLAG
;
	INX	H		;POINT TO CP/M DISK PARAMETER TABLE INDEX
	MOV	L,M		;MAKE DOUBLE TABLE INDEX*16
	MVI	H,00H
;
	REPT	4		;SHIFT LEFT 4  (*16)
	DAD	H
	ENDM
;
	LXI	D,DPBASE	;D&E REGS. = DISK PARAMETER BASE
	DAD	D		;H&L REGS. = BIAS OFFSET INTO TABLE
	XRA	A		;SET A REG. = 00
	RET			;RETURN FROM SELDSK 
;
	PAGE
;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)
;
	IF	ONEMINI
DSTAB:
	DB	0FFH,000H,000H,000H	;HARD DISK HEAD 0
	DB	0FFH,001H,000H,001H	;HARD DISK HEAD 1
	DB	0FFH,002H,000H,002H	;HARD DISK HEAD 2
	DB	0FFH,003H,000H,003H	;HARD DISK HEAD 3
	IF	MINISEL-4
	REPT	MINISEL-4
	DB	000H,000H,000H,000H	;FILL IN TABLE WITH
	ENDM				;DUMMY ENTRIES UP TO MINI'S
	ENDIF
	DB	0FFH,000H,0FFH,004H	;MINI DISK UNIT 0
	DB	000H,000H,000H,000H	;..ILLEGAL, ONLY ONE MINI
	ENDIF
;
	IF	NOT ONEMINI
DSTAB:
	DB	0FFH,000H,000H,000H	;HARD DISK HEAD 0
	DB	0FFH,001H,000H,001H	;HARD DISK HEAD 1
	DB	0FFH,002H,000H,002H	;HARD DISK HEAD 2
	DB	0FFH,003H,000H,003H	;HARD DISK HEAD 3
	IF	MINISEL-4
	REPT	MINISEL-4
	DB	000H,000H,000H,000H	;FILL IN TABLE WITH 
	ENDM				;DUMMY ENTRIES UP TO MINI'S
	ENDIF
	DB	0FFH,000H,0FFH,004H	;MINI DISK UNIT 0
	DB	0FFH,001H,0FFH,005H	;MINI DISK UNIT 1
	ENDIF
;
	PAGE
;
;SUBROUTINE TO GET THE PHYSICAL DRIVE NUMBER OUT OF THE DRIVE
;SELECT PARAMETER TABLE INTO (A)
;
GETDRNO:
	LDA	HSTDSK		;GET UNIT CP/M THINKS WE HAVE
	ADD	A
	ADD	A		;SETUP INDEX INTO FOUR BYTE TABLE
				;ENTRIES
	MOV	C,A
	MVI	B,0
	LXI	H,DSTAB+1	;BASE ADDRESS FOR ENTRIES OF PHYSICAL
				;DRIVE ADDRESS TRANSLATION
	DAD	B
	MOV	C,M		;GET PHYSICAL NUMBER INTO (A)
	RET
;
;
;
;MOVE DISK TO TRACK ZERO 
;
HOME:
	LDA	HSTWRT		;CHECK FOR PENDING WRITE
	ORA	A
	JNZ	HOMEIT
	STA	HSTACT		;CLEAR HOST ACTIVE FLAG
;
HOMEIT:
	LXI	H,0000H		;ITS LIKE WE ARE GOING TO TRACK 0
	SHLD	SEKTRK
;
	LHLD	HSTMHD		;GET PRESENT HOST DISK NUMBER AND TYPE FLAG
	SHLD	TEMPMHD		;..SAVE TO RESTORE ON HOME EXIT
;
	LDA	SEKDSK		;TEMPORARY SET OF HOST DISK FROM SELECTED
	STA	HSTDSK		;.."SEKDSK".. THANKS JOSE HERNANDAZ
;
	CALL	GETDRNO		;GET PHYSICAL DRIVE NUMBER TO (C)
	LDA	SEKMHD		;CHECK IF MINI OR HARD DISK
	ORA	A		;ZERO=HARD DISK
	JNZ	FLOPHME		;GO TO FLOPPY RESTORE ROUTINE
;
	CALL	HPLAT		;SET HARD DISK UNIT IOPB
	MVI	C,00H
	CALL	HSURF
	CALL	HREST		;GO RESTORE HARD DISK
	ORA	A
	JNZ	HOMEERR		;CHECK FOR RESTORE ERROR
HOMEOK:
	XRA	A
HOMEXIT:
	STA	ERFLAG		;RESET ERROR FLAG
	PUSH	PSW		;SAVE RETURN FLAG
	LHLD	TEMPMHD		;RESTORE BIOS ACTIVE TYPE FLAG AND HOST DISK
	SHLD	HSTMHD		;..TO VALUES BEFORE HOME OPEATION
	POP	PSW		;GET BACK BDOS RETURN FLAG
	RET			;RETURN FROM HOME, IF O.K. 
;
HOMEERR:
	CALL	EREXIT		;PRINT BIOS ERROR MESSAGE
	MVI	A,01H		;SET ERROR FLAG
	JMP	HOMEXIT		;TO HOME EXIT POINT
;
;
;MINI FLOPPY DISK RESTORE ROUTINE
;
FLOPHME:
	CALL	MUNIT		;SET MINI UNIT TO RESTORE
	CALL	MREST		;GO RESTORE
	ORA	A
	JZ	HOMEOK
	JMP	HOMEERR		;GO WORK FOR ERROR RECOVERY
;
;
;
;SET TRACK NUMBER SPECIFIED BY B&C REGS.
;
SETTRK:
	MOV	H,B
	MOV	L,C
	SHLD	SEKTRK		;TRACK TO SEEK
	RET
;
	PAGE
;
;TRANSLATE THE SECTOR GIVEN BY B&C REGS.
;
;	NO TRANSLATE DONE AT THIS TIME. HARD DISK CONTROLLER DOES IT
;	AND WE WILL TRANSLATE THE MINI FLOPPY AT THE PHYSICAL SECTOR
;	BASIS IN THE MINI FLOPPY READ/WRITE SETUP ROUTINE.
;
SECTRAN:
	MOV	H,B
	MOV	L,C
	RET			;RETURN FROM SECTRAN
;
;
;SET DISK SECTOR NUMBER 
;
SETSEC:
	MOV	A,C		;GET SECTOR NUMBER
	STA	SEKSEC		;SECTOR TO SEEK
	RET			;RETURN FROM SETSEC
;
;
;SET DISK DMA ADDRESS 
;
SETDMA:
	MOV	H,B		;MOVE B&C TO H&L
	MOV	L,C
	SHLD	DMAADR		;PUT AT DMA ADR ADDRESS
	RET			;RETURN FROM SETDMA
;
;READ THE SELECTED CP/M 2.2 SECTOR
;
READ:
	XRA	A		;CLEAR UNALLOCATED COUNT
	STA	UNACNT
	MVI	A,1
	STA	READOP		;READ OPERATION
	STA	RSFLAG		;MUST READ DATA
	MVI	A,WRUAL
	STA	WRTYPE		;TREAT AS UNALLOCCATED
	JMP	RWOPER		;TO PERFORM THE READ
;
	PAGE
;
;WRITE THE SELECTED CP/M 2.2 SECTOR
;
WRITE:
	XRA	A		;0 TO A REG.
	STA	READOP		;NOT A READ OPERATION
	MOV	A,C		;WRITE TYPE IN C
	STA	WRTYPE
	CPI	WRUAL		;WRITE UNALLOCATED?
	JNZ	CHKUNA		;CHECK FOR UNALLOCATED
;
;
;WRITE TO UNALLOCATED, SET PARAMETERS
;
	MVI	A,BLKSIZ/128	;NEXT UNALLOCATED RECORDS
	STA	UNACNT
	LDA	SEKDSK		;DISK TO SEEK
	STA	UNADSK		;UNADSK = SEKDSK
	LHLD	SEKTRK
	SHLD	UNATRK		;UNATRK = SECTRK
	LDA	SEKSEC
	STA	UNASEC		;UNASEC = SEKSEC
;
;
;CHECK FOR WRITE TO UNALLOCATED SECTOR
;
CHKUNA:
	LDA	UNACNT		;ANY UNALLOCATED REMAINING?
	ORA	A
	JZ	ALLOC		;SKIP IF NOT
;
;
;MORE UNALLOCATED RECORDS REMAIN
;
	DCR	A		;UNACNT = UNACNT-1
	STA	UNACNT
	LDA	SEKDSK		;SAME DISK?
	LXI	H,UNADSK
	CMP	M		;SEKDSK = UNADSK?
	JNZ	ALLOC		;SKIP IF NOT
;
	PAGE
;
;DISKS ARE THE SAME
;
	LXI	H,UNATRK
	CALL	SEKTRKCMP	;SEKTRK = UNATRK?
	JNZ	ALLOC		;SKIP IF NOT
;
;
;TRACKS ARE THE SAME
;
	LDA	SEKSEC		;SAME SECTOR?
	LXI	H,UNASEC
	CMP	M		;SEKSEC = UNASEC?
	JNZ	ALLOC		;SKIP IF NOT
;
;
;MATCH, MOVE TO NEXT SECTOR FOR FUTURE REFERENCE
;
	INR	M		;UNASEC = UNASEC+1
	MOV	A,M		;END OF TRACK?
	PUSH	B
	PUSH	PSW
	LDA	SEKMHD		;CHECK KIND OF DISK
	ORA	A		;0=HARD DISK
	JZ	HDMTCH		;HARD DISK MATCH
;
	MVI	B,FDSPT		;USE MINI DISK SPT
	JMP	MTCHCMP
;
HDMTCH:
	MVI	B,HDSPT		;USE HARD DISK SECTORS PER TRACK
MTCHCMP:
	POP	PSW
	CMP	B
	POP	B
	JC	NOOVF		;SKIP IF NO OVERFLOW
;
;
;OVERFLOW TO NEXT TRACK
;
	MVI	M,0		;UNASEC = 0
	LHLD	UNATRK
	INX	H
	SHLD	UNATRK		;UNATRK = UNATRK+1
;
;
;MATCH FOUND, MARK AS UNNECESSARY READ
;
NOOVF:
	XRA	A		;0 TO A REG.
	STA	RSFLAG		;RSFLAG = 0
	JMP	RWOPER		;TO PERFORM THE WRITE
;
;
;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
;
ALLOC:
	XRA	A		;0 TO A REG.
	STA	UNACNT		;UNACNT = 0
	INR	A		;1 TO A REG.
	STA	RSFLAG		;RSFLAG = 1
;
;
;COMMON CODE FOR READ AND WRITE FOLLOWS:
;
RWOPER:				;ENTER HERE TO PERFORM THE READ/WRITE
	XRA	A		;ZERO TO A REG.
	STA	ERFLAG		;NO ERRORS (YET)
	LDA	SEKSEC		;COMPUTE HOST SECTOR
;
	REPT	SECSHF
	ORA	A		;CARRY = 0
	RAR			;SHIFT RIGHT
	ENDM
;
	PAGE
;
;OUR DISK CONTROLLER NUMBERS ITS RECORDS FROM 1 AND NOT ZERO
;SO FIXUP THE "SEKHST" SECTOR NUMBER
;
	INR	A
	STA	SEKHST		;HOST SECTOR TO SEEK
;
;
;ACTIVE HOST SECTOR?
;
	LXI	H,HSTACT	;HOST ACTIVE FLAG
	MOV	A,M
	MVI	M,1		;ALWAYS BECOMES 1
	ORA	A		;WAS IT ALREADY?
	JZ	FILHST		;FILL HOST IF NOT
;
;
;HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
;
	LDA	SEKDSK
	LXI	H,HSTDSK	;SAME DISK?
	CMP	M		;SEKDSK = HSTDSK?
	JNZ	NOMATCH
;
;
;SAME DISK, SAME TRACK?
;
	LXI	H,HSTTRK
	CALL	SEKTRKCMP	;SEKTRK = HSTTRK?
	JNZ	NOMATCH
;
;
;SAME DISK, SAME TRACK, SAME BUFFER?
;
	LDA	SEKHST
	LXI	H,HSTSEC	;SEKHST = HSTSEC?
	CMP	M
	JZ	MATCH		;SKIP IF MATCH
;
	PAGE
;
;PROPER DISK, BUT NOT CORRECT SECTOR
;
NOMATCH:
	LDA	HSTWRT		;HOST WRITTEN?
	ORA	A
	JZ	FILHST
	CALL	WRITEHST	;CLEAR HOST BUFF
	LDA	ERFLAG		;CHECK FOR WRITE ERRORS
	ORA	A
	RNZ			;BALE OUT TO BDOS IF ERROR
;
;
;MAY HAVE TO FILL THE HOST BUFFER
;
FILHST:
	LDA	SEKMHD		;COPY SELECTED TYPE TO OPERATION TYPE
	STA	HSTMHD
	LDA	SEKDSK		;COPY SELECTED DISK TO OPERATION DISK
	STA	HSTDSK
	LHLD	SEKTRK		;COPY SELECTED TRACK TO OPERATION TRACK
	SHLD	HSTTRK
	LDA	SEKHST		;COPY SELECTED PHYS SECTOR TO OPERATION SECTOR
	STA	HSTSEC
	LDA	RSFLAG		;NEED TO READ?
	ORA	A
	JZ	MATCH		;SKIP PREREAD
;
	CALL	READHST		;YES, IF 1
	XRA	A		;0 TO A REG.
	STA	HSTWRT		;NO PENDING WRITE
	LDA	ERFLAG		;CHECK ERROR ON PREREAD?
	ORA	A
	RNZ			;BACK TO BDOS IF ERROR IN READING
;
	PAGE
;COPY DATA TO OR FROM BUFFER
;
MATCH:
	LDA	SEKSEC		;MASK BUFFER NUMBER
	ANI	SECMSK		;LEAST SIGNIF BITS
	MOV	L,A		;READY TO SHIFT
	MVI	H,0		;DOUBLE COUNT
;
	REPT	7		;SHIFT LEFT 7
	DAD	H
	ENDM
;
;HL HAS RELATIVE HOST BUFFER ADDRESS
;
	LXI	D,HSTBUF
	DAD	D		;HL = HOST ADDRESS
	XCHG			;NOW IN DE
	LHLD	DMAADR		;GET/PUT CP/M DATA
	MVI	C,128		;LENGTH OF MOVE; CP/M SECTOR SIZE
	LDA	READOP		;WHICH WAY?
	ORA	A
	JNZ	RWMOVE		;SKIP IF READ
;
;
;WRITE OPERATION, MARK AND SWITCH DIRECTION
;
	MVI	A,1
	STA	HSTWRT		;HSTWRT = 1
	XCHG			;SOURCE/DESTINATION SWAP
;
;
;C INITIALLY 128, DE IS SOURCE, HL IS DESTINATION
;
RWMOVE:
	LDAX	D		;SOURCE CHARACTER
	INX	D
	MOV	M,A		;TO DESTINATION
	INX	H
	DCR	C		;LOOP 128 TIMES
	JNZ	RWMOVE
;
;DATA HAS BEEN MOVED TO/FROM HOST BUFFER
;
	LDA	WRTYPE		;WRITE TYPE
	CPI	WRDIR		;TO DIRECTORY?
	LDA	ERFLAG		;IN CASE OF ERRORS
	RNZ			;NO FURTHER PROCESSING
;
;
;CLEAR HOST BUFFER FOR DIRECTORY WRITE
;
	ORA	A		;ERRORS?
	RNZ			;SKIP IF SO
	XRA	A		;0 TO A REG.
	STA	HSTWRT		;BUFFER WRITTEN
	CALL	WRITEHST
	LDA	ERFLAG
	RET
;
	PAGE
;
;UTILITY SUBROUTINE FOR 16-BIT COMPARE
;
SEKTRKCMP:			;HL = .UNATRK OR .HSTTRK, COMPARE 
				;..WITH SEKTRK
	XCHG
	LXI	H,SEKTRK
	LDAX	D		;LOW BYTE COMPARE
	CMP	M		;SAME?
	RNZ			;RETURN IF NOT
;
;
;LOW BYTES EQUAL, TEST HIGH FIRST
;
	INX	D
	INX	H
	LDAX	D
	CMP	M		;SETS FLAGS
	RET
;
	PAGE
WRITEHST:			;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 ERFLAG NON-ZERO IF ERROR
;
WRTSEC:
	LDA	HSTMHD		;SEE IF HARD DISK
	ORA	A
	JNZ	FLOPWR		;GO WRITE FLOPPY SECTOR
;
	CALL	HIOPB		;GO SETUP IOPB FOR OPERATION
	CALL	HWRIT		;GO WRITE IT
	ORA	A		;CHECK STATUS
	JNZ	WRTERR		;EXIT FOR WRITE ERROR
;
WRTOK:
	XRA	A
	STA	ERFLAG		;RESET ERROR FLAG
	RET			;RETURN FROM "WRITEHST", IF O.K. 
;
WRTERR:
	CALL	EREXIT		;PRINT BIOS ERROR MESSAGE
	MVI	A,01H		;SET ERROR FLAG
	STA	ERFLAG
	RET
;
FLOPWR:				;HERE TO PERFORM A MINI FLOPPY WRITE
	CALL	MIOPB		;SET MINI FLOPPY IOPB
	CALL	MWRIT		;GO WRITE MINI FLOPPY SECTOR
	ORA	A
	JNZ	WRTERR		;EXIT FOR WRITE ERROR
	JMP	WRTOK		;NORMAL "GOOD" EXIT
;
	PAGE
;
READHST:			;PERFORMS THE PHYSICAL READ FROM 
				;..THE HOST DISK
;
;HSTDSK = HOST DISK NUMBER, HSTTRK = HOST TRACK NUMBER,
;HSTSEC = HOST SECT NUMBER. READ "HSTSIZ" BYTES
;INTO HSTBUF AND RETURN ERROR FLAG IN ERFLAG.
;
READSEC:
	LDA	HSTMHD		;SEE IF HARD DISK
	ORA	A
	JNZ	FLOPRD		;GO READ FLOPPY SECTOR
;
	CALL	HIOPB		;SETUP IPOB FOR READ
	CALL	HREAD		;GET IN THE SECTOR
	ORA	A		;CHECK COMMAND STATUS
	JNZ	RDERR		;TO PROCESSING ROUTINE IF ERROR
RDOK:
	XRA	A
	STA	ERFLAG
	RET
;
RDERR:
	CALL	EREXIT		;PRINT BIOS ERROR MESSAGE
	MVI	A,01H		;SET ERROR FLAG
	STA	ERFLAG
	RET

;
FLOPRD:				;HERE TO PERFORM A MINI FLOPPY READ
	CALL	MIOPB		;SETUP MINI FLOPPY IOPB
	CALL	MREAD		;GO READ MINI FLOPPY SECTOR
	ORA	A
	JNZ	RDERR		;EXIT FOR READ ERROR
	JMP	RDOK		;NORMAL "GOOD" EXIT
;
	PAGE
;READ/WRITE BIOS ERROR PRINT ROUTINE
;WAITS FOR USER RESPONSE ON CONSOLE AFTER PRINTING MESSAGE
;AND THEN RETURNS TO THE CALLER
;
EREXIT:
	STA	IOERR		;SAVE ERROR STATUS
	LDA	HSTMHD		;SEE WHAT KIND OF UNIT CAUSED ERROR
	ORA	A
	JZ	HDERRMS		;0=ERROR FROM HARD DISK
	LXI	H,ERRMSF	;USE MINI FLOPPY ERROR MESSAGE INSTEAD
	JMP	ERMPRT
HDERRMS:
	LXI	H,ERRMSH	;PRINT BIOS ERROR MESSAGE FOR HARD DISK
ERMPRT:
	CALL	PRTMSG
	LXI	H,ERRMS1	;PRINT COMMON PART OF MESSAGE
	CALL	PRTMSG
	LDA	IOERR		;PRINT ERROR CODE
	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	HEXOUT
	POP	PSW
	CALL	HEXOUT
	LXI	H,ERRMS2	;PRINT REST OF MESSAGE
	CALL	PRTMSG
	LDA	HSTDSK		;PRINT CP/M DRIVE DESIGNATOR WITH ERROR
	ADI	'A'
	MOV	C,A
	CALL	CONOUT
	LXI	H,ERRMS3	;PRINT MESSAGE CLOSE
	CALL	PRTMSG
	CALL	CONIN		;WAIT FOR OPERATOR RESPONSE
	CPI	'C'-040H	;IF CTL-C THEN GO DO WARM BOOT
	JZ	WBOOT
	LXI	H,ERRMS4
	CALL	PRTMSG
	RET			;BACK TO CP/M
;
	PAGE
;
;ERROR ROUTINE MESSAGES
;
;
ERRMSH:
	DB	CR,LF,CR,LF,' *** HARD',0
ERRMSF:
	DB	CR,LF,CR,LF,' *** MINI FLOPPY',0
ERRMS1:
	DB	' DISK I/O ERROR - CODE(',0
ERRMS2:
	DB	') - DRIVE ',0
ERRMS3:
	DB	': ***  ',0
ERRMS4:
	DB	CR,LF,0
;
;
;SUBROUTINE TO SEND A HEX CHAR TO THE CONSOLE
;
HEXOUT:
	ANI	0FH		;LOW NIBBLE ONLY
	CPI	0AH		;GREATER THAN 9?
	JM	HEX1
	ADI	07H		;ADD OFFSET FOR A-F
HEX1:
	ADI	030H		;ADD IN ASCII OFFSET
	MOV	C,A		;PRINT RESULT
	CALL	CONOUT
	RET
;
	PAGE
;
;SUBROUTINE TO SETUP IOPB FOR HARD DISK READ/WRITE ROUTINES
;
HIOPB:
	CALL	GETDRNO		;SET IOPB FOR "DRIVE" SELECT
				;UNIT NUMBER
	CALL	HPLAT		;USE HEADS DIRECTLY FOR THE LOGICAL
	MVI	C,00H		;CP/M DRIVES
	CALL	HSURF
;
	LHLD	HSTTRK		;GET SELECTED CYLINDER NUMBER
	MOV	C,L
	MOV	B,H
	CALL	HCYL		;PUT INTO IOPB FOR HARD DISK CONTROLLER
	LXI	B,HSTBUF	;SET IOPB FOR BUFFER ADDRESS
	CALL	HBADDR
	MVI	C,01H		;SET FOR SINGLE SECTOR TRANSFER
	CALL	HCNT
	LDA	HSTSEC		;SET IOPB FOR RECORD NUMBER
	MOV	C,A		;FINALLY I FOUND THAT ONE
	CALL	HREC
	RET
;
	PAGE
;
;MINI FLOPPY I/O PARAMETER BLOCK SET UP ROUTINE
;
MIOPB:
	CALL	GETDRNO		;GET PHYSICAL DRIVE NUMBER FROM
	CALL	MUNIT		;..FROM DRIVE SELECT TABLE
	LDA	HSTTRK		;GET AND SET TRACK NUMBER
	PUSH	PSW
	ANI	01H		;FIND OUT WHAT THE SIDE NUMBER IS
	MOV	C,A
	CALL	MSURF		;SET MINI HEAD NUMBER
	POP	PSW
	ORA	A
	RAR			;DIVIDE TRACK BY 2
	MOV	C,A		;SEND PHYSICAL TRACK TO IOPB
	CALL	MCYL
;
	MVI	C,00H		;SET SIZE CODE TO 256 BYTES
	CALL	MSSIZE
	MVI	C,02H		;SET SECTOR COUNT TO 2
	CALL	MCNT
;
	LDA	HSTSEC		;CONVERT SECTOR NUMBER TO PROPER SKEW
	ORA	A		;CONVERT TO PAIRED ODD BASED
	RAL
	DCR	A
	DCR	A		;NOW ZERO BASED FOR INDEXING
	MVI	B,00H
	MOV	C,A		;DOUBLE BYTE INDEX WORD
	LXI	H,MFSTRAN	;TRANSLATE TABLE BASE ADDRESS
	DAD	B
	MOV	C,M
	CALL	MREC		;SET ACTUAL SECTOR TO START READ UPON
	LXI	B,HSTBUF	;SET FLOPPY BUFFER ADDRESS
	CALL	MBADDR
	RET
;
	PAGE
;
;MINI FLOPPY PHYSICAL SECTOR TRANSLATE TABLE
;
MFSTRAN:
	DB	1,2,5,6,9,10,13,14,3,4,7,8,11,12,15,16
				;NOTE THAT ONLY ODD SECTORS ALLOWED
;
;*********************************************************************
;
;	READ SEQUENTIAL DISK SECTORS INTO MEMORY AS SPECIFIED BY ENTRY
;	PARAMETERS. ENTRY WITH (E) REGISTER EQUAL TO THE NUMBER OF 512
;	BYTE SECTORS TO READ. TRACK 0 SECTOR 1 IS READ TO GET LOAD
;	PARAMETERS FOR BASE ADDRESS THAT MAY CHANGE WITH SYSGEN SIZE.
;	PUT HERE AS SUBROUTINE SO CAN BE USED BY BOTH WARM AND COLD BOOT
;	ROUTINES IN THE BIOS. ROUTINE USED ONLY FOR HARD DISK.
;
GETSYS:
	PUSH	D		;SAVE CALLERS RECORD COUNT
	MVI	C,DEFDSK	;SELECT DEFAULT DRIVE
	CALL	HPLAT		;USE HEADS DIRECTLY FOR THE LOGICAL
	MVI	C,00H		;CP/M DRIVES
	CALL	HSURF
	CALL	HREST		;RESTORE DRIVE
	ORA	A
	POP	D
	RNZ			;BACK TO BOOT ROUTINE IF ERROR
;
	PUSH	D
	MVI	C,01H		;START WITH RECORD 1
	CALL	HREC
	LXI	B,000H		;START WITH CYLINDER 0
	CALL	HCYL
	LXI	B,HSTBUF	;START OF BUFFER AREA
	CALL	HBADDR
	MVI	C,01H		;SET SINGLE SECTOR TRANSFER
	CALL	HCNT
	CALL	HREAD		;READ IT IN
	ORA	A		;
	POP	D
	RNZ			;BACK TO CALLER IF ERROR
;
	PAGE
;
;FIRST SECTOR IN NOW GO READ THE REST OF ALL THIS
;
	LHLD	HSTBUF		;GET BASE ADDRESS OF LOAD
	MVI	D,02H		;START LOAD WITH SECOND SECTOR
	LXI	B,0000H		;INITIAL WITH CYLINDER 0
GETSYS1:
	PUSH	B		;SAVE CYL
	PUSH	D		;SAVE RECORD NUMBER/REC COUNT
	PUSH	H		;SAVE LOAD ADDRESS
	CALL	HCYL		;PUT CYLINDER INTO IOPB
	MOV	C,D		;PUT RECORD NUMBER INTO IOPB
	CALL	HREC
	MOV	C,L		;PUT LOAD ADDRESS INTO IOPB
	MOV	B,H
	CALL	HBADDR
	CALL	HREAD		;GO TELL DISK TO READ
	POP	H		;GET BACK LOAD ADDRESS
	POP	D		;GET BACK REC / REC CNT
	POP	B		;GET BACK CYL
;
	ORA	A		;CHECK COMMAND COMPLETION STATUS
	RNZ			;BACK TO CALLER IF ERROR
;
	PUSH	B
	LXI	B,HSTSIZ	;GET ADDRESS INDEX
	DAD	B		;(HL) HAS NEW LOAD ADDRESS
	POP	B
	INR	D		;SET FOR NEXT RECORD
	MOV	A,D		;CHECK IF PAST END OF CYLINDER
	CPI	HDSPT+1
	JNZ	SAMTRK		;STILL ON SAME TRACK
;
	INX	B		;INCREMENT CYLINDER NUMBER
	MVI	D,01H		;SET RECORD BACK TO START OF TRACK
SAMTRK:
	DCR	E		;SEE IF ALL SECTORS IN YET
	JNZ	GETSYS1		;GO DO MORE IF NOT DONE YET
	XRA	A
	RET			;RETURN GOOD LOAD CODE
;
	PAGE
;*************************************************************************
;
;
;PRINT THE MESSAGE AT H&L UNTIL A ZERO 
;
;
PRTMSG:
	MOV	A,M		;GET CHARACTER TO PRINT
	ORA	A		;SET FLAGS
	RZ			;RETURN, IF END OF STRING FLAG
	MOV	C,A		;CHARACTER IN C REG., FOR CONSOLE OUTPUT
	PUSH	H		;SAVE MESSAGE POINTER
	CALL	CONOUT		;PRINT CHARACTER, CONSOLE OUTPUT
	POP	H		;GET POINTER BACK
	INX	H		;BUMP MESSAGE POINTER
	JMP	PRTMSG
;
;
;HDBIOS SIGNON MESSAGE
;
SMSG:
	DB	CR,LF,ESC,'Æ7;2m','CHRISTIAN ROVSING A/S  '
	DB	(MSIZE+3)/10+'0',(MSIZE+3) MOD 10+'0'
	DB	'K CP/M VER 2.2           '
	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','SEAGATE ST506 HARD DISK / 5 1/4 MINI '
	DB	'FLOPPY BIOS, VER. '
	DB	VERSION/10+'0','.',VERSION MOD 10+'0'
	DB	0
;
	PAGE
;****************************************************************************
;
;	STORAGE AREA FOR VARIABLES BEGINS HERE...
;
;		THE NEXT SEVERAL BYTES, BETWEEN STARTZ AND
;		ENDZ, ARE SET TO ZERO AT COLD BOOT TIME 
;
STARTZ	EQU	$		;START OF ZEROED AREA 
;
;
;NOTE:	THIS LOCATION STORES THE DISK CONTROLLER
;I/O ERROR CODE FOR DEBUGGING PURPOSES.
;
IOERR:
	DS	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:
	DS	1		;TEMP STORAGE FOR CURRENT TYPE OF DRIVE;
TEMPDSK:	
	DS	1		;TEMPORARY STORAGE FOR LOGGED DISK
;
MINIHARD:
	DS	1		;FLAG FOR MINI OR HARD DISK SELECTED
;
SEKMHD:
	DS	1		;FLAG FOR SELECTED DRIVE TYPE FLAG
SEKDSK:	
	DS	1		;SEEK DISK NUMBER
SEKTRK:	
	DS	2		;SEEK TRACK NUMBER
SEKSEC:	
	DS	1		;SEEK SECTOR NUMBER
;
	PAGE
;(FOLLOWING TWO VARIABLES MUST BE KEPT TOGETHER HERE TO PERMIT WORD
; REFERENCE TO THEM DURING THE DISK HOME ROUTINE)
;
HSTMHD:
	DS	1		;HOST DISK TYPE FLAG
HSTDSK:
	DS	1		;HOST DISK NUMBER
HSTTRK:	
	DS	2		;HOST TRACK NUMBER
HSTSEC:	
	DS	1		;HOST SECTOR NUMBER
;
SEKHST:	
	DS	1		;SEEK SHR SECSHF
HSTACT:	
	DS	1		;HOST ACTIVE FLAG
HSTWRT:	
	DS	1		;HOST WRITTEN FLAG
;
UNACNT:	
	DS	1		;UNALLOCATED RECORD COUNT
UNADSK:	
	DS	1		;LAST UNALLOCATED DISK
UNATRK:	
	DS	2		;LAST UNALLOCATED TRACK
UNASEC:	
	DS	1		;LAST UNALLOCATED SECTOR
;
ERFLAG:	
	DS	1		;ERROR REPORTING
RSFLAG:	
	DS	1		;READ SECTOR FLAG
READOP:	
	DS	1		;1 IF READ OPERATION
WRTYPE:	
	DS	1		;WRITE OPERATION TYPE
DMAADR:	
	DS	2		;DISK DMA TRANSFER ADDRESS
;
ENDZ	EQU	$		;END OF ZEROED AREA
;
	PAGE
;
;HOST DATA BUFFER  MEMORY AREA MUST BE ACCESSABLE VIA
;DMA BY THE HARD DISK CONTROLLER BOARD.
;
;
HSTBUF:	
	DS	HSTSIZ		;HOST BUFFER
;
;
;SET SIZE OF COLD BOOT CP/M IMAGE FOR TRACK 0 SECTOR 1 PARAMETER
;
IMGSIZ	EQU	HSTBUF-CCP
;
;
;SCRATCH RAM AREA FOR BDOS USE
;
	ENDEF			;LET DISKDEF FIXUP BDOS BUFFERS
;
;
	END
;
;
;+++...END OF FILE
«eof»