3B2: LPT Device; MMU and SCSI fixes

This change adds support for printing to an attached text file via the
Centronics port of a simulated PORTS feature card. A new device named
"LPT" has been added. See "help lpt" for documentation.

Additionally, there has been a fix to a bug in the SCSI tape boot
implementation and a very minor bug fix to the Rev 3 MMU.
This commit is contained in:
Seth Morabito 2023-04-09 10:36:40 -07:00
parent e4ad37eccc
commit 7be9f2f3e8
10 changed files with 253 additions and 87 deletions

View file

@ -846,9 +846,9 @@ t_stat cpu_show_cio(FILE *st, UNIT *uptr, int32 val, CONST void *desc)
fprintf(st, "---------------------\n"); fprintf(st, "---------------------\n");
for (slot = 0; slot < CIO_SLOTS; slot++) { for (slot = 0; slot < CIO_SLOTS; slot++) {
if (cio[slot].populated) { if (cio[slot].populated) {
fprintf(st, " %2d %s\n", slot, cio[slot].name); fprintf(st, " %2d %s\n", slot + 1, cio[slot].name);
} else { } else {
fprintf(st, " %2d -\n", slot); fprintf(st, " %2d -\n", slot + 1);
} }
} }

View file

@ -158,6 +158,7 @@ extern DEVICE timer_dev;
extern DEVICE tod_dev; extern DEVICE tod_dev;
extern DEVICE tti_dev; extern DEVICE tti_dev;
extern DEVICE tto_dev; extern DEVICE tto_dev;
extern DEVICE lpt_dev;
#if defined(REV3) #if defined(REV3)
extern DEVICE flt_dev; extern DEVICE flt_dev;
extern DEVICE ha_dev; extern DEVICE ha_dev;

View file

