mirror of
https://github.com/simh/simh.git
synced 2026-01-11 23:52:58 +00:00
Altair8800: SIMH device and WD17XX API corrections
SIMH: Adds support for wildcard filename transfers WD17XX: Corrects a problem with DRQ status
This commit is contained in:
parent
aad5351080
commit
d81cb4fc48
@ -36,13 +36,15 @@
|
||||
#include "s100_cpu.h"
|
||||
#include "s100_simh.h"
|
||||
|
||||
static t_stat simh_dev_reset(DEVICE *dptr);
|
||||
static t_stat simh_reset(DEVICE *dptr);
|
||||
static int32 simh_io_status(const int32 port, const int32 io, const int32 data);
|
||||
static int32 simh_io_data(const int32 port, const int32 io, const int32 data);
|
||||
static int32 simh_io_cmd(const int32 port, const int32 io, const int32 data);
|
||||
static int32 simh_cmd_in(const int32 port);
|
||||
static int32 simh_cmd_out(const int32 port, const int32 data);
|
||||
static t_stat simh_show_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
static void deleteNameList(void);
|
||||
static void processDirEntry(const char *directory, const char *filename, t_offset FileSize, const struct stat *filestat, void *context);
|
||||
static void createCPMCommandLine(void);
|
||||
static void attachCPM(UNIT *uptr, int32 readOnly);
|
||||
static void detachCPM(UNIT *uptr);
|
||||
@ -121,13 +123,23 @@ const char* simh_description(DEVICE *dptr) {
|
||||
DEVICE simh_dev = {
|
||||
"SIMH", &simh_unit, simh_reg, simh_mod,
|
||||
1, ADDRRADIX, ADDRWIDTH, 1, DATARADIX, DATAWIDTH,
|
||||
NULL, NULL, &simh_dev_reset,
|
||||
NULL, NULL, &simh_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, (DEV_DISABLE | DEV_DEBUG), 0,
|
||||
generic_dt, NULL, NULL, &simh_show_help, NULL, NULL, &simh_description
|
||||
};
|
||||
|
||||
typedef struct NameNode {
|
||||
char *name;
|
||||
struct NameNode *next;
|
||||
} NameNode_t;
|
||||
|
||||
static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH];
|
||||
static NameNode_t *nameListHead = NULL;
|
||||
static NameNode_t *currentName = NULL;
|
||||
static int32 currentNameIndex = 0;
|
||||
static int32 lastPathSeparatorIndex = 0;
|
||||
static int32 firstPathCharacterIndex = 0;
|
||||
|
||||
/* Z80 or 8080 programs communicate with the SIMH pseudo device via port 0xfe.
|
||||
The following principles apply:
|
||||
@ -183,6 +195,7 @@ static char cpmCommandLine[CPM_COMMAND_LINE_LENGTH];
|
||||
#define setZ80CPUCmd 19 /* 19 set the CPU to a Z80 */
|
||||
#define set8080CPUCmd 20 /* 20 set the CPU to an 8080 */
|
||||
#define getHostOSPathSeparatorCmd 28 /* 28 obtain the file path separator of the OS under which SIMH runs */
|
||||
#define getHostFilenamesCmd 29 /* 29 perform wildcard expansion and obtain list of file names */
|
||||
#define kSimhPseudoDeviceCommands 35 /* Highest AltairZ80 SIMH command */
|
||||
|
||||
static const char *cmdNames[kSimhPseudoDeviceCommands] = {
|
||||
@ -215,7 +228,7 @@ static const char *cmdNames[kSimhPseudoDeviceCommands] = {
|
||||
"Undefined",
|
||||
"Undefined",
|
||||
"getHostOSPathSeparator",
|
||||
"Undefined",
|
||||
"getHostFilenames",
|
||||
"Undefined",
|
||||
"Undefined",
|
||||
"Undefined",
|
||||
@ -225,7 +238,7 @@ static const char *cmdNames[kSimhPseudoDeviceCommands] = {
|
||||
|
||||
static char version[] = "SIMH005";
|
||||
|
||||
static t_stat simh_dev_reset(DEVICE *dptr) {
|
||||
static t_stat simh_reset(DEVICE *dptr) {
|
||||
if (dptr->flags & DEV_DIS) {
|
||||
s100_bus_remio(0xfe, 1, &simh_io_cmd); /* Command Port */
|
||||
}
|
||||
@ -245,6 +258,32 @@ static t_stat simh_dev_reset(DEVICE *dptr) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static void deleteNameList(void)
|
||||
{
|
||||
while (nameListHead != NULL) {
|
||||
NameNode_t *next = nameListHead -> next;
|
||||
free(nameListHead -> name);
|
||||
free(nameListHead);
|
||||
nameListHead = next;
|
||||
}
|
||||
|
||||
currentName = NULL;
|
||||
currentNameIndex = 0;
|
||||
}
|
||||
|
||||
static void processDirEntry(const char *directory, const char *filename, t_offset FileSize, const struct stat *filestat, void *context)
|
||||
{
|
||||
if (filename != NULL) {
|
||||
NameNode_t *top = (NameNode_t *) malloc(sizeof(NameNode_t));
|
||||
if (top) {
|
||||
top->name = strdup(filename);
|
||||
top->next = nameListHead;
|
||||
nameListHead = top;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void createCPMCommandLine(void) {
|
||||
int32 i, len = (s100_bus_memr(FCBAddress) & 0x7f); /* 0x80 contains length of command line, discard first char */
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
@ -332,17 +371,43 @@ static int32 simh_cmd_in(const int32 port)
|
||||
result = sim_file_path_separator;
|
||||
break;
|
||||
|
||||
case getHostFilenamesCmd:
|
||||
if (nameListHead != NULL) {
|
||||
if (currentName == NULL) {
|
||||
deleteNameList();
|
||||
lastCommand = 0;
|
||||
}
|
||||
else if (firstPathCharacterIndex <= lastPathSeparatorIndex) {
|
||||
result = cpmCommandLine[firstPathCharacterIndex++];
|
||||
}
|
||||
else {
|
||||
result = currentName -> name[currentNameIndex];
|
||||
|
||||
if (result == 0) {
|
||||
currentName = currentName -> next;
|
||||
firstPathCharacterIndex = currentNameIndex = 0;
|
||||
}
|
||||
else {
|
||||
currentNameIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" Undefined IN from SIMH pseudo device on port %03xh ignored.\n",
|
||||
s100_bus_get_addr(), port);
|
||||
|
||||
result = lastCommand = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int32 simh_cmd_out(const int32 port, const int32 data) {
|
||||
static int32 simh_cmd_out(const int32 port, const int32 data)
|
||||
{
|
||||
t_stat result;
|
||||
|
||||
switch(lastCommand) {
|
||||
default: /* lastCommand not yet set */
|
||||
@ -394,6 +459,40 @@ static int32 simh_cmd_out(const int32 port, const int32 data) {
|
||||
case getHostOSPathSeparatorCmd:
|
||||
break;
|
||||
|
||||
case getHostFilenamesCmd: /* list files of host file directory */
|
||||
if (nameListHead == NULL) {
|
||||
|
||||
createCPMCommandLine();
|
||||
|
||||
lastPathSeparatorIndex = 0;
|
||||
|
||||
while (cpmCommandLine[lastPathSeparatorIndex]) {
|
||||
lastPathSeparatorIndex++;
|
||||
}
|
||||
|
||||
while ((lastPathSeparatorIndex >= 0) && (cpmCommandLine[lastPathSeparatorIndex] != sim_file_path_separator)) {
|
||||
lastPathSeparatorIndex--;
|
||||
}
|
||||
|
||||
firstPathCharacterIndex = 0;
|
||||
|
||||
deleteNameList();
|
||||
|
||||
result = sim_dir_scan(cpmCommandLine, processDirEntry, NULL);
|
||||
|
||||
if (result == SCPE_OK) {
|
||||
currentName = nameListHead;
|
||||
currentNameIndex = 0;
|
||||
}
|
||||
else {
|
||||
deleteNameList();
|
||||
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT " Cannot expand '%s'. Error is %s.\n",
|
||||
s100_bus_get_addr(), cpmCommandLine, sim_error_text(result));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sim_debug(CMD_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" Unknown command (%i) to SIMH pseudo device on port %03xh ignored.\n",
|
||||
@ -404,20 +503,22 @@ static int32 simh_cmd_out(const int32 port, const int32 data) {
|
||||
return 0xff; /* ignored, since OUT */
|
||||
}
|
||||
|
||||
/* port 0xfc is a device for communication SIMH <--> Altair machine */
|
||||
/* port 0x12 is a device for communication SIMH <--> Altair machine */
|
||||
static int32 simh_io_status(const int32 port, const int32 io, const int32 data)
|
||||
{
|
||||
if (io == S100_IO_READ) { /* IN */
|
||||
if ((simh_unit.flags & UNIT_ATT) == 0) { /* SIMH is not attached */
|
||||
if (io == S100_IO_READ) { /* IN */
|
||||
if ((simh_unit.flags & UNIT_ATT) == 0) { /* SIMH is not attached */
|
||||
if ((simh_dev.dctrl & VERBOSE_MSG) && (warnUnattachedSIMH < warnLevelSIMH)) {
|
||||
warnUnattachedSIMH++;
|
||||
/*06*/ sim_debug(VERBOSE_MSG, &simh_dev, "PTR: " ADDRESS_FORMAT
|
||||
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "PTR: " ADDRESS_FORMAT
|
||||
" Attempt to test status of unattached SIMH[0x%02x]. 0x02 returned.\n", s100_bus_get_addr(), port);
|
||||
}
|
||||
|
||||
return SIMH_CAN_WRITE;
|
||||
}
|
||||
/* if EOF then SIMH_CAN_WRITE else
|
||||
(SIMH_CAN_WRITE and SIMH_CAN_READ) */
|
||||
|
||||
/* if EOF then SIMH_CAN_WRITE else (SIMH_CAN_WRITE and SIMH_CAN_READ) */
|
||||
return simh_unit.u3 ? SIMH_CAN_WRITE : (SIMH_CAN_READ | SIMH_CAN_WRITE);
|
||||
} /* OUT follows */
|
||||
if (data == SIMH_RESET) {
|
||||
@ -425,47 +526,58 @@ static int32 simh_io_status(const int32 port, const int32 io, const int32 data)
|
||||
sim_debug(CMD_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" Command OUT(0x%03x) = 0x%02x\n", s100_bus_get_addr(), port, data);
|
||||
}
|
||||
|
||||
return 0x00; /* ignored since OUT */
|
||||
}
|
||||
|
||||
/* port 0xfd is a device for communication SIMH <--> Altair machine */
|
||||
/* port 0x13 is a device for communication SIMH <--> Altair machine */
|
||||
static int32 simh_io_data(const int32 port, const int32 io, const int32 data)
|
||||
{
|
||||
int32 ch;
|
||||
|
||||
if (io == S100_IO_READ) { /* IN */
|
||||
if (simh_unit.u3) { /* EOF reached, no more data available */
|
||||
if (io == S100_IO_READ) { /* IN */
|
||||
if (simh_unit.u3) { /* EOF reached, no more data available */
|
||||
if ((simh_dev.dctrl & VERBOSE_MSG) && (warnSIMHEOF < warnLevelSIMH)) {
|
||||
warnSIMHEOF++;
|
||||
/*07*/ sim_debug(VERBOSE_MSG, &simh_dev, "PTR: " ADDRESS_FORMAT
|
||||
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "PTR: " ADDRESS_FORMAT
|
||||
" SIMH[0x%02x] attempted to read past EOF. 0x00 returned.\n", s100_bus_get_addr(), port);
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if ((simh_unit.flags & UNIT_ATT) == 0) { /* not attached */
|
||||
if ((simh_dev.dctrl & VERBOSE_MSG) && (warnUnattachedSIMH < warnLevelSIMH)) {
|
||||
warnUnattachedSIMH++;
|
||||
/*08*/ sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" Attempt to read from unattached SIMH[0x%02x]. 0x00 returned.\n", s100_bus_get_addr(), port);
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if ((ch = getc(simh_unit.fileref)) == EOF) { /* end of file? */
|
||||
simh_unit.u3 = TRUE; /* remember EOF reached */
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" EOF on read\n", s100_bus_get_addr());
|
||||
|
||||
return CONTROLZ_CHAR; /* ^Z denotes end of text file in CP/M */
|
||||
}
|
||||
|
||||
return ch & 0xff;
|
||||
} /* OUT follows */
|
||||
if (simh_unit.flags & UNIT_ATT) /* unit must be attached */
|
||||
|
||||
if (simh_unit.flags & UNIT_ATT) { /* unit must be attached */
|
||||
putc(data, simh_unit.fileref);
|
||||
/* else ignore data */
|
||||
}
|
||||
else if ((simh_dev.dctrl & VERBOSE_MSG) && (warnUnattachedSIMH < warnLevelSIMH)) {
|
||||
warnUnattachedSIMH++;
|
||||
/*09*/ sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
|
||||
sim_debug(VERBOSE_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" Attempt to output '0x%02x' to unattached SIMH[0x%02x] - ignored.\n", s100_bus_get_addr(), data, port);
|
||||
}
|
||||
|
||||
return 0x00; /* ignored since OUT */
|
||||
}
|
||||
|
||||
@ -481,7 +593,8 @@ static int32 simh_io_cmd(const int32 port, const int32 io, const int32 data)
|
||||
port, result, result,
|
||||
(32 <= (result & 0xff)) && ((result & 0xff) <= 127) ? (result & 0xff) : '?');
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sim_debug(OUT_MSG, &simh_dev, "SIMH: " ADDRESS_FORMAT
|
||||
" OUT(0x%02x) <- %i (0x%02x, '%c')\n", s100_bus_get_addr(),
|
||||
port, data, data,
|
||||
|
||||
@ -45,6 +45,7 @@ static uint8 wd17xx_sec_len(WD17XX_INFO *wd);
|
||||
static t_stat wd17xx_read_sector(WD17XX_INFO *wd, uint8 *sbuf, int32 *bytesread);
|
||||
static t_stat wd17xx_write_sector(WD17XX_INFO *wd, uint8 *sbuf, int32 *byteswritten);
|
||||
static void wd17xx_set_intrq(WD17XX_INFO *wd, int32 value);
|
||||
static void wd17xx_set_drq(WD17XX_INFO *wd, int32 value);
|
||||
|
||||
WD17XX_INFO * wd17xx_init(DEVICE *dptr)
|
||||
{
|
||||
@ -601,13 +602,13 @@ static void wd17xx_command(WD17XX_INFO *wd, uint8 cmd)
|
||||
|
||||
wd->status |= (WD17XX_STAT_DRQ); /* Set DRQ */
|
||||
wd->status |= (wd->dsk->unit->flags & UNIT_RO) ? WD17XX_STAT_WP : 0; /* Set WP */
|
||||
wd->drq = 1;
|
||||
wd->fdc_datacount = dsk_sector_size(wd->dsk, wd->track, wd->side);
|
||||
wd->fdc_dataindex = 0;
|
||||
wd->fdc_write = TRUE;
|
||||
wd->fdc_write_track = FALSE;
|
||||
wd->fdc_read = FALSE;
|
||||
wd->fdc_readadr = FALSE;
|
||||
wd17xx_set_drq(wd, 1);
|
||||
|
||||
sbuf[wd->fdc_dataindex] = wd->data;
|
||||
break;
|
||||
@ -626,11 +627,11 @@ static void wd17xx_command(WD17XX_INFO *wd, uint8 cmd)
|
||||
wd17xx_set_intrq(wd, TRUE);
|
||||
} else {
|
||||
wd->status = (WD17XX_STAT_DRQ | WD17XX_STAT_BUSY); /* Set DRQ, BUSY */
|
||||
wd->drq = 1;
|
||||
wd->fdc_datacount = 6;
|
||||
wd->fdc_dataindex = 0;
|
||||
wd->fdc_read = TRUE;
|
||||
wd->fdc_readadr = TRUE;
|
||||
wd17xx_set_drq(wd, 1);
|
||||
|
||||
sbuf[0] = wd->track;
|
||||
sbuf[1] = wd->side;
|
||||
@ -676,13 +677,13 @@ static void wd17xx_command(WD17XX_INFO *wd, uint8 cmd)
|
||||
sim_debug(wd->dbg_command, wd->dptr, WD17XX_NAME ADDRESS_FORMAT " CMD=FORCE_INTR\n", s100_bus_get_addr());
|
||||
if ((cmd & WD17XX_CMD_MASK) == 0) { /* I0-I3 == 0, no intr, but clear BUSY and terminate command */
|
||||
wd->status &= ~(WD17XX_STAT_DRQ | WD17XX_STAT_BUSY); /* Clear DRQ, BUSY */
|
||||
wd->drq = 0;
|
||||
wd->fdc_write = FALSE;
|
||||
wd->fdc_read = FALSE;
|
||||
wd->fdc_write_track = FALSE;
|
||||
wd->fdc_readadr = FALSE;
|
||||
wd->fdc_datacount = 0;
|
||||
wd->fdc_dataindex = 0;
|
||||
wd17xx_set_drq(wd, 0);
|
||||
}
|
||||
else if (cmd & 0x08) { /* Immediate Interrupt */
|
||||
wd17xx_set_intrq(wd, TRUE);
|
||||
@ -757,7 +758,7 @@ static void wd17xx_command(WD17XX_INFO *wd, uint8 cmd)
|
||||
s100_bus_int(1 << wd->intvector, wd->intvector * 2);
|
||||
}
|
||||
|
||||
wd->drq = 1;
|
||||
wd17xx_set_drq(wd, 1);
|
||||
break;
|
||||
|
||||
/* Type IV Commands */
|
||||
@ -840,6 +841,12 @@ static void wd17xx_set_intrq(WD17XX_INFO *wd, int32 value)
|
||||
wd->drq = !wd->intrq;
|
||||
}
|
||||
|
||||
static void wd17xx_set_drq(WD17XX_INFO *wd, int32 value)
|
||||
{
|
||||
wd->drq = (value) ? TRUE : FALSE; /* INTRQ and DRQ are mutually exclusive */
|
||||
wd->intrq = !wd->drq;
|
||||
}
|
||||
|
||||
void wd17xx_show(WD17XX_INFO *wd)
|
||||
{
|
||||
sim_debug(wd->dbg_verbose, wd->dptr, "fdctype: %02X\n", wd->fdctype);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user