Subttl MD-11 Cbios for Floppy Based CP/M 2.2 (Rev_17 7_Jan_85) ; ; Copyright 1983 ; Morrow Designs, Inc. ; San Leandro, Ca. ; Last Update 17_May_84 ; .z80 ;Set switch for zilog nmenonics include HD22DEF.MAC ;Include the common defintions ; Index: Cbios ;------------- ; ; start Bios Jump Table ; wboot Warm Boot ; gocpm Setup CPM's system variables and then enter the CCP ; const Get the Console input status ; conin Input a Character from the Console or the Submit Buffer ; cin Input a Character from the Console ; submt In Memory Submit ; find Find a block header ; conout Console Output with escape sequence translation ; outstr Output a string of characters to the console ; escape Cursor - Escape_Sequence Translation ; lookup Lookup a table ; ascout Output a byte in decimal ascii ; cout Console Output ; lst List Output ; listst Get the Status of the List Device ; rdrstat Get the Reader Status (and the Character if its ready) ; ptr Get a character from the reader ; ; home Home the Disk Heads ; seldsk Select a disk ; bdrv Bad Drive Common Error Return ; settrk Set the Track Number ; setsec Set the Sector Number ; setdma Set the DMA Address ; ; getab Read the Media Table from the current drive's boot sector ; read Read a Sector ; write Write a Sector ; rwmove Common Return for read and write ; diret Common Return for read, write and getab ; ; sectran Perform Sector Translation ; wrthst Write Host ; rdhst Read Host ; hstret Common Return for Wrthst and Rdhst Routines ; rdblk Read a Block ; wrblk Write a block ; discio Disk I/O ; dret Common Return for rdblk, wrblk and discio ; ; mstk Move the stack pointer ; gdsk Get a Pointer to the Current MTAB ; wrtbnk Write to the Bank Register ; cvmsg Change the Virtual Drive Message ; ----- Data Areas page 64 ;---------------------------------------------------------------------- ; System Equates (7_Jan_85) ;-------------------------- ; floppy equ False ; Location Defintions ;-------------------- ; memsize equ 64 cpm equ (memsize-10) * 1024 bdos equ cpm+806h bios equ cpm+1600h cstack equ -1-32 ;reserving 1 byte for stkct, 32 for interrupts stkct equ cstack ; Default Baud Rates ;------------------- ; dflt1 equ 6 ;console 9600 baud dflt2 equ 3 ;list 1200 baud dflt3 equ 6 ;sio 9600 buad ; Rom Jump Table Definitions ;--------------------------- ; rom equ 0 msgrm equ rom+3 ;rom print signon message routine hmrm equ rom+6 ;rom home disk routine rdhsrm equ rom+9 ;rom read disk routine wrhsrm equ rom+0Ch ;rom write disk routine disrm equ rom+0Fh ;rom direct disk i/o routine bterm equ rom+18h ;rom print boot err routine APIFrm equ rom+1Bh ;rom default for application interface area rdlsec equ rom+20h ;rom read a logical sector wrlsec equ rom+23h ;Rom write a logical sector fmthst equ 026h ; Other Defintions ;----------------- ; pun equ lst ;Punch Device dpboff equ 10 ;offset into dph for dpb pointer $txrdy equ 4 edv equ 40h drives equ 4-1 rev equ 40h primary equ 0 page ;---------------------------------------------------------------------- ; Bios Jump Table ;---------------- ; .phase bios start: jp cboot ;Cold Boot wbot: jp wboot ;Warm Boot jp const ;Console Status jp conin ;Console Input jp conout ;Console Output jp lst ;List Device Out jp pun ;Punch Device Out jp ptr ;Paper Tape Reader In jp home ;Home jp seldsk ;Select a Drive jp settrk ;Set the Track Number jp setsec ;Set the Sector Number jp setdma ;Set the DMA Address jp read ;Read a logical sector jp write ;Write a logical sector jp listst ;List Device Status jp sectran ;Sector Translation jp cvmsg ;change virtual drive mesg. ;the following direct routines require IX jp rdblk ;direct disk read jp wrblk ;direct disk wr jp discio ;direct disk i/o ;Misc Information/Vectors db romrev ;Revision Number dw APIF ;Pointer to Application Interface Area dw ramdaty ;Pointer to RamdatY dw ramdaty + MToff ;Pointer to the base of the first MTAB dw pool ;Pointer to the sector translation table etblptr:dw esctbl ctblptr:dw ctrltbl evctptr:dw escvect cvctptr:dw ctvect dw dcastrt jp initctc ;initialize all bit rate generators jp format ;format one track, requires ix page ;---------------------------------------------------------------------- ; Warm Boot Vector (7_Jan_85) ;---------------------------- ; wboot: jp rwboot ;---------------------------------------------------------------------- ; EXIXAI - ex ix,ai - exchange ix and ai areas ;--------------------------------------------- ; 1) location of user's original ix is replaced by system ix, ; program must remember where his ix is ; 2) enter with application's image of the AI area pointed to by IX ; exit with IX pointed to system AI ; 3) the system AI area has been exchanged with the user's AI, and should ; be preserved. another call here will restore the system AI. ; exixai: push bc push hl ;preserve ld hl,apif ld b,aileng exixa0: ld a,(ix+0) ;user's byte ld c,(hl) ;system byte ld (ix+0),c ld (hl),a inc hl inc ix djnz exixa0 pop hl pop bc ret ;---------------------------------------------------------------------- ; INITCTC - Set-up bit rates ;------------------------------------- ; initctc: ;initialize serial list for hardware handshake if req'd ld a,3 out (s2stat),a ;select reg 3 ld a,(cflag+ramdaty) bit @hwsync,a ld a,0c1h ;8bits/char, rxon jr z,intct1 ld a,0e1h intct1: out (s2stat),a ;8bits/char, auto, rx on ;initialize all 3 bit rate generators ld a,(ser1baud) ;index for table call getval ld a,0beh ;mode word for channel 2, mode 3 ld c,baud0 ;set-up channel 2 for serial 1 CON: call setbaud ld a,(ser2baud) call getval ld a,07eh ;mode word for channel 1, mode 3 ld c,baud1 ;set-up channel 1 for serial 2 LST: call setbaud ld a,(ser3baud) call getval ld a,03eh ;mode word for channel 0, mode 3 ld c,baud2 ;set-up channel 0 for serial 3 SIO: setbaud: ;set channel mode from [A], output 2 bytes from (hl) to (c) out (baudset),a ;set mode ld a,(hl) ;timer lo inc hl out (c),a ld a,(hl) ;timer hi out (c),a ret ;index into baudtbl using [A], leaving [HL] on value getval: ld hl,baudtbl ;base of bit rate values add a,a ;*2 ld c,a ld b,0 add hl,bc ret baudtbl: dw 1136 *2 ;110 dw 417 *2 ;300 dw 208 *2 ;600 dw 104 *2 ;1200 dw 52 *2 ;2400 dw 26 *2 ;4800 dw 13 *2 ;9600 dw 13 ;19,200 dw 1 ;reserved dw 1 ;reserved dw 1 ;reserved page ;---------------------------------------------------------------------- ; FUNCTION - Get a character, handle function key ;------------------------------------------------ ; if 0 ;never Function: call getchr ;get a character from current source cp leadin ;check for function key lead-in ret nz ;back to cp/m if not call getchr ;get function key identifier ld hl,fcntbl ;translation table call scan ;look for key jp nc,fcn2 ;if not found, ld hl,replay+2 ;convert to escape sequence ld (hl),a ;put key into block dec hl ;escape character dec hl ;length byte = 2 fcn2: ex de,hl ;[de]->string.length call inject ;inject string into ims jp function ;get the first character in sequence ;recurse if required page ;---------------------------------------------------------------------- ; INJECT - Insert character string into IMS buffer, activate IMS ;--------------------------------------------------------------- ; 1) enter with [DE] -> string with length byte first, exit w/IMS active ; inject: ld a,(de) ;get length byte ld c,a ;save ld b,0 inc de ;point at string text push de ;save string address ld hl,pool ;address of free space ld a,-1 ;free marker call find ;[de]=free length ;[hl]->free.leng(hi) push hl ;save free address ld h,d ld l,e ;[hl]=free length or a ;[cy]=0 sbc hl,bc ;free.len = free.len - string.len jr c,noims ;if not out of space, ex de,hl ;[de]=new free.len ex (sp),hl ;[hl]=free.address (save old length) ld (hl),d ;write new free.len(hi) dec hl ld (hl),e ;write new free.len(lo) inc hl inc hl ;[hl] -> free.data_area pop de ;[de] = old free.len add hl,de ;point at IMS.head (=fd) inc hl ;[hl] -> ims.len(lo) ld e,(hl) ;read ims.len inc hl ld d,(hl) ex de,hl ;[hl]=ims.len, [de]->ims.len(hi) add hl,de ;ims.len = ims.len + string.len ex de,hl ;[hl] -> ims.len(hi) sbc hl,bc ;ims.address = ims.address - string.len ld (hl),d ;write new ims header, ims.len(hi) dec hl ld (hl),e dec hl ld (hl),0fdh ;ims head complete inc hl inc hl inc hl ex de,hl ;[de] -> new ims space (destination) pop hl ;[hl] -> string text ldir ;copy string ld hl,ramdaty+cflag ld a,(hl) bit @imswet,a jr z,fcn5 bit @imsact,a jr z,fcn4 dec de ld a,(de) set 7,a ;mark bit ld (de),a ;of last char ld a,(hl) jr fcn4 fcn5: set @imswet,a fcn4: set @imsact,a ld (hl),a ret ;exit with carry = clear noims: ;enter here if no ims available pop de ;drop pop de ;drop ret ;exit with carry = set replay: db 2 ;length db 1bh ;escape db 0 ;replaced by key code page ;---------------------------------------------------------------------- ; SCAN - Search for key in table ;------------------------------- ; enter with [hl] -> table to be searched ; [a] = key to search for ; form of table is: ; element_count (byte) ; element_list (string) ; :: element = length (byte) ; string (text) ; scan: ld d,0 ld b,(hl) ;element count inc b inc hl ;point at key jr scan1 scan0: cp (hl) ;key we're looking for? inc hl ;point at string.length ret z ld e,(hl) ;not key, so get length inc e ;same as inc hl add hl,de ;next element scan1: djnz scan0 ;do until out of elements scf ;abnormal exit ret endif page ;---------------------------------------------------------------------- ; CONST - Get the Console input status ;------------------------------------- ; const: in a,(s1stat) ;console status routine bit 0,a ;see if rdy ld a,0 ret z ;return with 0 if not rdy ld a,0ffh ;return with ff if rdy ret ;---------------------------------------------------------------------- ; GETCHR - Input a Character from the Console or the Submit Buffer ;---------------------------------------------------------------- ; getchr: conin: ld a,(ramdaty+cflag) ;get cflag and 0c0h ;mask out ims flags cp 0c0h ;check if ims active jr z,submt ;jmp if submit active ;If not then fall through to cin ;---------------------------------------------------------------------- ; cin - Input a Character from the Console ;------------------------------------------ ; cin: in a,(s1stat) ;console input routine bit 0,a ;see if rdy jr z,cin ;jmp if not rdy in a,(s1data) ;get character chret: and 7fh ;mask off parity ret page ;---------------------------------------------------------------------- ; In Memory Submit ;----------------- ; ; submt locates the submit string block within the bios ram area, ; the next character is taken from the buffer and passed to cp/m. ; the free block and submit string block pointers are updated. ; if this was the last character in the buffer, then the imsbuf ; bit in cflag is cleared. ; if the parity bit is set on the character, then the ims bit in ; cflag is cleared, which de-activates ims until the next warm ; boot. ; parity equ 7 submt: in a,(s1stat) ;see if char. ready bit 0,a jr z,subgo ;jmp if no input in a,(s1data) ;get char. cp 3 ;see if cntl-c jr nz,subgo ;jmp if not ld hl,pool ld a,0fdh ;ims call find ;get count push de ;save length ld hl,pool ld a,0ffh ;free call find ex de,hl ;[hl]=free.len pop bc ;[bc]=ims.len add hl,bc ;[hl]=total space ex de,hl ;[hl]=free.len(hi) ld (hl),d dec hl ld (hl),e ;reset free length inc hl inc hl ;[hl] -> free.data space add hl,de ;[hl] -> end of free space ld (hl),0fdh ;ims header inc hl ld (hl),0 inc hl ld (hl),0 ;reset ims.len ld a,(ramdaty+cflag) ;de-activate ims res @imsact,a res @imswet,a ld (ramdaty+cflag),a ld a,18h ret subgo: ld hl,pool ;pointer to ram area ld a,0ffh ;free space code call find ;find free space inc de ;update free space pointer ld (hl),d dec hl ld (hl),e add hl,de ;set hl ==> ims buffer inc hl inc hl ld e,(hl) ;update ims buffer header ld (hl),0fdh inc hl ld d,(hl) dec de ld (hl),e inc hl ld a,e ;see if last char. or d ld a,(ramdaty+cflag) jr nz,skp1 ;jmp if not last char. res @imswet,a ;clear imsbuf flag skp1: bit parity,(hl) ;check parity bit of char. jr z,skp2 ;jmp if parity = 0 res @imsact,a ;de-activate ims skp2: ld (ramdaty+cflag),a ;save cflag ld a,(hl) ;get char. ld (hl),d ;finish updating ims block header jr chret ;return to cp/m ;---------------------------------------------------------------------- ; FIND - Find a block header ;--------------------------- ; find searches bios ram area starting from hl for the block ; header contained in a. ; find: cp (hl) ;see if header code matches inc hl ;increment pointer ld e,(hl) ;get offset to next block inc hl ld d,(hl) ret z ;return if block found inc hl ;set pointer to next block add hl,de jr find ;keep looking page ;---------------------------------------------------------------------- ; Console Output with escape sequence translation ;------------------------------------------------ ; on entry to xlate, register c contains the character to be output. ; a test is made to see if the system is in the process of outputing ; a multiple character escape sequence, or if the character is a ; morrow standars control code. if neither test is true, than the ; character is output. ; if the character is part of a multiple character escape sequence, ; then the character is passed to the escape routine. if the ; character is a mscc, then it is converted to the appropriate ; sequence, and output. ; esccod equ 1bh conout: ld a,(esc_lvl) ; test escape flag or a ; check if flag is set jr nz,escape ; if escape sequence, jump ld a,1fh ; test if mscc cp c jp c,cout ; if not, then xmit it ld a,esccod ; check if esc char cp c jp nz,notesc ; if not, jump ld a,1 ; otherwise, set escape ld (esc_lvl),a ; level to 1st stage ret ; and return notesc: ld hl,(ctblptr) ; set to search control table call lookup ; and lookup character in table or a ; see if char found jp z,cout ; if not, output char ld hl,(cvctptr) ; calculate string location page ;---------------------------------------------------------------------- ; OUTSTR - Output a string of characters to the console ;------------------------------------------------------ ; this routine outputs a string of characters to the console. ; it is used by the translate program to output a terminal ; specific string in order to implement a control sequence. ; when entered, the hl register pair points to the base of ; the string table, and the bc register pair is the offset ; to the string. characters are output starting with the ; first character until a byte value of ffh is detected. ; outstr: add hl,bc ; add offset to base ld e,(hl) ; get location of string Š inc hl ld d,(hl) ex de,hl ; move address of string to hl loop: ld a,(hl) ; get a char cp 0ffh ; see if done ( ffh==>done) ret z ld c,a ; if not, get char call cout ; xmit it inc hl jr loop ; until end of string page ;---------------------------------------------------------------------- ; ESCAPE - Cursor - Escape_Sequence Translation ;---------------------------------------------- ; ; this routine is used to create a string for direct ; cursor addressing, or to translate character codes. ; upon receipt of an escape code from ; a program, the esc_lvl is set to indicate an escape ; sequence is being output. when the next character is ; received, it is tested to see if it is an equals sign (=). ; if it is not, than an escape character is output, followed ; by the character received. if the character is the equal sign, ; then two more characters will be accepted, after-which a string ; will be output for positioning the cursor. ; escape: ld a,(esc_lvl) ; get current escape level cp 1 ; level 1? jr z,seq1 ; then process 1st part cp 2 ; level 2? jr z,seq2 ; then process 2nd level jr seq3 ; it must be level 3 ; seq1: ld a,'=' ; equal sign? cp c ; if char is =, then dca started jr z,set ; else, could be character to xlate xor a ; clear escape level ld (esc_lvl),a ld hl,(etblptr) ; point to xlate table call lookup ; lookup character or a ; see if char found jr nz,down ; if found, jump to output push bc ld c,esccod ; else, send escape, then char call cout ; send escape pop bc ; get original character jp cout ; send it down: ld hl,(evctptr) ; calculate string location jr outstr ; output the string set: ld a,2 ; otherwise, set for level 2 ld (esc_lvl),a ; processing ret ; and return seq2: ld a,c ld (first),a ; this is the first char ld a,3 ; set for level 3 ld (esc_lvl),a ret Š seq3: ld a,(offset2) ; get offset for 2nd char add a,c ; add to 2nd char ld (second),a ; save 2nd char ld a,0 ld (esc_lvl),a ; clear escape sequence ld de,first ; pointer to 1st char ld a,(de) ; get 1st char ld c,a ; save in c ld a,(offset1) ; get offset for 1st char add a,c ; add to 1st char ld (de),a ; save 1st char ld a,(order) push af rra sbc a,a ; 0==>1-2 : ff==>2-1 ld b,a ; save order in b ld a,e ; use order to adjust de sub b ld e,a ; de points to 1st char to output ld hl,dcastrt ; pointer to dca prefix sting call loop ; output string ld a,(de) ; get 1st char to output ld c,a pop af bit 1,a ; see if ascii push af call nz,ascout ; call ascii if nz call cout ; output char ld hl,dcamid ; pointer to seperator string call loop ; output string ld a,e ; use order to adjust de add a,b inc b add a,b ld e,a ; de points to 2nd char to output ld a,(de) ; get char to output ld c,a pop af call nz,ascout ; call ascii if flag set call cout ; output char outend: ld hl,dcaend ; point to dca terminator jp loop page ;---------------------------------------------------------------------- ; LOOKUP - Lookup a table ;------------------------ ; ; this routine is entered with the hl register pair pointing to ; the base of a table to be searched. register c contains the ; character to search for. upon return, the accumulator will ; contain 0 if the character was not found, and ffh if it was found. ; if the character was found in the table, then bc will contain ; the offset into the table, multiplied by 2. i.e bc / 2 = location Š; of character in table. the maximum number of values in the table is ; 20 h. ; lookup: ld b,0 ; init offset nmtch: ld a,(hl) ; get value from table cp 0ffh ; see if end of table jr z,nochar ; jmp if end cp c ; see if char matches jr z,mtch ; jmp if match inc hl ; inc table pointer inc b ; inc offset inc b ; " " jr nmtch ; continue search mtch: ld c,b ; put offset in bc ld b,0 ld a,0ffh ; set a to success ret nochar: xor a ; set a to failure ret page ;---------------------------------------------------------------------- ; ASCOUT - Output a byte in decimal ascii ;---------------------------------------- ; ; ascout takes a binary value in c and output its decimal ascii ; equivalent. ; ascout: push bc ld a,c ld c,'0' ;init to ascii 0 tens: sub 10 ;subtract 10 from value jr c,ones ;jmp if underflow inc c ;inc ascii tens value jr tens ;loop ones: ld b,a ;save intermediate value ld a,'0' ;a = ascii 0 cp c ;see if tens value is 0 call nz,cout ;output tens value if not 0 ld a,3ah ;ascii 0 plus 10 add a,b ;add to produce ones value pop bc ld c,a ;get ready for output ret page ;---------------------------------------------------------------------- ; COUT - Console Output ;---------------------- ; cout: in a,(s1stat) ;console output routine bit 2,a ;see if rdy jr z,cout ;jmp if not rdy ld a,c ;output character out (s1data),a ret ;---------------------------------------------------------------------- ; LST - List Output ;------------------ ; lst: ld a,(ramdaty+cflag) bit @cenlst,a jr nz,centout lstdrv: call listst ; status of lstflg jr z,lstdrv ; if not ready, loop over: ld a,c ; else, get char out (s2data),a ; xmit it ret centout: call centsts ;status jr z,centout ;wait for ready ld a,c ;get char out (cdata),a ;write data ld b,11111111b xor $CNTSTB ld c,00000000b or $CNTSTB call wrtbnk ;set strobe on ld c,0 call wrtbnk ;set strobe off ret centsts: in a,(cstat) and $CNTRDY ;test for busy = zero ret z ;exit false xor a dec a ;set true ret page ;---------------------------------------------------------------------- ; LISTST - Get the Status of the List Device ;------------------------------------------- ; 1) has xon/xoff protocol handler for micro decision cbios ; listst: ld a,(cflag+ramdaty) bit @cenlst,a ;if centronics list jr nz,centsts call rdrstat ; get a character, or null cp 13h ; if xoff r'cvd... jr nz,nxtchk ; if not, check if xon xor a ; set flag to not rdy ld (lstflg),a ret ; return not rdy nxtchk: cp 11h ; if xon, then it might be ready jr nz,chkflg ; else, state not changing ld a,0ffh ld (lstflg),a ; set flag to rdy chkflg: ld a,(lstflg) ; get status flag lstret: or a ; set flags ret z ; if zero, then xoff pending ld b,$txrdy ;presume software handshake in a,(s2stat) ; get status and b ; check if xmit ready (cts and dcd) cp b ld a,0 ; set not ready status jr nz,lstret ; jmp if not ready dec a ; set ready status ret ; and return it. page ;---------------------------------------------------------------------- ; RDRSTAT - Get the Reader Status (and the Character if its ready) ;----------------------------------------------------------------- ; rdrstat: in a,(s2stat) ; get status and $txrdy ret z ; return if no char in a,(s2data) ; else, get char and 7fh ; mask parity ret ;---------------------------------------------------------------------- ; PTR - Get a character from the reader ;-------------------------------------- ; ptr: call rdrstat ;get status or char. jr z,ptr ;loop if no char. ret page ;---------------------------------------------------------------------- ; WARM - Warm Boot ;----------------- ; rwboot: ld hl,cstack ld (hl),0 ld sp,hl ld iy,ramdatY ld (iy+hstdsk),0 ;select drive a ld (iy+hsttrk),0 ;set track 0 ld (iy+hsttrk+1),0 ld (iy+hstsec),2 ;start at sector 2 ld (iy+hstsec+1),0 ld (iy+hstbuf),0 ;Initialize the Disk_Buffer address ld (iy+hstbuf+1),high dskbuf ld bc,cpm ;Initialize the system load base addr. call setdma ;(set iy+dmaadr:= load base) rdlop: call rdhst ;Repeat Read the next sector of system ld a,(iy+erflag) ; If (error eq true) or a jp nz,bterr ; exit to rom ld hl,dskbuf ; HL:= Source (disk buffer) ld e,0 ld d,(iy+dmaadr+1) ; DE:= Destination (cpm) ld a,high (bios - 512) ; If (this is the last sector) cp d jr nz,notlst ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or (000000 or $XFER) call wrtbnk ; Set the Transfer Bit ld bc,512 ; BC:= Length of transfer ldir ; move sector ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or ($BANK2 or 00000) call wrtbnk ; Clear Transfer ld hl,cpm+3 jp gocpm ; setup low core, xeq cpm notlst: ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or (000000 or $XFER) call wrtbnk ; Set the Transfer Bit ld bc,1024 ; BC:= Length of transfer ldir ; move sector ld b,11111111b xor ($XFER) ld c,00000000b or (00000) call wrtbnk ; Clear Transfer ld (iy+dmaadr+1),d ; Update Destination address ld a,(iy+hstsec) inc a ld (iy+hstsec),a ; Sector:= Sector + 1 if floppy cp 6 ; If (last sector on track) else cp 9 ;hard disk will exit at end of cp/m endif jp nz,rdlop ld (iy+hstsec),1 ; Sector:= 1 inc (iy+hsttrk) ; Track:= Track + 1 jp rdlop ;On Boot Error exit to the rom bterr: ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or (000000 or 0000000) call wrtbnk ;Enable the Rom and Bank 1 jp bterm page ;---------------------------------------------------------------------- ; GOCPM - Setup CPM's system variables and then enter the CCP ;------------------------------------------------------------ ; gocpm: push hl ld bc,80h call setdma ;Dma_Address:= 80h (default) ld a,0c3h ld (0),a ;Loc_0:= Jump ld hl,wbot ld (1),hl ;loc_1->2:= Base of BIOS + 3 ld (5),a ;Loc_5:= Jump ld hl,bdos ld (6),hl ;Loc_6->7:= Base of BDOS xor a ld (3),a ;Loc_3:= 0 ld hl,(vnumb) ld (8),hl ;Loc_8:= Version Number set @imsact,(iy+cflag) ld (iy+unacnt),0 ld a,(4) ld c,a ;get drive for ccp pop hl jp (hl) page ;---------------------------------------------------------------------- ; HOME - Home the Disk Heads ;--------------------------- ; home: call mstk ;fix stack push ix ;save ix & iy push iy ld iy,ramdaty ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or (000000 or 0000000) call wrtbnk ;Enable the Rom call hmrm ;call rom cretn: ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or ($BANK2 or $_RMENB) call wrtbnk ;Disable the Rom pop iy ;restore ix & iy pop ix call ustk ;restore stack ret page ;---------------------------------------------------------------------- ; SELDSK - Select a disk ;----------------------- ; seldsk: ld a,drives ;check drive bound cp c jp c,bdrv ;jmp if bad call mstk ;set machine stack ld a,c ;new drive ld (ramdaty+sekdsk),a ;set drive as current ld hl,ramdaty ;pointer to ramdaty push de ;save primary/secondsry select call gdsk1 ;get mtab pointer in [HL] pop de ;restore primary/secondary select ;note, winchesters are foreign bit @frgn,(hl) ;see if foreign drive jr nz,skpset ;jp if foreign or hard bit primary,e ;see if first time jr nz,skpset ;jp if not first ; Prepare to read ID info from media push hl ;save dskdef pointer call getab ;read config table from diskette or a ;see if error jp nz,ubdrv ;back to drive a: if error jr dskchk fmtlog: ;format enters here with disk info copied to buffer push hl ;format enters with system mtab dskchk: ; Check ID info for correctness (checksum) ld b,11111111b xor $BANK2 ld c,00000000b or 000000 call wrtbnk ;select bank 1 dsktln equ 25 dsktb equ dskbuf+80h+dsktln ;address of end of table+1 ld hl,dsktb ;pointer to end of table+1 ld b,dsktln ;count must be odd! for field of E5 xor a ;init check byte ld e,a ;init 0-check byte chklp: dec hl ;dec pointer xor (hl) ;x-or table value into parity check byte ld d,a ;save parity check byte or e ;or in 0-check byte ld e,a ;save 0-check byte ld a,d ;restore pariy check byte djnz chklp ;dec table length & loop til done ; inc hl ;hl=>dskdef1, access to sided-ness or a ;a=0 if table ok ld a,e ;a = 0-check byte jr nz,sside ;assume s.s. if invalid table or a ;check 0-check byte jr nz,dskdpb ;invalid table if zero sside: ld de,sdpb ;pointer to s.s. dpb from ram pop hl ;restore ram mtab jr setsgl dskdpb: ;now we know that the media really is native morrow format dsktdb equ dskbuf+80h+9 ld de,dsktdb ;pointer to dpb in boot ;set ram MTAB according to disk MTAB bit @dblmed,(hl) ;check disk MTAB for d.s. media pop hl ;restore pointer to ram MTAB set @dblmed,(hl) ;presume double sided jr nz,dside ;but if single sided, setsgl: res @dblmed,(hl) ;set for s.s. media dside: ld b,11111111b xor $BANK2 ld c,00000000b or $BANK2 call wrtbnk xor a ;set z flag skpset: ;enter with z=1 if disk contains dpb to copy, pointed to by [DE] ;also, [HL] -> current MTAB ;note: this stub is called by format push hl push af ;save z-boolean for ldir below ld a,(sekdsk+ramdaty) ;get drive ld l,a ld h,0 add hl,hl add hl,hl add hl,hl add hl,hl ;get drive times 16 ld bc,dpbase add hl,bc ;hl=dph address push hl ;save dph address for bdos push de ;save disk dpb pointer ld de,dpboff ;offset to dpb address add hl,de ;get pointer to dpb address ld e,(hl) inc hl ld d,(hl) ;de points to ram dpb space pop hl ;restore disk dpb pointer pop bc ;dph address pop af ;restore boolean push bc ;dph address push de ;current dpb jr nz,notab ;skip if no dpb update ld b,11111111b xor $BANK2 ld c,00000000b or 000000 call wrtbnk ;select bank 1 ld bc,15 ;length of dpb on drive media ldir ;update dpb ld b,11111111b xor $BANK2 ld c,00000000b or $BANK2 call wrtbnk notab: pop hl ;current dpb ; Set the number of Logical sectors per track ld a,(hl) ;get sectors per track ld (sectrk+ramdaty),a ;save in ramdaty inc hl ld a,(hl) ld (sectrk+ramdaty+1),a ;high byte ; Figure the number of records per allocation block inc hl ;dpb.bsh inc hl ;dpb.blm ld a,(hl) ;get BLM inc a ;number of records per block ld (unamax+ramdaty),a ;save in ramdaty ; Figure the number of physical sectors per track = SPT / 2^secsiz pop hl ;current DPH ex (sp),hl ;restore current MTAB inc hl ;dskdef1, for sizmsk ld a,(hl) and $sizmsk ;get size inc a ld b,a ;set as a count ld a,(sectrk+ramdaty) ;read records per track pspt: srl a ;/2 djnz pspt rla ;*2 ld (physpt+ramdaty),a ;set physical sectors per track pop hl ;restore dph address ret call ustk ;restore user's stack ret ; Bad Drive ;---------- ; ubdrv: call bdrv jp uustk ;force exit from bios bdrv: ld hl,4 ;return error code and ld (hl),h ;set to drive a. ld l,h ret page ;---------------------------------------------------------------------- ; Set the Track Number ;--------------------- ; settrk: ld (sektrk+ramdaty),bc ;set track in ramdaty ret ;---------------------------------------------------------------------- ; Set the Sector Number ;---------------------- ; setsec: ld (seksec+ramdaty),bc ;set sector in ramdaty ret ;---------------------------------------------------------------------- ; Set the DMA Address ;-------------------- ; setdma: ld (dmaadr+ramdaty),bc ;set dma address in ramdaty ret page ;----------------------------------------------------------------------- ; GETAB - Read the Media Table from the current drive's boot sector ;------------------------------------------------------------------ ; getab: call mstk ;fix stack push ix push iy push bc ld iy,ramdaty xor a bit @hstwrt,(iy+dflag) call nz,wrthst res @hstwrt,(iy+dflag) res @hstact,(iy+dflag) pop bc or a ;see if error jr nz,diret ld (iy+hstdsk),c ;set APIF to read boot sector ld (iy+hsttrk),0 ld (iy+hsttrk+1),0 ld (iy+hstsec),1 call rdhst ;read boot sector jp diret ;Goto common return with read and write page ;---------------------------------------------------------------------- ; Read a Sector (23_Sept_83) ;--------------------------- ; read: call mstk ;fix the stack push ix ;save ix & iy push iy ld iy,ramdaty ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or (000000 or 0000000) call wrtbnk ;Enable the Rom and select Bank 1 call rdlsec ;read a logical sector jp rwmove ;move data ;---------------------------------------------------------------------- ; WRITE - Write a Sector (13_Oct_83) ;----------------------------------- ; write: call mstk ;fix the stack push ix ;save ix & iy push iy ld iy,ramdaty ld (iy+wrtype),c ;Set the Write Type ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or (000000 or 0000000) call wrtbnk ;Enable the Rom and select Bank 1 call wrlsec ;write a logical sector ; jp rwmove page ;---------------------------------------------------------------------- ; Common Return from Read/Write a logical sector ;----------------------------------------------- ; rwmove: or a ;If There were NO errors) jp nz,diret ld b,11111111b xor ($XFER or $_RMENB or $BANK2) ld a,c or $XFER or $_RMENB ld c,a ; (Add XFER and _RMENB to c) call wrtbnk ; Set XFER Clr_RMENB select BANKx ld bc,128 ; BC:= Length of transfer ldir ; move sector ld b,11111111b xor ($XFER or $_RMENB or $BANK2) ld c,00000000b or (00000 or $_RMENB or $BANK2) call wrtbnk ; Clear Transfer and enable Rom ld a,(iy+wrtype) ; If (this is a directory write) cp wrdir ld a,0 ; (A:=no error status) jp nz,diret res @hstwrt,(iy+dflag) ; clear write flag set @BufOK,(iy+OpFlag) ; BufOK:= buffer data OK call wrthst ; write buffer ; Common Return read, write and gettab ;------------------------------------- ; diret: ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or ($BANK2 or $_RMENB) call wrtbnk ;Enable Bank 2 and disable Rom pop iy ;restore ix & iy pop ix call ustk ;restore user's stack ld a,(ramdaty+erflag) ;get error code or a ret z ;exit no error ld a,(ramdaty+opflag) bit @serd,a ;if error display suppressed, ld a,(ramdaty+erflag) ret nz ;return to it, else call bdrv ;reset to drive A: rst 0 ;abort with trail page ;---------------------------------------------------------------------- ; SECTRAN - Perform Sector Translation ;------------------------------------- ; sectran:ld l,c ;hl=bc ld h,b inc hl ;start sectors at 1 ld a,d ;see if xlat table or e ret z ;return if no xlat ex de,hl ;hl=xlt add hl,bc ;add to table ld l,(hl) ;get xlated sector ld h,0 ret ;---------------------------------------------------------------------- ; RDHST - WRTHST - Read/Write Host Routines (13_Oct_83) ;------------------------------------------------------ ; ; Read Host ;---------- ; rdhst: ld b,11111111b xor ($_RMENB or $BANK2) ld c,00000000b or (0000000 or 000000) call wrtbnk ;Enable the Rom and select Bank 1 call rdhsrm ;call rom jr hstret ;return ; Write Host ;----------- ; wrthst: ld b,11111111b xor ($_RMENB or $BANK2) ld c,00000000b or (0000000 or 000000) call wrtbnk ;Enable the Rom and select Bank 1 call wrhsrm ;call the rom ; Common Return ;-------------- ; hstret: ld b,11111111b xor ($_RMENB or $BANK2) ld c,00000000b or ($_RMENB or $BANK2) call wrtbnk ;DisAble the Rom and select Bank 2 ld a,(iy+erflag) ;get status ret page ;---------------------------------------------------------------------- ; RDBLK - WRTBLK - Read/Write a Block (13_Oct_83) ;------------------------------------------------ ; 1) These routines allow EXTERNAL users to access the rom's ; rdhst, wrthst and discio routines. ; 2) The user's stack is saved and the stack in common memory is ; used instead. ; 3) For the duration of the rom access the user supplied application ; interface area is used. ; ; Read a Block ;------------- ; rdblk: ld iy,ramdaty ;init iy call mstk ;fix the stack push ix ;preserve user's ix call exixai ;swap ix and ai call rdhst ;call rom pop ix push ix call exixai ;restore ai and ix pop ix ;restore ix call ustk ;restore user's stack ret ;return to caller ; Write a block ;-------------- ; wrblk: ld iy,ramdaty ;init iy call mstk ;fix stack push ix ;preserve user's ix call exixai ;swap ix and ai call wrthst ;call rom pop ix push ix call exixai ;restore ai and ix pop ix ;restore ix call ustk ;restore user's stack ret ; Disk I/O ;--------- ; discio: ld iy,ramdaty call mstk ;fix the stack push ix ;save user's ix call exixai ;swap ix and ai ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or (000000 or 0000000) call wrtbnk ;Enable the Rom call disrm ;call the rom ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or ($BANK2 or $_RMENB) call wrtbnk ;DisAble the Rom pop ix push ix call exixai pop ix ld a,(iy+erflag) call ustk ;restore user's stack ret ;return to caller ; Format ;_______ ; format: ;enter with [de] -> old micro decision mtab/dpb pair, as on media ; [ix] -> user's APIF area ; apif.hstdsk = logical drive to format ; apif.hsttrk = track for format ; apif.hstsec -> sector table (in reverse order) ld a,drives cp (ix+0) ;see if legal jr nc,form2 ;illegal ld a,Edv ;no such drive ld (ix+(erflag-aioff)),a ;set error ret form2: ld a,(ix+0) ;get drive ld (sekdsk+ramdaty),a ;set drive ld iy,ramdaty call mstk push ix ;save user's ix call exixai ;swap ix and ai ld a,(de) ;read new mtab.dskdef0 bit @hrddsk,a ;see if harddsk jr z,formf ;if hard disk ld e,1 ;secondary select ld c,(iy+sekdsk) call seldsk ;secondary select jr form8 formf: ;login floppy by writing format's copy of disk info to diskbuf push de ;save new MTAB pointer (source) ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or ($BANK2 or $XFER) call wrtbnk ;write to bank1 from bank2 ld a,(iy+sekdsk) ;get login drive call gdsk ;get [hl] -> ram mtab ex (sp),hl ;replace with new mtab pointer ld de,dskbuf+80h ;ID area is destination ld bc,dsktln ;length ldir ;copy format's copy as if from disk ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or 000000 or 00000 call wrtbnk ;select bank 1, xfer off call mstk ;so seldsk can exit pop hl ;restore system mtab call fmtlog ;format logon for floppy form8: ld b,11111111b xor ($BANK2 or $XFER) ld c,00000000b or ($BANK2 or $XFER) call wrtbnk ;write to bank1 from bank2 ld l,(iy+hstsec) ;get pointer to gap stuff ld h,(iy+hstsec+1) ld de,fmtbuf ;destination in system bank ld c,3 ;3 bytes for gap table ld b,0 ldir ;copy gap table push hl ;save source for sector table ld a,(ramdaty+hstdsk) call gdsk ;get the mtab bit @hrddsk,(hl) ;test for hard disk ld hl,fmtbuf+3 ;table space for hard disk ld c,(iy+physpt) ;length is physical sectors per track ld b,0 ld de,0 ;zero additional offset for hard disk jp nz,formt1 ld de,12-3 ;additional offset for floppy formt1: add hl,de ex de,hl ;destination in [de] pop hl ;restore source pointer ldir ;copy sector table ; ld e,(iy+hstbuf) ;get count ; ld d,(iy+hstbuf+1) ; ld a,e ; or d ;test for zero = 1 ; jr nz,formt2 ; inc de ;zero, so make it one ;formt2: ; ld b,11111111b xor ($_RMENB or $XFER or $BANK2) ld c,00000000b or (0000000 or 00000 or 000000) call wrtbnk ;rom on, xfer off, bank1 ; ;formt3: ; push de call fmthst ;format the track ; pop de ;get count ; ; dec de ; ld a,e ; or d ; jr z,formt4 ; inc (iy+hsttrk) ;track=track+1 ; jr nz,formt3 ; inc (iy+hsttrk+1) ;hi byte ; jr nz,formt3 ; ;formt4: ld b,11111111b xor ($BANK2 or $_RMENB) ld c,00000000b or ($BANK2 or $_RMENB) call wrtbnk ;rom off, select bank2 pop ix push ix ;user's ix call exixai ;swap ai and ix pop ix call ustk ;restore user's stack ret ;return to caller page ;---------------------------------------------------------------------- ; MSTK - Move the stack pointer ;------------------------------ mstk: ;set machine stack, must be called, do not jump here ;conditionally swap to machine stack ;[AF] is trashed, others preserved ;note, this is a critical region, callable by interrupts push hl ;save user's [HL] ld hl,stkct ;stack count, number of times we have been here di ;interrupts off inc (hl) ;count++ ld a,1 ;first time? cp (hl) pop hl ;restore user's [HL] jp nz,mstk9 ;exit if not first time ld (cstack-6),hl ;save user's [HL] at top of system stack pop hl ;get return address ld (cstack-4),hl ;save on system stack ld hl,0 add hl,sp ;get user's stack address ld (cstack-2),hl ;save at base of system stack ;map: [user's stack] ; [return address] ;[SP]-> [user's HL ] ld sp,cstack-6 pop hl mstk9: ei ;interrupts on, sorry it took so long ret ;[SP]-> [user's stack] uustk: ;unconditionally restore user's stack, force exit from bios ;note: jump here, or call here treated same ;currently on system stack: ; old stack pointer ; 0 to N words of junk ld (cstack-4),hl ;return address could have been here, still inside stack ld hl,(cstack-2) ;recover user's stack di ;interrupts off ld sp,hl ;load ld hl,(cstack-4) ;restore [HL] xor a ld (stkct),a ; ei ret ustk: ;set user stack, must be called, do not jump here ;conditionally return to user's stack ;[AF] is trashed ;may be called by interrupt routines push hl ;save user's [HL] ld hl,stkct ;number of times we've been here di ;interrupts off dec (hl) pop hl jp nz,ustk9 push hl ld hl,(cstack-2) ;recover user's stack ld sp,hl ;set to user's stack ld hl,(cstack-4) ;get return address from system stack push hl ;put it on user's stack ld hl,(cstack-6) ;get [hl] from system stack ustk9: ei ret ;---------------------------------------------------------------------- ; GDSK - Get a Pointer to the Current MTAB (23_Sept_83) ;------------------------------------------------------ ; gdsk: push iy ;get iy into hl pop hl gdsk1: ld de,MToff ;calc. mtab pointer add hl,de rlca ;multiply drive by 16 rlca rlca rlca ld e,a ;add (16 * drive) to pointer add hl,de ret if 0 ;never ;---------------------------------------------------------------------- ; PUSHBK - Push bank and Select New Bank ;--------------------------------------- ; enter with [C] = new bank required, alters only @_RMENB, @BANK2, @XFER ; note: all 3 bits are always set per [C] pushbk: ld (hlsave),hl pop hl ;return address ld a,(cpybnk+ramdaty) ;get current bank push af ;save on stack push hl ;return address back on and not (@_RMENB + @XFER + @BANK2) ;clear all bits or c ;add new bits pushb1: ld (cpybnk+ramdaty),a ;write current contents out (bnkstb),a ;set bank ld hl,hlsave ;restore [hl] hlsave equ $-2 ;self modifying ret ;---------------------------------------------------------------------- ; POPBK - Restore previous bank, from contents of stack ;------------------------------------------------------ ; no entry requirements popbk: ld (hlsave),hl ;save hl pop hl ;return address pop af ;bank code push hl ;restore hl jr pushbk1 ;write the bank endif ;---------------------------------------------------------------------- ; wrtbnk - Write to the Bank Register (12_Sept_83) ;------------------------------------------------- ; 1) This is the common routine for seting or clearing bits in the ; Bank Strobe register. ; 2) Notice that the IY area (ramdatY) must be initialized before ; this routine is used. ; 3) Register Usage: ; A -> General purpose ; B -> Mask to clear the selected bit (i.e. NOT-bit) ; C -> Mask to set the bit (i.e. 0=clear bit, otherwise set bit) ; IY -> Pointer to ramdatY ; 5) Example: to set bit 3; B=11110111b, C=00001000b A=Don't Care ; wrtbnk: ld a,(ramdaty+cpybnk) ;A:= Current bank strobe contents and b ;(remove the selected bit) or c ;(set/clear the selected bit) ld (ramdaty+cpybnk),a ;Save the new contents out (bnkstb),a ret page ;---------------------------------------------------------------------- ; CVMSG - Change the Virtual Drive Message ;----------------------------------------- ; ; cvmsg is a routine to change the virtual drive message. ; on entry: hl points to the begining of the new message. ; de points to the location of the character ; which will be set to the logical drive ; that the virtual drive is to become. ; bc is the length of the new message. ; ; af,bc,de,hl are changed, all other regs. are unchanged. ; cvmsg: push hl ex de,hl xor a sbc hl,de ld de,vmsg add hl,de ld (vdrvp+ramdaty),hl pop hl ldir ret page ;---------------------------------------------------------------------- ; Disk Parameter Headers (5_Jan_85) ;---------------------------------- ; dpbase equ $ if floppy ;First Floppy Drive dpe0: dw xlt1k dw 0 dw 0 dw 0 dw dirbuf dw dpb0 dw csv0 dw alv0 ;First Hard Disk dpe1: dw 0 dw 0 dw 0 dw 0 dw dirbuf dw dpb08 dw 0 dw alv2 else ;First Hard Disk dpe0: dw 0 dw 0 dw 0 dw 0 dw dirbuf dw dpb08 dw 0 dw alv2 dpe1a: dw 0 dw 0 dw 0 dw 0 dw dirbuf dw dpb02 dw 0 dw alv2a ;First Floppy Drive dpe1: dw xlt1k dw 0 dw 0 dw 0 dw dirbuf dw dpb0 dw csv0 dw alv0 endif dpe2: ;Second Floppy Drive dw xlt1k dw 0,0,0 dw dirbuf dw dpb0 dw csv1 dw alv1 dpe3: ;third floppy drive dw xlt1k dw 0,0,0 dw dirbuf dw dpb0 dw csv3 dw alv3 page ;---------------------------------------------------------------------- ; Disk Parameter Blocks ;---------------------- ; ; floppy disk parameter blocks ;----------------------------- ; ;single sided disk sdpb: dw 40 db 4 db 15 db 1 dw 94 dw 127 db 0c0h db 0 dw 32 dw 2 ;double sided dpb0: dw 40 db 4 db 15 db 1 dw 194 dw 191 db 0e0h db 0 dw 48 dw 2 ; hard disk parameter blocks ;--------------------------- ; ;8 meg drive dpb08: dw 72 ;logical records per logical track db 5 ;bls = 4k db 31 db 1 ;2 logical extents per physical extent dw 227*36/4-1 ;227cyl (1 thru 227) * 36sec/cyl / 4sec/gp - 1 dw 16*4*32-1 ;9sec/trk*4trk/cyl*1024bytes/sec / 32bytes/dir - 1 = 1 cyl worth db 0FFh ;reserve 64k db 0FFh dw 0 ;no cks dw 8 ;one cyl, cylinder zero ;2 meg drive dpb02: dw 72 ;logical records per logical track db 5 ;bls = 4k db 31 db 1 ;2 logical extents per physical extent dw 227*36/4-1 ;78cyl (228 thru 305) * 36sec/cyl / 4sec/gp - 1 dw 16*4*32-1 ;2 groups db 0FFh ;reserve 2 db 0FFh dw 0 ;no cks dw 228*4 ;cyl 0-227 allocated above page include HDIXIY.MAC include HDMTAB.MAC ;---------------------------------------------------------------------- ; Messages Escape Strings and Misc ;--------------------------------- ; vmsgº db cr,lf,'Your floppy drive is being re-assigned as drive ' vdrv: db 'a.',cr,lf,'Exchange diskettes and press [return]',0 lstflg: db 0ffh ; printer ready flag dcastrtº äb 1bh,3dh,0ffh » dcá prefiø string Š ds 3,0ffh dcamid: ds 6,0ffh ; dca seperator dcaend: ds 6,0ffh ; dca terminator string esc_lvlº äb 0 ;indicateó esã sequencå level offset1: db 0 ;first character offset offset2: db 0 ;second character offset order: db 1 ;bit 0 = 0 --> row, then column, ; = 1 --> column, then row ;bit 1 = 0 --> binary cursor adresses ; 1 --> ascii cursor addresses first: db 0 ; temporary storage of first second: db 0 ; temporary storage of second pool: ;beginning of managed space xltab: db 0 dw 40 xlt1k: db 1,2,3,4,5,6,7,8 db 25,26,27,28,29,30,31,32 db 9,10,11,12,13,14,15,16 db 33,34,35,36,37,38,39,40 db 17,18,19,20,21,22,23,24 db 0feh ; console xlt table dw clen esctbl: db 0ffh ctrltbl:db 0ffh escvect:dw 0 ctvect: dw 0 page ; translation strings for the terminal go here ;--------------------------------------------- ; clen equ $-esctbl db 0FFh ;eot dw 100h ds 100h free: db 0FDh ;ims buffer header dw 0 page ;---------------------------------------------------------------------- ; BOOT - cold boot entry from 1 sector disk boot ;----------------------------------------------- ; cboot: ld hl,cstack ld (hl),0 ;init count ld sp,hl ;set stack call initctc ;initialize bit rate generators ; Make some space available ld hl,pool ld a,-1 call find ;get free pointer push hl ;save address, [de]= current length ld hl,alv@-free-3 ;length available add hl,de ;new size ex de,hl pop hl ;restore address ld (hl),d ;hi byte dec hl ld (hl),e ;lo byte of length inc hl inc hl ;[hl] -> first free byte add hl,de ;new free head ld (hl),0fdh inc hl ld (hl),0 inc hl ld (hl),0 ; Print signon message ld iy,ramdaty ld de,signon ld b,11111111b xor ($_RMENB) ld c,00000000b or (0000000) call wrtbnk ;Enable the Rom call msgrm ;print signon ld b,11111111b xor ($_RMENB) ld c,00000000b or ($_RMENB) call wrtbnk ;DisAble the Rom xor a ld (3),a ld (4),a ;Set the default drive for gocpm ld hl,cpm jp gocpm page ;---------------------------------------------------------------------- ; Sign_On Message (7_Jan_85) ;--------------------------- ; signon: db Cr,Lf, 'MD-HD -- CP/M 2.2 -- Rev ' db (((rev and 0F0h) shr 4) + asc0) db '.', ((rev and 0Fh) + asc0) db Cr,Lf, 'Copyright 1976 to 1980 Digital Research, Inc.' db Cr,Lf, 'Copyright 1982 to 1985 Morrow Designs, Inc.' If Floppy db Cr,Lf, 'Floppy Disk System ' Else db Cr,Lf, 'Hard Disk System ' EndIf db Cr,Lf,0 page ;---------------------------------------------------------------------- ; Allocation and Checksum Vectors (7_Jan_85) ;------------------------------------------- ; sksiz equ 64 ;stack reserve 32 levels struct equ 35bh ;length of this structure alv@ equ cstack-sksiz-struct ;First Floppy Disk alv0 equ alv@ ;ds 25 csv0 equ alv0 + 25 ;ds 48 ;Second Floppy Disk alv1 equ csv0 + 48 ;ds 25 csv1 equ alv1 + 25 ;ds 48 ;First Hard Disk alv2 equ csv1 + 48 ;ds 256 ;second half of hard disk, or continuation for 1 drive 11meg cpm3 only alv2a equ alv2 + 256 ;ds 88 ;Third Floppy Disk alv3 equ alv2a + 256 ;ds 25 csv3 equ alv3 + 25 ;ds 48 ;---------------------------------------------------------------------- ; Space for the Directory Buffer ;------------------------------- ; dirbuf equ csv3 + 48 ; endbios equ dirbuf + 128 ;top of memory end