All FujiNet networking functions can be done with writes to the correct AdamNet DCB, we just need a few bits of info, here's the data structure for a DCB in C:
Code: Select all
typedef struct _dcb
{
unsigned char status; // 1
void *buf; // 2
unsigned short len; // 2
unsigned long block; // 4
unsigned char unit; // 1
unsigned char reserved0; // 1
unsigned char reserved1; // 1
unsigned char reserved2; // 1
unsigned char reserved3; // 1
unsigned char reserved4; // 1
unsigned char reserved5; // 1
unsigned char dev; // 1
unsigned short max_len; // 2
unsigned char type; // 1
unsigned char dev_status; // 1
} DCB; // 21 bytes total
Notable entries:
* status - This does double duty, as both the status and command byte. You write the command, the Adam does the operation, and writes back a status sometime later.
* buf - 16 bit memory address in Z80 space for the target operation
* len - Length of I/O operation relative to the buffer.
* block - Used by block devices to denote the desired 32-bit block address.
* unit - logical unit number specified.
* dev - The Adamnet node number for this device. (1 = keyboard, 2 = printer, etc.)
* max_len - The maximum size of payload allowed for this device
* type - Device type, 0 = character, 1 = block
* dev_status - The 8-bit status byte returned in the last byte of a status packet.
So all we have to do for a typical program is to:
* Define a data structure that nicely maps a DCB
* Find the DCB we want in memory by comparing against the dev entry until we find it.
* Write to that section of memory any time we want something to happen for FujiNet
* Periodically poll status to see when that operation is considered complete by the 6801.
For MBASIC, I was able to do this with the following code:
Code: Select all
64000 REM FUJINET ROUTINES
64010 REM ----------------
64011 REM DCB FUNCS
64012 REM ----------------
64020 DCBLEN=21:DCBEGIN=&HFEC4:DCBNUM=&HFEC3
64021 NET$=STRING$(255,0)
64022 STAT=1:WRI=3:REA=4
64030 DEF FN DCB(X)=X*DCBLEN+DCBEGIN
64040 DEF FN DCBSTATUS(X)=PEEK(FNDCB(X))
64050 DEF FN DCBCMD(X)=FNDCB(X)
64060 DEF FN DCBBUFL(X)=FNDCB(X)+1
64061 DEF FN DCBBUFH(X)=FNDCB(X)+2
64070 DEF FN DCBDEVSTATUS(X)=PEEK(FNDCB(X)+20)
64080 DEF FN DCBDEV(X)=PEEK(FNDCB(X)+16)
64081 DEF FN DCBLENL(X)=FNDCB(X)+3
64082 DEF FN DCBLENH(X)=FNDCB(X)+4
64090 DEF FN DCBNUM(X)=PEEK(DCBNUM)
You can then find the correct DCB with the following code:
Code: Select all
64093 REM --------
64100 REM FIND DCB
64101 REM --------
64110 FOR X=0 TO FNDCBNUM(0)-1
64120 IF FNDCBDEV(X)=9 THEN NET=X:RETURN
64130 NEXT X
64140 RETURN
We can then send network operations with the following common code:
Code: Select all
64150 REM --------------------
64200 REM DO FUJINET OPERATION
64210 REM --------------------
64220 GOSUB 64100:REM FIND DCB
64230 POKE FNDCBBUFL(NET),PEEK(VARPTR(NET$)+1)
64240 POKE FNDCBBUFH(NET),PEEK(VARPTR(NET$)+2)
64250 POKE FNDCBLENL(NET),PEEK(VARPTR(NET$))
64260 POKE FNDCBLENH(NET),0
64270 POKE FNDCBCMD(NET),CMD
64280 IF FNDCBSTATUS(NET)<&H80 THEN GOTO 64280
64290 RETURN
After this, it's a simple matter of checking the status byte for the last bit set, to indicate that the command has completed.
After this, doing FujiNet commands is as simple as:
Code: Select all
NET$="O"+CHR$(12)+CHR$(0)+"N:TCP://192.168.1.10:8080/":CMD=WRI:GOSUB 64200:REM OPEN
NET$="WTHIS STRING GETS WRITTEN OUT."+CHR$(13):CMD=WRI:GOSUB 64200 REM WRITE
NET$="C":CMD=WRI:GOSUB 64200:REM CLOSE
NET$=STRING$(255,0):CMD=REA:GOSUB 64200:REM READ ANYTHING WAITING INTO NET$
-Thom