; title 'Serialization Program for MP/M-86 09/14/81' version equ 20 ;version 2.0 system equ 1 ;MP/M 86 system ; Serialization Program for MP/M 86 diskettes ; Note ********************************************************** ; This program contains Digital Research proprietary information, ; and must not be reproduced, copied, or transcribed in any form ; whatsoever ; *************************************************************** ; Copyright (C) 1979, 1980, 1981 ; Digital Research ; Box 579 Pacific Grove ; California, 93950 ; Revised: ; 14 Sept 81 by Thomas Rolander (MP/M II 8080) ; 18 Sept 81 by Danny Horovitz (MP/M-8086) ; '$' signs taken out of identifiers and labels for ; ASM86 compatibility, names of serialized ; programs changed, only one disk to be serialized tpa equ 100h ;transient program area org tpa jmp start Copyright: db 'COPYRIGHT (C) 1981,' db ' DIGITAL RESEARCH ' CoNmLen equ $-Copyright ; ; global equates boot equ 0000h bdos equ 0005h ; ; BDOS equates conin equ 1 ;read console device conout equ 2 ;write console device pbuff equ 9 ;print buffer rdbuff equ 10 ;read buffer resetds equ 13 ;reset disk system selectd equ 14 ;select disk openf equ 15 ;open file rdseqf equ 20 ;read sequential file wrseqf equ 21 ;write sequential file stdmadr equ 26 ;set DMA address ; Hardware dependent equates begtrk equ 0 ;beginning track # dirtrk equ 2 ;directory track # maxtrk equ 76 ;maximum track # sectrk equ 26 ;sectors per track srcdsk equ 2 ;source disk dstdsk equ 3 ;destination disk secsiz equ 128 ;sector size in # bytes nsrlsec equ 4 ;# of sectors to search serial # cr equ 0dh lf equ 0ah ; readtrk equ $ writtrk equ $+3 reread equ $+6 ; track read/write routines, filled in later jmp readdisk jmp writedisk jmp rereaddisk track: ds 1 ;set to track to read/write buffa: ds 2 ;set to buffer address to read/write iof: ds 1 ;io function 0 = read, 1 = write ; readdisk: ;read disk drive a, from track 'track' ;into the address given by 'buffa' mvi a,srcdsk! call sel ;select src drive jmp readd ; ; writedisk: ;write to disk drive b, to track 'track' ;from the address given by 'buffa' mvi a,1! sta iof ;set iofunction to write mvi a,dstdsk! call sel ;select dst drive jmp rwdisk ; rereaddisk: ;read from dstdsk, from track 'track' ;to the address given by 'buffa' mvi a,dstdsk! call sel ;dst drive selected readd: xra a! sta iof ;set to read function rwdisk: ;read or write disk lxi h,track! mov c,m ;get track number call trk ;track selected lhld buffa ;get dma address lxi d,sectrk ;d = 0, e = sectors per track rwloop: ;read/write loop inr d ;to next sector push d! push h! mov c,d! mvi b,0 lxi h,skewtbl! mov a,m! ora a jz noskew ;jump if no skew table dcr c! dad b! mov c,m noskew: call sec ;sector set pop b! push b ;get dma address call dma ;dma address set ;perform io function lda iof! ora a ;0=read, 1=write jnz writefunc ;read disk call dread jmp rwcomplete writefunc: ;write disk call dwrite rwcomplete: ;function complete pop h ;recall dma address lxi d,secsiz! dad d ;to nxt dma pop d ;recall sector and count ; check error conditions ora a! rnz ;rtn with non zero flag set dcr e ;count = count - 1 jnz rwloop ;for another sector ret ;with zero flag set for io complete ; ; ; utility subroutines for direct disk io wboot equ 1 ;warm boot address seldsk equ 24 ;select disk settrk equ 27 ;set track setsec equ 30 ;set sector setdma equ 33 ;set dma address readf equ 36 ;read disk writf equ 39 ;write disk ; sel: ;select drive given by register a mov c,a! lhld wboot! lxi d,seldsk! dad d! pchl ; trk: ;set track given by c lhld wboot! lxi d,settrk! dad d! pchl ; sec: ;set sector given by c lhld wboot! lxi d,setsec! dad d! pchl ; dma: ;set dma address to value of b,c lhld wboot! lxi d,setdma! dad d! pchl ; dread: ;perform read operation lhld wboot! lxi d,readf! dad d! pchl ; dwrite: ;perform write operation lhld wboot! lxi d,writf! dad d! pchl ; start: lxi sp,stack call signonmsg ;display sign on message call sysdskmsg! call ci ;system disk serialize ? ani 0dfh! cpi 'Y'! mvi a,dirtrk jnz sd1 lxi h,sysdsk! inr m! mvi a,begtrk sd1: sta strtrk call dskslctmsg! call read ;select 1/2, 2/2, or 1/2 & 2/2 lxi h,disk! mov m,c call orgmsg! call read ;origin prompt lxi h,origin! mov m,c ;saved the origin number inx h! mov m,b ;high order origin number byte lxi h,comlen! mov b,m! inx h! xchg lxi h,aorigin ;ascii version of the origin org2: ldax d! ora a! jz org3 inx d! mov m,a! inx h! dcr b! jnz org2 ;ascii version moved to buffer, pad it org3: mvi m,'-'! inx h! mvi m,'$' ;ready for printing ; ; now read the serial number call sermsg! call read lxi h,bserial! mov m,c! inx h! mov m,b ;binary copied lxi h,comlen! mvi a,5! sub m ;difference in reg-a lxi h,aserial! jz pad1 ;pad high order positions with 0 pad0: mvi m,'0'! inx h! dcr a! jnz pad0 pad1: lxi d,cbuff ;addressing buffer pad2: ldax d! ora a! jz pad3 ;looking for binary 0 mov m,a! inx h! inx d! jmp pad2 ;another char pad3: ;end of ascii fill (right adjusted in aserial) ; rddsk: ;read disk and copy lxi sp,stack ;reset stack pointer (entry from errors) call insmsg! call ci ;wait for response ; nextdisk: call curmsg! call asermsg! call newmsg! call ci ;new disk is ready, try the copy operation lda strtrk ;get start track lxi h,track! mov m,a ;initialize the track number lxi h,trcount! mvi m,'0'! inx h! mvi m,'0' ; rdtrk: ;read the next source track, compare with 0e5h for end lxi h,ibuff! shld buffa! call readtrk jz readok! call read0msg! jmp rddsk readok: ;track is in memory, track 0? lda track! ora a ;if track 0, do MPMLDR serialization cz serialize ; ;track in memory, check for last track lxi h,ibuff! lxi b,trlen trcomp: mvi a,0e5h! cmp m! jnz wrtrk inx h! dcx b! mov a,c! ora b jnz trcomp ;end of copy, all 0e5h's endcopy: ;write serial # into files in FCB table lda sysdsk! ora a! lxi h,FCBtabledisk1 jz nonsysdsk! lxi h,FCBtablesysdisk1 nonsysdsk: ;write serial # into disk1 lda disk! ani 01h! cnz srlfile ;write serial # into disk2 lxi h,FCBtabledisk2 lda disk! ani 02h! cnz srlfile lxi d,trmsg! call prmsg call incserial! jmp nextdisk ; ;not end of copy, write track to disk from ibuff wrtrk: call writtrk jz wrok! call write0msg! jmp nextdisk wrok: ;written to disk, now read it back and compare lxi h,obuff! shld buffa! call reread jz read1ok! call read1msg! jmp nextdisk read1ok: lxi h,ibuff! lxi d,obuff! lxi b,trlen wrcomp: ldax d! cmp m! jnz wrerr inx h! inx d! dcx b! mov a,c! ora b jnz wrcomp ;compare ok, increment track count and cycle lxi h,track! inr m mvi a,maxtrk+1! cmp m ;jump if last track on disk copied jz endcopy lxi h,trcount+1! inr m! mov a,m! cpi '9'+1 jc rdtrk ;overflow to high order track number mvi m,'0'! dcx h! inr m! jmp rdtrk ; wrerr: ;verify error call vererr! jmp nextdisk ; ; ; utility subroutines ci: mvi c,conin! jmp bdos ;read a character ; prmsg: mvi c,pbuff! jmp bdos ;print a buffer ; rderr: call invalid ; read: ;read constant value to b,c lxi d,maxlen! mvi c,rdbuff! call bdos ;buffer filled lxi h,comlen! mov a,m! ora a! jz rderr ;non zero length inx h! mov e,a! mvi d,0! dad d ;h,l address last pos+1 mvi m,0 ;cleared for end of scan lxi h,cbuff! lxi b,0 conv: mov a,m! ora a! rz ;return if end of convert sui '0'! cpi 10! jnc rderr push h! push b! pop h ;b,c copied to h,l dad h! dad h! dad h! dad b! dad b push h! pop b! pop h ;bc=bc*10 inx h! add c! mov c,a! mvi a,0! adc b! mov b,a jc rderr! jmp conv ;tested for overflow ; incserial: ;increment the serial number lhld bserial! inx h! shld bserial ;test for overflow mov a,l! ora h! jz serover ; lxi h,aserial+4! mvi b,5 ;length of serial number inc0: inr m! mov a,m! cpi '9'+1! rc ;return if carry mvi m,'0' ;clear the number dcx h! dcr b! jnz inc0 ; serover: ;overflow in serial number call overmsg jmp boot ; serialize: ;match ' DIGITAL RESEARCH ' and update serial # lxi h,ibuff! lxi b,nsrlsec*secsiz search: push h! push b lxi d,Copyright! mvi c,CoNmLen comp0: ldax d! cmp m jnz nomatch inx h! inx d! dcr c! jnz comp0 ;match complete, we've found the serial number pop b! pop d ;clears stack xchg! lhld origin! xchg! mov m,e ;low byte origin inx h! mvi m,version ;version number in binary inx h! mvi m,system ;system number in binary inx h! mov m,d ;high byte origin number inx h ;get the serial number xchg! lhld bserial! xchg mov m,d! inx h! mov m,e ;MPMLDR serial number is copied ret ; nomatch: ;try for next match pop b! pop h! inx h! dcx b! mov a,c! ora b jnz search ;not found call noserial! jmp rddsk ; rdwrsrlfl: sta iof ;save rdseqf / wrseqf func code push d! push h lxi d,32! dad d! mvi m,0 ;set nr = 0 pop h! pop d! mvi b,nsrlsec ;count = 4 sectors flrdwr: push b! push d! push h mvi c,stdmadr! call bdos pop d! push d lda iof! mov c,a! call bdos pop h! pop d! pop b inr a! jz srlflerr dcr b! rz push h! lxi h,secsiz! dad d xchg! pop h jmp flrdwr srlflerr: call badMPM! jmp rddsk ; srlfile: ;update serial # in all files in the FCB table ;HL = FCBTable address shld FCBtableadr ;reset disk system push h!mvi c,resetds! call bdos! pop h srlflopn: mov a,m! ora a! jz srlflrdwrvr push h! xchg! mvi c,openf call bdos ;open next file from FCB Table pop h! inr a! jz srlflerr lxi d,33! dad d! jmp srlflopn srlflrdwrvr: lhld FCBtableadr flrdwrvr: mov a,m! ora a! rz push h srlflrd: lxi d,ibuff ;dma buffer is ibuff mvi a,rdseqf! call rdwrsrlfl srlflwr: call serialize ;patch in serial # pop h! push h lxi d,ibuff ;dma buffer is ibuff mvi a,wrseqf! call rdwrsrlfl srlflvr: pop h! push h lxi d,obuff ;dma buffer is obuff mvi a,rdseqf! call rdwrsrlfl lxi h,ibuff! lxi d,obuff! lxi b,nsrlsec*secsiz flvr: ldax d! cmp m jnz srlflerr inx h! inx d! dcx b mov a,b! ora c jnz flvr pop h! lxi d,33! dad d jmp flrdwrvr ; FCBtablesysdisk1: ; ; MPM.SYS db dstdsk+1 ;drive code db 'MPM ' ;file name db 'SYS' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record FCBtabledisk1: ; SUP.MPM db dstdsk+1 ;drive code db 'SUP ' ;file name db 'MPM' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; ; RTM.MPM db dstdsk+1 ;drive code db 'RTM ' ;file name db 'MPM' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; ; MEM.MPM db dstdsk+1 ;drive code db 'MEM ' ;file name db 'MPM' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; CIO.MPM db dstdsk+1 ;drive code db 'CIO ' ;file name db 'MPM' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; ; BDOS.MPM db dstdsk+1 ;drive code db 'BDOS ' ;file name db 'MPM' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; ; GENSYS.CMD db dstdsk+1 ;drive code db 'GENSYS ' ;file name db 'CMD' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; ; MPMLDR.CMD db dstdsk+1 ;drive code db 'MPMLDR ' ;file name db 'CMD' ;file type db 0 ;extent ds 2 db 0 ;record count ds 16 ;allocation map db 0 ;next record ; db 0 ;end of FCB Table ; ; FCBtabledisk2: ; if files on second disk are to be serialized ; put their FCBs here db 0 ;end of FCB Table ; print strings insmsg: lxi d,$+6! jmp prmsg db cr,lf,'Insert control diskette in ' db 'A'+srcdsk db ':, type return$' ; signonmsg: lxi d,$+6! jmp prmsg db cr,lf,'MP/M-86 V' db version/10+'0','.',version mod 10 +'0' db ' Serialization',cr,lf,'$' ; sysdskmsg: lxi d,$+6! jmp prmsg db cr,lf,'System disk (Y/N)? $' ; dskslctmsg: lxi d,$+6! jmp prmsg db cr,lf,'Select type of disk serialization:' db cr,lf,' 1 = Disk 1/2' db cr,lf,' 2 = Disk 2/2' db cr,lf,' 3 = Disk 1/2 & 2/2' db cr,lf,'?$' ; orgmsg: lxi d,$+6! jmp prmsg db cr,lf,'Origin number? $' ; sermsg: lxi d,$+6! jmp prmsg db cr,lf,'Starting serial number? $' ; invalid: lxi d,$+6! jmp prmsg db cr,lf,'Invalid number, try again $' ; curmsg: lxi d,$+6! jmp prmsg db cr,lf,'Serializing disk $' ; asermsg: lxi d,aorigin! call prmsg lxi d,aserial! jmp prmsg ; newmsg: lxi d,$+6! jmp prmsg db cr,lf,'Insert new diskette in ' db 'A'+dstdsk db ':, type return$' ; noserial: lxi d,$+6! jmp prmsg db cr,lf,'Non MP/M-86 diskette, cannot serialize$' ; badMPM: lxi d,$+6! jmp prmsg db cr,lf,'Bad MP/M-86 files on disk$' ; vererr: lxi d,$+6! jmp prmsg db cr,lf,'Verification error, bad disk$' ; overmsg: lxi d,$+6! jmp prmsg db cr,lf,'Serial number overflow$' read0msg: lxi d,$+6! jmp prmsg db cr,lf,'Error on source disk, replace$' ; write0msg: lxi d,$+6! jmp prmsg db cr,lf,'Cannot write new disk, replace$' ; read1msg: lxi d,$+6! jmp prmsg db cr,lf,'Cannot re-read new disk, replace$' ; ; ; miscellaneous data areas ; disk: ds 1 ;1=1/2, 2=2/2, 3=1/2 & 2/2 sysdsk: db 0 ;0ffh="system disk" strtrk: ds 1 ;start track, begtrk or dirtrk FCBtableadr: ds 2 ;FCB table address origin: ds 2 ;binary origin aorig: db cr,lf aorigin: db '00000-$' trmsg: db cr,lf trcount: db '00 tracks verified$' bserial: ds 2 ;binary serial number aserial: db '00000$' ; skew table (first byte 0 if no skewing) skewtbl: db 0 ;no skew table for MDS-800 ; input buffer maxlen: db 7 comlen: ds 1 cbuff: ds 8 ; ds 32 ;stack stack: trlen equ sectrk*secsiz ;buffer size ibuff: ds trlen obuff: ds trlen db 1 ;force hex generation end