diff --git a/Makefile.mk b/Makefile.mk index a44c4cf..7d8e735 100644 --- a/Makefile.mk +++ b/Makefile.mk @@ -1,6 +1,6 @@ CFLAGS = -i -w -DSITEST_OBJS = dsitest.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o +DSITEST_OBJS = dsitest.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o asmglue.o DSITEST_PROG = dsitest AFPMOUNTER_OBJS = afpmounter.o callat.o endian.o @@ -9,7 +9,10 @@ AFPMOUNTER_PROG = afpmounter DUMPCMDTBL_OBJS = dumpcmdtbl.o asmglue.o DUMPCMDTBL_PROG = dumpcmdtbl -PROGS = $(DSITEST_PROG) $(AFPMOUNTER_PROG) $(DUMPCMDTBL_PROG) +AFPBRIDGE_OBJS = afpbridge.o aspinterface.o dsi.o readtcp.o endian.o tcpconnection.o atipmapping.o asmglue.o installcmds.o cmdproc.o callat.o +AFPBRIDGE_PROG = afpbridge + +PROGS = $(DSITEST_PROG) $(AFPMOUNTER_PROG) $(DUMPCMDTBL_PROG) $(AFPBRIDGE_PROG) .PHONY: $(PROGS) default: $(PROGS) @@ -23,6 +26,9 @@ $(AFPMOUNTER_PROG): $(AFPMOUNTER_OBJS) $(DUMPCMDTBL_PROG): $(DUMPCMDTBL_OBJS) occ $(CFLAGS) -o $@ $(DUMPCMDTBL_OBJS) +$(AFPBRIDGE_PROG): $(AFPBRIDGE_OBJS) + occ $(CFLAGS) -o $@ $(AFPBRIDGE_OBJS) + %.macros: %.asm macgen $< $@ /lang/orca/Libraries/ORCAInclude/m16.* diff --git a/afpbridge.c b/afpbridge.c new file mode 100644 index 0000000..6abe5b9 --- /dev/null +++ b/afpbridge.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "installcmds.h" +#include "aspinterface.h" +#include "dsi.h" +#include "asmglue.h" + +int main(void) { + Boolean loadedTCP = FALSE; + Boolean startedTCP = FALSE; + + if (!TCPIPStatus()) { + LoadOneTool(54, 0x0300); /* load Marinetti 3.0+ */ + if (toolerror()) + goto error; + loadedTCP = TRUE; + TCPIPStartUp(); + if (toolerror()) + goto error; + startedTCP = TRUE; + } + + installCmds(); + + while (TRUE) { + IncBusyFlag(); + PollAllSessions(); + DecBusyFlag(); + asm { cop 0x7f } + } + +error: + if (startedTCP) + TCPIPShutDown(); + if (loadedTCP) + UnloadOneTool(54); + return; +} diff --git a/asmglue.asm b/asmglue.asm index f71b3c4..d8e9526 100644 --- a/asmglue.asm +++ b/asmglue.asm @@ -1,6 +1,7 @@ case on mcopy asmglue.macros +ROMIN gequ $C081 LCBANK2 gequ $C083 STATEREG gequ $C068 @@ -15,6 +16,17 @@ ForceLCBank2 start rtl end +ForceRomIn start + short i,m + lda >STATEREG ;get original state reg. + tax + lda >ROMIN ;force ROM in to Language Card space + lda >ROMIN + long i,m + txa + rtl + end + RestoreStateReg start short m plx @@ -27,3 +39,7 @@ RestoreStateReg start long m rtl end + +completionRtn data + ds 4 + end diff --git a/asmglue.h b/asmglue.h index 1159d4a..48a04cd 100644 --- a/asmglue.h +++ b/asmglue.h @@ -4,6 +4,7 @@ #include extern Word ForceLCBank2(void); +extern Word ForceRomIn(void); extern void RestoreStateReg(Word); void IncBusyFlag(void) inline(0, 0xE10064); diff --git a/aspinterface.c b/aspinterface.c index 863886b..eb93bc4 100644 --- a/aspinterface.c +++ b/aspinterface.c @@ -9,6 +9,7 @@ #include "tcpconnection.h" #include "endian.h" #include "readtcp.h" +#include "asmglue.h" static void CompleteCommand(Session *sess, Word result); static void EndSession(Session *sess, Boolean callAttnRoutine); @@ -22,9 +23,13 @@ static void DoSPWrite(Session *sess, ASPWriteRec *commandRec); Session sessionTbl[MAX_SESSIONS]; +#pragma databank 1 void DispatchASPCommand(SPCommandRec *commandRec) { Session *sess; unsigned int i; + Word stateReg; + + stateReg = ForceRomIn(); if (commandRec->command == aspGetStatusCommand || commandRec->command==aspOpenSessionCommand) @@ -35,21 +40,22 @@ void DispatchASPCommand(SPCommandRec *commandRec) { } if (i == MAX_SESSIONS) { CompleteCommand(sess, aspTooManySessions); - return; + goto ret; } sess = &sessionTbl[i]; sess->spCommandRec = commandRec; if (!StartTCPConnection(sess)) { FlagFatalError(sess, 0); - return; + goto ret; } sess->dsiStatus = awaitingHeader; InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); } else { if (commandRec->refNum < SESSION_NUM_START) { // TODO call original AppleTalk routine (or do it earlier) - return; + commandRec->result = atInvalidCmdErr; + goto ret; } i = commandRec->refNum - SESSION_NUM_START; sess = &sessionTbl[i]; @@ -61,7 +67,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { if (commandRec->command != aspCloseSessionCommand) { if (sess->commandPending) { CompleteCommand(sess, aspSessNumErr); - return; + goto ret; } sess->commandPending = TRUE; } @@ -86,7 +92,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) { if ((commandRec->async & AT_ASYNC) && sess->commandPending) { commandRec->result = aspBusyErr; // indicate call in process - return; + goto ret; } // if we're here, the call is synchronous -- we must complete it @@ -98,7 +104,11 @@ void DispatchASPCommand(SPCommandRec *commandRec) { PollForData(sess); } } + +ret: + RestoreStateReg(stateReg); } +#pragma databank 0 static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { static const Word kFPGetSrvrInfo = 15; @@ -143,10 +153,13 @@ static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { sess->request.requestID = htons(sess->nextRequestID++); sess->request.writeOffset = 0; sess->request.totalDataLength = htonl(commandRec->cmdBlkLength); - sess->replyBuf = (void*)commandRec->replyBufferAddr; + sess->replyBuf = (void*)(commandRec->replyBufferAddr & 0x00FFFFFF); sess->replyBufLen = commandRec->replyBufferLen; - SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr, NULL); + /* Mask off high byte of addresses because PFI (at least) may + * put junk in them, and this can cause Marinetti errors. */ + SendDSIMessage(sess, &sess->request, + (void*)(commandRec->cmdBlkAddr & 0x00FFFFFF), NULL); } static void DoSPWrite(Session *sess, ASPWriteRec *commandRec) { @@ -156,11 +169,12 @@ static void DoSPWrite(Session *sess, ASPWriteRec *commandRec) { sess->request.writeOffset = htonl(commandRec->cmdBlkLength); sess->request.totalDataLength = htonl(commandRec->cmdBlkLength + commandRec->writeDataLength); - sess->replyBuf = (void*)commandRec->replyBufferAddr; + sess->replyBuf = (void*)(commandRec->replyBufferAddr & 0x00FFFFFF); sess->replyBufLen = commandRec->replyBufferLen; - SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr, - (void*)commandRec->writeDataAddr); + SendDSIMessage(sess, &sess->request, + (void*)(commandRec->cmdBlkAddr & 0x00FFFFFF), + (void*)(commandRec->writeDataAddr & 0x00FFFFFF)); } @@ -231,7 +245,10 @@ static void CompleteCommand(Session *sess, Word result) { EndSession(sess, FALSE); } else { sess->commandPending = FALSE; - InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); + if (sess->dsiStatus != error) { + sess->dsiStatus = awaitingHeader; + InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); + } } commandRec->result = result; @@ -248,3 +265,13 @@ static void EndSession(Session *sess, Boolean callAttnRoutine) { EndTCPConnection(sess); memset(sess, 0, sizeof(*sess)); } + +void PollAllSessions(void) { + unsigned int i; + + for (i = 0; i < MAX_SESSIONS; i++) { + if (sessionTbl[i].dsiStatus != unused) { + PollForData(&sessionTbl[i]); + } + } +} diff --git a/aspinterface.h b/aspinterface.h index ec08e1b..e6f1212 100644 --- a/aspinterface.h +++ b/aspinterface.h @@ -17,5 +17,6 @@ extern Session sessionTbl[MAX_SESSIONS]; void DispatchASPCommand(SPCommandRec *commandRec); void FinishASPCommand(Session *sess); void FlagFatalError(Session *sess, Word errorCode); +void PollAllSessions(void); #endif diff --git a/cmdproc.asm b/cmdproc.asm new file mode 100644 index 0000000..fc5658d --- /dev/null +++ b/cmdproc.asm @@ -0,0 +1,23 @@ + case on + +* Location of command rec ptr on entry to an AppleTalk command procedure +* (in the system zero page, which is the current direct page) +cmdRecPtr gequ $80 + +* Bogus segment to go into the .root file and force generation of .a/.o file +bogus private + nop + end + +* AppleTalk command procedure (which acts as a dispatcher for all commands) +cmdProc start + lda 3,s + pha + lda 3,s + pha + lda cmdRecPtr + sta 4,s + lda cmdRecPtr+2 + sta 6,s + jml DispatchASPCommand + end diff --git a/dsi.c b/dsi.c index 6c60d14..7531cdc 100644 --- a/dsi.c +++ b/dsi.c @@ -166,6 +166,9 @@ top: FlagFatalError(sess, aspNetworkErr); return; } + + sess->dsiStatus = awaitingHeader; + InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); } else { diff --git a/installcmds.c b/installcmds.c new file mode 100644 index 0000000..3f1c70d --- /dev/null +++ b/installcmds.c @@ -0,0 +1,50 @@ +#pragma noroot + +#include +#include +#include "asmglue.h" + +extern void cmdProc(void); +extern LongWord completionRtn; + +typedef struct NewCmd { + Word cmdNum; + void (*cmdAddr)(void); +} NewCmd; + +NewCmd newCmds[] = { + {aspGetStatusCommand, cmdProc}, + {aspOpenSessionCommand, cmdProc}, + {aspCloseSessionCommand, cmdProc}, + {aspCommandCommand, cmdProc}, + {aspWriteCommand, cmdProc}, + {0, 0} +}; + +LongWord *cmdTable = (LongWord *)0xE1D600; + +#define MAX_CMD rpmFlushSessionCommand + +LongWord oldCmds[MAX_CMD + 1]; /* holds old entries for commands we changed */ + +ATGetInfoRec getInfoRec; + +void installCmds(void) { + Word savedStateReg; + NewCmd *cmd; + + getInfoRec.async = 0; + getInfoRec.command = atGetInfoCommand; + _CALLAT(&getInfoRec); + completionRtn = getInfoRec.completionRtn; + + savedStateReg = ForceLCBank2(); + + for (cmd = newCmds; cmd->cmdNum != 0; cmd++) { + oldCmds[cmd->cmdNum] = cmdTable[cmd->cmdNum]; + cmdTable[cmd->cmdNum] = + (oldCmds[cmd->cmdNum] & 0xFF000000) | (LongWord)cmd->cmdAddr; + } + + RestoreStateReg(savedStateReg); +} diff --git a/installcmds.h b/installcmds.h new file mode 100644 index 0000000..468babf --- /dev/null +++ b/installcmds.h @@ -0,0 +1,6 @@ +#ifndef INSTALLCMDS_H +#define INSTALLCMDS_H + +void installCmds(void); + +#endif