PDP11, VAX: Added Ethernet packet transmission throttling support to XQ and XU devices.
Migrated the XQ help to the hierarchical help model. This is a work in progress which will eventually merge much from 0readme_ethernet.txt into the device help.
This commit is contained in:
parent
753e4dc925
commit
e9b312f26a
7 changed files with 470 additions and 61 deletions
|
@ -1723,7 +1723,7 @@ const char helpString[] =
|
||||||
" The type of device being emulated can be changed with the following\n"
|
" The type of device being emulated can be changed with the following\n"
|
||||||
" command:\n"
|
" command:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"+sim> SET %U TYPE={DMR,DMC}\n"
|
"+sim> SET %U TYPE={DMR|DMC}\n"
|
||||||
"\n"
|
"\n"
|
||||||
" A SET TYPE command should be entered before the device is attached to a\n"
|
" A SET TYPE command should be entered before the device is attached to a\n"
|
||||||
" listening port.\n"
|
" listening port.\n"
|
||||||
|
|
390
PDP11/pdp11_xq.c
390
PDP11/pdp11_xq.c
|
@ -273,6 +273,8 @@ t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc);
|
t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc);
|
t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc);
|
t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
|
t_stat xq_show_throttle (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
|
t_stat xq_set_throttle (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
t_stat xq_show_lockmode (FILE* st, UNIT* uptr, int32 val, void* desc);
|
t_stat xq_show_lockmode (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
t_stat xq_set_lockmode (UNIT* uptr, int32 val, char* cptr, void* desc);
|
t_stat xq_set_lockmode (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
t_stat xq_show_poll (FILE* st, UNIT* uptr, int32 val, void* desc);
|
t_stat xq_show_poll (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
|
@ -312,7 +314,10 @@ struct xq_device xqa = {
|
||||||
XQ_SERVICE_INTERVAL, /* poll */
|
XQ_SERVICE_INTERVAL, /* poll */
|
||||||
0, 0, /* coalesce */
|
0, 0, /* coalesce */
|
||||||
{0}, /* sanity */
|
{0}, /* sanity */
|
||||||
0 /* DEQNA-Lock mode */
|
0, /* DEQNA-Lock mode */
|
||||||
|
ETH_THROT_DEFAULT_TIME, /* ms throttle window */
|
||||||
|
ETH_THROT_DEFAULT_BURST, /* packet packet burst in throttle window */
|
||||||
|
ETH_THROT_DISABLED_DELAY /* throttle disabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xq_device xqb = {
|
struct xq_device xqb = {
|
||||||
|
@ -324,7 +329,10 @@ struct xq_device xqb = {
|
||||||
XQ_SERVICE_INTERVAL, /* poll */
|
XQ_SERVICE_INTERVAL, /* poll */
|
||||||
0, 0, /* coalesce */
|
0, 0, /* coalesce */
|
||||||
{0}, /* sanity */
|
{0}, /* sanity */
|
||||||
0 /* DEQNA-Lock mode */
|
0, /* DEQNA-Lock mode */
|
||||||
|
ETH_THROT_DEFAULT_TIME, /* ms throttle window */
|
||||||
|
ETH_THROT_DEFAULT_BURST, /* packet packet burst in throttle window */
|
||||||
|
ETH_THROT_DISABLED_DELAY /* throttle disabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* SIMH device structures */
|
/* SIMH device structures */
|
||||||
|
@ -402,6 +410,10 @@ REG xqa_reg[] = {
|
||||||
{ GRDATA ( SANT_ENAB, xqa.sanity.enabled, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_ENAB, xqa.sanity.enabled, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SANT_QSECS, xqa.sanity.quarter_secs, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_QSECS, xqa.sanity.quarter_secs, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SANT_TIMR, xqa.sanity.timer, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_TIMR, xqa.sanity.timer, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( LOCKMODE, xqa.lockmode, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_TIME, xqa.throttle_time, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_BURST, xqa.throttle_burst, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_DELAY, xqa.throttle_delay, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -458,6 +470,10 @@ REG xqb_reg[] = {
|
||||||
{ GRDATA ( SANT_ENAB, xqb.sanity.enabled, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_ENAB, xqb.sanity.enabled, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SANT_QSECS, xqb.sanity.quarter_secs, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_QSECS, xqb.sanity.quarter_secs, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SANT_TIMR, xqb.sanity.timer, XQ_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( SANT_TIMR, xqb.sanity.timer, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( LOCKMODE, xqb.lockmode, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_TIME, xqb.throttle_time, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_BURST, xqb.throttle_burst, XQ_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_DELAY, xqb.throttle_delay, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -485,6 +501,8 @@ MTAB xq_mod[] = {
|
||||||
#endif
|
#endif
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SANITY", "SANITY={ON|OFF}",
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SANITY", "SANITY={ON|OFF}",
|
||||||
&xq_set_sanity, &xq_show_sanity, NULL, "Sanity timer" },
|
&xq_set_sanity, &xq_show_sanity, NULL, "Sanity timer" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "THROTTLE", "THROTTLE=DISABLED|TIME=n{;BURST=n{;DELAY=n}}",
|
||||||
|
&xq_set_throttle, &xq_show_throttle, NULL, "Display transmit throttle configuration" },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "DEQNALOCK", "DEQNALOCK={ON|OFF}",
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "DEQNALOCK", "DEQNALOCK={ON|OFF}",
|
||||||
&xq_set_lockmode, &xq_show_lockmode, NULL, "DEQNA-Lock mode" },
|
&xq_set_lockmode, &xq_show_lockmode, NULL, "DEQNA-Lock mode" },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "LEDS", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "LEDS", NULL,
|
||||||
|
@ -493,16 +511,16 @@ MTAB xq_mod[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEBTAB xq_debug[] = {
|
DEBTAB xq_debug[] = {
|
||||||
{"TRACE", DBG_TRC},
|
{"TRACE", DBG_TRC, "trace routine calls"},
|
||||||
{"CSR", DBG_CSR},
|
{"CSR", DBG_CSR, "watch CSR"},
|
||||||
{"VAR", DBG_VAR},
|
{"VAR", DBG_VAR, "watch VAR"},
|
||||||
{"WARN", DBG_WRN},
|
{"WARN", DBG_WRN, "display warnings"},
|
||||||
{"SETUP", DBG_SET},
|
{"SETUP", DBG_SET, "display setup info"},
|
||||||
{"SANITY", DBG_SAN},
|
{"SANITY", DBG_SAN, "display sanity timer info"},
|
||||||
{"REG", DBG_REG},
|
{"REG", DBG_REG, "trace read/write registers"},
|
||||||
{"PACKET", DBG_PCK},
|
{"PACKET", DBG_PCK, "display packet headers"},
|
||||||
{"DATA", DBG_DAT},
|
{"DATA", DBG_DAT, "display packet data"},
|
||||||
{"ETH", DBG_ETH},
|
{"ETH", DBG_ETH, "debug ethernet device"},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -847,6 +865,78 @@ t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat xq_show_throttle (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||||
|
{
|
||||||
|
CTLR* xq = xq_unit2ctlr(uptr);
|
||||||
|
|
||||||
|
if (xq->var->throttle_delay == ETH_THROT_DISABLED_DELAY)
|
||||||
|
fprintf(st, "throttle=disabled");
|
||||||
|
else
|
||||||
|
fprintf(st, "throttle=time=%d;burst=%d;delay=%d", xq->var->throttle_time, xq->var->throttle_burst, xq->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat xq_set_throttle (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||||
|
{
|
||||||
|
CTLR* xq = xq_unit2ctlr(uptr);
|
||||||
|
char tbuf[CBUFSIZE], gbuf[CBUFSIZE];
|
||||||
|
char *tptr = cptr;
|
||||||
|
uint32 newval;
|
||||||
|
uint32 set_time = xq->var->throttle_time;
|
||||||
|
uint32 set_burst = xq->var->throttle_burst;
|
||||||
|
uint32 set_delay = xq->var->throttle_delay;
|
||||||
|
t_stat r = SCPE_OK;
|
||||||
|
|
||||||
|
if (!cptr) {
|
||||||
|
xq->var->throttle_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
eth_set_throttle (xq->var->etherface, xq->var->throttle_time, xq->var->throttle_burst, xq->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this assumes that the parameter has already been upcased */
|
||||||
|
if ((!strcmp (cptr, "ON")) ||
|
||||||
|
(!strcmp (cptr, "ENABLED")))
|
||||||
|
xq->var->throttle_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
else
|
||||||
|
if ((!strcmp (cptr, "OFF")) ||
|
||||||
|
(!strcmp (cptr, "DISABLED")))
|
||||||
|
xq->var->throttle_delay = ETH_THROT_DISABLED_DELAY;
|
||||||
|
else {
|
||||||
|
if (set_delay == ETH_THROT_DISABLED_DELAY)
|
||||||
|
set_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
while (*tptr) {
|
||||||
|
tptr = get_glyph_nc (tptr, tbuf, ';');
|
||||||
|
cptr = tbuf;
|
||||||
|
cptr = get_glyph (cptr, gbuf, '=');
|
||||||
|
if ((NULL == cptr) || ('\0' == *cptr))
|
||||||
|
return SCPE_ARG;
|
||||||
|
newval = (uint32)get_uint (cptr, 10, 100, &r);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (!MATCH_CMD(gbuf, "TIME")) {
|
||||||
|
set_time = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!MATCH_CMD(gbuf, "BURST")) {
|
||||||
|
if (newval > 30)
|
||||||
|
return SCPE_ARG;
|
||||||
|
set_burst = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!MATCH_CMD(gbuf, "DELAY")) {
|
||||||
|
set_delay = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
xq->var->throttle_time = set_time;
|
||||||
|
xq->var->throttle_burst = set_burst;
|
||||||
|
xq->var->throttle_delay = set_delay;
|
||||||
|
}
|
||||||
|
eth_set_throttle (xq->var->etherface, xq->var->throttle_time, xq->var->throttle_burst, xq->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat xq_show_lockmode (FILE* st, UNIT* uptr, int32 val, void* desc)
|
t_stat xq_show_lockmode (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||||
{
|
{
|
||||||
CTLR* xq = xq_unit2ctlr(uptr);
|
CTLR* xq = xq_unit2ctlr(uptr);
|
||||||
|
@ -2688,6 +2778,7 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
|
||||||
xq->var->etherface = NULL;
|
xq->var->etherface = NULL;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
eth_set_throttle (xq->var->etherface, xq->var->throttle_time, xq->var->throttle_burst, xq->var->throttle_delay);
|
||||||
if (xq->var->poll == 0) {
|
if (xq->var->poll == 0) {
|
||||||
status = eth_set_async(xq->var->etherface, xq->var->coalesce_latency_ticks);
|
status = eth_set_async(xq->var->etherface, xq->var->coalesce_latency_ticks);
|
||||||
if (status != SCPE_OK) {
|
if (status != SCPE_OK) {
|
||||||
|
@ -2978,52 +3069,239 @@ return SCPE_NOFNC;
|
||||||
|
|
||||||
t_stat xq_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
t_stat xq_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
fprintf (st, "DELQA-T/DELQA/DEQNA Qbus Ethernet Controllers\n\n");
|
const char helpString[] =
|
||||||
fprintf (st, "The simulator implements two DELQA-T/DELQA/DEQNA Qbus Ethernet controllers\n");
|
/* The '*'s in the next line represent the standard text width of a help line */
|
||||||
fprintf (st, "(XQ, XQB). Initially, XQ is enabled, and XQB is disabled. Options allow\n");
|
/****************************************************************************/
|
||||||
fprintf (st, "control of the MAC address, the controller type, the sanity timer and\n");
|
// " The %1s is a communication subsystem which consists of a microprocessor\n"
|
||||||
fprintf (st, "for the DELQA and DELQA-T devices a DEQNA-Lock mode.\n\n");
|
" The DELQA-T/DELQA/DEQNA Qbus devices interface the %S processors\n"
|
||||||
fprint_set_help (st, dptr);
|
" to an Ethernet Local Area Network (LAN).\n"
|
||||||
fprintf (st, "\nConfigured options and controller state can be displayed with:\n\n");
|
"\n"
|
||||||
fprint_show_help (st, dptr);
|
|
||||||
fprintf (st, "\nMAC address octets must be delimited by dashes, colons or periods.\n");
|
|
||||||
fprintf (st, "The controller defaults to 08-00-2B-AA-BB-CC, which should be sufficient if\n");
|
|
||||||
fprintf (st, "there is only one SIMH DELQA-T/DELQA/DEQNA controller on your LAN. Two cards\n");
|
|
||||||
fprintf (st, "with the same MAC address will see each other's packets, resulting in a serious\n");
|
|
||||||
fprintf (st, "mess.\n\n");
|
|
||||||
fprintf (st, "The DELQA-T type/mode is better and faster but may not be usable by older or\n");
|
|
||||||
fprintf (st, "non-DEC OS's. Also, be aware that DEQNA type is not supported on some more\n");
|
|
||||||
fprintf (st, "recent OS's. DEQNA-LOCK mode behaves exactly like a DEQNA, except for the\n");
|
|
||||||
fprintf (st, "operation of the VAR and MOP processing.\n\n");
|
|
||||||
fprintf (st, "The SANITY command change or display the INITIALIZATION sanity timer (DEQNA\n");
|
|
||||||
fprintf (st, "jumper W3/DELQA switch S4). The INITIALIZATION sanity timer has a default\n");
|
|
||||||
fprintf (st, "timeout of 4 minutes, and cannot be turned off, just reset. The normal sanity\n");
|
|
||||||
fprintf (st, "timer can be set by operating system software regardless of the state of this\n");
|
|
||||||
fprintf (st, "switch. Note that only the DEQNA (or the DELQA in DEQNA-LOCK mode (=DEQNA))\n");
|
|
||||||
fprintf (st, "supports the sanity timer -- it is ignored by a DELQA in Normal mode, which\n");
|
|
||||||
fprintf (st, "uses switch S4 for a different purpose.\n\n");
|
|
||||||
#if defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO)
|
|
||||||
fprintf (st, "The POLL command change or display the service polling timer. Scheduled\n");
|
|
||||||
fprintf (st, "service polling is unnecessary and inefficient when asynchronous I/O is\n");
|
|
||||||
fprintf (st, "available, therefore the default setting is disabled.\n");
|
|
||||||
#else /* !(defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO)) */
|
|
||||||
fprintf (st, "The POLL command change or display the service polling timer. The polling\n");
|
|
||||||
fprintf (st, "timer is calibrated to run the service thread on each simulated system clock\n");
|
|
||||||
fprintf (st, "tick. This should be sufficient for most situations, however if desired more\n");
|
|
||||||
fprintf (st, "frequent polling can be specified. Polling too frequent can seriously impact\n");
|
|
||||||
fprintf (st, "the simulator's ability to execute instructions efficiently.\n");
|
|
||||||
#endif /* defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO) */
|
|
||||||
fprintf (st, "\nTo access the network, the simulated Ethernet controller must be attached to a\n");
|
|
||||||
fprintf (st, "real Ethernet interface.\n\n");
|
|
||||||
eth_attach_help(st, dptr, uptr, flag, cptr);
|
|
||||||
#ifdef VM_PDP11
|
#ifdef VM_PDP11
|
||||||
fprintf (st, "On PDP-11 simulators, the XQ device is bootable.\n\n");
|
" The controllers are compatible with both 18- and 22-bit Qbus backplanes.\n"
|
||||||
|
"\n"
|
||||||
#endif
|
#endif
|
||||||
fprintf (st, "One final note: because of its asynchronous nature, the XQ controller is not\n");
|
" The simulator implements two DELQA-T/DELQA/DEQNA Qbus Ethernet controllers\n"
|
||||||
fprintf (st, "limited to the network speed of the real DELQA-T/DELQA/DEQNA controllers, nor\n");
|
" (XQ, XQB). Initially, XQ is enabled, and XQB is disabled.\n"
|
||||||
fprintf (st, "the 10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet (100\n");
|
"1 Hardware Description\n"
|
||||||
fprintf (st, "Mbit/sec) card, and \"Feel the Power!\" :-)\n");
|
" The %D conforms to the Ethernet 2.0 specification performing the\n"
|
||||||
return SCPE_OK;
|
" data link layer functions, and part of the physical layer functions.\n"
|
||||||
|
"2 Models\n"
|
||||||
|
"3 DEQNA\n"
|
||||||
|
" A M7504 Qbus Module. The DELQA module is a dual-height module which\n"
|
||||||
|
" plugs directly into the Qbus backplane.\n"
|
||||||
|
"3 DELQA\n"
|
||||||
|
" A M7516 Qbus Module. The DELQA module is a dual-height module which\n"
|
||||||
|
" plugs directly into the Qbus backplane.\n"
|
||||||
|
"3 DELQA-T\n"
|
||||||
|
" A M7516-YM Qbus Module. The DELQA-T, also known as the DELQA-PLUS,\n"
|
||||||
|
" is a dual-height module which plugs directly into the Qbus backplane.\n"
|
||||||
|
"\n"
|
||||||
|
" The DELQA-T device has an extended register programming interface\n"
|
||||||
|
" which is more efficient than the initial DEQNA and DELQA model.\n"
|
||||||
|
"2 $Registers\n"
|
||||||
|
"\n"
|
||||||
|
" These registers contain the emulated state of the device. These values\n"
|
||||||
|
" don't necessarily relate to any detail of the original device being\n"
|
||||||
|
" emulated but are merely internal details of the emulation.\n"
|
||||||
|
"1 Configuration\n"
|
||||||
|
" A %D device is configured with various SET and ATTACH commands\n"
|
||||||
|
/****************************************************************************/
|
||||||
|
"2 $Set commands\n"
|
||||||
|
"3 MAC\n"
|
||||||
|
" The MAC address of the controller is the Hardware MAC address which on\n"
|
||||||
|
" real hardware is uniquely assigned by the factory. Each LAN device on a\n"
|
||||||
|
" network must have unique MAC addresses for proper operation.\n"
|
||||||
|
"\n"
|
||||||
|
"+sim> SET %D MAC=<mac-address>\n"
|
||||||
|
"\n"
|
||||||
|
" A Valid MAC address is comprised of 6 pairs of hex digits delimited by\n"
|
||||||
|
" dashes, colons or period characters.\n"
|
||||||
|
"\n"
|
||||||
|
" The default MAC address for the XQ device is 08-00-2B-AA-BB-CC. The\n"
|
||||||
|
" default MAC address for the XQB device is 08-00-2B-BB-CC-DD.\n"
|
||||||
|
"\n"
|
||||||
|
" The SET MAC command must be done before the %D device is attached to a\n"
|
||||||
|
" network.\n"
|
||||||
|
"3 Type\n"
|
||||||
|
" The type of device being emulated can be changed with the following\n"
|
||||||
|
" command:\n"
|
||||||
|
"\n"
|
||||||
|
"+sim> SET %D TYPE={DEQNA|DELQA|DELQA-T}\n"
|
||||||
|
"\n"
|
||||||
|
" A SET TYPE command should be entered before the device is attached.\n"
|
||||||
|
/****************************************************************************/
|
||||||
|
"3 SANITY\n"
|
||||||
|
" The sanity timer exists to make sure that the simulated operating system\n"
|
||||||
|
" software is up and running. The sanity timer is also known as the host\n"
|
||||||
|
" inactivity timer.\n"
|
||||||
|
" The timer is reset by the operating system device driver interacting with\n"
|
||||||
|
" the device. If the timer expires, the device negates the Qbus DCOK signal\n"
|
||||||
|
" which causes the system to reboot.\n"
|
||||||
|
"\n"
|
||||||
|
" The initial state of the sanity timer on real DEQNA hardware is configured\n"
|
||||||
|
" with the switch W4 and is switch S4 on DELQA boards. The SET %D SANITY\n"
|
||||||
|
" command exists to reflect the setting of this switch.\n"
|
||||||
|
"3 DEQNALOCK\n"
|
||||||
|
" Setting DEQNALock mode causes a DELQA or DELQA-T device to behaves exactly\n"
|
||||||
|
" like a DEQNA, except for the operation of the VAR and MOP processing.\n"
|
||||||
|
"3 POLL\n"
|
||||||
|
#if defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO)
|
||||||
|
" The SET %D POLL command changes the service polling timer. Scheduled\n"
|
||||||
|
" service polling is unnecessary and inefficient when asynchronous I/O is\n"
|
||||||
|
" available, therefore the default setting is disabled.\n"
|
||||||
|
#else /* !(defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO)) */
|
||||||
|
" The SET %D POLL command changes the service polling timer. The polling\n"
|
||||||
|
" timer is calibrated to run the service thread on each simulated system clock\n"
|
||||||
|
" tick. This should be sufficient for most situations, however if desired more\n"
|
||||||
|
" frequent polling can be specified. Polling too frequent can seriously impact\n"
|
||||||
|
" the simulator's ability to execute instructions efficiently.\n"
|
||||||
|
#endif /* defined(USE_READER_THREAD) && defined(SIM_ASYNCH_IO) */
|
||||||
|
/****************************************************************************/
|
||||||
|
"3 THROTTLE\n"
|
||||||
|
" The faster network operation of a simulated DELQA-T/DELQA/DEQNA device\n"
|
||||||
|
" might be too fast to interact with real PDP11 or VAX systems running on\n"
|
||||||
|
" the same LAN.\n"
|
||||||
|
" Traffic from the simulated device can easily push the real hardware\n"
|
||||||
|
" harder than it ever would have seen historically. The net result can\n"
|
||||||
|
" be excessive packet loss due to various over-run conditions. To support\n"
|
||||||
|
" interoperation of simulated systems with legacy hardware, the simulated\n"
|
||||||
|
" system can explictly be configured to throttle back the traffic it puts\n"
|
||||||
|
" on the wire.\n"
|
||||||
|
"\n"
|
||||||
|
" Throttling is configured with the SET XQ THROTTLE commands:\n"
|
||||||
|
"\n"
|
||||||
|
"+sim> SET XQ THROTTLE=DISABLE\n"
|
||||||
|
"+sim> SET XQ THROTTLE=ON\n"
|
||||||
|
"+sim> SET XQ THROTTLE=TIME=n;BURST=p;DELAY=t\n"
|
||||||
|
"\n"
|
||||||
|
" TIME specifies the number of milliseconds between successive packet\n"
|
||||||
|
" transmissions which will trigger throttling.\n"
|
||||||
|
" BURST specifies the number of successive packets which each are less than\n"
|
||||||
|
" the TIME gap that will cause a delay in sending subsequent packets.\n"
|
||||||
|
" DELAY specifies the number of milliseconds which a throttled packet will\n"
|
||||||
|
" be delayed prior to its transmission.\n"
|
||||||
|
"\n"
|
||||||
|
/****************************************************************************/
|
||||||
|
"2 Attach\n"
|
||||||
|
" The device must be attached to a LAN device to communicate with systems\n"
|
||||||
|
" on that LAN\n"
|
||||||
|
"\n"
|
||||||
|
"+sim> SHOW %D ETH\n"
|
||||||
|
"+ETH devices:\n"
|
||||||
|
#if defined(_WIN32)
|
||||||
|
"+ eth0 \\Device\\NPF_{A6F81789-B849-4220-B09B-19760D401A38} (Local Area Connection)\n"
|
||||||
|
"+ eth1 udp:sourceport:remotehost:remoteport (Integrated UDP bridge support)\n"
|
||||||
|
"+sim> ATTACH %D eth0\n"
|
||||||
|
#else
|
||||||
|
"+ eth0 en0 (No description available)\n"
|
||||||
|
"+ eth1 tap:tapN (Integrated Tun/Tap support)\n"
|
||||||
|
"+ eth2 udp:sourceport:remotehost:remoteport (Integrated UDP bridge support)\n"
|
||||||
|
"+sim> ATTACH %D eth0\n"
|
||||||
|
"+sim> ATTACH %D en0\n"
|
||||||
|
#endif
|
||||||
|
"+sim> ATTACH %D udp:1234:remote.host.com:1234\n"
|
||||||
|
"\n"
|
||||||
|
"2 Examples\n"
|
||||||
|
" To configure two simulators to talk to each other use the following\n"
|
||||||
|
" example:\n"
|
||||||
|
" \n"
|
||||||
|
" Machine 1\n"
|
||||||
|
"+sim> SET %D ENABLE\n"
|
||||||
|
"+sim> SET %D PEER=LOCALHOST:2222\n"
|
||||||
|
"+sim> ATTACH %D 1111\n"
|
||||||
|
" \n"
|
||||||
|
" Machine 2\n"
|
||||||
|
"+sim> SET %D ENABLE\n"
|
||||||
|
"+sim> SET %U PEER=LOCALHOST:1111\n"
|
||||||
|
"+sim> ATTACH %U 2222\n"
|
||||||
|
"\n"
|
||||||
|
"1 Monitoring\n"
|
||||||
|
" The %D device configuration and state can be displayed with one of the\n"
|
||||||
|
" available show commands.\n"
|
||||||
|
"2 $Show commands\n"
|
||||||
|
"3 LEDs\n"
|
||||||
|
" The %D devices have on-board LEDS which are used by the operating system,\n"
|
||||||
|
" boot code, and diagnostics to indicate the state of the device. The LED\n"
|
||||||
|
" state is visible with the SHOW %D LEDS command.\n"
|
||||||
|
"1 Boot Support\n"
|
||||||
|
#ifdef VM_PDP11
|
||||||
|
" The %D device is bootable using the on-board ROM code in the PDP-11\n"
|
||||||
|
" simulator.\n"
|
||||||
|
#else
|
||||||
|
" The %D device is bootable via the processor boot ROM on all MicroVAX\n"
|
||||||
|
" systems.\n"
|
||||||
|
#endif
|
||||||
|
"1 Debugging\n"
|
||||||
|
" The simulator has a number of debug options, these are:\n"
|
||||||
|
"\n"
|
||||||
|
"++TRACE Shows detailed routine calls.\n"
|
||||||
|
"++CSR Shows activities affecting the CSR.\n"
|
||||||
|
"++VAR Shows activities affecting the VAR.\n"
|
||||||
|
"++WARN Shows warnings.\n"
|
||||||
|
"++SETUP Shows setup info.\n"
|
||||||
|
"++SANITY Shows sanity timer info.\n"
|
||||||
|
"++REG Shows all device register programatic read/write activity\n"
|
||||||
|
"++PACKET Shows packet headers.\n"
|
||||||
|
"++DATA Shows packet data.\n"
|
||||||
|
"++ETH Shows ethernet device details.\n"
|
||||||
|
"\n"
|
||||||
|
" To get a full trace use\n"
|
||||||
|
"\n"
|
||||||
|
"+sim> SET %D DEBUG\n"
|
||||||
|
"\n"
|
||||||
|
/****************************************************************************/
|
||||||
|
"1 Dependencies\n"
|
||||||
|
#if defined(_WIN32)
|
||||||
|
" The WinPcap package must be installed in order to enable\n"
|
||||||
|
" communication with other computers on the local LAN.\n"
|
||||||
|
"\n"
|
||||||
|
" The WinPcap package is available from http://www.winpcap.org/\n"
|
||||||
|
#else
|
||||||
|
" To build simulators with the ability to communicate to other computers\n"
|
||||||
|
" on the local LAN, the libpcap development package must be installed on\n"
|
||||||
|
" the system which builds the simulator.\n"
|
||||||
|
"\n"
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
#else
|
||||||
|
#if defined(__linux__)
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
"1 Privileges Required\n"
|
||||||
|
#if defined(_WIN32)
|
||||||
|
" Windows systems can attach the simulated %D device to the local LAN\n"
|
||||||
|
" network interface without any special privileges as long as the\n"
|
||||||
|
" WinPcap package has been previously installed on the host system.\n"
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
"1 Host Computer Communications\n"
|
||||||
|
#if defined(_WIN32)
|
||||||
|
" On Windows using the WinPcap interface, the simulated %D device\n"
|
||||||
|
" can be used to communicate with the host computer on the same LAN\n"
|
||||||
|
" which it is attached to.\n"
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
/****************************************************************************/
|
||||||
|
"1 Performance\n"
|
||||||
|
" On modern host systems and networks, the simulated DEQNA/DELQA/DELQA-T\n"
|
||||||
|
" device can easily move data at more than 20Mbits per second.\n"
|
||||||
|
" Real DEQNA/DELQA hardware rarely exceeded more than 1.5Mbits/second\n"
|
||||||
|
"\n"
|
||||||
|
" Due to this significant speed mismatch, there can be issues when\n"
|
||||||
|
" simulated systems attempt to communicate with real PDP11 and VAX systems\n"
|
||||||
|
" on the LAN. See SET %D THROTTLE to help accommodate such communications.\n"
|
||||||
|
"1 Related Devices\n"
|
||||||
|
" The %D can facilitate communication with other simh simulators which\n"
|
||||||
|
" have emulated Ethernet devices available as well as real systems that\n"
|
||||||
|
" are directly connected to the LAN.\n"
|
||||||
|
"\n"
|
||||||
|
" The other simulated Ethernet devices include:\n"
|
||||||
|
"\n"
|
||||||
|
"++DEUNA/DELUA Unibus PDP11 and VAX simulators\n"
|
||||||
|
"\n"
|
||||||
|
;
|
||||||
|
return scp_help (st, dptr, uptr, flag, helpString, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *xq_description (DEVICE *dptr)
|
char *xq_description (DEVICE *dptr)
|
||||||
|
|
|
@ -264,6 +264,9 @@ struct xq_device {
|
||||||
uint32 coalesce_latency_ticks; /* instructions in coalesce_latency microseconds */
|
uint32 coalesce_latency_ticks; /* instructions in coalesce_latency microseconds */
|
||||||
struct xq_sanity sanity; /* sanity timer information */
|
struct xq_sanity sanity; /* sanity timer information */
|
||||||
t_bool lockmode; /* DEQNA-Lock mode */
|
t_bool lockmode; /* DEQNA-Lock mode */
|
||||||
|
uint32 throttle_time; /* ms burst time window */
|
||||||
|
uint32 throttle_burst; /* packets passed with throttle_time which trigger throttling */
|
||||||
|
uint32 throttle_delay; /* ms to delay when throttling. 0 disables throttling */
|
||||||
/*- initialized values - DO NOT MOVE */
|
/*- initialized values - DO NOT MOVE */
|
||||||
|
|
||||||
/* I/O register storage */
|
/* I/O register storage */
|
||||||
|
|
|
@ -115,6 +115,8 @@ t_stat xu_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
t_stat xu_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc);
|
t_stat xu_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
t_stat xu_show_type (FILE* st, UNIT* uptr, int32 val, void* desc);
|
t_stat xu_show_type (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
t_stat xu_set_type (UNIT* uptr, int32 val, char* cptr, void* desc);
|
t_stat xu_set_type (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
|
t_stat xu_show_throttle (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||||
|
t_stat xu_set_throttle (UNIT* uptr, int32 val, char* cptr, void* desc);
|
||||||
int32 xu_int (void);
|
int32 xu_int (void);
|
||||||
t_stat xu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat xu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat xu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat xu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
|
@ -145,7 +147,10 @@ struct xu_device xua = {
|
||||||
xua_read_callback, /* read callback routine */
|
xua_read_callback, /* read callback routine */
|
||||||
xua_write_callback, /* write callback routine */
|
xua_write_callback, /* write callback routine */
|
||||||
{0x08, 0x00, 0x2B, 0xCC, 0xDD, 0xEE}, /* mac */
|
{0x08, 0x00, 0x2B, 0xCC, 0xDD, 0xEE}, /* mac */
|
||||||
XU_T_DELUA /* type */
|
XU_T_DELUA, /* type */
|
||||||
|
ETH_THROT_DEFAULT_TIME, /* ms throttle window */
|
||||||
|
ETH_THROT_DEFAULT_BURST, /* packet packet burst in throttle window */
|
||||||
|
ETH_THROT_DISABLED_DELAY /* throttle disabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
MTAB xu_mod[] = {
|
MTAB xu_mod[] = {
|
||||||
|
@ -172,6 +177,8 @@ MTAB xu_mod[] = {
|
||||||
NULL, &xu_show_filters, NULL, "Display MAC addresses which will be received" },
|
NULL, &xu_show_filters, NULL, "Display MAC addresses which will be received" },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "TYPE", "TYPE={DEUNA|DELUA}",
|
{ MTAB_XTD|MTAB_VDV, 0, "TYPE", "TYPE={DEUNA|DELUA}",
|
||||||
&xu_set_type, &xu_show_type, NULL, "Display the controller type" },
|
&xu_set_type, &xu_show_type, NULL, "Display the controller type" },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "THROTTLE", "THROTTLE=DISABLED|TIME=n{;BURST=n{;DELAY=n}}",
|
||||||
|
&xu_set_throttle, &xu_show_throttle, NULL, "Display transmit throttle configuration" },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -208,6 +215,9 @@ REG xua_reg[] = {
|
||||||
{ BRDATA ( TXHDR, xua.txhdr, XU_RDX, 16, 4), REG_HRO},
|
{ BRDATA ( TXHDR, xua.txhdr, XU_RDX, 16, 4), REG_HRO},
|
||||||
{ GRDATA ( BA, xua_dib.ba, XU_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( BA, xua_dib.ba, XU_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( VECTOR, xua_dib.vec, XU_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( VECTOR, xua_dib.vec, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_TIME, xua.throttle_time, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_BURST, xua.throttle_burst, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_DELAY, xua.throttle_delay, XU_RDX, 32, 0), REG_HRO},
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
DEBTAB xu_debug[] = {
|
DEBTAB xu_debug[] = {
|
||||||
|
@ -243,7 +253,10 @@ struct xu_device xub = {
|
||||||
xub_read_callback, /* read callback routine */
|
xub_read_callback, /* read callback routine */
|
||||||
xub_write_callback, /* write callback routine */
|
xub_write_callback, /* write callback routine */
|
||||||
{0x08, 0x00, 0x2B, 0xDD, 0xEE, 0xFF}, /* mac */
|
{0x08, 0x00, 0x2B, 0xDD, 0xEE, 0xFF}, /* mac */
|
||||||
XU_T_DELUA /* type */
|
XU_T_DELUA, /* type */
|
||||||
|
ETH_THROT_DEFAULT_TIME, /* ms throttle window */
|
||||||
|
ETH_THROT_DEFAULT_BURST, /* packet packet burst in throttle window */
|
||||||
|
ETH_THROT_DISABLED_DELAY /* throttle disabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
REG xub_reg[] = {
|
REG xub_reg[] = {
|
||||||
|
@ -279,6 +292,9 @@ REG xub_reg[] = {
|
||||||
{ BRDATA ( TXHDR, xub.txhdr, XU_RDX, 16, 4), REG_HRO},
|
{ BRDATA ( TXHDR, xub.txhdr, XU_RDX, 16, 4), REG_HRO},
|
||||||
{ GRDATA ( BA, xub_dib.ba, XU_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( BA, xub_dib.ba, XU_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( VECTOR, xub_dib.vec, XU_RDX, 32, 0), REG_HRO},
|
{ GRDATA ( VECTOR, xub_dib.vec, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_TIME, xub.throttle_time, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_BURST, xub.throttle_burst, XU_RDX, 32, 0), REG_HRO},
|
||||||
|
{ GRDATA ( THR_DELAY, xub.throttle_delay, XU_RDX, 32, 0), REG_HRO},
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
DEVICE xub_dev = {
|
DEVICE xub_dev = {
|
||||||
|
@ -440,6 +456,78 @@ t_stat xu_set_type (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat xu_show_throttle (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||||
|
{
|
||||||
|
CTLR* xu = xu_unit2ctlr(uptr);
|
||||||
|
|
||||||
|
if (xu->var->throttle_delay == ETH_THROT_DISABLED_DELAY)
|
||||||
|
fprintf(st, "throttle=disabled");
|
||||||
|
else
|
||||||
|
fprintf(st, "throttle=time=%d;burst=%d;delay=%d", xu->var->throttle_time, xu->var->throttle_burst, xu->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat xu_set_throttle (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||||
|
{
|
||||||
|
CTLR* xu = xu_unit2ctlr(uptr);
|
||||||
|
char tbuf[CBUFSIZE], gbuf[CBUFSIZE];
|
||||||
|
char *tptr = cptr;
|
||||||
|
uint32 newval;
|
||||||
|
uint32 set_time = xu->var->throttle_time;
|
||||||
|
uint32 set_burst = xu->var->throttle_burst;
|
||||||
|
uint32 set_delay = xu->var->throttle_delay;
|
||||||
|
t_stat r = SCPE_OK;
|
||||||
|
|
||||||
|
if (!cptr) {
|
||||||
|
xu->var->throttle_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
eth_set_throttle (xu->var->etherface, xu->var->throttle_time, xu->var->throttle_burst, xu->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this assumes that the parameter has already been upcased */
|
||||||
|
if ((!strcmp (cptr, "ON")) ||
|
||||||
|
(!strcmp (cptr, "ENABLED")))
|
||||||
|
xu->var->throttle_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
else
|
||||||
|
if ((!strcmp (cptr, "OFF")) ||
|
||||||
|
(!strcmp (cptr, "DISABLED")))
|
||||||
|
xu->var->throttle_delay = ETH_THROT_DISABLED_DELAY;
|
||||||
|
else {
|
||||||
|
if (set_delay == ETH_THROT_DISABLED_DELAY)
|
||||||
|
set_delay = ETH_THROT_DEFAULT_DELAY;
|
||||||
|
while (*tptr) {
|
||||||
|
tptr = get_glyph_nc (tptr, tbuf, ';');
|
||||||
|
cptr = tbuf;
|
||||||
|
cptr = get_glyph (cptr, gbuf, '=');
|
||||||
|
if ((NULL == cptr) || ('\0' == *cptr))
|
||||||
|
return SCPE_ARG;
|
||||||
|
newval = (uint32)get_uint (cptr, 10, 100, &r);
|
||||||
|
if (r != SCPE_OK)
|
||||||
|
return SCPE_ARG;
|
||||||
|
if (!MATCH_CMD(gbuf, "TIME")) {
|
||||||
|
set_time = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!MATCH_CMD(gbuf, "BURST")) {
|
||||||
|
if (newval > 30)
|
||||||
|
return SCPE_ARG;
|
||||||
|
set_burst = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!MATCH_CMD(gbuf, "DELAY")) {
|
||||||
|
set_delay = newval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return SCPE_ARG;
|
||||||
|
}
|
||||||
|
xu->var->throttle_time = set_time;
|
||||||
|
xu->var->throttle_burst = set_burst;
|
||||||
|
xu->var->throttle_delay = set_delay;
|
||||||
|
}
|
||||||
|
eth_set_throttle (xu->var->etherface, xu->var->throttle_time, xu->var->throttle_burst, xu->var->throttle_delay);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
|
|
||||||
void upd_stat16(uint16* stat, uint16 add)
|
void upd_stat16(uint16* stat, uint16 add)
|
||||||
|
@ -1656,6 +1744,7 @@ t_stat xu_attach(UNIT* uptr, char* cptr)
|
||||||
xu->var->etherface = 0;
|
xu->var->etherface = 0;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
eth_set_throttle (xu->var->etherface, xu->var->throttle_time, xu->var->throttle_burst, xu->var->throttle_delay);
|
||||||
if (SCPE_OK != eth_check_address_conflict (xu->var->etherface, &xu->var->mac)) {
|
if (SCPE_OK != eth_check_address_conflict (xu->var->etherface, &xu->var->mac)) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
|
@ -1808,7 +1897,7 @@ fprintf (st, "real Ethernet interface.\n\n");
|
||||||
eth_attach_help(st, dptr, uptr, flag, cptr);
|
eth_attach_help(st, dptr, uptr, flag, cptr);
|
||||||
fprintf (st, "One final note: because of its asynchronous nature, the XU controller is not\n");
|
fprintf (st, "One final note: because of its asynchronous nature, the XU controller is not\n");
|
||||||
fprintf (st, "limited to the ~1.5Mbit/sec of the real DEUNA/DELUA controllers, nor the\n");
|
fprintf (st, "limited to the ~1.5Mbit/sec of the real DEUNA/DELUA controllers, nor the\n");
|
||||||
fprintf (st, "10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet (100 Mbit/sec)\n");
|
fprintf (st, "10Mbit/sec of a standard Ethernet. Attach it to a Fast or Gigabit Ethernet\n");
|
||||||
fprintf (st, "card, and \"Feel the Power!\" :-)\n");
|
fprintf (st, "card, and \"Feel the Power!\" :-)\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,9 @@ struct xu_device {
|
||||||
ETH_PCALLBACK wcallback; /* write callback routine */
|
ETH_PCALLBACK wcallback; /* write callback routine */
|
||||||
ETH_MAC mac; /* MAC address */
|
ETH_MAC mac; /* MAC address */
|
||||||
enum xu_type type; /* controller type */
|
enum xu_type type; /* controller type */
|
||||||
|
uint32 throttle_time; /* ms burst time window */
|
||||||
|
uint32 throttle_burst; /* packets passed with throttle_time which trigger throttling */
|
||||||
|
uint32 throttle_delay; /* ms to delay when throttling. 0 disables throttling */
|
||||||
/*- initialized values - DO NOT MOVE */
|
/*- initialized values - DO NOT MOVE */
|
||||||
|
|
||||||
/* I/O register storage */
|
/* I/O register storage */
|
||||||
|
|
24
sim_ether.c
24
sim_ether.c
|
@ -365,7 +365,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "sim_ether.h"
|
#include "sim_ether.h"
|
||||||
#include "sim_sock.h"
|
#include "sim_sock.h"
|
||||||
|
#include "sim_timer.h"
|
||||||
|
|
||||||
/*============================================================================*/
|
/*============================================================================*/
|
||||||
/* OS-independant ethernet routines */
|
/* OS-independant ethernet routines */
|
||||||
|
@ -1670,6 +1670,16 @@ while (dev->handle) {
|
||||||
dev->write_requests = request->next;
|
dev->write_requests = request->next;
|
||||||
pthread_mutex_unlock (&dev->writer_lock);
|
pthread_mutex_unlock (&dev->writer_lock);
|
||||||
|
|
||||||
|
if (dev->throttle_delay != ETH_THROT_DISABLED_DELAY) {
|
||||||
|
uint32 packet_delta_time = sim_os_msec() - dev->throttle_packet_time;
|
||||||
|
dev->throttle_events <<= 1;
|
||||||
|
dev->throttle_events += (packet_delta_time < dev->throttle_time) ? 1 : 0;
|
||||||
|
if ((dev->throttle_events & dev->throttle_mask) == dev->throttle_mask) {
|
||||||
|
sim_os_ms_sleep (dev->throttle_delay);
|
||||||
|
++dev->throttle_count;
|
||||||
|
}
|
||||||
|
dev->throttle_packet_time = sim_os_msec();
|
||||||
|
}
|
||||||
dev->write_status = _eth_write(dev, &request->packet, NULL);
|
dev->write_status = _eth_write(dev, &request->packet, NULL);
|
||||||
|
|
||||||
pthread_mutex_lock (&dev->writer_lock);
|
pthread_mutex_lock (&dev->writer_lock);
|
||||||
|
@ -1720,6 +1730,16 @@ return SCPE_OK;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay)
|
||||||
|
{
|
||||||
|
if (!dev)
|
||||||
|
return SCPE_IERR;
|
||||||
|
dev->throttle_time = time;
|
||||||
|
dev->throttle_burst = burst;
|
||||||
|
dev->throttle_delay = delay;
|
||||||
|
dev->throttle_mask = (1 << dev->throttle_burst) - 1;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
|
t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
|
||||||
{
|
{
|
||||||
int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ;
|
int bufsz = (BUFSIZ < ETH_MAX_PACKET) ? ETH_MAX_PACKET : BUFSIZ;
|
||||||
|
@ -3516,6 +3536,8 @@ if (dev->loopback_packets_processed)
|
||||||
fprintf(st, " Asynch Interrupts: %s\n", dev->asynch_io?"Enabled":"Disabled");
|
fprintf(st, " Asynch Interrupts: %s\n", dev->asynch_io?"Enabled":"Disabled");
|
||||||
if (dev->asynch_io)
|
if (dev->asynch_io)
|
||||||
fprintf(st, " Interrupt Latency: %d uSec\n", dev->asynch_io_latency);
|
fprintf(st, " Interrupt Latency: %d uSec\n", dev->asynch_io_latency);
|
||||||
|
if (dev->throttle_count)
|
||||||
|
fprintf(st, " Throttle Delays: %d\n", dev->throttle_count);
|
||||||
fprintf(st, " Read Queue: Count: %d\n", dev->read_queue.count);
|
fprintf(st, " Read Queue: Count: %d\n", dev->read_queue.count);
|
||||||
fprintf(st, " Read Queue: High: %d\n", dev->read_queue.high);
|
fprintf(st, " Read Queue: High: %d\n", dev->read_queue.high);
|
||||||
fprintf(st, " Read Queue: Loss: %d\n", dev->read_queue.loss);
|
fprintf(st, " Read Queue: Loss: %d\n", dev->read_queue.loss);
|
||||||
|
|
14
sim_ether.h
14
sim_ether.h
|
@ -268,6 +268,19 @@ struct eth_device {
|
||||||
uint32 dbit; /* debugging bit */
|
uint32 dbit; /* debugging bit */
|
||||||
int reflections; /* packet reflections on interface */
|
int reflections; /* packet reflections on interface */
|
||||||
int need_crc; /* device needs CRC (Cyclic Redundancy Check) */
|
int need_crc; /* device needs CRC (Cyclic Redundancy Check) */
|
||||||
|
/* Throttling control parameters: */
|
||||||
|
uint32 throttle_time; /* ms burst time window */
|
||||||
|
#define ETH_THROT_DEFAULT_TIME 5 /* 5ms Default burst time window */
|
||||||
|
uint32 throttle_burst; /* packets passed with throttle_time which trigger throttling */
|
||||||
|
#define ETH_THROT_DEFAULT_BURST 4 /* 4 Packet burst in time window */
|
||||||
|
uint32 throttle_delay; /* ms to delay when throttling. 0 disables throttling */
|
||||||
|
#define ETH_THROT_DISABLED_DELAY 0 /* 0 Delay disables throttling */
|
||||||
|
#define ETH_THROT_DEFAULT_DELAY 10 /* 10ms Delay during burst */
|
||||||
|
/* Throttling state variables: */
|
||||||
|
uint32 throttle_mask; /* match test for threshold detection (1 << throttle_burst) - 1 */
|
||||||
|
uint32 throttle_events; /* keeps track of packet arrival values */
|
||||||
|
uint32 throttle_packet_time; /* time last packet was transmitted */
|
||||||
|
uint32 throttle_count; /* Total Throttle Delays */
|
||||||
#if defined (USE_READER_THREAD)
|
#if defined (USE_READER_THREAD)
|
||||||
int asynch_io; /* Asynchronous Interrupt scheduling enabled */
|
int asynch_io; /* Asynchronous Interrupt scheduling enabled */
|
||||||
int asynch_io_latency; /* instructions to delay pending interrupt */
|
int asynch_io_latency; /* instructions to delay pending interrupt */
|
||||||
|
@ -315,6 +328,7 @@ int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices
|
||||||
void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */
|
void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */
|
||||||
t_stat eth_set_async (ETH_DEV* dev, int latency); /* set read behavior to be async */
|
t_stat eth_set_async (ETH_DEV* dev, int latency); /* set read behavior to be async */
|
||||||
t_stat eth_clr_async (ETH_DEV* dev); /* set read behavior to be not async */
|
t_stat eth_clr_async (ETH_DEV* dev); /* set read behavior to be not async */
|
||||||
|
t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay); /* set transmit throttle parameters */
|
||||||
uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len); /* Compute Ethernet Autodin II CRC for buffer */
|
uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len); /* Compute Ethernet Autodin II CRC for buffer */
|
||||||
|
|
||||||
void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, char* txt); /* trace ethernet packet header+crc */
|
void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, char* txt); /* trace ethernet packet header+crc */
|
||||||
|
|
Loading…
Add table
Reference in a new issue