home *** CD-ROM | disk | FTP | other *** search
- .Z80
- .COMMENT @
-
- ***************************************************************
- * *
- * --- Custom BIOS for CP/M 2.2 --- *
- * *
- * Version: 1.0 28 0ct 1984. *
- * *
- * by Mark Little. *
- * *
- ***************************************************************
-
- Custom BIOS for the Ferguson Big Board I to allow
- auto-execution of commands on Cold Boot ONLY.
-
- NOTE:
- -----
- This has been implemented for a specific system which
- uses the parallel port for a Terminal. It also does not have
- a printer implemented. You will most likely have to modify
- the I/O jumps into the monitor and insert the printer setup in
- the Cold Boot routine. The listing of the CBIOS supplied with
- the system will show you how to do it. Also, the CBIOS supplied
- with the original system modifies the monitor code, preventing
- easy monitor modification. This version has eliminated that
- problem (without affecting operation).
- The CBIOS uses a portion of the Monitor Work Area to
- store its variables and implement its stack. Normally the area
- used (0FF7CH - 0FFFFH) is unused once the monitor loses control
- and is free for use, so BEWARE if you have software that uses
- this area also.
-
- INSTALLATION.
- -------------
-
- (1) Modify to suit your system.
- (2) Assemble to produce a .HEX file
- (3) DDT CPM60.COM (supplied on original CP/M diskette)
- (4) ICBIOS.HEX (Identify File to use)
- (5) R1E7D (Read in file with offset 1F80H-103H)
- (6) ^C (Exit DDT with changing memory image)
- (7) SYSGEN (RETURN with asked for Source Drive)
- (8) Test your modifications.
- (9) Place a copy of you modifications in Public Domain
-
-
- @
-
-
- MEMORY_SIZE EQU 64 ; 64k bytes of RAM
- MONITOR_SIZE EQU 4 ; 4k bytes of Monitor
- USER_MEMORY EQU MEMORY_SIZE-MONITOR_SIZE
- MONITOR EQU USER_MEMORY*1024
- BIAS EQU (USER_MEMORY-20)*1024
- CCP EQU BIAS+03400H
- CBIOS EQU CCP+01600H
- BDOS EQU CCP+00806H ; BDOS Entry point
- STACK EQU 00000H ; Stack pointer
- IOBYTE EQU 00003H ; I/O Byte
- CONSOLE_STATUS EQU MONITOR+6
- CONSOLE_INPUT EQU MONITOR+9
- LIST_OUTPUT EQU MONITOR+15
- READ_DEVICE EQU MONITOR+21 ; Read device
- TIKCNT EQU 0FF5DH ; Tick counter
- RUN_UNIT EQU 0FF79H ; Run unit
- DISK_UNIT EQU RUN_UNIT+1 ; Disk Unit
- TRACK EQU DISK_UNIT+1 ; Track
- SECTOR EQU TRACK+1 ; Sector
- DMA_ADDRESS EQU SECTOR+1 ; DMA address store
- RETRY_COUNT EQU DMA_ADDRESS+2 ; Retry count
-
- SYDAP EQU 28 ; System Control Port
- MAX_DRIVE EQU 04H ; Max No of drives
-
- CR EQU 0DH ; Carriage return
- LF EQU 0AH ; Line feed
- FF EQU 0CH ; Form Feed
- TAB EQU 08H ; TAB character
-
- ; Set assembly address.
-
- .PHASE CBIOS
-
- ; Jump Table into CBIOS.
-
- JP COLD_BOOT ; Cold Boot Entry
- JP WARM_BOOT ; Warm Boot Entry
- JP CONSOLE_STATUS ; Console Status
- JP CONSOLE_INPUT ; Console Input
- JP CONSOLE_OUTPUT ; Console output
- JP LIST_OUTPUT ; List output
- JP PUNCH_DEVICE ; Punch output
- JP READ_DEVICE ; Reader input
- JP HOME_HEAD ; Home Disk head
- JP SELECT_DRIVE ; Select the drive
- JP SEEK_TRACK ; Seek to a sector
- JP SET_SECTOR ; Set the sector
- JP SET_DMA_ADDRESS ; Set DMA address
- JP READ_SECTOR ; Read a sector
- JP WRITE_SECTOR ; Write a sector
- JP LIST_STATUS ; List status
- JP TRANSLATE_SECTOR ; Locate physical
-
- ; Send a character to the Punch Device.
-
- PUNCH_DEVICE:
- LD A,C
- JP MONITOR+24 ; Go to the monitor
-
- ; Return permanent ready in this version.
-
- LIST_STATUS:
- XOR A ; Zero register
- DEC A ; Reset the 'Z' flag
- RET
-
- ; Console Output routine.
-
- CONSOLE_OUTPUT:
- LD A,C
- JP MONITOR+12 ; Send to Console
-
- ; Cold Boot CBIOS Routine.
-
- COLD_BOOT:
- XOR A ; Zero the byte
- LD (IOBYTE),A ; Reset I/O byte
- LD HL,TITLE_MESSAGE ; Title
- CALL SHOW_MESSAGE ; Send to console
- CALL SET_DEFAULTS ; Default addresses
- JP CCP ; Cold start the CCP
-
- ; Warm Boot CBIOS Routine.
-
- WARM_BOOT:
- LD SP,STACK ; Monitor stack area
- LD A,(DISK_UNIT) ; Get disk unit
- LD (RUN_UNIT),A ; Save it
- LD C,0 ; Select disk 'A'
- CALL SELECT_DRIVE ; Select it
- CALL HOME_HEAD ; Send to track 0
- LD HL,CCP ; Point to the CCP
- LD BC,00D02H
- CALL READ_LOOP ; Even sectors, track 0
- LD HL,CCP+00080H ; Update DMA address
- LD BC,00C03H
- CALL READ_LOOP ; Odd sectors, track 1
- LD C,1
- CALL SEEK_TRACK ; Seek track 1
- JR NZ,FATAL_LOAD_ERROR ; Oops - Abort it now
-
- LD HL,BIAS+4080H
- LD BC,00A01H
- CALL READ_LOOP ; Odd sectors, track 1
- LD HL,BIAS+04100H
- LD BC,00902H
- CALL READ_LOOP ; Even sectors, track 1
- CALL SET_DEFAULTS ; Set default values
- JP CCP+3 ; Warm start CCP
-
- ; Set up Default Values.
-
- SET_DEFAULTS:
- LD A,0C3H ; Jump command
- LD (00000H),A ; Warm start jump
- LD (00005H),A ; BDOS jump
- LD (00038H),A ; Restart FF jump
- LD HL,CBIOS+3 ; Routine address
- LD (00001H),HL ; Put into position
- LD HL,BDOS ; Routine address
- LD (00006H),HL ; Put into position
- LD HL,MONITOR ; Monitor cold start
- LD (00039H),HL ; Put into position
- LD BC,00080H ; Default DMA address
- CALL SET_DMA_ADDRESS ; Save it
- LD A,(RUN_UNIT)
- LD (DISK_UNIT),A
- LD C,A ; Put unit into 'C'
- RET
-
- ; Read a series of sectors.
-
- READ_LOOP:
- LD (DMA_ADDRESS),HL ; Save DMA address
- LD A,C ; Get the sector
- LD (SECTOR),A ; Save it
- PUSH HL
- PUSH BC ; Save registers
- CALL READ_SECTOR ; Read a sector
- POP BC
- POP HL ; Restore 'em
- JR NZ,FATAL_LOAD_ERROR ; Oops - Abort now
-
- INC H ; Set DMA by 256 bytes
- INC C
- INC C ; Bump sector by 2
- DJNZ READ_LOOP ; Read next sector
- RET
-
- ; Show that CP/M was unable to be loaded from Disk.
-
- FATAL_LOAD_ERROR:
- LD HL,FATAL_ERROR ; Error message
- CALL SHOW_MESSAGE ; Tell the user
- IN A,(SYDAP) ; Get port status
- OR 01000100B ; Mask to kill disks
- OUT (SYDAP),A ; Send to the port
- HALT ; Stop the processor
-
- ; Store the Sector number passed.
-
- SET_SECTOR:
- LD A,C ; Get the sector
- LD (SECTOR),A ; Save the Sector
- RET
-
- ; Translate to the Physical Sector.
-
- TRANSLATE_SECTOR:
- EX DE,HL ; Swap to use
- ADD HL,BC ; Point to sector
- LD L,(HL) ; Put into L
- LD H,0 ; Make HL the sector
- RET
-
- ; Set the DMA address.
-
- SET_DMA_ADDRESS:
- LD (DMA_ADDRESS),BC ; Save it
- RET
-
- ; Select the Drive to use.
-
- SELECT_DRIVE:
- LD HL,0 ; Clear result
- LD A,C ; Get drive Number
- CP MAX_DRIVE ; Out of bounds?
- RET NC ; Yes - Abort
-
- LD (DISK_UNIT),A ; Store new drive
- LD L,A ; Drive into HL
- ADD HL,HL ; Drive*2
- ADD HL,HL ; Drive*4
- ADD HL,HL ; Drive*8
- ADD HL,HL ; Drive*16
- LD DE,DRIVE_PARAM_HEADER ; Parameter block
- ADD HL,DE ; Point to correct one
- PUSH HL ; Save table pointer
- LD B,0 ; Fastest seek speed
- LD C,A ; Load Disk Drive No.
- CALL MONITOR+27 ; Do monitor routine
- POP HL ; Restore table pointer
- RET Z ; Return if successful
-
- LD C,1
- CALL REPORT
- JR NZ,SELECT_DRIVE2 ; Jump if abort found
-
- LD A,(DISK_UNIT) ; Else try again
- LD C,A
- JR SELECT_DRIVE
-
- SELECT_DRIVE2:
- LD HL,0 ; Flag as bad one
- LD A,(RUN_UNIT)
- LD (DISK_UNIT),A ; Restore old drive
- RET
-
- ; Home the Disk Drive's head to Track 0.
-
- HOME_HEAD:
- CALL MONITOR+30 ; Monitor Home routine
- RET Z ; Return if OK
-
- LD C,2
- CALL REPORT
- JR Z,HOME_HEAD ; Retry if error
-
- RET
-
- ; Seek to the selected track.
-
- SEEK_TRACK:
- LD A,C ; Get the track
- LD (TRACK),A ; Save the track
- SEEK_TRACK1:
- CALL MONITOR+33 ; Call the monitor
- RET Z ; Return if no error
-
- LD C,2 ; Type of error
- CALL REPORT ; Show the error
- RET NZ ; Fatal Error - Abort!
-
- LD A,(TRACK) ; Get the track
- LD C,A
- JR SEEK_TRACK1 ; Retry
-
-
- ; Read a Sector.
-
- READ_SECTOR:
- LD HL,(DMA_ADDRESS) ; Get the DMA address
- LD A,(SECTOR) ; Get the sector
- LD C,A
- CALL MONITOR+36 ; Call the monitor
- RET Z ; Return if no error
-
- LD C,3 ; Type of error
- CALL REPORT ; Show the error
- JR Z,READ_SECTOR ; Retry
-
- RET ; Abort
-
-
- ; Write a sector.
-
- WRITE_SECTOR:
- LD HL,(DMA_ADDRESS) ; Get the DMA address
- LD A,(SECTOR) ; Get the sector
- LD C,A
- CALL MONITOR+39 ; Call the monitor
- RET Z ; Return if no error
-
- LD C,4 ; Type of error
- CALL REPORT ; Show the error
- JR Z,WRITE_SECTOR ; Retry
-
- RET ; Abort
-
- ; Report on the error.
-
- REPORT:
- LD E,A ; Save error flags
- LD D,C ; Save error type
- LD HL,DISK_MESSAGES ; Point to messages
- CALL SHOW_MESSAGE ; Show the message
- DEC HL ; Step back
- LD B,D ; Get error class
- FIND_MESSAGE:
- CALL SKIP ; Find next '$'
- DJNZ FIND_MESSAGE ; Move to the message
-
- CALL SHOW_MESSAGE ; Show error message
- LD HL,ERROR_MESSAGE ; Finish error message
- CALL SHOW_MESSAGE ; Show it
-
- ; Determine the nature of the error.
-
- LD A,E ; Get the flags
- RLA ; Test if drive unready
- JR C,DISK_NOT_READY ; Yes - Skip this bit
-
- LD E,A ; Save the flags
- LD HL,RW_ERRORS ; R/W error messages
- LD A,D ; Get the error type
- CP 3 ; Sel/Seek or R/W?
- JR NC,NOT_SEEK_ERRORS ; Read/Write errors
-
- LD HL,SEEK_ERRORS ; Select message set
- NOT_SEEK_ERRORS:
- LD B,5 ; Five bits to test
- RES 0,D ; Reset comma flag
- WHICH_ERROR:
- SLA E ; Move it left
- JR NC,SELECT_MESSAGE ; Not this one!
-
- LD A,',' ; Load with comma
- BIT 0,D ; Print a comma?
- CALL NZ,MONITOR+12 ; Yes - Do it
-
- CALL SHOW_MESSAGE ; Show the error msg
- SET 0,D ; Make a comma show
- JR TEST_NEXT_BIT ; Continue
-
- SELECT_MESSAGE:
- CALL SKIP ; Move to next message
- RES 0,D ; Kill comma flag
- TEST_NEXT_BIT:
- DJNZ WHICH_ERROR ; Test all bits
-
- LD HL,TRK_SEC_MESSAGE ; Track/Sector message
- CALL SHOW_MESSAGE ; Display it
- LD A,(TRACK) ; Get the track number
- CALL SHOW_HEX_BYTE ; Show it
- LD A,'/' ; Delimiter
- CALL MONITOR+12 ; Send to console
- LD A,(SECTOR) ; get the sector number
- CALL SHOW_HEX_BYTE ; Show it
- PERM_ERROR:
- LD A,1 ; Flag permanent error
- OR A
- RET
-
- DISK_NOT_READY:
- LD HL,DISK_UNREADY ; Show message
- CALL SHOW_MESSAGE ; Show 'em
- CALL CONSOLE_STATUS ; Key Pressed?
- JR Z,WAIT_A_SECOND ; No - Wait, then retry
-
- CALL CONSOLE_INPUT ; Get the character
- CP 'C'-40H ; Abort it?
- JR Z,PERM_ERROR ; Yes!
-
- WAIT_A_SECOND:
- LD A,(TIKCNT) ; Get the current tick
- LD B,A ; Save it
- WAIT:
- LD A,(TIKCNT) ; Get the time
- CP B ; Same?
- JR Z,WAIT ; Yes - Wait
-
- XOR A ; Flag a retry
- RET
-
- ; Skip a message string.
-
- SKIP:
- PUSH BC ; Save
- LD B,255 ; Arbitary large No.
- LD A,'$' ; Terminator
- CPIR ; Block search
- POP BC ; Restore
- RET
-
- ; Send a message string to the Console.
-
- SHOW_MESSAGE:
- LD A,(HL) ; get a character
- CP '$' ; EOT?
- INC HL ; Step pointer
- RET Z ; Yes - Exit
-
- CALL MONITOR+12 ; Send to console
- JR SHOW_MESSAGE ; Continue
-
- ; Send a byte to the screen in HEX format.
-
- SHOW_HEX_BYTE:
- PUSH AF ; Save byte
- RRA
- RRA
- RRA
- RRA ; Swap nibbles
- CALL SHOW_HEX_NIBBLE ; Show it
- POP AF ; Restore byte
- SHOW_HEX_NIBBLE:
- AND 00001111B ; Select lower nibble
- ADD A,90H
- DAA
- ADC A,40H
- DAA ; Convert to hex
- JP MONITOR+12 ; Send to console
-
- ; Title of the CBIOS.
-
- TITLE_MESSAGE:
- DEFB FF,CR,LF
- DEFM "Iceworks' CP/M 2.2 Version: 1.0"
- DEFB CR,LF,'$'
-
- ; Fatal Load Error Message.
-
- FATAL_ERROR:
- DEFB FF,TAB
- DEFM "UNABLE TO LOAD CP/M"
- DEFB CR,LF,'$'
-
- ; Disk Error Messages.
-
- DISK_MESSAGES:
- DEFB CR,LF
- DEFM 'BIOS $'
- DEFM 'SELECT $'
- DEFM 'SEEK $'
- DEFM 'READ $'
- DEFM 'WRITE $'
-
- ; Tail of Error Message.
-
- ERROR_MESSAGE:
- DEFM 'ERROR $'
-
- ; Seek Error Messages.
-
- SEEK_ERRORS:
- DEFM '$'
- DEFM '$'
- DEFM 'CANNOT SEEK$'
- DEFM 'BAD CRC$'
- DEFM 'CANNOT RESTORE$'
-
- ; Drive Not Ready Message.
-
- DISK_UNREADY:
- DEFB CR,LF
- DEFM 'Drive not ready -'
- DEFM CR,LF,'$'
-
- ; Read/Write Errors.
-
- RW_ERRORS:
- DEFM 'WRITE PROTECTED$'
- DEFM 'WRITE FAULT$'
- DEFM 'RECORD NOT FOUND$'
- DEFM 'BAD CRC$'
- DEFM 'DATA OVERRUN$'
-
- ; Track/Sector Message.
-
- TRK_SEC_MESSAGE:
- DEFM ' Track/Sector = $'
-
- ; Drive Parameter Headers for a 4 drive system.
-
- DRIVE_PARAM_HEADER:
-
- DEFW SECTAB,00000H ; Disk Unit 0
- DEFW 00000H,00000H
- DEFW DIRBUF,DPBLOK
- DEFW CHECK0,ALLOC0
-
- DEFW SECTAB,00000H ; Disk Unit 1
- DEFW 00000H,00000H
- DEFW DIRBUF,DPBLOK
- DEFW CHECK1,ALLOC1
-
- DEFW SECTAB,00000H ; Disk Unit 2
- DEFW 00000H,00000H
- DEFW DIRBUF,DPBLOK
- DEFW CHECK2,ALLOC2
-
- DEFW SECTAB,00000H ; Disk Unit 3
- DEFW 00000H,00000H
- DEFW DIRBUF,DPBLOK
- DEFW CHECK3,ALLOC3
-
- ; Sector Translation Table (Standard 1 in 6 interleave).
-
- SECTAB:
- DEFB 1,7,13,19
- DEFB 25,5,11,17
- DEFB 23,3,9,15
- DEFB 21,2,8,14
- DEFB 20,26,6,12
- DEFB 18,24,4,10
- DEFB 16,22
-
- ; Disk Parameter Block for standard 8" Floppy.
-
- DPBLOK:
- DEFW 26 ; Sectors per track
- DEFB 3 ; Block shift constant
- DEFB 7 ; Block mask constant
- DEFB 0 ; Block extent Constatnnt
- DEFW 242 ; Maximum block number
- DEFW 63 ; Maximum Direct. Entry
- DEFB 11000000B ; Allocation Mask MSB
- DEFB 00000000B ; " " LSB
- DEFW 16 ; Check size
- DEFW 2 ; Reserved tracks
-
- ; Disk I/O Buffers for BDOS file Handler.
-
- DIRBUF:
- DEFS 128 ; Scratch Directory
- ALLOC0:
- DEFS 32 ; Allocation Buffer 0
- CHECK0:
- DEFS 16 ; Check Vector 0
- ALLOC1:
- DEFS 32
- CHECK1:
- DEFS 16
- ALLOC2:
- DEFS 32
- CHECK2:
- DEFS 16
- ALLOC3:
- DEFS 32
- CHECK3:
- DEFS 16
-
- END COLD_BOOT