2018-08-07 01:22:33 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2018-08-09 01:12:03 +00:00
|
|
|
#include <gsos.h>
|
2018-08-07 01:22:33 +00:00
|
|
|
#include "driver.h"
|
2018-08-09 01:12:03 +00:00
|
|
|
#include "driverwrapper.h"
|
2018-08-07 01:22:33 +00:00
|
|
|
#include "version.h"
|
|
|
|
|
|
|
|
struct DIB dibs[NDIBS] = {0};
|
|
|
|
struct DIBList dibList = {NDIBS};
|
|
|
|
|
2018-08-09 01:12:03 +00:00
|
|
|
struct GSOSDP *gsosDP = (void*)0x00BD00; /* GS/OS direct page ptr */
|
2018-08-07 01:22:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
void InitDIBs(void) {
|
|
|
|
for (unsigned i = 0; i < NDIBS; i++) {
|
|
|
|
dibs[i].linkPtr = (i < NDIBS-1) ? &dibs[i+1] : NULL;
|
2018-08-09 01:12:03 +00:00
|
|
|
dibs[i].entryPtr = DriverWrapper;
|
2018-08-07 01:22:33 +00:00
|
|
|
/* speed-independent, block device, read allowed, removable */
|
|
|
|
dibs[i].characteristics = 0x03A4;
|
|
|
|
dibs[i].blockCount = 0;
|
|
|
|
|
|
|
|
int nameLen = sprintf(dibs[i].devName + 1, "NETDISK%u", i+1);
|
|
|
|
dibs[i].devName[0] = nameLen;
|
|
|
|
for (unsigned j = nameLen + 1; j < sizeof(dibs[i].devName); j++) {
|
|
|
|
dibs[i].devName[j] = ' ';
|
|
|
|
}
|
|
|
|
|
|
|
|
dibs[i].slotNum = 0x8003;
|
|
|
|
dibs[i].unitNum = i+1;
|
|
|
|
dibs[i].version = DRIVER_VERSION;
|
|
|
|
dibs[i].deviceID = DEVICE_GENERIC_FLOPPY_DRIVE;
|
|
|
|
|
|
|
|
dibList.dibPointers[i] = &dibs[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2018-08-09 01:12:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
#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
|