Title Micro_Decision Installation SubProceedure Number 2 (12_Sept_84) ; ; Copyright 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; John Zalabak ; .z80 Aseg Org 0100h ; This is the Second of Two SubProceedures used to install the ; number of Physical Drives on a Micro-Decision. This is done as part ; of the Micro-Desision installation proceedure. ; ; First, this SubProceedure announces the end of the installation ; proceedure and then waits for the user to type a carriage return ; before continuing. ; Once the user has entered the carriage return the program ; then patches the number of physical drives in the disk system image ; so that it matches the memory resident system. ; ;---------------------------------------------------------------------- ; Index (10_Sept_84) ;------------------- ; ; Isub2_Main Main Line of Terminal Initialization ; ; Proceed_Prompt Print the Proceed Prompt ; Clear_Screen Clear the Console Screen ; Get_Position Determine the drive's position (eg left hand, upper...) ; ; Get_Version Check the CP/M version ; Install_Drives Install the Number of Physical Drives ; ; Read_Cpm2_Bios Read the Cp/m 2.2 Bios ; Write_Cpm2_Bios Write the Cp/m 2.2 Bios ; Setup_IX Setup the IX and Initialize Pertinant Values ; ; Get_Bios_Pntr Get One of the Bios Pointers ; Get_DE_Indr_HL Load the DE register Pair Indirectly Through the HL ; ; Cpm2_Bias Figure the Memory Bias for Cpm 2.2 ; Apply_Bias_DE Apply the Bias to the DE Pair ; ; Report_Errors Report an Error on the Console ; Print_Message Print a Message on the Console ; page 60 ;---------------------------------------------------------------------- ; Equates (12_Sept_84) ;--------------------- ; ;Bios/Bdos Equates Bios_Entry equ 0 ;Bios: Entry Vector Location Bdos_Entry equ 5 ;Bdos: Entry Vector Location Bdos_ConIn equ 1 ; Console Input Bdos_ConOut equ 2 ; Console Output Bdos_PString equ 9 ; Print a Sting on the Console Bdos_Ret_Ver equ 12 ; Return CP/M version ;Cp/m 2.2 Bios Jump Table Offsets Bios_Offset equ 200h ;Offset: Bios Start from Start Disk Buffer Bios_Address equ 1 ;Address of Bios (Warm Boot Vector Addr) WBoot_Offset equ 4 ;Warm Boot address (Gives base of Bios) RdBlk_Offset equ 37h ;Read a Block from the Floppy Disk WrBlk_Offset equ 3Ah ;Write a Block to the Floppy Disk RamDatX_Offset equ 40h ;Pointer to RamDatX Area RamDatY_Offset equ 42h ;Pointer to RamDatY Area Mtab_Offset equ 44h ;Pointer to Mtabs ;RamDatX Area Definitions HstDsk equ 0 ;Host Level Disk HstTrk equ 1 ; " " Track HstSec equ 2 ; " " Sector SecCnt equ 3 ;Sector Count (1 to n) Retry equ 4 ;Error Retry Count HstBuf equ 5 ;Host Buffer ErFlag equ 7 ;Error Flag ;Error String Codes Error_Opening equ 10 ;Error Intro Error_Version equ 11 ;Wrong Version of CP/M Sys_Read_Err equ 12 ;Unable to read System from the Disk Sys_Write_Err equ 13 ;Unable to Write System to the Disk ;Message Strings Msg_Left equ 21 ;Left Hand Drive Msg_Lower equ 22 ;Lower Drive Msg_Right equ 23 ;Right Hand Drive Msg_Upper equ 24 ;Upper Drive Msg_Single equ 25 ;Single Drive System Message Msg_Double_1 equ 26 ;Double Drive System Message #1 Msg_Double_2 equ 27 ;Double Drive System Message #2 Msg_Double_3 equ 28 ;Double Drive System Message #3 Msg_Double_4 equ 29 ;Double Drive System Message #4 Msg_Response equ 30 ;Response Prompt Message ;Non Printing Ascii Equates Control_C equ 03h ;Control C (Force CPM Warm Boot) Tab equ 09h ;Tab Lf equ 0Ah ;Line Feed Cr equ 0Dh ;Carriage Return Esc equ 1Bh ;Escape Bright equ '(' ;Start High Lighting Dim equ ')' ;Start Low Lighting ;Other Definitions Disk_Buffer equ 2000h ;Start of Disk Buffer (must be above Rom) Mtab_Leng equ 9 ;Length of an Mtab Tot_Mtab equ 5 ;Total Number of Mtabs @Double_Sided equ 5 ;Bit Position for Double Sided in DskDef0 page ;====================================================================== ; Main Line of Sub Installation Proceedure 2 (12_Sept_84) ;======================================================== ; Isub2_Main: call Proceed_Prompt ;Print the Prompt ld a,Msg_Response ;A:= Response Message Prompt call Print_Message ;Print the Response Prompt ImLp1: ld c,Bdos_ConIn ;Repeat C:= Console Input Funciton call Bdos_Entry ; Get the User's Response cp Control_C ; If (Response eq Control C) jp z,Bios_Entry ; Goto Warm Boot cp Cr jr nz,ImLp1 ;Until (Response eq Carriage Return) call Get_Version ;If (this is NOT Version 2.x) jr nz,ImErr ; Goto Report Error call Read_Cpm2_Bios ;Read the Bios or a ;If (there was an error) jr nz,ImErr ; Goto Report Error call Install_Drives ;Install the Drives call Write_Cpm2_Bios ;Write the Bios or a ;If (There was an Error) jr z,ImDone ; Goto Report Error ImErr: call Report_Errors ;Report the Error ImDone: jp Bios_Entry ;Return page ;====================================================================== ; Prompt the User to Change Diskettes Before Proceeding (11_Sept_84) ;=================================================================== ; 1) This routine clears the console screen and then prints one ; of two prompt messages. ; 2) If its a single drive system then the prompt is a single string. ; 3) If its a double drive system then the prompt string consists of ; several segments because single sided double drive systems have ; the B: drive located to the Right of the A: drive while on a double ; sided double drive system the B: drive is above the A: drive. ; 4) The proceedure Get_Position returns the accm equal to: 0 for a ; Single Drive system, the entry value of the C Register for single ; sided double drive systems or the entry value of the C Register plus ; one if its a double sided double drive system. ; Proceed_Prompt: call Clear_Screen ;Clear the Console Screen ld c,80 ;C:= dummy message code call Get_Position ;If (This is a Single Drive System) or a jr nz,PpSk1 ld a,Msg_Single ; A:= Single Drive System Message call Print_Message ; Print the Single Drive Message ret ; Return PpSk1: ld a,Msg_Double_1 ;Else A:= Double Drive System Msg #1 call Print_Message ; Print Double Message #1 ld c,Msg_Left ; C:= Left Hand Drive Message call Get_Position call Print_Message ; Print Position Message 1 ld a,Msg_Double_2 ; A:= Double Drive System Msg #2 call Print_Message ; Print Double Message #2 ld c,Msg_Right ; C:= Right Hand Drive Message call Get_Position call Print_Message ; Print Position Message 2 ld a,Msg_Double_3 ; A:= Double Drive System Msg #3 call Print_Message ; Print Double Message #3 ld c,Msg_Left ; C:= Left Hand Drive Message call Get_Position call Print_Message ; Print Position Message 3 ld a,Msg_Double_4 ; A:= Double Drive System Msg #4 call Print_Message ; Print Double Message #4 ret ;Return page ;---------------------------------------------------------------------- ; Clear the Console Screen (20_Jul_84) ;------------------------------------- ; 1) This Routine Simply outputs a Carriage Return followed by 50 Line ; Feeds to the Console. ; 2) NONE of the Register Pairs are altered. ; Clear_Screen: push bc push de push hl ld c,Bdos_ConOut ;C:= Bdos Console Output Function Number ld e,Cr ;E:= Carriage Return call Bdos_Entry ;Print a Carriage Return ld b,50 ;B:= Character Counter ld c,Bdos_ConOut ;C:= Bdos Console Output Function Number CsSk1: push bc ;Repeat ld e,Lf ; E:= Line Feed call Bdos_Entry ; Print the Line Feed pop bc djnz CsSk1 ;Until (Character Counter - 1 eq 0) pop hl pop de pop bc ret ;Return page ;====================================================================== ; Get the Drive Position Code (11_Sept_84) ;========================================= ; 1) This Routine returns the accm equal to... ; 0 for a Single Drive System ; C_Reg + 0 for a Single Sided Double Drive System ; C_Reg + 1 for a Double Sided Double Drive System ; Get_Position: ld de,RamDatY_Offset call Get_Bios_Pntr ;DE:= Pointer to Start of RamDatY dec de dec de ;DE:= Pointer to Vnum ld a,(de) ;Update Vnum or a ;If (there's only one drive) ret z ; Return (A:= 0) ld de,Mtab_Offset call Get_Bios_Pntr ;DE:= Pointer to DskDef0 ld a,(de) bit @Double_Sided,a ;If (it a Single Sided System) ld a,c ; ret z ; Return (A:= C_Reg) inc a ;Else ret ; Return (A:= C_Reg + 1) page ;====================================================================== ; Check the CP/M version (5_Jul_84) ;================================== ; 1) This routine checks the CP/M version. It returns with the ; Z flag = 1 if CP/M 2. ; Get_Version: ld c,Bdos_Ret_Ver ;Return version Bdos call call Bdos_Entry ld a,0F0h and l cp 20h ;If (this is NOT CP/M 2.x) ld a,Error_Version ; A:= Version Error ret nz ; Return ld a,0 ;Else A:= No Error ret ; Return page ;====================================================================== ; Install the Number of Physical Drives (6_Jul_84) ;================================================= ; 1) This routine Updates the Bios Image of Vnum, copies the resident ; system's Mtabs into the Memory image and then resets the current ; track values in the memory image to De:Calibrated (0FFh). ; Install_Drives: call Cpm2_Bias ;Figure the Bias values ld de,RamDatY_Offset call Get_Bios_Pntr ;DE:= Pointer to Start of RamDatY dec de dec de ;DE:= Pointer to Vnum ld a,(de) ;A:= Vnum call Apply_Bias_DE ;DE:= Pointer to Memory Image of Vnum ld (de),a ;Update Vnum ld de,Mtab_Offset call Get_Bios_Pntr ;DE:= Pointer to Start of Mtabs push de call Apply_Bias_DE ;DE:= Pointer to Memory Image of Mtabs pop hl ;HL:= Pointer to System Mtabs ld bc,Mtab_Leng * Tot_Mtab ;BC:= Counter for number of Mtabs push de ;(Save pointer to start of Memory Mtabs) ldir ;Move the System Mtabs to Memory Image pop hl ld de,Mtab_Leng - 1 ;DE:= Offset to Current Track in Mtab add hl,de ;HL:= Pointer to Current Track (memory image) ld de,Mtab_Leng ;DE:= Length of an Mtab ld b,Tot_Mtab ;B:= Counter (total number of Mtabs) IdLp1: ld (hl),0FFh ;Repeat Reset the Current Track add hl,de ; HL:= HL + Mtab_Leng djnz IdLp1 ;Until (all current track values reset) ret ;Return page ;====================================================================== ; Read the Cp/m 2.2 Bios (23_Jun_84) ;=================================== ; 1) This routine reads the Bios from the system tracks into the ; next free memory space (next free space pointer set in Build_Tables) ; Read_Cpm2_Bios: call Setup_IX ;Set IX to RamdatX and Save the Original ld de,RdBlk_Offset ;DE:= Offset to the RdBlk Address call Get_Bios_Pntr ex de,hl ;HL:= Vector to Read a Block Routine call IR_HL ;Execute the read a block routine ld a,(ix+ErFlag) or a ;If (there were no errors) ret z ; Return ld a,Sys_Read_Err ;Else A:= Error Code ret ; Return IR_HL: jp (hl) ;====================================================================== ; Write the Cp/m 2.2 Bios (25_Jun_84) ;==================================== ; 1) This routine writes the Bios back to the system tracks. ; Write_Cpm2_Bios: call Setup_IX ;Set IX to RamdatX and Save the Original ld de,WrBlk_Offset ;DE:= Offset to the WrBlk Address call Get_Bios_Pntr ex de,hl ;HL:= Vector to Read a Block Routine call IW_HL ;Execute the Write a Block routine ld a,(ix+ErFlag) or a ;If (There were no errors) ret z ; Return ld a,Sys_Write_Err ;Else A:= Error Code ret ; Return IW_HL: jp (hl) page ;---------------------------------------------------------------------- ; Setup the IX and Initialize Pertinant Values (22_Jun_84) ;--------------------------------------------------------- ; 1) This routine Sets the IX register 2 pages before the start of ; the Bdos and then initializes the essential parameters. ; Setup_IX: ld hl,(Bdos_Entry+1) ;HL:= Pointer to Start of Bdos ld l,0 ;HL:= Pointer to Base of Bios dec h ;HL:= Base Page of Bios - 1 dec h push hl pop ix ;IX:= Base Page of Bios - 1 ld (ix+HstDsk),0 ;Drive:= 0 ld (ix+HstTrk),1 ;Starting_Track:= 1 ld (ix+HstSec),2 ;Starting_Sector:= 2 ld (ix+SecCnt),4 ;Number_of_Sectors_to_Read:= 4 ld (ix+Retry),10 ;Retries:= 10 ld (ix+HstBuf), LOW Disk_Buffer ld (ix+HstBuf+1),HIGH Disk_Buffer ld (ix+ErFlag),0 ;Error_Flag:= Reset ret ;---------------------------------------------------------------------- ; Get One of the Bios Pointers (20_Jun_84) ;----------------------------------------- ; Get_Bios_Pntr: ld hl,(Bios_Entry+1) ;HL:= Pointer to Warm Boot Entry ld l,0 ;HL:= Pointer to Base of Bios call Get_DE_Indr_HL ;DE:= Contents of Addr Pointed to by HL ret ;Return ;---------------------------------------------------------------------- ; Load the DE register Pair Indirectly Through the HL (20_Jun_84) ;---------------------------------------------------------------- ; 1) This routine Loads the DE register pair Indirectly through the ; HL register pair after adding the entry values of the DE and HL. ; 2) Register Usage: ; DE -> On Entry = Offset; On Exit = (HL + DE) ; HL -> [preseved] Base Address ; Get_DE_Indr_HL: add hl,de ;HL:= Pointer to RamDatY Pointer ld e,(hl) inc hl ld d,(hl) ;DE:= Contents of Addr Pointed to by HL dec hl ret ;Return page ;---------------------------------------------------------------------- ; Figure the Memory Bias for Cpm 2.2 (21_Jun_84) ;----------------------------------------------- ; 1) This routine Sets up the Bios Base and the Bios Bias. The Bios ; Base is the starting memory address of where the bios is current ; loaded. The bios Bias is the Starting Memory Address of where the ; bios is intented to be loaded. ; Cpm2_Bias: ld hl,Disk_Buffer ;HL:= Start of the Disk Buffer ld de,Bios_Offset ;DE:= Offset to Bios Start add hl,de ;HL:= Pointer to Start of Cpm Bios ld (Bios_Base),hl ;(save the Base address of the Bios) ld de,WBoot_Offset ;DE:= Offset to Warm Boot Address call Get_DE_Indr_HL ld e,0 ;DE:= Start of Load Location of Bios ld (Bios_Bias),de ;(save the Load address of the Bios) ret ;---------------------------------------------------------------------- ; Apply the Bias to the DE Pair (21_Jun_84) ;------------------------------------------ ; 1) This routine adjusts the DE pair. On entry, the DE pair is pointing ; to the actual load address of an object. On exit, the DE pair is ; pointing to the current memory location containing that object. ; 2) Register Usage: ; DE -> Entry: Load Address; Exit: Actual Address ; HL -> Used in figuring the offsets ; Apply_Bias_DE: push hl ex de,hl ;HL:= Load Address Data Object ld de,(Bios_Bias) ;DE:= Load Address Base of Bios or a sbc hl,de ;HL:= Offset from Bios Base ld de,(Bios_Base) ;DE:= Offset to Base of Bios in Memory add hl,de ex de,hl ;DE:= Current Memory address pop hl ret page ;====================================================================== ; Report Errors (5_Jun_84) ;========================= ; 1) Report Errors on the console. ; 2) Register Usage: ; A -> Has Error Code on entry ; Report_Errors: push af ld a,Error_Opening call Print_Message ;Print the Error Opening Message pop af call Print_Message ;Print the Error Message ret ;====================================================================== ; Print a Message on the Console (11_Sept_84) ;============================================ ; 1) This routine prints a message string on the console. ; 2) Register Usage: ; A -> Has Error Code on entry ; B -> Counter ; C -> Holds copy of Error Code ; DE -> Pointer to Message String ; HL -> Pointer into Message Code Table ; Print_Message: ld c,a ;C:= Error Code to Find ld b,Max_Table ld hl,Message_Table ;HL:= Start of the Message table PMLp1: ld a,(hl) ;Repeat A:= Table's Message Code inc hl ld e,(hl) inc hl ld d,(hl) ; DE:= Pointer to String inc hl ; (HL equal to start next entry) cp c ; If (Code eq table) jr z,PMprn ; Goto Print djnz PMLp1 ;Until (the whole tables been checked) ld de,NoCode ;(set pointer to 'Unrecognized Message') PMprn: ld c,Bdos_PString ; call Bdos_Entry ; Print the Message ret page ;---------------------------------------------------------------------- ; Message String Lookup Table (12_Sept_84) ;----------------------------------------- ; Message_Table: db Error_Opening ;Error Intro dw ErrOpn db Error_Version ;Wrong Version of CP/M dw EVmsg db Sys_Read_Err ;Unable to read System from the Disk dw SRmsg db Sys_Write_Err ;Unable to Write System to the Disk dw SWmsg db Msg_Left ;Left Hand Drive dw LHmsg db Msg_Lower ;Lower Drive dw LOmsg db Msg_Right ;Right Hand Drive dw RHmsg db Msg_Upper ;Upper Drive dw UPmsg db Msg_Single ;Single Drive System Message dw SMmsg db Msg_Double_1 ;Double Drive System Message #1 dw D1msg db Msg_Double_2 ;Double Drive System Message #2 dw D2msg db Msg_Double_3 ;Double Drive System Message #3 dw D3msg db Msg_Double_4 ;Double Drive System Message #4 dw D4msg db Msg_Response ;Response Prompt Message dw RSmsg End_Table: Max_Table equ ( (End_Table - Message_Table)/3 ) + 1 page ;---------------------------------------------------------------------- ; Text Strings (12_Sept_84) ;-------------------------- ; ErrOpn: db Cr,Lf,'*=> Error: $' EVmsg: db Cr,Lf,'This Program only runs under CP/M 2.x $' SRmsg: db Cr,Lf,'Unable to read System from the Disk $' SWmsg: db Cr,Lf,'Unable to Write System to the Disk $' LHmsg: db 'left hand $' LOmsg: db 'lower $' RHmsg: db 'right hand $' UPmsg: db 'upper $' SMmsg: db Esc,Dim,Cr,Lf,Lf,Lf,Tab db 'We are now done with your ' db Esc,Bright db 'DISTRIBUTION ' db Esc,Dim db 'diskette. Please' db Cr,Lf,Tab db 'store it in a safe place.$' D1msg: db Esc,Dim,Cr,Lf,Lf,Lf,Tab db 'We are now done with your ' db Esc,Bright db 'DISTRIBUTION ' db Esc,Dim db 'diskette. Please remove it' db Cr,Lf,Tab db 'from your $' D2msg: db 'disk drive and store it in a safe place.' db Cr,Lf,Lf,Tab db 'Now take your ' db Esc,Bright db 'WORKING ' db Esc,Dim db 'diskette from your $' D3msg: db 'disk drive' db Cr,Lf,Tab db 'and put it in your $' D4msg: db 'disk drive so we can finish' db Cr,Lf,Tab db 'the installation proceedure.$' RSmsg: db Cr,Lf,Lf,Lf,Tab db 'Press ' db Esc,Bright db '[RETURN] ' db Esc,Dim db 'when you are ready to proceed $' CrLf: db Cr,Lf,'$' NoCode: db 'Unrecognized Message $' page ;---------------------------------------------------------------------- ; Local Data Area (5_Jul_84) ;--------------------------- ; Bios_Base: dw 0 ;Actual Memory Address of the Bios Bios_Bias: dw 0 ;Intended Load Address of the Bios end ;---------------------------------------------------------------------- ; Original Message Text ;---------------------- ; Single Drive Message We are now done with you DISTRIBUTION diskette. Please store it in a safe place. Double Drive Message We are now done with your DISTRIBUTION diskette. Please remove it from you right hand disk drive and store it in a safe place. Now take your WORKING diskette from you right hand disk drive and put it in you left hand disk drive so we can finish the installation proceedure. Press [RETURN] when you are ready to proceed .