diff --git a/Makefile b/Makefile index b540732..ac994ee 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS = -w-1 -O-1 HTTPTEST_OBJS = httptest.a hostname.a http.a readtcp.a seturl.a strcasecmp.a tcpconnection.a urlparser.a HTTPTEST_PROG = httptest -NETDISKINIT_OBJS = initstart.a netdiskinit.a hostname.a http.a readtcp.a seturl.a strcasecmp.a tcpconnection.a urlparser.a driver.a installdriver.a asmglue.a +NETDISKINIT_OBJS = initstart.a netdiskinit.a hostname.a http.a readtcp.a seturl.a strcasecmp.a tcpconnection.a urlparser.a driver.a installdriver.a asmglue.a driverwrapper.a # NETDISKINIT_RSRC = NETDISKINIT_PROG = NetDiskInit diff --git a/driver.c b/driver.c index f96a32f..bd54bb1 100644 --- a/driver.c +++ b/driver.c @@ -1,21 +1,20 @@ #include #include +#include #include "driver.h" +#include "driverwrapper.h" #include "version.h" struct DIB dibs[NDIBS] = {0}; struct DIBList dibList = {NDIBS}; -void *gsosDP = (void*)0x00BD00; /* GS/OS direct page ptr */ +struct GSOSDP *gsosDP = (void*)0x00BD00; /* GS/OS direct page ptr */ -static asm dummy(void) { - rtl -} void InitDIBs(void) { for (unsigned i = 0; i < NDIBS; i++) { dibs[i].linkPtr = (i < NDIBS-1) ? &dibs[i+1] : NULL; - dibs[i].entryPtr = dummy; // TODO driver entry point + dibs[i].entryPtr = DriverWrapper; /* speed-independent, block device, read allowed, removable */ dibs[i].characteristics = 0x03A4; dibs[i].blockCount = 0; @@ -35,3 +34,154 @@ void InitDIBs(void) { } } + + +#pragma databank 1 +Word DriverDispatch(Word callNum, struct GSOSDP *dp) { + Word retVal = 0; + + switch (callNum) { + case Driver_Startup: + gsosDP = dp; + break; + + case Driver_Open: + case Driver_Close: + /* Only applicable to character devices, but no error for block devs */ + break; + + case Driver_Read: + //TODO + break; + + case Driver_Write: + //TODO Maybe do disk-switched logic and/or block size validation? + retVal = drvrWrtProt; + dp->transferCount = 0; + break; + + case Driver_Status: + switch (dp->statusCode) { + case Get_Device_Status: + if (dp->requestCount < 2) { + dp->transferCount = 0; + retVal = drvrBadParm; + break; + } + //TODO handle actual disk, and disk-switched logic + /* no disk in drive, ... */ + ((DeviceStatusRec*)dp->statusListPtr)->statusWord = 0; + if (dp->requestCount < 6) { + dp->transferCount = 2; + break; + } + ((DeviceStatusRec*)dp->statusListPtr)->numBlocks = 0; + dp->requestCount = 6; + break; + + case Get_Config_Parameters: + if (dp->requestCount < 2) { + dp->transferCount = 0; + retVal = drvrBadParm; + break; + } + /* config list has length 0 */ + *(Word*)dp->statusListPtr = 0; + dp->transferCount = 2; + break; + + case Get_Wait_Status: + if (dp->requestCount != 2) { + dp->transferCount = 0; + retVal = drvrBadParm; + break; + } + /* always in wait mode */ + *(Word*)dp->statusListPtr = 0; + dp->transferCount = 2; + break; + + case Get_Format_Options: + /* no format options */ + dp->transferCount = 0; + break; + + case Get_Partition_Map: + /* no partition map */ + dp->transferCount = 0; + break; + + default: + dp->transferCount = 0; + retVal = drvrBadCode; + break; + } + break; + + case Driver_Control: + switch (dp->controlCode) { + case eject: + //TODO + break; + + case setConfigParameters: + dp->transferCount = 0; + if (dp->requestCount < 2) { + retVal = drvrBadParm; + break; + } + /* config list should be empty (zero length) */ + if (*(Word*)dp->controlListPtr != 0) { + retVal = drvrBadParm; + break; + } + break; + + case setWaitStatus: + dp->transferCount = 0; + if (dp->requestCount != 2) { + retVal = drvrBadParm; + break; + } + /* only wait mode is valid */ + if (*(Word*)dp->controlListPtr != 0) { + retVal = drvrBadParm; + break; + } + break; + + case resetDevice: + case formatDevice: + case setFormatOptions: + case assignPartitionOwner: + case armSignal: + case disarmSignal: + case setPartitionMap: + /* do nothing, and return no error */ + dp->transferCount = 0; + break; + + default: + dp->transferCount = 0; + retVal = drvrBadCode; + break; + } + break; + + case Driver_Flush: + /* Only applicable to character devices; error for block devices */ + retVal = drvrBadReq; + break; + + case Driver_Shutdown: + //TODO + break; + + default: + retVal = drvrBadReq; + break; + } + + return retVal; +} +#pragma databank 0 diff --git a/driver.h b/driver.h index 5ffd82b..827eb37 100644 --- a/driver.h +++ b/driver.h @@ -7,6 +7,7 @@ #define NDIBS 16 +/* device information block */ struct DIB { void *linkPtr; void *entryPtr; @@ -23,16 +24,62 @@ struct DIB { Word DIBDevNum; }; +/* list of DIBs (argument to INSTALL_DRIVER) */ struct DIBList { LongWord count; struct DIB *dibPointers[NDIBS]; }; +/* GS/OS direct page structure */ +struct GSOSDP { + Word deviceNum; + Word callNum; + void *bufferPtr; + LongWord requestCount; + LongWord transferCount; + LongWord blockNum; + Word blockSize; + Word fstNum; + Word volumeID; + Word cachePriority; + void *cachePointer; + struct DIB *dibPointer; +}; +#define statusListPtr bufferPtr +#define statusCode fstNum +#define controlListPtr bufferPtr +#define controlCode fstNum + +/* GS/OS driver call numbers */ +#define Driver_Startup 0x0000 +#define Driver_Open 0x0001 +#define Driver_Read 0x0002 +#define Driver_Write 0x0003 +#define Driver_Close 0x0004 +#define Driver_Status 0x0005 +#define Driver_Control 0x0006 +#define Driver_Flush 0x0007 +#define Driver_Shutdown 0x0008 + +/* Driver_Status subcalls */ +#define Get_Device_Status 0x0000 +#define Get_Config_Parameters 0x0001 +#define Get_Wait_Status 0x0002 +#define Get_Format_Options 0x0003 +#define Get_Partition_Map 0x0004 + +/* Status list record for Get_DeviceStatus */ +typedef struct DeviceStatusRec { + Word statusWord; + LongWord numBlocks; +} DeviceStatusRec; + extern struct DIB dibs[NDIBS]; extern struct DIBList dibList; extern void *gsosDP; void InitDIBs(void); +Word DriverDispatch(Word callNum, struct GSOSDP *dp); #endif diff --git a/driverwrapper.asm b/driverwrapper.asm new file mode 100644 index 0000000..e996e69 --- /dev/null +++ b/driverwrapper.asm @@ -0,0 +1,20 @@ + case on + +dummy private + end + +DriverWrapper start + pea $0000 ; direct page pointer + phd + + pha ; call number + + jsl DriverDispatch + + tay ; set carry based on return value + bne err_ret + clc + rtl +err_ret sec + rtl + end diff --git a/driverwrapper.h b/driverwrapper.h new file mode 100644 index 0000000..beca511 --- /dev/null +++ b/driverwrapper.h @@ -0,0 +1,7 @@ +#ifndef DRIVERWRAPPER_H +#define DRIVERWRAPPER_H + +/* Driver wrapper code, meant to be called by GS/OS */ +void DriverWrapper(void); + +#endif