@ -51,8 +51,6 @@
#include "3b2_mem.h" #include "3b2_mem.h"
#include "3b2_stddev.h" #include "3b2_stddev.h"
#define IO_SCHED 1000
/* Device and units for PORTS cards /* Device and units for PORTS cards
* -------------------------------- * --------------------------------
* *
@ -100,13 +98,8 @@
#define PORTS_DIAG_CRC5 0x4be7bccc /* Used by SVR 2.0.5 */ #define PORTS_DIAG_CRC5 0x4be7bccc /* Used by SVR 2.0.5 */
#define PORTS_DIAG_CRC6 0x3197f6dd /* Used by SVR 2.0.5 */ #define PORTS_DIAG_CRC6 0x3197f6dd /* Used by SVR 2.0.5 */
#define PORTS_DFLT_LINES 4
#define PORTS_DFLT_CARDS 1
#define LN(slot,port) (ports_slot_ln[(slot)] + (port)) #define LN(slot,port) (ports_slot_ln[(slot)] + (port))
#define LSLOT(ln) (ports_ln_slot[ln]) #define LSLOT(ln) (ports_ln_slot[ln])
/* #define LN(slot,port) ((PORTS_LINES * ((slot) - ports_base_slot)) + (port)) */
/* #define LSLOT(ln) (((ln) / PORTS_LINES) + ports_base_slot) */
#define LPORT(ln) ((ln) % PORTS_LINES) #define LPORT(ln) ((ln) % PORTS_LINES)
int8 ports_base_slot; /* First slot in our contiguous block */ int8 ports_base_slot; /* First slot in our contiguous block */
@ -115,21 +108,23 @@ uint8 ports_int_subdev; /* Interrupting subdevice */
t_bool ports_conf = FALSE; /* Have PORTS cards been configured? */ t_bool ports_conf = FALSE; /* Have PORTS cards been configured? */
uint32 ports_crc; /* CRC32 of downloaded memory */ uint32 ports_crc; /* CRC32 of downloaded memory */
/* Mapping of line number to CIO card slot. Up to 32 lines spread over /* Mapping of line number to CIO card slot. Up to 32 lines spread over 8
8 slots are supported. */ slots are supported. */
uint8 ports_ln_slot[MAX_LINES]; uint8 ports_ln_slot[MAX_LINES];
/* Mapping of slot number to base line number belonging to the card in /* Mapping of slot number to base line number belonging to the card in
that slot. I.e., if there are two PORTS cards, one in slot 3 and that slot. I.e., if there are two PORTS cards, one in slot 3 and one in
one in slot 5, index 3 will have starting line 0, index 5 will have slot 5, index 3 will have starting line 0, index 5 will have starting
starting line 4. */ line 4. */
uint32 ports_slot_ln[CIO_SLOTS]; uint32 ports_slot_ln[CIO_SLOTS];
/* PORTS-specific state for each slot */ /* PORTS-specific state for each slot */
PORTS_LINE_STATE *ports_state = NULL; PORTS_LINE_STATE *ports_state = NULL;
/* Baud rates determined by the low nybble /* Line-printer state (only one is supported) */
* of the PORT_OPTIONS cflag */ PORTS_LINE_STATE lpt_state;
/* Baud rates determined by the low nybble of the PORT_OPTIONS cflag */
CONST char *ports_baud[16] = { CONST char *ports_baud[16] = {
"75", "110", "134", "150", "75", "110", "134", "150",
"300", "600", "1200", "2000", "300", "600", "1200", "2000",
@ -199,6 +194,38 @@ DEVICE ports_dev = {
NULL, /* device description */ NULL, /* device description */
}; };
UNIT lpt_unit = {
UDATA(NULL, UNIT_SEQ|UNIT_ATTABLE|UNIT_TEXT, 0), SERIAL_OUT_WAIT
};
DEVICE lpt_dev = {
"LPT", /* name */
&lpt_unit, /* units */
NULL, /* registers */
NULL, /* modifiers */
1, /* # units */
16, /* address radix */
32, /* address width */
1, /* address incr. */
16, /* data radix */
8, /* data width */
NULL, /* examine routine */
NULL, /* deposit routine */
&lpt_reset, /* reset routine */
NULL, /* boot routine */
&lpt_attach, /* attach routine */
&lpt_detach, /* detach routine */
NULL, /* context */
DEV_DISABLE|DEV_DIS, /* flags */
0, /* debug control flags */
NULL, /* debug flag names */
NULL, /* memory size change */
NULL, /* logical name */
&lpt_help, /* help routine */
NULL, /* attach help routine */
NULL, /* help context */
&lpt_description /* device description */
};
static void cio_irq(uint8 slot, uint8 dev, int32 delay) static void cio_irq(uint8 slot, uint8 dev, int32 delay)
{ {
@ -207,6 +234,23 @@ static void cio_irq(uint8 slot, uint8 dev, int32 delay)
sim_activate(&ports_unit[2], delay); sim_activate(&ports_unit[2], delay);
} }
static void lpt_out(uint8 c)
{
if (!lpt_state.conn) {
return;
}
fputc(c, lpt_unit.fileref);
if (ferror(lpt_unit.fileref)) {
sim_perror("LPT I/O error");
clearerr(lpt_unit.fileref);
return;
}
lpt_unit.pos++;
}
/* /*
* Set the number of lines for the PORTS mux. This will add or remove * Set the number of lines for the PORTS mux. This will add or remove
* cards as necessary. The number of lines must be a multiple of 4. * cards as necessary. The number of lines must be a multiple of 4.
@ -276,10 +320,22 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
PORTS_OPTIONS opts; PORTS_OPTIONS opts;
char line_config[16]; char line_config[16];
uint8 app_data[4] = {0}; uint8 app_data[4] = {0};
PORTS_LINE_STATE *state;
centry.address = rentry->address; centry.address = rentry->address;
cio[slot].op = rentry->opcode; cio[slot].op = rentry->opcode;
ln = LN(slot, rentry->subdevice & 0xf);
if ((rentry->subdevice & 7) == PORTS_CENTRONICS) {
ln = 0;
state = &lpt_state;
} else {
ln = LN(slot, rentry->subdevice & 7);
state = &ports_state[ln];
}
sim_debug(TRACE_DBG, &ports_dev,
"[ports_cmd] Command: slot %d, subdev %d, opcode 0x%02x\n",
slot, rentry->subdevice, rentry->opcode);
switch(rentry->opcode) { switch(rentry->opcode) {
case CIO_DLM: case CIO_DLM:
@ -378,10 +434,10 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
sim_debug(TRACE_DBG, &ports_dev, " PPC Options: vtime=%02x\n", opts.vtime); sim_debug(TRACE_DBG, &ports_dev, " PPC Options: vtime=%02x\n", opts.vtime);
sim_debug(TRACE_DBG, &ports_dev, " PPC Options: vcount=%02x\n", opts.vcount); sim_debug(TRACE_DBG, &ports_dev, " PPC Options: vcount=%02x\n", opts.vcount);
ports_state[ln].iflag = opts.iflag; state->iflag = opts.iflag;
ports_state[ln].oflag = opts.oflag; state->oflag = opts.oflag;
if ((rentry->subdevice & 0xf) < PORTS_LINES) { if ((rentry->subdevice & 7) < PORTS_LINES) {
/* Adjust baud rate */ /* Adjust baud rate */
sprintf(line_config, "%s-8N1", sprintf(line_config, "%s-8N1",
ports_baud[opts.cflag&0xf]); ports_baud[opts.cflag&0xf]);
@ -409,8 +465,7 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
centry.opcode = CIO_ULM; centry.opcode = CIO_ULM;
/* TODO: It's unknown what the value 0x50 means, but this /* 0x50 (80 decimal) is the expected PROM version */
* is what a real board sends. */
app_data[0] = 0x50; app_data[0] = 0x50;
cio_cqueue(slot, CIO_STAT, PPQESIZE, &centry, app_data); cio_cqueue(slot, CIO_STAT, PPQESIZE, &centry, app_data);
cio_irq(slot, rentry->subdevice, DELAY_VERS); cio_irq(slot, rentry->subdevice, DELAY_VERS);
@ -421,7 +476,9 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
"[ports_cmd] PPC CONNECT - subdevice = %02x\n", "[ports_cmd] PPC CONNECT - subdevice = %02x\n",
rentry->subdevice); rentry->subdevice);
if (rentry->subdevice < PORTS_LINES) {
ports_state[ln].conn = TRUE; ports_state[ln].conn = TRUE;
}
centry.opcode = PPC_CONN; centry.opcode = PPC_CONN;
centry.subdevice = rentry->subdevice; centry.subdevice = rentry->subdevice;
@ -437,11 +494,10 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
"[ports_cmd] PPC XMIT - subdevice = %02x, address=%08x, byte_count=%d\n", "[ports_cmd] PPC XMIT - subdevice = %02x, address=%08x, byte_count=%d\n",
rentry->subdevice, rentry->address, rentry->byte_count); rentry->subdevice, rentry->address, rentry->byte_count);
/* Set state for xmit */ state->tx_addr = rentry->address;
ports_state[ln].tx_addr = rentry->address; state->tx_req_addr = state->tx_addr;
ports_state[ln].tx_req_addr = rentry->address; state->tx_chars = rentry->byte_count + 1;
ports_state[ln].tx_chars = rentry->byte_count + 1; state->tx_req_chars = state->tx_chars;
ports_state[ln].tx_req_chars = rentry->byte_count + 1;
sim_activate_after(&ports_unit[1], ports_unit[1].wait); sim_activate_after(&ports_unit[1], ports_unit[1].wait);
@ -490,20 +546,26 @@ static void ports_cmd(uint8 slot, cio_entry *rentry, uint8 *rapp_data)
/* /*
* Update the connection status of the given port. * Update the connection status of the given port.
*/ */
static void ports_update_conn(uint32 ln) static void ports_update_conn(uint8 slot, uint8 subdev)
{ {
cio_entry centry = {0}; cio_entry centry = {0};
uint8 slot;
uint8 app_data[4] = {0}; uint8 app_data[4] = {0};
uint32 ln = LN(slot, subdev);
slot = LSLOT(ln); /* If the card hasn't sysgened, there's no way to write a completion
* queue entry */
/* If the card hasn't sysgened, there's no way to write a
* completion queue entry */
if (cio[slot].sysgen_s != CIO_SYSGEN) { if (cio[slot].sysgen_s != CIO_SYSGEN) {
return; return;
} }
sim_debug(TRACE_DBG, &ports_dev, "[ports_update_conn] slot=%d, subdev=%d\n", slot, subdev);
if (subdev == PORTS_CENTRONICS) {
if (!lpt_state.conn) {
return;
}
app_data[0] = AC_CON;
} else {
if (ports_ldsc[ln].conn) { if (ports_ldsc[ln].conn) {
app_data[0] = AC_CON; app_data[0] = AC_CON;
ports_state[ln].conn = TRUE; ports_state[ln].conn = TRUE;
@ -515,9 +577,10 @@ static void ports_update_conn(uint32 ln)
app_data[0] = 0; app_data[0] = 0;
} }
} }
}
centry.opcode = PPC_ASYNC; centry.opcode = PPC_ASYNC;
centry.subdevice = LPORT(ln); centry.subdevice = subdev;
cio_cqueue(slot, CIO_CMD, PPQESIZE, &centry, app_data); cio_cqueue(slot, CIO_CMD, PPQESIZE, &centry, app_data);
/* Interrupt */ /* Interrupt */
@ -556,7 +619,7 @@ void ports_full(uint8 slot)
cio_entry rqe = {0}; cio_entry rqe = {0};
uint8 app_data[4] = {0}; uint8 app_data[4] = {0};
for (i = 0; i < PORTS_LINES; i++) { for (i = 0; i < PORTS_RCV_QUEUE; i++) {
if (cio_rqueue(slot, i, PPQESIZE, &rqe, app_data) == SCPE_OK) { if (cio_rqueue(slot, i, PPQESIZE, &rqe, app_data) == SCPE_OK) {
ports_cmd(slot, &rqe, app_data); ports_cmd(slot, &rqe, app_data);
} }
@ -576,7 +639,7 @@ t_stat ports_reset(DEVICE *dptr)
sim_set_uname(&ports_unit[1], "PORTS-XMT"); sim_set_uname(&ports_unit[1], "PORTS-XMT");
sim_set_uname(&ports_unit[2], "PORTS-CIO"); sim_set_uname(&ports_unit[2], "PORTS-CIO");
ports_desc.lines = PORTS_DFLT_LINES; ports_desc.lines = PORTS_LINES;
ports_desc.ldsc = ports_ldsc = ports_desc.ldsc = ports_ldsc =
(TMLN *)calloc(ports_desc.lines, sizeof(*ports_ldsc)); (TMLN *)calloc(ports_desc.lines, sizeof(*ports_ldsc));
} }
@ -641,11 +704,13 @@ t_stat ports_cio_svc(UNIT *uptr)
switch (cio[ports_int_slot].op) { switch (cio[ports_int_slot].op) {
case PPC_CONN: case PPC_CONN:
cio[ports_int_slot].op = PPC_ASYNC; cio[ports_int_slot].op = PPC_ASYNC;
if (ports_int_subdev < PORTS_LINES) {
ports_ldsc[LN(ports_int_slot, ports_int_subdev)].rcve = 1; ports_ldsc[LN(ports_int_slot, ports_int_subdev)].rcve = 1;
}
sim_activate(&ports_unit[2], DELAY_ASYNC); sim_activate(&ports_unit[2], DELAY_ASYNC);
break; break;
case PPC_ASYNC: case PPC_ASYNC:
ports_update_conn(LN(ports_int_slot, ports_int_subdev)); ports_update_conn(ports_int_slot, ports_int_subdev);
break; break;
default: default:
break; break;
@ -670,14 +735,16 @@ t_stat ports_rcv_svc(UNIT *uptr)
ln = tmxr_poll_conn(&ports_desc); ln = tmxr_poll_conn(&ports_desc);
if (ln >= 0) { if (ln >= 0) {
ports_update_conn(ln); /* Possibly connect a newly opened port */
ports_update_conn(LSLOT(ln), LPORT(ln));
} }
for (ln = 0; ln < ports_desc.lines; ln++) { for (ln = 0; ln < ports_desc.lines; ln++) {
slot = LSLOT(ln); slot = LSLOT(ln);
if (!ports_ldsc[ln].conn && ports_state[ln].conn) { if (!ports_ldsc[ln].conn && ports_state[ln].conn) {
ports_update_conn(ln); /* Disconnect a connected line, it has been dropped */
ports_update_conn(LSLOT(ln), LPORT(ln));
} else if (ports_ldsc[ln].conn && ports_state[ln].conn) { } else if (ports_ldsc[ln].conn && ports_state[ln].conn) {
temp = tmxr_getc_ln(&ports_ldsc[ln]); temp = tmxr_getc_ln(&ports_ldsc[ln]);
@ -728,7 +795,7 @@ t_stat ports_xmt_svc(UNIT *uptr)
uint8 app_data[4] = {0}; uint8 app_data[4] = {0};
uint32 wait = 0x7fffffff; uint32 wait = 0x7fffffff;
/* Scan all lines for output */ /* Scan all MUX lines for output */
for (ln = 0; ln < ports_desc.lines; ln++) { for (ln = 0; ln < ports_desc.lines; ln++) {
slot = LSLOT(ln); slot = LSLOT(ln);
if (ports_ldsc[ln].conn && ports_state[ln].tx_chars > 0) { if (ports_ldsc[ln].conn && ports_state[ln].tx_chars > 0) {
@ -748,30 +815,53 @@ t_stat ports_xmt_svc(UNIT *uptr)
/* Indicate that we're in a CRLF translation */ /* Indicate that we're in a CRLF translation */
ports_state[ln].crlf = TRUE; ports_state[ln].crlf = TRUE;
} }
} else {
break;
}
ports_state[ln].crlf = FALSE; ports_state[ln].crlf = FALSE;
if (tmxr_putc_ln(&ports_ldsc[ln], c) == SCPE_OK) { if (tmxr_putc_ln(&ports_ldsc[ln], c) == SCPE_OK) {
wait = MIN(wait, ports_ldsc[ln].txdeltausecs); wait = MIN(wait, ports_ldsc[ln].txdeltausecs);
ports_state[ln].tx_chars--; ports_state[ln].tx_chars--;
ports_state[ln].tx_addr++; ports_state[ln].tx_addr++;
sim_debug(IO_DBG, &ports_dev,
"[ports_xmt_svc] [LINE %d] XMIT: %02x (%c)\n",
ln, c, c);
} }
if (ports_state[ln].tx_chars == 0) { if (ports_state[ln].tx_chars == 0) {
sim_debug(TRACE_DBG, &ports_dev,
"[ports_xmt_svc] Done with xmit, card=%d port=%d. Interrupting.\n",
slot, LPORT(ln));
centry.byte_count = ports_state[ln].tx_req_chars; centry.byte_count = ports_state[ln].tx_req_chars;
centry.subdevice = LPORT(ln); centry.subdevice = LPORT(ln);
centry.opcode = PPC_XMIT; centry.opcode = PPC_XMIT;
centry.address = ports_state[ln].tx_req_addr; centry.address = ports_state[ln].tx_req_addr;
app_data[0] = RC_FLU; app_data[0] = GC_FLU;
cio_cqueue(slot, CIO_STAT, PPQESIZE, &centry, app_data);
CIO_SET_INT(slot);
}
}
}
}
/* Scan LPT line for output */
if (lpt_state.conn && lpt_state.tx_chars > 0) {
tx = TRUE;
/* This is a hack -- we just want the slot of the first installed
PORTS board */
slot = LSLOT(0);
wait = MIN(wait, SERIAL_OUT_WAIT);
c = pread_b(lpt_state.tx_addr, BUS_PER);
/* The PORTS card optionally handles NL->CRLF */
if (c == 0xa && (lpt_state.oflag & ONLCR) && !(lpt_state.crlf)) {
/* Indicate that we're in a CRLF translation */
lpt_state.crlf = TRUE;
lpt_out(0xd);
} else {
lpt_state.crlf = FALSE;
lpt_state.tx_chars--;
lpt_state.tx_addr++;
lpt_out(c);
if (lpt_state.tx_chars == 0) {
centry.byte_count = lpt_state.tx_req_chars;
centry.subdevice = PORTS_CENTRONICS;
centry.opcode = PPC_XMIT;
centry.address = lpt_state.tx_req_addr;
app_data[0] = GC_FLU;
cio_cqueue(slot, CIO_STAT, PPQESIZE, &centry, app_data); cio_cqueue(slot, CIO_STAT, PPQESIZE, &centry, app_data);
CIO_SET_INT(slot); CIO_SET_INT(slot);
} }
@ -836,3 +926,59 @@ t_stat ports_detach(UNIT *uptr)
return SCPE_OK; return SCPE_OK;
} }
t_stat lpt_reset(DEVICE *dptr)
{
/* No-op */
return SCPE_OK;
}
t_stat lpt_attach(UNIT *uptr, const char *cptr)
{
t_stat reason;
if (ports_dev.flags & DEV_DIS) {
return SCPE_NOFNC;
}
if ((reason = attach_unit(uptr, cptr)) == SCPE_OK) {
lpt_state.conn = TRUE;
}
return reason;
}
t_stat lpt_detach(UNIT *uptr)
{
lpt_state.conn = FALSE;
return detach_unit(uptr);
}
t_stat lpt_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
{
fprintf(st, "Line Printer (LPT)\n\n");
fprintf(st, "The line printer (LPT) simulates an AT&T 470 120cps line printer\n");
fprintf(st, "connected to the Centronics port of the first installed PORTS card. It\n");
fprintf(st, "writes text output to an attached file on disk. To use the LPT device,\n");
fprintf(st, "first ENABLE it, then ATTACH it to a disk file to be used for text \n");
fprintf(st, "output, for example:\n\n");
fprintf(st, " SET LPT ENABLE\n");
fprintf(st, " ATTACH LPT my_output.txt\n\n");
fprintf(st, "To use this device under System V UNIX, set up a printer attached to\n");
fprintf(st, "TTY number 5 of the first installed PORTS card.\n\n");
fprintf(st, "For example, if the first installed PORTS card has created TTY devices\n");
fprintf(st, "/dev/tty21 through /dev/tty25 (where /dev/tty2* indicates that the PORTS\n");
fprintf(st, "card is in backplane slot 2), the printer will be on TTY device /dev/tty25.\n\n");
fprintf(st, "Please note that the LPT requires at least one PORTS card be configured. It\n");
fprintf(st, "will not allow attaching to an output file unless a PORTS card is enabled.\n");
fprintf(st, "If you see the output\n\n");
fprintf(st, " Command not allowed\n\n");
fprintf(st, "when trying to attach the LPT device, it means you have not enabled at\n");
fprintf(st, "least one PORTS card.\n");
return SCPE_OK;
}
const char *lpt_description(DEVICE *dptr)
{
return "AT&T 470 120cps Dot Matrix Printer";
}

View file

@ -51,16 +51,15 @@
#define PORTS_IPL 10 #define PORTS_IPL 10
#define PORTS_VERSION 1 #define PORTS_VERSION 1
#define MAX_CARDS 8 /* Up to 8 PORTS cards with 32 lines total #define MAX_CARDS 8 /* Up to 8 PORTS cards supported */
supported */ #define PORTS_CENTRONICS 4 /* Subdevice 4 is the centronics port */
#define PORTS_LINES 4 #define PORTS_LINES 4 /* Subdevices 0-3 are RS232 ports */
#define PORTS_RCV_QUEUE 5 #define PORTS_RCV_QUEUE 5 /* Total of 5 receive queues for all ports */
/* /*
* Sub-field values for the PPC_DEVICE request entry; these are placed * Sub-field values for the PPC_DEVICE request entry; these are placed in
* in app_data.bt[0] in the PPC_DEVICE application field. The prefix * app_data.bt[0] in the PPC_DEVICE application field. The prefix DR
* DR indicates that this is a code for use in "device" request * indicates that this is a code for use in "device" request entries only.
* entries only.
*/ */
#define DR_ENA 1 /* enable a device */ #define DR_ENA 1 /* enable a device */
@ -222,6 +221,11 @@ t_stat ports_xmt_svc(UNIT *uptr);
t_stat ports_cio_svc(UNIT *uptr); t_stat ports_cio_svc(UNIT *uptr);
t_stat ports_attach(UNIT *uptr, CONST char *cptr); t_stat ports_attach(UNIT *uptr, CONST char *cptr);
t_stat ports_detach(UNIT *uptr); t_stat ports_detach(UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
t_stat lpt_attach (UNIT *uptr, CONST char *ptr);
t_stat lpt_detach (UNIT *uptr);
t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
const char *lpt_description (DEVICE *dptr);
void ports_sysgen(uint8 slot); void ports_sysgen(uint8 slot);
void ports_express(uint8 slot); void ports_express(uint8 slot);
void ports_full(uint8 slot); void ports_full(uint8 slot);

View file

@ -97,6 +97,8 @@
#define MEMID_1M 2 #define MEMID_1M 2
#define MEMID_2M 1 #define MEMID_2M 1
#define MEMID_4M 3 #define MEMID_4M 3
#define MMUBASE 0x40000
#define MMUSIZE 0x1000
/* DMA Controller */ /* DMA Controller */
#define DMACBASE 0x48000 #define DMACBASE 0x48000

View file

@ -140,9 +140,6 @@
* *
***********************************************************************/ ***********************************************************************/
#define MMUBASE 0x40000
#define MMUSIZE 0x1000
#define MMU_SRS 0x04 /* Section RAM array size (words) */ #define MMU_SRS 0x04 /* Section RAM array size (words) */
#define MMU_SDCS 0x20 /* Segment Descriptor Cache H/L array size #define MMU_SDCS 0x20 /* Segment Descriptor Cache H/L array size
(words) */ (words) */

View file

@ -60,6 +60,7 @@ DEVICE *sim_devices[] = {
&if_dev, &if_dev,
&id_dev, &id_dev,
&ports_dev, &ports_dev,
&lpt_dev,
&ctc_dev, &ctc_dev,
&ni_dev, &ni_dev,
NULL NULL
@ -77,6 +78,7 @@ void full_reset()
id_reset(&id_dev); id_reset(&id_dev);
csr_reset(&csr_dev); csr_reset(&csr_dev);
ports_reset(&ports_dev); ports_reset(&ports_dev);
lpt_reset(&lpt_dev);
ctc_reset(&ctc_dev); ctc_reset(&ctc_dev);
ni_reset(&ni_dev); ni_reset(&ni_dev);
} }

View file

@ -600,6 +600,10 @@ void mmu_write(uint32 pa, uint32 val, size_t size)
/* Flush all PDC cache entries for this section */ /* Flush all PDC cache entries for this section */
for (i = 0; i < MMU_PDCS; i++) { for (i = 0; i < MMU_PDCS; i++) {
if (((mmu_state.pdch[i] >> 24) & 0x3) == index) { if (((mmu_state.pdch[i] >> 24) & 0x3) == index) {
sim_debug(MMU_CACHE_DBG, &mmu_dev,
"Flushing MMU PDC entry at index %d "
"(pdc_lo=%08x pdc_hi=%08x)\n",
i, mmu_state.pdcl[i], mmu_state.pdch[i]);
mmu_state.pdch[i] &= ~(PDC_G_MASK); mmu_state.pdch[i] &= ~(PDC_G_MASK);
} }
} }
@ -1041,8 +1045,9 @@ uint32 mmu_xlate_addr(uint32 va, uint8 r_acc)
succ = mmu_decode_va(va, r_acc, TRUE, &pa); succ = mmu_decode_va(va, r_acc, TRUE, &pa);
if (succ == SCPE_OK) {
mmu_state.var = va; mmu_state.var = va;
if (succ == SCPE_OK) {
return pa; return pa;
} else { } else {
cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT);

View file

@ -60,6 +60,7 @@ DEVICE *sim_devices[] = {
&if_dev, &if_dev,
&ha_dev, &ha_dev,
&ports_dev, &ports_dev,
&lpt_dev,
&ni_dev, &ni_dev,
NULL NULL
}; };
@ -76,5 +77,6 @@ void full_reset()
ha_reset(&ha_dev); ha_reset(&ha_dev);
csr_reset(&csr_dev); csr_reset(&csr_dev);
ports_reset(&ports_dev); ports_reset(&ports_dev);
lpt_reset(&lpt_dev);
ni_reset(&ni_dev); ni_reset(&ni_dev);
} }

View file

@ -506,7 +506,16 @@ static void ha_boot_tape(UNIT *uptr, uint8 tc)
return; return;
} }
r = sim_tape_rdrecf(uptr, buf, &sectsread, HA_BLKSZ); /* Read block 0 */ r = sim_tape_sprecf(uptr, &sectsread); /* Skip block 0 */
if (r != SCPE_OK) {
sim_debug(HA_TRACE, &ha_dev,
"[ha_boot_tape] Could not skip block 0.\n");
HA_STAT(tc, HA_CKCON, CIO_SUCCESS);
return;
}
r = sim_tape_rdrecf(uptr, buf, &sectsread, HA_BLKSZ); /* Read block 1 */
if (r != SCPE_OK) { if (r != SCPE_OK) {
sim_debug(HA_TRACE, &ha_dev, sim_debug(HA_TRACE, &ha_dev,
@ -523,8 +532,6 @@ static void ha_boot_tape(UNIT *uptr, uint8 tc)
"[ha_boot_tape] Transfered 512 bytes to 0x%08x\n", "[ha_boot_tape] Transfered 512 bytes to 0x%08x\n",
HA_BOOT_ADDR); HA_BOOT_ADDR);
r = sim_tape_sprecf(uptr, &sectsread); /* Skip block 1 */
HA_STAT(tc, HA_GOOD, CIO_SUCCESS); HA_STAT(tc, HA_GOOD, CIO_SUCCESS);
ha_state.ts[tc].rep.addr = HA_BOOT_ADDR; ha_state.ts[tc].rep.addr = HA_BOOT_ADDR;