Implement support for DSIWrite, plus a few other cleanups.

This commit is contained in:
Stephen Heumann 2017-03-23 02:31:06 -05:00
parent 275f3456ba
commit ee83e402f8
6 changed files with 141 additions and 63 deletions

View File

@ -10,11 +10,14 @@
#include "endian.h" #include "endian.h"
#include "readtcp.h" #include "readtcp.h"
void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec); static void CompleteCommand(Session *sess, Word result);
void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec); static void EndSession(Session *sess, Boolean callAttnRoutine);
void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec);
void DoSPCommand(Session *sess, ASPCommandRec *commandRec); static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec);
void DoSPWrite(Session *sess, ASPWriteRec *commandRec); static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec);
static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec);
static void DoSPCommand(Session *sess, ASPCommandRec *commandRec);
static void DoSPWrite(Session *sess, ASPWriteRec *commandRec);
Session sessionTbl[MAX_SESSIONS]; Session sessionTbl[MAX_SESSIONS];
@ -31,16 +34,14 @@ void DispatchASPCommand(SPCommandRec *commandRec) {
break; break;
} }
if (i == MAX_SESSIONS) { if (i == MAX_SESSIONS) {
commandRec->result = aspTooManySessions; CompleteCommand(sess, aspTooManySessions);
CompleteCommand(sess);
return; return;
} }
sess = &sessionTbl[i]; sess = &sessionTbl[i];
sess->spCommandRec = commandRec; sess->spCommandRec = commandRec;
if (!StartTCPConnection(sess)) { if (!StartTCPConnection(sess)) {
// Error code was set in TCPIPConnect FlagFatalError(sess, 0);
CompleteCommand(sess);
return; return;
} }
sess->dsiStatus = awaitingHeader; sess->dsiStatus = awaitingHeader;
@ -59,8 +60,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) {
// one is in progress // one is in progress
if (commandRec->command != aspCloseSessionCommand) { if (commandRec->command != aspCloseSessionCommand) {
if (sess->commandPending) { if (sess->commandPending) {
commandRec->result = aspSessNumErr; CompleteCommand(sess, aspSessNumErr);
CompleteCommand(sess);
return; return;
} }
sess->commandPending = TRUE; sess->commandPending = TRUE;
@ -100,7 +100,7 @@ void DispatchASPCommand(SPCommandRec *commandRec) {
} }
} }
void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) { static void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) {
static const Word kFPGetSrvrInfo = 15; static const Word kFPGetSrvrInfo = 15;
sess->request.flags = DSI_REQUEST; sess->request.flags = DSI_REQUEST;
sess->request.command = DSIGetStatus; sess->request.command = DSIGetStatus;
@ -110,10 +110,10 @@ void DoSPGetStatus(Session *sess, ASPGetStatusRec *commandRec) {
sess->replyBuf = (void*)commandRec->bufferAddr; sess->replyBuf = (void*)commandRec->bufferAddr;
sess->replyBufLen = commandRec->bufferLength; sess->replyBufLen = commandRec->bufferLength;
SendDSIMessage(sess, &sess->request, &kFPGetSrvrInfo); SendDSIMessage(sess, &sess->request, &kFPGetSrvrInfo, NULL);
} }
void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) { static void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) {
sess->request.flags = DSI_REQUEST; sess->request.flags = DSI_REQUEST;
sess->request.command = DSIOpenSession; sess->request.command = DSIOpenSession;
sess->request.requestID = htons(sess->nextRequestID++); sess->request.requestID = htons(sess->nextRequestID++);
@ -122,10 +122,10 @@ void DoSPOpenSession(Session *sess, ASPOpenSessionRec *commandRec) {
sess->replyBuf = NULL; sess->replyBuf = NULL;
sess->replyBufLen = 0; sess->replyBufLen = 0;
SendDSIMessage(sess, &sess->request, NULL); SendDSIMessage(sess, &sess->request, NULL, NULL);
} }
void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) { static void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) {
sess->request.flags = DSI_REQUEST; sess->request.flags = DSI_REQUEST;
sess->request.command = DSICloseSession; sess->request.command = DSICloseSession;
sess->request.requestID = htons(sess->nextRequestID++); sess->request.requestID = htons(sess->nextRequestID++);
@ -134,10 +134,10 @@ void DoSPCloseSession(Session *sess, ASPCloseSessionRec *commandRec) {
sess->replyBuf = NULL; sess->replyBuf = NULL;
sess->replyBufLen = 0; sess->replyBufLen = 0;
SendDSIMessage(sess, &sess->request, NULL); SendDSIMessage(sess, &sess->request, NULL, NULL);
} }
void DoSPCommand(Session *sess, ASPCommandRec *commandRec) { static void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
sess->request.flags = DSI_REQUEST; sess->request.flags = DSI_REQUEST;
sess->request.command = DSICommand; sess->request.command = DSICommand;
sess->request.requestID = htons(sess->nextRequestID++); sess->request.requestID = htons(sess->nextRequestID++);
@ -146,13 +146,39 @@ void DoSPCommand(Session *sess, ASPCommandRec *commandRec) {
sess->replyBuf = (void*)commandRec->replyBufferAddr; sess->replyBuf = (void*)commandRec->replyBufferAddr;
sess->replyBufLen = commandRec->replyBufferLen; sess->replyBufLen = commandRec->replyBufferLen;
SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr); SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr, NULL);
} }
void DoSPWrite(Session *sess, ASPWriteRec *commandRec) { static void DoSPWrite(Session *sess, ASPWriteRec *commandRec) {
// TODO sess->request.flags = DSI_REQUEST;
sess->request.command = DSIWrite;
sess->request.requestID = htons(sess->nextRequestID++);
sess->request.writeOffset = htonl(commandRec->cmdBlkLength);
sess->request.totalDataLength =
htonl(commandRec->cmdBlkLength + commandRec->writeDataLength);
sess->replyBuf = (void*)commandRec->replyBufferAddr;
sess->replyBufLen = commandRec->replyBufferLen;
SendDSIMessage(sess, &sess->request, (void*)commandRec->cmdBlkAddr,
(void*)commandRec->writeDataAddr);
} }
void FlagFatalError(Session *sess, Word errorCode) {
sess->dsiStatus = error;
if (errorCode == 0) {
// TODO deduce better error code from Marinetti errors?
errorCode = aspNetworkErr;
}
if (sess->commandPending) {
CompleteCommand(sess, errorCode);
}
EndSession(sess, TRUE);
}
// Fill in any necessary data in the ASP command rec for a successful return // Fill in any necessary data in the ASP command rec for a successful return
void FinishASPCommand(Session *sess) { void FinishASPCommand(Session *sess) {
LongWord dataLength; LongWord dataLength;
@ -181,30 +207,44 @@ void FinishASPCommand(Session *sess) {
((ASPCommandRec*)(sess->spCommandRec))->replyLength = dataLength; ((ASPCommandRec*)(sess->spCommandRec))->replyLength = dataLength;
break; break;
case aspWriteCommand: case aspWriteCommand:
// TODO ((ASPWriteRec*)(sess->spCommandRec))->cmdResult =
sess->reply.errorCode;
((ASPWriteRec*)(sess->spCommandRec))->replyLength = dataLength;
((ASPWriteRec*)(sess->spCommandRec))->writtenLength =
((ASPWriteRec*)(sess->spCommandRec))->writeDataLength;
break; break;
} }
complete: complete:
CompleteCommand(sess); CompleteCommand(sess, 0);
} }
/* Actions to complete a command, whether successful or not */ /* Actions to complete a command, whether successful or not */
void CompleteCommand(Session *sess) { static void CompleteCommand(Session *sess, Word result) {
SPCommandRec *commandRec;
commandRec = sess->spCommandRec;
if (sess->spCommandRec->command == aspGetStatusCommand if (sess->spCommandRec->command == aspGetStatusCommand
|| sess->spCommandRec->command == aspCloseSessionCommand) || sess->spCommandRec->command == aspCloseSessionCommand)
{ {
EndTCPConnection(sess); EndSession(sess, FALSE);
}
// TODO call completion routine
if (sess->spCommandRec->command == aspGetStatusCommand
|| sess->spCommandRec->command == aspCloseSessionCommand)
{
memset(sess, 0, sizeof(*sess));
} else { } else {
sess->commandPending = FALSE; sess->commandPending = FALSE;
InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply); InitReadTCP(sess, DSI_HEADER_SIZE, &sess->reply);
} }
commandRec->result = result;
// TODO call completion routine
}
static void EndSession(Session *sess, Boolean callAttnRoutine) {
if (callAttnRoutine) {
// TODO call the attention routine to report end of session
}
EndTCPConnection(sess);
memset(sess, 0, sizeof(*sess));
} }

