******************************************************************************; ; ; ; SSS DDDD SSS Y Y SSS TTTTT EEEEE M M SSS ; ; S S D D S S Y Y S S T E MM MM S S ; ; S D D S Y Y S T E M MM M S ; ; SSS D D SSS Y SSS T EEE M M SSS ; ; S D D S Y S T E M M S ; ; S S D D S S Y S S T E M M S S ; ; SSS DDDD SSS Y SSS T EEEEE M M SSS ; ; ; ; ; ; SD SYSTEMS, INC. ; ; 10111 MILLER RD. ; ; DALLAS, TX 75228 ; ; ; ; COPYRIGHT (C) 1983 ; ; ; ;*****************************************************************************; Title 'RAMDRVR Ram/Rom-Disk driver for cpm 3.0' ;=============================================================================; ; V/R Description Initials-Date ; ;-----------------------------------------------------------------------------; ; 1.0 Original Version dkb... 2/5/83 ; ; 1.1 Updated for 4 Ram boards wbd... 3/7/83 ; ; 1.2 Checksum added wbd... 3/9/83 ; ; 1.3 Rom read and login routines corrected wbd... 3/15/83 ; ; 1.4 Correct match byte on rom login wbd... 3/30/83 ; ; 1.5 RELEASE for distribution CPM30 rel 1.5 dkb... 5/23/83 ; ; 1.6a Change bank selects thru ?bank efj... 7/13/83 ; ; 1.6b Change Initialization for new release dkb... 7/13/83 ; ; 1.6 RELEASE for distribution CPM30 rel 1.6 wbd... 7/13/83 ; ; 1.7a Fix initialization problem wbd... 8/2/83 ; ; 1.7b Fix error return efj... 8/11/83 ; ;=============================================================================; ; ; This program reads and writes to a Ramdisk ; the addressing provided is track and sector ; the register conventions conform to cpm extrn @cbnk,@dbnk,@dma,@sect,@trk,@rdrv,?pderr,?pdec,?pmsg extrn ?bank public rdsd0,rdsd1 maclib z80 ; ; equates for ramdisk bdseldsk equ 0c0h ; board select address latch0 equ bdseldsk latch1 equ bdseldsk+1 latch2 equ bdseldsk+2 ; romdisk equ 0 ; romdisk is a: disk rombdsel equ 0b8h rom0 equ rombdsel+7 rom1 equ rombdsel+6 rom2 equ rombdsel+5 intioby equ 0 false equ 0 true equ not false ; floppy equ 0 hard equ 1 remote equ 2 rom equ 3 ram equ 4 winches equ 5 ; dseg ram$init: return ; no init at cold start ..dkb 1.7a ram$login: ; dkb 1.7a call ram$find$size ; size the ramdisk ..dkb-3 call ram$check$byte ; setup latch in latch0 cpi 0e5h jrz ENDCK ; init done set normal entry dkb1.7a call ram$check$byte ; reset latch again mvi a,0e5h out latch0 ; set byte sta init$flag ; ret ; dkb 1.7a endck: lxi h,ram$sel ; address of normal entry dkb 1.7a mvi a,jmp ; jump instruction dkb 1.7a sta ram$init ! shld ram$init+1 ; set up bypass for future dkb 1.7a jr ram$sel ; now do normal thing dkb 1.7a ram$check$byte: xra a sta track+1 sta sector lda offset sta track call diskaddr ; set sector and track dcx h ; backup one mov a,l ! out latch1 mov a,h ! out latch2 ret ;********************NEW INIT****************************** ram$sel: ; ..dkb 1.7a lda init$flag ; get init flag ..dkb-3 ora a ; non zero ..dkb-3 cnz init ; go init it ..dkb-3 xra a ; clear flag ..dlb-3 sta init$flag ; so next no initiali ..dkb-3 jmp ram$find$size ; terminate as usaul ..dkb-3 init: push h call ram$find$size ; get size of ramdisk pop h mvi a,0 ; get sector # for initialization sta sector sta track+1 ; lda offset ; get # of system tracks sta track lhld dsksize inx h ; bump one for count ..dkb-3 lda spt+2 ; get shift factor setsize: dad h dcr a jnz setsize ; setup # sectors per disk push h ; ..dkb-3 call prtsiz ; go print size ..dkb-3 pop h ; ..dkb-3 mov c,h ; msb in c ..dkb-3 inr c ; bump one for count ..dkb-3 mov b,l ; and lsb in b for loop ..dkb-3 wrtlop: lxi h,dumsec ; get "E5" dummy sector shld dmaadr push b ; save reg b (sector count) call ram$wrt ; write sector lda sector inr a ; incr sector # cpi 26 ; last sector ? cz inctrk ; yes, bump track sta sector pop b ; restore count djnz wrtlop ; add this here ..dkb-3 dcr c jnz wrtlop ; do all sectors ; djnz wrtlop ; ..dkb-3 lxi h,donms ; finished jmp ?pmsg ; exit thru printmesage ..dkb-3 inctrk: lhld track inx h shld track push h lxi h,backup call ?pmsg pop h call ?pdec ; print track nmbr..dkb-3 xra a ret ; ; backup: db 8,8,8,8,8,0 prtsiz: lxi h,initms ; get sig-ms call ?pmsg ; print i lhld dsksize ; get disk size for printing inx h ; adjust for blksize-1 lda spt+2 ; get block mask sui 3 ; check for single density jz singles ; yes, do single dad h ; double blocksize for 2-density singles: call ?pdec ; setup decimal size lxi h,sizk ; get rest of message call ?pmsg ; print it ret ;********************END NEW INIT************************** rom$init: ret rom$login: xra a ; set rom addr to 0 out rom1 out rom2 in rom0 ; get char in rom cpi 31h ; is it a 31? wbd-4 rz ; yes- return OK jmp errexit ; not there error exit ram$find$size: mvi c,0 ; initialize dubtbl pointer mvi b,30h call ramsiz ; check for 1st board jrz ck2 ; there- try for 2 errexit: pop h ; "call ram$find$size" return address pop h ; "call ipchl" return address 1.7b pop h ; "push h": dph pointer lxi h,0 ; flag invalid drive with hl=0 ret ; return to ?sctrn caller ck2: mvi b,60h ; 2nd board there? call ramsiz jrnz setsiz ; no- set for 1 board inr c ; increment tbl pntr mvi b,0A0h ; and try for 3rd board call ramsiz jrnz setsiz ; no- set for 2 boards inr c ; increment tbl pntr mvi b,0E0h ; and try for 4th board call ramsiz jrnz setsiz ; no- set for 3 boards inr c ; must be 4 boards setsiz: push b ; save c reg wbd-1 mov a,c ; dkb-3 sta nbrds ; save # boards dkb-3 lxi h,dubtbl ; get dubtbl addrs wbd-1 mvi b,0 ; index into table wbd-1 dad b ; by twice value wbd-1 dad b ; in c reg wbd-1 mov a,m ; get the 2 bytes wbd-1 inx h mov h,m mov l,a lxi d,ramdub ; put table data into wbd-1 lxi b,dublength ; disk parameter block wbd-1 ldir xra a pop b ; wbd-1 ret ; return with zero set wbd-1 ramsiz: call boot0 ; determine size of ramdisk in latch0 ; save current data sta savbyt call boot0 mvi a,55h ; test byte out latch0 call boot0 in latch0 ; read back test byte cpi 55h rnz ; wbd-1 call boot0 ; restore data byte lda savbyt out latch0 xra a ; return with zero set wbd-1 ret ; boot0: mvi a,0 out latch1 ; set ramdisk address for 192k mov a,b out latch2 ret ; dubtbl: dw ram1dub dw ram2dub dw ram3dub dw ram4dub ; ram$read: call sethst ; set dma,sector,track,drive call diskaddr ; load address to ram disk mov a,l out latch1 mov a,h out latch2 mvi b,128 ; sector size mvi c,latch0 ; address for data .. dkb lhld dmaadr ; get dma address call read ; go do read wbd-2 push d ; checksum returned in de wbd-2 call chkadr ; set up ramdisk address wbd-2 pop d ; restore checksum wbd-2 in latch0 ; read checksum from ramdisk wbd-2 cmp e ; wbd-2 mov l,a in latch0 ; wbd-2 mov h,a jnz ckserr ; local error msg wbd-2 cmp d ; wbd-2 jnz ckserr ; wbd-2 xra a ; successful cp/m return wbd-2 ret ; wbd-2 ; rom$read: call sethst ; set dma,sector,track,drive call diskaddr ; load address to rom disk mov a,l out rom1 mov a,h out rom2 mvi b,128 ; sector size mvi c,rom0 ; address of rom data ... dkb lhld dmaadr ; get dma address call read ; go read it wbd-3 xra a ; successful cp/m return wbd-3 ret ; wbd-3 ; ram$write: call sethst ; set dma,sector,track,drive ram$wrt: call diskaddr ; load address to ram disk mov a,l out latch1 mov a,h out latch2 mvi b,128 ; sector size mvi c,latch0 ; address for data ... dkb lhld dmaadr ; get dma addr call write ; go do write wbd-2 push d ; checksum returned in de wbd-2 call chkadr ; set up checksum addr in ramdisk pop d ; wbd-2 mov a,e ; wbd-2 out latch0 ; write checksum to ramdisk wbd-2 mov a,d ; wbd-2 out latch0 ; wbd-2 xra a ; no error return wbd-2 ret ; wbd-2 ; chkadr: ; compute and load checksum address lxi h,0 ; start at block 0 wbd-2 lda psh ; size of sector (128*log2) wbd-2 ora a ; wbd-2 jrz chkad1 ; wbd-2 dad h ; correct for 256 bytes/sector wbd-2 chkad1: mvi b,6 ; multiply by 2^6 wbd-2 chkad2: dad h ; wbd-2 djnz chkad2 ; wbd-2 xchg ; put offset in de wbd-2 lhld tempdskaddr ; get track and sector offset wbd-2 dad h ; x2 for 2-byte table wbd-2 mvi b,4 ; divide by 16 and save modulo wbd-2 mvi c,0 ; in reg c wbd-2 chkad3: ; do a 16 bit shift right wbd-2 srlr h ; on reg hl and save remainder wbd-2 rarr l ; in reg c wbd-2 rarr c ; wbd-2 djnz chkad3 ; wbd-2 srlr c ; shift right 4 times wbd-2 srlr c ; to adjust counter wbd-2 srlr c ; wbd-2 srlr c ; wbd-2 dad d ; add track/sector offset wbd-2 mov a,l ; to board offset wbd-2 out latch1 ; put address to ramdisk wbd-2 mov a,h ; wbd-2 out latch2 ; wbd-2 inr c ; allow for c=0 wbd-2 chkad4: dcr c ; wbd-2 jrz chkad5 ; wbd-2 in latch0 ; read ramdisk to point to wbd-2 jmp chkad4 ; checksum wbd-2 chkad5: ret ; wbd-2 rom$write: mvi a,2 ; read only error wbd-3 ret ; wbd-3 cseg ; this must be in common read: di ; wbd-4 push psw ; save a wbd-4 push b ; save byte count wbd-2 push h ; save dma addr wbd-2 lda @dbnk ; out banksel ; set bank for transfer call ?bank ; set bank for transfer inir ; read sector jmp cksum ; wbd-2 write: di ; wbd-4 push psw ; wbd-4 push b ; save byte count wbd-2 push h ; save dma addr wbd-2 lda init$flag ; check init flag wd1.7a ora a jrnz init$wrt ; if so, skip bank switch wd1.7a lda @dbnk ; out banksel ; set bank for transfer call ?bank ; set bank for transfer init$wrt: outir ; write a sector jmp cksum ; wbd-2 cksum: pop h ; restore dma addr wbd-2 pop b ; restore byte count wbd-2 mvi d,0 ; initialize checksum msb wbd-2 mvi a,0 ; initialize checksum lsb wbd-2 cksum2: add m ; wbd-2 jrnc cksum1 ; wbd-2 inr d ; wbd-2 cksum1: inx h ; increment data pointer wbd-2 djnz cksum2 ; loop nr of bytes/sector wbd-2 mov e,a ; return result in de wbd-2 lda @cbnk ; out banksel call ?bank ; set bank pop psw ; wbd-4 ei ; wbd-4 ret ; wbd-2 dseg ; diskaddr: ; compute and load ramdisk address mvi b,26 ; offset for 26 sectors per track lded track ; get number of tracks wbd-2 call multiply lda sector ; get sector number add l mov l,a jnc dskadr1 inr h dskadr1: shld tempdskaddr ; save result for checksum wbd-2 mvi c,3 ; multiply by 8 to get byte offset dskadr3: dad h dcr c jnz dskadr3 ; loop ret ; ckserr: shld hladr sded deadr lhld track ; dkb-1 mov a,h ; get track in a .. dkb-1 ora a ; check for > = 100h dkb-1 jnz ckser1 ; if so, then error exists dkb-1 mov b,l ; else get lsb in b dkb-1 lda offset ; and offset in a dkb-1 cmp b ; and check for match dkb-1 jz ckser1 ; if zero, then bad track dkb-1 jnc syserr ; if less than, then not bad dkb-1 ckser1: ; dkb-1 call ?pderr lxi h,ckms call ?pmsg lhld hladr ; dkb-1 call ?pdec lxi h,ckms1 call ?pmsg lhld deadr ; dkb-1 call ?pdec lxi h,crlf call ?pmsg mvi a,1 ret ; syserr: ; dkb-1 xra a ; system tracks is where checksum is ret ; stored, so return ok if error is here ; ckms: db ', Checksum Error, Read ',0 ckms1: db ', Expected ',0 initms: db 7,10,13,'Initializing RAM-Disk for ',0 sizk: db 'k Storage' crlf: db 10,13,9,' Track 00000',0 donms: db 7,10,13,' **** Initialization Complete ****',10,13,0 nbrds: db 0 ; init$flag: db 0 hladr: dw 0 deadr: dw 0 ; tempdskaddr: ds 2 ; sethst: lhld @dma ; get address for transfer shld dmaadr ; update local pointer lda @rdrv ; get relative unit number sta drive ; save it lda @sect ; get host sector number dcr a ; make it 0 to 25 sta sector ; set local value lhld @trk ; get host track shld track ; set local value ret ; multiply: ; in: de=# of tracks, b=26 (sectors) ; out: hl contains result wbd-2 lxi h,0 ; zero out hl (accumulator) wbd-2 mov a,e ; chk for zero tracks wbd-2 ora d rz ; 0 tracks? return with 0 result mult1: dad d ; add de to hl for b times djnz mult1 ; wbd-2 ret ; done - return to caller wbd-2 ; xdph0: dw ram$write ; address of sector write dw ram$read ; address of sector read dw ram$init ; address of drive login dkb 1.7a dw rom$init ; address of drive init routine dkb 1.7a db 0 ; physical unit number db ram ; controller type rdsd0: dw 0 ; translate table address db 0,0,0,0,0,0,0,0,0 ; bios scratch area db 0 ; media flag dubadr: dw ramdub ; disk parameter block (dpb) dw -2 ; checksum allocated by gencpm dw -2 ; alloc vector allocated by gencpm dw -2,-2,-2 ; dirbcb,dtabcb,hask alloc'd by gencpm db 0 ; hash bank ; xdph1: dw rom$write ; address of sector write dw rom$read ; address of sector read dw rom$login ; address of drive login dw rom$init ; address of drive init routine db 0 ; physical unit number db rom ; controller type rdsd1: dw xstd ; translate table address db 0,0,0,0,0,0,0,0,0 ; bios scratch area db 0 ; media flag dw romdub ; disk parameter block (dpb) dw -2 ; checksum allocated by gencpm dw -2 ; alloc vector allocated by gencpm dw -2,-2,-2 ; dirbcb,dtabcb,hask alloc'd by gencpm db 0 ; hash bank ; cseg ramdub: spt: dw 26 ; spt db 4,15,0 ; blm bls exm dsksize: dw 502 ; dsm dw 255 ; drm dw 0F0h ; alloc vector for directory dw 64 ; checksum size cks offset: dw 5 ; offset for system tracks (off) psh: db 0,0 ; sector size, and shift mask dublength equ $-ramdub dseg ram1dub: dw 26 ; spt db 3,7,0 ; blm bls exm dw 248 ; dsm dw 63 ; drm dw 0C0h ; alloc vector for dirctory dw 16 ; checksum size cks dw 2 ; offset for system tracks (off) db 0,0 ; sector size, and shift mask ; ram2dub: dw 26 ; spt db 4,15,0 ; blm bls exm dw 250 ; dsm dw 127 ; drm dw 0C0h ; alloc vector for dirctory dw 32 ; checksum size cks dw 3 ; offset for system tracks (off) db 0,0 ; sector size, and shift mask ; ram3dub: dw 26 ; spt db 4,15,0 ; blm bls exm dw 376 ; dsm dw 191 ; drm dw 0E0h ; alloc vector for directory dw 48 ; checksum size cks dw 4 ; offset for system tracks (off) db 0,0 ; sector size, and shift mask ; ram4dub: dw 26 ; spt db 4,15,0 ; blm bls exm dw 502 ; dsm dw 255 ; drm dw 0F0h ; alloc vector for directory dw 64 ; checksum size cks dw 5 ; offset for system tracks (off) db 0,0 ; sector size, and shift mask cseg ; romdub: dw 26 ; spt db 3,7,0 ; blm bls exm dw 246 ; dsm dw 63 ; drm dw 0C0h ; alloc vector for dirctory dw 16 ; checksum size cks dw 2 ; offset for system tracks (off) db 0,0 ; sector size, and shift mask dseg xstd: db 1,7,0Dh,13h,19h,05h,0Bh,11h,17h,3,9,0Fh,15h,2 db 8,0Eh,14h,1Ah,6,0Ch,12h,18h,4,0Ah,10h,16h ; ; scratch ram area for bdos use ; dmaadr: ds 2 ; storage for dma address track: ds 2 ; storage for track sector: ds 1 ; storage for current sector drive: ds 1 ; currently selected drive savbyt: ds 1 ; save area for ramsiz wbd-1 dumsec: rept 8 dw 0e5e5h,0e5e5h,0e5e5h,0e5e5h,0e5e5h,0e5e5h,0e5e5h,0e5e5h endm end