/**************************************************************************** OS/A65 Version 1.4.0 Multitasking Operating System for 6502 Computers Copyright (C) 1989-1997 Andre Fachat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************/ .( #include "fstcp.h" #define MAXQUEUE MAXFILES .data status .dsb MAXFILES stream .dsb MAXFILES fscmd .dsb MAXFILES fstask .dsb MAXFILES fsrxb .dsb MAXFILES ; received data buffer to be transfered to stream fsqueue .dsb MAXQUEUE fsnq .byt 0 signal .byt 0 fsconn .byt 0 fscnt .byt 0 .text fstcp_srv .byte FSTCP_SERVER_IP, >FSTCP_SERVER_PORT, fstcp_srv jsr tcp_open bcs openerr stx fsconn openerr rts .) &&&fstcp_mloop .( /* called from mainloop */ lda fsconn /* if negative, everything is cleared up */ bpl ok dec fscnt /* not give too much load when retrying */ bne ok lda #fstcp_srv jsr tcp_open /* reopen */ bcs ok stx fsconn ok rts .) fstcp_queue .( txa ldy fsnq cpy #MAXQUEUE bcs foops /* shouldn't happen! */ sta fsqueue,y inc fsnq clc rts foops sec rts .) fstcp_loop .( ldy #TCB_STATE lda (tcbp),y cmp #TCP_ESTAB bne looperr jsr rxloop jsr qloop jsr dloop looperr rts .) .data task .byt 0 cmd .byt 0 len .word 0 slot .byt 0 fd .byt 0 .text /**************************************************************************** * check streams and get/put data */ dloop .( ldx #<-1 stx fd l0 ldx fd inx cpx #MAXFILES bcc l1 rts l1 stx fd lda status,x cmp #F_RD bne rd1 ; do read check lda stream,x tax lda #SC_STAT jsr STRCMD cmp #E_NUL bne noend rdclose lda #FS_CLOSE jsr send_msg bcs l0a rdc1 ldx fd lda stream,x tax lda #SC_EOF jsr STRCMD lda #F_FREE ldx fd sta status,x l0a jmp l0 noend cmp #E_SLWM beq doit cmp #E_SEMPTY bne l0a doit lda #FS_READ jsr send_msg ldx fd lda #F_RD_SENT sta status,x ; this is changed to F_RD_RXD when a packet was rxd jmp l0 rd1 cmp #F_RD_RXD beq rdrx cmp #F_RD_EOF beq rdrx cmp #F_RD_CLOSE beq rdclose jmp write rdrx lda fsrxb,x tax jsr getbadr bcc rd1a DB("illegal block adr in dloop rd^m^j") rd1b jmp rdclose rd1a sta pp sty pp+1 rdloop ldy #3 lda (pp),y sta len+1 dey lda (pp),y sta len dey lda (pp),y tax dey lda (pp),y clc adc pp sta pd txa adc pp+1 sta pd+1 datloop lda len ora len+1 bne datok ldx fd lda fsrxb,x tax jsr bfree ldx fd lda status,x cmp #F_RD_EOF bne l00 lda #F_RD_CLOSE .byt $2c l00 lda #F_RD sta status,x jmp l0 datok ldx fd lda stream,x tax ldy #0 lda (pd),y jsr PUTC bcc nextd1 cmp #E_NUL bne noclose DB("rxd E_NUL from stream^m^j") ldx fd lda fsrxb,x tax jsr bfree jmp rdclose nextd1 jmp nextd noclose cmp #E_SFULL bne nextd DB("stream full, put back=") lda len+1:jsr EHexout:lda len:jsr EHexout:jsr ECrlfout ; buffer full, so put length back to block ldy #0 lda pd sec sbc pp sta (pp),y iny lda pd+1 sbc pp+1 sta (pp),y iny lda len sta (pp),y iny lda len+1 sta (pp),y jmp l0 nextd inc pd bne n0 inc pd+1 n0 lda len bne n1 dec len+1 n1 dec len jmp datloop write cmp #F_WR_WAIT beq trysend1 cmp #F_WR_WEOF bne nowait trysend1 jmp trysend nowait cmp #F_WR beq l0d l0c1 jmp l0 l0d ldx fd lda stream,x tax lda #SC_STAT jsr STRCMD pha:DB("STAT gives "):pla:pha:jsr EHexout:jsr ECrlfout:pla cmp #E_SFULL beq send cmp #E_SHWM beq send lda #SC_RWANZ jsr STRCMD pha:DB("RWANZ gives "):pla:pha:jsr EHexout:jsr ECrlfout:pla cmp #0 ; number of writing tasks - last packet! bne l0c1 send lda #TCP_DOFFSET+FSP_DATA+64 ldy #0 jsr balloc bcs l0c1 txa ldy fd sta fsrxb,y lda #TCP_DOFFSET+FSP_DATA jsr getpinfo bcs l0c1 ldx fd lda stream,x tax ldy #0 wrl jsr GETC bcs wrle sta (pd),y iny cpy #64 bcc wrl lda #E_OK wrle pha tya:pha:DB("GETC gives "):tsx:lda $102,x:jsr EHexout:jsr ECrlfout:pla:tay lda pd sec sbc #FSP_DATA sta pd bcs w1 dec pd+1 w1 tya clc adc #FSP_DATA sta pdl ldy #FSP_LEN sta (pd),y lda fd ldy #FSP_FD sta (pd),y ldx fd lda fsrxb,x tax lda pdl ldy #0 clc adc #TCP_DOFFSET bcc w2 iny w2 jsr btrunc ldy #0 lda #TCP_DOFFSET sta (pp),y iny lda pdl sta (pp),y iny lda #0 sta (pp),y pla cmp #E_EOF beq wend ldx #F_WR_WAIT lda #FS_WRITE bne we2 wend ldx #F_WR_WEOF lda #FS_EOF we2 ldy #FSP_CMD sta (pd),y txa ldx fd sta status,x ldx fd lda fsrxb,y tax jsr incownr jsr tx_queue_packet bcs l0c bcc l0e trysend ldx fd lda fsrxb,y tax jsr incownr jsr queueslot bcs l0c l0e ldx fd ;lda #F_WR ;sta status,x lda fsrxb,x tax jsr bfree ldx fd lda status,x cmp #F_WR_WAIT beq l0f lda stream,x tax lda #SC_NUL jsr STRCMD lda #F_FREE .byt $2c l0f lda #F_WR ldy fd sta status,y l0c jmp l0 .) /**************************************************************************** * process requests from filesystem interface */ rxloop .( lda sendbuf ; test WWW server interference bne norx clc jsr RECEIVE bcc ok norx rts ok stx task sty len sta cmd /* get free fd */ jsr getfd bcc noretnofil jmp retnofil noretnofil sty fd /* interprete received request */ ldy #0 lda len clc adc #TCP_DOFFSET bcc l1 iny l1 jsr balloc bcs retnomem2 sta pp sty pp+1 stx slot clc adc #TCP_DOFFSET sta pd tya adc #0 sta pd+1 /* save stream and prepare PCBUF for sending */ ldy fd lda cmd sta fscmd,y sta PCBUF+FS_OPEN_DRV lda PCBUF+FS_OPEN_STR sta stream,y tya sta PCBUF+FS_OPEN_PFAD lda len sta PCBUF+FS_OPEN_STR ldy #0 lda #TCP_DOFFSET sta (pp),y iny lda #0 sta (pp),y iny lda len sta (pp),y iny lda len+1 sta (pp),y /* DB("cmd=") lda cmd:jsr EHexout:lda #":":jsr ECout */ ldy #0 l2 lda PCBUF,y sta (pd),y /*jsr EHexout:lda #" ":jsr ECout*/ iny cpy len bcc l2 /*jsr ECrlfout*/ ldx slot jsr tx_queue_packet retnomem2 bcs retnomem ldy fd lda #F_CMD_SENT sta status,y lda task sta fstask,y /* A filesystem is _never_ allowed to release the PCBUF during OPEN etc! */ #if 0 /*def NOMMU*/ ldx #SEM_SENDBUF jsr VSEM /*DB("free'd SEM_SENDBUF^m^j")*/ #endif lda #E_OK clc rts retnomem DB("retnomem!^m^j") lda #E_NOMEM .byt $2c retnofil lda #E_NOFILE sta PCBUF+FS_X_ERR ldy #1 ldx task jsr SEND rts .) getfd .( ldy #0 clc l0 lda status,y beq found iny cpy #MAXFILES bcc l0 found rts .) /**************************************************************************** * check incoming packets */ qloop .( lda fsnq bne gotone rts gotone /* TODO: this implementation wants each reply in exactly one packet! */ ldx fsqueue jsr getbadr sta pp sty pp+1 /* DB("pp=") lda pp+1:jsr EHexout: lda pp:jsr EHexout DB(" do=") ldy #1: lda (pp),y: jsr EHexout ldy #0: lda (pp),y: jsr EHexout DB(", l=") ldy #3: lda (pp),y: jsr EHexout ldy #2: lda (pp),y: jsr EHexout DB(" slot=") lda fsqueue:jsr EHexout jsr ECrlfout */ ldy #0 lda (pp),y clc adc pp sta pd iny lda (pp),y adc pp+1 sta pd+1 iny lda (pp),y sta len iny lda (pp),y sta len+1 /* interpret reply packet */ ldy #FSP_FD lda (pd),y sta fd tay lda status,y bne noillfd illfd DB("illegal FD^m^j") ldx fsqueue jsr bfree jmp nextbuf noillfd ldy #FSP_LEN lda (pd),y cmp len bne illlen lda len+1 beq noilllen illlen DB("illegal len^m^j") disc ldx fsqueue jsr bfree jmp nextbuf noilllen /* DB("pkt type ") ldy #FSP_CMD:lda (pd),y:jsr EHexout DB(", fd="):lda fd:jsr EHexout DB(", st="):ldy fd:lda status,y:jsr EHexout:jsr ECrlfout */ ldy #FSP_CMD lda (pd),y cmp #FS_REPLY beq reply jmp noreply reply /* first (and only) data byte is reply value */ lda len cmp #4 bne illlen ldx fd lda status,x cmp #F_CMD_SENT beq noillreply DB("reply but not CMD_SENT: st=") lda status,x:jsr EHexout:jsr ECrlfout jmp disc noillreply #if 0 /*def NOMMU*/ sec ldx #SEM_SENDBUF jsr PSEM bcc gotbuf DB("didn't get SEM_SENDBUF^m^j") sec rts gotbuf /* DB("got SEM_SENDBUF^m^jpd=") lda pd+1:jsr EHexout:lda pd:jsr EHexout DB(", retval=") ldy #FSP_DATA:lda (pd),y:jsr EHexout DB(", fscmd=") ldy fd:lda fscmd,y:jsr EHexout jsr ECrlfout */ #endif ldy #FSP_DATA lda (pd),y sta PCBUF+FS_X_ERR cmp #E_OK bne l1 ldy fd lda fscmd,y cmp #FS_OPEN_RD beq rd cmp #FS_OPEN_WR beq wr cmp #FS_OPEN_DR bne l1 rd lda #F_RD .byt $2c wr lda #F_WR .byt $2c l1 lda #F_FREE ldy fd sta status,y ldy fd lda fstask,y tax ldy #FS_X_SLEN lda PCBUF+FS_X_ERR jsr SEND ldx fsqueue jsr bfree jmp nextbuf noreply cmp #FS_WRITE beq write cmp #FS_EOF bne nowrite ldy #F_RD_EOF .byt $2c write ldy #F_RD_RXD ldx fd lda status,x cmp #F_RD_SENT bne illwrite lda fsqueue ldx fd sta fsrxb,x tya sta status,x ldx fsqueue jsr getbadr sta pp sty pp+1 ldy #0 lda (pp),y clc adc #FSP_DATA sta (pp),y iny lda (pp),y adc #0 sta (pp),y iny lda (pp),y sec sbc #FSP_DATA sta (pp),y iny lda (pp),y sbc #0 sta (pp),y jmp nextbuf illwrite DB("illegal write ^m^j") ldx fsqueue jsr bfree jmp nextbuf nowrite DB("packet not a reply!^m^j") ldx fsqueue jsr bfree nextbuf ldy #1 l0 lda fsqueue,y dey sta fsqueue,y iny iny cpy fsnq bcc l0 dec fsnq jmp qloop .) /**************************************************************************** * process signal from tcp */ fstcp_signal .( sta signal #if 0 DB("fstcp_signal: ") lda signal: jsr EHexout jsr ECrlfout lda signal #endif jsr tcp_signal ldx #0 stx fd l0 lda status,x beq next cmp #F_RD bcc next cmp #F_RD_RXD beq r1 cmp #F_RD_EOF beq r1 cmp #F_RD_CLOSE+1 bcs write bcc rdc1 r1 lda fsrxb,x tax jsr bfree rdc1 ldx fd lda stream,x tax lda #SC_EOF jsr STRCMD jmp nextfree write cmp #F_WR beq wrc cmp #F_WR_WAIT beq w1 cmp #F_WR_WEOF bne next w1 ldx fd lda fsrxb,x tax jsr bfree wrc ldx fd lda stream,x tax lda #SC_NUL jsr STRCMD nextfree ldx fd lda #F_FREE sta status,x next inc fd ldx fd cpx #MAXFILES bcc l0 q1 ldy fsnq beq noqueue dey lda fsqueue,y tax jsr bfree dec fsnq jmp q1 noqueue lda #<-1 sta fsconn sta fscnt rts .) /****************************************************************************/ send_msg .( sta cmd ldy #0 lda #TCP_DOFFSET+3 jsr balloc bcs retnomem2 lda #TCP_DOFFSET jsr getpinfo bcs retnomem2 /* save stream and prepare PCBUF for sending */ ldy #0 lda cmd sta (pd),y iny lda #3 sta (pd),y iny lda fd sta (pd),y ldy #0 lda #TCP_DOFFSET sta (pp),y iny lda #0 sta (pp),y iny lda #3 sta (pp),y iny lda #0 sta (pp),y ldx pslot jsr tx_queue_packet retnomem2 rts .) .)