mirror of
https://github.com/rcornwell/sims.git
synced 2026-02-26 16:53:58 +00:00
KA10: added CH11 interface for KS10.
This commit is contained in:
577
PDP10/ks10_ch11.c
Normal file
577
PDP10/ks10_ch11.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/* ks10_ch11.c: CH11 Chaosnet interface.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2022, Richard Cornwell, original by Lars Brinkhoff.
|
||||
|
||||
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 AUTHOR 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.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
*/
|
||||
|
||||
#include "kx10_defs.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#ifndef NUM_DEVS_CH11
|
||||
#define NUM_DEVS_CH11 0
|
||||
#endif
|
||||
|
||||
#if (NUM_DEVS_CH11 > 0)
|
||||
|
||||
/* CSR 076410 */
|
||||
|
||||
#define CSR_BSY 0000001 /* Xmit busy RO */
|
||||
#define CSR_LUP 0000002 /* Loop back R/W */
|
||||
#define CSR_SPY 0000004 /* Receive msgs from any destination R/W */
|
||||
#define CSR_RCL 0000010 /* Clear receiver WO */
|
||||
#define CSR_REN 0000020 /* Receiver int enable R/W */
|
||||
#define CSR_TEN 0000040 /* Transmitter int enable R/W */
|
||||
#define CSR_TAB 0000100 /* Transmit abort by conflict RO */
|
||||
#define CSR_TDN 0000200 /* Transmit Done */
|
||||
#define CSR_TCL 0000400 /* Clear transmitter WO */
|
||||
#define CSR_LOS 0017000 /* Lost count RO */
|
||||
#define CSR_RST 0020000 /* I/O Reset WO */
|
||||
#define CSR_ERR 0040000 /* CRC Error RO */
|
||||
#define CSR_RDN 0100000 /* Receive done */
|
||||
|
||||
|
||||
/* MY # 764142 Host number RO */
|
||||
|
||||
/* WBF 764142 Write bufffer WO */
|
||||
|
||||
/* RBF 764144 Read buffer RO */
|
||||
|
||||
/* RBC 764146 Receive bit counter RO */
|
||||
|
||||
/* XMT 764152 Read initiates transmission */
|
||||
|
||||
|
||||
#define CHUDP_HEADER 4
|
||||
#define IOLN_CH 020
|
||||
#define DBG_TRC 0x0001
|
||||
#define DBG_REG 0x0002
|
||||
#define DBG_PKT 0x0004
|
||||
#define DBG_DAT 0x0008
|
||||
#define DBG_INT 0x0010
|
||||
#define DBG_ERR 0x0020
|
||||
|
||||
int ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||
int ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||
uint16 ch11_checksum (const uint8 *p, int count);
|
||||
int ch11_test_int (struct pdp_dib *dibp);
|
||||
void ch11_validate (const uint8 *p, int count);
|
||||
t_stat ch11_transmit (struct pdp_dib *dibp);
|
||||
void ch11_receive (struct pdp_dib *dibp);
|
||||
void ch11_clear (struct pdp_dib *dibp);
|
||||
t_stat ch11_svc(UNIT *);
|
||||
t_stat ch11_reset (DEVICE *);
|
||||
t_stat ch11_attach (UNIT *, CONST char *);
|
||||
t_stat ch11_detach (UNIT *);
|
||||
t_stat ch11_show_peer (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
||||
t_stat ch11_set_peer (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
|
||||
t_stat ch11_show_node (FILE* st, UNIT* uptr, int32 val, CONST void* desc);
|
||||
t_stat ch11_set_node (UNIT* uptr, int32 val, CONST char* cptr, void* desc);
|
||||
t_stat ch11_help (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
t_stat ch11_help_attach (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
const char *ch11_description (DEVICE *);
|
||||
|
||||
static char peer[256];
|
||||
int address;
|
||||
static uint16 ch11_csr;
|
||||
static int rx_count;
|
||||
static int tx_count;
|
||||
static uint8 rx_buffer[512+100];
|
||||
static uint8 tx_buffer[512+100];
|
||||
|
||||
TMLN ch11_lines[1] = { {0} };
|
||||
TMXR ch11_tmxr = { 1, NULL, 0, ch11_lines};
|
||||
|
||||
UNIT ch11_unit[] = {
|
||||
{UDATA (&ch11_svc, UNIT_IDLE|UNIT_ATTABLE, 0) },
|
||||
};
|
||||
|
||||
REG ch11_reg[] = {
|
||||
{ ORDATA(CSR, ch11_csr, 16)},
|
||||
{ GRDATAD(RXCNT, rx_count, 16, 16, 0, "Receive word count"), REG_FIT|REG_RO},
|
||||
{ GRDATAD(TXCNT, tx_count, 16, 16, 0, "Transmit word count"), REG_FIT|REG_RO},
|
||||
{ BRDATAD(RXBUF, rx_buffer, 16, 8, sizeof rx_buffer, "Receive packet buffer"), REG_FIT},
|
||||
{ BRDATAD(TXBUF, tx_buffer, 16, 8, sizeof tx_buffer, "Transmit packet buffer"), REG_FIT},
|
||||
{ BRDATAD(PEER, peer, 16, 8, sizeof peer, "Network peer"), REG_HRO},
|
||||
{ GRDATAD(NODE, address, 16, 16, 0, "Node address"), REG_HRO},
|
||||
{ NULL } };
|
||||
|
||||
MTAB ch11_mod[] = {
|
||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "addr", "addr", &uba_set_addr, uba_show_addr,
|
||||
NULL, "Sets address of CH11" },
|
||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "vect", "vect", &uba_set_vect, uba_show_vect,
|
||||
NULL, "Sets vect of CH11" },
|
||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "br", "br", &uba_set_br, uba_show_br,
|
||||
NULL, "Sets br of CH11" },
|
||||
{MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "ctl", "ctl", &uba_set_ctl, uba_show_ctl,
|
||||
NULL, "Sets uba of CH11" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "PEER", "PEER",
|
||||
&ch11_set_peer, &ch11_show_peer, NULL, "Remote host name and port" },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "NODE", "NODE",
|
||||
&ch11_set_node, &ch11_show_node, NULL, "Chaosnet node address" },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
DIB ch11_dib = { 0764140, 017, 0270, 6, 3, &ch11_read, &ch11_write, NULL, 0, 0 };
|
||||
|
||||
DEBTAB ch11_debug[] = {
|
||||
{ "TRC", DBG_TRC, "Detailed trace" },
|
||||
{ "REG", DBG_REG, "Hardware registers" },
|
||||
{ "PKT", DBG_PKT, "Packets" },
|
||||
{ "DAT", DBG_DAT, "Packet data" },
|
||||
{ "INT", DBG_INT, "Interrupts" },
|
||||
{ "ERR", DBG_ERR, "Error conditions" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ch11_dev = {
|
||||
"CH", ch11_unit, ch11_reg, ch11_mod,
|
||||
1, 8, 16, 1, 8, 16,
|
||||
NULL, NULL, &ch11_reset,
|
||||
NULL, &ch11_attach, &ch11_detach,
|
||||
&ch11_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_MUX,
|
||||
0, ch11_debug, NULL, NULL, &ch11_help, &ch11_help_attach, NULL,
|
||||
&ch11_description
|
||||
};
|
||||
|
||||
int
|
||||
ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
{
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
uint16 temp;
|
||||
int ln;
|
||||
TMLN *lp;
|
||||
int i;
|
||||
|
||||
addr &= dibp->uba_mask;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "CH11 write %06o %06o %o\n",
|
||||
addr, data, access);
|
||||
|
||||
switch (addr & 016) {
|
||||
case 000: /* CSR */
|
||||
if (data & CSR_RCL) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Clear RX\n");
|
||||
ch11_csr &= ~CSR_RDN;
|
||||
rx_count = 0;
|
||||
ch11_lines[0].rcve = TRUE;
|
||||
}
|
||||
if (data & CSR_RST) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Reset\n");
|
||||
ch11_clear (dibp);
|
||||
}
|
||||
if (data & CSR_TCL) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Clear TX\n");
|
||||
tx_count = 0;
|
||||
ch11_csr |= CSR_TDN;
|
||||
}
|
||||
ch11_csr &= ~(CSR_REN|CSR_TEN);
|
||||
ch11_csr |= data & (CSR_REN|CSR_TEN);
|
||||
break;
|
||||
|
||||
case 002: /* Write buffer */
|
||||
ch11_csr &= ~CSR_TDN;
|
||||
if (tx_count < 512) {
|
||||
i = CHUDP_HEADER + tx_count;
|
||||
tx_buffer[i] = (data >> 8) & 0xff;
|
||||
tx_buffer[i+1] = data & 0xff;
|
||||
tx_count+=2;
|
||||
sim_debug (DBG_DAT, &ch11_dev, "Write buffer word %d:%02x %02x %06o %06o\n",
|
||||
tx_count, tx_buffer[i], tx_buffer[i+1], data, ch11_csr);
|
||||
} else {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Write buffer overflow\n");
|
||||
}
|
||||
break;
|
||||
case 004: /* Read buffer */
|
||||
case 006: /* Bit count */
|
||||
case 012: /* Start transmission */
|
||||
case 010: /* Empty */
|
||||
case 014: /* Empty */
|
||||
case 016: /* Empty */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
{
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
uint16 temp;
|
||||
int ln;
|
||||
TMLN *lp;
|
||||
int i;
|
||||
|
||||
addr &= dibp->uba_mask;
|
||||
*data = 0;
|
||||
switch (addr & 016) {
|
||||
case 000: /* CSR */
|
||||
*data = ch11_csr;
|
||||
break;
|
||||
|
||||
case 002: /* Host number */
|
||||
*data = address;
|
||||
break;
|
||||
|
||||
case 004: /* Read buffer */
|
||||
if (rx_count == 0) {
|
||||
*data = 0;
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Read empty buffer\n");
|
||||
} else {
|
||||
i = 512-rx_count;
|
||||
ch11_csr &= ~CSR_RDN;
|
||||
*data = ((uint64)(rx_buffer[i]) & 0xff) << 8;
|
||||
*data |= ((uint64)(rx_buffer[i+1]) & 0xff);
|
||||
rx_count-=2;
|
||||
sim_debug (DBG_DAT, &ch11_dev, "Read buffer word %d:%02x %02x %06o %06o\n",
|
||||
rx_count, rx_buffer[i], rx_buffer[i+1], *data, ch11_csr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 006: /* Bit count */
|
||||
*data = ((512 - rx_count) - 1) & 07777;
|
||||
break;
|
||||
case 012: /* Start transmission */
|
||||
sim_debug (DBG_REG, &ch11_dev, "XMIT TX\n");
|
||||
ch11_transmit(dibp);
|
||||
break;
|
||||
|
||||
case 010: /* Empty */
|
||||
case 014: /* Empty */
|
||||
case 016: /* Empty */
|
||||
break;
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "CH11 read %06o %06o %o\n",
|
||||
addr, *data, access);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16
|
||||
ch11_checksum (const uint8 *p, int count)
|
||||
{
|
||||
int32 sum = 0;
|
||||
|
||||
while (count > 1) {
|
||||
sum += (p[0]<<8) | p[1];
|
||||
p += 2;
|
||||
count -= 2;
|
||||
}
|
||||
|
||||
if ( count > 0)
|
||||
sum += p[0];
|
||||
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
|
||||
return (~sum) & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ch11_test_int (struct pdp_dib *dibp)
|
||||
{
|
||||
if ((ch11_csr & (CSR_RDN|CSR_REN)) == (CSR_RDN|CSR_REN) ||
|
||||
(ch11_csr & (CSR_TDN|CSR_TEN)) == (CSR_TDN|CSR_TEN)) {
|
||||
sim_debug (DBG_INT, &ch11_dev, "%s %s Interrupt\n",
|
||||
ch11_csr & CSR_RDN ? "RX" : "",
|
||||
ch11_csr & CSR_TDN ? "TX" : "");
|
||||
uba_set_irq(dibp);
|
||||
} else {
|
||||
/* Nothing found, so clear any flags */
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "Clr irq\n");
|
||||
uba_clr_irq(dibp);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ch11_validate (const uint8 *p, int count)
|
||||
{
|
||||
uint16 chksum;
|
||||
int size;
|
||||
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Packet opcode: %02x\n", p[0]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "MBZ: %02x\n", p[1]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Forwarding count: %02x\n", p[2] >> 4);
|
||||
size = ((p[2] & 0xF) << 8) + p[3];
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Packet size: %03x\n", size);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Destination address: %o\n", (p[4] << 8) + p[5]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Destination index: %02x\n", (p[6] << 8) + p[7]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Source address: %o\n", (p[8] << 8) + p[9]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Source index: %02x\n", (p[10] << 8) + p[11]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Packet number: %02x\n", (p[12] << 8) + p[13]);
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Acknowledgement: %02x\n", (p[14] << 8) + p[15]);
|
||||
|
||||
if (p[1] != 0)
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Bad packet\n");
|
||||
|
||||
chksum = ch11_checksum (p, count);
|
||||
if (chksum != 0) {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Checksum error: %04x\n", chksum);
|
||||
ch11_csr |= CSR_ERR;
|
||||
} else
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Checksum: %05o\n", chksum);
|
||||
}
|
||||
|
||||
t_stat
|
||||
ch11_transmit (struct pdp_dib *dibp)
|
||||
{
|
||||
size_t len;
|
||||
t_stat r;
|
||||
int i = CHUDP_HEADER + tx_count;
|
||||
uint16 chk;
|
||||
|
||||
if (tx_count > (512 - CHUDP_HEADER)) {
|
||||
sim_debug (DBG_PKT, &ch11_dev, "Pack size failed, %d bytes.\n", (int)tx_count);
|
||||
ch11_csr |= CSR_ERR;
|
||||
return SCPE_INCOMP;
|
||||
}
|
||||
tx_buffer[i] = tx_buffer[8+CHUDP_HEADER];
|
||||
tx_buffer[i+1] = tx_buffer[9+CHUDP_HEADER];
|
||||
tx_count += 2;
|
||||
chk = ch11_checksum(tx_buffer + CHUDP_HEADER, tx_count);
|
||||
tx_buffer[i+2] = (chk >> 8) & 0xff;
|
||||
tx_buffer[i+3] = chk & 0xff;
|
||||
tx_count += 2;
|
||||
|
||||
tmxr_poll_tx (&ch11_tmxr);
|
||||
len = CHUDP_HEADER + (size_t)tx_count;
|
||||
r = tmxr_put_packet_ln (&ch11_lines[0], (const uint8 *)&tx_buffer, len);
|
||||
if (r == SCPE_OK) {
|
||||
sim_debug (DBG_PKT, &ch11_dev, "Sent UDP packet, %d bytes.\n", (int)len);
|
||||
tmxr_poll_tx (&ch11_tmxr);
|
||||
} else {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Sending UDP failed: %d.\n", r);
|
||||
ch11_csr |= CSR_TAB;
|
||||
}
|
||||
tx_count = 0;
|
||||
ch11_test_int (dibp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ch11_receive (struct pdp_dib *dibp)
|
||||
{
|
||||
size_t count;
|
||||
const uint8 *p;
|
||||
uint16 dest;
|
||||
|
||||
tmxr_poll_rx (&ch11_tmxr);
|
||||
if (tmxr_get_packet_ln (&ch11_lines[0], &p, &count) != SCPE_OK) {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "TMXR error receiving packet\n");
|
||||
return;
|
||||
}
|
||||
if (p == NULL)
|
||||
return;
|
||||
dest = ((p[4+CHUDP_HEADER] & 0xff) << 8) + (p[5+CHUDP_HEADER] & 0xff);
|
||||
|
||||
sim_debug (DBG_PKT, &ch11_dev, "Received UDP packet, %d bytes for: %o\n", (int)count, dest);
|
||||
/* Check if packet for us. */
|
||||
if (dest != address && dest != 0 && (ch11_csr & CSR_SPY) == 0)
|
||||
return;
|
||||
|
||||
if ((CSR_RDN & ch11_csr) == 0) {
|
||||
count = (count + 1) & 0776;
|
||||
memcpy (rx_buffer + (512 - count), p, count);
|
||||
rx_count = count;
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Rx count, %d\n", rx_count);
|
||||
ch11_validate (p + CHUDP_HEADER, count - CHUDP_HEADER);
|
||||
ch11_csr |= CSR_RDN;
|
||||
ch11_lines[0].rcve = FALSE;
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Rx off\n");
|
||||
ch11_test_int (dibp);
|
||||
} else {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Lost packet\n");
|
||||
if ((ch11_csr & CSR_LOS) != CSR_LOS)
|
||||
ch11_csr = (ch11_csr & ~CSR_LOS) | (CSR_LOS & (ch11_csr + 01000));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ch11_clear (struct pdp_dib *dibp)
|
||||
{
|
||||
ch11_csr = CSR_TDN;
|
||||
rx_count = 0;
|
||||
tx_count = 0;
|
||||
|
||||
tx_buffer[0] = 1; /* CHUDP header */
|
||||
tx_buffer[1] = 1;
|
||||
tx_buffer[2] = 0;
|
||||
tx_buffer[3] = 0;
|
||||
ch11_lines[0].rcve = TRUE;
|
||||
|
||||
ch11_test_int (dibp);
|
||||
}
|
||||
|
||||
t_stat
|
||||
ch11_svc(UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
|
||||
sim_clock_coschedule (uptr, 1000);
|
||||
(void)tmxr_poll_conn (&ch11_tmxr);
|
||||
if (ch11_lines[0].conn) {
|
||||
ch11_receive (dibp);
|
||||
}
|
||||
if (tx_count == 0)
|
||||
ch11_csr |= CSR_TDN;
|
||||
ch11_test_int (dibp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
char linkinfo[256];
|
||||
t_stat r;
|
||||
|
||||
ch11_dev.dctrl |= 0xF77F0000;
|
||||
if (address == -1)
|
||||
return sim_messagef (SCPE_2FARG, "Must set Chaosnet NODE address first \"SET CH NODE=val\"\n");
|
||||
if (peer[0] == '\0')
|
||||
return sim_messagef (SCPE_2FARG, "Must set Chaosnet PEER \"SET CH PEER=host:port\"\n");
|
||||
|
||||
snprintf (linkinfo, sizeof(linkinfo), "Buffer=%d,UDP,%s,PACKET,Connect=%.*s,Line=0",
|
||||
(int)sizeof tx_buffer, cptr, (int)(sizeof(linkinfo) - (45 + strlen(cptr))), peer);
|
||||
r = tmxr_attach (&ch11_tmxr, uptr, linkinfo);
|
||||
if (r != SCPE_OK) {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "TMXR error opening master\n");
|
||||
return sim_messagef (r, "Error Opening: %s\n", peer);
|
||||
}
|
||||
|
||||
uptr->filename = (char *)realloc (uptr->filename, 1 + strlen (cptr));
|
||||
strcpy (uptr->filename, cptr);
|
||||
sim_activate (uptr, 1000);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_detach (UNIT *uptr)
|
||||
{
|
||||
sim_cancel (uptr);
|
||||
tmxr_detach (&ch11_tmxr, uptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_reset (DEVICE *dptr)
|
||||
{
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
|
||||
ch11_clear (dibp);
|
||||
if (ch11_unit[0].flags & UNIT_ATT)
|
||||
sim_activate (&ch11_unit[0], 100);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_show_peer (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||
{
|
||||
fprintf (st, "peer=%s", peer[0] ? peer : "unspecified");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_set_peer (UNIT* uptr, int32 val, CONST char* cptr, void* desc)
|
||||
{
|
||||
char host[256], port[256];
|
||||
|
||||
if ((cptr == NULL) || (*cptr == 0))
|
||||
return SCPE_ARG;
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
return SCPE_ALATT;
|
||||
if (sim_parse_addr (cptr, host, sizeof host, NULL, port, sizeof port, NULL, NULL))
|
||||
return SCPE_ARG;
|
||||
if (host[0] == '\0')
|
||||
return SCPE_ARG;
|
||||
|
||||
strncpy (peer, cptr, sizeof(peer) - 1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_show_node (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
|
||||
{
|
||||
if (address == -1)
|
||||
fprintf (st, "node=unspecified");
|
||||
else
|
||||
fprintf (st, "node=%o", address);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_set_node (UNIT* uptr, int32 val, CONST char* cptr, void* desc)
|
||||
{
|
||||
t_stat r;
|
||||
int x;
|
||||
|
||||
if ((cptr == NULL) || (*cptr == 0))
|
||||
return SCPE_ARG;
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
return SCPE_ALATT;
|
||||
|
||||
x = (int)get_uint (cptr, 8, 0177777, &r);
|
||||
if (r != SCPE_OK)
|
||||
return SCPE_ARG;
|
||||
|
||||
address = x;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
const char *ch11_description (DEVICE *dptr)
|
||||
{
|
||||
return "CH11 Chaosnet interface";
|
||||
}
|
||||
|
||||
t_stat ch11_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
fprintf (st, "CH11 Chaosnet interface\n\n");
|
||||
fprintf (st, "It's a network interface for MIT's Chaosnet. Options allow\n");
|
||||
fprintf (st, "control of the node address and network peer. The node address must\n");
|
||||
fprintf (st, "be a 16-bit octal number.\n");
|
||||
fprint_set_help (st, dptr);
|
||||
fprintf (st, "\nConfigured options and controller state can be displayed with:\n");
|
||||
fprint_show_help (st, dptr);
|
||||
fprintf (st, "\nThe CH11 simulation will encapsulate Chaosnet packets in UDP or TCP.\n");
|
||||
fprintf (st, "To access the network, the simulated Chaosnet interface must be attached\n");
|
||||
fprintf (st, "to a network peer.\n\n");
|
||||
ch11_help_attach (st, dptr, uptr, flag, cptr);
|
||||
fprintf (st, "Software that runs on SIMH that supports this device include:\n");
|
||||
fprintf (st, " - ITS, the PDP-10 Incompatible Timesharing System\n");
|
||||
fprintf (st, "Outside SIMH, there's KLH10 and Lisp machine simulators. Various\n");
|
||||
fprintf (st, "encapsulating transport mechanisms exist: UDP, IP, Ethernet.\n\n");
|
||||
fprintf (st, "Documentation:\n");
|
||||
fprintf (st, "https://lm-3.github.io/amber.html#Hardware-Programming-Documentation\n\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ch11_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||||
{
|
||||
fprintf (st, "To configure CH11, first set the local Chaosnet node address, and\n");
|
||||
fprintf (st, "the peer:\n\n");
|
||||
fprintf (st, " sim> SET CH NODE=<octal address>\n");
|
||||
fprintf (st, " sim> SET CH PEER=<remote host>:<remote port>\n\n");
|
||||
fprintf (st, "Then, attach a local port. By default UDP is used:\n\n");
|
||||
fprintf (st, " sim> ATTACH CH <local port>\n\n");
|
||||
fprintf (st, "If TCP is desired, add \"TCP\":\n\n");
|
||||
fprintf (st, " sim> ATTACH CH <local port>,TCP\n\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -740,15 +740,15 @@ extern void ka10_lights_clear_aux (int);
|
||||
#define NUM_DEVS_TTY 1
|
||||
#define NUM_LINES_TTY 64
|
||||
#define NUM_DEVS_NIA 1
|
||||
#define NUM_DEVS_DN 0
|
||||
#define NUM_DEVS_DN 1
|
||||
#elif KS
|
||||
#define NUM_DEVS_LP20 1
|
||||
#define NUM_DEVS_DZ 4
|
||||
#define NUM_DEVS_TCU 1
|
||||
#define NUM_DEVS_DUP 0
|
||||
#if KS_ITS
|
||||
#define NUM_DEVS_IMP 0 /* KS_ITS */
|
||||
#define NUM_DEVS_CH11 0 /* KS_ITS */
|
||||
#define NUM_DEVS_IMP 0 /* KS_ITS */
|
||||
#define NUM_DEVS_CH11 KS_ITS
|
||||
#endif
|
||||
#endif
|
||||
#if KA | KI
|
||||
|
||||
8
makefile
8
makefile
@@ -123,8 +123,8 @@ endif
|
||||
ifneq (,$(or $(findstring pdp6,${MAKECMDGOALS}),$(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS})))
|
||||
VIDEO_USEFUL = true
|
||||
endif
|
||||
# building the KA10, KI10 or KL10 networking can be used.
|
||||
ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS},$(findstring pdp10-kl,${MAKECMDGOALS}))))
|
||||
# building the KA10, KI10, KL10, KS10 networking can be used.
|
||||
ifneq (,$(or $(findstring pdp10-ka,${MAKECMDGOALS}),$(findstring pdp10-ki,${MAKECMDGOALS},$(findstring pdp10-kl,${MAKECMDGOALS},$(findstring pdp10-ks,{MAKECMDGOALS})))))
|
||||
NETWORK_USEFUL = true
|
||||
endif
|
||||
# building the SEL32 networking can be ussed
|
||||
@@ -2153,14 +2153,14 @@ KL10 = ${KL10D}/kx10_cpu.c ${KL10D}/kx10_sys.c ${KL10D}/kx10_df.c \
|
||||
${KL10D}/kx10_rp.c ${KL10D}/kx10_tu.c ${KL10D}/kx10_rs.c \
|
||||
${KL10D}/kx10_imp.c ${KL10D}/kl10_fe.c ${KL10D}/ka10_pd.c \
|
||||
${KL10D}/ka10_ch10.c ${KL10D}/kx10_lp.c ${KL10D}/kl10_nia.c \
|
||||
${KL10D}/kx10_disk.c ${KL10D}/kl10_dn.c
|
||||
${KL10D}/kx10_disk.c
|
||||
KL10_OPT = -DKL=1 -DUSE_INT64 -I $(KL10D) ${NETWORK_OPT}
|
||||
|
||||
KS10D = ${SIMHD}/PDP10
|
||||
KS10 = ${KS10D}/kx10_cpu.c ${KS10D}/kx10_sys.c ${KS10D}/kx10_disk.c \
|
||||
${KS10D}/ks10_cty.c ${KS10D}/ks10_uba.c ${KS10D}/kx10_rh.c \
|
||||
${KS10D}/kx10_rp.c ${KS10D}/kx10_tu.c ${KS10D}/ks10_dz.c \
|
||||
${KS10D}/ks10_tcu.c ${KS10D}/ks10_lp.c
|
||||
${KS10D}/ks10_tcu.c ${KS10D}/ks10_lp.c ${KS10D}/ks10_ch11.c
|
||||
KS10_OPT = -DKS=1 -DUSE_INT64 -I $(KS10D) ${NETWORK_OPT}
|
||||
|
||||
ATT3B2D = ${SIMHD}/3B2
|
||||
|
||||
Reference in New Issue
Block a user