Merge of working DMC-11 device from Rob Jarratt.

pdp11_dmc.c
	- Fixed DMA bug which wrote data into the wrong simulated memory address.
	- Fixed incoming IP address checking.

pdp11_io_lib.c
	- Added the DMC device to the autoconfigure device table

vax780_defs.h
	- Added comment for DMC11
This commit is contained in:
Mark Pizzolato 2012-11-06 17:00:54 -08:00
parent c9b31427b4
commit d51df0eba5
3 changed files with 1528 additions and 1501 deletions

View file

@ -72,7 +72,7 @@ The other test was to configure DECnet on VMS 4.6 and do SET HOST.
// TODO: Show active connections like DZ does, for multipoint.
// TODO: Test MOP.
// TODO: Implement actual DDCMP protocol and run over UDP.
// TODO: Allow NCP SHOW COUNTERS to work (think this is the base address thing)
// TODO: Allow NCP SHOW COUNTERS to work (think this is the base address thing). Since fixing how I get the addresses this should work now.
#include <time.h>
#include <ctype.h>
@ -236,7 +236,7 @@ int dmc_buffer_queue_full(BUFFER_QUEUE *q);
void dmc_buffer_queue_get_stats(BUFFER_QUEUE *q, int *available, int *contains_data, int *transfer_in_progress);
void dmc_start_transfer_transmit_buffer(CTLR *controller);
void dmc_error_and_close_receive(CTLR *controller, char *format);
void dmc_close_receive(CTLR *controller, char *reason);
void dmc_close_receive(CTLR *controller, char *reason, char *from);
void dmc_close_transmit(CTLR *controller, char *reason);
int dmc_get_socket(CTLR *controller, int forRead);
int dmc_get_receive_socket(CTLR *controller, int forRead);
@ -396,12 +396,21 @@ DEVICE dmp_dev[] =
&dmp_dib[0], DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_NET | DEV_DEBUG, 0, dmc_debug }
};
LINE dmc_line[DMC_NUMDEVICE];
LINE dmc_line[DMC_NUMDEVICE] =
{
{ 0, INVALID_SOCKET },
{ 0, INVALID_SOCKET },
{ 0, INVALID_SOCKET },
{ 0, INVALID_SOCKET }
};
BUFFER_QUEUE dmc_receive_queues[DMC_NUMDEVICE];
BUFFER_QUEUE dmc_transmit_queues[DMC_NUMDEVICE];
LINE dmp_line[DMP_NUMDEVICE];
LINE dmp_line[DMP_NUMDEVICE] =
{
{ 0, INVALID_SOCKET }
};
BUFFER_QUEUE dmp_receive_queues[DMP_NUMDEVICE];
BUFFER_QUEUE dmp_transmit_queues[DMP_NUMDEVICE];
@ -415,6 +424,8 @@ CTLR dmc_ctrls[] =
{ &dmp_csrs[0], &dmp_dev[0], Initialised, Idle, 0, 0, &dmp_line[0], &dmp_receive_queues[0], &dmp_transmit_queues[0], INVALID_SOCKET, -1, 30, DMP }
};
extern int32 tmxr_poll; /* calibrated delay */
UNIT_STATS *dmc_get_unit_stats(UNIT *uptr)
{
UNIT_STATS *ans = NULL;
@ -741,11 +752,11 @@ t_stat dmc_setlinemode (UNIT* uptr, int32 val, char* cptr, void* desc)
if (!cptr) return SCPE_IERR;
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
if (strcmp(cptr, "PRIMARY") == 0)
if (MATCH_CMD(cptr, "PRIMARY") == 0)
{
controller->line->isPrimary = 1;
}
else if (strcmp(cptr, "SECONDARY") == 0)
else if (MATCH_CMD(cptr, "SECONDARY") == 0)
{
controller->line->isPrimary = 0;
}
@ -1162,7 +1173,7 @@ void dmc_process_master_clear(CTLR *controller)
}
dmc_buffer_queue_init(controller, controller->receive_queue, "receive");
dmc_buffer_queue_init(controller, controller->transmit_queue, "transmit");
//dmc_close_receive(controller, "master clear");
//dmc_close_receive(controller, "master clear", NULL);
//dmc_close_transmit(controller, "master clear");
controller->transfer_state = Idle;
@ -1230,10 +1241,13 @@ void dmc_start_control_output_transfer(CTLR *controller)
t_stat dmc_svc(UNIT* uptr)
{
CTLR *controller;
int32 poll;
TIMER *poll_timer = &dmc_get_unit_stats(uptr)->poll_timer;
TIMER *between_polls_timer = &dmc_get_unit_stats(uptr)->between_polls_timer;
poll = clk_cosched (tmxr_poll);
if (dmc_timer_started(between_polls_timer))
{
dmc_timer_stop(between_polls_timer);
@ -1265,7 +1279,7 @@ t_stat dmc_svc(UNIT* uptr)
if (controller->transfer_state == Idle) dmc_start_transfer_transmit_buffer(controller);
/* resubmit service timer */
sim_activate(controller->device->units, controller->svc_poll_interval);
sim_activate(controller->device->units, poll/*controller->svc_poll_interval*/);
dmc_timer_stop(poll_timer);
if (dmc_timer_started(between_polls_timer))
@ -1364,11 +1378,12 @@ void dmc_buffer_trace_line(int tracelevel, CTLR *controller, uint8 *buf, int len
sim_debug(tracelevel, controller->device, "%s %s %s\n", prefix, hex, ascii);
}
void dmc_buffer_trace(CTLR *controller, uint8 *buf, int length, char *prefix)
void dmc_buffer_trace(CTLR *controller, uint8 *buf, int length, char *prefix, uint32 address)
{
int i;
if (length >= 0 && controller->device->dctrl & DBG_DAT)
{
sim_debug(DBG_DAT, controller->device, "%s Buffer address 0x%08x (%d bytes)\n", prefix, address, length);
for(i = 0; i < length / TRACE_BYTES_PER_LINE; i++)
{
dmc_buffer_trace_line(DBG_DAT, controller, buf + i*TRACE_BYTES_PER_LINE, TRACE_BYTES_PER_LINE, prefix);
@ -1435,7 +1450,7 @@ void dmc_buffer_queue_add(BUFFER_QUEUE *q, uint32 address, uint16 count)
}
else
{
sim_debug(DBG_WRN, q->controller->device, "Failed to queue %s buffer, queue full\n", q->name);
sim_debug(DBG_WRN, q->controller->device, "Failed to queue %s buffer address=0x%08x, queue full\n", q->name, address);
// TODO: Report error here.
}
}
@ -1539,12 +1554,12 @@ t_stat dmc_open_master_socket(CTLR *controller, char *port)
controller->master_socket = sim_master_sock(port, &ans);
if (controller->master_socket == INVALID_SOCKET)
{
sim_debug(DBG_WRN, controller->device, "Failed to open master socket\n");
sim_debug(DBG_WRN, controller->device, "Failed to open master socket on port %s\n", port);
ans = SCPE_OPENERR;
}
else
{
printf ("DMC-11 %s listening on port %s (socket %d)\n", controller->device->name, port, controller->master_socket);
printf ("DMC-11 %s listening on port %s\n", controller->device->name, port);
}
}
@ -1561,7 +1576,7 @@ t_stat dmc_close_master_socket(CTLR *controller)
// Gets the bidirectional socket and handles arbitration of determining which socket to use.
int dmc_get_socket(CTLR *controller, int forRead)
{
static int lastans = 0;
// static int lastans = 0;
int ans = 0;
if (controller->line->isPrimary)
{
@ -1572,12 +1587,12 @@ int dmc_get_socket(CTLR *controller, int forRead)
ans = dmc_get_receive_socket(controller, forRead); // TODO: After change to single socket, loopback may not work.
}
if (lastans != ans)
{
sim_debug(DBG_SOK, controller->device, "Get Socket forread=%d, changed to %d\n", forRead, ans);
}
lastans = ans;
// if (lastans != ans)
// {
//sim_debug(DBG_SOK, controller->device, "Get Socket forread=%d, changed to %d\n", forRead, ans);
// }
// lastans = ans;
//
return ans;
}
@ -1591,10 +1606,13 @@ int dmc_get_receive_socket(CTLR *controller, int forRead)
controller->line->socket = sim_accept_conn (controller->master_socket, &ipaddr); /* poll connect */
if (controller->line->socket != INVALID_SOCKET)
{
if (strcmp(ipaddr, controller->line->transmit_host))
char host[sizeof(controller->line->transmit_host)];
sim_parse_addr (controller->line->transmit_host, host, sizeof(host), NULL, NULL, 0, NULL);
if (strcmp(ipaddr, host))
{
sim_debug(DBG_WRN, controller->device, "Received connection from unexpected source IP %s. Closing the connection.\n", ipaddr);
dmc_close_receive(controller, "Unathorized connection");
dmc_close_receive(controller, "Unathorized connection", ipaddr);
}
else
{
@ -1615,7 +1633,7 @@ int dmc_get_receive_socket(CTLR *controller, int forRead)
}
else if (readable == -1) /* Failed to open */
{
dmc_close_receive(controller, "failed to connect");
dmc_close_receive(controller, "failed to connect", NULL);
ans = 0;
}
else /* connected */
@ -1641,7 +1659,7 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
dmc_close_transmit(controller, "loopback change");
}
if (controller->line->socket == INVALID_SOCKET && (time(NULL) - controller->line->last_connect_attempt) > controller->connect_poll_interval)
if (controller->line->socket == INVALID_SOCKET && ((int32)(time(NULL) - controller->line->last_connect_attempt)) > controller->connect_poll_interval)
{
char hostport[CBUFSIZE];
@ -1653,10 +1671,11 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
else
sprintf(hostport, "%s", controller->line->transmit_host);
sim_debug(DBG_SOK, controller->device, "Trying to open transmit socket to address:port %s\n", hostport);
controller->line->last_connect_attempt = time(NULL);
controller->line->socket = sim_connect_sock(hostport, NULL, NULL);
if (controller->line->socket != INVALID_SOCKET)
{
sim_debug(DBG_SOK, controller->device, "Opened transmit socket to port %d, socket %d\n", hostport, controller->line->socket);
sim_debug(DBG_SOK, controller->device, "Opened transmit socket to port %s\n", hostport);
controller->line->transmit_writeable = FALSE;
}
}
@ -1688,9 +1707,9 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
return ans;
}
void dmc_close_receive(CTLR *controller, char *reason)
void dmc_close_receive(CTLR *controller, char *reason, char *from)
{
sim_debug(DBG_SOK, controller->device, "Closing receive socket on port %d, socket %d, reason: %s\n", controller->line->receive_port, controller->line->socket, reason);
sim_debug(DBG_SOK, controller->device, "Closing receive socket on port %s, reason: %s%s%s\n", controller->line->receive_port, reason, from ? " from " : "", from ? from : "");
sim_close_sock(controller->line->socket, FALSE);
controller->line->socket = INVALID_SOCKET;
@ -1712,7 +1731,7 @@ void dmc_error_and_close_receive(CTLR *controller, char *format)
}
else
{
dmc_close_receive(controller, errmsg);
dmc_close_receive(controller, errmsg, NULL);
}
}
@ -1733,7 +1752,7 @@ void dmc_close_transmit(CTLR *controller, char *reason)
int dmc_buffer_fill_receive_buffers(CTLR *controller)
{
int ans = FALSE;
int socket;
SOCKET socket;
if (controller->state == Initialised)
{
/* accept any inbound connection but just throw away any data */
@ -1745,8 +1764,7 @@ int dmc_buffer_fill_receive_buffers(CTLR *controller)
bytes_read = sim_read_sock(socket, buffer, sizeof(buffer));
if (bytes_read < 0)
{
printf("Socket error was when trying to fill receive buffers when controller initialised.\n");
//dmc_error_and_close_receive(controller, "read error, code=%d");
dmc_error_and_close_receive(controller, "read error, code=%d");
}
else if (bytes_read > 0)
{
@ -1811,7 +1829,7 @@ printf("Socket error was when trying to fill receive buffers when controller ini
int bytes_to_read = dmc_line_speed_calculate_byte_length(controller->line->bytes_received_in_last_second, buffer->actual_block_len - buffer->actual_bytes_transferred, controller->line->speed);
if (bytes_to_read > 0)
{
bytes_read = sim_read_sock(controller->line->socket, buffer->transfer_buffer + buffer->actual_bytes_transferred, bytes_to_read);
bytes_read = sim_read_sock(controller->line->socket, (char *)(buffer->transfer_buffer + buffer->actual_bytes_transferred), bytes_to_read);
}
}
@ -1822,7 +1840,7 @@ printf("Socket error was when trying to fill receive buffers when controller ini
if (buffer->actual_bytes_transferred >= buffer->actual_block_len)
{
dmc_buffer_trace(controller, buffer->transfer_buffer, buffer->actual_bytes_transferred, "REC ");
dmc_buffer_trace(controller, buffer->transfer_buffer, buffer->actual_bytes_transferred, "REC ", buffer->address);
controller->buffers_received_from_net++;
buffer->state = ContainsData;
if (!lost_data)
@ -1878,7 +1896,6 @@ printf("Socket error was when trying to fill receive buffers when trying to read
int dmc_buffer_send_transmit_buffers(CTLR *controller)
{
int ans = FALSE;
int socket;
/* when transmit buffer is queued it is marked as available, not as ContainsData */
BUFFER *buffer = dmc_buffer_queue_find_first_available(controller->transmit_queue);
while (buffer != NULL)
@ -1886,34 +1903,44 @@ int dmc_buffer_send_transmit_buffers(CTLR *controller)
if (dmc_get_socket(controller, FALSE)) // TODO: , buffer->is_loopback);
{
int bytes = 0;
int bytes_to_send;
uint16 block_len;
int total_buffer_len = (buffer->count > 0) ? buffer->count + sizeof(block_len) : 0;
socket = controller->line->socket;
/* only send the buffer if it actually has some data, sometimes get zero length buffers - don't send these */
if (total_buffer_len > 0)
{
if (buffer->actual_bytes_transferred <= 0)
if (buffer->transfer_buffer == NULL)
{
int n;
/* construct buffer and include block length bytes */
buffer->transfer_buffer = (uint8 *)malloc(total_buffer_len);
block_len = htons(buffer->count);
memcpy(buffer->transfer_buffer, (char *)&block_len, sizeof(block_len));
Map_ReadB(buffer->address, buffer->count, buffer->transfer_buffer + sizeof(block_len));
n = Map_ReadB(buffer->address, buffer->count, buffer->transfer_buffer + sizeof(block_len));
if (n > 0)
{
sim_debug(DBG_WRN, controller->device, "DMA error\n");
}
}
bytes = sim_write_sock (controller->line->socket, buffer->transfer_buffer + buffer->actual_bytes_transferred, buffer->count + sizeof(block_len) - buffer->actual_bytes_transferred);
bytes_to_send = dmc_line_speed_calculate_byte_length(controller->line->bytes_sent_in_last_second, buffer->count + sizeof(block_len) - buffer->actual_bytes_transferred, controller->line->speed);
if (bytes_to_send > 0)
{
bytes = sim_write_sock (controller->line->socket, (char *)(buffer->transfer_buffer + buffer->actual_bytes_transferred), bytes_to_send);
if (bytes >= 0)
{
buffer->actual_bytes_transferred += bytes;
controller->line->bytes_sent_in_last_second += bytes;
}
if (buffer->actual_bytes_transferred >= total_buffer_len || bytes < 0)
{
dmc_buffer_trace(controller, buffer->transfer_buffer+sizeof(block_len), buffer->count, "TRAN");
dmc_buffer_trace(controller, buffer->transfer_buffer+sizeof(block_len), buffer->count, "TRAN", buffer->address);
free(buffer->transfer_buffer);
}
}
}
if (buffer->actual_bytes_transferred >= total_buffer_len)
{
@ -2009,7 +2036,7 @@ void dmc_process_input_transfer_completion(CTLR *controller)
if (controller->transfer_type == TYPE_BASEI)
{
//int i;
uint32 baseaddr = sel6 >> 14 | sel4;
uint32 baseaddr = ((sel6 >> 14) << 16) | sel4;
uint16 count = sel6 & 0x3FFF;
sim_debug(DBG_INF, controller->device, "Completing Base In input transfer, base address=0x%08x count=%d\n", baseaddr, count);
//for (i = 0; i < count; i++)
@ -2020,7 +2047,7 @@ void dmc_process_input_transfer_completion(CTLR *controller)
}
else if (controller->transfer_type == TYPE_BACCI)
{
uint32 addr = sel6 >> 14 | sel4;
uint32 addr = ((sel6 >> 14) << 16) | sel4;
uint16 count = sel6 & 0x3FFF;
if (controller->transfer_in_io != dmc_is_in_io_set(controller))
{

View file

@ -352,7 +352,7 @@ AUTO_CON auto_tab[] = {
{ { NULL }, 1, 2, 8, 8 }, /* DU11 */
{ { NULL }, 1, 2, 8, 8 }, /* DUP11 */
{ { NULL }, 10, 2, 8, 8 }, /* LK11A */
{ { NULL }, 1, 2, 8, 8 }, /* DMC11 */
{ { "DMC" }, 1, 2, 8, 8 }, /* DMC11 */
{ { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */
{ { NULL }, 1, 2, 8, 8 }, /* KMC11 */
{ { NULL }, 1, 2, 8, 8 }, /* LPP11 */

View file

@ -313,7 +313,7 @@ typedef struct {
#define IOLN_PTR 004
#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */
#define IOLN_PTP 004
#define IOBA_DMC (IOPAGEBASE + 0760060)
#define IOBA_DMC (IOPAGEBASE + 0760060) /* DMC11 */
#define IOLN_DMC 010
/* Interrupt assignments; within each level, priority is right to left */