revnum equ 24 ;Cbios revision number ***************************************************************** * * * The following equates relate the Thinker Toys 2D controller. * * If the controller is non standard (0F800H) only the ORIGIN * * equate need be changed. This version of the Cbios will work * * with 2D controller boards rev 0, 1, 3, 3.1, 4. * * * ***************************************************************** origin equ 0f800h djram equ origin+400h ;Disk Jockey 2D RAM address djcin equ djram+3h ;Disk Jockey 2D character input routine djcout equ djram+6h ;Disk Jockey 2D character output routine djhome equ djram+9h ;Disk Jockey 2D track zero seek djtrk equ djram+0ch ;Disk Jockey 2D track seek routine djsec equ djram+0fh ;Disk Jockey 2D set sector routine djdma equ djram+012h ;Disk Jockey 2D set DMA address djread equ djram+15h ;Disk Jockey 2D read routine djwrite equ djram+18h ;Disk Jockey 2D write routine djsel equ djram+1bh ;Disk Jockey 2D select drive routine djtstat equ djram+21h ;Disk Jockey 2D terminal status routine djstat equ djram+27h ;Disk Jockey 2D status routine djerr equ djram+2ah ;Disk Jockey 2D error, flash led djden equ djram+2dh ;Disk Jockey 2D set density routine djside equ djram+30h ;Disk Jockey 2D set side routine tpa equ 100h ;Transient memory wboot equ 0 ;Warm boot jump address bdos equ 5 ;BDOS entry jump address acr equ 0dh ;A carriage return alf equ 0ah ;A line feed retries equ 20 org 100h lxi sp,stack start lxi d,prompt ;Print prompt message call pbuff getser lxi d,sernum ;Ask about starting serial number call pbuff call readcon call convert ;Try to convert serial number to binary jnc serok lxi d,badser ;Complain about serial number call pbuff jmp getser ; and let him/her guess again serok dcx h shld binser ;Save binary serial number lxi h,ascii+4 ;Last digit of ASCII version of serial dcr m lxi d,source ;Ask for source drive call pbuff call readcon main lhld binser MOV A,H ORA L JZ PRTSER ;If serial #00000 do just once inx h ;Bump the serial number shld binser ; and save it lxi h,ascii+4 mvi b,5 ;Number of digits in serial number inc0 inr m ;Bump ASCII version of serial number mov a,m cpi '9'+1 jc prtser mvi m,'0' ;Handle ASCII carry on increment dcx h dcr b jnz inc0 restart equ $ prtser lxi d,sermsg ;State the we are serializing a disk call pbuff call readcon ; and wait for a return lxi d,lfmsg ;Print a CR/LF call pbuff mvi c,0 ;Select A: drive, track 0 call djsel mvi c,0 ;Select side 0 call djside mvi c,1 ;Select sector 1 call djsec lxi b,ibuff ;Set DMA address call djdma lxi b,retries*100h+1;Retries + sector number onesec push b call djread pop b jnc oneok ;Carry set on error dcr b ;Bump error count jnz onesec lxi d,redaerr ;Tell the poor guy all about it jmp nice ;Print, and restart oneok call djstat ani 0ch ;Mask out sector size bits cpi 0ch ;1024 byte sector only for Decision I's mvi a,3 jz prep0 lxi d,badden ;Weird sizes get error message call pbuff jmp restart prep0 sta newsize ;Save sector size call formt ;Format a track jc restart ;Krash on error lxi d,lfmsg ;Print a CR/LF call pbuff mvi a,-1 ;Initialize the track counter sta trk mvi a,26 ;Number of Sectors Per Track sta spt lxé h,100è ;Differencå betweeî loaä addresó shld posdma ; (sector size) * 2 lxi h,-100h shld negpos lxi h,-0c80h ;25 sectors * 128 bytes/sector shld negdma nxttrk mvi c,0 ;Select drive A: call djsel mvi c,0 ;Side 0 call djside lda trk ;Bump track counter inr a sta trk cz djhome ;If track 0 then home lda trk cpi 77 ;77 tracks on a disk jz complte mov c,a call djtrk ;Step to correct track xra a ;Read sta func lxi h,ibuff ;DMA address call dodisk ;Read from source disk lxi d,redaerr ;Complain if error jnz nice lxi d,astrk ;One snowflake (*) per track call pbuff mvi c,1 ;Select drive B: call djsel mvi c,0 ;Side 0 call djside lda trk ;Check track address ana a cz djhome ;Home if 0 lda trk mov c,a call djtrk ;Seek to track lda trk cpi 0 cz fixccp ;Fix CCP and BDOS serial numbers on track 0 cpi 2 cz fxmovio ;Fix MOVCPM/CCP serial number on track 2 cpi 3 cz fixmov ;Fix MOVCPM/BDOS serial number on track 3 mvi a,1 ;Write function sta func lxi h,ibuff call dodisk ;Write a track lxi d,wrtberr jnz nice ;Handle errors xra a ;Bask to a read function sta func lxi h,obuff call dodisk ;Verify track format lxi d,redberr jnz nice lda trk ana a lxi b,13*128 ;Verify track data jz comp lda newsize ana a lxi b,13*128 ;13*128 for single, 4*1024 for double jz comp lxi b,4*1024 comp lxi h,ibuff ;Actuall track data verify lxi d,obuff cmplop ldax d inx d cmp m inx h jnz verror ldax d inx d cmp m inx h jnz verror dcx b mov a,b ora c jnz cmplop lda trk ana a lxi b,13*128 jz tste5 lda newsize ana a lxi b,13*128 ;13*128 for single, 4*1024 for double jz tste5 lxi b,4*1024 tste5 lxi h,ibuff quest mov a,m inx h cpi 0e5h jnz more mov a,m inx h cpi 0e5h jnz more dcx b mov a,b ora c jnz quest complte lxi d,okmsg call pbuff jmp main nice call pbuff jmp restart more lda newsize ana a jz nxttrk mvi a,8 ;Include this code for double sta spt lxi h,800h shld posdma lxi h,-800h shld negpos lxi h,-1c00h shld negdma jmp nxttrk verror lxi d,vermsg call pbuff jmp restart dodisk mvi a,-1 sta sec lxi d,0 negpos equ $-2 dad d shld newdma onetrk mvi a,0 sec equ $-1 adi 2 sta sec mov c,a mvi a,0 spt equ $-1 adi 2 cmp c rz dcr a cmp c jnz nowrap mvi a,2 sta sec mov c,a lhld newdma lxi d,0 negdma equ $-2 dad d shld newdma nowrap call djsec lxi h,0 newdma equ $-2 lxi d,0 posdma equ $-2 dad d shld newdma mov b,h mov c,l call djdma lxi b,retries*100h+0 trk equ $-2 retry push b mvi a,0 func equ $-1 ana a jz doread call djwrite tsterr pop b jnc onetrk dcr b jnz retry ori 1 ret doread call djread jmp tsterr fixccp lxi d,0528h ;Start of track + 0528h for CCP call fix lxi d,0a00h ;Start of track + 0a00h for BDOS jmp fix fxmovio lxi d,1528h ;Start of track + 1528h for MOVCPM/CCP jmp fix fixmov lxi d,0200h ;Start of track + 0200h for MOVCPM/BDOS fix lxi h,ibuff dad d mvi m,34 inx h mvi m,22 inx h xchg lhld binser xchg mvi m,0 inx h mvi m,0 inx h mov m,d inx h mov m,e lda trk ret convert lxi h,0 lxi d,buffdat lxi b,ascii lda bufflen cpi 5 stc rnz cnvloop lda bufflen dcr a stc cmc rm sta bufflen ldax d inx d cpi '0' rc cpi '9'+1 cmc rc stax b inx b push b sui '0' dad h mov b,h mov c,l dad h dad h dad b mov c,a mvi b,0 dad b pop b jmp cnvloop readcon lxi d,buffmax mvi c,10 jmp bdos pbuff mvi c,9 jmp bdos source db acr,alf db 'Insert source in A, press RETURN: $' prompt db acr,alf db 'Serial program for CP/M Ver. 2.0 ' db 'Rev ' db revnum/10 + '0' db '.' db (revnum mod 10) + '0' db acr, alf db 'This SERIAL.COM program is for Decision I CP/M''s only' db acr, alf db '$' sernum db acr,alf db 'Beginning serial number: $' okmsg db acr,alf db 'Serialization complete.$' sermsg db acr,alf db 'Serializing Disk 34-' ascii db '00000' db acr,alf db 'Insert new disk in Drive B, press RETURN: $' badser db acr,alf db 'Bad serial number, try again.$' badden db acr,alf db 'Bad density on drive A, replace.$' redaerr db acr,alf db 'Read error on drive A, replace.$' redberr db acr,alf db 'Read error on drive B, replace.$' wrtberr db acr,alf db 'Write error on drive B, replace.$' vermsg db acr,alf db 'Verification error on drive B, replace: $' lfmsg db acr,alf,'$' astrk db '*$' typemsg db acr,alf db 'Disk Jockey type ? (1 = 2D model B, 2 = 2DIO): $' binser dw 0 buffmax db 10 bufflen db 0 buffdat ds 10 DISKIO EQU ORIGIN+3f8h DATREG EQU DISKIO+7 DRVSEL EQU DISKIO+1 CSTALL EQU DISKIO+3 CMDREG EQU DISKIO+4 SBEGIN EQU origin+3deh RAMINS EQU origin+7e2h DSIDE EQU 10Q UNLOADB EQU 17Q WTCMD EQU 364Q SICMD EQU 131Q IMMIRQ EQU 320Q UNLOADA EQU 30Q RESTOR EQU 11Q INDEX EQU 20Q TRKZRO EQU 4 intrqa equ 1 intrqb equ 4 lhsdenb equ 90dh lhddenb equ 80ch lhsdena equ 111h lhddena equ 10h formt LHLD ORIGIN+7 ;adjust INX H ; the MOV A,M ; calling LXI H,STDVSL+1 ; routines LXI D,4 ; for MOV M,A ; different XRI 3 ; versions DAD D ; of the MOV M,A ; disk DAD D ; jockey MOV M,A ; controller LDA DRVNO ;get the drive no MOV C,A MVI A,177Q ;drive select bits QLOOP RLC ;rotate select bits DCR C ; to proper drive JP QLOOP ; position ani 3fh STA SELECT ;save for TRACK routine call stdvsl call model lxi b,lhsdena jz prep lxi b,lhsdenb prep mov a,b call stbits mov a,c call stbits lxi h,cmdreg mvi m,immirq mvi a,40h wirqd dcr a jnz wirqd mov a,m rar jc notrdy ral ral jc notrdy lxi d,wmessg ral jc notrdyx LXI D,0 call gtindx IXLOOP call gtstat ani index xra b JNZ dorest DCX D MOV A,D ORA E JNZ IXLOOP NOTRDY LXI d,RMESSG ;not ready message notrdyx xchg LXI d,AMESSG ;drive message CALL SENDMP ;send error message call unload stc ret dorest MVI M,RESTOR wrstrs mov a,m rar jnc wrstrs wrstrd MOV A,M rar jc wrstrd MOV A,M ANI TRKZRO JZ NOTRDY LXI B,SDLIST LXI H,DLIST CALL OVLAY LXI B,L128 LXI H,SLIST CALL OVLAY mvi a,'*' call pchar CALL INDEXP MVI H,0 CALL TRACK LXI D,TABLE lda newsize add a jz findix mov l,a mvi h,0 DAD D MOV C,M INX H MOV B,M LXI H,SLIST CALL OVLAY LXI B,DDLIST LXI H,DLIST CALL OVLAY call model lxi b,lhddena jz loadd lxi b,lhddenb loadd mov a,b call stbits mov a,c call stbits FINDIX CALL INDEXP MVI H,1 TKSTEP mvi a,'*' call pchar LXI D,CMDREG MVI A,SICMD STAX D WSICMS LDAX D RAR JNC WSICMS WSICMD LDAX D RAR JC WSICMD CALL TRACK MOV H,D INR H MVI A,77 CMP H JNZ TKSTEP call unload ora a ret SENDMP PUSH h ;save second half CALL pbuff ;send first half LDA LETTER ;print the CALL pchar ; letter POP d ;send the second jmp pbuff rbuff lxi d,inbufx mvi c,10 call bdos lda inbufx+1 ana a mvi a,acr rz lda inbuf cpi 'a' rc cpi 'z'+1 rnc sui 40q ret pchar push h push b push d push psw mov e,a mvi c,2 call bdos pop psw pop d pop b pop h ret inbufx db 10,0 inbuf db 0,0,0,0,0,0,0,0,0,0 STDVSL STA DISKIO+1 RET STBITS STA DISKIO+2 RET GTSTAT LDA DISKIO+2 RET model lda diskio-4 cpi (ret) ret unload call model mvi a,unloada jz stbits mvi a,unloadb jmp stbits gtindx call model mvi b,0 rz mvi b,index ret INDEXP call gtindx windxh call gtstat ANI INDEX xra b JZ windxh windxl call gtstat ani index xra b jnz windxl ret indxw call gtindx jmp windxl TABLE DW L128 DW L256 DW L512 DW L1024 TRACK lda select call stdvsl XRA A STA SIDENO CALL WTRACK call gtstat ANI DSIDE RNZ INR A STA SIDENO LDA SELECT ANI 357Q call stdvsl WIL call indxw XCHG WTRACK call model jz fmt MVI A,22Q ;store stax d STA RAMINS ; instruction STA CSTALL ;ready stall fmt LXI D,DATREG ;1791 data reg MVI L,1 ;initialize sector reg LXI B,4e50H ;data & count OVLD1 EQU $-2 MVI A,WTCMD ;issue a write STA CMDREG ; track command jz wtl1a lxi b,4e4eh ovldx equ $-2 MOV A,B ;write first STAX D ; data byte CALL SBEGIN ;second byte wtl1a XCHG ;adjust the registers WTL1 MOV M,B ;index mark DCR C ; preamble JNZ WTL1 ; field LXI B,0CH ;data & count OVLD2 EQU $-2 WTL2 MOV M,B ;index mark DCR C ; zero leader JNZ WTL2 ; field OVLD3 MVI M,0F6H ;special double MVI M,0F6H ; density clock MVI M,0F6H ; and data mark WTL3 MVI M,0FCH ;index mark LXI B,4E32H ;data & count OVLD4 EQU $-2 WTL4 MOV M,B ;sector mark DCR C ; preamble JNZ WTL4 ; field SLOOP LXI B,0CH ;data & count OVLD5 EQU $-2 WTL5 MOV M,B ;sector mark DCR C ; zero leader JNZ WTL5 ; field OVLD6 MVI M,0F5H ;special double MVI M,0F5H ; density clock MVI M,0F5H ; and data mark WTL6 MVI M,0FEH ;sector mark MOV M,D ;track number MVI M,0 ;side number SIDENO EQU $-1 MOV M,E ;sector number MVI M,1 ;sector length OVLS1 EQU $-1 MVI M,0F7H ;crc data bytes INR E ;increment sector LXI B,4E16H ;data & count OVLD7 EQU $-2 WTL7 MOV M,B ;sector mark DCR C ; postamble JNZ WTL7 ; field LXI B,0CH ;data & count OVLD8 EQU $-2 WTL8 MOV M,B ;data mark DCR C ; zero leader JNZ WTL8 ; field OVLD9 MVI M,0F5H ;special double MVI M,0F5H ; density clock MVI M,0F5H ; and data mark WTL9 MVI M,0FBH ;data mark LXI B,0e540H ;data & count OVLS2 EQU $-2 WTL10 MOV M,B ;write first DCR C ; quarter of JNZ WTL10 ; sector data MVI C,40H ;count OVLS3 EQU $-1 WTL11 MOV M,B ;write second DCR C ; quarter of JNZ WTL11 ; sector data MVI C,40H ;count OVLS4 EQU $-1 WTL12 MOV M,B ;write third DCR C ; quarter of JNZ WTL12 ; sector data MVI C,40H ;count OVLS5 EQU $-1 WTL13 MOV M,B ;write fourth DCR C ; quarter of JNZ WTL13 ; sector data MVI M,0F7H ;crc data bytes MVI A,27 ;last sector + 1 OVLS6 EQU $-1 LXI B,4E36H ;count & data OVLS7 EQU $-2 WTL14 MOV M,B ;data DCR C ; postamble JNZ WTL14 ; field CMP E ;last sector test JNZ SLOOP WTL15 MOV M,B ;fill data DCR C ; to index hole JNZ WTL15 WTL16 MOV M,B ;fill data DCR C ; to index hole JNZ WTL16 WTL17 MOV M,B ;fill data DCR C ; to index hole JNZ WTL17 RET OVLAY MOV A,M ;length of list PUSH H ;save list ptr LXI H,WTRACK ;overlay area XTHL ; recover pointer MVI D,0 OVLAY1 INX H ;increment pointer MOV E,M ;get offset XTHL ;exchange pointers DAD D ;add the offset PUSH PSW ;save length count LDAX B ;get replacement data MOV M,A ;do the replacement INX B ;next replacement data POP PSW ;recover length count DCR A ;decrement XTHL ;exchange pointers JNZ OVLAY1 POP H ;adjust stack RET * The lists below represents the distances * between successive locations of the WTRACK * routine that are to be overlaid in order * that the same routine will serve to format * different sized and density diskette * sector formats DLIST DB 20 ;length of list DB OVLD1-WTRACK DB 1 db ovldx-ovld1-1 db 1 DB OVLD2-ovldx-1 DB OVLD3-OVLD2 DB 1 DB 1 DB OVLD4-OVLD3-2 DB 1 DB OVLD5-OVLD4-1 DB OVLD6-OVLD5 DB 1 DB 1 DB OVLD7-OVLD6-2 DB 1 DB OVLD8-OVLD7-1 DB OVLD9-OVLD8 DB 1 DB 1 SLIST DB 9 ;list length DB OVLS1-WTRACK DB OVLS2-OVLS1 DB 1 DB OVLS3-OVLS2-1 DB OVLS4-OVLS3 DB OVLS5-OVLS4 DB OVLS6-OVLS5 DB OVLS7-OVLS6 DB 1 * Overlay data for single density * formatted diskettes SDLIST DW 0FF28H dw 0ff26h DB 6 JMP WTL3 DW 0FF1AH DB 6 JMP WTL6 DW 0FF0BH DB 6 JMP WTL9 * Overlay data for double density * formatted diskettes DDLIST DW 4E50H dw 4e4eh DB 0CH MVI M,0F6H DB 36H DW 4E32H DB 0CH MVI M,0F5H DB 36H DW 4E16H DB 0CH MVI M,0F5H DB 36H * Overlay data for single density * 26 sectors/track 128 byte sectors L128 DB 0 DW 0e520H DB 20H DB 20H DB 20H DB 27 DW 0FF1BH * Overlay data for double density * 26 sectors/track 256 byte sectors L256 DB 1 DW 0e540H DB 40H DB 40H DB 40H DB 27 DW 4E36H * Overlay data for double density * 15 sectors/track 512 byte sectors L512 DB 2 DW 0e580H DB 80H DB 80H DB 80H DB 16 DW 4E6AH * Overlay data for double density * 8 sectors/track 1024 byte sectors L1024 DB 3 DW 0e500H DB 0 DB 0 DB 0 DB 9 DW 4E74H AMESSG db acr,alf db 'Drive $' RMESSG db ' Is Not Ready.$' WMESSG db ' Is Write Protected.$' acralf db acr,alf,'$' drvno db 1 letter db 'B' select db 0 newsize db 0 ;0 for single, 3 for double ibuff ds 8*1024 obuff ds 8*1024 ds 50 stack equ $ end