3b2: NI 10Base5 Ethernet Device
- Implements an Ethernet device ("NI", for "Network Interface") for the 3B2 simulator.
This commit is contained in:
parent
4b82a90c43
commit
b0a4fb443c
12 changed files with 1859 additions and 122 deletions
|
@ -170,9 +170,10 @@ static DEBTAB cpu_deb_tab[] = {
|
|||
{ "INIT", INIT_MSG, "Initialization" },
|
||||
{ "IRQ", IRQ_MSG, "Interrupt Handling" },
|
||||
{ "IO", IO_DBG, "I/O Dispatch" },
|
||||
{ "CIO", CIO_DBG, "Common I/O Interface" },
|
||||
{ "TRACE", TRACE_DBG, "Call Trace" },
|
||||
{ "ERROR", ERR_MSG, "Error" },
|
||||
{ NULL, 0 }
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) };
|
||||
|
@ -180,9 +181,13 @@ UNIT cpu_unit = { UDATA (NULL, UNIT_FIX|UNIT_BINK|UNIT_IDLE, MAXMEMSIZE) };
|
|||
#define UNIT_V_EXHALT (UNIT_V_UF + 0) /* halt to console */
|
||||
#define UNIT_EXHALT (1u << UNIT_V_EXHALT)
|
||||
|
||||
/*
|
||||
* TODO: This works fine for now, but the moment we want to emulate
|
||||
* SCSI (0x0100) or EPORTS (0x0102) we're in trouble!
|
||||
*/
|
||||
const char *cio_names[8] = {
|
||||
"", "*VOID*", "*VOID*", "PORTS",
|
||||
"*VOID*", "CTC", "*VOID*", "*VOID*"
|
||||
"", "SBD", "NI", "PORTS",
|
||||
"*VOID*", "CTC", "NAU", "*VOID*"
|
||||
};
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
|
@ -1821,9 +1826,9 @@ t_stat sim_instr(void)
|
|||
if (cio[i].intr &&
|
||||
cio[i].ipl == cpu_int_ipl &&
|
||||
cio[i].ivec == cpu_int_vec) {
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
"[%08x] [IRQ] Handling CIO interrupt for card %d\n",
|
||||
R[NUM_PC], i);
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[%08x] [IRQ] Handling CIO interrupt for card %d ivec=%02x\n",
|
||||
R[NUM_PC], i, cpu_int_vec);
|
||||
|
||||
cio[i].intr = FALSE;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,12 @@ noret __libc_longjmp (jmp_buf buf, int val);
|
|||
#define HALF_MASK 0xffffu
|
||||
#define BYTE_MASK 0xff
|
||||
|
||||
/*
|
||||
* Custom t_stat
|
||||
*/
|
||||
|
||||
#define SCPE_PEND (SCPE_OK + 1) /* CIO job already pending */
|
||||
#define SCPE_NOJOB (SCPE_OK + 2) /* No CIO job on the request queue */
|
||||
/*
|
||||
*
|
||||
* Physical memory in the 3B2 is arranged as follows:
|
||||
|
@ -141,15 +147,19 @@ noret __libc_longjmp (jmp_buf buf, int val);
|
|||
#define C_STACK_FAULT 9
|
||||
|
||||
/* Debug flags */
|
||||
#define READ_MSG 0x001
|
||||
#define WRITE_MSG 0x002
|
||||
#define DECODE_MSG 0x004
|
||||
#define EXECUTE_MSG 0x008
|
||||
#define INIT_MSG 0x010
|
||||
#define IRQ_MSG 0x020
|
||||
#define IO_DBG 0x040
|
||||
#define TRACE_DBG 0x080
|
||||
#define ERR_MSG 0x100
|
||||
#define READ_MSG 0x0001
|
||||
#define WRITE_MSG 0x0002
|
||||
#define DECODE_MSG 0x0004
|
||||
#define EXECUTE_MSG 0x0008
|
||||
#define INIT_MSG 0x0010
|
||||
#define IRQ_MSG 0x0020
|
||||
#define IO_DBG 0x0040
|
||||
#define CIO_DBG 0x0080
|
||||
#define TRACE_DBG 0x0100
|
||||
#define CALL_DBG 0x0200
|
||||
#define PKT_DBG 0x0400
|
||||
#define ERR_MSG 0x0800
|
||||
#define CACHE_DBG 0x1000
|
||||
|
||||
/* Data types operated on by instructions. NB: These integer values
|
||||
have meaning when decoding instructions, so this is not just an
|
||||
|
|
|
@ -171,12 +171,10 @@ t_stat if_detach(UNIT *uptr)
|
|||
|
||||
uint32 if_read(uint32 pa, size_t size) {
|
||||
uint8 reg, data;
|
||||
uint32 pc;
|
||||
UNIT *uptr;
|
||||
|
||||
uptr = &(if_dev.units[0]);
|
||||
reg = (uint8)(pa - IFBASE);
|
||||
pc = R[NUM_PC];
|
||||
|
||||
switch (reg) {
|
||||
case IF_STATUS_REG:
|
||||
|
|
140
3B2/3b2_io.c
140
3B2/3b2_io.c
|
@ -56,6 +56,7 @@ void cio_clear(uint8 cid)
|
|||
cio[cid].id = 0;
|
||||
cio[cid].exp_handler = NULL;
|
||||
cio[cid].full_handler = NULL;
|
||||
cio[cid].reset_handler = NULL;
|
||||
cio[cid].sysgen = NULL;
|
||||
cio[cid].rqp = 0;
|
||||
cio[cid].cqp = 0;
|
||||
|
@ -101,7 +102,7 @@ void cio_sysgen(uint8 cid)
|
|||
|
||||
sysgen_p = pread_w(SYSGEN_PTR);
|
||||
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[%08x] [SYSGEN] Starting sysgen for card %d. sysgen_p=%08x\n",
|
||||
R[NUM_PC], cid, sysgen_p);
|
||||
|
||||
|
@ -115,22 +116,22 @@ void cio_sysgen(uint8 cid)
|
|||
cio[cid].ivec = pread_b(sysgen_p + 10);
|
||||
cio[cid].no_rque = pread_b(sysgen_p + 11);
|
||||
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen rqp = %08x\n",
|
||||
cio[cid].rqp);
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen cqp = %08x\n",
|
||||
cio[cid].cqp);
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen rqs = %02x\n",
|
||||
cio[cid].rqs);
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen cqs = %02x\n",
|
||||
cio[cid].cqs);
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen ivec = %02x\n",
|
||||
cio[cid].ivec);
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[SYSGEN] sysgen no_rque = %02x\n",
|
||||
cio[cid].no_rque);
|
||||
|
||||
|
@ -138,20 +139,19 @@ void cio_sysgen(uint8 cid)
|
|||
if (cio[cid].sysgen != NULL) {
|
||||
cio[cid].sysgen(cid);
|
||||
} else {
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[%08x] [cio_sysgen] Not running custom sysgen.\n",
|
||||
R[NUM_PC]);
|
||||
}
|
||||
}
|
||||
|
||||
void cio_cexpress(uint8 cid, uint16 esize, cio_entry *cqe, uint8 *app_data)
|
||||
void cio_cexpress(uint8 cid, uint32 esize, cio_entry *cqe, uint8 *app_data)
|
||||
{
|
||||
int32 i;
|
||||
uint32 cqp;
|
||||
uint32 i, cqp;
|
||||
|
||||
cqp = cio[cid].cqp;
|
||||
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[%08x] [cio_cexpress] cqp = %08x seqbit = %d\n",
|
||||
R[NUM_PC], cqp, cio[cid].seqbit);
|
||||
|
||||
|
@ -170,12 +170,11 @@ void cio_cexpress(uint8 cid, uint16 esize, cio_entry *cqe, uint8 *app_data)
|
|||
}
|
||||
}
|
||||
|
||||
void cio_cqueue(uint8 cid, uint8 cmd_stat, uint16 esize,
|
||||
void cio_cqueue(uint8 cid, uint8 cmd_stat, uint32 esize,
|
||||
cio_entry *cqe, uint8 *app_data)
|
||||
{
|
||||
int32 i;
|
||||
uint32 cqp, top;
|
||||
uint16 lp, ulp;
|
||||
uint32 i, cqp, top;
|
||||
uint16 lp;
|
||||
|
||||
/* Apply the CMD/STAT bit */
|
||||
cqe->subdevice |= (cmd_stat << 7);
|
||||
|
@ -191,7 +190,6 @@ void cio_cqueue(uint8 cid, uint8 cmd_stat, uint16 esize,
|
|||
/* Get the load pointer. This is a 16-bit absolute offset
|
||||
* from the top of the queue to the start of the entry. */
|
||||
lp = pread_h(cqp + esize);
|
||||
ulp = pread_h(cqp + esize + 2);
|
||||
|
||||
/* Load the entry at the supplied address */
|
||||
pwrite_h(top + lp, cqe->byte_count);
|
||||
|
@ -209,22 +207,17 @@ void cio_cqueue(uint8 cid, uint8 cmd_stat, uint16 esize,
|
|||
* start of the queue */
|
||||
if (cio[cid].cqs > 0) {
|
||||
lp = (lp + esize) % (esize * cio[cid].cqs);
|
||||
|
||||
/* Store it back to the correct location */
|
||||
pwrite_h(cqp + esize, lp);
|
||||
} else {
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
"[%08x] [cio_cqueue] ERROR! Completion Queue Size is 0!",
|
||||
R[NUM_PC]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the Express Entry from the Request Queue
|
||||
*/
|
||||
void cio_rexpress(uint8 cid, uint16 esize, cio_entry *rqe, uint8 *app_data)
|
||||
void cio_rexpress(uint8 cid, uint32 esize, cio_entry *rqe, uint8 *app_data)
|
||||
{
|
||||
int32 i;
|
||||
uint32 i;
|
||||
uint32 rqp;
|
||||
|
||||
rqp = cio[cid].rqp;
|
||||
|
@ -247,12 +240,12 @@ void cio_rexpress(uint8 cid, uint16 esize, cio_entry *rqe, uint8 *app_data)
|
|||
* be serviced.
|
||||
*
|
||||
* Returns SCPE_OK on success, or SCPE_NXM if no entry was found.
|
||||
*
|
||||
*/
|
||||
t_stat cio_rqueue(uint8 cid, uint8 qnum, uint16 esize,
|
||||
t_stat cio_rqueue(uint8 cid, uint32 qnum, uint32 esize,
|
||||
cio_entry *rqe, uint8 *app_data)
|
||||
{
|
||||
int32 i;
|
||||
uint32 rqp, top;
|
||||
uint32 i, rqp, top;
|
||||
uint16 lp, ulp;
|
||||
|
||||
/* Get the physical address of the request queue in main memory */
|
||||
|
@ -263,6 +256,8 @@ t_stat cio_rqueue(uint8 cid, uint8 qnum, uint16 esize,
|
|||
lp = pread_h(rqp);
|
||||
ulp = pread_h(rqp + 2);
|
||||
|
||||
/* Check to see if the request queue is empty. If it is, there's
|
||||
* nothing to take. */
|
||||
if (lp == ulp) {
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
@ -294,7 +289,7 @@ t_stat cio_rqueue(uint8 cid, uint8 qnum, uint16 esize,
|
|||
/*
|
||||
* Return the Load Pointer for the given request queue
|
||||
*/
|
||||
uint16 cio_r_lp(uint8 cid, uint8 qnum, uint16 esize)
|
||||
uint16 cio_r_lp(uint8 cid, uint32 qnum, uint32 esize)
|
||||
{
|
||||
uint32 rqp;
|
||||
|
||||
|
@ -308,7 +303,7 @@ uint16 cio_r_lp(uint8 cid, uint8 qnum, uint16 esize)
|
|||
/*
|
||||
* Return the Unload Pointer for the given request queue
|
||||
*/
|
||||
uint16 cio_r_ulp(uint8 cid, uint8 qnum, uint16 esize)
|
||||
uint16 cio_r_ulp(uint8 cid, uint32 qnum, uint32 esize)
|
||||
{
|
||||
uint32 rqp;
|
||||
|
||||
|
@ -319,14 +314,14 @@ uint16 cio_r_ulp(uint8 cid, uint8 qnum, uint16 esize)
|
|||
return pread_h(rqp + 2);
|
||||
}
|
||||
|
||||
uint16 cio_c_lp(uint8 cid, uint16 esize)
|
||||
uint16 cio_c_lp(uint8 cid, uint32 esize)
|
||||
{
|
||||
uint32 cqp;
|
||||
cqp = cio[cid].cqp + esize;
|
||||
return pread_h(cqp);
|
||||
}
|
||||
|
||||
uint16 cio_c_ulp(uint8 cid, uint16 esize)
|
||||
uint16 cio_c_ulp(uint8 cid, uint32 esize)
|
||||
{
|
||||
uint32 cqp;
|
||||
cqp = cio[cid].cqp + esize;
|
||||
|
@ -337,7 +332,7 @@ uint16 cio_c_ulp(uint8 cid, uint16 esize)
|
|||
* Returns true if there is room in the completion queue
|
||||
* for a new entry.
|
||||
*/
|
||||
t_bool cio_cqueue_avail(uint8 cid, uint16 esize)
|
||||
t_bool cio_cqueue_avail(uint8 cid, uint32 esize)
|
||||
{
|
||||
uint32 lp, ulp;
|
||||
|
||||
|
@ -347,6 +342,21 @@ t_bool cio_cqueue_avail(uint8 cid, uint16 esize)
|
|||
return(((lp + esize) % (cio[cid].cqs * esize)) != ulp);
|
||||
}
|
||||
|
||||
t_bool cio_rqueue_avail(uint8 cid, uint32 qnum, uint32 esize)
|
||||
{
|
||||
uint32 rqp, lp, ulp;
|
||||
|
||||
/* Get the physical address of the request queue in main memory */
|
||||
rqp = cio[cid].rqp +
|
||||
esize +
|
||||
(qnum * (LUSIZE + (esize * cio[cid].rqs)));
|
||||
|
||||
lp = pread_h(rqp);
|
||||
ulp = pread_h(rqp + 2);
|
||||
|
||||
return(lp != ulp);
|
||||
}
|
||||
|
||||
uint32 io_read(uint32 pa, size_t size)
|
||||
{
|
||||
struct iolink *p;
|
||||
|
@ -403,7 +413,7 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
case CIO_INT_NONE: /* We've never seen an INT0 or INT1 */
|
||||
case CIO_INT0: /* We've seen an INT0 but not an INT1. */
|
||||
cio[cid].sysgen_s |= CIO_INT0;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT0) ID\n",
|
||||
R[NUM_PC], cid);
|
||||
/* Return the correct byte of our board ID */
|
||||
|
@ -415,7 +425,7 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
break;
|
||||
case CIO_INT1: /* We've seen an INT1 but not an INT0. Time to sysgen */
|
||||
cio[cid].sysgen_s |= CIO_INT0;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT0) SYSGEN\n",
|
||||
R[NUM_PC], cid);
|
||||
cio_sysgen(cid);
|
||||
|
@ -423,7 +433,7 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
break;
|
||||
case CIO_SYSGEN: /* We've already sysgen'ed */
|
||||
cio[cid].sysgen_s |= CIO_INT0; /* This must come BEFORE the exp_handler */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT0) EXPRESS JOB\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].exp_handler(cid);
|
||||
|
@ -432,7 +442,7 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
default:
|
||||
/* This should never happen */
|
||||
stop_reason = STOP_ERR;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT0) ERROR IN STATE MACHINE sysgen_s=%02x\n",
|
||||
R[NUM_PC], cid, cio[cid].sysgen_s);
|
||||
data = 0;
|
||||
|
@ -445,20 +455,20 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
case CIO_INT_NONE: /* We've never seen an INT0 or INT1 */
|
||||
case CIO_INT1: /* We've seen an INT1 but not an INT0 */
|
||||
/* There's nothing to do in this instance */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT1) IGNORED\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1;
|
||||
break;
|
||||
case CIO_INT0: /* We've seen an INT0 but not an INT1. Time to sysgen */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT1) SYSGEN\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1;
|
||||
cio_sysgen(cid);
|
||||
break;
|
||||
case CIO_SYSGEN: /* We've already sysgen'ed */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT1) FULL\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1; /* This must come BEFORE the full handler */
|
||||
|
@ -467,7 +477,7 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
default:
|
||||
/* This should never happen */
|
||||
stop_reason = STOP_ERR;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d INT1) ERROR IN STATE MACHINE sysgen_s=%02x\n",
|
||||
R[NUM_PC], cid, cio[cid].sysgen_s);
|
||||
break;
|
||||
|
@ -475,15 +485,18 @@ uint32 io_read(uint32 pa, size_t size)
|
|||
|
||||
return 0; /* Data returned is arbitrary */
|
||||
case IOF_STAT:
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] (%d RESET)\n",
|
||||
R[NUM_PC], cid);
|
||||
if (cio[cid].reset_handler) {
|
||||
cio[cid].reset_handler(cid);
|
||||
}
|
||||
cio[cid].sysgen_s = 0;
|
||||
return 0; /* Data returned is arbitrary */
|
||||
default:
|
||||
/* We should never reach here, but if we do, there's
|
||||
* nothing listening. */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[READ] [%08x] No card at cid=%d reg=%d\n",
|
||||
R[NUM_PC], cid, reg);
|
||||
csr_data |= CSRTIMO;
|
||||
|
@ -520,7 +533,7 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
|
||||
if (cio[cid].id == 0) {
|
||||
/* Nothing lives here */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] No card at cid=%d reg=%d\n",
|
||||
R[NUM_PC], cid, reg);
|
||||
csr_data |= CSRTIMO;
|
||||
|
@ -540,20 +553,20 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
switch(cio[cid].sysgen_s) {
|
||||
case CIO_INT_NONE: /* We've never seen an INT0 or INT1 */
|
||||
case CIO_INT0: /* We've seen an INT0 but not an INT1. */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT0) ID\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT0;
|
||||
break;
|
||||
case CIO_INT1: /* We've seen an INT1 but not an INT0. Time to sysgen */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT0) SYSGEN\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT0;
|
||||
cio_sysgen(cid);
|
||||
break;
|
||||
case CIO_SYSGEN: /* We've already sysgen'ed */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT0) EXPRESS JOB\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT0;
|
||||
|
@ -562,7 +575,7 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
default:
|
||||
/* This should never happen */
|
||||
stop_reason = STOP_ERR;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT0) ERROR IN STATE MACHINE sysgen_s=%02x\n",
|
||||
R[NUM_PC], cid, cio[cid].sysgen_s);
|
||||
break;
|
||||
|
@ -574,20 +587,20 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
case CIO_INT_NONE: /* We've never seen an INT0 or INT1 */
|
||||
case CIO_INT1: /* We've seen an INT1 but not an INT0 */
|
||||
/* There's nothing to do in this instance */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT1) IGNORED\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1;
|
||||
break;
|
||||
case CIO_INT0: /* We've seen an INT0 but not an INT1. Time to sysgen */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT1) SYSGEN\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1;
|
||||
cio_sysgen(cid);
|
||||
break;
|
||||
case CIO_SYSGEN: /* We've already sysgen'ed */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT1) FULL\n",
|
||||
R[NUM_PC], cid);
|
||||
cio[cid].sysgen_s |= CIO_INT1;
|
||||
|
@ -596,7 +609,7 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
default:
|
||||
/* This should never happen */
|
||||
stop_reason = STOP_ERR;
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d INT1) ERROR IN STATE MACHINE sysgen_s=%02x\n",
|
||||
R[NUM_PC], cid, cio[cid].sysgen_s);
|
||||
break;
|
||||
|
@ -604,15 +617,18 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
|
||||
return;
|
||||
case IOF_STAT:
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] (%d RESET)\n",
|
||||
R[NUM_PC], cid);
|
||||
if (cio[cid].reset_handler) {
|
||||
cio[cid].reset_handler(cid);
|
||||
}
|
||||
cio[cid].sysgen_s = 0;
|
||||
return;
|
||||
default:
|
||||
/* We should never reach here, but if we do, there's
|
||||
* nothing listening. */
|
||||
sim_debug(IO_DBG, &cpu_dev,
|
||||
sim_debug(CIO_DBG, &cpu_dev,
|
||||
"[WRITE] [%08x] No card at cid=%d reg=%d\n",
|
||||
R[NUM_PC], cid, reg);
|
||||
csr_data |= CSRTIMO;
|
||||
|
@ -640,10 +656,18 @@ void io_write(uint32 pa, uint32 val, size_t size)
|
|||
|
||||
/* For debugging only */
|
||||
void dump_entry(uint32 dbits, DEVICE *dev, CONST char *type,
|
||||
uint16 esize, cio_entry *entry, uint8 *app_data)
|
||||
uint32 esize, cio_entry *entry, uint8 *app_data)
|
||||
{
|
||||
sim_debug(dbits, dev,
|
||||
"*** %s ENTRY: byte_count=%04x, subdevice=%02x, opcode=%d, address=%08x\n",
|
||||
type, entry->byte_count, entry->subdevice,
|
||||
entry->opcode, entry->address);
|
||||
char appl[64];
|
||||
uint32 i, c_offset;
|
||||
|
||||
for (i = 0, c_offset=0; i < (esize - QESIZE); i++) {
|
||||
snprintf(appl + c_offset, 3, "%02x", app_data[i]);
|
||||
c_offset += 2;
|
||||
}
|
||||
|
||||
sim_debug(dbits, dev,
|
||||
"*** %s ENTRY: byte_count=%04x, subdevice=%02x, opcode=%d, address=%08x, app_data=%s\n",
|
||||
type, entry->byte_count, entry->subdevice,
|
||||
entry->opcode, entry->address, appl);
|
||||
}
|
||||
|
|
28
3B2/3b2_io.h
28
3B2/3b2_io.h
|
@ -134,6 +134,11 @@
|
|||
#define CIO_DOS 4
|
||||
#define CIO_DSD 5
|
||||
|
||||
/* Response */
|
||||
#define CIO_SUCCESS 0
|
||||
#define CIO_FAILURE 2
|
||||
#define CIO_SYSGEN_OK 3
|
||||
|
||||
/* Map a physical address to a card ID */
|
||||
#define CID(pa) (((((pa) >> 0x14) & 0x1f) / 2) - 1)
|
||||
/* Map a card ID to a base address */
|
||||
|
@ -158,6 +163,7 @@ typedef struct {
|
|||
void (*exp_handler)(uint8 cid); /* Handler for express jobs */
|
||||
void (*full_handler)(uint8 cid); /* Handler for full jobs */
|
||||
void (*sysgen)(uint8 cid); /* Sysgen routine (optional) */
|
||||
void (*reset_handler)(uint8 cid); /* RESET request handler (optional) */
|
||||
uint32 rqp; /* Request Queue Pointer */
|
||||
uint32 cqp; /* Completion Queue Pointer */
|
||||
uint8 rqs; /* Request queue size */
|
||||
|
@ -213,6 +219,7 @@ typedef struct {
|
|||
uint32 retcode;
|
||||
} pump;
|
||||
|
||||
extern t_bool cio_skip_seqbit;
|
||||
extern uint16 cio_ints;
|
||||
extern CIO_STATE cio[CIO_SLOTS];
|
||||
|
||||
|
@ -221,18 +228,19 @@ t_stat cio_svc(UNIT *uptr);
|
|||
|
||||
void cio_clear(uint8 cid);
|
||||
uint32 cio_crc32_shift(uint32 crc, uint8 data);
|
||||
void cio_cexpress(uint8 cid, uint16 esize, cio_entry *cqe, uint8 *app_data);
|
||||
void cio_cqueue(uint8 cid, uint8 cmd_stat, uint16 esize, cio_entry *cqe, uint8 *app_data);
|
||||
void cio_rexpress(uint8 cid, uint16 esize, cio_entry *rqe, uint8 *app_data);
|
||||
t_stat cio_rqueue(uint8 cid, uint8 qnum, uint16 esize, cio_entry *rqe, uint8 *app_data);
|
||||
t_bool cio_cqueue_avail(uint8 cid, uint16 esize);
|
||||
uint16 cio_r_lp(uint8 cid, uint8 qnum, uint16 esize);
|
||||
uint16 cio_r_ulp(uint8 cid, uint8 qnum, uint16 esize);
|
||||
uint16 cio_c_lp(uint8 cid, uint16 esize);
|
||||
uint16 cio_c_ulp(uint8 cid, uint16 esize);
|
||||
void cio_cexpress(uint8 cid, uint32 esize, cio_entry *cqe, uint8 *app_data);
|
||||
void cio_cqueue(uint8 cid, uint8 cmd_stat, uint32 esize, cio_entry *cqe, uint8 *app_data);
|
||||
t_bool cio_cqueue_avail(uint8 cid, uint32 esize);
|
||||
void cio_rexpress(uint8 cid, uint32 esize, cio_entry *rqe, uint8 *app_data);
|
||||
t_stat cio_rqueue(uint8 cid, uint32 qnum, uint32 esize, cio_entry *rqe, uint8 *app_data);
|
||||
t_bool cio_rqueue_avail(uint8 cid, uint32 qnum, uint32 esize);
|
||||
uint16 cio_r_lp(uint8 cid, uint32 qnum, uint32 esize);
|
||||
uint16 cio_r_ulp(uint8 cid, uint32 qnum, uint32 esize);
|
||||
uint16 cio_c_lp(uint8 cid, uint32 esize);
|
||||
uint16 cio_c_ulp(uint8 cid, uint32 esize);
|
||||
void cio_sysgen(uint8 cid);
|
||||
|
||||
void dump_entry(uint32 dbits, DEVICE *dev, CONST char *type,
|
||||
uint16 esize, cio_entry *entry, uint8 *app_data);
|
||||
uint32 esize, cio_entry *entry, uint8 *app_data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -332,6 +332,9 @@ void pwrite_b(uint32 pa, uint8 val);
|
|||
void pwrite_h(uint32 pa, uint16 val);
|
||||
void pwrite_w(uint32 pa, uint32 val);
|
||||
|
||||
/* TODO: REMOVE AFTER DEBUGGING */
|
||||
uint32 safe_read_w(uint32 va);
|
||||
|
||||
/* Virtual memory translation */
|
||||
uint32 mmu_xlate_addr(uint32 va, uint8 r_acc);
|
||||
t_stat mmu_decode_vaddr(uint32 vaddr, uint8 r_acc,
|
||||
|
|
1270
3B2/3b2_ni.c
Normal file
1270
3B2/3b2_ni.c
Normal file
File diff suppressed because it is too large
Load diff
219
3B2/3b2_ni.h
Normal file
219
3B2/3b2_ni.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
/* 3b2_ni.h: AT&T 3B2 Model 400 "NI" feature card
|
||||
|
||||
Copyright (c) 2018, Seth J. Morabito
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use, copy,
|
||||
modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of the author shall
|
||||
not be used in advertising or otherwise to promote the sale, use or
|
||||
other dealings in this Software without prior written authorization
|
||||
from the author.
|
||||
*/
|
||||
|
||||
#ifndef _3B2_NI_H_
|
||||
#define _3B2_NI_H_
|
||||
|
||||
#include "3b2_defs.h"
|
||||
#include "3b2_io.h"
|
||||
#include "sim_ether.h"
|
||||
|
||||
#define NI_ID 0x0002
|
||||
#define NI_IPL 12
|
||||
|
||||
/* Opcodes for NI card */
|
||||
|
||||
#define NI_SETID 6
|
||||
#define NI_TURNOFF 7
|
||||
#define NI_TURNON 8
|
||||
#define NI_SEND 11
|
||||
#define NI_RECV 12
|
||||
#define NI_STATS 13
|
||||
#define NI_SANITY 15
|
||||
#define NI_SEND_A 22
|
||||
|
||||
#define MAC_SIZE_BYTES 6
|
||||
#define MAC_SIZE_CHARS 20
|
||||
|
||||
#define NIQESIZE 12
|
||||
#define NI_QUE_MAX 1024
|
||||
#define NI_TMR_WAIT_DEFAULT 3000
|
||||
#define NI_RCV_POLL_US 8000
|
||||
#define NI_XMIT_DELAY_US 60000
|
||||
#define NI_INT_DELAY_US 500
|
||||
#define NI_SANITY_INTERVAL_US 5000000
|
||||
|
||||
/* Maximum allowed number of multicast addresses */
|
||||
#define NI_MULTI_MAX 64
|
||||
|
||||
/* At least two filter addresses are always configured:
|
||||
* 1. The host MAC
|
||||
* 2. The broadcast address */
|
||||
#define NI_FILTER_MIN 2
|
||||
|
||||
/* Maximum total allowed number of filter addresses, including the
|
||||
* host's MAC and the broadcast address. */
|
||||
#define NI_FILTER_MAX NI_MULTI_MAX + NI_FILTER_MIN
|
||||
|
||||
/* Indexes in the internal filter address table of the
|
||||
* host's MAC and the broadcast address */
|
||||
#define NI_NIC_MAC 0
|
||||
#define NI_BCST_MAC 1
|
||||
|
||||
/*
|
||||
* For performance reasons, there are two modes of polling the receive
|
||||
* queues. Initially, polling is VERY aggressive as we race the
|
||||
* filling of the receive queues. Once we've taken three jobs from
|
||||
* each of the two receive queues, we switch to slow polling,
|
||||
* which uses coscheduling.
|
||||
*/
|
||||
|
||||
#define NI_QPOLL_FAST 100
|
||||
#define NI_QPOLL_SLOW 50000
|
||||
|
||||
#define NI_DIAG_CRC1 0x795268a4
|
||||
#define NI_DIAG_CRC2 0xfab1057c
|
||||
#define NI_DIAG_CRC3 0x10ca00cd
|
||||
#define NI_PUMP_CRC1 0xfab1057c
|
||||
#define NI_PUMP_CRC2 0xf6744bed
|
||||
|
||||
#define EIG_TABLE_SIZE 40
|
||||
#define PKT_HEADER_LEN_OFFSET EIG_TABLE_SIZE
|
||||
#define PKT_START_OFFSET (PKT_HEADER_LEN_OFFSET + 4)
|
||||
|
||||
/*
|
||||
* The NI card has two request queues for packet receive: One for
|
||||
* small packets, and one for large packets. The small queue is meant
|
||||
* for packets smaller than 128 bytes. The large queue is meant for
|
||||
* packets up to 1500 bytes (no jumbo frames allowed)
|
||||
*/
|
||||
|
||||
#define GE_QUEUE 0 /* General request queue */
|
||||
#define SM_QUEUE 1 /* Small packet receive queue */
|
||||
#define LG_QUEUE 2 /* Large packet receive queue */
|
||||
#define SM_PKT_MAX 106 /* Max size of small packets (excluding CRC) */
|
||||
#define LG_PKT_MAX 1514 /* Max size of large packets (excluding CRC) */
|
||||
|
||||
/*
|
||||
* NI-specific debugging flags
|
||||
*/
|
||||
#define DBG_TRACE 0x01
|
||||
#define DBG_IO 0x02
|
||||
#define DBG_CACHE 0x04
|
||||
#define DBG_DAT 0x08
|
||||
#define DBG_ERR 0x10
|
||||
#define DBG_ETH 0x20
|
||||
|
||||
#define NI_CACHE_HAS_SPACE(i) (((ni.job_cache[(i)].wp + 1) % NI_CACHE_LEN) != ni.job_cache[(i)].rp)
|
||||
|
||||
/*
|
||||
* The NI card caches up to three jobs taken from each of the two
|
||||
* packet receive queues so that they are available immediately after
|
||||
* receipt of a packet. These jobs are kept in small circular buffers.
|
||||
* Each job is represented by an ni_rec_job structure, containing a
|
||||
* buffer pointer and a slot number. The slot number is used by both
|
||||
* the driver and the firmware to correlate a packet receive buffer
|
||||
* with a completion queue event.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32 addr; /* address of job's buffer */
|
||||
uint8 slot; /* slot number of the job */
|
||||
} ni_rec_job;
|
||||
|
||||
#define NI_CACHE_LEN 4
|
||||
|
||||
typedef struct {
|
||||
ni_rec_job req[NI_CACHE_LEN]; /* the cache */
|
||||
int wp; /* write pointer */
|
||||
int rp; /* read pointer */
|
||||
} ni_job_cache;
|
||||
|
||||
/*
|
||||
* When the NI driver submits a packet send request to the general
|
||||
* request queue, it constructs one or more ni_prot_info structs in
|
||||
* main memory that point to the protocol-specific byte data of the
|
||||
* packet (minus the Ethernet frame). These structs are packed one
|
||||
* after the other following the Ethernet frame header in the job's
|
||||
* request buffer. The last entry has its "last" bit set to non-zero.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32 addr; /* Physical address of the buffer in system RAM */
|
||||
uint16 size; /* Length of the buffer */
|
||||
uint16 last; /* Is this the last entry in the list? */
|
||||
} ni_prot_info;
|
||||
|
||||
typedef struct {
|
||||
uint32 rq_taken;
|
||||
uint32 tx_fail;
|
||||
uint32 rx_dropped;
|
||||
uint32 rx_pkt;
|
||||
uint32 tx_pkt;
|
||||
uint32 rx_bytes;
|
||||
uint32 tx_bytes;
|
||||
} ni_stat_info;
|
||||
|
||||
typedef struct {
|
||||
uint8 cid;
|
||||
t_bool initialized;
|
||||
t_bool enabled;
|
||||
uint32 crc;
|
||||
uint32 poll_rate;
|
||||
char mac_str[MAC_SIZE_CHARS];
|
||||
uint8 mac_bytes[MAC_SIZE_BYTES];
|
||||
ni_job_cache job_cache[2];
|
||||
ni_prot_info prot;
|
||||
ni_stat_info stats;
|
||||
uint8 fcf_seq;
|
||||
ETH_DEV* eth;
|
||||
ETH_PACK rd_buf;
|
||||
ETH_PACK wr_buf;
|
||||
ETH_QUE readq;
|
||||
ETH_MAC macs[NI_FILTER_MAX]; /* List of all filter addresses */
|
||||
int filter_count; /* Number of filters available */
|
||||
ETH_PCALLBACK callback;
|
||||
} NI_STATE;
|
||||
|
||||
extern DEVICE ni_dev;
|
||||
|
||||
void ni_recv_callback(int status);
|
||||
t_stat ni_reset(DEVICE *dptr);
|
||||
t_stat ni_rcv_svc(UNIT *uptr);
|
||||
t_stat ni_sanity_svc(UNIT *uptr);
|
||||
t_stat ni_rq_svc(UNIT *uptr);
|
||||
t_stat ni_cio_svc(UNIT *uptr);
|
||||
t_stat ni_attach(UNIT *uptr, CONST char *cptr);
|
||||
t_stat ni_detach(UNIT *uptr);
|
||||
t_stat ni_setmac(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat ni_showmac(FILE* st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
t_stat ni_try_job(uint8 cid);
|
||||
t_stat ni_show_stats(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
t_stat ni_set_stats(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat ni_show_poll(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
t_stat ni_show_filters(FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
const char *ni_description(DEVICE *dptr);
|
||||
t_stat ni_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
void ni_cio_reset(uint8 cid);
|
||||
void ni_process_packet();
|
||||
void ni_int_ack(uint8 cid);
|
||||
void ni_sysgen(uint8 cid);
|
||||
void ni_express(uint8 cid);
|
||||
void ni_full(uint8 cid);
|
||||
|
||||
#endif /* _3B2_NI_H_ */
|
|
@ -93,14 +93,14 @@ extern UNIT cio_unit;
|
|||
#define PORTS_DIAG_CRC2 0x77a1ea56
|
||||
#define PORTS_DIAG_CRC3 0x84cf938b
|
||||
|
||||
#define LN(cid,port) ((PORTS_LINES * ((cid) - base_cid)) + (port))
|
||||
#define LCID(ln) (((ln) / PORTS_LINES) + base_cid)
|
||||
#define LN(cid,port) ((PORTS_LINES * ((cid) - ports_base_cid)) + (port))
|
||||
#define LCID(ln) (((ln) / PORTS_LINES) + ports_base_cid)
|
||||
#define LPORT(ln) ((ln) % PORTS_LINES)
|
||||
|
||||
int8 ports_base_cid; /* First cid in our contiguous block */
|
||||
uint8 ports_int_cid; /* Interrupting card ID */
|
||||
uint8 ports_int_subdev; /* Interrupting subdevice */
|
||||
t_bool ports_conf = FALSE; /* Have PORTS cards been configured? */
|
||||
int8 base_cid; /* First cid in our contiguous block */
|
||||
uint8 int_cid; /* Interrupting card ID */
|
||||
uint8 int_subdev; /* Interrupting subdevice */
|
||||
uint32 ports_crc; /* CRC32 of downloaded memory */
|
||||
|
||||
/* PORTS-specific state for each slot */
|
||||
|
@ -184,8 +184,8 @@ DEVICE ports_dev = {
|
|||
|
||||
static void cio_irq(uint8 cid, uint8 dev, int32 delay)
|
||||
{
|
||||
int_cid = cid;
|
||||
int_subdev = dev & 0xf;
|
||||
ports_int_cid = cid;
|
||||
ports_int_subdev = dev & 0xf;
|
||||
sim_activate(&ports_unit[2], delay);
|
||||
}
|
||||
|
||||
|
@ -268,13 +268,15 @@ static void ports_cmd(uint8 cid, cio_entry *rentry, uint8 *rapp_data)
|
|||
for (i = 0; i < rentry->byte_count; i++) {
|
||||
ports_crc = cio_crc32_shift(ports_crc, pread_b(rentry->address + i));
|
||||
}
|
||||
centry.address = rentry->address + rentry->byte_count;
|
||||
sim_debug(TRACE_DBG, &ports_dev,
|
||||
"[%08x] [ports_cmd] CIO Download Memory: bytecnt=%04x "
|
||||
"addr=%08x return_addr=%08x subdev=%02x (CRC=%08x)\n",
|
||||
R[NUM_PC],
|
||||
rentry->byte_count, rentry->address,
|
||||
centry.address, centry.subdevice, ports_crc);
|
||||
centry.address = rentry->address + rentry->byte_count;
|
||||
/* We intentionally do not set the subdevice in
|
||||
* the completion entry */
|
||||
cio_cexpress(cid, PPQESIZE, ¢ry, app_data);
|
||||
cio_irq(cid, rentry->subdevice, DELAY_DLM);
|
||||
break;
|
||||
|
@ -523,7 +525,7 @@ void ports_sysgen(uint8 cid)
|
|||
cio_cexpress(cid, PPQESIZE, &cqe, app_data);
|
||||
cio_cqueue(cid, CIO_STAT, PPQESIZE, &cqe, app_data);
|
||||
|
||||
int_cid = cid;
|
||||
ports_int_cid = cid;
|
||||
sim_activate(&ports_unit[2], DELAY_STD);
|
||||
}
|
||||
|
||||
|
@ -599,7 +601,7 @@ t_stat ports_reset(DEVICE *dptr)
|
|||
}
|
||||
|
||||
/* Remember the base card slot */
|
||||
base_cid = cid;
|
||||
ports_base_cid = cid;
|
||||
|
||||
end_slot = (cid + (ports_desc.lines/PORTS_LINES));
|
||||
|
||||
|
@ -669,20 +671,20 @@ t_stat ports_cio_svc(UNIT *uptr)
|
|||
{
|
||||
sim_debug(TRACE_DBG, &ports_dev,
|
||||
"[ports_cio_svc] IRQ for board %d device %d\n",
|
||||
int_cid, int_subdev);
|
||||
ports_int_cid, ports_int_subdev);
|
||||
|
||||
if (cio[int_cid].ivec > 0) {
|
||||
cio[int_cid].intr = TRUE;
|
||||
if (cio[ports_int_cid].ivec > 0) {
|
||||
cio[ports_int_cid].intr = TRUE;
|
||||
}
|
||||
|
||||
switch (cio[int_cid].op) {
|
||||
switch (cio[ports_int_cid].op) {
|
||||
case PPC_CONN:
|
||||
cio[int_cid].op = PPC_ASYNC;
|
||||
ports_ldsc[LN(int_cid, int_subdev)].rcve = 1;
|
||||
cio[ports_int_cid].op = PPC_ASYNC;
|
||||
ports_ldsc[LN(ports_int_cid, ports_int_subdev)].rcve = 1;
|
||||
sim_activate(&ports_unit[2], DELAY_ASYNC);
|
||||
break;
|
||||
case PPC_ASYNC:
|
||||
ports_update_conn(LN(int_cid, int_subdev));
|
||||
ports_update_conn(LN(ports_int_cid, ports_int_subdev));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "3b2_mmu.h"
|
||||
#include "3b2_ctc.h"
|
||||
#include "3b2_ports.h"
|
||||
#include "3b2_ni.h"
|
||||
#include "3b2_sysdev.h"
|
||||
|
||||
char sim_name[] = "AT&T 3B2 Model 400";
|
||||
|
@ -65,6 +66,7 @@ DEVICE *sim_devices[] = {
|
|||
&id_dev,
|
||||
&ports_dev,
|
||||
&ctc_dev,
|
||||
&ni_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -93,6 +95,7 @@ void full_reset()
|
|||
csr_reset(&csr_dev);
|
||||
ports_reset(&ports_dev);
|
||||
ctc_reset(&ctc_dev);
|
||||
ni_reset(&ni_dev);
|
||||
}
|
||||
|
||||
t_stat sim_load(FILE *fileref, CONST char *cptr, CONST char *fnam, int flag)
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../3B2/;../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18"
|
||||
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64"
|
||||
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18"
|
||||
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG"
|
||||
KeepComments="false"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="0"
|
||||
|
@ -125,8 +125,8 @@
|
|||
InlineFunctionExpansion="1"
|
||||
OmitFramePointers="true"
|
||||
WholeProgramOptimization="true"
|
||||
AdditionalIncludeDirectories="../3B2/;../../windows-build/libSDL/SDL2-2.0.5/include;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18"
|
||||
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64"
|
||||
AdditionalIncludeDirectories="../3B2/;./;../;../slirp;../slirp_glue;../slirp_glue/qemu;../slirp_glue/qemu/win32/include;../../windows-build/winpcap/Wpdpack/Include;../../windows-build/PCRE/include/;../../windows-build/pthreads;../../windows-build/libSDL/SDL2-2.0.8/include;../../windows-build/libpng-1.6.18"
|
||||
PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;SIM_NEED_GIT_COMMIT_ID;HAVE_PCREPOSIX_H;PCRE_STATIC;USE_INT64;USE_ADDR64;USE_SHARED;PTW32_STATIC_LIB;SIM_ASYNCH_IO;USE_READER_THREAD;HAVE_SLIRP_NETWORK;USE_SIMH_SLIRP_DEBUG"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
|
@ -224,6 +224,10 @@
|
|||
RelativePath="..\3B2\3b2_mmu.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_ni.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_ports.c"
|
||||
>
|
||||
|
@ -236,6 +240,29 @@
|
|||
RelativePath="..\3B2\3b2_sysdev.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\windows-build\pthreads\pthread.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
|
||||
CompileAs="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
WholeProgramOptimization="false"
|
||||
PreprocessorDefinitions="HAVE_CONFIG_H;PTW32_BUILD_INLINED;PTW32_STATIC_LIB;__CLEANUP_C;$(NOINHERIT)"
|
||||
CompileAs="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\scp.c"
|
||||
>
|
||||
|
@ -280,6 +307,170 @@
|
|||
RelativePath="..\sim_video.c"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="slirp"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\slirp\arp_table.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\bootp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\bootp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\cksum.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\debug.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\dnssearch.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp_glue\glib_qemu_stubs.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\if.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\if.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\ip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\ip_icmp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\ip_icmp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\ip_input.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\ip_output.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\libslirp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\main.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\mbuf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\mbuf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\misc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\misc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\sbuf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\sbuf.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp_glue\sim_slirp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\slirp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\slirp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\slirp_config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\socket.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\socket.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_input.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_output.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_subr.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_timer.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_timer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcp_var.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tcpip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tftp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\tftp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\udp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\slirp\udp.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
|
@ -321,6 +512,10 @@
|
|||
RelativePath="..\3B2\3b2_mmu.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_ni.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\3B2\3b2_ports.h"
|
||||
>
|
||||
|
|
6
makefile
6
makefile
|
@ -108,7 +108,7 @@ ifneq (,$(findstring besm6,$(MAKECMDGOALS)))
|
|||
BESM6_BUILD = true
|
||||
endif
|
||||
# building the pdp11, pdp10, or any vax simulator could use networking support
|
||||
ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring pdp10,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS))))
|
||||
ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring pdp10,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring 3b2,$(MAKECMDGOALS))$(findstring all,$(MAKECMDGOALS))))
|
||||
NETWORK_USEFUL = true
|
||||
ifneq (,$(findstring all,$(MAKECMDGOALS)))
|
||||
BUILD_MULTIPLE = s
|
||||
|
@ -1842,8 +1842,8 @@ ATT3B2 = ${ATT3B2D}/3b2_cpu.c ${ATT3B2D}/3b2_mmu.c \
|
|||
${ATT3B2D}/3b2_id.c ${ATT3B2D}/3b2_dmac.c \
|
||||
${ATT3B2D}/3b2_sys.c ${ATT3B2D}/3b2_io.c \
|
||||
${ATT3B2D}/3b2_ports.c ${ATT3B2D}/3b2_ctc.c \
|
||||
${ATT3B2D}/3b2_sysdev.c
|
||||
ATT3B2_OPT = -I ${ATT3B2D} -DUSE_INT64 -DUSE_ADDR64
|
||||
${ATT3B2D}/3b2_ni.c ${ATT3B2D}/3b2_sysdev.c
|
||||
ATT3B2_OPT = -DUSE_INT64 -DUSE_ADDR64 -I ${ATT3B2D} ${NETWORK_OPT}
|
||||
#
|
||||
# Build everything (not the unsupported/incomplete or experimental simulators)
|
||||
#
|
||||
|
|
Loading…
Add table
Reference in a new issue