View File

@ -16,6 +16,6 @@ extern Session sessionTbl[MAX_SESSIONS];
void DispatchASPCommand(SPCommandRec *commandRec); void DispatchASPCommand(SPCommandRec *commandRec);
void FinishASPCommand(Session *sess); void FinishASPCommand(Session *sess);
void CompleteCommand(Session *sess); void FlagFatalError(Session *sess, Word errorCode);
#endif #endif

45
dsi.c
View File

@ -30,43 +30,40 @@ static DSIRequestHeader attentionReplyRec = {
0 /* reserved */ 0 /* reserved */
}; };
void FlagFatalError(Session *sess, Word errorCode) {
sess->dsiStatus = error;
if (errorCode) {
if (sess->commandPending) {
sess->spCommandRec->result = errorCode;
}
} else {
// TODO deduce error code from Marinetti errors
}
CompleteCommand(sess);
}
void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload,
void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload) { void *extraPayload) {
Boolean hasData; LongWord cmdLen;
LongWord extraLen;
hasData = header->totalDataLength != 0;
sess->tcperr = TCPIPWriteTCP(sess->ipid, (void*)header, sess->tcperr = TCPIPWriteTCP(sess->ipid, (void*)header,
DSI_HEADER_SIZE, DSI_HEADER_SIZE,
!hasData, FALSE); !header->totalDataLength, FALSE);
sess->toolerr = toolerror(); sess->toolerr = toolerror();
if (sess->tcperr || sess->toolerr) { if (sess->tcperr || sess->toolerr) {
FlagFatalError(sess, 0); FlagFatalError(sess, 0);
return; return;
} }
if (hasData) { if (header->writeOffset) {
sess->tcperr = TCPIPWriteTCP(sess->ipid, payload, cmdLen = ntohl(header->writeOffset);
ntohl(header->totalDataLength), extraLen = ntohl(header->totalDataLength) - cmdLen;
TRUE, FALSE); } else {
cmdLen = ntohl(header->totalDataLength);
extraLen = 0;
}
while (cmdLen) {
sess->tcperr = TCPIPWriteTCP(sess->ipid, payload, cmdLen,
!extraLen, FALSE);
sess->toolerr = toolerror(); sess->toolerr = toolerror();
if (sess->tcperr || sess->toolerr) { if (sess->tcperr || sess->toolerr) {
FlagFatalError(sess, 0); FlagFatalError(sess, 0);
return; return;
} }
cmdLen = extraLen;
payload = extraPayload;
extraLen = 0;
} }
} }
@ -158,13 +155,13 @@ top:
{ {
if (sess->reply.command == DSIAttention) { if (sess->reply.command == DSIAttention) {
attentionReplyRec.requestID = sess->reply.requestID; attentionReplyRec.requestID = sess->reply.requestID;
SendDSIMessage(sess, &attentionReplyRec, NULL); SendDSIMessage(sess, &attentionReplyRec, NULL, NULL);
//TODO call attention routine. //TODO call attention routine.
} else if (sess->reply.command == DSICloseSession) { } else if (sess->reply.command == DSICloseSession) {
// TODO handle close // TODO handle close
} else if (sess->reply.command == DSITickle) { } else if (sess->reply.command == DSITickle) {
tickleRequestRec.requestID = htons(sess->nextRequestID++); tickleRequestRec.requestID = htons(sess->nextRequestID++);
SendDSIMessage(sess, &tickleRequestRec, NULL); SendDSIMessage(sess, &tickleRequestRec, NULL, NULL);
} else { } else {
FlagFatalError(sess, aspNetworkErr); FlagFatalError(sess, aspNetworkErr);
return; return;

3
dsi.h
View File

@ -4,7 +4,8 @@
#include "dsiproto.h" #include "dsiproto.h"
#include "session.h" #include "session.h"
void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload); void SendDSIMessage(Session *sess, DSIRequestHeader *header, void *payload,
void *extraPayload);
void PollForData(Session *sess); void PollForData(Session *sess);
#endif #endif

View File

@ -5,13 +5,32 @@
#include <orca.h> #include <orca.h>
#include "aspinterface.h" #include "aspinterface.h"
#include "atipmapping.h" #include "atipmapping.h"
#include "endian.h"
ASPGetStatusRec getStatusRec; ASPGetStatusRec getStatusRec;
ASPOpenSessionRec openSessionRec; ASPOpenSessionRec openSessionRec;
ASPCommandRec commandRec; ASPCommandRec commandRec;
ASPWriteRec writeRec;
ASPCloseSessionRec closeSessionRec; ASPCloseSessionRec closeSessionRec;
Byte replyBuffer[1024]; Byte replyBuffer[1024];
struct FPFlushRec {
Byte CommandCode;
Byte Pad;
Word VolumeID;
} fpFlushRec;
struct FPWriteRec {
Byte CommandCode;
Byte Flag;
Word OForkRefNum;
LongWord Offset;
LongWord ReqCount;
} fpWriteRec;
#define kFPFlush 10
#define kFPWrite 33
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Boolean loadedTCP = FALSE; Boolean loadedTCP = FALSE;
@ -81,14 +100,32 @@ int main(int argc, char **argv)
printf("result code = %04x\n", openSessionRec.result); printf("result code = %04x\n", openSessionRec.result);
if (openSessionRec.result) if (openSessionRec.result)
goto error; goto error;
writeRec.async = AT_SYNC;
writeRec.command = aspWriteCommand;
writeRec.completionPtr = 0;
writeRec.refNum = openSessionRec.refNum;
writeRec.cmdBlkLength = sizeof(fpWriteRec);
writeRec.cmdBlkAddr = (LongWord)&fpWriteRec;
fpWriteRec.CommandCode = kFPWrite;
fpWriteRec.ReqCount = htonl(16);
writeRec.writeDataLength = 16;
writeRec.writeDataAddr = (LongWord)&openSessionRec;
writeRec.replyBufferLen = sizeof(replyBuffer);
writeRec.replyBufferAddr = (LongWord)&replyBuffer;
printf("Sending write...\n");
DispatchASPCommand((SPCommandRec *)&writeRec);
printf("result code = %04x, write result = %08lx\n",
writeRec.result, writeRec.cmdResult);
commandRec.async = AT_SYNC; commandRec.async = AT_SYNC;
commandRec.command = aspCommandCommand; commandRec.command = aspCommandCommand;
commandRec.completionPtr = 0; commandRec.completionPtr = 0;
commandRec.refNum = openSessionRec.refNum; commandRec.refNum = openSessionRec.refNum;
// FIXME this sends meaningless garbage, not a real AFP request commandRec.cmdBlkLength = sizeof(fpFlushRec);
commandRec.cmdBlkLength = 10; commandRec.cmdBlkAddr = (LongWord)&fpFlushRec;
commandRec.cmdBlkAddr = (LongWord)&openSessionRec; fpFlushRec.CommandCode = kFPFlush;
commandRec.replyBufferLen = sizeof(replyBuffer); commandRec.replyBufferLen = sizeof(replyBuffer);
commandRec.replyBufferAddr = (LongWord)&replyBuffer; commandRec.replyBufferAddr = (LongWord)&replyBuffer;

View File

@ -3,7 +3,10 @@
#include <types.h> #include <types.h>
/* Undefine these in case they're defined as macros */ /*
* Undefine these in case they're defined as macros.
* (In particular, GNO has broken macro definitions for these.)
*/
#undef htons #undef htons
#undef ntohs #undef ntohs
#undef htonl #undef htonl