home *** CD-ROM | disk | FTP | other *** search
- MODULE NETWORK ; (* by fred brooks PD software *)
-
- (* --------------------------------------------------------------------------
-
- NETWORK : MIDI MULTI CPU NETWORK FOR TDI Modula-2/ST
-
- --------------------------------------------------------------------------*)
-
- (*$T- *) (*$S- *)
-
-
- FROM SYSTEM IMPORT ADDRESS, ADR, SETREG, CODE, REGISTER ,BYTE ,TSIZE,SIZE;
- FROM GEMX IMPORT BasePageAddress, BasePageType ;
- FROM BIOS IMPORT BPB ,BConStat ,BConIn, BCosStat, BConOut, Device,
- MediaChange,MCState,GetBPB,RWAbs,RW,DriveSet,DriveMap;
- FROM XBIOS IMPORT SuperExec,SerialDevice,IORec,IORECPTR,IOREC,VSync;
- FROM GEMDOS IMPORT TermRes,Open,Close ;
- IMPORT GEMDOS;
- FROM ASCII IMPORT SYN,STX,SOH,BEL;
-
- CONST
- MaxSeq = 1;
- recsize = 511;
- MAGIC = 3141592653;
- USERS = 16;
- retry = 10;
- debug = FALSE;
- trace = FALSE;
-
- (* Because we dont know what registers the BIOS is using we must use
- the following opcodes to save the registers *)
- MOVEMDEC = 48E7H ; (* 68000 opcode for MOVEM <regs>,-(A7) *)
- MOVEMINC = 4CDFH ; (* 68000 opcode for MOVEM (A7)+,<regs> *)
- SAVEREGS = 07FFCH ; (* Registers D1..A5 for DEC *)
- RESTREGS = 03FFEH ; (* Registers D1..A5 for INC *)
- RTS = 04E75H ; (* 68000 return from subroutine opcode *)
-
- TYPE
- (* Procedure types to mimic correct sequence for "C" BIOS routines *)
-
- CBPBProc = PROCEDURE ( CARDINAL ) ;
- CMediaChProc = PROCEDURE ( CARDINAL ) ;
- CRWAbsProc = PROCEDURE ( CARDINAL, CARDINAL, CARDINAL, ADDRESS, CARDINAL );
- midibuffer = ARRAY [0..2000] OF CARDINAL;
- SequenceNr = [0..MaxSeq];
- message = ARRAY [0..recsize] OF BYTE;
- message1 = ARRAY [0..17] OF BYTE;
- FrameKind = (ack,data,resetreq,resetconf,diag);
- DataKind = (rdmediareq,rdmediaconf,rdbpbreq,rdbpbconf,
- rdrwabsreq,rdrwabsconf);
- evtype = (framearrival,cksumerr,timeout,hostready,reset,nothing);
-
- frame = RECORD
- syn : CHAR; (* these are sync chars *)
- stx : CHAR; (* for the frames *)
- kind : FrameKind;
- seq : SequenceNr;
- ack : SequenceNr;
- cmd : DataKind;
- rw : CARDINAL; (* read or write data *)
- recno : CARDINAL; (* sector for data*)
- d0 : LONGCARD; (* data return variable *)
- info : message;
- user : CARDINAL;
- remoteuser : CARDINAL;
- cksum : CARDINAL;
- END;
-
- framecptr = POINTER TO framecmd;
- framecmd = RECORD
- syn : CHAR; (* these are sync chars *)
- stx : CHAR; (* for the frames *)
- kind : FrameKind;
- seq : SequenceNr;
- ack : SequenceNr;
- cmd : DataKind;
- rw : CARDINAL; (* read or write data *)
- recno : CARDINAL; (* sector for data*)
- d0 : LONGCARD; (* data return variable *)
- info : message1;
- user : CARDINAL;
- remoteuser : CARDINAL;
- cksum : CARDINAL;
- END;
-
- control = RECORD
- magic : LONGCARD;
- USER : CARDINAL;
- REMOTEUSER : CARDINAL;
- reset : BOOLEAN;
- networkactive : BOOLEAN;
- remotedrive : CARDINAL;
- drivemap : DriveSet;
- nextframetosend : ARRAY [0..15] OF SequenceNr;
- frameexpected : ARRAY [0..15] OF SequenceNr;
- sendreset : BOOLEAN;
- END;
-
- consave = RECORD
- magic : LONGCARD;
- USER : CARDINAL;
- REMOTEUSER : CARDINAL;
- reset : BOOLEAN;
- networkactive : BOOLEAN;
- END;
-
- vblqueueptr = POINTER TO ADDRESS;
- frameptr = POINTER TO ARRAY [0..1024] OF BYTE;
-
- VAR
-
-
- (* BIOS variables : These can only be accessed with the 68000 in supervisor
- mode. The Modula-2 language allows you to fix the location of variables *)
-
- HDBPB [0472H] : ADDRESS ; (* hard disk get Bios Parameter Block *)
- HDRWAbs [0476H] : ADDRESS ; (* hard disk read/write abs *)
- HDMediaCh [047EH] : ADDRESS ; (* hard disk media change *)
- DriveBits [04C2H] : SET OF [0..31]; (* disk drives present map *)
- Cptr [0210H] : ADDRESS; (* control record pointer *)
- Dptr [0214H] : DriveSet; (* save original drive map *)
- Mptr [0218H] : LONGCARD;
- charcount,framesize,cksum,recframesize,sndframesize,
- SIZEframe,SIZEframecmd : CARDINAL;
- vblqueue : vblqueueptr; (* set to vbl routines vector *)
- vblptr : vblqueueptr;
-
- networkconnect : BOOLEAN; (* DCD = 1 TRUE *)
- gotframe : BOOLEAN;
- framebufferfull : BOOLEAN;
- cleartosend : BOOLEAN;
- readytosend : BOOLEAN;
- requesttosend : BOOLEAN;
- framewaiting : BOOLEAN;
- timer,OK : BOOLEAN;
- gotmediach : ARRAY [0..5] OF BOOLEAN;
- gotbpb : ARRAY [0..5] OF BOOLEAN;
- vblactive : BOOLEAN;
- networkerror : BOOLEAN;
- shortframe : BOOLEAN;
-
- sframe,rframe,SFRAME,RFRAME,
- nframe1,nframe2 : frame;
- rframeptr,sframeptr,
- bpbptr,nbpbptr : frameptr;
- framecmdptr,framecmdptr1 : framecptr;
- event : evtype;
- C : control;
- recchar,timestart,timefortimeout,timeouttime : LONGCARD;
- timestart1,timefortimeout1,timeouttime1 : LONGCARD;
- i,i1,i2,i3,mediacount,handle : INTEGER;
- wsector,drvnr,DriveA,DriveF,devicestart,d,R,
- REMOTEUSER,receivedfromuser : CARDINAL;
- rbuffer : midibuffer;
- rbptr : IORECPTR;
- numBytes,sec,min,hour,time,count : LONGCARD ;
- status : LONGINT ;
-
- (* The following are saved copies of the BIOS variables so that the real
- hard disk routines can be called if a hard disk access is requested. *)
-
- SaveHDBPB : CBPBProc ; (* hard disk get Bios Parameter Block *)
- SaveHDRWAbs : CRWAbsProc ; (* hard disk read/write abs *)
- SaveHDMediaCh : CMediaChProc ; (* hard disk media change *)
-
- (* NETWORK control *)
-
- NetworkBPB : ARRAY [0..5] OF BPB ; (* BIOS Parameter block for NETWORK *)
-
- PROCEDURE MoveMemory ( From, To : ADDRESS ; Bytes : LONGCARD ) ;
- (* This routine shows how time critical portions of code can be optimised to
- run faster. It relys on the code generation rules of the compiler which
- can be checked by dis-assembling the link file with DecLnk.*)
-
- CONST
- MOVEB = 12D8H ; (* MOVE.B (A0)+,(A1)+ *)
- MOVEL = 22D8H ; (* MOVE.L (A0)+,(A1)+ *)
- A0 = 0+8 ; (* register A0 *)
- A1 = 1+8 ; (* register A1 *)
-
- BEGIN
- SETREG(A0,From) ; (* load From pointer into A0 *)
- SETREG(A1,To) ; (* load To pointer into A1 *)
-
- IF ( ODD(From) OR ODD(To) ) THEN (* must do bytes *)
- WHILE ( Bytes <> 0 ) DO
- CODE(MOVEB) ;
- DEC(Bytes) ;
- END ;
- ELSE (* even addresses so can do long moves *)
- WHILE ( Bytes > 3 ) DO
- CODE(MOVEL) ;
- DEC(Bytes,4) ;
- END ;
- WHILE ( Bytes <> 0 ) DO
- CODE(MOVEB) ; (* clean up remainder *)
- DEC(Bytes) ;
- END ;
- END ;
- END MoveMemory ;
-
-
- PROCEDURE inc(VAR k: SequenceNr); (* increment k circulary *)
- BEGIN
- IF k<MaxSeq THEN k:=k+1 ELSE k:=0 END;
- END inc;
-
-
- (* The following procedures mimic the disk handling routines called by the
- BIOS. Their procedure declarations have been written to mimic the "C"
- calling sequence. *)
-
- PROCEDURE RDRWAbs ( device, RecordNum, SectorCount : CARDINAL ;
- Buffer : ADDRESS ; Flag : CARDINAL ) ;
- (* NB. It is assumed that GEMDOS wont call this routine with out of range
- parameters *)
- CONST D0 = 0 ;
- BEGIN
- CODE(MOVEMDEC,SAVEREGS) ; (* save registers on stack *)
- status := 0;
- IF (device >= DriveA) AND (device <=DriveF) THEN (* is NETWORK channel *)
- IF ( Flag = 0 ) OR ( Flag = 2 ) (* read *) THEN
- FOR wsector:=0 TO (SectorCount-1) DO
- C.remotedrive:=device-devicestart;
- nframe1.d0:=LONGCARD(device-devicestart);
- nframe1.recno:=RecordNum+wsector;
- nframe1.rw:=Flag; (* read *)
- resetnewdisk;
- IF getfromremote(rdrwabsreq,rdrwabsconf,nframe1) THEN
- MoveMemory(ADR(nframe1.info),Buffer+ADDRESS(wsector)*512,
- 512);
- status:=0;
- ELSE
- status:=(-11);
- END; (* if *)
- END; (* for *)
- IF networkerror THEN C.sendreset:=TRUE END; (* send network reset to remote cpu *)
- SETREG(D0,status) ;
- ELSIF ( Flag = 1 ) OR ( Flag = 3 ) THEN (* write *)
- FOR wsector:=0 TO (SectorCount-1) DO
- C.remotedrive:=device-devicestart;
- nframe1.d0:=LONGCARD(device-devicestart);
- nframe1.recno:=RecordNum+wsector;
- nframe1.rw:=Flag; (* write *)
- resetnewdisk;
- MoveMemory(Buffer+ADDRESS(wsector)*512,ADR(nframe1.info),512);
- IF getfromremote(rdrwabsreq,rdrwabsconf,nframe1) THEN
- status:=0;
- ELSE
- status:=(-10);
- END;
- END; (* for *)
- IF networkerror THEN C.sendreset:=TRUE END; (* send network reset to remote cpu *)
- SETREG(D0,status) ;
- ELSE
- SETREG(D0,LONGINT(-3)) ;
- END ;
- ELSE (* not NETWORK *)
- SaveHDRWAbs (device,RecordNum,SectorCount,Buffer,Flag) ;
- END ;
- CODE(MOVEMINC,RESTREGS) ; (* Restore registers from stack *)
- END RDRWAbs ;
-
- PROCEDURE RDMediaCh ( device : CARDINAL ) ;
- CONST D0 = 0 ;
- BEGIN
- CODE(MOVEMDEC,SAVEREGS) ; (* save registers on stack *)
- IF (device >= DriveA) AND (device <=DriveF) THEN (* is NETWORK channel *)
- C.remotedrive:=device-devicestart;
- nframe1.d0:=LONGCARD(device-devicestart);
- IF newdisk() THEN
- gotmediach[device-devicestart]:=FALSE;
- gotbpb[device-devicestart]:=FALSE;
- END;
- IF (NOT gotmediach[device-devicestart]) THEN
- IF getfromremote(rdmediareq,rdmediaconf,nframe1) THEN
- gotmediach[device-devicestart]:=TRUE;
- IF nframe1.d0=1 THEN nframe1.d0:=2 END;
- SETREG(D0,nframe1.d0) ; (* "C" uses D0 as return location *)
- ELSE
- SETREG(D0,Changed);
- END;
- ELSE
- SETREG(D0,NoChange) ; (* "C" uses D0 as return location *)
- END;
- ELSE (* not NETWORK *)
- SaveHDMediaCh(device) ;
- END;
- CODE(MOVEMINC,RESTREGS) ; (* Restore registers from stack *)
- END RDMediaCh ;
-
- PROCEDURE RDBPB ( device : CARDINAL ) ;
- CONST D0 = 0 ;
- BEGIN
- CODE(MOVEMDEC,SAVEREGS) ; (* save registers on stack *)
- IF (device >= DriveA) AND (device <=DriveF) THEN (* is NETWORK channel *)
- C.remotedrive:=device-devicestart;
- nframe1.d0:=LONGCARD(device-devicestart);
- IF newdisk() THEN gotbpb[device-devicestart]:=FALSE; gotmediach[device-devicestart]:=FALSE END;
- (* gotbpb[device-devicestart]:=FALSE; (* test *) *)
- IF (NOT gotbpb[device-devicestart]) THEN
- IF getfromremote(rdbpbreq,rdbpbconf,nframe1) THEN
- gotbpb[device-devicestart]:=TRUE;
- bpbptr:=ADR(nframe1.info);
- nbpbptr:=ADR(NetworkBPB[device-devicestart]);
- FOR i3:=0 TO TSIZE(BPB)-1 DO
- nbpbptr^[i3]:=bpbptr^[i3];
- END;
- resetnewdisk;
- SETREG(D0,ADR(NetworkBPB[device-devicestart])); (* D0 returns address of the BPB *)
- ELSE
- SETREG(D0,0);
- END;
- ELSE
- SETREG(D0,ADR(NetworkBPB[device-devicestart])); (* D0 returns address of the BPB *)
- END;
- IF networkerror THEN C.sendreset:=TRUE END; (* send network reset to remote cpu *)
- ELSE (* not NETWORK *)
- SaveHDBPB(device) ;
- END ;
- CODE(MOVEMINC,RESTREGS) ; (* Restore registers from stack *)
- END RDBPB ;
-
- PROCEDURE resetnewdisk;
- BEGIN
- CODE(3f3cH,0017H,4e4eH,548fH); (* gettime *)
- timestart1:=LONGCARD(REGISTER(0));
- timefortimeout1:=timestart1;
- IncTime(timefortimeout1,4);
- END resetnewdisk;
-
- PROCEDURE newdisk(): BOOLEAN;
- BEGIN
- CODE(3f3cH,0017H,4e4eH,548fH); (* gettime *)
- timeouttime1:=LONGCARD(REGISTER(0));
- SETREG(0,timeouttime1);
- CODE(0280H,0,0FFFFH);
- timeouttime1:=LONGCARD(REGISTER(0));
- IF timeouttime1>timefortimeout1 THEN
- resetnewdisk;
- RETURN TRUE;
- END;
- RETURN FALSE;
- END newdisk;
-
- (* ----------------------------------------------------------------------- *)
-
- PROCEDURE Initialise () : BOOLEAN ;
- (* returns TRUE if NETWORK is to be installed *)
- BEGIN
- CODE(3f3cH,0017H,4e4eH,548fH); (* gettime *)
- CODE(2f00H,3f3cH,0016H,4e4eH,5c8fH); (* settime *)
- SuperExec(PROC(setcontrol)); (* set address of global control record *)
- rbptr:=IORec(MIDI);
- rbptr^.ibuf:=ADR(rbuffer);
- rbptr^.ibufsize:=4000;
- C.magic:=MAGIC;
- C.remotedrive:=0;
- C.USER:=1;
- C.REMOTEUSER:=1;
- framesize:=TSIZE(frame);
- recframesize:=framesize;
- sndframesize:=framesize;
- sframe.user:=C.USER;
- sframe.remoteuser:=C.REMOTEUSER;
- R:=0;
- RETURN TRUE;
- END Initialise ;
-
- (*$P- *) (* set vector to control record *)
- PROCEDURE setcontrol;
- BEGIN
- Cptr:=ADR(C);
- IF Mptr#MAGIC THEN
- C.drivemap:=DriveMap();
- Dptr:=C.drivemap;
- END;
- C.drivemap:=Dptr;
- Mptr:=MAGIC;
- CODE(RTS);
- END setcontrol;
-
- (* this routine reads the 232 port data and sync's it into frames *)
- (* it runs as a background process in a vbl time slot *)
- (*$P- *)
- PROCEDURE recframe;
- BEGIN
- IF C.networkactive AND vblactive THEN
- CODE(02f39H,0,04a2H); (* move.l $4a2,-(sp) save BIOS pointer *)
- CODE(04b9H,0,02eH,0,04a2H); (* sub 46 from pointer *)
- nrecframe;
- Nwait(event);
- IF event#nothing THEN HandleEvents() END;
- CODE(023dfH,0,04a2H); (* restore BIOS pointer *)
- END;
- CODE(RTS);
- END recframe;
-
- PROCEDURE nrecframe;
- BEGIN
- WHILE (BConStat(HSS)) AND (NOT framebufferfull) DO
- recchar := BConIn(HSS); (* read midi port *)
- IF (CHAR(recchar)=SYN) AND (NOT gotframe) THEN
- gotframe:=TRUE; (* got sync char from data *)
- charcount:=0;
- END;
- IF (charcount=1) AND ((CHAR(recchar)#STX) AND (CHAR(recchar)#SOH)) THEN
- gotframe:=FALSE; (* false start try again *)
- charcount:=0;
- END;
- IF (charcount=1) AND (CHAR(recchar)=STX) THEN
- recframesize:=SIZEframe;
- END;
- IF (charcount=1) AND (CHAR(recchar)=SOH) THEN
- recframesize:=SIZEframecmd;
- END;
- IF gotframe THEN (* put data in buffer *)
- rframeptr^[charcount]:=BYTE(recchar);
- INC(charcount);
- IF charcount=recframesize THEN (* got full frame *)
- gotframe := FALSE;
- IF recframesize=SIZEframecmd THEN
- rframe.user:=framecmdptr^.user;
- rframe.remoteuser:=framecmdptr^.remoteuser;
- rframe.cksum:=framecmdptr^.cksum;
- END;
- IF (rframe.user=C.USER) AND C.networkactive THEN
- framebufferfull := TRUE;
- ELSE
- IF rframe.remoteuser#C.USER THEN
- REMOTEUSER:=rframe.user;
- sendf(rframe); (* retransmit *)
- END;
- END;
- END;
- END;
- END; (* WHILE *)
- END nrecframe;
-
- (* The following compiler directive stops the compiler from generating the
- normal Modula-2 entry/exit code for the next procedure. This is needed as
- this routine is called in supervisor mode by the BIOS function to install
- the BIOS vectors. *)
- (*$P- Stop entry/exit code for next procedure *)
- PROCEDURE InstallVectors ;
- BEGIN
- CODE(13FCH,3H,0FFFFH,0FC04H); (* RESET MIDI ACIA *)
- CODE(13FCH,95H,0FFFFH,0FC04H); (* SET NEW SPEED ON MIDI ACIA *)
- (* First save the current hard disk vectors *)
- SaveHDBPB := CBPBProc(HDBPB) ;
- SaveHDRWAbs := CRWAbsProc(HDRWAbs) ;
- SaveHDMediaCh := CMediaChProc(HDMediaCh) ;
- (* Now set the BIOS vectors to our routines *)
- HDBPB := ADDRESS(RDBPB) ;
- HDRWAbs := ADDRESS(RDRWAbs) ;
- HDMediaCh := ADDRESS(RDMediaCh) ;
- drvnr:=2;
- WHILE drvnr IN DriveBits DO
- INC(drvnr);
- END; (* while *)
- INC(drvnr);
- devicestart:=drvnr;
- DriveA:=drvnr;
- DriveF:=drvnr+5;
- INCL(DriveBits,drvnr) ; (* set new drive A *)
- INCL(DriveBits,drvnr+1) ; (* set new drive B *)
- INCL(DriveBits,drvnr+2) ; (* set new drive C *)
- INCL(DriveBits,drvnr+3) ; (* set new drive D *)
- INCL(DriveBits,drvnr+4) ; (* set new drive E *)
- INCL(DriveBits,drvnr+5) ; (* set new drive F *)
- networkconnect := FALSE;
- vblactive:=TRUE;
- gotframe := FALSE;
- framebufferfull := FALSE;
- charcount:=0;
- SIZEframe:=TSIZE(frame);
- SIZEframecmd:=TSIZE(framecmd);
-
- vblqueue := vblqueueptr(0456H);
- vblptr := vblqueue^; (* set to address of vbls *)
- rframeptr := ADR(rframe);
- framecmdptr:=ADR(rframe);
- sframeptr := ADR(sframe);
- LOOP (* set up vbl vector to make packet frame from 232 input *)
- IF vblptr^ = ADDRESS(0) THEN
- vblptr^ := ADDRESS(recframe);
- EXIT;
- ELSE
- (*$T-*) INC(vblptr,4) ; (*$T=*)
- END;
- END; (* LOOP *)
- CODE(RTS) ; (* code to return to calling BIOS function *)
- END InstallVectors ;
-
- (*$P+ *)
- PROCEDURE sendf(VAR f: frame);
- BEGIN
- sframe:=f;
- sframe.cksum:=0;
- IF ((sframe.cmd=rdrwabsconf) AND ((sframe.rw=0) OR (sframe.rw=2))) OR ((sframe.cmd=rdrwabsreq) AND ((sframe.rw=1) OR (sframe.rw=3))) THEN
- sndframesize:=SIZEframe;
- sframe.syn := SYN ;
- sframe.stx := STX ;
- sframe.remoteuser := C.USER ;
- sframe.user := REMOTEUSER;
- shortframe:=FALSE;
- IF trace THEN BConOut(CON,":") END;
- ELSE
- sndframesize:=SIZEframecmd;
- sframe.syn := SYN ;
- sframe.stx := SOH ;
- framecmdptr1:=ADR(sframe);
- framecmdptr1^.remoteuser := C.USER ;
- framecmdptr1^.user := REMOTEUSER;
- shortframe:=TRUE;
- IF trace THEN BConOut(CON,".") END;
- END;
- FOR i1:=0 TO sndframesize-5 DO (* compute checksum *)
- sframe.cksum:=sframe.cksum+CARDINAL(sframeptr^[i1])
- END;
- IF shortframe THEN framecmdptr1^.cksum:=sframe.cksum END;
-
- FOR i1:=0 TO sndframesize-1 DO (* send frame *)
- BConOut(HSS,CHAR(sframeptr^[i1]));
- END;
- REPEAT
- UNTIL BCosStat(HSS); (* wait until all sent *)
- END sendf;
-
- PROCEDURE getf(VAR f: frame);
- BEGIN
- f:=rframe;
- framebufferfull:=FALSE;
- END getf;
-
- PROCEDURE waitcts(what: BOOLEAN); (* wait for cleartosend state *)
- BEGIN
- IF what THEN
- REPEAT
- nrecframe;
- Nwait(event);
- HandleEvents();
- IF R>retry THEN
- networkerror:=TRUE;
- RETURN; (* trouble *)
- END;
- UNTIL cleartosend;
- RETURN;
- ELSE
- LOOP
- nrecframe;
- Nwait(event);
- IF (NOT cleartosend) THEN EXIT END;
- HandleEvents();
- IF R>retry THEN
- networkerror:=TRUE;
- RETURN; (* trouble *)
- END;
- END; (* loop *)
- IF trace THEN BConOut(CON,"N") END;
- HandleEvents();
- END;
- END waitcts;
-
- (* request for data from remote hosts disk drives and system *)
- (* what wanted in command, the correct reply in reply, data in f *)
- PROCEDURE getfromremote(command, reply: DataKind; VAR f: frame): BOOLEAN;
- BEGIN
- IF (NOT C.networkactive) THEN RETURN FALSE END; (* error *)
- networkerror:=FALSE;
- R:=0;
- StartTimer;
- vblactive:=FALSE;
- IF trace THEN BConOut(CON,"A") END;
- f.kind:=data;
- f.cmd:=command;
- waitcts(TRUE);
- IF networkerror THEN RETURN FALSE END;
- IF trace THEN BConOut(CON,"B") END;
- SFRAME:=f;
- REMOTEUSER := C.REMOTEUSER;
- requesttosend:=TRUE;
- waitcts(FALSE);
- IF networkerror THEN RETURN FALSE END;
- IF trace THEN BConOut(CON,"C") END;
- REPEAT
- nrecframe;
- Nwait(event);
- HandleEvents();
- IF R>retry THEN networkerror:=TRUE END;
- IF networkerror THEN RETURN FALSE END;
- UNTIL framewaiting AND (RFRAME.cmd=reply);
- IF trace THEN BConOut(CON,"D") END;
- f:=RFRAME;
- f.rw:=5;
- framewaiting:=FALSE;
- REMOTEUSER := C.REMOTEUSER;
- sendtoremote(ack,reply,f); (* send ack for reply *)
- IF networkerror THEN RETURN FALSE END;
- IF trace THEN BConOut(CON,"Z") END;
- vblactive:=TRUE;
- VSync;
- RETURN TRUE;
- END getfromremote;
-
- PROCEDURE sendtoremote(type: FrameKind; command: DataKind;VAR f: frame);
- BEGIN
- IF trace THEN BConOut(CON,"T") END;
- f.kind:=type;
- f.cmd:=command;
- IF debug THEN cleartosend:=TRUE END; (* so we can send in loop *)
- waitcts(TRUE);
- IF trace THEN BConOut(CON,"1") END;
- SFRAME:=f;
- requesttosend:=TRUE;
- waitcts(FALSE);
- IF trace THEN BConOut(CON,"2") END;
- IF SFRAME.kind=ack THEN cleartosend:=TRUE END;
- END sendtoremote;
-
- PROCEDURE ToHost(VAR f: frame);
- BEGIN
- IF trace THEN BConOut(CON,"H") END;
- IF f.kind=diag THEN
- framewaiting:=FALSE;
- RETURN;
- END;
- IF f.kind=data THEN
- IF f.cmd=rdmediareq THEN
- IF trace THEN BConOut(CON,"M") END;
- framewaiting:=FALSE;
- nframe2.d0:=LONGCARD(MediaChange(CARDINAL(f.d0)));
- REMOTEUSER := receivedfromuser;
- sendtoremote(data,rdmediaconf,nframe2);
- RETURN;
- END;
- IF f.cmd=rdbpbreq THEN
- IF trace THEN BConOut(CON,"P") END;
- framewaiting:=FALSE;
- nframe2.d0:=LONGCARD(GetBPB(CARDINAL(f.d0)));
- bpbptr:=ADDRESS(nframe2.d0);
- nbpbptr:=ADR(nframe2.info);
- FOR i:=0 TO TSIZE(BPB)-1 DO
- nbpbptr^[i]:=bpbptr^[i];
- END;
- REMOTEUSER := receivedfromuser;
- sendtoremote(data,rdbpbconf,nframe2);
- RETURN;
- END;
- IF f.cmd=rdrwabsreq THEN
- IF trace THEN BConOut(CON,"W") END;
- framewaiting:=FALSE;
- nframe2.d0:=LONGCARD(RWAbs(RW(f.rw),ADR(f.info),1,f.recno,
- CARDINAL(f.d0)));
- IF (f.rw=0) OR (f.rw=2) THEN
- nframe2.rw:=f.rw;
- nframe2.info:=f.info; (* if rec get buffer to send *)
- END;
- REMOTEUSER := receivedfromuser;
- sendtoremote(data,rdrwabsconf,nframe2);
- RETURN;
- END;
- END;
- END ToHost;
-
- PROCEDURE senddata;
- BEGIN
- SFRAME.seq:=C.nextframetosend[SFRAME.remoteuser];
- SFRAME.ack:=1-C.frameexpected[SFRAME.remoteuser];
- sendf(SFRAME);
- IF (SFRAME.kind#ack) AND (SFRAME.kind#resetreq) THEN
- StartTimer; (* set timer to wait for frame ack from remote host *)
- END;
- END senddata;
-
- PROCEDURE StartTimer;
- BEGIN
- CODE(3f3cH,0017H,4e4eH,548fH); (* gettime *)
- timestart:=LONGCARD(REGISTER(0));
- timer:=TRUE; (* test *)
- timefortimeout:=timestart;
- IncTime(timefortimeout,4);
- END StartTimer;
-
- PROCEDURE IncTime(VAR t : LONGCARD; c: CARDINAL);
- BEGIN
- IF c<1 THEN RETURN END;
-
- time:=t;
- SETREG(0,time);
- CODE(0280H,0,001FH);
- sec:=LONGCARD(REGISTER(0));
-
- time:=t;
- SETREG(0,time);
- CODE(0280H,0,07E0H);
- min:=LONGCARD(REGISTER(0));
- min:=min DIV 32;
-
- time:=t;
- SETREG(0,time);
- CODE(0280H,0,0F800H);
- hour:=LONGCARD(REGISTER(0));
- hour:=hour DIV 2048;
-
- WHILE c#0 DO
- sec:=sec+1;
- c:=c-1;
-
- IF sec>29 THEN
- sec:=sec-30;
- min:=min+1;
- END;
-
- IF min>59 THEN
- min:=min-60;
- hour:=hour+1;
- END;
-
- IF hour>23 THEN
- hour:=hour-24;
- END;
- END; (* while *)
- t:=0;
- t:=sec;
- t:=t+(min*32);
- t:=t+(hour*2048);
- END IncTime;
-
- PROCEDURE TimeOut(): BOOLEAN;
- BEGIN
- IF (NOT timer) THEN RETURN FALSE END;
- CODE(3f3cH,0017H,4e4eH,548fH); (* gettime *)
- timeouttime:=LONGCARD(REGISTER(0));
- SETREG(0,timeouttime);
- CODE(0280H,0,0FFFFH);
- timeouttime:=LONGCARD(REGISTER(0));
- IF timeouttime>timefortimeout THEN
- StartTimer;
- RETURN TRUE;
- END;
- RETURN FALSE;
- END TimeOut;
-
- PROCEDURE Nwait(VAR e: evtype);
- BEGIN
-
- IF requesttosend AND cleartosend THEN
- e:=hostready;
- requesttosend:=FALSE;
- cleartosend:=FALSE;
- RETURN;
- END;
-
- IF C.sendreset THEN
- e:=reset;
- END;
-
- IF framebufferfull THEN
- cksum:=0;
- FOR i2:=0 TO recframesize-5 DO
- cksum:=cksum+CARDINAL(rframeptr^[i2])
- END;
- IF (cksum=rframe.cksum) THEN
- receivedfromuser := rframe.remoteuser;
- e:=framearrival;
- INC(R);
- ELSE
- e:=cksumerr;
- framebufferfull:=FALSE;
- IF trace THEN BConOut(CON,"U") END;
- END;
- RETURN;
- END;
- nrecframe;
- IF TimeOut() THEN
- e:=timeout;
- INC(R);
- END; (* so sorry no frame ack *)
- END Nwait;
-
- PROCEDURE HandleEvents();
- BEGIN
- IF event=hostready THEN
- event:=nothing;
- IF trace THEN BConOut(CON,"S") END;
- senddata;
- END;
-
- IF event=reset THEN
- IF trace THEN BConOut(CON,"I") END;
- charcount:=0;
- R:=0;
- gotframe:=FALSE;
- framebufferfull:=FALSE;
- FOR d:=0 TO 5 DO
- gotmediach[d]:=FALSE;
- gotbpb[d]:=FALSE;
- END;
- C.nextframetosend[SFRAME.remoteuser]:=0;
- C.frameexpected[SFRAME.remoteuser]:=0;
- cleartosend:=TRUE;
- requesttosend:=FALSE;
- framewaiting:=FALSE;
- timer:=FALSE;
- C.sendreset:=FALSE;
- event:=nothing;
- SFRAME.kind:=resetreq;
- senddata;
- END;
-
- IF event=framearrival THEN
- event:=nothing;
-
- IF (rframe.kind=ack) OR (rframe.kind=resetreq) THEN
- framewaiting:=FALSE
- END;
- IF trace AND (NOT framewaiting) THEN BConOut(CON,"F") END;
-
- IF (NOT framewaiting) THEN getf(RFRAME) END;
- framebufferfull:=FALSE;
-
- IF (RFRAME.ack=C.nextframetosend[RFRAME.remoteuser]) OR debug THEN
- IF trace THEN BConOut(CON,"K") END;
- cleartosend:=TRUE;
- StartTimer;
- R:=0;
- timer:=FALSE;
- inc(C.nextframetosend[RFRAME.remoteuser]);
- END;
-
- IF (RFRAME.seq=C.frameexpected[RFRAME.remoteuser]) OR debug THEN
- IF trace THEN BConOut(CON,"E") END;
- IF RFRAME.kind#ack THEN (* try to exec command *)
- inc(C.frameexpected[RFRAME.remoteuser]);
- framewaiting:=TRUE;
- R:=0;
- ToHost(RFRAME);
- END;
- END;
- IF RFRAME.kind=resetreq THEN
- IF trace THEN BConOut(CON,"*") END;
- charcount:=0;
- gotframe:=FALSE;
- framebufferfull:=FALSE;
- C.nextframetosend[RFRAME.remoteuser]:=0;
- C.frameexpected[RFRAME.remoteuser]:=0;
- FOR d:=0 TO 5 DO
- gotmediach[d]:=FALSE;
- gotbpb[d]:=FALSE;
- END;
- cleartosend:=TRUE;
- requesttosend:=FALSE;
- framewaiting:=FALSE;
- timer:=FALSE;
- C.sendreset:=FALSE;
- event:=nothing;
- END;
- END;
-
- SFRAME.seq:=C.nextframetosend[SFRAME.remoteuser];
- SFRAME.ack:=1-C.frameexpected[SFRAME.remoteuser];
-
- IF event=timeout THEN
- event:=nothing;
- IF trace THEN BConOut(CON,"R") END;
- sendf(SFRAME);
- framewaiting:=FALSE;
- END;
- END HandleEvents;
-
- BEGIN (* body of module *)
- IF Initialise() THEN
-
- charcount:=0;
- gotframe:=FALSE;
- framebufferfull:=FALSE;
- FOR d:=0 TO 15 DO
- C.nextframetosend[d]:=0;
- C.frameexpected[d]:=0;
- END;
- FOR d:=0 TO 5 DO
- gotmediach[d]:=FALSE;
- gotbpb[d]:=FALSE;
- END;
- cleartosend:=TRUE;
- requesttosend:=FALSE;
- framewaiting:=FALSE;
- timer:=FALSE;
- C.sendreset:=FALSE;
- event:=nothing;
- C.networkactive:=TRUE;
- SuperExec(PROC(InstallVectors)) ; (* install the NETWORK *)
- Open("ANETMIDI.INT",0,handle);
- IF handle>0 THEN (* if there is, load in init file *)
- count:=TSIZE(consave);
- GEMDOS.Read(handle,count,ADR(C));
- OK:=Close(handle);
- END;
- WITH BasePageAddress^ DO
- TermRes(CodeLen+BssLen+LONGCARD(CodeBase-ADDRESS(BasePageAddress)),0);
- END;
- END ;
- END NETWORK.
-