|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 29056 (0x7180)
Types: TextFile
Names: »BIOSKRNL.Z80«
└─⟦21f5a1bd4⟧ Bits:30003500 CP/M Plus (tm) Version 3.0 BIOS Revision F
└─⟦this⟧ »BIOSKRNL.Z80«
└─⟦67f37b9ce⟧ Bits:30003503 JET80/W20FT systemdisk
└─⟦this⟧ »BIOSKRNL.Z80«
Title Bioskrnl.Z80 Root to Bios. CP/M 3.0
;------------------------------------------------------------;
; The total system consists of: ;
; Bioskrnl.Z80 Root ;
; Boot.Z80 Boot module ;
; Chario.Z80 Character I/O module ;
; Drives.Asm Disk defintion module ;
; Fdrives.Asm for floppy systems ;
; Wdrives.Asm for winchester systems ;
; Extmem.Rel External memory module ;
; ExtmemF.Rel for floppy systems ;
; ExtmemA.Rel for winchester Adaptec ;
; ExtmemX.Rel for winchester Xebec ;
; Cntrlr.Rel Controller commands for Adaptec ;
; Scb.Asm System variables ;
;------------------------------------------------------------;
; Latest update: 1985-11-15. PSW
; Bios revision: F
.Z80
True Equ -1
False Equ Not True
BotFlg Equ 0C000h ; Boot flag address
NetWork Equ False
WrkStn Equ False
Page 66
; External variables:
Extrn @CoVec,@CiVec,@AoVec ; I/O REDIRECTION VECTORS
Extrn @AiVec,@LoVec ; - " -
Extrn @MxTpa ; MAX TPA IN USER BANK
Extrn @BnkBf ; COMMON 128 BYTE BUFFER
Extrn Bank0Call
; Init
Extrn ?Patch,?Init ;
Extrn ?LdCcp,?RlCcp ; LOAD & RELOAD CCP
; User defined character I/O routines:
Extrn ?Ci,?Co,?CiSt,?CoSt ;
Extrn ?CInit,IniStm ;
Extrn @CTbl ;
; Disk:
Extrn @DTbl ; POINTER TABLE
Entry @ADrv,@RDrv,@Trk,@Sect ; DISKPARAMETERS
Entry @Dma,@DBnk,@Cnt ; - " -
; Memory module:
Entry @CBnk,BnkMsk,MuxByte ; CURRENT BANK
Entry DmaFlg
Entry ?PMsg ; WRITES MESSAGES
; Global lables to bios calls:
Entry ?Boot,?WBoot,?ConSt,?ConIn,?ConO,?List,?AuxO,?AuxI
Entry ?Home,?SlDsk,?StTrk,?StSec,?StDma,?Read,?Write
Entry ?ListS,?ScTrn
Entry ?ConOs,?AuxIs,?AuxOs,?DvTbl,?DevIn,?DrTbl
Entry ?MltIo,?Flush,?Mov,?Tim,?BnkSl,?StBnk,?XMov
; Global lable to userfunction:
Extrn ?UserF
; Interrupt vectors:
Entry Sio1Iv,CtcIrv
Entry PioIrv
Entry IntVect
; Interrupt driven routines:
Extrn KbdIrq,UnkInt,LptIrq,ClkIrq
If Not WrkStn
Extrn PioGaI,PioGbI
Endif
Extrn KbdErRq,LptErRq,SetLptBuff
Page
; Port address:
; Dma-COMMANDS
DmRSet Equ 0C3h ; SOFTWARE RESET
DmEnab Equ 087h ; ENABLE Dma
DmDisa Equ 083h ; DISABLE Dma
If Not WrkStn
Dma Equ 18h ; Dma.
BnkMux Equ 1BH ; Bank-Dma-MULTIPLEXER
DmBk11 Equ 00000000B ; Bank1 --> Bank1
DmBk00 Equ 00001000B ; Bank0 --> Bank0
DmBk10 Equ 00010000B ; Bank1 --> Bank0
DmBk01 Equ 00011000B ; Bank0 --> Bank1
Bank1 Equ 00000000B ; Bank1 (64K FOR CPU)
Bank0 Equ 00100000B ; Bank0 (48K FOR CPU)
Else
Dma Equ 0F0h ; Dma
BnkMux Equ 0F4h ; Bank-Dma-MULTIPLEXER
DmBk11 Equ 00000100b ; Bank1 --> Bank1
DmBk00 Equ 00000000b ; Bank0 --> Bank0
DmBk10 Equ 00000110b ; Bank1 --> Bank0
DmBk01 Equ 00000010b ; Bank0 --> Bank1
Bank1 Equ 00100000b ; Bank1 (64K FOR CPU)
Bank0 Equ 00100001b ; Bank0 (48K FOR CPU)
Endif
CtlQ Equ 'Q'-'@'
CtlS Equ 'S'-'@'
MbXonXoff Equ 00010000B ; XON/XOFF PROTOCOLL ON.
JpOp Equ 0C3H ; Z80 JUMP INSTRUCTION
Ccp Equ 100H ; LOAD ADDRESS FOR Ccp
Page
Cseg
;------------------------------------------------------------;
; Bios Jump Vectors ;
;------------------------------------------------------------;
?Boot: Jp Boot ;
?WBoot: Jp WBoot ;
?ConSt: Jp ConSt ;
?ConIn: Jp ConIn ;
?ConO: Jp ConOut ;
?List: Jp List ;
?AuxO: Jp AuxOut ;
?AuxI: Jp AuxIn ;
?Home: Jp Home ;
?SlDsk: Jp SelDsk ;
?StTrk: Jp SetTrk ;
?StSec: Jp SetSec ;
?StDma: Jp SetDma ;
?Read: Jp Read ;
?Write: Jp Write ;
?ListS: Jp ListSt ;
?ScTrn: Jp SecTrn ;
?ConOs: Jp ConoSt ;
?AuxIs: Jp AuxISt ;
?AuxOs: Jp AuxOSt ;
?DvTbl: Jp DevTbl ;
?DevIn: Jp ?CInit ; IN CHARIO.Z80
?DrTbl: Jp GetDrv ;
?MltIo: Jp MultIO ;
?Flush: Jp Flush ;
?Mov: Jp ?Move ;
?Tim: Jp Return ; NOT INSTALLED
?BnkSl: Jp BnkSel ;
?StBnk: Jp SetBnk ;
?XMov: Jp ?XMove ;
Jp ?UserF ; IN EXTMEM.Z80
Jp Return ;
Jp Return ;
Nop ; GIVE CORRECT START FOR INT.VECTORS.
Page
;------------------------------------------------------------;
; Interrupt Vectors ;
;------------------------------------------------------------;
IntVect Equ $ ; INTERRUPT VECTOR ADDRESS
PioIrv Equ $ ; PIO BASE INTERRUPT VECTOR
If Not WrkStn
Dw PioGaI ; GRAPHIC SCREEN READY
Dw PioGbI ; GRAPHIC KEY BOARD
Else
Dw UnkInt ;
Dw UnkInt ;
Endif
CtcIrv Equ $ ; CTC BASE INTERRUPT VEKTOR
Dw UnkInt ;
Dw UnkInt ;
Dw UnkInt ;
Dw ClkIrq ; (10 Hz TICK)
Sio1Iv Equ $ ; SIO1 BASE INTERRUPT VECTOR
Dw KbdIrq ; KEYBOARD INT.
Dw KbdIrq ;
Dw KbdIrq ;
Dw KbdErRq ;
Dw LptIrq ;
Dw LptIrq ;
Dw LptIrq ;
Dw LptErRq ;
Db 'This area is used as stack by CCP but You '
Db 'can use it for interrupt vectors when'
Db ' CCP not in ram '
Boot$Stack Equ $
Page
;------------------------------------------------------------;
; Boot -- Cold start init. routunes. ;
;------------------------------------------------------------;
Dseg ;; Code in Bank0.
Boot: Di ;;
Ld Sp,Boot$Stack ;;
Call ?Patch ;; Patch loader parameters
Ld Bc,16*256+0 ;; B=Counter, C=Dev#.
C_Init_Loop: ;;
Push Bc ;;
Call ?CInit ;; Init char. dev.
Pop Bc ;;
Inc C ;;
Djnz C_Init_Loop ;;
Call ?Init ;; Init the rest.
If Not NetWork
Ld A,(BotFlg) ;; Winchester boot?
And A ;;
Jr Z,GoOn ;; No...jump
Ld Hl,(@DTbl+4) ;; GET C:
Ld De,(@DTbl+2) ;; B:
Ld Bc,(@DTbl) ;; A:
Ld (@DTbl),De ;; B: --> A:
Ld (@DTbl+2),Hl ;; C: --> B:
Ld (@DTbl+4),Bc ;; A: --> C:
Endif
; Go on init 16 logical disk units.
GoOn: Ld Bc,16*256+0 ;; B=Counter, C=Log. drive#
Ld Hl,@DTbl ;; drive table.
D_In_Loop: ;;
Push Bc ;; save # and drive.
Ld E,(Hl) ;; get DPH-vector
Inc Hl ;;
Ld D,(Hl) ;; in De.
Inc Hl ;;
Ld A,E ;; does drive exist ?
Or D ;;
Jr Z,D_In_Next ;; No...next
Push Hl ;; save vector pointer
Ex De,Hl ;;
Dec Hl ;; .media byte
Dec Hl ;; .controller rel. address
Ld A,(Hl) ;; get it
Ld (@RDrv),A ;; and save it
Ld A,C ;; And save
Ld (@ADrv),A ;; logical drive#.
Dec Hl ;; Get init-vector
Ld D,(Hl) ;;
Dec Hl ;;
Ld E,(Hl) ;; into De.
Ex De,Hl ;;
Call IPcHl ;; execute init.
Pop Hl ;; Restore vector pointer.
D_In_Next: ;;
Pop Bc ;; Restore counter, drive
Inc C ;; Next drive
Djnz D_In_Loop ;; Loop...
Jp Boot$1 ;; Take the last part in Bank1.
Cseg ; Bank 1.
Boot$1:
Call SetJumps ; Set jump vectors
Call ?LdCcp ; Read Ccp.Com from disk
Jp Ccp ;
;------------------------------------------------------------;
; WBoot -- Warm boot routine. ;
;------------------------------------------------------------;
WBoot:
Ld Sp,Boot$Stack ;
Ld Hl,0 ;
Ld C,5 ; Reset Lpt interrupt buffer
Call ?UserF ;
Ld C,2 ;
Call ?UserF ; Flush floppy/winchester buffers
Call SetJumps ; Init page zero
Call ?RlCcp ; Reread Ccp.Com
Jp Ccp ;
SetJumps:
Ld A,1 ; Select Bank1
Call ?BnkSl ;
Ld A,JpOp ; Z80 Jp opcode
Ld Hl,?WBoot ; Warm Boot entry point
Ld (0),A ;
Ld (1),Hl ;
Ld Hl,(@MxTpa) ; Bdos entry point
Ld (5),A ;
Ld (6),Hl ;
Return: Ret ;
;------------------------------------------------------------;
; DevTbl -- Returns the address to character device table. ;
;------------------------------------------------------------;
DevTbl: Ld Hl,@CTbl ;
Ret ;
;------------------------------------------------------------;
; GetDrv -- Returns the address to drive table. ;
;------------------------------------------------------------;
GetDrv: Ld Hl,@DTbl ;
Ret ;
Page
;------------------------------------------------------------;
; Character I/O Routines. ;
;------------------------------------------------------------;
;------------------------------------------------------------;
; ConOut -- Console output. Sends a charcter in (C) to all ;
; choosen devices. ;
;------------------------------------------------------------;
ConOut:
Ld Hl,ConOutB0 ;
Jp Bank0Call ;
Dseg
ConOutB0: ;;
Ld Hl,(@CoVec) ;; Get console oputput bit vector
Jr OutScan ;;
Cseg
;------------------------------------------------------------;
; AuxOut -- Auxilliary output. Sends a character in (C) to ;
; all choosen devices. ;
;------------------------------------------------------------;
AuxOut:
Ld Hl,AuxOutB0 ;
Jp Bank0Call ;
Dseg
AuxOutB0: ;;
Ld Hl,(@AoVec) ;; Get aux output bit vector
Jr OutScan ;;
Cseg
;------------------------------------------------------------;
; List -- List output. Sends a character in (C) to all ;
; choosen devices. ;
;------------------------------------------------------------;
List:
Ld Hl,ListB0 ;
Jp Bank0Call ;
Dseg
ListB0: ;;
Ld Hl,(@LoVec) ;; Get list output bit vector
;; and do OutScan
OutScan: ;;
Ld B,0 ;; Start with device 0.
CoNext:
Add Hl,Hl ;; Shift next device bit
Jr NC,NoOutDev ;; Jump...if not set
Push Hl ;; Save bit vector
Push Bc ;; device and char.
CoOutRdy: ;;
Call Coster ;;
Or A ;; Ready ? ?
Jr Z,CoOutRdy ;; No...jump
Pop Bc ;; B=device# C=Char
Push Bc ;; save
Call ?Co ;; Send char
Pop Bc ;; Restore
Pop Hl ;;
NoOutDev: ;;
Inc B ;; Next device#
Ld A,H ;; Any bits left in bit vector
Or L ;;
Jr Nz,CoNext ;; Yes...loop
Ret ;;
Cseg
;------------------------------------------------------------;
; ConoSt -- Console output status. Returns true if all ;
; choosen console output devices are ready. ;
;------------------------------------------------------------;
ConoSt: ;
Ld Hl,ConoStB0 ;
Jp Bank0Call ;
Dseg
ConoStB0: ;;
Ld Hl,(@CoVec) ;; Get console output bit vector
Jr OStScan ;;
Cseg
;------------------------------------------------------------;
; AuxOSt -- Auxiliary output status. Returns true if all ;
; choosen aux output devices are ready. ;
;------------------------------------------------------------;
AuxOSt: ;
Ld Hl,AuxOStB0 ;
Jp Bank0Call ;
Dseg
AuxOStB0: ;;
Ld Hl,(@AoVec) ;; Get aux output bit vector
Jr OStScan ;;
Cseg
;------------------------------------------------------------;
; ListSt -- List output status. Returns true if all choosen ;
; list output devices are ready. ;
;------------------------------------------------------------;
ListSt: ;
Ld Hl,LstStoStB0 ;
Jp Bank0Call ;
Dseg
LstStoStB0: ;;
Ld Hl,(@LoVec) ;; Get list output bit vector.
OStScan: ;;
Ld B,0 ;; Start with device #0.
CosNext: ;;
Add Hl,Hl ;; Shift next device bit
Push Hl ;; save bit vector
Push Bc ;; B=dev#, C=Char.
Ld A,-1 ;; Set dev. ready
Call C,Coster ;; Get status if choosen
Pop Bc ;; Restore
Pop Hl ;;
Or A ;; Ready ?
Ret Z ;; No...Return false.
Inc B ;; Next device
Ld A,H ;; Any more devs. ?
Or L ;;
Jr Nz,CosNext ;; Yes...loop
Or 0FFH ;; All choosen devices ready
Ret ;; Return true.
; CHECK IF OUTPUT DEVICE READY (XON/XOFF SUPPORT).
Coster: Ld L,B ;; CHANGE DEVICE # TO 16 BITS
Ld H,0 ;; Hl=DEV#
Push Hl ;;
Add Hl,Hl ;; OFFSET IN DEVICE-TABLE
Add Hl,Hl ;;
Add Hl,Hl ;; Hl=Hl*8
Ld De,@CTbl+6 ;; De= MODE BYTE FØR DEV 0
Add Hl,De ;; Hl=RÆTT MODE BYTE
Ld A,(Hl) ;; GET MODE BYTE
And MbXonXoff ;; XON/XOFF PROTOCOLL?
Pop Hl ;; Hl=DEVICE #
Jp Z,?CoSt ;; NO XON/XOFF...JUMP
Ld De,XoffList ;;
Add Hl,De ;; Hl=PLACE IN XoffList
Ld C,0 ;; FLAGSTATUS FOR ^C, ^S, ^Q ONLY
Call CiStl ;;
Ld A,(Hl) ;;
Call Nz,CIL ;;
Cp CtlQ ;;
Jr Nz,NotQ ;;
Ld A,-1 ;; SET READY-FLAG
NotQ: Cp CtlS ;; CTL-S?
Jr Nz,NotS ;; NO...JUMP
Xor A ;; CLEAR FLAG
NotS: Ld (Hl),A ;; SAVE FLAG
Call CoSt1 ;; GET OUTPUT STATUS
And (Hl) ;; And MASK WITH XON/XOFF FLAG
Ret ;; And Return IT AS STATUS
CiStl: Push Bc ;; GET INPUT STATUS WITH (Bc) & (Hl)
Push Hl ;;
Call ?CiSt ;;
Pop Hl ;;
Pop Bc ;;
Or A ;;
Ret ;;
CoSt1: Push Bc ;; GET OUTPUT STATUS, SAVE (Bc) & (Hl)
Push Hl ;;
Call ?CoSt ;;
Pop Hl ;;
Pop Bc ;;
Or A ;;
Ret ;;
CIL: Push Bc ;; GET INPUT And SAVE (Bc) & (Hl)
Push Hl ;;
Call ?Ci ;;
Pop Hl ;;
Pop Bc ;;
Ret ;;
Cseg
;------------------------------------------------------------;
; ConSt -- Console input status. Returns true if any choosen ;
; console input device has a character available. ;
;------------------------------------------------------------;
ConSt: ;
Ld Hl,ConStB0 ;
Jp Bank0Call ;
Dseg
ConStB0: ;;
Ld Hl,(@CiVec) ;; Get console input bit vector
Jr IstScan ;;
Cseg
;------------------------------------------------------------;
; AuxISt -- Auxialiary input status. Returns true if any ;
; Choosen aux input device has a character avail. ;
;------------------------------------------------------------;
AuxISt: ;
Ld Hl,AuxIStB0 ;
Jp Bank0Call ;
Dseg
AuxIStB0: ;;
Ld Hl,(@AiVec) ;; Get aux input bit vector
IstScan: ;;
Ld Bc,0 ;; START WITH DEVICE 0
;; CREG = 0 = FLAG, STATUS Call ONLY
CisNext: ;;
Xor A ;; SET DEVICE NOT READY
Add Hl,Hl ;; SHIFT OUT ONE BIT
Call C,CiStl ;; CHECK STATUS ON THIS DEVICE
Or A ;; IF ANY READY Return TRUE.
Ret Nz ;;
Inc B ;; NEXT DEVICE #
Ld A,H ;; CHECK IF ANY MORE DEV.
Or L ;;
Jr Nz,CisNext ;;
Xor A ;; ALL CHOOSEN NOT READY. FALSE
Ret ;;
Cseg
;------------------------------------------------------------;
; ConIn -- Console input. Returns a character from first ;
; ready console device. ;
;------------------------------------------------------------;
ConIn: ;
Ld Hl,ConInB0 ;
Jp Bank0Call ;
Dseg
ConInB0: ;;
Ld Hl,(@CiVec) ;; Get console input bit vector
Call InScan ;;
And 7FH ;; strip off parity bit.
Ret ;;
Cseg
;------------------------------------------------------------;
; AuxIn -- Auxialiary input. Returns a character from first ;
; ready aux input device. ;
;------------------------------------------------------------;
AuxIn: ;
Ld Hl,AuxInB0 ;
Jp Bank0Call ;
Dseg
AuxInB0: ;;
Ld Hl,(@AiVec) ;; Get aux input bit vector
InScan: ;;
Push Hl ;; SAVE BIT VECTOR
Ld B,0 ;; START WITH DEVICE 0
Ld C,-1 ;; CREG = FF = STATUS Call FOR INPUT
CiNext: ;;
Xor A ;; SET NO CHAR
Add Hl,Hl ;; SHIFT OUT ONE BIT
Call C,CiStl ;; CHECK IF DEVICE HAS A CHAR
Or A ;; CHAR?
Jr Nz,CiRdy ;; YES...JUMP
Inc B ;; TEST NEXT DEVICE
Ld A,H ;;
Or L ;;
Jr Nz,CiNext ;;
Pop Hl ;; Hl=BIT VECTOR
Jr InScan ;; LOOP UNTIL GOT A CHAR
CiRdy: Pop Hl ;; Hl=BIT VECTOR
Jp ?Ci ;; GET INPUT FROM DEVICE # IN B.
Page
Cseg
;------------------------------------------------------------;
; Subroutines ;
;------------------------------------------------------------;
IPcHl: Jp (Hl) ; VECTOR-Call
?PMsg: ; Prints a message @(Hl) terminated
; with Db 0.
Ld A,(Hl) ; Get next char
Or A ; is it 0 ?
Ret Z ; Yes...Return
Push Hl ; Save registers
Push De ;
Push Bc ;
Ld C,A ; char in (C)
Call ?ConO ; print it
Pop Bc ; Restore
Pop De ;
Pop Hl ;
Inc Hl ; Next byte
Jr ?PMsg ; Loop...
;------------------------------------------------------------;
; ?Move -- Blockmove: Memory to memory. ;
; ;
; At entry: Hl = Destination address. ;
; De = Source address. ;
; Bc = Counter. ;
; At exit: Hl & De pointing to the next bytes ;
; that follows the move. ;
;------------------------------------------------------------;
?Move: Ld A,B ; Is it a zero-move ?
Or C ;
Ret Z ; Yes...quit
Ld A,(BnkFlg) ; Is ?XMove involved ?
And A ;
Jr Nz,Move1 ; Yes...
Ex De,Hl ; Exchange addresses to fit
Ldir ; this instruction
Ex De,Hl ; and get them back.
Ret ;
Move1: Di ; Shut up for a moment
Call WaitDma ; Wait for Dma
Xor A ; Zero ?XMove-flag
Ld (BnkFlg),A ;
Ld (SrcAdr),De ; Set source address in Dmatable
Ld (DstAdr),Hl ; Set destination address in Dmatable
Add Hl,Bc ; Hl= End dest.address
Push Hl ; Saved.
Ex De,Hl ;
Add Hl,Bc ; Hl= End sourceaddress
Push Hl ; saved.
Dec Bc ; Reduce blocklength with 1
Ld (Length),Bc ; Check for the Dma command
Ld A,B ;
Or C ;
Ld A,11001101b ; If not 1 byte set burst mode
Jr Nz,Move2 ;
Ld A,10001101b ; else set byte mode.
Move2: Ld (Mode),A ; SAVE THE Mode
Ld Hl,(DstBnk) ;
Ld A,H ; Dest.bank in A.
Rla ; shift out left
Or L ; add on source bank.
And 00000011b ; mask garbidge.
Ld L,A ; Will give index
Ld H,0 ; in table.
Ld De,BnkTbl ; Offset in the table.
Add Hl,De ; Point to the right byte
Ld A,(Hl) ; Get it.
Ld Hl,BnkMsk ; Add on bankmask
Or (Hl) ;
Ld Hl,DmaTbl ; Point to the Dmatable.
Out (BnkMux),A ; Start dma
Ld (MuxByte),A ;
Push Bc ; Save counter
Call IniStm ;
Pop Bc ; Restore counter
Ld A,B ;
Or C ;
Jr Z,Move4 ;
Move3: In A,(Dma) ; Read status
And 00100000b ; ready ?
Jr Nz,Move3 ; No...
Move4: Ld A,DmDisa ; Disable Dma
Out (Dma),A ;
Xor A ; Free Dma
Ld (DmaFlg),A
Ei ; Speak again
Pop De ; Restore parameters
Pop Hl ;
Ld Bc,0 ; COUNTER=0
Ret ;
;------------------------------------------------------------;
; WaitDma -- Wait until Dma is free, then mark it busy. ;
;------------------------------------------------------------;
WaitDma: ;
Ld A,(DmaFlg) ;
And A ;
Jr Nz,WaitDma ;
Inc A ;
Ld (DmaFlg),A ;
Ret ;
;------------------------------------------------------------;
; ?XMove -- Sets correct banks for data transferes. ;
; ;
; At entry: B = Destination bank. ;
; C = Source bank. ;
;------------------------------------------------------------;
?XMove: ;
Ld A,True ;
Ld (BnkFlg),A ; Mark ?XMove
Ld (DstBnk),Bc ; Gives (C) in dest.bank
; and (B) in source bank.
Ret ;
;------------------------------------------------------------;
; BnkSel -- Select bank. ;
; ;
; At entry: A = Memory Bank. ;
;------------------------------------------------------------;
BnkSel: ;
Di ; Nothing crazy may happen now
Ld (@CBnk),A ; Save current bank
And 1 ; mask
Ld A,Bank0 ; Start with Bank0.
Jr Z,Bnk1 ; Bank0 ? Yes...
Ld A,Bank1 ; Else set Bank1.
Bnk1: ;
Ld (BnkMsk),A ;
Out (BnkMux),A ; Send it to Bank select port.
Ld (MuxByte),A ;
Ei ; It worked.
Ret ;
Page
;------------------------------------------------------------;
; Disk Drive Routines ;
;------------------------------------------------------------;
Dseg ;; Bank 0.
;------------------------------------------------------------;
; SelDsk -- Select disk drive. Executes the login procedure ;
; for the drive if it is the first time select. ;
; ;
; At entry: C = Selected drive. ;
; E = Bit0 reset if not slected before. ;
; At exit: Hl = 0 if drives does not exist. ;
; Hl = @DPH if drive exists. ;
;------------------------------------------------------------;
SelDsk: Ld A,C ;;
Ld (@ADrv),A ;; SAVE #
Ld L,C ;; CREATE INDEX
Ld H,0 ;;
Add Hl,Hl ;; Hl=2*DRIVE #TO OFFSET
Ld Bc,@DTbl ;; POINT TO DRIVE-TABLE-HEAD
Add Hl,Bc ;; Hl=CORRECT VECTOR IN @DTbl
Ld A,(Hl) ;; GET DPH-POINTER
Inc Hl ;;
Ld H,(Hl) ;;
Ld L,A ;; Hl=DPH-POINTER
Or H ;; SET Z-FLAG And
Ret Z ;; Return IF NO DRIVE
Ld A,E ;;
And 1 ;; FIRST SELECT?
Ret Nz ;; NO...Return
Push Hl ;; SAVE DPH-POINTER
Ex De,Hl ;;
Ld Hl,-2 ;; GET (DPH-2)
Add Hl,De ;;
Ld A,(Hl) ;;
Ld (@RDrv),A ;; SAVE THE CONTROLLER RELATIVE DRIVE#
Ld Hl,-6 ;; GET THE LOGIN-VECTOR
Add Hl,De ;;
Ld A,(Hl) ;;
Inc Hl ;;
Ld H,(Hl) ;;
Ld L,A ;;
Call IPcHl ;; DO LOGIN
Pop Hl ;; Hl=DPH-POINTER
Ret ;;
;------------------------------------------------------------;
; Home -- Home selected drive. Do SetTrk (0). ;
; ;
; SetTrk -- Set track address. ;
; ;
; At entry: Bc = Track address ;
; At exit: (@Trk) = Track address. ;
;------------------------------------------------------------;
Home: Ld Bc,0 ;; Track=0
SetTrk: Ld (@Trk),Bc ;; Save track address
Ret ;;
;------------------------------------------------------------;
; SetSec -- Set sector address. ;
; ;
; At entry: Bc = Sector address ;
; At exit: (@Sect) = Sector address. ;
;------------------------------------------------------------;
SetSec: Ld (@Sect),Bc ;; Save sector address
Ret ;;
;------------------------------------------------------------;
; SetDma -- Set Direct Memory Access disk address. ;
; ;
; At entry: Bc = Dma address ;
; At exit: (@Dma) = Dma address ;
; (@DBnk) = @CBnk ;
;------------------------------------------------------------;
SetDma: Ld (@Dma),Bc ;; Set global Dma address
Ld A,(@CBnk) ;; Default Dma Bank is current Bank
;; get current Bank & do SetBnk
;------------------------------------------------------------;
; SetBnk -- Set disk I/O memory Bank. ;
; ;
; At entry: A = Disk Bank # ;
; At exit: (@DBnk) = Disk Bank # ;
;------------------------------------------------------------;
SetBnk: Ld (@DBnk),A ;; Set Disk Dma Bank
Ret ;;
;------------------------------------------------------------;
; SecTrn -- Sector translate. Translate logical sector number;
; to physical sector number. ;
; ;
; At entry: Bc = Logical sector # ;
; De = Pointing to TransTable. (0 if none). ;
; At exit: Hl = Physical sector #. ;
;------------------------------------------------------------;
SecTrn: Ld L,C ;;
Ld H,B ;; Hl=CP/M sector # (relative 0)
Inc Hl ;; Hl= -"- (relative 1)
Ld A,D ;; Test De=0
Or E ;;
Ret Z ;; Yes...Return, no TransTable
Dec Hl ;; Hl= CP/M sector # (relative 0)
Add Hl,De ;; Hl=Index in table
Ld L,(Hl) ;; Translate to sector # from table
Ld H,0 ;; 8 bits value
Ret ;;
;------------------------------------------------------------;
; Read -- Reads physical sector from selected disk to current;
; @Dma address. ;
; ;
; At entry: None ;
; At exit: A = 0 Ok. ;
; A = 1 if error. ;
; A =-1 if media change. ;
;------------------------------------------------------------;
Read: Ld De,-8 ;; Index offset to Readroutine
Push De ;; on the stack
Jr RWCommon ;; Read-Write-Common-Routine
;------------------------------------------------------------;
; Write -- Writes physical sector on selected disk from ;
; current @Dma address. ;
; ;
; At entry: C = Deblocking code. ;
; At exit: A = 0 If Ok. ;
; A = 1 Physical error. ;
; A = 2 Disk is R/O. ;
; A =-1 If media change. ;
;------------------------------------------------------------;
Write: Ld De,-10 ;; Index offset to Writeroutine
Push De ;; on the stack
RWCommon: ;;
Ld Hl,(@ADrv) ;; Get drive #
Ld H,0 ;;
Add Hl,Hl ;; Hl=2*Drive#
Ld De,@DTbl ;;
Add Hl,De ;;
Ld A,(Hl) ;;
Inc Hl ;;
Ld H,(Hl) ;;
Ld L,A ;; Hl=DPH
Pop De ;; De=Read/Write
Push Hl ;; SAVE DPH-ADDRESS
Add Hl,De ;; Hl=Read/Write IN DPH
Ld A,(Hl) ;;
Inc Hl ;;
Ld H,(Hl) ;;
Ld L,A ;; Hl=Read/Write-VECTOR
Pop De ;; DE=DPH
Dec De ;;
Dec De ;;
Ld A,(De) ;;
Ld (@RDrv),A ;; A=CONTROLLER RELATIVE DRIVE#
Inc De ;; BACK TO DPH
Inc De ;;
Jp (Hl) ;; DO THE ROUTINE IN EXTMEM.Z80
;------------------------------------------------------------;
; MultIO -- Set multiple sector count. ;
; ;
; At entry: A = Sector count. ;
; At exit: (@Cnt) = Multiple sector count. ;
;------------------------------------------------------------;
MultIO: Ld (@Cnt),A ;; Save the counter.
Ret ;;
;------------------------------------------------------------;
; Flush -- Flush all disk buffers. ;
;------------------------------------------------------------;
Flush: Ld C,2 ;;
Call ?UserF ;;
Xor A ;; Return no error.
Ret ;;
Page
;------------------------------------------------------------;
; Variables ;
;------------------------------------------------------------;
Cseg ; MUST BE IN Bank1
@ADrv: Db 0 ; SELECTED DISK DRIVE #
@RDrv: Db 0 ; CONTROLLER RELATIVE DISK DRIVE#
@Trk: Dw 0 ; TRACK #
@Sect: Dw 0 ; SECTOR #
@Dma: Dw 0 ; Dma ADDRESS
@Cnt: Db 0 ; RECORD COUNT FOR MULTISECTOR I/O
@DBnk: Db 0 ; Bank FOR Dma OPERATIONS
@CBnk: Db 0 ; Bank FOR PROCESSOR OPERATIONS
BnkMsk: Db Bank0 ; MASK FOR PROC-/Dma-OPERATIONS.
MuxByte: Db 0 ;
DmaFlg: Db 0 ; Dma busy flag
BnkFlg: Db 0 ; FLAG FOR ?XMov
DstBnk: Db 0 ; DEST-Bank FOR ?XMove-?Move
SrcBnk: Db 0 ; SOURCE-Bank FOR ?XMove-?Move
BnkTbl: Db DmBk00 ; Bank0 --> Bank0
Db DmBk10 ; Bank1 --> Bank0
Db DmBk01 ; Bank0 --> Bank1
Db DmBk11 ; Bank1 --> Bank1
DmaTbl: Db 23,Dma ; 23 Bytes to Dma
Db DmDisa ; DISABLE Dma
Db DmRset
Db DmRset
Db DmRset
Db DmRset
Db DmRset
Db DmRset
Db 01111101B ; CR1A: BLOCKLENGTH LOW o. HI FOLLOWS,
; PORT A START ADDRESS LOW o. HI
; FOLLOWS A->B, TRANSFER.
SrcAdr: Dw 0 ; SORCE-ADDRESS (PORT A)
Length: Dw 0 ; BLOCKLENGTH - 1.
Db 00010100B ; CR1B: PORT ADDR. Inc. PORT A-MEMORY.
Db 00010000B ; CR1B: PORT ADDR. Inc. PORT B-MEMORY
Mode: Db 0 ; CR2B: BURST/BYTE-Mode
DstAdr: Dw 0 ; DEST-ADDRESS (PORT B)
Db 10000010B ; CR2A: STOP END-OF-BLOCK
Db 11001111B ; CR2D: LOAD STARTADRESSES FOR BOTH
; PORTS And ZERO THE COUNTER.
Db 10001011B ; CR2D: ZERO STATUS-BITS
Db 10110011B ; CR2D: FORCE READY.
Db DmEnab ; ENABLE Dma
Db 10111111B ; CR2D: SET NEXT READ STATUS.
Db 0 ; TABLE END.
Dseg ;; Bank0
XoffList: Db -1,-1,-1,-1,-1,-1,-1,-1
Db -1,-1,-1,-1,-1,-1,-1,-1
End
«eof»