; ; title 'C128 external Disk drive support 28 Apr 86' ; ; This program contains the stubs for bringing up the C128 CP/M ; for the first time. ; ; The method used to stub the system I/O is to send the ; operation request to the serial port as a command and ; recieve responce from the serial channel. ; ; The commands supported are: ; ; CMD: 'I' ; input keyboard char ; RSP: xx ; returns keybord char or 00 if none ; ; CMD 'O'xx ; send char xx to display ; RSP: xx ; echo character ; ; CMD: Rttss ; read sector of data adr by track (tt) sector (ss) ; RSP: xx..yy ; returns 128 bytes of data plus a check sum ; ; CMD: Wttssxx..yy ; write sector of data, sent with a check sum ; ; to (xx..yy) adr by track (tt) sector (ss) ; RSP: xx ; xx=00 if no error ; page maclib cpm3 maclib z80 maclib cxequ public ?int65,?in65,?ins65,?out65,?outs65 extrn ?intbd ; Utility routines in standard BIOS extrn ?pmsg ; print message @ up to 00 ; saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status ; ; drive table ; public @dtbl extrn cmdsk0,cmdsk1,cmdsk2,cmdsk3,cmdsk4,RMdsk page ; ; DRVTBL.ASM ; CSEG ; place code in common memory @dtbl: dw cmdsk0 ;* drive A 1541/1571 dw cmdsk1 ;* drive B 1541/1571 dw cmdsk2 ;* drive C 1541/1571 dw cmdsk3 ;* drive D 1541/1571 dw cmdsk4 ;* drive E shares drive A dw 0 ;* drive F dw 0 ;* drive G if EXTSYS dw @fdsd0 ;* drive H (external RS232) else dw 0 ;* drive H endif dw 0 ;* drive I dw 0 ;* drive J dw 0 ;* drive K dw 0 ;* drive L dw RMdsk ;* drive M Memory Disk (RAM disk) dw 0 ;* drive N dw 0 ;* drive O dw 0 ;* drive P if EXTSYS CSEG ; ; Extended Disk Parameter Headers (XPDHs) ; dw fd$write dw fd$read dw fd$login dw fd$init db 0 ; relative drive zero db 0 ; format type byte @fdsd0: dph sk128sssd,dpb$8$sssd ; ; DPB FOR 8 IBM 3740 format ( 243K ) ; dpb$8$sssd: dpb 128,26,77,1024,64,2 sk128sssd: skew 26,6,1 page ; ; send an illegial command, should get a period back, meaning ; that the the command was bad. at this point extrnal system ; is ready to receive a valid command. ; CSEG resync: mvi c,0dh call send$c call get cpi '.' jrnz resync mvi c,'O' call send$c mvi c,07 ; beep the bell call send$c call get ; should be a bell code cpi 07 rz call get jr resync ; ; CXDISK.ASM ; ; ; ; dseg fd$read: mvi a,10 sta error$count ; set retrys to 10 retry$read: lxi h,retry$read push h ; save retry address on the stack mvi a,'R' call set$up$dsk ; send command, track and sector read$loop: call get if banked call put$byte$de$bank ; save byte disk bank mov a,c else mov m,a endif inx h call do$sum jrnz read$loop call get lda check$sum cmp c jrnz dsk$error pop h ; remove retry address xra a ; A=0 (no errors) ; ; fd$init: fd$login: ret ; ; ; if banked cseg put$byte$de$bank: lda force$map ; read current MMU configuration stax d ; force to preconfig reg adr in DE mov m,c ; save C in proper bank sta force$map ; force the old bank back ret endif page ; ; ; dseg dsk$error: call resync lda error$count dcr a sta error$count rnz ; return to retry address inr a ; A=1 if hard error pop h ; remove retry address on error ret error$count: db 0 page ; ; ; dseg fd$write: mvi a,10 sta error$count ; set retrys to 10 retry$write: lxi h,retry$write push h mvi a,'W' call set$up$dsk ; send command, track and sector write$loop: if banked call get$byte$de$bank else mov c,m endif call send$c ; leaves sent char in A inx h call do$sum jrnz write$loop lda check$sum call send$a call get ora a ; A=0 if no errors jrnz dsk$error pop h ; remove error address ret ; A=0 (no errors) if banked cseg get$byte$de$bank: lda force$map ; read current MMU configuration stax d ; set current disk bank (in DE) mov c,m sta force$map ; write current MMU conf back ret endif page ; ; compute check sum and adjust byte count ; dseg do$sum: mov b,a lda check$sum ; get the current sum add b ; add in new byte sta check$sum ; save new sum lda count ; get byte count dcr a ; one less to get sta count ; save for later ret ; zero flag set if DONE check$sum: db 0 count: db 0 ; ; send the command, track and sector to the external system ; set count to 128 bytes, clear the checksum and set HL to ; the DMA address ; set$up$dsk: call send$a ; send the comand lda @trk call send$a ; send the track lda @sect call send$a ; send the sector xra a sta check$sum mvi a,80h sta count ; transfer 128 bytes lhld @dma ; HL = current DMA address if banked lxi d,bank$0 ; start by pointing to bank 0 lda @dbnk ; get the current disk I/O bank ora a ; is it set to bank 0 rz ; yes, return inx d ; no, point to bank 1 endif ret page ;========================================================== ; CHARACTOR INITILIZATION ROUTINES ;========================================================== ; ; ; dseg ; ; set external system com rate to 19.2 K baud ; ?int65: init$ext: lhld usart$adr mov b,h mov c,l inx b inx b ; point to command reg mvi a,cmd$init outp a inx b ; point to control reg mvi a,cntr$init$19200 ; baud rate equ 19200 outp a dcx b ; (02) dcx b ; (01) inp a ; read status dcx b ; (00) inp a ; read hung data ret page ;========================================================== ; CHARACTOR INPUT ROUTINES ;========================================================== ; ; ; dseg ?in65: ╗ characte˛ input call ?ins65 ; check for character adv. jrz ?in65 ; loop if NOT lda key ; get the key code push psw ; save on stack xra a ; clear key sta key pop psw ; recover current key ret page ;========================================================== ; CHARACTER DEVICE INPUT STATUS ;========================================================== ; ; ; dseg ?ins65: ; character input status lda key ; is there already a key ora a jrnz ret$true ; yes, return true mvi a,'I' ; no, test if any typed call send$a call get ; get key ora a ; =0 if none rz ; return character not advaliable sta key ; was one, save in key ?outs65: ret$true: ori 0ffh ret key: db 0 page ;========================================================== ; CHARACTER DEVICE OUTPUT ;========================================================== ; the charactor to be output is in the C register ; ; ; dseg ?out65: ; character output mov a,c push psw mvi a,'O' call send$a pop psw call send$a ; jmp get ; fall thru to GET ;========================================================== ; EXTERNAL DEVICE LOW LEVEL DRIVERS ;========================================================== ; ; ; dseg get: call in$stat jrz get dcx b ; point to data reg (RxD) inp a mov c,a ret ; ; ; send$c: mov a,c send$a: push psw ; save the character to be output send$loop: call out$stat jrz send$loop pop psw dcx b : point to data register (TxD) outp a ret ; ; ; in$stat: lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani rxrdy ret ; ; ; out$stat: lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani txrdy ret else ;========================================================== ; CHARACTOR INITILIZATION ROUTINES ;========================================================== ; ; ; dseg ; ; set com rate to value in ?int$bd ; (may need to change rate if not supported) ?int65: init$ext: if use$6551 ; ; must gate 6551 to user port ; this is done by init'ing the out data to an input ; and then setting DTR ; lxi b,CIA2+data$dir$a inp a ori 100b ; make TxD bit (2) an input outp a endif lhld usart$adr mov b,h mov c,l inx b ; point to status reg outp a ; software reset (wr to stat reg) inx b ; point to Command register mvi a,cmd$init ; set DTR active outp a inx b ; point to Control register lda ?int$bd ; get 6551 baud rate ori 10h ; use baud rate generator outp a ; 1 stop (7=0), 8 bits (65=0) ret page ;========================================================== ; CHARACTOR INPUT ROUTINES ;========================================================== ; ; ; dseg ?in65: ╗ characte˛ input call ?ins65 jrz ?in65 dcx b ; point to data reg inp a ret ;========================================================== ; CHARACTER DEVICE INPUT STATUS ;========================================================== ; ; ; dseg ?ins65: ; character input status lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani rxrdy rz ori -1 ret ;========================================================== ; CHARACTER DEVICE OUTPUT ;========================================================== ; the charactor to be output is in the C register ; ; ; dseg ?out65: ; character output mov a,c push psw call ?outs65 jrz ?out65 pop psw dcx b ; point to data register outp a ret ;========================================================== ; CHARACTER DEVICE OUTPUT STATUS ;========================================================== ; ; ; dseg ?outs65: ; character input status lhld usart$adr mov b,h mov c,l inx b ; point to status register inp a ani txrdy rz ori -1 ret endif end