mirror of
https://github.com/simh/simh.git
synced 2026-02-16 12:44:09 +00:00
Merged in new ethernet code to potentially leverage AsynchIO
This commit is contained in:
1032
PDP11/pdp11_xq.c
1032
PDP11/pdp11_xq.c
File diff suppressed because it is too large
Load Diff
187
PDP11/pdp11_xq.h
187
PDP11/pdp11_xq.h
@@ -28,6 +28,14 @@
|
||||
|
||||
Modification history:
|
||||
|
||||
03-Mar-08 MP Added DELQA-T (aka DELQA Plus) device emulation support.
|
||||
06-Feb-08 MP Added dropped frame statistics to record when the receiver discards
|
||||
received packets due to the receiver being disabled, or due to the
|
||||
XQ device's packet receive queue being full. Also removed the
|
||||
filter statistic counter since there was no code which ever set it.
|
||||
29-Jan-08 MP Dynamically determine the timer polling rate based on the
|
||||
calibrated tmr_poll and clk_tps values of the simulator.
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
20-Jan-04 DTH Added new sanity timer and system id timer
|
||||
19-Jan-04 DTH Added XQ_SERVICE_INTERVAL, poll
|
||||
@@ -84,12 +92,11 @@ extern int32 int_req[IPL_HLVL];
|
||||
#define XQ_HW_SANITY_SECS 240 /* seconds before HW sanity timer expires */
|
||||
#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */
|
||||
|
||||
enum xq_type {XQ_T_DEQNA, XQ_T_DELQA};
|
||||
enum xq_type {XQ_T_DEQNA, XQ_T_DELQA, XQ_T_DELQA_PLUS};
|
||||
|
||||
struct xq_sanity {
|
||||
int enabled; /* sanity timer enabled? 2=HW, 1=SW, 0=off */
|
||||
int quarter_secs; /* sanity timer value in 1/4 seconds */
|
||||
int max; /* maximum timeout (based on poll) */
|
||||
int timer; /* countdown timer */
|
||||
};
|
||||
|
||||
@@ -104,17 +111,132 @@ struct xq_setup {
|
||||
ETH_MAC macs[XQ_FILTER_MAX]; /* MAC addresses to respond to */
|
||||
};
|
||||
|
||||
struct xq_turbo_init_block { /* DELQA-T Initialization Block */
|
||||
uint16 mode;
|
||||
#define XQ_IN_MO_PRO 0x8000 /* Promiscuous Mode */
|
||||
#define XQ_IN_MO_INT 0x0040 /* Internal Loopback Mode */
|
||||
#define XQ_IN_MO_DRT 0x0020 /* Disable Retry */
|
||||
#define XQ_IN_MO_DTC 0x0008 /* Disable Transmit CRC */
|
||||
#define XQ_IN_MO_LOP 0x0004 /* Loopback */
|
||||
ETH_MAC phys; /* Physical MAC Address */
|
||||
ETH_MULTIHASH hash_filter; /* 64bit LANCE Hash Filter for Multicast Address selection */
|
||||
uint16 rdra_l;
|
||||
uint16 rdra_h;
|
||||
uint16 tdra_l;
|
||||
uint16 tdra_h;
|
||||
uint16 options;
|
||||
#define XQ_IN_OP_HIT 0x0002 /* Host Inactivity Timer Enable Flag */
|
||||
#define XQ_IN_OP_INT 0x0001 /* Interrupt Enable Flag*/
|
||||
uint16 vector; /* Interrupt Vector */
|
||||
uint16 hit_timeout; /* Host Inactivity Timer Timeout Value */
|
||||
uint8 bootpassword[6]; /* MOP Console Boot Password */
|
||||
};
|
||||
|
||||
/* DELQA-T Mode - Transmit Buffer Descriptor */
|
||||
struct transmit_buffer_descriptor {
|
||||
uint16 tmd0;
|
||||
#define XQ_TMD0_ERR1 0x4000 /* Error Summary. The OR of TMD1 (LC0, LCA, and RTR) */
|
||||
#define XQ_TMD0_MOR 0x1000 /* More than one retry on transmit */
|
||||
#define XQ_TMD0_ONE 0x0800 /* One retry on transmit */
|
||||
#define XQ_TMD0_DEF 0x0400 /* Deferral during transmit */
|
||||
uint16 tmd1;
|
||||
#define XQ_TMD1_LCO 0x1000 /* Late collision on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_LCA 0x0800 /* Loss of carrier on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_RTR 0x0400 /* Retry error on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_TDR 0x03FF /* Time Domain Reflectometry value */
|
||||
uint16 tmd2;
|
||||
#define XQ_TMD2_ERR2 0x8000 /* Error Summary. The OR of TMD2 (BBL, CER, and MIS) */
|
||||
#define XQ_TMD2_BBL 0x4000 /* Babble error on transmit */
|
||||
#define XQ_TMD2_CER 0x2000 /* Collision error on transmit */
|
||||
#define XQ_TMD2_MIS 0x1000 /* Packet lost on receive */
|
||||
#define XQ_TMD2_EOR 0x0800 /* End Of Receive Ring Reached */
|
||||
#define XQ_TMD2_RON 0x0020 /* Receiver On */
|
||||
#define XQ_TMD2_TON 0x0010 /* Transmitter On */
|
||||
uint16 tmd3;
|
||||
#define XQ_TMD3_OWN 0x8000 /* Ownership field. 0 = DELQA-T, 1 = Host Driver */
|
||||
#define XQ_TMD3_FOT 0x4000 /* First Of Two flag. 1 = first in chained, 0 = no chain or last in chain */
|
||||
#define XQ_TMD3_BCT 0x0FFF /* Byte Count */
|
||||
uint16 ladr; /* Low 16bits of Buffer Address */
|
||||
uint16 hadr; /* Most significant bits of the Buffer Address */
|
||||
uint16 hostuse1;
|
||||
uint16 hostuse2;
|
||||
};
|
||||
#define XQ_TURBO_XM_BCNT 12 /* Transmit Buffer Descriptor Count */
|
||||
|
||||
struct receive_buffer_descriptor {
|
||||
uint16 rmd0;
|
||||
#define XQ_RMD0_ERR3 0x4000 /* Error Summary. The OR of FRA, CRC, OFL and BUF */
|
||||
#define XQ_RMD0_FRA 0x2000 /* Framing error on receive */
|
||||
#define XQ_RMD0_OFL 0x1000 /* Overflow error on receive (Giant packet) */
|
||||
#define XQ_RMD0_CRC 0x0800 /* CRC error on receive */
|
||||
#define XQ_RMD0_BUF 0x0400 /* Internal device buffer error. Part of Giant packet lost */
|
||||
#define XQ_RMD0_STP 0x0200 /* Start of Packet Flag */
|
||||
#define XQ_RMD0_ENP 0x0100 /* End of Packet Flag */
|
||||
uint16 rmd1;
|
||||
#define XQ_RMD1_MCNT 0x0FFF /* Message byte count (including CRC) */
|
||||
uint16 rmd2;
|
||||
#define XQ_RMD2_ERR4 0x8000 /* Error Summary. The OR of RMD2 (RBL, CER, and MIS) */
|
||||
#define XQ_RMD2_BBL 0x4000 /* Babble error on transmit */
|
||||
#define XQ_RMD2_CER 0x2000 /* Collision error on transmit */
|
||||
#define XQ_RMD2_MIS 0x1000 /* Packet lost on receive */
|
||||
#define XQ_RMD2_EOR 0x0800 /* End Of Receive Ring Reached */
|
||||
#define XQ_RMD2_RON 0x0020 /* Receiver On */
|
||||
#define XQ_RMD2_TON 0x0010 /* Transmitter On */
|
||||
uint16 rmd3;
|
||||
#define XQ_RMD3_OWN 0x8000 /* Ownership field. 0 = DELQA-T, 1 = Host Driver */
|
||||
uint16 ladr; /* Low 16bits of Buffer Address */
|
||||
uint16 hadr; /* Most significant bits of the Buffer Address */
|
||||
uint16 hostuse1;
|
||||
uint16 hostuse2;
|
||||
};
|
||||
#define XQ_TURBO_RC_BCNT 32 /* Receive Buffer Descriptor Count */
|
||||
|
||||
struct xq_stats {
|
||||
int recv; /* received packets */
|
||||
int filter; /* filtered packets */
|
||||
int dropped; /* received packets dropped */
|
||||
int xmit; /* transmitted packets */
|
||||
int fail; /* transmit failed */
|
||||
int runt; /* runts */
|
||||
int reset; /* reset count */
|
||||
int giant; /* oversize packets */
|
||||
int setup; /* setup packets */
|
||||
int loop; /* loopback packets */
|
||||
};
|
||||
|
||||
#pragma pack(2)
|
||||
struct xq_mop_counters {
|
||||
uint16 seconds; /* Seconds since last zeroed */
|
||||
uint32 b_rcvd; /* Bytes Received */
|
||||
uint32 b_xmit; /* Bytes Transmitted */
|
||||
uint32 p_rcvd; /* Packets Received */
|
||||
uint32 p_xmit; /* Packets Transmitted */
|
||||
uint32 mb_rcvd; /* Multicast Bytes Received */
|
||||
uint32 mp_rcvd; /* Multicast Packets Received */
|
||||
uint32 p_x_col1; /* Packets Transmitted Initially Deferred */
|
||||
uint32 p_x_col2; /* Packets Transmitted after 2 attempts */
|
||||
uint32 p_x_col3; /* Packets Transmitted after 3+ attempts */
|
||||
uint16 p_x_fail; /* Transmit Packets Aborted (Send Failure) */
|
||||
uint16 p_x_f_bitmap; /* Transmit Packets Aborted (Send Failure) Bitmap */
|
||||
#define XQ_XF_RTRY 0x0001 /* Excessive Collisions */
|
||||
#define XQ_XF_LCAR 0x0002 /* Loss of Carrier */
|
||||
#define XQ_XF_MLEN 0x0010 /* Data Block Too Long */
|
||||
#define XQ_XF_LCOL 0x0020 /* Late Collision */
|
||||
uint16 p_r_fail; /* Packets received with Error (Receive Failure) */
|
||||
uint16 p_r_f_bitmap; /* Packets received with Error (Receive Failure) Bitmap */
|
||||
#define XQ_RF_CRC 0x0001 /* Block Check Error */
|
||||
#define XQ_RF_FRAM 0x0002 /* Framing Error */
|
||||
#define XQ_RF_MLEN 0x0004 /* Message Length Error */
|
||||
uint16 h_dest_err; /* Host Counter - Unrecognized Frame Destination Error */
|
||||
uint16 r_p_lost_i; /* Receive Packet Lost: Internal Buffer Error */
|
||||
uint16 r_p_lost_s; /* Receive Packet Lost: System Buffer Error (Unavailable or Truncated) */
|
||||
uint16 h_no_buf; /* Host Counter - User Buffer Unavailable */
|
||||
uint32 mb_xmit; /* Multicast Bytes Tramsmitted */
|
||||
uint16 reserved1; /* */
|
||||
uint16 reserved2; /* */
|
||||
uint16 babble; /* Babble Counter */
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct xq_meb { /* MEB block */
|
||||
uint8 type;
|
||||
uint8 add_lo;
|
||||
@@ -128,18 +250,36 @@ struct xq_device {
|
||||
/*+ initialized values - DO NOT MOVE */
|
||||
ETH_PCALLBACK rcallback; /* read callback routine */
|
||||
ETH_PCALLBACK wcallback; /* write callback routine */
|
||||
ETH_MAC mac; /* MAC address */
|
||||
ETH_MAC mac; /* Hardware MAC address */
|
||||
enum xq_type type; /* controller type */
|
||||
int poll; /* poll ethernet times/sec */
|
||||
enum xq_type mode; /* controller operating mode */
|
||||
uint16 poll; /* configured poll ethernet times/sec for receive */
|
||||
uint16 coalesce_latency; /* microseconds to hold-off interrupts when not polling */
|
||||
uint16 coalesce_latency_ticks; /* instructions in coalesce_latency microseconds */
|
||||
struct xq_sanity sanity; /* sanity timer information */
|
||||
/*- initialized values - DO NOT MOVE */
|
||||
|
||||
/* I/O register storage */
|
||||
uint16 addr[6];
|
||||
|
||||
uint16 rbdl[2];
|
||||
uint16 xbdl[2];
|
||||
uint16 var;
|
||||
uint16 csr;
|
||||
|
||||
uint16 srr; /* Status and Response Register - DELQA-T only */
|
||||
uint16 srqr; /* Synchronous Request Register - DELQA-T only */
|
||||
uint32 iba; /* Init Block Address Register - DELQA-T only */
|
||||
uint16 icr; /* Interrupt Request Register - DELQA-T only */
|
||||
uint16 pending_interrupt; /* Pending Interrupt - DELQA-T only */
|
||||
struct xq_turbo_init_block
|
||||
init;
|
||||
struct transmit_buffer_descriptor
|
||||
xring[XQ_TURBO_XM_BCNT]; /* Transmit Buffer Ring */
|
||||
uint32 tbindx; /* Transmit Buffer Ring Index */
|
||||
struct receive_buffer_descriptor
|
||||
rring[XQ_TURBO_RC_BCNT]; /* Receive Buffer Ring */
|
||||
uint32 rbindx; /* Receive Buffer Ring Index */
|
||||
|
||||
uint32 irq; /* interrupt request flag */
|
||||
|
||||
/* buffers, etc. */
|
||||
@@ -151,11 +291,11 @@ struct xq_device {
|
||||
uint32 rbdl_ba;
|
||||
uint32 xbdl_ba;
|
||||
ETH_DEV* etherface;
|
||||
int receiving;
|
||||
ETH_PACK read_buffer;
|
||||
ETH_PACK write_buffer;
|
||||
ETH_QUE ReadQ;
|
||||
int idtmr; /* countdown for ID Timer */
|
||||
int32 idtmr; /* countdown for ID Timer */
|
||||
uint32 must_poll; /* receiver must poll instead of counting on asynch polls */
|
||||
};
|
||||
|
||||
struct xq_controller {
|
||||
@@ -207,6 +347,7 @@ typedef struct xq_controller CTLR;
|
||||
#define XQ_VEC_RO 0x5C02 /* Read-Only bits */
|
||||
#define XQ_VEC_RW 0xA3FD /* Read/Write bits */
|
||||
|
||||
/* DEQNA - DELQA Normal Mode Buffer Descriptors */
|
||||
#define XQ_DSC_V 0x8000 /* Valid bit */
|
||||
#define XQ_DSC_C 0x4000 /* Chain bit */
|
||||
#define XQ_DSC_E 0x2000 /* End of Message bit [Transmit only] */
|
||||
@@ -214,11 +355,38 @@ typedef struct xq_controller CTLR;
|
||||
#define XQ_DSC_L 0x0080 /* Low Byte Termination bit [Transmit only] */
|
||||
#define XQ_DSC_H 0x0040 /* High Byte Start bit [Transmit only] */
|
||||
|
||||
/* DEQNA - DELQA Normal Mode Setup Packet Flags */
|
||||
#define XQ_SETUP_MC 0x0001 /* multicast bit */
|
||||
#define XQ_SETUP_PM 0x0002 /* promiscuous bit */
|
||||
#define XQ_SETUP_LD 0x000C /* led bits */
|
||||
#define XQ_SETUP_ST 0x0070 /* sanity timer bits */
|
||||
|
||||
/* DELQA-T Mode - Status and Response Register (SRR) */
|
||||
#define XQ_SRR_FES 0x8000 /* Fatal Error Summary [RO] */
|
||||
#define XQ_SRR_CHN 0x4000 /* Chaining Error [RO] */
|
||||
#define XQ_SRR_NXM 0x1000 /* Non-Existant Memory Error [RO] */
|
||||
#define XQ_SRR_PAR 0x0800 /* Parity Error (Qbus) [RO] */
|
||||
#define XQ_SRR_IME 0x0400 /* Internal Memory Error [RO] */
|
||||
#define XQ_SRR_TBL 0x0200 /* Transmit Buffer Too Long Error [RO] */
|
||||
#define XQ_SRR_RESP 0x0003 /* Synchronous Response Field [RO] */
|
||||
#define XQ_SRR_TRBO 0x0001 /* Select Turbo Response [RO] */
|
||||
#define XQ_SRR_STRT 0x0002 /* Start Device Response [RO] */
|
||||
#define XQ_SRR_STOP 0x0003 /* Stop Device Response [RO] */
|
||||
|
||||
/* DELQA-T Mode - Synchronous Request Register (SRQR) */
|
||||
#define XQ_SRQR_STRT 0x0002 /* Start Device Request [WO] */
|
||||
#define XQ_SRQR_STOP 0x0003 /* Stop Device Request [WO] */
|
||||
#define XQ_SRQR_RW 0x0003 /* Writable Bits in SRQR [WO] */
|
||||
|
||||
/* DELQA-T Mode - Asynchronous Request Register (ARQR) */
|
||||
#define XQ_ARQR_TRQ 0x8000 /* Transmit Request [WO] */
|
||||
#define XQ_ARQR_RRQ 0x0080 /* Receieve Request [WO] */
|
||||
#define XQ_ARQR_SR 0x0002 /* Software Reset Request [WO] */
|
||||
|
||||
/* DELQA-T Mode - Interrupt Control Register (ICR) */
|
||||
#define XQ_ICR_ENA 0x0001 /* Interrupt Enabled [WO] */
|
||||
|
||||
|
||||
/* debugging bitmaps */
|
||||
#define DBG_TRC 0x0001 /* trace routine calls */
|
||||
#define DBG_REG 0x0002 /* trace read/write registers */
|
||||
@@ -227,7 +395,8 @@ typedef struct xq_controller CTLR;
|
||||
#define DBG_WRN 0x0010 /* display warnings */
|
||||
#define DBG_SAN 0x0020 /* display sanity timer info */
|
||||
#define DBG_SET 0x0040 /* display setup info */
|
||||
#define DBG_PCK 0x0080 /* display packets */
|
||||
#define DBG_PCK 0x0080 /* display packet headers */
|
||||
#define DBG_DAT 0x0100 /* display packet data */
|
||||
#define DBG_ETH 0x8000 /* debug ethernet device */
|
||||
|
||||
#endif /* _PDP11_XQ_H */
|
||||
|
||||
180
PDP11/pdp11_xu.c
180
PDP11/pdp11_xu.c
@@ -1,7 +1,7 @@
|
||||
/* pdp11_xu.c: DEUNA/DELUA ethernet controller simulator
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2003-2007, David T. Hittner
|
||||
Copyright (c) 2003-2011, David T. Hittner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -30,7 +30,7 @@
|
||||
Digital DELUA Users Guide, Part# EK-DELUA-UG-002
|
||||
Digital DEUNA Users Guide, Part# EK-DEUNA-UG-001
|
||||
These manuals can be found online at:
|
||||
http://www.spies.com/~aek/pdf/dec/unibus
|
||||
http://www.bitsavers.org/pdf/dec/unibus
|
||||
|
||||
Testing performed:
|
||||
1) Receives/Transmits single packet under custom RSX driver
|
||||
@@ -41,7 +41,13 @@
|
||||
DECNET - SET HOST in/out, COPY in/out
|
||||
TCP/IP - PING in/out; SET HOST/TELNET in/out, COPY/FTP in/out
|
||||
Clustering - Successfully clustered with AlphaVMS 8.2
|
||||
4) Runs VAX EVDWA diagnostic tests 1-10; tests 11-19 (M68000/ROM/RAM) fail
|
||||
4) VMS 4.7 on VAX780 summary:
|
||||
(Jan/2011: Win7 x64 host; MS VC++ 2008; SIMH v3.8-2 rc1 base; WinPcap 4.1)
|
||||
LAT - SET HOST/LAT in (no outbound exists)
|
||||
DECNET - SET HOST in/out, DIR in/out, COPY in/out
|
||||
TCP/IP - no kit available to test
|
||||
Clustering - not tested
|
||||
5) Runs VAX EVDWA diagnostic tests 1-10; tests 11-19 (M68000/ROM/RAM) fail
|
||||
|
||||
Known issues:
|
||||
1) Most auxiliary commands are not implemented yet.
|
||||
@@ -56,6 +62,14 @@
|
||||
|
||||
Modification history:
|
||||
|
||||
12-Jan-11 DTH Added SHOW XU FILTERS modifier
|
||||
11-Jan-11 DTH Corrected SELFTEST command, enabling use by VMS 3.7, VMS 4.7, and Ultrix 1.1
|
||||
09-Dec-10 MP Added address conflict check during attach.
|
||||
06-Dec-10 MP Added loopback processing support
|
||||
30-Nov-10 MP Fixed the fact that no broadcast packets were received by the DEUNA
|
||||
15-Aug-08 MP Fixed transmitted packets to have the correct source MAC address.
|
||||
Fixed incorrect address filter setting calling eth_filter().
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag
|
||||
03-May-07 DTH Added missing FC_RMAL command; cleared multicast on write
|
||||
29-Oct-06 RMS Synced poll and clock
|
||||
@@ -112,6 +126,7 @@ void xu_clrint (CTLR* xu);
|
||||
void xu_process_receive(CTLR* xu);
|
||||
void xu_dump_rxring(CTLR* xu);
|
||||
void xu_dump_txring(CTLR* xu);
|
||||
t_stat xu_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||
|
||||
DIB xua_dib = { IOBA_XU, IOLN_XU, &xu_rd, &xu_wr,
|
||||
1, IVCL (XU), VEC_XU, {&xu_int} };
|
||||
@@ -143,6 +158,8 @@ MTAB xu_mod[] = {
|
||||
NULL, ð_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS",
|
||||
&xu_set_stats, &xu_show_stats, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "FILTERS", "FILTERS",
|
||||
NULL, &xu_show_filters, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE={DEUNA|DELUA}",
|
||||
&xu_set_type, &xu_show_type, NULL },
|
||||
{ 0 },
|
||||
@@ -156,6 +173,7 @@ DEBTAB xu_debug[] = {
|
||||
{"WARN", DBG_WRN},
|
||||
{"REG", DBG_REG},
|
||||
{"PACKET", DBG_PCK},
|
||||
{"DATA", DBG_DAT},
|
||||
{"ETH", DBG_ETH},
|
||||
{0}
|
||||
};
|
||||
@@ -294,20 +312,39 @@ t_stat xu_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||
|
||||
t_stat xu_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
char* fmt = " %-24s%d\n";
|
||||
char* fmt = " %-26s%d\n";
|
||||
CTLR* xu = xu_unit2ctlr(uptr);
|
||||
struct xu_stats* stats = &xu->var->stats;
|
||||
|
||||
fprintf(st, "Ethernet statistics:\n");
|
||||
fprintf(st, fmt, "Seconds since cleared:", stats->secs);
|
||||
fprintf(st, fmt, "Recv frames:", stats->frecv);
|
||||
fprintf(st, fmt, "Recv dbytes:", stats->rbytes);
|
||||
fprintf(st, fmt, "Xmit frames:", stats->ftrans);
|
||||
fprintf(st, fmt, "Xmit dbytes:", stats->tbytes);
|
||||
fprintf(st, fmt, "Recv frames(multicast):", stats->mfrecv);
|
||||
fprintf(st, fmt, "Recv dbytes(multicast):", stats->mrbytes);
|
||||
fprintf(st, fmt, "Xmit frames(multicast):", stats->mftrans);
|
||||
fprintf(st, fmt, "Xmit dbytes(multicast):", stats->mtbytes);
|
||||
fprintf(st, fmt, "Seconds since cleared:", stats->secs);
|
||||
fprintf(st, fmt, "Recv frames:", stats->frecv);
|
||||
fprintf(st, fmt, "Recv dbytes:", stats->rbytes);
|
||||
fprintf(st, fmt, "Xmit frames:", stats->ftrans);
|
||||
fprintf(st, fmt, "Xmit dbytes:", stats->tbytes);
|
||||
fprintf(st, fmt, "Recv frames(multicast):", stats->mfrecv);
|
||||
fprintf(st, fmt, "Recv dbytes(multicast):", stats->mrbytes);
|
||||
fprintf(st, fmt, "Xmit frames(multicast):", stats->mftrans);
|
||||
fprintf(st, fmt, "Xmit dbytes(multicast):", stats->mtbytes);
|
||||
fprintf(st, fmt, "Loopback forward Frames:", stats->loopf);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat xu_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
CTLR* xu = xu_unit2ctlr(uptr);
|
||||
char buffer[20];
|
||||
int i;
|
||||
|
||||
fprintf(st, "Filters:\n");
|
||||
for (i=0; i<XU_FILTER_MAX; i++) {
|
||||
eth_mac_fmt((ETH_MAC*)xu->var->setup.macs[i], buffer);
|
||||
fprintf(st, " [%2d]: %s\n", i, buffer);
|
||||
}
|
||||
if (xu->var->setup.multicast)
|
||||
fprintf(st, "All Multicast Receive Mode\n");
|
||||
if (xu->var->setup.promiscuous)
|
||||
fprintf(st, "Promiscuous Receive Mode\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -359,13 +396,63 @@ void bit_stat16(uint16* stat, uint16 bits)
|
||||
*stat |= bits;
|
||||
}
|
||||
|
||||
t_stat xu_process_loopback(CTLR* xu, ETH_PACK* pack)
|
||||
{
|
||||
ETH_PACK response;
|
||||
ETH_MAC physical_address;
|
||||
t_stat status;
|
||||
int offset = 16 + (pack->msg[14] | (pack->msg[15] << 8));
|
||||
int function = pack->msg[offset] | (pack->msg[offset+1] << 8);
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_process_loopback()\n");
|
||||
|
||||
if (function != 2 /*forward*/)
|
||||
return SCPE_NOFNC;
|
||||
|
||||
/* create forward response packet */
|
||||
memcpy (&response, pack, sizeof(ETH_PACK));
|
||||
memcpy (physical_address, xu->var->setup.macs[0], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC));
|
||||
offset += 8;
|
||||
response.msg[14] = offset & 0xFF;
|
||||
response.msg[15] = (offset >> 8) & 0xFF;
|
||||
|
||||
/* send response packet */
|
||||
status = eth_write(xu->var->etherface, &response, NULL);
|
||||
++xu->var->stats.loopf;
|
||||
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, response.msg, response.len, ((function == 1) ? "xu-loopbackreply" : "xu-loopbackforward"), DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
t_stat xu_process_local (CTLR* xu, ETH_PACK* pack)
|
||||
{
|
||||
return SCPE_NOFNC; /* not implemented yet */
|
||||
/* returns SCPE_OK if local processing occurred,
|
||||
otherwise returns SCPE_NOFNC or some other code */
|
||||
int protocol;
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_process_local()\n");
|
||||
|
||||
protocol = pack->msg[12] | (pack->msg[13] << 8);
|
||||
switch (protocol) {
|
||||
case 0x0090: /* ethernet loopback */
|
||||
return xu_process_loopback(xu, pack);
|
||||
break;
|
||||
case 0x0260: /* MOP remote console */
|
||||
return SCPE_NOFNC; /* not implemented yet */
|
||||
break;
|
||||
}
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
void xu_read_callback(CTLR* xu, int status)
|
||||
{
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, xu->var->read_buffer.msg, xu->var->read_buffer.len, "xu-recvd", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
/* process any packets locally that can be */
|
||||
status = xu_process_local (xu, &xu->var->read_buffer);
|
||||
|
||||
@@ -442,6 +529,8 @@ t_stat xu_system_id (CTLR* xu, const ETH_MAC dest, uint16 receipt_id)
|
||||
/* write system id */
|
||||
system_id.len = 60;
|
||||
status = eth_write(xu->var->etherface, &system_id, NULL);
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, system_id.msg, system_id.len, "xu-systemid", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -524,6 +613,7 @@ void xu_setclrint(CTLR* xu, int32 bits)
|
||||
t_stat xu_sw_reset (CTLR* xu)
|
||||
{
|
||||
t_stat status;
|
||||
int i;
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_sw_reset()\n");
|
||||
|
||||
@@ -559,10 +649,12 @@ t_stat xu_sw_reset (CTLR* xu)
|
||||
|
||||
/* reset ethernet interface */
|
||||
memcpy (xu->var->setup.macs[0], xu->var->mac, sizeof(ETH_MAC));
|
||||
xu->var->setup.mac_count = 1;
|
||||
for (i=0; i<6; i++)
|
||||
xu->var->setup.macs[1][i] = 0xff; /* Broadcast Address */
|
||||
xu->var->setup.mac_count = 2;
|
||||
if (xu->var->etherface)
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
&xu->var->mac, xu->var->setup.multicast,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
|
||||
/* activate device if not disabled */
|
||||
@@ -670,24 +762,24 @@ int32 xu_command(CTLR* xu)
|
||||
case FC_RMAL: /* read multicast address list */
|
||||
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
|
||||
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
||||
wstatus = Map_WriteB(udbb, mtlen * 3, (uint8*) &xu->var->setup.macs[1]);
|
||||
break;
|
||||
wstatus = Map_WriteB(udbb, mtlen * 3, (uint8*) &xu->var->setup.macs[2]);
|
||||
break;
|
||||
|
||||
case FC_WMAL: /* write multicast address list */
|
||||
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
|
||||
sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
|
||||
sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
|
||||
if (mtlen > 10)
|
||||
return PCSR0_PCEI;
|
||||
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
||||
/* clear existing multicast list */
|
||||
for (i=1; i<XU_FILTER_MAX; i++) {
|
||||
for (j=0; j<6; j++)
|
||||
xu->var->setup.macs[i][j] = 0;
|
||||
}
|
||||
/* get multicast list from host */
|
||||
rstatus = Map_ReadB(udbb, mtlen * 6, (uint8*) &xu->var->setup.macs[1]);
|
||||
/* clear existing multicast list */
|
||||
for (i=2; i<XU_FILTER_MAX; i++) {
|
||||
for (j=0; j<6; j++)
|
||||
xu->var->setup.macs[i][j] = 0;
|
||||
}
|
||||
/* get multicast list from host */
|
||||
rstatus = Map_ReadB(udbb, mtlen * 6, (uint8*) &xu->var->setup.macs[2]);
|
||||
if (rstatus == 0) {
|
||||
xu->var->setup.mac_count = mtlen + 1;
|
||||
xu->var->setup.mac_count = mtlen + 2;
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
@@ -807,7 +899,7 @@ sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
|
||||
case FC_WMODE: /* write mode register */
|
||||
value = xu->var->mode;
|
||||
xu->var->mode = xu->var->pcb[1];
|
||||
sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
|
||||
sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
|
||||
|
||||
/* set promiscuous and multicast flags */
|
||||
xu->var->setup.promiscuous = (xu->var->mode & MODE_PROM) ? 1 : 0;
|
||||
@@ -816,7 +908,7 @@ sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
|
||||
/* if promiscuous or multicast flags changed, change filter */
|
||||
if ((value ^ xu->var->mode) & (MODE_PROM | MODE_ENAL))
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
&xu->var->mac, xu->var->setup.multicast,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
break;
|
||||
|
||||
@@ -1151,6 +1243,11 @@ void xu_process_transmit(CTLR* xu)
|
||||
runt = 1;
|
||||
}
|
||||
|
||||
/* As described in the DEUNA User Guide (Section 4.7), the DEUNA is responsible
|
||||
for inserting the appropriate source MAC address in the outgoing packet header,
|
||||
so we do that now. */
|
||||
memcpy(xu->var->write_buffer.msg+6, (uint8*)&xu->var->setup.macs[0], sizeof(ETH_MAC));
|
||||
|
||||
/* are we in internal loopback mode ? */
|
||||
if ((xu->var->mode & MODE_LOOP) && (xu->var->mode & MODE_INTL)) {
|
||||
/* just put packet in receive buffer */
|
||||
@@ -1160,6 +1257,9 @@ void xu_process_transmit(CTLR* xu)
|
||||
wstatus = eth_write(xu->var->etherface, &xu->var->write_buffer, xu->var->wcallback);
|
||||
if (wstatus)
|
||||
xu->var->pcsr0 |= PCSR0_PCEI;
|
||||
else
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, xu->var->write_buffer.msg, xu->var->write_buffer.len, "xu-write", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
}
|
||||
|
||||
/* update transmit status in transmit buffer */
|
||||
@@ -1263,7 +1363,14 @@ void xu_port_command (CTLR* xu)
|
||||
break;
|
||||
|
||||
case CMD_SELFTEST: /* SELFTEST */
|
||||
xu_sw_reset(xu);
|
||||
/*
|
||||
SELFTEST is a <=15-second self diagnostic test, setting various
|
||||
error flags and the DONE (DNI) flag when complete. For simulation
|
||||
purposes, signal completion immediately with no errors. This
|
||||
inexact behavior could be incompatible with any guest machine
|
||||
diagnostics that are expecting to be able to monitor the
|
||||
controller's progress through the diagnostic testing.
|
||||
*/
|
||||
xu->var->pcsr0 |= PCSR0_DNI;
|
||||
break;
|
||||
|
||||
@@ -1348,7 +1455,7 @@ t_stat xu_rd(int32 *data, int32 PA, int32 access)
|
||||
*data = xu->var->pcsr3;
|
||||
break;
|
||||
}
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_rd(), PCSR%d, data=%04x\n", reg, *data);
|
||||
sim_debug(DBG_REG, xu->dev, "xu_rd(), PCSR%d, data=%04x\n", reg, *data);
|
||||
if (PA & 1)
|
||||
sim_debug(DBG_WRN, xu->dev, "xu_rd(), Unexpected Odd address access of PCSR%d\n", reg);
|
||||
return SCPE_OK;
|
||||
@@ -1375,7 +1482,7 @@ t_stat xu_wr(int32 data, int32 PA, int32 access)
|
||||
strcpy(desc, "Unknown");
|
||||
break;
|
||||
}
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_wr(), PCSR%d, data=%08x, PA=%08x, access=%d[%s]\n", reg, data, PA, access, desc);
|
||||
sim_debug(DBG_REG, xu->dev, "xu_wr(), PCSR%d, data=%08x, PA=%08x, access=%d[%s]\n", reg, data, PA, access, desc);
|
||||
switch (reg) {
|
||||
case 00:
|
||||
/* Clear write-one-to-clear interrupt bits */
|
||||
@@ -1458,6 +1565,15 @@ t_stat xu_attach(UNIT* uptr, char* cptr)
|
||||
xu->var->etherface = 0;
|
||||
return status;
|
||||
}
|
||||
if (SCPE_OK != eth_check_address_conflict (xu->var->etherface, &xu->var->mac)) {
|
||||
char buf[32];
|
||||
|
||||
eth_mac_fmt(&xu->var->mac, buf); /* format ethernet mac address */
|
||||
printf("%s: MAC Address Conflict on LAN for address %s\n", xu->dev->name, buf);
|
||||
if (sim_log) fprintf (sim_log, "%s: MAC Address Conflict on LAN for address %s\n", xu->dev->name, buf);
|
||||
eth_close(xu->var->etherface);
|
||||
return SCPE_NOATT;
|
||||
}
|
||||
uptr->filename = tptr;
|
||||
uptr->flags |= UNIT_ATT;
|
||||
eth_setcrc(xu->var->etherface, 1); /* enable CRC */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* pdp11_xu.h: DEUNA/DELUA ethernet controller information
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2003-2008, David T. Hittner
|
||||
Copyright (c) 2003-2005, David T. Hittner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
Modification history:
|
||||
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
08-Dec-05 DTH Added load_server, increased UDBSIZE for system ID parameters
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
05-Jan-04 DTH Added network statistics
|
||||
@@ -66,7 +67,7 @@ extern int32 int_req[IPL_HLVL];
|
||||
#include "sim_ether.h"
|
||||
|
||||
#define XU_QUE_MAX 500 /* message queue array */
|
||||
#define XU_FILTER_MAX 11 /* mac + 10 multicast addrs */
|
||||
#define XU_FILTER_MAX 12 /* mac + broadcast + 10 multicast addrs */
|
||||
#define XU_SERVICE_INTERVAL 100 /* times per second */
|
||||
#define XU_ID_TIMER_VAL 540 /* 9 min * 60 sec */
|
||||
#define UDBSIZE 200 /* max size of UDB (in words) */
|
||||
@@ -107,6 +108,7 @@ struct xu_stats {
|
||||
uint16 txccf; /* transmit collision test failure */
|
||||
uint16 porterr; /* port driver errors */
|
||||
uint16 bablcnt; /* babble counter */
|
||||
uint32 loopf; /* loopback frames processed */
|
||||
};
|
||||
|
||||
struct xu_device {
|
||||
@@ -300,7 +302,8 @@ typedef struct xu_controller CTLR;
|
||||
#define DBG_TRC 0x0001 /* trace routine calls */
|
||||
#define DBG_REG 0x0002 /* trace read/write registers */
|
||||
#define DBG_WRN 0x0004 /* display warnings */
|
||||
#define DBG_PCK 0x0080 /* display packets */
|
||||
#define DBG_PCK 0x0080 /* display packet headers */
|
||||
#define DBG_DAT 0x0100 /* display packet data */
|
||||
#define DBG_ETH 0x8000 /* debug ethernet device */
|
||||
|
||||
#endif /* _PDP11_XU_H */
|
||||
|
||||
Reference in New Issue
Block a user