Title CP/M 2.2 Bios Rsx (31_Aug_84) ; ; Morrow Designs, Inc. ; San Leandro Ca. ; .z80 cseg Include HD22DEF.MAC ; This RSX will provide CP/M 2.2 compatible BIOS support for CP/M ; 3.x. It performs logical sector blocking and deblocking needed for some ; programs. All actual I/O is done by CP/M 3.0 BIOS. ; ; The original version of this program was written by Mike Griswold ; of Fort Worth Texas. It was published in the July 1984 issue of Doctor ; Dobb's Journal. ; ; The version here has been converted to z80 nmenonics and modified ; to run on an Md-Hd system with dynamic sector reallocation. Specifically, ; the modifications are: ; ; 1) Several labels have been added and some of the lables have been ; changed to make things more understandable. ; ; 2) The local cold boot routines have been moved into the sector ; buffer to save Tpa space. ; ; 3) The Local SelDsk function has been modified so that: ; A) It can now read the Dph (the Dph is in the system bank). ; B) Disk Capacity is truncated to 8 meg. ; ; 4) The Sector Blocking/DeBlocking routine has been heavily modified. ; A) Suppression of PreReads on Unallocated writes has been ; removed so that dynamic sector reallocation will work. ; B) Error Returns have been added after the calls to host ; reads and writes (otherwise these errors go undetected). ; ; 5) The Variable Area at the end of the code section has been edited. ; the variables dealing with unallocated sector identification have ; been deleted and the remaining variables reorganized. ; page 60 ;---------------------------------------------------------------------- ; Equates (28_Aug_84) ;-------------------- ; ;Bdos Function Numbers Bdos_Exec_Bios equ 50 ;Direct Bios Call Function Bdos_PString equ 9 ;Print String Function ;Direct Bios Function Call Numbers Bios_Fun_SelDsk equ 9 ;Select Disk Bios_Fun_SetTrk equ 10 ;Set the Track Number Bios_Fun_SetSec equ 11 ;Set the Sector Number Bios_Fun_SetDMA equ 12 ;Set the Dma Address Bios_Fun_Read equ 13 ;Read Bios_Fun_Write equ 14 ;Write Bios_Fun_SecTrn equ 16 ;Sector Translation Bios_Fun_SetBnk equ 28 ;Set the Bank ;Morrow Extended Bios Function Numbers EB_Read_System equ 0 ;Read from System Memory EB_Write_System equ 1 ;Write to System Memory EB_Get_RamDatY equ 2 ;Read RamDatY from System Memory EB_Exec_System equ 14 ;Execute in System Memory ;Rom Addresses Rom_RdHst equ 9 ;Read to Host Rom_WrtHst equ 0Ch ;Write to Host Rom_RdLSec equ 20h ;Read a Logical Sector Rom_WrLSec equ 23h ;Write a Logical Sector ;Offsets Offset_SecTrn equ 30h ;SecTrn from Start of Bios Jump Table Offset_SelDsk equ 1Bh ;SelDsk from Start of Bios Jump Table ;Other Equates No equ 0 ;Remove/Non_Banked is False Yes equ 0FFh ;Remove/Non_Banked is True Cr equ 0Dh ;Carriage Return Lf equ 0Ah ;Line Feed Dph_Length equ 25 ;Length of the Dph page ;---------------------------------------------------------------------- ; Rsx Prefix Section (20_Aug_84) ;------------------------------- ; Serial: db 1,2,3,4,5,6 ;Space for the Serial Number Entry: db 0C3h ;Jump to Start of Code dw Local_Cold_Boot ;Vector to Start of Code Next: db 0C3h ;Jump to Start of Next Rsx dw 0 ;Vector to Next Rsx Prev: dw 0 ;Address of Previous Rsx or Location 5 Remove: db Yes ;No to keep Rsx active after Warm Boot NonBank: db No ;No for using both banked & non-banked systems Name: db 'BIOS 2.2' ;Name of this Rsx Loader: db 0 ;Loader Flag dw 0 ;Reserved page ;---------------------------------------------------------------------- ; Cp/m 2.2 Bios Jump Table ;------------------------- ; ; Align jump table on a page boundary ds 229,0 cbt: jp Local_WBoot wbt: jp Local_WBoot jp xconst jp xconin jp xconout jp xlist jp xauxout jp xauxin jp Local_Home jp Local_SelDsk jp Local_SetTrk jp Local_SetSec jp Local_SetDma jp Local_Read jp Local_Write jp xlistst jp Local_SecTrn ;---------------------------------------------------------------------- ; Cp/m 3.0 Bios Jump Table ;------------------------- ; 1) Non_Disk system I/O is copied here to allow easy access to ; the routines. ; xwboot: jp 0 xconst: jp 0 xconin: jp 0 xconout:jp 0 xlist: jp 0 xauxout:jp 0 xauxin: jp 0 jp 0 jp 0 jp 0 jp 0 jp 0 jp 0 jp 0 xlistst:jp 0 page ;====================================================================== ; Cold Boot (21_Aug_84) ;====================== ; Local_Cold_Boot: push af push hl push de push bc ;(save registers) ld hl,next ld (entry+1),hl ;Skip this rsx from now on ld hl,(1) ld (Save_Warm_Boot),hl ;Save the Old Bios Jump Table Address ld de,xwboot ld bc,15*3 ldir ;Copy 1st 15 Entries of Bios Jump Table ld hl,wbt ld (1),hl ;ReDirect Bios Pointer to this Rsx call Get_RamDatY ;Get the System's RamDatY res @HstAct,(iy+DFlag) ;Host_Active:= No res @HstWrt,(iy+DFlag) ;Host_Write:= No call Put_RamDatY ;Restore System's RamDatY ld c,Bdos_PString ;C:= Print String Function Number ld de,Sign_On_Message ;DE:= Pointer to Sign On Message call Next ;Print the Sign-On Message pop bc pop de pop hl pop af ;(Restore Registers) jp next page ;====================================================================== ; Warm Boot (20_Aug_84) ;====================== ; Local_WBoot: ld hl,(Save_Warm_Boot) ld (1),hl ;Restore the original Bios Address jp 0 ;====================================================================== ; Home Disk (28_Aug_84) ;====================== ; Local_Home: call Get_RamDatY ;Read RamDatY into Local Memory bit @HstWrt,(iy+DFlag) ;If (there is a Pending Write) jr nz,LhSk1 res @HstAct,(iy+DFlag) ;Buffer:= Not Active LhSk1: call Put_RamDatY ;Restore RamDatY to System Memory ret page ;====================================================================== ; Select Disk (27_Aug_84) ;======================== ; 1) Create a fake DPH for programs that might use it ; 2) Truncate Disk Capacity to 8 meg. ; Local_SelDsk: ld a,c ld (Local_SekDsk),a ;Local_SekDsk:= Current Disk Number ld e,0 ld hl,(Save_Warm_Boot) ld l,Offset_SelDsk ;HL:= SelDsk Entry in Jump Tbl ld a,EB_Exec_System ;A:= Execute in System Bank call Extended_Bios ;Select the Disk ld a,h or l ;If (Drive is InValid) ret z ; Return ld a,EB_Read_System ;A:= Read from system memory ld bc,Dph_Length ;BC:= Transfer Length of 25 bytes ld de,RamDatY ;DE:= Pointer to Local Buffer call Extended_Bios ;Read the Dph into the Local Buffer ex de,hl ld e,(hl) inc hl ld d,(hl) ;DE:= Pointer to Sector Translation Table ld (Dph),de ;Save pointer to Sector Translation Table ld de,11 add hl,de ;HL:= Pointer to DPB Pointer in DPH ld e,(hl) inc hl ld d,(hl) ;DE:= Pointer to DPB ld (Dpb),de ;Save pointer to Dpb in Fake Dph ex de,hl ld e,(hl) inc hl ld d,(hl) ld (Local_SecTrk),de ;Save Number of Logical Sectors/Track ld de,4 add hl,de push hl ld e,(hl) inc hl ld d,(hl) ex de,hl ;HL:= Dsm ld de,7FAh ;DE:= 8meg capacity (assume 4k blocks) or a sbc hl,de pop hl jr c,SdSk1 ;If (Storage of Disk is Gt 8meg) ld (hl),e inc hl ld (hl),d ; Jam it to 8meg dec hl SdSk1: ld de,11 ;DE:= Offset to PHM in Dpb add hl,de ld a,(hl) ld (Save_Phm),a ;Save Logical Sectors/Physical Sector ld hl,dph ;HL:= Local Dph (the one just built) ret page ;====================================================================== ; Set the Current Track ;====================== ; Local_SetTrk: ld (Local_SekTrk),bc ;Update the Track Number ret ;====================================================================== ; Set the Current Dma Address ;============================ ; Local_SetDma: ld (Local_DmaAdr),bc ;Update the Dma Address ret ;====================================================================== ; Set sector number ;================== ; Local_SetSec: ld (Local_SekSec),bc ;Update the Sector Number ret ;====================================================================== ; Read a Sector (30_Aug_84) ;========================== ; Local_Read: push iy push ix ld c,0 ;C:= Forced to Write Allocated call Save_and_Setup ld hl,Rom_RdLSec ;HL:= Pointer to read a logical sector jp RwMove ;Move the Data ;====================================================================== ; Write a Sector (30_Aug_83) ;=========================== ; Local_Write: push iy push ix call Save_and_Setup ld hl,Rom_WrLSec ;HL:= Pointer to write a logical sector jp RwMove ;Move the Data page ;---------------------------------------------------------------------- ; Common Code for Read/Write a logical sector (31_Aug_84) ;-------------------------------------------------------- ; RwMove: ld a,EB_Exec_System call Extended_Bios ;Read/Write a Logical Sector or a ;If (There were No Errors) jp nz,RmSk2 ld a,c ; A:= 0 for read, A:= 2 for write or a ; If (this is a write) jr z,RmSk1 dec a ; A:= 1 (Write Sys Mem) RmSk1: ld bc,128 ; BC:= Length of transfer call Extended_Bios ; Move the Sector call Get_RamDatY ; Read RamDatY back into Local Memory ld a,(RamDatY+WrType) ; If (this is a directory write) cp WrDir ld a,0 ; (A:=no error status) jp nz,RmSk2 res @HstWrt,(iy+DFlag) ; clear write flag set @BufOK,(iy+OpFlag) ; BufOK:= buffer data OK call Put_RamDatY ; ReStore RamDatY ld a,EB_Exec_System ld hl,Rom_WrtHst call Extended_Bios ; write buffer RmSk2: pop ix pop iy or a ;If (there were no errors) ret z ; Return ld hl,4 ;return error code and ld (hl),h ;set to drive a. ld l,h ret ;Return page ;---------------------------------------------------------------------- ; Save Parameters and Setup RamDatY (28_Aug_84) ;---------------------------------------------- ; 1) This routine moves the parameters saved in the Set_Sector, ; Set_Track, Set_Dma_Address and Select_Disk Routines in the ; system copy of RamDatY. ; 2) If this is a write operation then the B register is non-zero, in ; which case the C register contains the write type (saved in WrType). ; Save_and_Setup: push bc call Get_RamDatY ;Get RamDatY from System Memory pop bc ld (iy+WrType),c ; Save the Write Type ld a,(Local_SekDsk) ;Install the Drive Number ld (RamDatY+SekDsk),a ld (RamDatY+HstDsk),a ld hl,(Local_SekTrk) ;Install the Logical Track Number ld (RamDatY+SekTrk),hl ld hl,(Local_SekSec) ;Install the Logical Sector Number ld (RamDatY+SekSec),hl ld hl,(Local_DmaAdr) ;If (Dma Address has been defined) ld a,h or l jr nz,SsSk2 ld hl,80h SsSk2: ld (RamDatY+DmaAdr),hl ; Install the Dma Address ld hl,(Local_SecTrk) ld (RamDatY+SecTrk),hl ;Install Number of Logical Sectors/Track call Put_RamDatY ;Put RamDatY back into System Memory ret page ;====================================================================== ; Translate sectors (31_Aug_84) ;============================== ; 1) This routine preforms logical to physical sector address ; translation. ; 2) Register Usage: ; A -> General Purpose ; BC -> Enter equal to the Logical Sector Number ; DE -> Pointer to Sector Translation Table (0 if No Table) ; HL -> Exit equal to the Physical Sector Number. ; Local_SecTrn: ld l,c ld h,b ;HL:= BC (Logical Sector Number) ld a,e ;If (There is no translation Table) or d jr z,LsDone ; Return (HL:= Physical Sector Number) ld a,(Save_Phm) ;A:= Logical Sectors per Physical Sector or a ;If (Sector Size gt 128) jr z,LsSk1 ld l,0 ; Remainder:= 0 LsLp1: srl b ; Repeat rr c ; Divide by 2 rr l srl a jr nz,LsLp± » Untiì (Sectoò Counteò eñ 0) LsSk1: ld a,l ld (Save_Remainder),a ld hl,(Save_Warm_Boot) ld l,Offset_SecTrn ;HL:= SecTrn Addr in Bios Jump Table ld a,EB_Exec_System ;A:= Execute in System Memory call Extended_Bios ;Translate the Sector ld a,(Save_Phm) ;A:= Logical Sectors per Physical Sector or a ;If (Sector Size eq 128) ret z ; Return dec hl ld d,a ;D:= Logical Sector Count ld a,(Save_Remainder) ld e,a ;E:= Remainder LsLp2: sla e ;Repeat rl l rl h ; Multiply by 2 srl d ; Dec Sector Count jr nz,LsLp2 ;Until (Sector Count eq 0) LsDone: inc hl ;Increment the Sector Base from 0 to 1 ret ;Return page ;---------------------------------------------------------------------- ; Call the Bios Extended Bios (Cold Boot) Entry Point (1_Aug_84) ;--------------------------------------------------------------- ; 1) All registers must have been set up before entering this routine. ; 2) Notice that NONE of the Registers are effected by this routine. ; Extended_Bios: push hl ;Save the HL Register Pair ld hl,(Save_Warm_Boot) ;HL:= Warm Boot Address ld l,0 ;HL:= Cold Boot Address ex (sp),hl ;HL:= Entry Value; Stack:= Cold Boot Entry ret ;Goto The Cold Boot entry ;---------------------------------------------------------------------- ; Move the System RamDatY Area into Local Memory (28_Aug_84) ;----------------------------------------------------------- ; 1) This routine calls the extended bios functions entry point, ; and then saves the registers. ; 2) Enter with Accm equal to the extended bios function desired ; Get_RamDatY: ld (Save_IY),iy ld a,EB_Get_RamDatY ;A:= Get RamDatY Function Number ld de,RamDatY ;DE:= Pointer to Local RamDatY Buffer call Extended_Bios ;Move System Memory into local buffer ld (Save_BC),bc ;Save the returned registers ld (Save_DE),de ld (Save_HL),hl ld iy,RamDatY ;IY:= Pointer to RamDatY Area ret ;Return ;---------------------------------------------------------------------- ; Move the Local RamDatY Area Back into System Memory (30_Jul_84) ;---------------------------------------------------------------- ; Put_RamDatY: ld a,EB_Write_System ;Function_1:= Write to system memory ld bc,(Save_BC) ld de,(Save_DE) ld hl,(Save_HL) ;Restore the Returned Registers ex de,hl ;HL:= Swap Source and Destination call Extended_Bios ;Write Buffer back into system memory ld iy,(Save_IY) ret page ;---------------------------------------------------------------------- ; Direct Bios Call Parameter Block (30_Aug_84) ;--------------------------------------------- ; ;For Extended Bios Calls Save_BC: dw 0 ;Save location for the BC register pair Save_DE: dw 0 ; " " " " DE " " Save_HL: dw 0 ; " " " " HL " " Save_IY: dw 0 ; " " " " IY " " Save_SP: dw 0 ; " " " " SP " " Save_Phm: db 0 ;Logical Sectors per Physical Sector Save_Remainder: db 0 ;Remainder used in Local_SecTrn Save_Warm_Boot: dw 0 ;address of old BIOS ;---------------------------------------------------------------------- ; Fake Dph ;--------- ; 1) This fake DPH holds the addresses of the actual DPB. ; The CP/M 3.0 DPH is *not* understood by CP/M 2.2 Programs. ; Dph: dw 0 ;Xlt dw 0 ;Bdos Scratch Area dw 0 ; " " " dw 0 ; " " " dw 0 ;DirBuf Dpb: dw 0 ;Dpb Pointer dw 0 ;Csv dw 0 ;Alv ;---------------------------------------------------------------------- ; Variable Storage Area (27_Aug_84) ;---------------------------------- ; Local_SekDsk: db 0 Local_SekTrk: dw 0 ;logical track number Local_SekSec: dw 0 ;logical sector number Local_DmaAdr: dw 0 ;last dma address Local_SecTrk: dw 0 ;Number of Logical Sectors/Track page ;---------------------------------------------------------------------- ; General Disk Operations Data Area (13_Oct_83) ;---------------------------------------------- ; RamDatY: db 0 ;(SEKDSK) BDOS disk number dw 0 ;(SEKTRK) BDOS track number ; dw 0 ;(SEKSEC) BDOS sector number ; dw 0 ;(SEKHST) Actual sector number on the disk ; db 0 ;(UNACNT) Unallocated record count db 0 ;(UNADSK) Unallocated disk number dw 0 ;(UNATRK) Unallocated track number ; dw 0 ;(UNASEC) Unallocated sector number ; db 0 ;(UNAMAX) Sectors per Unallocated block dw 0 ;(SECTRK) Logical Sectors per track ; db 0 ;(PHYSPT) Physical sectors per track db 0 ;(WRTYPE) Write type db 0 ;(CFLAG) Flag Byte db 0 ;(DFLAG) Flag Byte db 0 ;(TRSEC) Offset to logical sector within physical sector dw 0 ;(VMSGP) Pointer to virtual drive message ; dw 0 ;(VDRVP) Pointer to virtual drive in message ; db 0 ;(CDSK) Current drive db 0 ;(VDSK) Current virtual drive dw 0 ;(DMAADR) BDOS DMA address ; dw 0 ;(CONOUT) Pointer to Current console output routine ; dw 0 ;(CONIN) Pointer to Current console input routine ; dw 0 ;(CONSTS) Pointer to Current console status routine db 0 ;(CPYBNK) Copy of bank strobe (printer restore false=1) page ;---------------------------------------------------------------------- ; Default Application Interface area (19_Oct_83) ;----------------------------------------------- ; APIF: db 0 ;(HSTDRV) BDOS Drive Number (1st floppy) dw 0 ;(HSTTRK) Desired Cylinder (lo) ; Desired Cylinder (hi) dw 0 ;(HSTSEC) Desired Sector (lo) ; Desired Sector (hi) db 0 ;(SECCNT) Number of sectors to transfer db 0 ;(RETRY) Retry Count dw 0 ;(HSTBUF) Buffer Address (lo) ; Buffer Address (hi) db 0 ;(ERFLAG) Error Code db 0 ;(OPFLAG) Options Flag dw 0 ;(PHYTRK) Physical track number (lo) ; Physical track number (hi) db 0 ;(PHYHD) Desired Head db 0 ;(PHYSEC) Physical sector number db 0 ;(PHYDRV) Physical Drive Number dw 0 ;(IOADD) Execution Address (lo) ; Execution Address (hi) ;---------------------------------------------------------------------- ; Text: Signon Message (27_Aug_84) ;--------------------------------- ; Sign_On_Message: db Cr,Lf,'Cpm 2.2 Bios is Active',Cr,Lf,'$' end