Title Physical Disk I/O Module for SWP CoPower_88 (18_May_84) ; ; Morrow Design, Inc. ; San Leandro, Ca. ; Copyright 1984 ; Modified for an MD-HD ; Russell Smith ; .z80 cseg ;---------------------------------------------------------------------- ; Public Declarations (16_May_84) ;-------------------------------- ; entry diskdvr,init,restore,finit,fstore ext Hd_DBP ;---------------------------------------------------------------------- ; Local Equates (18_May_84) ;-------------------------- ; ; Bios Addresses ;--------------- ; Wbadd equ 1 ;Location of the Bios Warm Boot Address Read_Sector equ 27h ;Read a Sector offset from start of jump table Write_Sector equ 2Ah ;Write a Sector offset from start of jump table SetDma equ 24h ;Set Dma offset from start of jump table ; Extended Bios Function Numbers ;------------------------------- ; EB_Read_Sys equ 0 ;Read from the system bank to the tpa bank EB_Write_Sys equ 1 ;Write to the system bank from the tpa bank EB_Get_RamY equ 2 ;Read System RamDatY and APIF EB_Get_Mtab equ 3 ;Read System Mtabs EB_format equ 9 ;Format a track EB_Execute equ 14 ;Execute in the System Bank EB_Verify equ 16 ;Verify track ; Bdos Calls ;----------- ; Display_String equ 9 ;Dislpay String Open_File equ 0fh ;Open file Close_File equ 10h ;Close file Bdos_Read equ 21h ;Read Random Bdos_Write equ 22h ;Write Random Bdos_Set_Dma equ 1ah ;Set Dma Disk_Reset equ 13 ;Reset disk system Bdos_Free_Space equ 46 ;Get free space Bdos_Error_Mode equ 45 ;Set error mode Bdos equ 5 ; Disk driver operation code definitions ;--------------------------------------- ; getsec equ 1 ;read sector putsec equ 2 ;write sector putfmt equ 4 ;format track ; Data structure for disk i/o control block ;------------------------------------------ ; dskop equ 0 ;disk operation code dskdrv equ 1 ;drive# (with side# in bit 7) dsktrk equ 2 ;track# dsksec equ 3 ;sector# dskptr equ 5 ;read/write pointer dskaux equ 7 ;auxilliary parameters (2 bytes) dsksts equ 9 ;operation completion status ; Lengths and Offsets ;-------------------- ; GOLeng equ 36 ;Length of the RamDatY (General Operation data) AILeng equ 18 ;Length of the RamDatX area MToff equ 36h ;Offset to 1st MTab from start of RamDatY Mtab_Length equ 16 ;Length of an Mtab DBP_Sec_Dsk equ 8 DBP_Sec_Trk equ 4 DBP_Fats equ 5 DBP_Sec_Fat equ 6 DBP_Res_Sec equ 3 DBP_Dirs equ 6 ; Offsets for the Apif area ;-------------------------- ; HstDsk equ 0 ;Host Disk (Logical Drive Number) HstTrk equ 1 ;Host Track HstSec equ 3 ;Host Sector (Physical Sector) SecCnt equ 5 ;Sector Count Retry equ 6 ;Retry Count Hstbuf equ 7 ;Host Buffer Address ErFlag equ 9 ;Error Flag OpFlag equ 10 ;Options Flag PhyTrk equ 11 ;Physical Track Number PhyHd equ 13 ;Physical Head Number IOadd equ 16 ;Execution Address ; Offsets used in MD-3s but not in an MD-11 ;StAdd equ 14 ;CmdCnt equ 21 ;CmdBuf equ 22 page ;---------------------------------------------------------------------- ; Main Line of the Disk Driver Routine (16_May_84) ;------------------------------------------------- ; diskdvr: ld a,(ix+dskop) cp 1 jp z,read ;jump if disk read operation cp 2 jp z,write ;jump if disk write operation cp 4 jp z,format ;jump if track format operation ld (ix+dsksts),255 ;else set all error bits and return ret page ;====================================================================== ; Copy the Local Disk Control Block into RamDatY (17_May_84) ;=========================================================== ; 1) This routine First turns the floppy disk drives into IBM format ; and then reads and saves the address of the apif area. ; Init: ld de,Temp_Buffer ;(on return this is moved to the HL reg) ld a,EB_Get_Mtab ;A:= Read Mtabs Function call Get_Buffer ;Read System Mtabs ld b,4 ;B:= Counter (number of floppy drives) ld de,Mtab_Length ;DE:= Length of an Mtab FTlp1: add hl,de ;Repeat HL:= Start of Next Floppy Mtab ld a,(hl) and 10000011b ; Leave @Vd and $HdMsk or 01000100b ; Add @DblMed ld (hl),a ; Install DskDef0 inc hl ld a,(hl) and 11000000b ; Leave @DrvCal and @DrvRdy or 00100010b ; Add @DrvDen and 512 byte sectors ld (hl),a ; Install DskDef1 dec hl djnz FTlp1 ;Until (all four floppies updated) call Put_Buffer ;Install the Updated system Mtabs ld de,Temp_Buffer ;DE:= Temp Buffer (destination) ld a,EB_Get_RamY ;A:= Read RamDatY and APIF Function call Get_Buffer ;Read System RamDatY and Apif ex de,hl ;HL:= Address of RamDatY in System Bank ld (Ramdaty_Address),hl ld de,GOLeng ;DE:= Length of RamDatY add hl,de ;HL:= Address of APIF in System Bank ld (APIF_Address),hl ;(save the APIF address) ld de,Temp_Buffer ;get free space on disk ld c,Bdos_Set_Dma call Bdos ld e,0 ld c,Bdos_Free_Space call Bdos ld hl,Temp_Buffer ;get free space in regs C D & E ld e,(hl) inc hl ld d,(hl) inc hl ld c,(hl) ld b,2 ;divide C D & E by 4 to convert shft: srl c ;to 512 byte sectors rr d rr e djnz shft ld c,a ;check for more than 32 Mbytes or a jr z,Size_Ok ;jump if not more ld de,0ffffh ;set to 32 Mbytes Size_Ok: ld hl,(Hd_DBP) ;calc pointer to hard disk DBP ld bc,Hd_DBP add hl,bc push hl ;save DBP pointer call Set_Size ;Set MSDOS drive size to free space pop hl ;restore DBP pointer call Calc_Dir_Size ;Calculate Start and End of Dir ld de,FCB ;pointer to FCB ld c,Open_File call Bdos ;Open MsDos file or a jr nz,Bad_File ld bc,1 ;BC:= Length of transfer ld de,(APIF_Address) ld hl,OpFlag add hl,de ex de,hl ;DE:= Destination ld hl,Local_Apif+OpFlag ;HL:=Source ld a,11000010b ;(set @RomIO, @SerUR and @SerD) ld (hl),a ld a,EB_Write_Sys ;A:= Write System Memory Function call Do_Cold ;Set OpFlag byte to system Apif ld e,0ffh ;set error mode to return mode ld c,Bdos_Error_Mode call Bdos ret Bad_File: ld de,No_File ld c,Display_String call Bdos call Restore jp 0 page ;====================================================================== ; Set hard disk size in DBP (18_Jul_84) ;========================================= Set_Size: ld bc,DBP_Sec_Dsk ;get pointer to sectors/disk add hl,bc ld (hl),e ;set sectors/disk in DBP inc hl ld (hl),d ld bc,DBP_Sec_Trk ;get pointer to sectors/track add hl,bc ld (hl),e ;set sectors/track in DBP inc hl ld (hl),d ret ;====================================================================== ; Set hard disk directory size for Flush routine (18_Jul_84) ;=========================================================== Calc_Dir_Size: push hl ;save DBP pointer ld de,DBP_Fats ;get pointer to number of Fats add hl,de ld b,(hl) ;B = number of Fats ld de,DBP_Sec_Fat ;get pointer to sectors/fat add hl,de ld e,(hl) ;DE = sectors/fat inc hl ld d,(hl) ld hl,0 ;calc. number of sectors in all fats mul_fat: add hl,de djnz mul_fat ex de,hl ;DE = sectors in all fats pop hl ;restore DBP pointer push hl ;save DBP pointer ld bc,DBP_Res_Sec ;get pointer to reserved sectors add hl,bc ld c,(hl) ;BC = reserved sectors inc hl ld b,(hl) ex de,hl ;add fat sectors and reserved sectors add hl,bc sla l ;multiply by 4 to get first record of dir rl h sla l rl h ld (Start_Dir),hl ;save first record of dir ex de,hl ;DE = first record of dir pop hl ;restore DBP pointer ld bc,DBP_Dirs ;get pointer to number of dir entries add hl,bc ld c,(hl) ;BC = number of dir entries inc hl ld b,(hl) srl b ;divide by 4 to get number of rr c ;dir records srl b rr c ex de,hl add hl,bc ;HL = last record of dir + 1 ld (End_Dir),hl ;save last record ret ;====================================================================== ; Restore MTAB's to Morrow Format (19_May_84) ;======================================= ; Restore: ld c,Close_file ;Close MsDos File ld de,Fcb call Bdos ld de,Temp_Buffer ;(on return this is moved to the HL reg) ld a,EB_Get_Mtab ;A:= Read Mtabs Function call Get_Buffer ;Read System Mtabs ld b,4 ;B:= Counter (number of floppy drives) ld de,Mtab_Length ;DE:= Length of an Mtab RTlp1: add hl,de ;Repeat HL:= Start of Next Floppy Mtab ld a,(hl) and 10000011b ; Leave @Vd and $HdMsk ld (hl),a ; Install DskDef0 inc hl ld a,(hl) and 11000000b ; Leave @DrvCal and @DrvRdy or 00100011b ; Add @DrvDen and 512 byte sectors ld (hl),a ; Install DskDef1 dec hl djnz RTlp1 ;Until (all four floppies updated) jp Put_Buffer ;Install the Updated system Mtabs ;====================================================================== ; Sector Read Function (18_May_84) ;================================= ; read: ld a,(ix+dskdrv) ;Get drive and 3 cp 0 ;See if drive A jp z,Read_Hd ;Jump if drive A call Setup_Apif ;store parameters for rom call ld hl,(1) ;HL:= Address Warm Boot ld l,0 ;HL:= Address of Cold Boot ld de,Read_Sector ;DE:= Offset to Read from Cold Boot add hl,de ;HL:= Address of bios read routine ld a,EB_Execute ;A:= Execute in system bank function call Do_Cold ;read sector via rdHst entry point ld e,(ix+dskptr) ;transfer sector to buffer ld d,(ix+dskptr+1) ld hl,0f000h ld bc,200h ldir flret: call Get_Error ;get error code ld a,0 ;set system apif to drive A ld (Local_Apif+HstDsk),a ld bc,1 ;BC:= Length of transfer ld de,(APIF_Address) ;DE:= Destination ld hl,Local_Apif ;HL:= Source ld a,EB_Write_Sys ;A:= Write System Memory Function call Do_Cold ;Install the updated Apif ld bc,1 ;BC:= Length of transfer ld de,(Ramdaty_Address) ;DE:= Destination ld hl,Local_Apif ;HL:= Source ld a,EB_Write_Sys ;A:= Write System Memory Function jp Do_Cold ;====================================================================== ; Sector Write Function (18_May_84) ;================================== ; write: ld a,(ix+dskdrv) ;Get drive and 3 cp 0 ;See if drive A jr z,Write_Hd ;Jump if drive A call Setup_Apif ld l,(ix+dskptr) ld h,(ix+dskptr+1) ld de,0f000h ld bc,200h ldir ld hl,(1) ;HL:= Address Warm Boot ld l,0 ;HL:= Address of Cold Boot ld de,Write_Sector ;DE:= Offset to Write from Cold Boot add hl,de ;HL:= Address of bios write routine ld a,EB_Execute ;A:= Execute in system bank function call Do_Cold ;write sector via wrtHst rom entry jp flret page ;====================================================================== ; Hard Disk Sector Write Function (18_May_84) ;============================================ ; Write_Hd: call Hd_Setup ;Setup for Hard Disk wloop: push hl ; save record push de ; save buffer pointer push bc ld (Record),hl ; put record in FCB ld c,Bdos_Set_Dma ; Set_Dma function code call Bdos ; call system ld de,FCB ; pointer to FCB lä c,Bdos_Write ; Write Random code call Bdos ; call system or a ;check for error call nz,Hd_Err ;call if error or a ;check if fatal error jr nz,eret ;return if fatal error pop bc pop de ; buffer pointer ld hl,80h ; adjust buffer pointer add hl,de ex de,hl pop hl ; record inc hl ; increment record djnz wloop ; loop until done ld a,0 ld (ix+dsksts),a ;set error code call Flush ;Flush file if needed ret eret: pop bc pop de pop hl ret ;====================================================================== ; Hard Disk Sector Read Function (18_May_84) ;=========================================== ; Read_Hd: call Hd_Setup ;Setup for Hard Disk rloop: push hl ; save record push de ; save buffer pointer push bc ld (Record),hl ; put record in FCB ld c,Bdos_Set_Dma ; Set_Dma function code call Bdos ; call system ld de,FCB ; pointer to FCB lä c,Bdos_Read ; Write Random code call Bdos ; call system or a ;check for error call nz,Hd_Err ;call if error or a ;check if fatal error jr nz,eret ;return if fatal error pop bc pop de ; buffer pointer ld hl,80h ; adjust buffer pointer add hl,de ex de,hl pop hl ; record inc hl ; increment record djnz rloop ; loop until done ld a,0 ld (ix+dsksts),a ;set error code ret ;====================================================================== ; Get error code from Apif (18_Jul_84) ;========================================= Get_Error: ld bc,1 ;BC:= Length of transfer ld de,(APIF_Address) ld hl,ErFlag add hl,de ;HL:=Source ld de,Local_Apif+ErFlag ;DE:= Destination ld a,EB_Read_Sys ;A:= Read System Memory Function call Do_Cold ;Get error byte from system Apif ld a,(Local_Apif+ErFlag) ;pass back error flag ld (ix+dsksts),a ret ;====================================================================== ; Flush MsDos File (18_May_84) ;========================================= Flush: ld hl,(Cur_Rec) ;get current record push hl ;save current record ld de,(End_Dir) ;check if (current record < end of dir) xor a ;clear carry sbc hl,de pop hl ;restore currnet record ret nc ;return if current record is not in dir ld de,(Start_Dir) ;check if (start of dir < current record) xor a ;clear carry sbc hl,de ret c ;return if current record is not in dir ld c,Close_File ;Bdos Close File code ld de,FCB call Bdos or a jp nz,Hd_Err ld c,Open_File ;Bdos Open File code ld de,FCB call Bdos or a jp nz,Hd_Err ret ;====================================================================== ; Hard disk error routine (18_Jul_84) ;==================================== Hd_Err: cp 0ffh ;see if hardware error jp z,Get_Error ;jump if hardware cp 2 ;check for fatal errors: 2,3, or 5 jr z,Gen_Err ;jump if fatal cp 3 jr z,Gen_Err cp 5 jr z,Gen_Err ld a,0 ;no fatal error ld (ix+dsksts),a ret Gen_Err: ld a,0ffh ;fatal error ld (ix+dsksts),a ret ;====================================================================== ; Format/Verify track function (6_Jul_84) ;========================================= ; Format: ld a,(ix+dskdrv) and 00000011b or a jr nz,not_hard ld (ix+dsksts),0ffh ret not_hard: ld (Local_Apif+HstDsk),a ;set HstDsk in ramdatx xor a ;clear carry ld (Local_Apif+HstTrk+1),a ld a,(ix+dsktrk) biô 7,(ix+dskdrv) jr z,FaSkp1 ;jump if selecting side zero scf FaSkp1: rla ;else create 2x odd track number ld (Local_Apif+HstTrk),a ;set HstTrk in ramdatx ld b,11100010b ;(@RomIO, @NoVer, @SerUR and @SerD) or a ;see if track 0 jr nz,not_trk0 ;jump if not ld b,11110010b ;(@RomIO, @Recal, @NoVer, @SerUR and @SerD) not_trk0: ld hl,ftable ld (Local_Apif+HstSec),hl ;set HstSec in Apif ld a,10 ld (Local_Apif+Retry),a ;Retry_Count:= 10 ld a,0 ld (Local_Apif+ErFlag),a ;Error Flag:= 0 ld a,b ld (Local_Apif+OpFlag),a ;Setup OpFlag ld a,1 ld (Local_Apif+SecCnt),a ;Sector_Count:= 1 ld a,EB_format push ix ld ix,Local_Apif ld de,Mtab call Do_Cold pop ix ld a,d ld (ix+dsksts),a or a jr nz,fret ld a,EB_Verify call Do_Cold ld (ix+dsksts),d ld (ix+dskaux),e fret: ld a,0 ;drive A ld (Local_Apif+HstDsk),a ld bc,1 ;BC:= Length of transfer ld de,(APIF_Address) ;DE:= Destination ld hl,Local_Apif ;HL:= Source ld a,EB_Write_Sys ;A:= Write System Memory Function call Do_Cold ;Install the updated Apif ret page ;---------------------------------------------------------------------- ; Setup Apif Area (17_May_84) ;---------------------------- ; Setup_Apif: ld a,(ix+dskdrv) and 00000011b ld (Local_Apif+HstDsk),a ;set HstDsk in ramdatx xor a ;clear carry ld (Local_Apif+HstTrk+1),a ld a,(ix+dsktrk) biô 7,(ix+dskdrv) jr z,SaSkp1 ;jump if selecting side zero scf SaSkp1: rla ;else create 2x odd track number ld (Local_Apif+HstTrk),a ;set HstTrk in ramdatx ld a,(ix+dsksec) ld (Local_Apif+HstSec),a ;set HstSec in ramdatx ld a,10 ld (Local_Apif+Retry),a ;Retry_Count:= 10 ld bc,0f000h call Set_Dma ;Set buffer address ld a,0 ld (Local_Apif+ErFlag),a ;Error Flag:= 0 ld a,11000010b ;(set @RomIO, @SerUR and @SerD) ld (Local_Apif+OpFlag),a ;Setup OpFlag ld a,1 ld (Local_Apif+SecCnt),a ;Sector_Count:= 1 ld bc,AILeng ;BC:= Length of the Apif Area ld de,(APIF_Address) ;DE:= Destination ld hl,Local_Apif ;HL:= Source ld a,EB_Write_Sys ;A:= Write System Memory Function call Do_Cold ;Install the updated Apif ld bc,1 ;BC:= Length of transfer ld de,(Ramdaty_Address) ;DE:= Destination ld hl,Local_Apif ;HL:= Source ld a,EB_Write_Sys ;A:= Write System Memory Function call Do_Cold ;Set SekDsk byte to Ramdaty ret page ;====================================================================== ; Hard Disk Setup (18_May_84) ;============================ ; Hd_Setup: ld l,(ix+dsksec) ; get MSDOS relative sector ld h,(ix+dsksec+1) dec hl ;set to 0 base ; Multiply sector by 4 to convert to CP/M record sla l ; x2 rl h sla l ; x4 rl h ld (Cur_Rec),hl ;save record ld b,4 ; record count ld e,(ix+dskptr) ; get disk buffer pointer ld d,(ix+dskptr+1) ret page ;---------------------------------------------------------------------- ; Move system memory into a local buffer (4_Jan_84) ;-------------------------------------------------- ; 1) This routine calls the cold start bios entry point, and then saves ; the registers after swapping hl and de (source and destination). ; Get_Buffer: call Do_Cold ;Move System Memory into local buffer ld (save_BC),bc ;Save the returned registers ex de,hl ;HL:= Pointer to first xlt ld (save_DE),de ld (save_HL),hl ret ;Return ;---------------------------------------------------------------------- ; Restore a Buffer into System Memory (4_Jan_84) ;----------------------------------------------- ; 1) This is the inverse of GetBuf. ; 2) GetBuf MUST be called before entering this routine. ; Put_Buffer: ld a,1 ;Function_1:= Write to system memory ld bc,(Save_BC) ld de,(Save_DE) ld hl,(Save_HL) ;Restore the Returned Registers call Do_Cold ;Write the Mtabs back into system memory ret ;---------------------------------------------------------------------- ; Set the CP/M dma address (18_May_84) ;------------------------------------- ; 1) This routine calls the CP/M SetDma entry through the Cold ; Boot Entry. ; Set_Dma: ld hl,(1) ;HL:= Address Warm Boot ld l,0 ;HL:= Address of Cold Boot ld de,SetDma ;DE:= Offset to SetDma from Cold Boot add hl,de ;HL:= Address of bios write routine ld a,EB_Execute ;A:= Execute in system bank function call Do_Cold ;write sector via wrtHst rom entry ret ;---------------------------------------------------------------------- ; Call the Bios Cold Boot Entry Point (4_Jan_84) ;----------------------------------------------- ; 1) The Cold Boot Entry point to the bios (1st entry in the bios ; jump table) is located by looking at locations 1 & 2 which ; point to the warm boot address (the desired address + 3). ; Do_Cold: push hl ;Save the HL Register Pair ld hl,(Wbadd) ;HL:= Warm Boot Address ld l,0 ;HL:= Cold Boot Address ex (sp),hl ;Restore the HL Register Pair ret ;Goto The Cold Boot entry page ;---------------------------------------------------------------------- ; Format Initialize (7_Jul_84) ;----------------------------- ; Finit: ld c,Close_File ld de,Fcb call Bdos ret ;---------------------------------------------------------------------- ; Format Restore (7_Jul_84) ;----------------------------- ; Fstore: ld c,Disk_Reset call Bdos ld c,Open_File ld de,Fcb Call Bdos ret ;---------------------------------------------------------------------- ; Local Data Area (17_May_84) ;---------------------------- ; cnttab: defb 18*3 defb 18*3 defb 10*3 defb 5*3 Start_Dir: ds 2 End_Dir: ds 2 Cur_Rec: ds 2 ; Save Locations for Extended Bios Data Movement Functions ;--------------------------------------------------------- ; Save_BC: defw 0 ;Save of the BC reg (length) Save_DE: defw 0 ;Save of the DE reg (destination) Save_HL: defw 0 ;Save of the HL reg (source) ; Local Apif Data ;---------------- ; APIF_Address: defw 0 ;Address of Apif in sys bank Ramdaty_Address:defw 0 ;Address of Ramdaty in sys bank Local_Apif: defs AILeng,0 ;Local Copy of Apif ; MsDos File FCB ;--------------- ; FCB: db 1 ;Drive A db 'MSDOS FIL' ;File name ds 21,0 record: ds 3,0 ; Gap/Sector Table ;----------------- ; Ftable: db 50 db 32h db 80 db 9,8,7,6,5,4,3,2,1 ; Mtab/DPB ;--------- ; Mtab: db 0 db 4 ds 7,0 dw 24h ds 13,0 db 20h No_File: db 0dh,0ah,'No MSDOS.FIL file was found.$' ; Format/Verify Buffer ;--------------------- ; Temp_Buffer: defs 1024,0 ;temp buffer for format/verify end