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: Show active connections like DZ does, for multipoint.
// TODO: Test MOP. // TODO: Test MOP.
// TODO: Implement actual DDCMP protocol and run over UDP. // 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 <time.h>
#include <ctype.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_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_start_transfer_transmit_buffer(CTLR *controller);
void dmc_error_and_close_receive(CTLR *controller, char *format); 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); void dmc_close_transmit(CTLR *controller, char *reason);
int dmc_get_socket(CTLR *controller, int forRead); int dmc_get_socket(CTLR *controller, int forRead);
int dmc_get_receive_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 } &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_receive_queues[DMC_NUMDEVICE];
BUFFER_QUEUE dmc_transmit_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_receive_queues[DMP_NUMDEVICE];
BUFFER_QUEUE dmp_transmit_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 } { &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 *dmc_get_unit_stats(UNIT *uptr)
{ {
UNIT_STATS *ans = NULL; 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 (!cptr) return SCPE_IERR;
if (uptr->flags & UNIT_ATT) return SCPE_ALATT; if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
if (strcmp(cptr, "PRIMARY") == 0) if (MATCH_CMD(cptr, "PRIMARY") == 0)
{ {
controller->line->isPrimary = 1; controller->line->isPrimary = 1;
} }
else if (strcmp(cptr, "SECONDARY") == 0) else if (MATCH_CMD(cptr, "SECONDARY") == 0)
{ {
controller->line->isPrimary = 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->receive_queue, "receive");
dmc_buffer_queue_init(controller, controller->transmit_queue, "transmit"); 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"); //dmc_close_transmit(controller, "master clear");
controller->transfer_state = Idle; controller->transfer_state = Idle;
@ -1230,10 +1241,13 @@ void dmc_start_control_output_transfer(CTLR *controller)
t_stat dmc_svc(UNIT* uptr) t_stat dmc_svc(UNIT* uptr)
{ {
CTLR *controller; CTLR *controller;
int32 poll;
TIMER *poll_timer = &dmc_get_unit_stats(uptr)->poll_timer; TIMER *poll_timer = &dmc_get_unit_stats(uptr)->poll_timer;
TIMER *between_polls_timer = &dmc_get_unit_stats(uptr)->between_polls_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)) if (dmc_timer_started(between_polls_timer))
{ {
dmc_timer_stop(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); if (controller->transfer_state == Idle) dmc_start_transfer_transmit_buffer(controller);
/* resubmit service timer */ /* 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); dmc_timer_stop(poll_timer);
if (dmc_timer_started(between_polls_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); 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; int i;
if (length >= 0 && controller->device->dctrl & DBG_DAT) 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++) 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); 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 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. // 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); controller->master_socket = sim_master_sock(port, &ans);
if (controller->master_socket == INVALID_SOCKET) 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; ans = SCPE_OPENERR;
} }
else 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. // Gets the bidirectional socket and handles arbitration of determining which socket to use.
int dmc_get_socket(CTLR *controller, int forRead) int dmc_get_socket(CTLR *controller, int forRead)
{ {
static int lastans = 0; // static int lastans = 0;
int ans = 0; int ans = 0;
if (controller->line->isPrimary) 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. ans = dmc_get_receive_socket(controller, forRead); // TODO: After change to single socket, loopback may not work.
} }
if (lastans != ans) // if (lastans != ans)
{ // {
sim_debug(DBG_SOK, controller->device, "Get Socket forread=%d, changed to %d\n", forRead, ans); //sim_debug(DBG_SOK, controller->device, "Get Socket forread=%d, changed to %d\n", forRead, ans);
} // }
lastans = ans; // lastans = ans;
//
return 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 */ controller->line->socket = sim_accept_conn (controller->master_socket, &ipaddr); /* poll connect */
if (controller->line->socket != INVALID_SOCKET) 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); 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 else
{ {
@ -1615,7 +1633,7 @@ int dmc_get_receive_socket(CTLR *controller, int forRead)
} }
else if (readable == -1) /* Failed to open */ else if (readable == -1) /* Failed to open */
{ {
dmc_close_receive(controller, "failed to connect"); dmc_close_receive(controller, "failed to connect", NULL);
ans = 0; ans = 0;
} }
else /* connected */ else /* connected */
@ -1641,7 +1659,7 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
dmc_close_transmit(controller, "loopback change"); 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]; char hostport[CBUFSIZE];
@ -1653,10 +1671,11 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
else else
sprintf(hostport, "%s", controller->line->transmit_host); sprintf(hostport, "%s", controller->line->transmit_host);
sim_debug(DBG_SOK, controller->device, "Trying to open transmit socket to address:port %s\n", hostport); 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); controller->line->socket = sim_connect_sock(hostport, NULL, NULL);
if (controller->line->socket != INVALID_SOCKET) 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; controller->line->transmit_writeable = FALSE;
} }
} }
@ -1688,9 +1707,9 @@ int dmc_get_transmit_socket(CTLR *controller, int is_loopback, int forRead)
return ans; 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); sim_close_sock(controller->line->socket, FALSE);
controller->line->socket = INVALID_SOCKET; controller->line->socket = INVALID_SOCKET;
@ -1712,7 +1731,7 @@ void dmc_error_and_close_receive(CTLR *controller, char *format)
} }
else 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 dmc_buffer_fill_receive_buffers(CTLR *controller)
{ {
int ans = FALSE; int ans = FALSE;
int socket; SOCKET socket;
if (controller->state == Initialised) if (controller->state == Initialised)
{ {
/* accept any inbound connection but just throw away any data */ /* 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)); bytes_read = sim_read_sock(socket, buffer, sizeof(buffer));
if (bytes_read < 0) 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) 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); 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) 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) 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++; controller->buffers_received_from_net++;
buffer->state = ContainsData; buffer->state = ContainsData;
if (!lost_data) 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 dmc_buffer_send_transmit_buffers(CTLR *controller)
{ {
int ans = FALSE; int ans = FALSE;
int socket;
/* when transmit buffer is queued it is marked as available, not as ContainsData */ /* when transmit buffer is queued it is marked as available, not as ContainsData */
BUFFER *buffer = dmc_buffer_queue_find_first_available(controller->transmit_queue); BUFFER *buffer = dmc_buffer_queue_find_first_available(controller->transmit_queue);
while (buffer != NULL) 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); if (dmc_get_socket(controller, FALSE)) // TODO: , buffer->is_loopback);
{ {
int bytes = 0; int bytes = 0;
int bytes_to_send;
uint16 block_len; uint16 block_len;
int total_buffer_len = (buffer->count > 0) ? buffer->count + sizeof(block_len) : 0; 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 */ /* 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 (total_buffer_len > 0)
{ {
if (buffer->actual_bytes_transferred <= 0) if (buffer->transfer_buffer == NULL)
{ {
int n;
/* construct buffer and include block length bytes */ /* construct buffer and include block length bytes */
buffer->transfer_buffer = (uint8 *)malloc(total_buffer_len); buffer->transfer_buffer = (uint8 *)malloc(total_buffer_len);
block_len = htons(buffer->count); block_len = htons(buffer->count);
memcpy(buffer->transfer_buffer, (char *)&block_len, sizeof(block_len)); 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) if (bytes >= 0)
{ {
buffer->actual_bytes_transferred += bytes; buffer->actual_bytes_transferred += bytes;
controller->line->bytes_sent_in_last_second += bytes;
} }
if (buffer->actual_bytes_transferred >= total_buffer_len || bytes < 0) 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); free(buffer->transfer_buffer);
} }
} }
}
if (buffer->actual_bytes_transferred >= total_buffer_len) 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) if (controller->transfer_type == TYPE_BASEI)
{ {
//int i; //int i;
uint32 baseaddr = sel6 >> 14 | sel4; uint32 baseaddr = ((sel6 >> 14) << 16) | sel4;
uint16 count = sel6 & 0x3FFF; uint16 count = sel6 & 0x3FFF;
sim_debug(DBG_INF, controller->device, "Completing Base In input transfer, base address=0x%08x count=%d\n", baseaddr, count); 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++) //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) else if (controller->transfer_type == TYPE_BACCI)
{ {
uint32 addr = sel6 >> 14 | sel4; uint32 addr = ((sel6 >> 14) << 16) | sel4;
uint16 count = sel6 & 0x3FFF; uint16 count = sel6 & 0x3FFF;
if (controller->transfer_in_io != dmc_is_in_io_set(controller)) 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 }, /* DU11 */
{ { NULL }, 1, 2, 8, 8 }, /* DUP11 */ { { NULL }, 1, 2, 8, 8 }, /* DUP11 */
{ { NULL }, 10, 2, 8, 8 }, /* LK11A */ { { 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 */ { { "DZ" }, DZ_MUXES, 2, 8, 8 }, /* DZ11 */
{ { NULL }, 1, 2, 8, 8 }, /* KMC11 */ { { NULL }, 1, 2, 8, 8 }, /* KMC11 */
{ { NULL }, 1, 2, 8, 8 }, /* LPP11 */ { { NULL }, 1, 2, 8, 8 }, /* LPP11 */

View file

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