mirror of
https://github.com/simh/simh.git
synced 2026-04-12 23:17:31 +00:00
Notes For V3.1-0
RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially debugged. Do NOT enable these features for normal operations. 1. New Features in 3.1-0 1.1 SCP and libraries - Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X. - Added status return to tmxr_putc_ln. - Added sim_putchar_s to handle possible output stalls. 1.2 All DECtapes - Added "DECtape off reel" error stop. 1.3 All Asynchronous Consoles - Added support for output congestion stall if using a Telnet connection. 1.4 PDP-1 - Added Type 23 parallel drum support. 1.5 PDP-8 - Added instruction history. - Added TSC8-75 option support for ETOS. - Added TD8E DECtape support. 1.6 PDP-18b - Added instruction history. - Changed PDP-9, PDP-15 API default to enabled. 1.7 PDP-11 - Added support for 18b only Qbus devices. - Formalized bus and addressing definitions. - Added control to enable/disable autoconfiguration. - Added stub support for second Unibus Ethernet controller. 1.7 Interdata 32b - Added instruction history. 1.8 Eclipse - Added floating point support. - Added programmable interval timer support. 1.9 H316 - Added DMA/DMC support. - Added fixed head disk support. - Added moving head disk support. - Added magtape support. 1.10 IBM 1130 (Brian Knittel) - Added support for physical card reader, using the Cardread interface (www.ibm1130.org/sim/downloads). - Added support for physical printer (flushes output buffer after each line). 2. Bugs Fixed in 3.1-0 2.1 SCP and libraries - Fixed numerous bugs in Ethernet library. 2.2 All DECtapes - Fixed reverse checksum value in 'read all' mode. - Simplified (and sped up) timing. 2.3 PDP-8 - Fixed bug in RX28 read status (found by Charles Dickman). - Fixed RX28 double density write. 2.4 PDP-18b - Fixed autoincrement bug in PDP-4, PDP-7, PDP-9. 2.5 PDP-11/VAX - Revised RQ MB->LBN conversion for greater accuracy. - Fixed bug in IO configuration (found by David Hittner). - Fixed bug with multiple RQ RAUSER drives. - Fixed bug in second Qbus Ethernet controller interrupts. 2.6 Nova/Eclipse - Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen). - Fixed bug in MT, reset completes despite I/O reset (Charles Owen). - Fixed bug in MT, space operations return word count (Charles Owen). 2.7 IBM 1130 (Brian Knittel) - Fixed bug in setting carry bit in subtract and subtract double. - Fixed timing problem in console printer simulation. 2.8 1620 - Fixed bug in branch digit (found by Dave Babcock). 3. New Features in 3.0 vs prior releases 3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support. 3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET <tape_unit> FORMAT=format sets the specified tape unit's format. - SHOW <tape_unit> FORMAT displays the specified tape unit's format. - Tape format can also be set as part of the ATTACH command, using the -F switch. 3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). 3.4 PDP-1 - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. - The LOAD command takes an optional argument specifying the memory field to be loaded. - The PTR BOOT command takes its starting memory field from the TA (address switch) register. 3.5 PDP-18b Family - Added PDP-4 EAE support. - Added PDP-15 FP15 support. - Added PDP-15 XVM support. - Added PDP-15 "re-entrancy ECO". - Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. 4. Bugs Fixed in 3.0 vs prior releases 4.1 SCP and Libraries - Fixed end of file problem in dep, idep. - Fixed handling of trailing spaces in dep, idep. 4.2 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: o First and second operands reversed o Separated fraction received wrong exponent o Overflow calculation on separated integer incorrect o Fraction not set to zero if exponent out of range - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.3 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. - Fixed chaining bug, D lost if return to SCP. - Fixed H branch, branch occurs after continue. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. - Revised fetch to model hardware more closely. - Fixed tape read end-of-record handling based on real 1401. - Added diagnostic read (space forward). 4.4 Nova - Fixed DSK variable size interaction with restore. - Fixed bug in DSK set size routine. 4.5 PDP-1 - Fixed DT variable size interaction with restore. - Updated CPU, line printer, standard devices to detect indefinite I/O wait. - Fixed incorrect logical, missing activate, break in drum simulator. - Fixed bugs in instruction decoding, overprinting for line printer. - Fixed system hang if continue after PTR error. - Fixed PTR to start/stop on successive rpa instructions. 4.6 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). - Added XQ features and fixed bugs: o Corrected XQ interrupts on IE state transition (code by Tom Evans). o Added XQ interrupt clear on soft reset. o Removed XQ interrupt when setting XL or RL (multiple people). o Added SET/SHOW XQ STATS. o Added SHOW XQ FILTERS. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.7 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. - Fixed bug in PDP-4 line printer overprinting. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. - Fixed priorities in PDP-15 API (differs from PDP-9). - Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). - Fixed bug in CAF, clears API subsystem. 4.8 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. - Fixed bug in DF, RF set size routine. 4.9 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. - Fixed DR drum sizes. - Fixed DR variable capacity interaction with SAVE/RESTORE. 4.10 GRI - Fixed bug in SC queue pointer management. 4.11 PDP-10 - Fixed bug in RP read header. 4.12 Ibm1130 - Fixed bugs found by APL 1130. 4.13 Altairz80 - Fixed bug in real-time clock on Windows host. 4.14 1620 - Fixed bug in immediate index add (found by Michael Short).
This commit is contained in:
committed by
Mark Pizzolato
parent
b2101ecdd4
commit
1da2d9452d
@@ -1,6 +1,6 @@
|
||||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
cpu PDP-11 CPU (J-11 microprocessor)
|
||||
|
||||
29-Dec-03 RMS Formalized 18b Qbus support
|
||||
21-Dec-03 RMS Added autoconfiguration controls
|
||||
05-Jun-03 RMS Fixed bugs in memory size table
|
||||
12-Mar-03 RMS Added logical name support
|
||||
01-Feb-03 RMS Changed R display to follow PSW<rs>, added SP display
|
||||
@@ -276,6 +278,7 @@ int32 stop_vecabort = 1; /* stop on vec abort */
|
||||
int32 stop_spabort = 1; /* stop on SP abort */
|
||||
int32 wait_enable = 0; /* wait state enable */
|
||||
int32 cpu_log = 0; /* logging */
|
||||
int32 autcon_enb = 1; /* autoconfig enable */
|
||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
int32 pcq_p = 0; /* PC queue ptr */
|
||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
@@ -323,6 +326,8 @@ void set_r_display (int32 rs, int32 cm);
|
||||
|
||||
extern t_stat build_dib_tab (int32 ubm);
|
||||
extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
extern t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
extern t_stat iopageR (int32 *data, uint32 addr, int32 access);
|
||||
extern t_stat iopageW (int32 data, uint32 addr, int32 access);
|
||||
extern int32 calc_ints (int32 nipl, int32 trq);
|
||||
@@ -532,6 +537,7 @@ REG cpu_reg[] = {
|
||||
{ GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
|
||||
{ GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
|
||||
{ BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) },
|
||||
{ FLDATA (AUTOCON, autcon_enb, 0), REG_HRO },
|
||||
{ BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
@@ -539,10 +545,10 @@ REG cpu_reg[] = {
|
||||
{ NULL} };
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL },
|
||||
{ UNIT_MAP, UNIT_18B, "18b Unibus", "U18", &cpu_set_bus },
|
||||
{ UNIT_MAP, UNIT_UBM, "22b Unibus + RH70", "URH70", &cpu_set_bus },
|
||||
{ UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", &cpu_set_bus },
|
||||
{ UNIT_MAP, 0, "22b addressing", "22B", &cpu_set_bus },
|
||||
{ UNIT_MAP, 0, "22b Qbus", "Q22", &cpu_set_bus },
|
||||
{ UNIT_CIS, UNIT_CIS, "CIS", "CIS", NULL },
|
||||
{ UNIT_CIS, 0, "no CIS", "NOCIS", NULL },
|
||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
||||
@@ -566,6 +572,10 @@ MTAB cpu_mod[] = {
|
||||
{ UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
||||
NULL, &show_iospace },
|
||||
{ MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",
|
||||
&set_autocon, &show_autocon },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",
|
||||
&set_autocon, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE cpu_dev = {
|
||||
@@ -2467,23 +2477,24 @@ for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1];
|
||||
free (M);
|
||||
M = nM;
|
||||
MEMSIZE = val;
|
||||
return cpu_set_bus (uptr, (cpu_unit.flags & UNIT_MAP) | 1, cptr, desc); }
|
||||
return cpu_set_bus (uptr, cpu_unit.flags, cptr, desc); }
|
||||
|
||||
/* Bus configuration, disable Unibus or Qbus devices */
|
||||
|
||||
t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
uint32 i, target;
|
||||
uint32 i, mask;
|
||||
|
||||
if ((MEMSIZE <= UNIMEMSIZE) || (val & UNIT_18B) ||
|
||||
(!(val & 1) && ((uint32) val == (cpu_unit.flags & UNIT_MAP)))) return SCPE_OK;
|
||||
if (val & UNIT_MAP) target = DEV_QBUS; /* going to Ubus? */
|
||||
else target = DEV_UBUS; /* going to Qbus */
|
||||
if ((val & UNIT_MAP) || (val & UNIT_18B)) /* Unibus variant? */
|
||||
mask = DEV_UBUS;
|
||||
else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus? */
|
||||
mask = DEV_QBUS | DEV_Q18;
|
||||
else mask = DEV_QBUS; /* must be 22b */
|
||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
if ((dptr->flags & DEV_DISABLE) && /* disable-able? */
|
||||
!(dptr->flags & DEV_DIS) && /* enabled? */
|
||||
((dptr->flags & (DEV_QBUS|DEV_UBUS)) == target)) {
|
||||
((dptr->flags & mask) == 0)) { /* not allowed? */
|
||||
printf ("Disabling %s\n", sim_dname (dptr));
|
||||
if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr));
|
||||
dptr->flags = dptr->flags | DEV_DIS; } }
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
22-Dec-03 RMS Added second DEUNA/DELUA support
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
19-May-03 RMS Revised for new conditional compilation
|
||||
05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark)
|
||||
28-Feb-03 RMS Added TM logging support
|
||||
@@ -295,6 +297,7 @@ typedef struct fpac fpac_t;
|
||||
#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */
|
||||
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
|
||||
#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */
|
||||
#define STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||
|
||||
/* Timers */
|
||||
@@ -312,9 +315,11 @@ typedef struct fpac fpac_t;
|
||||
|
||||
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
|
||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */
|
||||
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
|
||||
#define DEV_UBUS (1u << DEV_V_UBUS)
|
||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||
|
||||
#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */
|
||||
@@ -341,11 +346,13 @@ struct pdp_dib {
|
||||
|
||||
typedef struct pdp_dib DIB;
|
||||
|
||||
/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */
|
||||
/* I/O page layout - XUB, RQB,RQC,RQD float based on number of DZ's */
|
||||
|
||||
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
|
||||
#define IOLN_DZ 010
|
||||
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
|
||||
#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2)))
|
||||
#define IOLN_XUB 010
|
||||
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
|
||||
#define IOLN_RQB 004
|
||||
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
|
||||
#define IOLN_RQC 004
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-11 Simulator Usage
|
||||
Date: 15-Sep-2003
|
||||
Date: 15-Dec-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
@@ -127,6 +127,7 @@ The PDP-11 simulator implements several unique stop conditions:
|
||||
- trap condition 'n' occurs, and register STOP_TRAP<n> is set
|
||||
- wait state entered, and no I/O operations outstanding
|
||||
(ie, no interrupt can ever occur)
|
||||
- a simulated DECtape runs off the end of its reel
|
||||
|
||||
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
||||
is not implemented.
|
||||
@@ -289,11 +290,13 @@ In addition to autoconfiguration, most devices support the SET ADDRESS
|
||||
command, which allows the I/O page address of the device to be changed,
|
||||
and the SET VECTOR command, which allows the vector of the device to be
|
||||
changed. Explicitly setting the I/O address of a device which normally
|
||||
uses autoconfiguration DISABLES autoconfiguration for that device. As
|
||||
a consequence, the user may have to manually configure all other
|
||||
autoconfigured devices, because the autoconfiguration algorithm no
|
||||
longer recognizes the explicitly configured device. A device can be
|
||||
reset to autoconfigure with the SET <device> AUTOCONFIGURE command.
|
||||
uses autoconfiguration DISABLES autoconfiguration for that device and for
|
||||
the entire system. As a consequence, the user may have to manually configure
|
||||
all other autoconfigured devices, because the autoconfiguration algorithm
|
||||
no longer recognizes the explicitly configured device. A device can be
|
||||
reset to autoconfigure with the SET <device> AUTOCONFIGURE command. Auto-
|
||||
configuration can be restored for the entire system with the SET CPU
|
||||
AUTOCONFIGURE command.
|
||||
|
||||
The current I/O map can be displayed with the SHOW CPU IOSPACE command.
|
||||
Addresses that have set by autoconfiguration are marked with an asterisk (*).
|
||||
@@ -994,7 +997,6 @@ The TC controller implements these registers:
|
||||
IE 1 interrupt enable flag
|
||||
CTIME 31 time to complete transport stop
|
||||
LTIME 31 time between lines
|
||||
ACTIME 31 time to accelerate to full speed
|
||||
DCTIME 31 time to decelerate to a full stop
|
||||
SUBSTATE 2 read/write command substate
|
||||
POS[0:7] 32 position, in lines, units 0-7
|
||||
@@ -1005,8 +1007,9 @@ among the DECtape parameters, or the DECtape simulator will fail to
|
||||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
- DCTIME needs to be at least 100 times LTIME
|
||||
|
||||
Acceleration time is set to 75% of deceleration time.
|
||||
|
||||
2.9 Magnetic Tape Controllers
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
hk RK611/RK06/RK07 disk
|
||||
|
||||
29-Dec-03 RMS Added 18b Qbus support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
||||
This is a somewhat abstracted implementation of the RK611, more closely
|
||||
@@ -438,7 +439,7 @@ DEVICE hk_dev = {
|
||||
HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID,
|
||||
NULL, NULL, &hk_reset,
|
||||
&hk_boot, &hk_attach, &hk_detach,
|
||||
&hk_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routines, I/O addresses 17777440 - 17777476 */
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls
|
||||
21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner)
|
||||
12-Mar-03 RMS Added logical name support
|
||||
08-Oct-02 RMS Trimmed I/O bus addresses
|
||||
Added support for dynamic tables
|
||||
@@ -43,6 +45,7 @@ extern UNIT cpu_unit;
|
||||
extern int32 cpu_bme, cpu_18b, cpu_ubm;
|
||||
extern int32 trap_req, ipl;
|
||||
extern int32 cpu_log;
|
||||
extern int32 autcon_enb;
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[];
|
||||
|
||||
@@ -297,6 +300,24 @@ else { /* physical */
|
||||
return (lim - alim); }
|
||||
}
|
||||
|
||||
/* Enable/disable autoconfiguration */
|
||||
|
||||
t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr != NULL) return SCPE_ARG;
|
||||
autcon_enb = val;
|
||||
return auto_config (0, 0);
|
||||
}
|
||||
|
||||
/* Show autoconfiguration status */
|
||||
|
||||
t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, "autoconfiguration ");
|
||||
fprintf (st, autcon_enb? "enabled": "disabled");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change device address */
|
||||
|
||||
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
@@ -318,7 +339,8 @@ if ((newba <= IOPAGEBASE) || /* > IO page base? */
|
||||
(newba % ((uint32) val))) return SCPE_ARG; /* check modulus */
|
||||
dibp->ba = newba; /* store */
|
||||
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
||||
return auto_config (0, 0); /* autoconfigure */
|
||||
autcon_enb = 0; /* autoconfig off */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show device address */
|
||||
@@ -374,6 +396,8 @@ if ((r != SCPE_OK) || (newvec <= VEC_Q) ||
|
||||
((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) ||
|
||||
(newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG;
|
||||
dibp->vec = newvec;
|
||||
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
||||
autcon_enb = 0; /* autoconfig off */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -427,14 +451,20 @@ return FALSE;
|
||||
|
||||
/* Build interrupt tables */
|
||||
|
||||
void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) )
|
||||
t_bool build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) )
|
||||
{
|
||||
int32 ilvl = vloc / 32;
|
||||
int32 ibit = vloc % 32;
|
||||
|
||||
if (iack != NULL) int_ack[ilvl][ibit] = iack;
|
||||
else int_vec[ilvl][ibit] = ivec;
|
||||
return;
|
||||
if (iack != NULL) {
|
||||
if (int_ack[ilvl][ibit] &&
|
||||
(int_ack[ilvl][ibit] != iack)) return TRUE;
|
||||
int_ack[ilvl][ibit] = iack; }
|
||||
else if (ivec != 0) {
|
||||
if (int_vec[ilvl][ibit] &&
|
||||
(int_vec[ilvl][ibit] != ivec)) return TRUE;
|
||||
int_vec[ilvl][ibit] = ivec; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Build dib_tab from device list */
|
||||
@@ -453,9 +483,15 @@ for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
||||
if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR;
|
||||
for (k = 0; k < dibp->vnum; k++) /* loop thru vec */
|
||||
build_int_vec (dibp->vloc + k, /* add vector */
|
||||
dibp->vec + (k * 4), dibp->ack[k]);
|
||||
for (k = 0; k < dibp->vnum; k++) { /* loop thru vec */
|
||||
if (build_int_vec (dibp->vloc + k, /* add vector */
|
||||
dibp->vec + (k * 4), dibp->ack[k])) {
|
||||
printf ("Device %s interrupt slot conflict at %d\n",
|
||||
sim_dname (dptr), dibp->vloc + k);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Device %s interrupt slot conflict at %d\n",
|
||||
sim_dname (dptr), dibp->vloc + k);
|
||||
return SCPE_IERR; } }
|
||||
if (dibp->lnt != 0) { /* I/O addresses? */
|
||||
dib_tab[j++] = dibp; /* add DIB to dib_tab */
|
||||
if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */
|
||||
@@ -575,6 +611,7 @@ DIB *dibp;
|
||||
int32 i, j, k;
|
||||
extern DEVICE *find_dev (char *ptr);
|
||||
|
||||
if (autcon_enb == 0) return SCPE_OK; /* enabled? */
|
||||
if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */
|
||||
if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */
|
||||
for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_rk.c: RK11 cartridge disk simulator
|
||||
/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,8 +23,9 @@
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
rk RK11/RK05 cartridge disk
|
||||
rk RK11/RKV11/RK05 cartridge disk
|
||||
|
||||
29-Dec-03 RMS Added RKV11 support
|
||||
29-Sep-02 RMS Added variable address support to bootstrap
|
||||
Added vector change/display support
|
||||
Revised mapping mnemonics
|
||||
@@ -261,7 +262,7 @@ DEVICE rk_dev = {
|
||||
RK_NUMDR, 8, 24, 1, 8, 16,
|
||||
NULL, NULL, &rk_reset,
|
||||
&rk_boot, NULL, NULL,
|
||||
&rk_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&rk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17777400 - 17777416
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
rq RQDX3 disk controller
|
||||
|
||||
07-Oct-03 RMS Fixed problem with multiple RAUSER drives
|
||||
17-Sep-03 RMS Fixed MB to LBN conversion to be more accurate
|
||||
11-Jul-03 RMS Fixed bug in user disk size (found by Chaskiel M Grundman)
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
@@ -1422,7 +1424,8 @@ int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd)
|
||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
||||
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
||||
uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */
|
||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
||||
/* uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
||||
@@ -1866,6 +1869,7 @@ return;
|
||||
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
||||
{
|
||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
||||
|
||||
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
||||
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
||||
@@ -1878,7 +1882,7 @@ cp->pak[pkt].d[ONL_UIDD] = (UID_DISK << ONL_UIDD_V_CLS) |
|
||||
(drv_tab[dtyp].mod << ONL_UIDD_V_MOD); /* UID hi */
|
||||
PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */
|
||||
if (all) { /* if long form */
|
||||
PUTP32 (pkt, ONL_SIZL, drv_tab[dtyp].lbn); /* user LBNs */
|
||||
PUTP32 (pkt, ONL_SIZL, maxlbn); /* user LBNs */
|
||||
cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */
|
||||
cp->pak[pkt].d[ONL_VSNH] = 0; }
|
||||
return;
|
||||
@@ -2012,13 +2016,13 @@ if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
if (cptr) {
|
||||
cap = (int32) get_uint (cptr, 10, max, &r);
|
||||
if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG;
|
||||
drv_tab[val].lbn = cap << (20 - 9); }
|
||||
drv_tab[val].lbn = cap * 1954; }
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
||||
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show unit type (and capacity if user defined) */
|
||||
/* Show unit type */
|
||||
|
||||
t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
@@ -2034,7 +2038,6 @@ int32 dtyp = GET_DTYPE (uptr->flags);
|
||||
MSC *cp = rq_ctxmap[uptr->cnum];
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP;
|
||||
|
||||
@@ -121,7 +121,7 @@ int32 rx_cwait = 100; /* command time */
|
||||
int32 rx_swait = 10; /* seek, per track */
|
||||
int32 rx_xwait = 1; /* tr set time */
|
||||
uint8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */
|
||||
static int32 bptr = 0; /* buffer pointer */
|
||||
int32 rx_bptr = 0; /* buffer pointer */
|
||||
int32 rx_enb = 1; /* device enable */
|
||||
|
||||
DEVICE rx_dev;
|
||||
@@ -157,7 +157,7 @@ REG rx_reg[] = {
|
||||
{ ORDATA (RXTA, rx_track, 8) },
|
||||
{ ORDATA (RXSA, rx_sector, 8) },
|
||||
{ DRDATA (STAPTR, rx_state, 3), REG_RO },
|
||||
{ DRDATA (BUFPTR, bptr, 7) },
|
||||
{ DRDATA (BUFPTR, rx_bptr, 7) },
|
||||
{ FLDATA (INT, IREQ (RX), INT_V_RX) },
|
||||
{ FLDATA (ERR, rx_csr, RXCS_V_ERR) },
|
||||
{ FLDATA (TR, rx_csr, RXCS_V_TR) },
|
||||
@@ -237,7 +237,7 @@ case 0: /* RXCS */
|
||||
if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */
|
||||
rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC);
|
||||
drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */
|
||||
bptr = 0; /* clear buf pointer */
|
||||
rx_bptr = 0; /* clear buf pointer */
|
||||
switch (RXCS_GETFNC (data)) { /* case on func */
|
||||
case RXCS_FILL:
|
||||
rx_state = FILL; /* state = fill */
|
||||
@@ -287,10 +287,10 @@ return SCPE_OK;
|
||||
RWDS Save sector, set TR, set RWDT
|
||||
RWDT Save track, set RWXFR
|
||||
RWXFR Read/write buffer
|
||||
FILL copy ir to rx_buf[bptr], advance ptr
|
||||
if bptr > max, finish command, else set tr
|
||||
EMPTY if bptr > max, finish command, else
|
||||
copy rx_buf[bptr] to ir, advance ptr, set tr
|
||||
FILL copy ir to rx_buf[rx_bptr], advance ptr
|
||||
if rx_bptr > max, finish command, else set tr
|
||||
EMPTY if rx_bptr > max, finish command, else
|
||||
copy rx_buf[rx_bptr] to ir, advance ptr, set tr
|
||||
CMD_COMPLETE copy requested data to ir, finish command
|
||||
INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command
|
||||
|
||||
@@ -302,6 +302,7 @@ t_stat rx_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i, func;
|
||||
uint32 da;
|
||||
int8 *fbuf = uptr->filebuf;
|
||||
|
||||
func = RXCS_GETFNC (rx_csr); /* get function */
|
||||
switch (rx_state) { /* case on state */
|
||||
@@ -310,17 +311,17 @@ case IDLE: /* idle */
|
||||
return SCPE_IERR; /* done */
|
||||
|
||||
case EMPTY: /* empty buffer */
|
||||
if (bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */
|
||||
if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */
|
||||
else {
|
||||
rx_dbr = rx_buf[bptr]; /* get next */
|
||||
bptr = bptr + 1;
|
||||
rx_dbr = rx_buf[rx_bptr]; /* get next */
|
||||
rx_bptr = rx_bptr + 1;
|
||||
rx_csr = rx_csr | RXCS_TR; } /* set xfer */
|
||||
break;
|
||||
|
||||
case FILL: /* fill buffer */
|
||||
rx_buf[bptr] = rx_dbr; /* write next */
|
||||
bptr = bptr + 1;
|
||||
if (bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* if more, set xfer */
|
||||
rx_buf[rx_bptr] = rx_dbr; /* write next */
|
||||
rx_bptr = rx_bptr + 1;
|
||||
if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* more? set xfer */
|
||||
else rx_done (0, 0); /* else done */
|
||||
break;
|
||||
|
||||
@@ -350,13 +351,13 @@ case RWXFR:
|
||||
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
|
||||
if (func == RXCS_READ) { /* read? */
|
||||
for (i = 0; i < RX_NUMBY; i++)
|
||||
rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); }
|
||||
rx_buf[i] = fbuf[da + i]; }
|
||||
else {
|
||||
if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||
rx_done (RXES_WLK, 0100); /* done, error */
|
||||
break; }
|
||||
for (i = 0; i < RX_NUMBY; i++) /* write */
|
||||
*(((int8 *) uptr->filebuf) + da + i) = rx_buf[i];
|
||||
fbuf[da + i] = rx_buf[i];
|
||||
da = da + RX_NUMBY;
|
||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||
rx_done (0, 0); /* done */
|
||||
@@ -377,7 +378,7 @@ case INIT_COMPLETE: /* init complete */
|
||||
break; }
|
||||
da = CALC_DA (1, 1); /* track 1, sector 1 */
|
||||
for (i = 0; i < RX_NUMBY; i++) /* read sector */
|
||||
rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i);
|
||||
rx_buf[i] = fbuf[da + i];
|
||||
rx_done (RXES_ID, 0); /* set done */
|
||||
if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020;
|
||||
break; } /* end case state */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_ry.c: RY11/RX02 floppy disk simulator
|
||||
/* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,8 +23,9 @@
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
ry RY11/RX02 floppy disk
|
||||
ry RX211/RXV21/RX02 floppy disk
|
||||
|
||||
29-Dec-03 RMS Added RXV21 support
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
@@ -146,7 +147,6 @@ int32 ry_cwait = 100; /* command time */
|
||||
int32 ry_swait = 10; /* seek, per track */
|
||||
int32 ry_xwait = 1; /* tr set time */
|
||||
uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */
|
||||
int32 ry_enb = 0; /* device enable */
|
||||
|
||||
DEVICE ry_dev;
|
||||
t_stat ry_rd (int32 *data, int32 PA, int32 access);
|
||||
@@ -227,7 +227,7 @@ DEVICE ry_dev = {
|
||||
RX_NUMDR, 8, 20, 1, 8, 8,
|
||||
NULL, NULL, &ry_reset,
|
||||
&ry_boot, &ry_attach, NULL,
|
||||
&ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS };
|
||||
&ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17777170 - 17777172
|
||||
|
||||
@@ -341,6 +341,7 @@ t_stat ry_svc (UNIT *uptr)
|
||||
int32 i, t, func, bps;
|
||||
static uint8 estat[8];
|
||||
uint32 ba, da;
|
||||
int8 *fbuf = uptr->filebuf;
|
||||
|
||||
func = RYCS_GETFNC (ry_csr); /* get function */
|
||||
bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */
|
||||
@@ -401,12 +402,12 @@ case RWXFR: /* read/write */
|
||||
if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */
|
||||
if (func == RYCS_READ) { /* read? */
|
||||
for (i = 0; i < bps; i++)
|
||||
rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); }
|
||||
rx2xb[i] = fbuf[da + i]; }
|
||||
else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||
ry_done (0, 0100); /* done, error */
|
||||
break; }
|
||||
for (i = 0; i < bps; i++) /* write */
|
||||
*(((int8 *) uptr->filebuf) + da + i) = rx2xb[i];
|
||||
fbuf[da + i] = rx2xb[i];
|
||||
da = da + bps;
|
||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||
ry_done (0, 0); /* done */
|
||||
@@ -420,8 +421,7 @@ case SDCNF: /* confirm set density */
|
||||
sim_activate (uptr, ry_cwait * 100); /* schedule operation */
|
||||
break;
|
||||
case SDXFR: /* erase disk */
|
||||
for (i = 0; i < (int32) uptr->capac; i++)
|
||||
*(((int8 *) uptr->filebuf) + i) = 0;
|
||||
for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0;
|
||||
uptr->hwmark = uptr->capac;
|
||||
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
||||
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
||||
@@ -462,7 +462,7 @@ case INIT_COMPLETE: /* init complete */
|
||||
break; }
|
||||
da = CALC_DA (1, 1, bps); /* track 1, sector 1 */
|
||||
for (i = 0; i < bps; i++) /* read sector */
|
||||
rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i);
|
||||
rx2xb[i] = fbuf[da + i];
|
||||
ry_done (RYES_ID, 0); /* set done */
|
||||
if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020;
|
||||
break; } /* end case state */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -26,6 +26,7 @@
|
||||
tti,tto DL11 terminal input/output
|
||||
clk KW11L line frequency clock
|
||||
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
|
||||
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
||||
@@ -319,10 +320,12 @@ t_stat tto_svc (UNIT *uptr)
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
tto_csr = tto_csr | CSR_DONE;
|
||||
if (tto_csr & CSR_IE) SET_INT (TTO);
|
||||
c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar (c)) != SCPE_OK) return r;
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-Dec-03 RMS Added second DEUNA/DELUA support
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
06-May-03 RMS Added support for second DEQNA/DELQA
|
||||
09-Jan-03 RMS Added DELUA support
|
||||
09-Jan-03 RMS Added DELUA/DEUNA support
|
||||
17-Oct-02 RMS Fixed bugs in branch, SOB address parsing
|
||||
09-Oct-02 RMS Added DELQA support
|
||||
12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine
|
||||
@@ -64,7 +66,7 @@ extern DEVICE dt_dev;
|
||||
extern DEVICE tm_dev, ts_dev;
|
||||
extern DEVICE tq_dev;
|
||||
extern DEVICE xq_dev, xqb_dev;
|
||||
extern DEVICE xu_dev;
|
||||
extern DEVICE xu_dev, xub_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
@@ -113,6 +115,7 @@ DEVICE *sim_devices[] = {
|
||||
&xq_dev,
|
||||
&xqb_dev,
|
||||
&xu_dev,
|
||||
&xub_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
@@ -138,7 +141,8 @@ const char *sim_stop_messages[] = {
|
||||
"Trap vector fetch abort",
|
||||
"Trap stack push abort",
|
||||
"RQDX3 consistency error",
|
||||
"Sanity timer expired" };
|
||||
"Sanity timer expired"
|
||||
"DECtape off reel" };
|
||||
|
||||
/* Binary loader.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_tc.c: PDP-11 DECtape simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,10 @@
|
||||
|
||||
tc TC11/TU56 DECtape
|
||||
|
||||
29-Dec-03 RMS Changed initial status to disabled (in Qbus system)
|
||||
18-Oct-03 RMS Fixed reverse checksum in read all
|
||||
Added DECtape off reel message
|
||||
Simplified timing
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
29-Sep-02 RMS Added variable address support to bootstrap
|
||||
@@ -58,13 +62,16 @@
|
||||
When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format.
|
||||
|
||||
DECtape motion is measured in 3b lines. Time between lines is 33.33us.
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape is
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape (as
|
||||
taken from the TD8E formatter) is:
|
||||
|
||||
reverse end zone 36000 lines ~ 10 feet
|
||||
reverse end zone 8192 reverse end zone codes ~ 10 feet
|
||||
reverse buffer 200 interblock codes
|
||||
block 0
|
||||
:
|
||||
block n
|
||||
forward end zone 36000 lines ~ 10 feet
|
||||
forward buffer 200 interblock codes
|
||||
forward end zone 8192 forward end zone codes ~ 10 feet
|
||||
|
||||
A block consists of five 18b header words, a tape-specific number of data
|
||||
words, and five 18b trailer words. All systems except the PDP-8 use a
|
||||
@@ -79,9 +86,9 @@
|
||||
header word 0 0
|
||||
header word 1 block number (for forward reads)
|
||||
header words 2,3 0
|
||||
header word 4 0
|
||||
header word 4 checksum (for reverse reads)
|
||||
:
|
||||
trailer word 4 checksum
|
||||
trailer word 4 checksum (for forward reads)
|
||||
trailer words 3,2 0
|
||||
trailer word 1 block number (for reverse reads)
|
||||
trailer word 0 0
|
||||
@@ -106,13 +113,15 @@
|
||||
|
||||
/* System independent DECtape constants */
|
||||
|
||||
#define DT_EZLIN 36000 /* end zone length */
|
||||
#define DT_HTLIN 30 /* header/trailer lines */
|
||||
#define DT_BLKLN 6 /* blk no line in h/t */
|
||||
#define DT_CSMLN 24 /* checksum line in h/t */
|
||||
#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */
|
||||
#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */
|
||||
#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */
|
||||
#define DT_LPERMC 6 /* lines per mark track */
|
||||
#define DT_BLKWD 1 /* blk no word in h/t */
|
||||
#define DT_CSMWD 4 /* checksum word in h/t */
|
||||
#define DT_HTWRD 5 /* header/trailer words */
|
||||
#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */
|
||||
#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */
|
||||
#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */
|
||||
#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */
|
||||
#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */
|
||||
|
||||
/* 16b, 18b, 36b DECtape constants */
|
||||
|
||||
@@ -270,8 +279,7 @@ int32 tcba = 0; /* bus address */
|
||||
int32 tcdt = 0; /* data */
|
||||
int32 dt_ctime = 100; /* fast cmd time */
|
||||
int32 dt_ltime = 12; /* interline time */
|
||||
int32 dt_actime = 54000; /* accel time */
|
||||
int32 dt_dctime = 72000; /* decel time */
|
||||
int32 dt_dctime = 40000; /* decel time */
|
||||
int32 dt_substate = 0;
|
||||
int32 dt_logblk = 0;
|
||||
|
||||
@@ -340,7 +348,6 @@ REG dt_reg[] = {
|
||||
{ FLDATA (IE, tccm, CSR_V_DONE) },
|
||||
{ DRDATA (CTIME, dt_ctime, 31), REG_NZ },
|
||||
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
||||
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
|
||||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||
{ ORDATA (SUBSTATE, dt_substate, 1) },
|
||||
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
||||
@@ -371,7 +378,7 @@ DEVICE dt_dev = {
|
||||
DT_NUMDR + 1, 8, 24, 1, 8, 18,
|
||||
NULL, NULL, &dt_reset,
|
||||
&dt_boot, &dt_attach, &dt_detach,
|
||||
&dt_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&dt_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS };
|
||||
|
||||
/* IO dispatch routines, I/O addresses 17777340 - 17777350 */
|
||||
|
||||
@@ -523,7 +530,7 @@ if (new_fnc == FNC_SSEL) { /* stop unit? */
|
||||
if (prev_mot == DTS_STOP) { /* start? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* stop current */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
@@ -537,7 +544,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */
|
||||
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* cancel cur */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
@@ -674,11 +681,13 @@ case DTS_STOP: /* stop */
|
||||
delta = 0;
|
||||
break;
|
||||
case DTS_DECF: /* slowing */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = dt_dctime / dt_ltime;
|
||||
delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ACCF: /* accelerating */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime;
|
||||
delta = (ulin * ulin) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ATSF: /* at speed */
|
||||
@@ -715,7 +724,7 @@ t_stat dt_svc (UNIT *uptr)
|
||||
int32 mot = DTS_GETMOT (uptr->STATE);
|
||||
int32 dir = mot & DTS_DIR;
|
||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 blk, wrd, relpos, dat;
|
||||
uint32 ba, ma, mma;
|
||||
|
||||
@@ -728,10 +737,10 @@ uint32 ba, ma, mma;
|
||||
|
||||
switch (mot) {
|
||||
case DTS_DECF: case DTS_DECR: /* decelerating */
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
|
||||
if (uptr->STATE) /* not stopped? */
|
||||
sim_activate (uptr, dt_actime); /* must be reversing */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */
|
||||
return SCPE_OK;
|
||||
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
||||
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
||||
@@ -748,7 +757,7 @@ default: /* other */
|
||||
Off reel - detach unit (it must be deselected)
|
||||
*/
|
||||
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
if (DT_QEZ (uptr)) { /* in end zone? */
|
||||
dt_seterr (uptr, STA_END); /* end zone error */
|
||||
return SCPE_OK; }
|
||||
@@ -785,7 +794,7 @@ case FNC_READ: /* read */
|
||||
dt_seterr (uptr, STA_NXM);
|
||||
break; }
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */
|
||||
M[mma >> 1] = tcdt = fbuf[ba] & DMASK; /* read word */
|
||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
||||
@@ -822,7 +831,7 @@ case FNC_WRIT: /* write */
|
||||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
bptr[ba] = tcdt; /* write word */
|
||||
fbuf[ba] = tcdt; /* write word */
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
||||
if (tcwc == 0) dt_substate = 1;
|
||||
if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */
|
||||
@@ -844,7 +853,7 @@ case FNC_RALL:
|
||||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
dat = bptr[ba]; } /* get tape word */
|
||||
dat = fbuf[ba]; } /* get tape word */
|
||||
else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */
|
||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||
tcdt = dat & DMASK; /* low 16b */
|
||||
@@ -866,7 +875,7 @@ case FNC_WALL:
|
||||
dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */
|
||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
bptr[ba] = dat; /* write word */
|
||||
fbuf[ba] = dat; /* write word */
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; }
|
||||
/* else /* ignore hdr */
|
||||
sim_activate (uptr, DT_WSIZE * dt_ltime);
|
||||
@@ -941,13 +950,13 @@ return dat;
|
||||
|
||||
int32 dt_csum (UNIT *uptr, int32 blk)
|
||||
{
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 ba = blk * DTU_BSIZE (uptr);
|
||||
int32 i, csum, wrd;
|
||||
|
||||
csum = 077; /* init csum */
|
||||
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
|
||||
wrd = bptr[ba + i] ^ 0777777; /* get ~word */
|
||||
wrd = fbuf[ba + i] ^ 0777777; /* get ~word */
|
||||
csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; }
|
||||
return (csum & 077);
|
||||
}
|
||||
@@ -959,6 +968,7 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos)
|
||||
int32 wrd = relpos / DT_WSIZE;
|
||||
|
||||
if (wrd == DT_BLKWD) return blk; /* fwd blknum */
|
||||
if (wrd == DT_CSMWD) return 077; /* rev csum */
|
||||
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
|
||||
return (dt_csum (uptr, blk) << 12);
|
||||
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */
|
||||
@@ -1067,7 +1077,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, sz, k, *bptr;
|
||||
uint32 ba, sz, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
@@ -1089,7 +1099,7 @@ uptr->filebuf = calloc (uptr->capac, sizeof (int32));
|
||||
if (uptr->filebuf == NULL) { /* can't alloc? */
|
||||
detach_unit (uptr);
|
||||
return SCPE_MEM; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
||||
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
||||
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
||||
@@ -1101,9 +1111,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
if (k == 0) break;
|
||||
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
|
||||
bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
((uint32) (pdp8b[k + 1] >> 6) & 077);
|
||||
bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
|
||||
fbuf[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
|
||||
((uint32) (pdp8b[k + 2] & 07777));
|
||||
ba = ba + 2; } /* end blk loop */
|
||||
} /* end file loop */
|
||||
@@ -1114,7 +1124,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
if (k == 0) break;
|
||||
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
||||
for (k = 0; k < D18_BSIZE; k++)
|
||||
bptr[ba++] = pdp11b[k]; }
|
||||
fbuf[ba++] = pdp11b[k]; }
|
||||
uptr->hwmark = ba; } /* end elif */
|
||||
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
||||
uptr->capac, uptr->fileref);
|
||||
@@ -1137,7 +1147,7 @@ t_stat dt_detach (UNIT* uptr)
|
||||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, k, *bptr;
|
||||
uint32 ba, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
|
||||
@@ -1148,17 +1158,17 @@ if (sim_is_active (uptr)) { /* active? cancel op */
|
||||
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||
if (tccm & CSR_IE) SET_INT (DTA); }
|
||||
uptr->STATE = uptr->pos = 0; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
rewind (uptr->fileref); /* start of file */
|
||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||
pdp8b[k] = (bptr[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((bptr[ba] & 077) << 6) |
|
||||
((bptr[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = bptr[ba + 1] & 07777;
|
||||
pdp8b[k] = (fbuf[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) |
|
||||
((fbuf[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = fbuf[ba + 1] & 07777;
|
||||
ba = ba + 2; } /* end loop blk */
|
||||
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
@@ -1166,7 +1176,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
||||
pdp11b[k] = bptr[ba++] & DMASK;
|
||||
pdp11b[k] = fbuf[ba++] & DMASK;
|
||||
fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
} /* end if 16b */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_tm.c: PDP-11 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
tm TM11/TU10 magtape
|
||||
|
||||
29-Dec-03 RMS Added 18b Qbus support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library, added logging
|
||||
@@ -231,7 +232,7 @@ DEVICE tm_dev = {
|
||||
TM_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tm_reset,
|
||||
&tm_boot, &tm_attach, &tm_detach,
|
||||
&tm_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&tm_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17772520 - 17772532
|
||||
|
||||
|
||||
191
PDP11/pdp11_xq.c
191
PDP11/pdp11_xq.c
@@ -69,6 +69,27 @@
|
||||
|
||||
Modification history:
|
||||
|
||||
03-Dec-03 DTH Added minimum name length to show xq eth
|
||||
25-Nov-03 DTH Reworked interrupts to fix broken XQB implementation
|
||||
19-Nov-03 MP Rearranged timer reset sequencing to allow for a device to be
|
||||
disabled after it had been enabled.
|
||||
17-Nov-03 DTH Standardized #include of timeb.h
|
||||
28-Sep-03 MP - Fixed bug in xq_process_setup which would leave the
|
||||
device in promiscuous or all multicast mode once it
|
||||
ever had been there.
|
||||
- Fixed output format in show_xq_sanity to end in "\n"
|
||||
- Added display of All Multicase and promiscuous to
|
||||
xq_show_filters
|
||||
- The stuck in All Multicast or Promiscuous issue is
|
||||
worse than previously thought. See comments in
|
||||
xq_process_setup.
|
||||
- Change xq_setmac to also allow ":" as a address
|
||||
separator character, since sim_ether's eth_mac_fmt
|
||||
formats them with this separator character.
|
||||
- Changed xq_sw_reset to behave more like the set of
|
||||
actions described in Table 3-6 of the DELQA manua.
|
||||
The manual mentions "N/A" which I'm interpreting to
|
||||
mean "Not Affected".
|
||||
05-Jun-03 DTH Added receive packet splitting
|
||||
03-Jun-03 DTH Added SHOW XQ FILTERS
|
||||
02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing
|
||||
@@ -92,7 +113,7 @@
|
||||
of Receiver Enabled. This was an issue since the
|
||||
it seems that at least VMS's XQ driver makes this
|
||||
transition often and the resulting overhead reduces
|
||||
the simulated CPU instruction execution thruput by
|
||||
the simulated CPU instruction execution throughput by
|
||||
about 40%. I start the system id timer on device
|
||||
reset and it fires once a second so that it can
|
||||
leverage the reasonably recalibrated tmr_poll value.
|
||||
@@ -100,7 +121,7 @@
|
||||
dynamically computed clock values to achieve an
|
||||
approximate interval of 100 per second. This is
|
||||
more than sufficient for normal system behaviour
|
||||
expecially since we service recieves with every
|
||||
expecially since we service receives with every
|
||||
transmit. The previous fixed value of 2500
|
||||
attempted to get 200/sec but it was a guess that
|
||||
didn't adapt. On faster host systems (possibly
|
||||
@@ -128,7 +149,7 @@
|
||||
05-Dec-02 MP Restructured the flow of processing in xq_svc so that eth_read
|
||||
is called repeatedly until either a packet isn't found or
|
||||
there is no room for another one in the queue. Once that has
|
||||
been done, xq_processrdbl is called to pass the queued packets
|
||||
been done, xq_process_rdbl is called to pass the queued packets
|
||||
into the simulated system as space is available there.
|
||||
xq_process_rdbl is also called at the beginning of xq_svc to
|
||||
drain the queue into the simulated system, making more room
|
||||
@@ -216,8 +237,6 @@ t_stat xq_process_xbdl(CTLR* xq);
|
||||
t_stat xq_dispatch_xbdl(CTLR* xq);
|
||||
void xq_start_receiver(void);
|
||||
void xq_sw_reset(CTLR* xq);
|
||||
int32 xq_inta (void);
|
||||
int32 xq_intb (void);
|
||||
t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
void xq_start_santmr(CTLR* xq);
|
||||
@@ -230,6 +249,9 @@ void xqa_read_callback(int status);
|
||||
void xqb_read_callback(int status);
|
||||
void xqa_write_callback(int status);
|
||||
void xqb_write_callback(int status);
|
||||
void xq_setint (CTLR* xq);
|
||||
void xq_clrint (CTLR* xq);
|
||||
int32 xq_int (void);
|
||||
|
||||
struct xq_device xqa = {
|
||||
xqa_read_callback, /* read callback routine */
|
||||
@@ -249,7 +271,7 @@ struct xq_device xqb = {
|
||||
|
||||
/* SIMH device structures */
|
||||
DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr,
|
||||
1, IVCL (XQ), 0, { &xq_inta } };
|
||||
1, IVCL (XQ), 0, { &xq_int } };
|
||||
|
||||
UNIT xqa_unit[] = {
|
||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
||||
@@ -268,6 +290,7 @@ REG xqa_reg[] = {
|
||||
{ GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) },
|
||||
{ GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) },
|
||||
{ GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) },
|
||||
{ FLDATA ( INT, xqa.irq, 0) },
|
||||
{ GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_L1, xqa.setup.l1, XQ_RDX, 32, 0), REG_HRO},
|
||||
@@ -279,7 +302,7 @@ REG xqa_reg[] = {
|
||||
};
|
||||
|
||||
DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr,
|
||||
1, IVCL (XQ), 0, { &xq_intb } };
|
||||
1, IVCL (XQ), 0, { &xq_int } };
|
||||
|
||||
UNIT xqb_unit[] = {
|
||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
||||
@@ -298,6 +321,7 @@ REG xqb_reg[] = {
|
||||
{ GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) },
|
||||
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) },
|
||||
{ GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) },
|
||||
{ FLDATA ( INT, xqb.irq, 0) },
|
||||
{ GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_L1, xqb.setup.l1, XQ_RDX, 32, 0), REG_HRO},
|
||||
@@ -372,7 +396,7 @@ void xq_csr_changes(CTLR* xq, uint16 data);
|
||||
void xq_var_changes(CTLR* xq, uint16 data);
|
||||
|
||||
/* sanity timer debugging */
|
||||
#include <sys\timeb.h>
|
||||
#include <sys/timeb.h>
|
||||
struct timeb start, finish;
|
||||
|
||||
#endif /* XQ_DEBUG */
|
||||
@@ -575,7 +599,9 @@ t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||
if (len != 17) return SCPE_ARG;
|
||||
/* make sure byte separators are OK */
|
||||
for (i=2; i<len; i=i+3) {
|
||||
if ((cptr[i] != '-') && (cptr[i] != '.')) return SCPE_ARG;
|
||||
if ((cptr[i] != '-') &&
|
||||
(cptr[i] != '.') &&
|
||||
(cptr[i] != ':')) return SCPE_ARG;
|
||||
cptr[i] = '\0';
|
||||
}
|
||||
/* get and set address bytes */
|
||||
@@ -601,15 +627,17 @@ t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc)
|
||||
t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
#define XQ_MAX_LIST 10
|
||||
int i;
|
||||
ETH_LIST list[XQ_MAX_LIST];
|
||||
int number = eth_devices(XQ_MAX_LIST, list);
|
||||
|
||||
fprintf(st, "ETH devices:\n");
|
||||
if (number)
|
||||
if (number) {
|
||||
int i, min, len;
|
||||
for (i=0, min=0; i<number; i++)
|
||||
if ((len = strlen(list[i].name)) > min) min = len;
|
||||
for (i=0; i<number; i++)
|
||||
fprintf(st," %d %s (%s)\n", i, list[i].name, list[i].desc);
|
||||
else
|
||||
fprintf(st," %d %-*s (%s)\n", i, min, list[i].name, list[i].desc);
|
||||
} else
|
||||
fprintf(st, " no network devices are available\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -662,6 +690,10 @@ t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
eth_mac_fmt((ETH_MAC*)xq->var->setup.macs[i], buffer);
|
||||
fprintf(st, " [%2d]: %s\n", i, buffer);
|
||||
};
|
||||
if (xq->var->setup.multicast)
|
||||
fprintf(st, "All Multicast Receive Mode\n");
|
||||
if (xq->var->setup.promiscuous)
|
||||
fprintf(st, "Promiscuous Receive Mode\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -695,8 +727,8 @@ t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
|
||||
fprintf(st, "sanity=");
|
||||
switch (xq->var->sanity.enabled) {
|
||||
case 0: fprintf(st, "OFF"); break;
|
||||
case 1: fprintf(st, "ON"); break;
|
||||
case 0: fprintf(st, "OFF\n"); break;
|
||||
case 1: fprintf(st, "ON\n"); break;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -724,7 +756,7 @@ t_stat xq_nxm_error(CTLR* xq)
|
||||
|
||||
/* interrupt if required */
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -761,7 +793,7 @@ void xq_write_callback (CTLR* xq, int status)
|
||||
/* update csr */
|
||||
xq->var->csr |= XQ_CSR_XI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* reset sanity timer */
|
||||
xq_reset_santmr(xq);
|
||||
@@ -846,7 +878,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||
uint16 b_length, w_length, rbl;
|
||||
uint32 address;
|
||||
struct xq_msg_itm* item;
|
||||
char* rbuf;
|
||||
uint8* rbuf;
|
||||
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name);
|
||||
@@ -906,7 +938,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||
#endif
|
||||
/* pad runts with zeros up to minimum size - this allows "legal" (size - 60)
|
||||
processing of those weird short ARP packets that seem to occur occasionally */
|
||||
memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET);
|
||||
memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET-rbl);
|
||||
rbl = ETH_MIN_PACKET;
|
||||
};
|
||||
|
||||
@@ -976,7 +1008,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_RI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* set to next bdl (implicit chain) */
|
||||
xq->var->rbdl_ba += 12;
|
||||
@@ -1059,15 +1091,42 @@ t_stat xq_process_setup(CTLR* xq)
|
||||
xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)];
|
||||
}
|
||||
|
||||
/*
|
||||
Under VMS the setup packet that is passed to turn promiscuous
|
||||
off after it has been on doesn't seem to follow the rules documented
|
||||
in both the DEQNA and DELQA manuals.
|
||||
These rules seem to say that setup packets less than 128 should only
|
||||
modify the address filter set and probably not the All-Multicast and
|
||||
Promiscuous modes, however, VMS V5-5 and V7.3 seem to send a 127 byte
|
||||
packet to turn this functionality off. I'm not sure how real hardware
|
||||
behaves in this case, since the only consequence is extra interrupt
|
||||
load. To realize and retain the benefits of the newly added BPF
|
||||
functionality in sim_ether, I've modified the logic implemented here
|
||||
to disable Promiscuous mode when a "small" setup packet is processed.
|
||||
I'm deliberately not modifying the All-Multicast mode the same way
|
||||
since I don't have an observable case of its behavior. These two
|
||||
different modes come from very different usage situations:
|
||||
1) Promiscuous mode is usually entered for relatively short periods
|
||||
of time due to the needs of a specific application program which
|
||||
is doing some sort of management/monitoring function (i.e. tcpdump)
|
||||
2) All-Multicast mode is only entered by the OS Kernel Port Driver
|
||||
when it happens to have clients (usually network stacks or service
|
||||
programs) which as a group need to listen to more multicast ethernet
|
||||
addresses than the 12 (or so) which the hardware supports directly.
|
||||
so, I believe that the All-Multicast mode, is first rarely used, and if
|
||||
it ever is used, once set, it will probably be set either forever or for
|
||||
long periods of time, and the additional interrupt processing load to
|
||||
deal with the distinctly lower multicast traffic set is clearly lower than
|
||||
that of the promiscuous mode.
|
||||
*/
|
||||
xq->var->setup.promiscuous = 0;
|
||||
/* process high byte count */
|
||||
if (xq->var->write_buffer.len > 128) {
|
||||
uint16 len = xq->var->write_buffer.len;
|
||||
uint16 led, san;
|
||||
|
||||
if (len & XQ_SETUP_MC)
|
||||
xq->var->setup.multicast = 1;
|
||||
if (len & XQ_SETUP_PM)
|
||||
xq->var->setup.promiscuous = 1;
|
||||
xq->var->setup.multicast = (0 != (len & XQ_SETUP_MC));
|
||||
xq->var->setup.promiscuous = (0 != (len & XQ_SETUP_PM));
|
||||
if (led = (len & XQ_SETUP_LD) >> 2) {
|
||||
switch (led) {
|
||||
case 1: xq->var->setup.l1 = 0; break;
|
||||
@@ -1214,7 +1273,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_XI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* now trigger "read" of setup or loopback packet */
|
||||
if (~xq->var->csr & XQ_CSR_RL)
|
||||
@@ -1446,13 +1505,26 @@ void xq_sw_reset(CTLR* xq)
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* clear CPU interrupts */
|
||||
CLR_INT(XQ);
|
||||
xq_clrint(xq);
|
||||
|
||||
/* flush read queue */
|
||||
xq_clear_queue(&xq->var->ReadQ);
|
||||
|
||||
/* clear setup info */
|
||||
memset (&xq->var->setup, 0, sizeof(xq->var->setup));
|
||||
xq->var->setup.multicast = 0;
|
||||
xq->var->setup.promiscuous = 0;
|
||||
if (xq->var->etherface) {
|
||||
int count = 0;
|
||||
ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
|
||||
ETH_MAC filters[XQ_FILTER_MAX + 1];
|
||||
|
||||
/* set ethernet filter */
|
||||
/* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */
|
||||
for (i = 0; i < XQ_FILTER_MAX; i++)
|
||||
if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC)))
|
||||
memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC));
|
||||
eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous);
|
||||
}
|
||||
}
|
||||
|
||||
/* write registers: */
|
||||
@@ -1676,7 +1748,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_RI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* reset sanity timer */
|
||||
xq_reset_santmr(xq);
|
||||
@@ -1724,8 +1796,8 @@ t_stat xq_wr_csr(CTLR* xq, int32 data)
|
||||
/* check and correct CPU interrupt state */
|
||||
old_int_state = (saved_csr & XQ_CSR_IE) && (saved_csr & (XQ_CSR_XI | XQ_CSR_RI));
|
||||
new_int_state = (xq->var->csr & XQ_CSR_IE) && (xq->var->csr & (XQ_CSR_XI | XQ_CSR_RI));
|
||||
if ( old_int_state && !new_int_state) CLR_INT(XQ);
|
||||
if (!old_int_state && new_int_state) SET_INT(XQ);
|
||||
if ( old_int_state && !new_int_state) xq_clrint(xq);
|
||||
if (!old_int_state && new_int_state) xq_setint(xq);
|
||||
|
||||
#ifdef VM_PDP11
|
||||
/* request boot/diagnostic rom? [PDP-11 only] */
|
||||
@@ -1803,12 +1875,6 @@ t_stat xq_reset(DEVICE* dptr)
|
||||
/* init control status register */
|
||||
xq->var->csr = XQ_CSR_RL | XQ_CSR_XL;
|
||||
|
||||
/* reset ethernet interface */
|
||||
if (xq->var->etherface) {
|
||||
status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0);
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
}
|
||||
|
||||
/* init read queue (first time only) */
|
||||
status = xq_init_queue (xq, &xq->var->ReadQ);
|
||||
if (status != SCPE_OK)
|
||||
@@ -1817,6 +1883,11 @@ t_stat xq_reset(DEVICE* dptr)
|
||||
/* clear read queue */
|
||||
xq_clear_queue(&xq->var->ReadQ);
|
||||
|
||||
/* reset ethernet interface */
|
||||
if (xq->var->etherface) {
|
||||
status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0);
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* start sanity timer if power-on SANITY is set */
|
||||
switch (xq->var->type) {
|
||||
case XQ_T_DEQNA:
|
||||
@@ -1830,6 +1901,8 @@ t_stat xq_reset(DEVICE* dptr)
|
||||
xq_start_idtmr(xq);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -1841,11 +1914,9 @@ void xq_start_santmr(CTLR* xq)
|
||||
/* must be recalculated each time since tmr_poll is a dynamic number */
|
||||
const int32 quarter_sec = (clk_tps * tmr_poll) / 4;
|
||||
|
||||
#if 0
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n",
|
||||
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll);
|
||||
#endif
|
||||
#endif
|
||||
if (sim_is_active(xq_santmr)) /* cancel timer, just in case */
|
||||
sim_cancel(xq_santmr);
|
||||
@@ -1897,12 +1968,10 @@ t_stat xq_sansvc(UNIT* uptr)
|
||||
If this section is entered, it means that the sanity timer has expired
|
||||
without being reset, and the controller must reboot the processor.
|
||||
*/
|
||||
#if 0
|
||||
#ifdef XQ_DEBUG
|
||||
ftime(&finish);
|
||||
fprintf(stderr,"%s: SANITY TIMER EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n",
|
||||
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll, finish.time - start.time);
|
||||
#endif
|
||||
#endif
|
||||
xq_boot_host();
|
||||
}
|
||||
@@ -1944,6 +2013,9 @@ t_stat xq_system_id (CTLR* xq, const ETH_MAC dest, uint16 receipt_id)
|
||||
uint8* const msg = &system_id.msg[0];
|
||||
t_stat status;
|
||||
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: SYSTEM ID BROADCAST\n", xq->dev->name);
|
||||
#endif
|
||||
memset (&system_id, 0, sizeof(system_id));
|
||||
memcpy (&msg[0], dest, sizeof(ETH_MAC));
|
||||
memcpy (&msg[6], xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC));
|
||||
@@ -2089,6 +2161,9 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
|
||||
/* turn on transceiver power indicator */
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* reset the device with the new attach info */
|
||||
xq_reset(xq->dev);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -2098,6 +2173,7 @@ t_stat xq_detach(UNIT* uptr)
|
||||
{
|
||||
t_stat status;
|
||||
CTLR* xq = xq_unit2ctlr(uptr);
|
||||
int i;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) {
|
||||
status = eth_close (xq->var->etherface);
|
||||
@@ -2106,6 +2182,9 @@ t_stat xq_detach(UNIT* uptr)
|
||||
free(uptr->filename);
|
||||
uptr->filename = NULL;
|
||||
uptr->flags &= ~UNIT_ATT;
|
||||
/* cancel all timers (ethernet, sanity, system_id) */
|
||||
for (i=0; i<3; i++)
|
||||
sim_cancel(&xq->unit[i]);
|
||||
}
|
||||
|
||||
/* turn off transceiver power indicator */
|
||||
@@ -2114,14 +2193,38 @@ t_stat xq_detach(UNIT* uptr)
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int32 xq_inta (void)
|
||||
void xq_setint(CTLR* xq)
|
||||
{
|
||||
return xqa_dib.vec;
|
||||
xq->var->irq = 1;
|
||||
SET_INT(XQ);
|
||||
return;
|
||||
}
|
||||
|
||||
int32 xq_intb (void)
|
||||
void xq_clrint(CTLR* xq)
|
||||
{
|
||||
return xqb_dib.vec;
|
||||
int i;
|
||||
xq->var->irq = 0; /* set controller irq off */
|
||||
/* clear master interrupt? */
|
||||
for (i=0; i<XQ_MAX_CONTROLLERS; i++) /* check all controllers.. */
|
||||
if (xq_ctrl[i].var->irq) { /* if any irqs enabled */
|
||||
SET_INT(XQ); /* set master interrupt on */
|
||||
return;
|
||||
}
|
||||
CLR_INT(XQ); /* clear master interrupt */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 xq_int (void)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<XQ_MAX_CONTROLLERS; i++) {
|
||||
CTLR* xq = &xq_ctrl[i];
|
||||
if (xq->var->irq) { /* if interrupt pending */
|
||||
xq_clrint(xq); /* clear interrupt */
|
||||
return xq->dib->vec; /* return vector */
|
||||
}
|
||||
}
|
||||
return 0; /* no interrupt request active */
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
Modification history:
|
||||
|
||||
25-Nov-03 DTH Added interrupt request flag
|
||||
02-Jun-03 DTH Added struct xq_stats
|
||||
28-May-03 DTH Made xq_msg_que.item dynamic
|
||||
28-May-03 MP Optimized structures, removed rtime variable
|
||||
@@ -152,6 +153,7 @@ struct xq_device {
|
||||
uint16 xbdl[2];
|
||||
uint16 var;
|
||||
uint16 csr;
|
||||
uint32 irq; /* interrupt request flag */
|
||||
|
||||
/* buffers, etc. */
|
||||
struct xq_setup setup;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
xu DEUNA/DELUNA Ethernet interface (stub)
|
||||
|
||||
22-Dec-03 RMS Added second (stub) device
|
||||
*/
|
||||
|
||||
#if defined (VM_PDP10) /* PDP10 version */
|
||||
@@ -61,3 +63,29 @@ DEVICE xu_dev = {
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
&xu_dib, DEV_DIS | DEV_UBUS };
|
||||
|
||||
#if defined (VM_PDP11)
|
||||
|
||||
/* XUB data structures
|
||||
|
||||
xub_dev XUB device descriptor
|
||||
xub_unit XUB unit list
|
||||
xub_reg XUB register list
|
||||
*/
|
||||
|
||||
DIB xub_dib = { IOBA_XUB, IOLN_XUB, NULL, NULL,
|
||||
1, IVCL (XU), VEC_XU, { NULL } };
|
||||
|
||||
UNIT xub_unit = { UDATA (NULL, 0, 0) };
|
||||
|
||||
REG xub_reg[] = {
|
||||
{ NULL } };
|
||||
|
||||
DEVICE xub_dev = {
|
||||
"XUB", &xub_unit, xub_reg, NULL,
|
||||
1, 8, 8, 1, 8, 8,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
&xub_dib, DEV_DIS | DEV_UBUS };
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user