.TITLE KERMIT-65 CCS 7710 com card - interupt driven .SBTTL 6502 version - Ted Medin ; Thanks to Bill Rupp for the loan of his equipment and thus this driver ; Version 1.0 ; Warning interupts must be allowed by card. ; Based on the KERMIT Protocol. ; $Header: appccs.m65,v 1.11 88/12/22 09:22:13 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 ; ------ ----------- ; ;$Log: appccs.m65,v $ ;Revision 1.11 88/12/22 09:22:13 medin ;Use time constant for the wait routine, ;enlarge the input buffer to $900. ;Revision 1.10 88/04/27 18:05:59 medin ; Dont allow interupts when you exit kermit. ;Revision 1.9 88/03/28 13:31:35 medin ; Attempt to make the interupt routine faster. ;Revision 1.8 88/01/15 08:42:30 medin ;New origin for 3.81 ;Revision 1.7 87/06/29 10:55:05 medin ; Change wait rtn to use apple nom rtn, change org for 3.78. ;Revision 1.6 87/05/13 18:09:28 medin ; Change org to correspond with 3.76 ;Revision 1.5 87/02/20 23:57:07 medin ; Put the version number in the hearld so we can keep track of the com ;drivers also. Thanks Rhoda. ; DONT FORGET TO UPDATE THE VERSION ;Revision 1.4 86/12/23 10:17:59 medin ; Protect ourselves from interupts during initialization and ;tattle that we cant set baud via software. ;Revision 1.3 86/12/09 22:14:52 medin ; Acknowledge Bill Rupp for the loan of his equipment. ;Revision 1.2 86/12/09 22:08:38 medin ; This is the interupt driven version of the ccs 7710 serial card. ; ; ; 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.8] end of this routine timect .blkb 1 ;[1.11] 1 ms delay via 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.7]wait: .blkb 3 ;[54] wait routine-a reg contains milliseconds wait: .blkb 3 ;[1.7] wait routine-apple rom rtn 220=125ms,198=100ms,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 .=$7b00 ;[1.8][54] place to start com card assembly start = . ;need a label at begining kr2pch = $c081 ;data port kr2pst = $c080 ;status port kr2pcr = $c080 ;command port kr2pcc = $c080 ;control port mncinb = $95 ; Control port command(8 bit,no par,1-stop,in int,16xbaud) mnminb = $3 ; Master port reset mssinb = $1 ; status bit for input ready mssoub = $2 ;status bit for output busy moutb = $60 ; break command on output moutnt = $b5 ; command to start input & output with interupts ; ACIA commands ; xxxx xx00 clock 1x baud rate ; xxxx xx01 clock 16x baud ; xxxx xx10 clock 64x baud ; xxxx xx11 acia master reset ; xxx0 00xx 7data + even parity + 2 stop bits ; xxx0 01xx 7data + odd par + 2 stop ; xxx0 10xx 7data + even par + 1 stop ; xxx0 11xx 7data + odd par + 1 stop ; xxx1 00xx 8data + no par + 2 stop ; xxx1 01xx 8data + no par + 1 stop ; xxx1 10xx 8data + even par + 1 stop ; xxx1 11xx 8data + odd par + 1 stop ; x00x xxxx set CTS, disable xmit interupts ; x01x xxxx set CTS, enable xmit interupts ; x10x xxxx clear CTS, disable xmit interupts ; x11x xxxx set CTS, disable xmit interups, xmit break on xmit data ; 0xxx xxxx disable receive interrupts ; 1xxx xxxx enable receive interrupts on rec full,rec overrun,DTR signal inactive ; STATUS bits ; .... ...x receive data reg full when x=1 ; .... ..x. xmit reg ready for data ; .... .x.. DTR inactive - dont send ; .... x... RTS inactive - dont send ; ...x .... rec data improper frame ; ..x. .... rec data overrun ; .x.. .... parity error in rec data ; x... .... ACIA-generated xmit or rec interupt 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] " xofcnt .byte 0 ;count of times buffer overran kwrk01 .byte 0 ;[1.11] .ifne debug ;[1] conditional assembly cixon .byte 0 ;[1] count of input xon request cixoff .byte 0 ;[1] " 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 " ctrlq = $11 ;xon ^Q ctrls = $13 ;xoff ^S irqsva = $45 ;place dos saves a reg dirq = $3fe ;[51] interupt address sscstp = $578 ;[47] +slot,bit 7 on turns off commands to ssc herld nasc 1 ;tell who we are bad nasc 1 nbaud nasc 1 bcom .byte '< nasc <-- IS UNKNOWN COM CARD COMMAND> 1 ; ; CCS 7710 Card I/O Device support - These routines support the ; Apple CCS 7710 Card. ; tl2rpt: ;[51] a is already saved in irqsva txa ;[51] save x pha ;[51] tl2rpe ;[67] enhanced // has all regs saved ;[1.9] ldx kersli ;[51] ;[1.9] lda kr2pst,x ;[51] get status lda kr2pst ;[1.9] get status bpl tl2nts ;[51] not our interupt and #mssinb ;[51] look at input bit bne tl2inp ;[51] this is input ready bit flowfg ;[57] is flow controll on? bpl tl2out ;[57] no bvs tl2noo ;[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 tl2out ;[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 jmp tl2ou2 ;[1][57] always jump tl2ou0: lda xon ;[57] how about giving the xon ? beq tl2out ;[57] no .ifne debug ;[1] inc caixon ;[1] bump count of actual input xons given .endc ;[1] lda #0 ;[57] turn off xoff sta xon ;[57] lda #ctrlq ;[57] now for the xon tl2ou2: jsr telspa ;[57] set parity correctly ;[1.9] sta kr2pch,x ;[57] stop this flood tl2oup sta kr2pch ;[1.9] stop this flood jmp tl2com ;[1][57] always jump tl2out: lda outptr ;[51] see if any to output cmp poutpt ;[51] beq tl2noo ;[51] no more to output ldx poutpt ;[51] pointer to next ch to output lda outbuf,x ;[51] get next ch ;[1.9] ldx kersli ;[51] now for the port ;[1.9] sta kr2pch,x ;[51] give it to card tl2rpp sta kr2pch ;[1.9] give it to card inc poutpt ;[51] bump to next ch to output jmp tl2com ;[51] common return tl2nts: pla ;[51] restore x tax ;[51] jmp (hdirq) ;[51] and pass it on sans a reg tl2noo: lda #mncinb ;[51] turn off the output interupt ;[1.9] sta kr2pcr,x ;[51] tl2no3 sta kr2pcr ;[1.9] jmp tl2com ;[51] common return from interupt ;[1.9]tl2inp: lda kr2pch,x ;[51] we have an input character tl2inp: lda kr2pch ;[1.9] we have an input character ldx pinptr ;[51] pointer to next input character store ;[1.11] sta inbuf,x ;[51] save ch ;[1.11] inc pinptr ;[51] ready for next input bit flowfg ;[57] are we flow controll ;[1.11] bpl tl2com ;[57] no we may overun the buffers bpl tl2icm ;[1.11] no we may overun the buffers ;[1.11] lda inbuf,x ;[59] is host telling us stop ? and #$7f ;[59] ignore parity ; bvc tl2in2 ;[59] are we already stoped?, yes 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] .ifne debug ;[1] inc coxon ;[1] bump count of output xons given .endc ;[1] ;[1.11] dec pinptr ;[59] and ignore this character jsr tl2suo ;[59] start up output jmp tl2com ;[59] and carry on 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! ;[1.11] dec pinptr ;[59] ignore this character jmp tl2com ;[1] thats all tl2in4 ;[59] place to hang ones hat ;[1.11] lda xoff ;[57] have we already asked for ^S ? ;[1.11] bne tl2com ;[57] yes no need for another ; inx ;[57] ; inx ;[57] ; inx ;[57] ; cpx inptr ;[57] are we about to overrun ? ;[1.11] txa ;[59] lets try stoping when half full ;[1.11] clc ;[59] ;[1] adc #126 ;[59] ;[1.11] adc #7 ;[1] ;[1.11] cmp inptr ;[59] are we filling up ? ;[1.11] bne tl2com ;[57] no ;[1.11] jsr tl2suo ;[57] yes,start up output ;[1.11] sta xoff ;[57] turn on xon(non 0) ;[1.11] .ifne debug ;[1.11] ;[1.11] inc xofcnt ;just for debug ;[1.11] .endc ;[1.11] tl2icm inc pinptr ;[1.11] now bump the ptr bne tl2com ;[1.11] thats all ldx store+2 ;[1.11] now for the msb inx ;[1.11] cpx #outbuf^ ;[1.11] too far? bne tl2ic0 ;[1.11] no ldx #inbuf^ ;[1.11] yes tl2ic0 stx store+2 ;[1.11] update the msb tl2com: pla ;[51] get x tax ;[51] tl2eac lda irqsva ;[51] get a tl2rti rti ;[51] return from interupt tl2suo: ;[1.9] ldx kersli ;[22] Get I/O location offset lda #moutnt ;[51] turn on xmit and rec interupt ;[1.9] sta kr2pcr,x ;[51] tell card about it tl2su3 sta kr2pcr ;[1.9] tell card about it tl2su0: rts ; tl2int: sei ;lockout interupts just in case ;[1.11] lda hdirq ;see if we already saved ;[1.11] 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.11] beq setnm ;whee just exactly right bcs setnm ;ok trble ldx #bad\ ;got to tell someone ldy #bad^ jsr prstr ;print the message jsr prcrlf ;and terminate it properly setnm: init0: lda kerins ;[47] initialize slot beq .+5 ;hate to do this jmp tl2prr ;[47] already initialized return ; apple machine id ;rom--> $fbb3 $fbbf $fbc0 ; II $38 ; II+ $ea ; //e $06 $ea ; //e+ $e0 enhanced ; //c $06 $00 $00 ;prodos--> $bf98 ; II,II+,//e bit 3 = 0 ; others bit 3 = 1 ; //c bits 7,6 = 10 lda $fbc0 cmp #$e0 ; is this an enhanced 2e? beq setenh ; yes cmp #0 ; no, how about a 2c? bne init3 ; no lda $fbbf ; yes, how about an enhanced 2c? bne init3 ; no setenh lda tl2rti ; yes sta tl2com lda #$ea ; a nop sta tl2nts ; this keeps the stack straight sta tl2nts+1 ; incase there are mult interups lda #tl2rpe\ ;[67][51] sta dirq ;[67][51] setup inturpt address lda #tl2rpe^ ;[67][51] sta dirq+1 ;[67][51] 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.11] and the msb also sta store+2 ;[1.11] sta get+2 ;[1.11] ;[67] lda #tl2rpt\ ;[51] ;[67] sta dirq ;[51] setup inturpt address ;[67] lda #tl2rpt^ ;[51] ;[67] sta dirq+1 ;[51] ldx kersli ;[47] get slot number stx kerins ;[67] tell weve been here clc lda #kr2pst\ ;[1.9] status address adc kersli ;[1.9] calculate proper address for status sta tl2rpe+1 ;[1.9] and set interupt rtn sta tl2su3+1 ;[1.9] sta tl2no3+1 clc lda #kr2pch\ ;[1.9] data port address adc kersli ;[1.9] calulate proper address for ld & st sta tl2rpp+1 ;[1.9] and set interupt rtn sta tl2inp+1 sta tl2oup+1 lda #mnminb ;[47] Master port init sta kr2pcr,x ;[47] Com master port lda #mncinb ;[47] Control port init sta kr2pcc,x ;[47] tl2prr: cli ;[51] allow the interurpts to happen rts ;[22] Return tl2cp: sei ;[51] lockout inturpts lda inptr ;[51] check input for chs cmp pinptr ;[51] bne tl2cp3 ;[1.11] how about msb, no lda store+2 ;[1.11] yes check that also cmp get+2 ;[1.11] tl2cp3 ;[1.11] cli ;[51] allow interupts rts ;[22] ... tl2gpc: sei ;[51] lockout interupts ldx inptr ;[51] get input character get ;[1.11] lda inbuf,x ;[51] inc inptr ;[51] bump in pointer bne tl2gp0 ;[1.11] ldy get+2 ;[1.11] bump msb also iny ;[1.11] cpy #outbuf^ ;[1.11] too far? bne tl2gp7 ;[1.11] no ldy #inbuf^ ;[1.11] yes, circle those wagons tl2gp7 sty get+2 ;[1.11] msb ;[1.11] ldy xon ;[57] are we flow controlling ? ;[1.11] beq tl2gp0 ;[57] no ;[1.11] inx ;[57] ;[1.11] inx ;[57] ;[1.11] inx ;[57] ;[1.11] cpx pinptr ;[57] have we about caught up ? ;[1.11] bne tl2gp0 ;[57] no ;[1.11] pha ;[57] save ch ;[1.11] lda #0 ;[57] turn off xon ;[1.11] sta xoff ;[57] ;[1.11] jsr tl2suo ;[57] now start up output with a ^Q ;[1.11] pla ;[57] restore ch tl2gp0: cli ;[51] allow interupts ; ldx parity ;[22] Check parity ; cpx #nparit ;[22] No parity ; beq tl2rtc ;[22] Go return the character ; and #$7f ;[22] There is parity, so strip it off tl2rtc: rts ;[22] and return tl2ppc: pha ;[22] Hold the byte to send sei ;[51] lockout interupts jsr tl2suo ;[57] start up output pla ;[22] Fetch the data byte off the stack ; jsr telspa ;[22] Go set the parity appropriately ldx outptr ;[51] get output pointer sta outbuf,x ;[51] save in buffer for interupt inc outptr ;[51] ready for next output cli ;[51] allow interupts rts ;[22] and return tl2exi: sei ;lockout interupts ;[1.11] lda hdirq ;have we alredy done this? ;[1.11] 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.11] sta hdirq sta hdirq+1 ldx kersli ;[47] get slot number sta kr2pcr,x ;shut it down ;[1.10exit9: cli ;now allow them exit9: ;[1.10]cli ;now allow them rts tl2cmd: ;find out what command beq tl2rts ;its drop line and we cant 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 baud ; sorry we cant ldx #nbaud\ ;tell that we cant ldy #nbaud^ ;drop the line jmp tl2prn ;and tell kermit we cant txon: ;[1.9]bit flowfg ;do we have flow control ;[1.9] bpl tl2fls ;no can do sei ;protect ourselves from interupts jsr tl2suo ;[57] now start up output lda #0 sta xoff ;tell interupt to start up .ifne debug ;[1] inc cixon ;[1] bump count of xon requests .endc ;[1] cli ltxon lda xon ;[1] got to wait for ch to be sent bne ltxon ;[1] its called true syncronization lda #1 ;give a true return rts txoff: ;[1.9]bit flowfg ;do we have flow control ? ;[1.9] bpl tl2fls ;no sei jsr tl2suo ;[57] now start up output .ifne debug ;[1] inc cixoff ;[1] bump count of xoff requests .endc ;[1] lda #1 ;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 break: sei ;lock out interupts ldy kersli ; ss card routine is not on lda #moutb ; sta kr2pcr,y ; start the break sta kr2pch,y ; start xmit cli ; allow others to go ;[1.7] lda #233 ; for 233 millseconds ;[1.7] jsr wait ; the y reg is not clobered ;[1.11] lda #220 ;[1.7] for 125 millseconds lda #233 ;[1.11] for 233 millseconds sta kwrk01 ;[1.11] break3 lda timect ;[1.11] 1 ms at a time jsr wait ;[1.7] dec kwrk01 ;[1.11] bne break3 ;[1.11] ;[1.11] lda #206 ;[1.7] for 108 millseconds ;[1.11] jsr wait ;[1.7] which is a grand total of 223ms lda #moutnt ; restore the commands sei ; see how nice one can be sta kr2pcr,y ; cli ;allow interupts lda #1 ;return true rts ;[1.11]inbuf .blkb 256 ;input buffer inbuf .blkb $900 ;[1.11]input buffer ***** inbuf & outbuf no separations outbuf .blkb 256 ;output buffer endcom ;[1.8]