.TITLE KERMIT-65 Super serial com card - interupt driven .SBTTL 6502 version - Ted Medin ; Version 1.0 ; Warning interupts must be allowed by card. ; This means sw2-6 MUST be on. ; Based on the KERMIT Protocol. ; $Header: appssc.m65,v 1.15 90/10/15 14:27:07 medin Locked $ .SBTTL Define start address for assembly .=$1003 ;[39] Start assembly here debug = 0 ;[1] debug flag - when 0 will not add debug code .SBTTL Revision History ; ; Edit # Description ; ------ ----------- ; .ifne 0 ; get around the revisions ; DONT FORGET TO UPDATE THE VERSION ;$Log: appssc.m65,v $ Revision 1.15 90/10/15 14:27:07 medin new org of $7f00 for 3.87 version 1.15 ;Revision 1.14 88/12/22 09:13:22 medin ;verison 1.14 changes for time count, input buffer now $900 and ;it now drops line via dtr. ;Revision 1.13 88/08/16 16:24:17 medin ;fix break so it doesnt drop dtr ;Revision 1.12 88/04/27 18:11:45 medin ;Shut off interupts when exiting kermit ;Revision 1.11 88/01/15 08:40:25 medin ;New origin for 3.81 ;Revision 1.10 87/12/10 10:38:18 medin ;Polish code thats all. ;Revision 1.9 87/06/29 09:51:39 medin ; Change org to work with 3.78 & change wait rtn to handle apple rom rtn ;Revision 1.8 87/05/13 18:12:38 medin ; Change org to correspond with 3.76 ;Revision 1.7 87/02/20 23:18:59 medin ; Put version number in the herald which is displayed by the main ;routine. Thanks to Rhoda for that idea. ;Revision 1.6 87/02/17 08:39:23 medin ; Clean up code for //c interupts. Debug turned off. ;Revision 1.5 87/01/28 08:24:38 medin ;Redo the driver so that the //c will operate correctly. The output ;interupt is always left on thus the //c will give the driver bith ;interupts without any special memory locations. ;Revision 1.4 87/01/08 11:39:41 medin ;Paul Close's changes to allow the super serial with interupts to ;work on a //c. Some slight changes to lock out interupts in critical ;phases. ;Revision 1.3 86/12/09 13:22:13 medin ; Slight change to the initialization for the //e+ & //c. ;The stack would get corrupted in case there were multiple interupts ;and we had to pass an interupt to the next requester. ; ;Revision 1.2 86/10/31 10:30:13 medin ; Add debug code which may be optionaly generated. ;Change the flow control commands to wait till the xon/xoff actually ;is sent down the line. ; ;Revision 1.1 86/10/28 10:20:03 medin ;Initial revision .endc ; ; ; Vector for com cards starts here ; location $1003 for data ; location $1020 for routine jumps ; location $1040 for main routines ; sscdbd: .blkb 1 ;[54]contains baud index(ala super serial card) used by init ; 6 - 300 baud ; 7 - 600 ; etc .blkb 1 ; crdnam: .word herld ;[54] null terminated string of who we are kersli: .blkb 1 ;[54] com slot $n0 kerins: .blkb 1 ;[54] force initialization flag-when 0 endker: .blkb 2 ;[54] address of end of main kermit flowfg: .blkb 1 ;[57] flow flag for xon/xoff controll b7=1 yes tl0end .word endcom ;[1.11] end of this routine timect .blkb 1 ;[1.14] time constant for rom wait rtn .=sscdbd+29 ;[54] future expansion tlinit: jmp tl2int ;[54] initialize com card tl0cmd: jmp tl2cmd ;[54] command in A reg ; ;[54] 0 - hang up ;[54] $0b - set baud ;[54] $0c - set break on the line ;[57] $91 - turn remote on (xon) ;[57] $93 - turn remote off(xoff) ; ;[54] routine will return false(0) if unable tl0cp: jmp tl2cp ;[54] check for input ch ready-0 false tl0gpc: jmp tl2gpc ;[54] get input ch tl0ppc: jmp tl2ppc ;[54] put output character tl0exi: jmp tl2exi ;[54] reset card and restore initialized .=sscdbd+29+32 ;[54] futures ;[1.9]wait: .blkb 3 ;[54] wait routine-a reg contains milliseconds wait: .blkb 3 ;[1.9] wait routine-use rom wait 220=125ms 25=2ms prstr: .blkb 3 ;[54] print string x=lsb,y=msb x&y->null terminated string rdkey: .blkb 3 ;[54] read keyboard prcrlf: .blkb 3 ;[54] print cr and lf telcnc: .blkb 3 ;[54] check for keyboard character telspa: .blkb 3 ;[57] set character parity prbyte = $fdda ; Routine - Print A-reg as 2 hex nibbles .=$7f00 ;[1.15][1.11][1.9][1.8] place to start com card assembly start = . ;need a label at begining kr2pch = $c088 ;[22] Port character base (Super Serial card) kr2pst = $c089 ;[22] Port strobe base (Super Serial card) kr2pcr = $c08a ;[41] Base for prot control register (SSC) kr2pcc = $c08b ;[47] Com control mncinb = $18 ;[47] Control port init(8 bit,no par,1-stop,1200 baud) mnminb = $5 ;[51] Master port init(DTR, IRQ interups) & output interupts mnint = 1 ;[1.14] input interupt only mssinb = $8 ;[51] status bit for input ready mssoub = $10 ; status bit for output ready mssodb = 4 ;[1.8] overrun detected bit =1 then yes moutb = $c ;[51] mask for the output bits of command moutnt = $4 ;[51] command to start output with interupts true = 1 ; a true response false = 0 ; a false " inptr .byte 0 ;[51] input q pointer pinptr .byte 0 ;[51] p " outptr .byte 0 ;[51] output q pointer poutpt .byte 0 ;[51] p " hdirq .word ;[51] hold area for dos IRQ xon: .byte 0 ;[57] flow controll xoff: .byte 0 ;[57] " kwrk01 .byte 0 ;[1.14] .ifne debug ;[1] conditional assembly xofcnt .byte 0 ;count of times buffer overran cixon .byte 0 ;[1] count of input xon request cixoff .byte 0 ;[1] " xoff " cinixn .byte 0 ; count of input no interupt xon cinixf .byte 0 ; " xoff coxon .byte 0 ;[1] count of ouput xon requests coxoff .byte 0 ;[1] " xoff " caixon .byte 0 ;[1] count of actual input xon sent caixof .byte 0 ;[1] " xoff " .endc ;[1] hxon = $91 ;^Q with high bit on hxoff = $93 ;^S " null = 0 ;null com character ctrlq = $11 ;xon ^Q ctrls = $13 ;xoff ^S irqsva = $45 ;place dos saves a reg dirq = $3fe ;[51] interupt address tcps = $4f8 ; //c port status + slot sscstp = $578 ;[47] +slot,bit 7 on turns off commands to ssc herld nasc 1 ;tell who we are bad nasc 1 bcom .byte '< nasc <- BAD COM CMD> 1 ; ; Super Serial Card I/O Device support - These routines support the ; Apple Super Serial Card. ; tl2nts: pla ;[51] restore x tax ;[51] jmp (hdirq) ;[51] and pass it on sans a reg tl2rpt: ;[51] a is already saved in irqsva txa ;[51] save x pha ;[51] tl2rpe ;[67] enhanced // has all regs saved lda kr2pst ;[51] get status bpl tl2nts ;[51] not our interupt .ifne debug ;[1.8] pha ;[1.8] and #mssodb ;[1.8] overrun detected? beq .+3 ;[1.8] no brk ;[1.8] yes cataclismic but it does the job pla ;[1.8] restore input ch .endc ;[1.8] and #mssinb ;[51] look at input bit,since output may be stalled bne tl2inp ;[51] this is input ready tl2out: bit flowfg ;[57] is flow controll on? bpl tl2xfs ;[57] no bvs tl2jcm ;[59] yes, is output ctlr S on?, yes lda xoff ;[57] have we given the ^S ? beq tl2ou0 ;[57] maybe lda xon ;[57] yes bne tl2xfs ;[57] is it time to give the xoff ? .ifne debug ;[1] inc caixof ;[1] bump count of actual input xoffs given .endc ;[1] lda #ctrls ;[57] yes sta xon ;[57] tatle ;[1.14] jmp tl2ou2 ;[1][57] always jump bne tl2ou2 ;[1.14] always jump tl2ou0: lda xon ;[57] how about giving the xon ? beq tl2xfs ;[57] no .ifne debug ;[1] inc caixon ;[1] bump count of actual input xons given .endc ;[1] lda #0 ;[57] turn off xoff sta xoff ;[57] sta xon ;[57] lda #ctrlq ;[57] now for the xon tl2ou2: jsr telspa ;[57] set parity correctly x reg clobbered tl2oup sta kr2pch ;[57] stop this flood tl2jcm jmp tl2com ; thats all tl2xfs lda outptr ;[51] see if any to output cmp poutpt ;[51] ;[1.14] beq tl2noo ;[51] no more to output beq tl2ou7 ;[1.14] no more to output inc poutpt ;tell we have output one cmp poutpt ; now cmp ;[1.14] beq tl2com ; thats all beq tl2ou7 ;[1.14] thats all ldx poutpt ;[51] pointer to next ch to output lda outbuf,x ;[51] get next ch tl2rpp sta kr2pch ;[51] give it to card jmp tl2com ;[51] common return tl2ou7 jsr tl2noi ;[1.14] turn off output jmp tl2noo ;[1.14] tl2inp: lda kr2pch ;[51] we have an input character ldx pinptr ;[51] pointer to next input character store ;[1.14] this is where we store the input chs sta inbuf,x ;[51] save ch ;[1.14] inc pinptr ;[51] ready for next input bit flowfg ;[57] are we flow controll bpl tl2icm ;[57] no we may overun the buffers ; bvc tl2in2 ;[59] are we already stoped?, yes ;[1.14] lda inbuf,x ;[59] is host telling us stop ? bit doesnt des a reg and #$7f ;[59] ignore parity cmp #ctrlq ;[59] do we have a continue bne tl2in2 ;[59] no lda #$bf ;[59] yes, now turn on flow and flowfg ;[59] sta flowfg ;[59] jsr tl2suo ;[1.14] start up output .ifne debug ;[1] inc coxon ;[1] bump count of output xons given .endc ;[1] ;[1.14] dec pinptr ;[59] and ignore this character ;[1.14] jmp tl2icm ;[59] and carry on jmp tl2noo ;[1.14] skip the increment tl2in2 cmp #ctrls ;[59] do we have a stop? bne tl2in4 ;[59] .ifne debug ;[1] inc coxoff ;[1] bump count of output xoffs given .endc ;[1] lda #$40 ;[59] yes tell all ora flowfg ;[59] would you believe the remote sta flowfg ;[59] has asked us to stop! jsr tl2suo ;[1.14] start up output ;[1.14] dec pinptr ;[59] ignore this character ;[1.14] jmp tl2icm ;[1] thats all jmp tl2noo ;[1.14] skip the increment tl2in4 ;[59] place to hang ones hat ;[1.14] lda xoff ;[57] have we already asked for ^S ? ;[1.14] bne tl2icm ;[57] yes no need for another ;[1.14] txa ;[59] lets try stoping when half full ;[1.14] clc ;[59] ;[1.8] adc #7 ;[1] ;[1.14] adc #128 ;[1.8] ;[1.14] cmp inptr ;[59] are we filling up ? ;[1.14] bne tl2icm ;[57] no ;[1.14] inc xoff ;[57] turn on xoff(non 0) ;[1.14] .ifne debug ;[1.14] inc xofcnt ;just for debug ;[1.14] .endc tl2icm inc pinptr ;[1.14] now bump the ptr bne tl2noo ;[1.14] thats all ldx store+2 ;[1.14] now for the msb inx ;[1.14] cpx #outbuf^ ;[1.14] too far? bne tl2ic0 ;[1.14] no ldx #inbuf^ ;[1.14] yes tl2ic0 stx store+2 ;[1.14] update the msb tl2noo tl2xor tl2com: pla ;[51] get x tax ;[51] tl2eac lda irqsva ;[51] get a tl2rti rti ;[51] return from interupt tl2noi lda #mnint ; input interupts only tl2no7 sta kr2pcr ; give the command rts ; tl2suo lda #mnminb ; both interupts bne tl2no7 ; common code tl2int: sei ; lock out interupts may be required for the //c ;[1.14] lda hdirq ;see if we already saved ;[1.14] bne init0 ;yes lda hdirq+1 ;maybe bne init0 ;sure thing lda dirq ;[51] save dos IR for exit sta hdirq ;[51] lda dirq+1 ;[51] sta hdirq+1 ;[51] lda #start^ cmp endker+1 ;are we loaded above main beq dontno ;cant tell yet bcc trble ;yes we are in trouble bcs setnm ;ok dontno lda #start\ ;well lets check 16 bits cmp endker ;[1.14] beq setnm ;whee just exactly right bcs setnm ;ok trble ldx #bad\ ;got to tell someone ldy #bad^ jsr tl2prn ;print the message setnm: init0: lda kerins ;[47] initialize slot beq init1 cli ;[47] already initialized return rts ; apple machine id ;rom--> $fbb3 $fbc0 ; II $38 ; II+ $ea ; //e $06 $ea ; //e+ $e0 enhanced ; //c $06 $00 ;prodos--> $bf98 ; II,II+,//e bit 3 = 0 ; others bit 3 = 1 ; //c bits 7,6 = 10 ;setc ldx #tecome-tecoms ; size of the end of interupt ;setcl lda tecoms-1,x ; move to the end ; sta tl2com-1,x ; dex ; are we thru ; bne setcl ; no ; lda kersli ; change from $n0 -> $0n ; lsr a ; lsr a ; lsr a ; lsr a ; sta tecome+1 ; make it short ; ldx #terpte-tecome ; size of start of interupt ;setcl1 lda tecome-1,x ; move to the start ; sta tl2c-1,x ; dex ; thru ? ; bne setcl1 ; no ; lda #tl2c\ ; now for the interupt vector ; sta dirq ; lda #tl2c^ ; jmp seten1 ; now for the common code setc ;[1.14] lda #$60 ;[1.14] its a rts sta tl2suo ;[1.14] ignore this for //c sta tl2noi ;[1.14] bne setenh ;[1.14] init1 lda $fbc0 beq setc ; this is a //c cmp #$e0 ; is this an enhanced 2e? bne init3 ; no ;[1.14]setc setenh lda tl2rti ; yes sta tl2com lda #tl2rpe\ ;[67][51] sta dirq ;[67][51] setup inturpt address lda #tl2rpe^ ;[67][51] seten1 sta dirq+1 ;[67][51] ldx #0 ; now set the stack straight seten2 lda tl2nts+2,x ; in case its not our interupt sta tl2nts,x inx cpx #3 ; are we thru? bne seten2 ; no ldx #0 ; now set up the ram banks for interupts bit $c011 bmi .+4 ;hate to do this ldx #8 bit $c012 bpl .+4 ;ssigh! inx inx bit $c081 bit $c081 phx ;save the current state for later ; .byte $da lda $c016 ;how about it asl a ldy #1 tl2ilp lda $fffe,y sta $c009 ;set alt card sta $fffe,y sta $c008 ;now for main ram sta $fffe,y dey bpl tl2ilp bcc .+5 ;have we switch out the wrong one? sta $c009 ;yes plx ; .byte $fa bit $c081,x ; .byte $3c,$81,$c0 bit $c081,x ; .byte $3c,$81,$c0 jmp init4 ;[67] init3 lda #tl2rpt\ ;[67][51] sta dirq ;[67][51] setup inturpt address lda #tl2rpt^ ;[67][51] sta dirq+1 ;[67][51] init4 ;[67] lda #0 ;[51] clear pointers etc sta inptr ;[51] sta pinptr ;[51] sta outptr ;[51] sta poutpt ;[51] lda #inbuf^ ;[1.14] and the msb also sta store+2 ;[1.14] sta get+2 ;[1.14] ldx kersli ;[47] get slot number stx kerins ;[67] tell weve been here clc ;[1.14] lda status lda #kr2pst\ ;[1.14] easy way - status adc kersli ; calculate proper address for status sta tl2rpe+1 ; and set interupt rtn sta cwsou1+1 ; [75] this was a tough bug to find clc ;[1.14] lda getput lda #kr2pch\ ;[1.14] data adc kersli ; calulate proper address for ld & st sta tl2rpp+1 ; and set interupt rtn sta tl2inp+1 sta tl2oup+1 sta cwsou2+1 ;[75] tough to find sta tl2pp7+1 ;[1.14] lda #kr2pcr\ ;[1.14] command clc ;[1.14] adc kersli ;[1.14] sta tl2no7+1 ;[1.14] lda #mnminb ;[47] Master port init ;[1.14] sta kr2pst,x ;[47] Com port status sta kr2pcr,x ;[47] Com master port lda #mncinb ;[47] Control port init and #$f0 ;[47] drop baud ora sscdbd ;[47] and add default baud sta kr2pcc,x ;[47] tl2prr: cli ;[51] allow the interurpts to happen rts ;[22] Return ;[1.14]status .word kr2pst ; status port for ssc ;[1.14]getput .word kr2pch ; read write port for ssc tl2cp: sei ;[51] lockout inturpts lda inptr ;[51] check input for chs cmp pinptr ;[51] bne tl2cp3 ;[1.14] how about msb, no lda store+2 ;[1.14] yes check that also cmp get+2 ;[1.14] tl2cp3 ;[1.14] cli ;[51] allow interupts rts ;[22] ... tl2gpc: sei ;[51] lockout interupts ldx inptr ;[51] get input character get ;[1.14] lda inbuf,x ;[51] inc inptr ;[51] bump in pointer bne tl2gp0 ;[1.14] ldy get+2 ;[1.14] bump msb also iny ;[1.14] cpy #outbuf^ ;[1.14] too far? bne tl2gp7 ;[1.14] no ldy #inbuf^ ;[1.14] yes, circle those wagons tl2gp7 sty get+2 ;[1.14] msb ;[1.14] ldy xon ;[57] are we flow controlling ? ;[1.14] beq tl2gp0 ;[57] no ;[1.14] inx ;[57] ;[1.14] inx ;[57] ;[1.14] inx ;[57] ;[1.14] cpx pinptr ;[57] have we about caught up ? ;[1.14] bne tl2gp0 ;[57] no ;[1.14] pha ;[1.8] ;[1.14] lda #ctrlq ;[1.14] bug pure and simple ;[1.14] jsr cwsout ;[1.8] ;[1.14] beq tl2gp4 ;[1.8] depend on acc of 0 ;[1.14] lda #0 ;[1.8] ;[1.14] sta xon ;[1.8] ;[1.14]tl2gp4 sta xoff ;[1.8] ;[1.14] pla ;[1.8] ; pha ;[57] save ch ;[1.8] ldy #0 ;[57] turn off xon ;[1.8] sty xoff ;[57] ; pla ;[57] restore ch tl2gp0: cli ;[51] allow interupts tl2rtc: rts ;[22] and return tl2ppc: ;[22] Hold the byte to send sei ;[51] lockout interupts ldx outptr ;[51] get output pointer sta outbuf,x ;[51] save in buffer for interupt cpx poutpt ; has output stalled ? bne tl2pp2 ; no were still busy outputing ;[1.14] ldx kersli ; get slot ;[1.14] sta kr2pch,x ; and give ssc the ch tl2pp7 sta kr2pch ;[1.14] jsr tl2suo ;[1.14] start up output tl2pp2 inc outptr ;[51] ready for next output cli ;[51] allow interupts rts ;[22] and return tl2exi: sei ;lockout interupts ;[1.10] lda hdirq ;have we alredy done this? ;[1.10] bne exit0 ;nope lda hdirq+1 ;maybe beq exit9 ;definitly exit0: lda hdirq ;[51] restore dos IRQ address sta dirq ;[51] lda hdirq+1 ;[51] sta dirq+1 ;[51] lda #0 ;tell we did this ;[1.10] sta hdirq sta hdirq+1 ldx kersli ;[47] get slot number sta kr2pst,x ;shut it down sta kr2pcr,x ;[1.12]exit9: cli ;allow the interupts exit9: ;[1.12]cli ;allow the interupts rts cwsout ;ldx kersli ; see if we can start up output tax ; save the output ch cwsou1 lda kr2pst ; get the status and #mssoub ; is the output bit 1? beq cwsou3 ; no sigh! txa ; get the ch to output and #$7f ; drop parity jsr telspa ; set parity correctly x reg clobbered cwsou2 sta kr2pch ; send the ch jsr tl2suo ;[1.14] lda #true ; say we did it cwsou3 rts ; bye tl2cmd: ;find out what command ;[1.14] beq tl2rts ;its drop line and we cant beq tl2exi ;[1.14]its drop line cmp #$0c beq break ;its a break command cmp #$0b beq baud ;its a set baud command cmp #hxon beq txon ;its a turn xon cmp #hxoff beq txoff ;its a turn xoff jsr prbyte ;print command ldx #bcom\ ;and tell all ldy #bcom^ tl2prn jsr prstr jsr prcrlf tl2fls: ;a false return tl2rts: ;tell that we cant lda #0 ;unknown command rts ;return txon: ;bit flowfg ;do we have flow control ; bpl tl2fls ;no can do sei ;protect ourselves from interupts .ifne debug ;[1] inc cixon ;[1] bump count of xon requests .endc ;[1] jsr cwsout ; can we start up output? beq txon3 ; no do the interupt thing lda #0 ; yes, tell its all done sta xoff sta xon .ifne debug ;[1] inc cinixn ;[1] bump count of xon requests without interupts .endc ;[1] lda #true ; tell its ok cli ; allow interupts rts ; thats all txon3 ; do the interupt flow control lda #0 sta xoff ;tell interupt to start up cli ltxon lda xon ;[1] got to wait for ch to be sent bne ltxon ;[1] its called true syncronization lda #true ;give a true return rts txoff: ;bit flowfg ;do we have flow control ? ; bpl tl2fls ;no sei .ifne debug ;[1] inc cixoff ;[1] bump count of xoff requests .endc ;[1] jsr cwsout ; can we send output beq txoff3 ; no sigh! .ifne debug ;[1] inc cinixf ;[1] bump count of xoff requests without interupt .endc ;[1] lda #true ; just in case we have to xon via interupts sta xon sta xoff cli ; allow interupts rts txoff3 ; do it durring interupt lda #true ;we need xoff sta xoff ;this also gives a true return cli ltxoff lda xon ;[1] wait for it to be sent beq ltxoff ;[1] are we syncronized? no rts baud: ldx kersli ;[47] get slot number sei ;protect ourselves lda kr2pcc,x ;[47] get com control and #$f0 ;[47] and clear baud ora sscdbd ;[47] enter sta kr2pcc,x ;[47] and set new baud rate cli ; now its ok rts ;return true(non 0) break: sei ;lock out interupts ldy kersli ;[47] ss card routine is not on ;[1.13] lda #$c ;[47] lda kr2pcr,y ;[1.13] get current command ora #$c ;[1.13] now for the break sta kr2pcr,y ;[47] start the break ;[1.9] lda #233 ;[47] for 233 millseconds ;[1.9] jsr wait ;[47] the y reg is not clobered ;[1.14] lda #220 ;[1.9] wait 125 ms lda #233 ;[1.9] wait 233 ms sta kwrk01 ;[1.14] break3 lda timect ;[1.14] 1 ms at a time jsr wait ;[1.9] only the a reg is clobered dec kwrk01 ;[1.14] bne break3 ;[1.14] ;[1.14] lda #206 ;[1.9] how about 108 ms ;[1.14] jsr wait ;[1.9] only the a reg is clobered lda #mnminb ; start up the port again sta kr2pcr,y ;[47] cli ;allow interupts lda #true ;return true rts ;[1.14]inbuf .blkb 256 ;input buffer inbuf .blkb $900 ;[1.14]input buffer ***** inbuf & outbuf no separations outbuf .blkb 256 ;output buffer endcom ;[1.11]