> SerNet/s , Add serial port network support to NFS " v0.01 14-Mar-95 Initial bits (C v0.02 22-Mar-95 all done except Tx from tube and Broadcast Rx 2, Broadcast immediate sends broken scout <% No check for idle before action F: P mcode% &3000 Z"LOAD NFSROM "+~mcode% drom2%=&9FB5:OSBYTE=&FFF4 n: xEcoTx%=mcode%!&1631 &FFFF !EcoInit%=mcode%!&1634 &FFFF 'EcoNMIRelease%=mcode%!&1637 &FFFF %EcoNMIClaim%=mcode%!&163A &FFFF : 'TxStatus=&FC08:TxRDY=1:TxData=&FC09 'RxStatus=&FC08:RxRDY=2:RxData=&FC09 : esc=&9B  Workspace at &0D80-&0D91  &0D80 dest stn  &0D81 dest net  &0D82 src stn  &0D83 src net  &0D84 ctrl  &0D85 port * &0D86-9 RemoteAddr, Transfer Address ". &0D8A-D Transfer End Address , &0D86-D Broadcast data 6* &0D8E incoming scout index/data flag @$ &0D8F esc/tube/ack-nack/netnum J$ &0D90-1 Incoming receive block T: ^-ݤorg(A%):P%=A%:O%=P%-&8000+mcode%:=P*3+4 h P=0 1 r[OPT org(&8009) |)EQUS "SER" :\ Title="SER,NET" : :OPT org(&9630) :\ Low level networking entry points (JMP SerNetTx :\ Transmit block CJMP SerNetInit :\ Initialise, put receive handlers in place -JMP EcoNMIRelease% :\ I must release NMIs .JMP EcoNMIClaim% :\ I can take over NMIs : OPT org(&9643) %JMP SerNetIRQ :\ IRQ occured : OPT org(rom2%) \ Service routine \ =============== RTS : : & \ Initialise network drivers 0 \ ========================== :.SerNetInit D9JSR EcoInit% :\ Initialise Econet drivers NLDA #7:LDX #7:JSR OSBYTE X=LDA #8:LDX #7:JSR OSBYTE :\ Set serial port speed to 9600 b6LDA #0:STA &190+232 :\ Serial IRQs come to me lRTS v: : \ Transmit a block of data \ ========================  .SerNetTx \ On entry, \ X is important \ A,Y unimportant \ &A0/1=>workspace+&6F \ (&A0),0 = control byte \ 1 = port \ 2 = station \ 3 = net \ 4-7 =>buffer start \ 8-11 =>buffer end  !\ 12-15= Remote Address \  \ On exit, *,\ (&A0),0 = result, read by OSBYTE &32 4\ A,Y = unimportant >\ X = preserved H\ R4LDY #3:LDA (&A0),Y :\ Get network number \CMP #&FF:BEQ SerTxBroadcast f #&F0:CMP #&70 pDBEQ SerTx:JMP EcoTx% :\ Not net &7x, pass to Econet driver z: .SerTxBroadcast :JSR EcoTx% :\ Send broadcast to Econet  .SerTx : .\ Transmit a block of data via serial port 1\ Sends
\ <\ Should wait for 'Background reception not in progress' : ATXA:PHA:LDA &A9:PHA:LDA &A8:PHA :\ Save X and some workspace 3LDX #0:JSR SerTxScoutStart :\ Frame start 0LDY #2:LDA (&A0),Y:JSR SerTxByte :\ dest stn 0INY:LDA (&A0),Y:JSR SerTxByte :\ dest net /LDA &D22:JSR SerTxByte :\ src stn LDA &D8F: #15 .A #&70:JSR SerTxByte :\ src net $,LDY #0:LDA (&A0),Y:JSR SerTxByte :\ Ctrl .,INY:LDA (&A0),Y:JSR SerTxByte :\ Port 8!BNE SerTxNotImmediate:LDY #12 B.SerTxRAddr L:LDA (&A0),Y:JSR SerTxByte :\ Send RemoteAddress VINY:CPY #16:BNE SerTxRAddr `.SerTxNotImmediate j6LDY #2:LDA (&A0),Y:CMP #&FF:PHP :\ Dest=???.255 ? t\\\ ~%\\\ Should check for Tube address \\\ INY:LDA (&A0),Y:STA &A8 5INY:LDA (&A0),Y:STA &A9 :\ &A8/9=address PLP:BNE SerTxNotBroadcast .SerTxBroadcast LDA (&A8),Y:JSR SerTxByte :BIT &D8F:BMI SerRxEsc2nd :\ Waiting for escaped byte H:CMP #esc:BEQ SerRxEsc1st :\ Start of escape sequence R8LDY &D8E:BMI SerRxData :\ Waiting for data frame \CCPY #12:BCS SerRxExit :\ Scout overrun, ignore extra bytes f5STA &D80,Y:INY:STY &D8E :\ Store byte of scout p&BNE SerRxExit :\ Exit z: .SerRxEsc1st ALDA #&80:A &D8F:STA &D8F :\ Set b7, waiting for escaped byte BNE SerRxExit : .SerRxEsc2nd >CMP #esc:BNE SerRxEscCmd :\ esc,<>esc -> escaped command \ esc,esc -> esc : .SerRxData :BIT &D8F:BVC SerRxIO :\ b6=0, read to I/O memory 5STA &FEE5:BVS SerRxUpdate :\ Read to Tube memory  .SerRxIO TAY LDA &D86:STA &A8 LDA &D87:STA &A9 5TYA:LDY #0:STA (&A8),Y :\ Store received byte $.SerRxUpdate .9INC &D86:BNE SerRxUpdEnd :\ Update transfer address 8INC &D87:BNE SerRxUpdEnd BINC &D88:BNE SerRxUpdEnd L INC &D89 V.SerRxUpdEnd `#\ Should check for data overrun j.SerRxExit t9PLA:STA &A9:PLA:TAY :\ Restore workspace and Y ~LDA #0:RTS : \ Escaped command \ --------------- %\ &esc,&Ax - %10100xxx - incoming $\ &esc,&Ax - %10101xxx - replies \ '\ %1010000x - ScoutStart %\ %1010001x - ScoutEnd &\ %1010010x - DataStart $\ %1010011x - DataEnd \ %\ %1010100x - ScoutACK %\ %1010101x - ScoutNAK $\ %1010110x - DataACK $\ %1010111x - DataNAK \ (.SerRxEscCmd 2TAY: #&F0 <7CMP #&A0:BNE SerRxExit :\ Not %1010xxxx, ignore FTYA: #7:LSR A PBNE SerRxScoutEnd Z: d\ ScoutStart n9STA &D8E:BEQ SerRxExit :\ Set count index to zero x: .SerRxScoutEnd CMP #2:BCS SerRxDataStart ;LDA &D85:BEQ SerRxImmediate:\ Port=0, immediate command \ %\ Look through open receive block 9\ See if anything's listening for this incoming scout 5\ This is where gateway action could be performed :\ If deststn<>mystn destnet<>0, pass out onto Econet /\ Would need complemntary EcoRx->SerTx code \ =JSR FindReceiveBlock :\ Returns X=ScoutACK/ScoutNAK .JSR SerTxCommand :\ Send ACK/NAK JMP SerRxExit : .SerRxDataStart BNE SerRxDataEnd "2LDA #&80:STA &D8E :\ Waiting for data ,BNE SerRxExit 6: @.SerRxDataEnd J2CMP #4:BCS SerRxACK :\ ACK/NAK received T*JSR SerTxDataACK :\ Send ACK ^6LDA &D90:STA &A8 :\ Get Rx block address hLDA &D91:STA &A9 r LDY #11 |.SerRxEndAddr LLDA &D7E,Y:STA (&A8),Y :\ Update end address with final data address DEY:CPY #8:BNE SerRxEndAddr :LDY #3:LDA &D83:STA (&A8),Y:\ Actual Net received from :DEY:LDA &D82:STA (&A8),Y :\ Actual Stn received from 6DEY:LDA &D85:STA (&A8),Y :\ Actual port received MDEY:LDA &D84:STA (&A8),Y :\ Received control byte, closes receive block ALDA #0:STA &D8E :\ Reset back to waiting for scout .BIT &D8F:BVC SerRxExit :\ I/O transfer .LDA #&C0+&3E:JSR &406 :\ Release Tube /STA &D8F: #15:STA &D8F :\ Clear Tube flag JMP SerRxExit : .SerRxACK @TYA: #3:A #1 :\ A=01 11 01 11 for ACK/NAK/ACK/NAK 4ASL A:ASL A:ASL A:ASL A :\ A=&1x=ACK, &3x=NAK ;A &D8F:STA &D8F :\ Put ACK/NAK into flag byte &JMP SerRxExit 0: :\ Immediate Operations D\ -------------------- N!\ If &D80<>mystat, not for me X \ If &D81<>mynet, not for me b.SerRxImmediate l9LDA &D84:CMP #&88 :\ Only MachType supported v3BEQ P%+5:JMP SerRxExit :\ Ignore all others : *\\\ Need to send a long scout in reply '\\\ dstn,dnet,sstn,snet,b1,b2,b3,b4 \\\ 6\\\ Need to wait until foreground not transmitting \\\ JMP SerRxExit : : ,\ Look for a matching open receive block ,\ ====================================== ?\ Receive blocks are in private Econet workspace at (&9E),Y =\ If &D64.b7=1, listening receive block at &00C0 for FSOp M\ 0 - 0=end blocks, &7F=open receive block, &80+x=receive control byte \ 1 - port \ 2 - stn \ 3 - net *\ 4-7 - buffer start 4\ 8-11 - buffer end >\ H.FindReceiveBlock R=LDA &9F:STA &A9:LDA #0:STA &A8 :\ &A8/9=>Econet workspace \BIT &D64:BPL FindRxLp fESTA &A9:LDA #&C0:STA &A8 :\ &A8/9=>&00C0 FSOp receive block p .FindRxLp z LDY #0 =LDA (&A8),Y:BEQ FindRxNone :\ End of blocks, no match ACMP #&7F:BNE FindRxNext :\ Not an open block, try next 8INY:LDA (&A8),Y:BEQ FindRxPort :\ Listen on any port BCMP &D85:BNE FindRxNext :\ Port doesn't match, try next .FindRxPort ;INY:LDA (&A8),Y:BEQ FindRxFound:\ Listen to any station ECMP &0D80:BNE FindRxNext :\ Station doesn't match, try next ;INY:LDA (&A8),Y:BEQ FindRxFound:\ Listen to any network ACMP &0D81:BEQ FindRxFound :\ Nets match, jump to process : L.FindRxNext :\ This block doesn't match, step to next 8LDA &A9:BEQ FindRxNone :\ FSOp receive block @LDA &A8:CLC:ADC #12 :\ Step to next receive block ASTA &A8:BCC FindRxLp :\ Loop back to check this one .FindRxNone LSEC:LDX #&AA:RTS :\ X=ScoutEndNAK - no receive block found $: .\ Receive block matches 8\ --------------------- B.FindRxFound LLDA &A8:STA &D90 VALDA &A9:STA &D91 :\ Point to this receive block `\\\ j&\\\ If broadcast, eat the data now t\\\ ~ LDY #4 .FindRxAddrLp MLDA (&A8),Y:STA &D82,Y :\ Copy AddrStart and AddrEnd to workspace  INY:CPY #12:BNE FindRxAddrLp 8LDA &D89:CMP #&FF:BNE FindRxIO :\ I/O memory, return .FindRxTube 0LDA #&80+&3E:JSR &406 :\ Claim Tube BCC FindRxTube =LDA #1:JSR &406 :\ Transfer bytes to CoPro 9LDA &D8F:A #&40:STA &D8F :\ Flag 'Tube transfer'  .FindRxIO 3CLC:LDX #&A8:RTS :\ X=ScoutEndACK : ]   6"*SAVE SerNet/rom ";~mcode%;" ";~O%;" 0 FFFBBC00"