Merge branch 'master' into Extra-VAXen
This commit is contained in:
commit
a3973f0e8c
12 changed files with 290 additions and 92 deletions
|
@ -142,8 +142,7 @@ Most *nix platforms have these APIs available and on these platforms
|
|||
simh is typically built with these available since on these platforms,
|
||||
pthreads is required for simh networking support. Windows can also
|
||||
utilize the pthreads APIs if the compile and run time support for the
|
||||
win32Pthreads package has been installed on the build system and the
|
||||
run time dll is available in the execution environment.
|
||||
win32Pthreads package has been installed on the build system.
|
||||
|
||||
Sample Asynch I/O device implementations.
|
||||
The pdp11_rq.c module has been refactored to leverage the asynch I/O
|
||||
|
|
|
@ -1689,6 +1689,16 @@ t_stat xq_process_loopback(CTLR* xq, ETH_PACK* pack)
|
|||
physical_address = &xq->var->setup.macs[0];
|
||||
else
|
||||
physical_address = &xq->var->mac;
|
||||
|
||||
/* The only packets we should be responding to are ones which
|
||||
we received due to them being directed to our physical MAC address,
|
||||
OR the Broadcast address OR to a Multicast address we're listening to
|
||||
(we may receive others if we're in promiscuous mode, but shouldn't
|
||||
respond to them) */
|
||||
if ((0 == (pack->msg[0]&1)) && /* Multicast or Broadcast */
|
||||
(0 != memcmp(physical_address, pack->msg, sizeof(ETH_MAC))))
|
||||
return SCPE_NOFNC;
|
||||
|
||||
memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC));
|
||||
offset += 8 - 16; /* Account for the Ethernet Header and Offset value in this number */
|
||||
|
|
|
@ -416,6 +416,17 @@ t_stat xu_process_loopback(CTLR* xu, ETH_PACK* pack)
|
|||
/* create forward response packet */
|
||||
memcpy (&response, pack, sizeof(ETH_PACK));
|
||||
memcpy (physical_address, xu->var->setup.macs[0], sizeof(ETH_MAC));
|
||||
|
||||
/* The only packets we should be responding to are ones which
|
||||
we received due to them being directed to our physical MAC address,
|
||||
OR the Broadcast address OR to a Multicast address we're listening to
|
||||
(we may receive others if we're in promiscuous mode, but shouldn't
|
||||
respond to them) */
|
||||
if ((0 == (pack->msg[0]&1)) && /* Multicast or Broadcast */
|
||||
(0 != memcmp(physical_address, pack->msg, sizeof(ETH_MAC))))
|
||||
return SCPE_NOFNC;
|
||||
|
||||
|
||||
memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC));
|
||||
offset += 8;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef ROM_vax780_vmb_exe_H
|
||||
#define ROM_vax780_vmb_exe_H 0
|
||||
/*
|
||||
VAX/vax780_vmb_exe.h produced at Tue Sep 20 04:39:17 2011
|
||||
from VAX/vmb.exe which was last modified at Tue Sep 20 03:24:44 2011
|
||||
file size: 44544 (0xAE00)
|
||||
VAX/vax780_vmb_exe.h produced at Sun Feb 26 12:32:44 2012
|
||||
from VAX/vmb.exe which was last modified at Sat Feb 18 00:01:12 2012
|
||||
file size: 44544 (0xAE00) - checksum: 0xFFC014CC
|
||||
*/
|
||||
unsigned char vax780_vmb_exe[] = {
|
||||
0xD4,0xEF,0x34,0x61,0x00,0x00,0x17,0xEF,0xB8,0x5D,0x00,0x00,0xC1,0xAB,0x38,0xAB,
|
||||
|
@ -2788,3 +2790,4 @@ unsigned char vax780_vmb_exe[] = {
|
|||
0x4C,0x52,0x45,0x41,0x44,0x3A,0x58,0x2D,0x32,0x20,0x20,0x43,0x4F,0x4E,0x49,0x4F,
|
||||
0x3A,0x58,0x2D,0x33,0x20,0x20,0x2A,0x45,0x6E,0x64,0x20,0x6F,0x66,0x20,0x49,0x64,
|
||||
0x65,0x6E,0x74,0x20,0x6C,0x69,0x73,0x74,0x73,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,};
|
||||
#endif /* ROM_vax780_vmb_exe_H */
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#ifndef ROM_vax_ka655x_bin_H
|
||||
#define ROM_vax_ka655x_bin_H 0
|
||||
/*
|
||||
VAX/vax_ka655x_bin.h produced at Tue Sep 20 04:39:07 2011
|
||||
from VAX/ka655x.bin which was last modified at Tue Sep 20 03:24:43 2011
|
||||
file size: 131072 (0x20000)
|
||||
VAX/vax_ka655x_bin.h produced at Sun Feb 26 12:32:44 2012
|
||||
from VAX/ka655x.bin which was last modified at Sat Feb 18 00:01:12 2012
|
||||
file size: 131072 (0x20000) - checksum: 0xFF7673B6
|
||||
*/
|
||||
unsigned char vax_ka655x_bin[] = {
|
||||
0x11,0x22,0x11,0xFE,0x02,0x03,0x53,0x01,0x31,0x89,0x03,0x00,0x31,0x8B,0x03,0x00,
|
||||
|
@ -8196,3 +8198,4 @@ unsigned char vax_ka655x_bin[] = {
|
|||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
|
||||
#endif /* ROM_vax_ka655x_bin_H */
|
||||
|
|
119
makefile
119
makefile
|
@ -28,7 +28,9 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
|||
ifeq ($(GCC),)
|
||||
GCC = gcc
|
||||
endif
|
||||
ifeq (SunOS,$(shell uname))
|
||||
OSTYPE = $(shell uname)
|
||||
OSNAME = $(OSTYPE)
|
||||
ifeq (SunOS,$(OSTYPE))
|
||||
TEST = /bin/test
|
||||
else
|
||||
TEST = test
|
||||
|
@ -40,14 +42,16 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
|||
INCPATH:=/usr/include
|
||||
LIBPATH:=/usr/lib
|
||||
OS_CCDEFS = -D_GNU_SOURCE
|
||||
ifeq (Darwin,$(shell uname))
|
||||
ifeq (Darwin,$(OSTYPE))
|
||||
OSNAME = OSX
|
||||
LIBEXT = dylib
|
||||
else
|
||||
ifeq (Linux,$(shell uname))
|
||||
ifeq (Linux,$(OSTYPE))
|
||||
LIBPATH := $(sort $(foreach lib,$(shell /sbin/ldconfig -p | grep ' => /' | sed 's/^.* => //'),$(dir $(lib))))
|
||||
LIBEXT = so
|
||||
else
|
||||
ifeq (SunOS,$(shell uname))
|
||||
ifeq (SunOS,$(OSTYPE))
|
||||
OSNAME = Solaris
|
||||
LIBPATH := $(shell crle | grep 'Default Library Path' | awk '{ print $$5 }' | sed 's/:/ /g')
|
||||
LIBEXT = so
|
||||
OS_LDFLAGS += -lsocket -lnsl
|
||||
|
@ -68,7 +72,7 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
|||
LIBPATH += /usr/pkg/lib
|
||||
OS_LDFLAGS += -L/usr/pkg/lib -R/usr/pkg/lib
|
||||
endif
|
||||
ifneq (,$(findstring NetBSD,$(shell uname))$(findstring FreeBSD,$(shell uname)))
|
||||
ifneq (,$(findstring NetBSD,$(OSTYPE))$(findstring FreeBSD,$(OSTYPE)))
|
||||
LIBEXT = so
|
||||
else
|
||||
LIBEXT = a
|
||||
|
@ -104,49 +108,41 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
|||
OS_LDFLAGS += -ldl
|
||||
$(info using libdl: $(call find_lib,dl) $(call find_include,dlfcn))
|
||||
else
|
||||
ifeq (BSD,$(findstring BSD,$(shell uname)))
|
||||
ifeq (BSD,$(findstring BSD,$(OSTYPE)))
|
||||
OS_CCDEFS += -DHAVE_DLOPEN=so
|
||||
$(info using libdl: $(call find_include,dlfcn))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(call find_include,pcap))
|
||||
ifneq (,$(call find_lib,pcap))
|
||||
ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line
|
||||
NETWORK_CCDEFS = -DUSE_NETWORK
|
||||
NETWORK_LDFLAGS = -lpcap
|
||||
$(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap))
|
||||
else # default build uses dynamic libpcap
|
||||
# building the pdp11, or any vax simulator could use networking support
|
||||
ifneq (,$(or $(findstring pdp11,$(MAKECMDGOALS)),$(findstring vax,$(MAKECMDGOALS)),$(findstring all,$(MAKECMDGOALS))))
|
||||
NETWORK_USEFUL = true
|
||||
else
|
||||
ifeq ($(MAKECMDGOALS),)
|
||||
# default target is all
|
||||
NETWORK_USEFUL = true
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(NETWORK_USEFUL))
|
||||
ifneq (,$(call find_include,pcap))
|
||||
ifneq (,$(call find_lib,pcap))
|
||||
ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line
|
||||
NETWORK_CCDEFS = -DUSE_NETWORK
|
||||
NETWORK_LDFLAGS = -lpcap
|
||||
$(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap))
|
||||
else # default build uses dynamic libpcap
|
||||
NETWORK_CCDEFS = -DUSE_SHARED
|
||||
$(info using libpcap: $(call find_include,pcap))
|
||||
endif
|
||||
$(info *** Simulator(s) being built with networking support using)
|
||||
$(info *** $(OSTYPE) provided libpcap components)
|
||||
else
|
||||
NETWORK_CCDEFS = -DUSE_SHARED
|
||||
$(info using libpcap: $(call find_include,pcap))
|
||||
$(info *** Simulator(s) being built with networking support using)
|
||||
$(info *** $(OSTYPE) provided libpcap components)
|
||||
endif
|
||||
else
|
||||
NETWORK_CCDEFS = -DUSE_SHARED
|
||||
$(info using libpcap: $(call find_include,pcap))
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(call find_lib,vdeplug))
|
||||
ifneq (,$(call find_include,libvdeplug))
|
||||
# Provide support for vde networking
|
||||
NETWORK_CCDEFS += -DUSE_VDE_NETWORK
|
||||
NETWORK_LDFLAGS += -lvdeplug
|
||||
$(info using libvdeplug: $(call find_lib,vdeplug) $(call find_include,libvdeplug))
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(call find_include,linux/if_tun))
|
||||
# Provide support for Tap networking on Linux
|
||||
NETWORK_CCDEFS += -DUSE_TAP_NETWORK
|
||||
endif
|
||||
ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi))
|
||||
# Provide support for Tap networking on BSD platforms (including OS X)
|
||||
NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP
|
||||
endif
|
||||
ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi))
|
||||
MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi
|
||||
endif
|
||||
NETWORK_OPT = $(NETWORK_CCDEFS)
|
||||
ifneq ($(USE_NETWORK),) # Network support specified on the GNU make command line
|
||||
ifneq (USE_NETWORK,$(findstring USE_NETWORK,$(NETWORK_CCDEFS)))
|
||||
# Look for package built from tcpdump.org sources with default install target
|
||||
LIBPATH += /usr/local/lib
|
||||
INCPATH += /usr/local/include
|
||||
|
@ -154,16 +150,55 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin)
|
|||
LIBEXT = a
|
||||
ifneq (,$(call find_lib,pcap))
|
||||
ifneq (,$(call find_include,pcap))
|
||||
NETWORK_OPT := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,pcap)
|
||||
NETWORK_CCDEFS := -DUSE_NETWORK -isystem $(dir $(call find_include,pcap)) $(call find_lib,pcap)
|
||||
$(info using libpcap: $(call find_lib,pcap) $(call find_include,pcap))
|
||||
$(info *** Warning ***)
|
||||
$(info *** Warning *** Simulator(s) being built with networking support using)
|
||||
$(info *** Warning *** libpcap components from www.tcpdump.org.)
|
||||
$(info *** Warning *** Some users have had problems using the www.tcpdump.org libpcap)
|
||||
$(info *** Warning *** components for simh networking. For best results, with)
|
||||
$(info *** Warning *** simh networking, it is recommended that you install the)
|
||||
$(info *** Warning *** libpcap-dev package from your $(OSTYPE) distribution)
|
||||
$(info *** Warning ***)
|
||||
else
|
||||
$(error using libpcap: $(call find_lib,pcap) missing pcap.h)
|
||||
endif
|
||||
LIBEXT = $(LIBEXTSAVE)
|
||||
else
|
||||
$(error missing libpcap)
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(findstring USE_NETWORK,$(NETWORK_CCDEFS))$(findstring USE_SHARED,$(NETWORK_CCDEFS)))
|
||||
# Given we have libpcap components, consider other network connections as well
|
||||
ifneq (,$(call find_lib,vdeplug))
|
||||
# libvdeplug requires the use of the OS provided libpcap
|
||||
ifeq (,$(findstring usr/local,$(NETWORK_CCDEFS)))
|
||||
ifneq (,$(call find_include,libvdeplug))
|
||||
# Provide support for vde networking
|
||||
NETWORK_CCDEFS += -DUSE_VDE_NETWORK
|
||||
NETWORK_LDFLAGS += -lvdeplug
|
||||
$(info using libvdeplug: $(call find_lib,vdeplug) $(call find_include,libvdeplug))
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(call find_include,linux/if_tun))
|
||||
# Provide support for Tap networking on Linux
|
||||
NETWORK_CCDEFS += -DUSE_TAP_NETWORK
|
||||
endif
|
||||
ifeq (bsdtuntap,$(shell if $(TEST) -e /usr/include/net/if_tun.h -o -e /Library/Extensions/tap.kext; then echo bsdtuntap; fi))
|
||||
# Provide support for Tap networking on BSD platforms (including OS X)
|
||||
NETWORK_CCDEFS += -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP
|
||||
endif
|
||||
else
|
||||
$(info *** Warning ***)
|
||||
$(info *** Warning *** Simulator(s) are being built WITHOUT networking support)
|
||||
$(info *** Warning ***)
|
||||
$(info *** Warning *** To build simulator(s) with networking support you should install)
|
||||
$(info *** Warning *** the libpcap-dev package from your $(OSTYPE) distribution)
|
||||
$(info *** Warning ***)
|
||||
endif
|
||||
NETWORK_OPT = $(NETWORK_CCDEFS)
|
||||
endif
|
||||
ifneq (binexists,$(shell if $(TEST) -e BIN; then echo binexists; fi))
|
||||
MKDIRBIN = if $(TEST) ! -e BIN; then mkdir BIN; fi
|
||||
endif
|
||||
else
|
||||
#Win32 Environments (via MinGW32)
|
||||
|
|
2
scp.c
2
scp.c
|
@ -3965,6 +3965,8 @@ if (!initialized) {
|
|||
handle = dlopen("libncurses." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL);
|
||||
handle = dlopen("libcurses." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL);
|
||||
handle = dlopen("libreadline." __STR(HAVE_DLOPEN), RTLD_NOW|RTLD_GLOBAL);
|
||||
if (!handle)
|
||||
handle = dlopen("libreadline." __STR(HAVE_DLOPEN) ".6", RTLD_NOW|RTLD_GLOBAL);
|
||||
if (handle) {
|
||||
p_readline = dlsym(handle, "readline");
|
||||
p_add_history = dlsym(handle, "add_history");
|
||||
|
|
|
@ -53,7 +53,9 @@
|
|||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
int sim_make_ROM_include(const char *rom_filename,
|
||||
int sim_make_ROM_include(const char *rom_filename,
|
||||
int expected_size,
|
||||
int expected_checksum,
|
||||
const char *include_filename,
|
||||
const char *rom_array_name)
|
||||
{
|
||||
|
@ -64,24 +66,44 @@ int bytes_written = 0;
|
|||
int c;
|
||||
struct stat statb;
|
||||
unsigned char *ROMData = NULL;
|
||||
unsigned int checksum = 0;
|
||||
|
||||
if (NULL == (rFile = fopen (rom_filename, "rb"))) {
|
||||
printf ("Error Opening '%s' for input: %s\n", rom_filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (stat (rom_filename, &statb)) {
|
||||
printf ("Error Stating '%s': %s\n", rom_filename, strerror(errno));
|
||||
printf ("Error stating '%s': %s\n", rom_filename, strerror(errno));
|
||||
fclose (rFile);
|
||||
return -1;
|
||||
}
|
||||
if (statb.st_size != expected_size) {
|
||||
printf ("Error: ROM file '%s' has an unexpected size: %d vs %d\n", rom_filename, (int)statb.st_size, expected_size);
|
||||
printf ("This can happen if the file was transferred or unpacked incorrectly\n");
|
||||
printf ("and in the process tried to convert line endings rather than passing\n");
|
||||
printf ("the file's contents unmodified\n");
|
||||
fclose (rFile);
|
||||
return -1;
|
||||
}
|
||||
ROMData = malloc (statb.st_size);
|
||||
if (statb.st_size != fread (ROMData, sizeof(*ROMData), statb.st_size, rFile)) {
|
||||
printf ("Error Stating '%s': %s\n", rom_filename, strerror(errno));
|
||||
printf ("Error reading '%s': %s\n", rom_filename, strerror(errno));
|
||||
fclose (rFile);
|
||||
free (ROMData);
|
||||
return -1;
|
||||
}
|
||||
fclose (rFile);
|
||||
for (c=0; c<statb.st_size; ++c)
|
||||
checksum += ROMData[c];
|
||||
checksum = ~checksum;
|
||||
if ((expected_checksum != 0) && (checksum != expected_checksum)) {
|
||||
printf ("Error: ROM file '%s' has an unexpected checksum: 0x%08X vs 0x%08X\n", rom_filename, checksum, expected_checksum);
|
||||
printf ("This can happen if the file was transferred or unpacked incorrectly\n");
|
||||
printf ("and in the process tried to convert line endings rather than passing\n");
|
||||
printf ("the file's contents unmodified\n");
|
||||
fclose (rFile);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* If the target include file already exists, determine if it contains the exact
|
||||
* data in the base ROM image. If so, then we are already done
|
||||
|
@ -130,7 +152,7 @@ fprintf (iFile, "#define ROM_%s_H 0\n", rom_array_name);
|
|||
fprintf (iFile, "/*\n");
|
||||
fprintf (iFile, " %s produced at %s", include_filename, ctime(&now));
|
||||
fprintf (iFile, " from %s which was last modified at %s", rom_filename, ctime(&statb.st_mtime));
|
||||
fprintf (iFile, " file size: %d (0x%X)\n", (int)statb.st_size, (int)statb.st_size);
|
||||
fprintf (iFile, " file size: %d (0x%X) - checksum: 0x%08X\n", (int)statb.st_size, (int)statb.st_size, checksum);
|
||||
fprintf (iFile, "*/\n");
|
||||
fprintf (iFile, "unsigned char %s[] = {", rom_array_name);
|
||||
for (bytes_written=0;bytes_written<statb.st_size; ++bytes_written) {
|
||||
|
@ -156,7 +178,8 @@ return 0;
|
|||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
sim_make_ROM_include ("VAX/ka655x.bin", "VAX/vax_ka655x_bin.h", "vax_ka655x_bin");
|
||||
sim_make_ROM_include ("VAX/vmb.exe", "VAX/vax780_vmb_exe.h", "vax780_vmb_exe");
|
||||
exit(0);
|
||||
int status = 0;
|
||||
status += sim_make_ROM_include ("VAX/ka655x.bin", 131072, 0xFF7673B6, "VAX/vax_ka655x_bin.h", "vax_ka655x_bin");
|
||||
status += sim_make_ROM_include ("VAX/vmb.exe", 44544, 0xFFC014CC, "VAX/vax780_vmb_exe.h", "vax780_vmb_exe");
|
||||
exit((status == 0) ? 0 : 1);
|
||||
}
|
||||
|
|
|
@ -930,6 +930,13 @@ static HANDLE std_input;
|
|||
static HANDLE std_output;
|
||||
static DWORD saved_mode;
|
||||
|
||||
/* Note: This routine catches all the potential events which some aspect
|
||||
of the windows system can generate. The CTRL_C_EVENT won't be
|
||||
generated by a user typing in a console session since that
|
||||
session is in RAW mode. In general, Ctrl-C on a simulator's
|
||||
console terminal is a useful character to be passed to the
|
||||
simulator. This code does nothing to disable or affect that. */
|
||||
|
||||
static BOOL WINAPI
|
||||
ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
|
|
|
@ -2132,6 +2132,7 @@ typedef struct _VHD_DynamicDiskHeader {
|
|||
} VHD_DynamicDiskHeader;
|
||||
|
||||
#define VHD_BAT_FREE_ENTRY (0xFFFFFFFF)
|
||||
#define VHD_DATA_BLOCK_ALIGNMENT ((uint64)4096) /* Optimum when underlying storage has 4k sectors */
|
||||
|
||||
static char *VHD_DiskTypes[] =
|
||||
{
|
||||
|
@ -3214,6 +3215,14 @@ while (sects) {
|
|||
BitMap = malloc(BitMapSectors*SectorSize);
|
||||
memset(BitMap, 0xFF, BitMapBytes);
|
||||
BlockOffset -= sizeof(hVHD->Footer);
|
||||
/* align the data portion of the block to the desired alignment */
|
||||
/* compute the address of the data portion of the block */
|
||||
BlockOffset += BitMapSectors*SectorSize;
|
||||
/* round up this address to the desired alignment */
|
||||
BlockOffset += VHD_DATA_BLOCK_ALIGNMENT-1;
|
||||
BlockOffset &= ~(VHD_DATA_BLOCK_ALIGNMENT-1);
|
||||
/* the actual block address is the beginning of the block bitmap */
|
||||
BlockOffset -= BitMapSectors*SectorSize;
|
||||
hVHD->BAT[BlockNumber] = NtoHl((uint32)(BlockOffset/SectorSize));
|
||||
if (WriteFilePosition(hVHD->File,
|
||||
BitMap,
|
||||
|
|
136
sim_ether.c
136
sim_ether.c
|
@ -560,7 +560,7 @@ char* eth_getname(int number, char* name)
|
|||
ETH_LIST list[ETH_MAX_DEVICE];
|
||||
int count = eth_devices(ETH_MAX_DEVICE, list);
|
||||
|
||||
if (count <= number) return 0;
|
||||
if (count <= number) return NULL;
|
||||
strcpy(name, list[number].name);
|
||||
return name;
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ char* eth_getname_bydesc(char* desc, char* name)
|
|||
return name;
|
||||
}
|
||||
/* not found */
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* strncasecmp() is not available on all platforms */
|
||||
|
@ -621,16 +621,13 @@ char* eth_getname_byname(char* name, char* temp)
|
|||
found = 0;
|
||||
n = strlen(name);
|
||||
for (i=0; i<count && !found; i++) {
|
||||
if (eth_strncasecmp(name, list[i].name, n) == 0) {
|
||||
if ((n == strlen(list[i].name)) &&
|
||||
(eth_strncasecmp(name, list[i].name, n) == 0)) {
|
||||
found = 1;
|
||||
strcpy(temp, list[i].name); /* only case might be different */
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
return temp;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (found ? temp : NULL);
|
||||
}
|
||||
|
||||
void eth_zero(ETH_DEV* dev)
|
||||
|
@ -657,7 +654,7 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|||
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, (int)min, list[i].name, list[i].desc);
|
||||
fprintf(st," %2d %-*s (%s)\n", i, (int)min, list[i].name, list[i].desc);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -1452,16 +1449,16 @@ if ((strlen(name) == 4)
|
|||
) {
|
||||
num = atoi(&name[3]);
|
||||
savname = eth_getname(num, temp);
|
||||
if (savname == 0) /* didn't translate */
|
||||
if (savname == NULL) /* didn't translate */
|
||||
return SCPE_OPENERR;
|
||||
}
|
||||
else {
|
||||
/* are they trying to use device description? */
|
||||
savname = eth_getname_bydesc(name, temp);
|
||||
if (savname == 0) { /* didn't translate */
|
||||
if (savname == NULL) { /* didn't translate */
|
||||
/* probably is not ethX and has no description */
|
||||
savname = eth_getname_byname(name, temp);
|
||||
if (savname == 0) /* didn't translate */
|
||||
if (savname == NULL) /* didn't translate */
|
||||
savname = name;
|
||||
}
|
||||
}
|
||||
|
@ -1724,6 +1721,66 @@ char mac_string[32];
|
|||
eth_mac_fmt(mac, mac_string);
|
||||
sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string);
|
||||
|
||||
/* The process of checking address conflicts is used in two ways:
|
||||
1) to determine the behavior of the currently running packet
|
||||
delivery facility regarding whether it may receive copies
|
||||
of every packet sent (and how many).
|
||||
2) to verify if a MAC address which this facility is planning
|
||||
to use as the source address of packets is already in use
|
||||
by some other node on the local network
|
||||
Case #1, doesn't require (and explicitly doesn't want) any
|
||||
interaction or response from other systems on the LAN so
|
||||
therefore no considerations regarding switch packet forwarding
|
||||
are important. Meanwhile, Case #2 does require responses from
|
||||
other components on the LAN to provide useful functionality.
|
||||
The original designers of this mechanism did this when essentially
|
||||
all LANs were single collision domains (i.e. ALL nodes which might
|
||||
be affected by an address conflict were physically present on a single
|
||||
Ethernet cable which might have been extended by a couple of repeaters).
|
||||
Since that time, essentially no networks are single collision domains.
|
||||
Thick and thinwire Ethernet cables don’t exist and very few networks
|
||||
even have hubs. Today, essentially all LANs are deployed using one
|
||||
or more layers of network switches. In a switched LAN environment, the
|
||||
switches on the LAN ‘learn’ which ports on the LAN source traffic from
|
||||
which MAC addresses and then forward traffic destined for particular
|
||||
MAC address to the appropriate ports. If a particular MAC address is
|
||||
already in use somewhere on the LAN, then the switches ‘know’ where
|
||||
it is. The host based test using the loopback protocol is poorly
|
||||
designed to detect this condition. This test is performed by the host
|
||||
first changing the device’s Physical MAC address to the address which
|
||||
is to be tested, and then sending a loopback packet FROM AND TO this
|
||||
MAC address with a loopback reply to be sent by a system which may be
|
||||
currently using the MAC address. If no reply is received, then the
|
||||
MAC address is presumed to be unused. The sending of this packet will
|
||||
result in its delivery to the right system since the switch port/MAC
|
||||
address tables know where to deliver packets destined to this MAC
|
||||
address, however the response it generates won’t be delivered to the
|
||||
system performing the test since the switches on the LAN won’t know
|
||||
about the local port being the right target for packets with this MAC
|
||||
address. A better test design to detect these conflicts would be for
|
||||
the testing system to send a loopback packet FROM the current physical
|
||||
MAC address (BEFORE changing it) TO the MAC address being tested with
|
||||
the loopback response coming to the current physical MAC address of
|
||||
the device. If a response is received, then the address is in use and
|
||||
the attempt to change the device’s MAC address should fail. Since we
|
||||
can’t change the software running in these simulators to implement this
|
||||
better conflict detection approach, we can still ‘do the right thing’
|
||||
in the sim_ether layer. We’re already handling the loopback test
|
||||
packets specially since we always had to avoid receiving the packets
|
||||
which were being sent, but needed to allow for the incoming loopback
|
||||
packets to be properly dealt with. We can extend this current special
|
||||
handling to change outgoing ‘loopback to self’ packets to have source
|
||||
AND loopback destination addresses in the packets to be the host NIC’s
|
||||
physical address. The switch network will already know the correct
|
||||
MAC/port relationship for the host NIC’s physical address, so loopback
|
||||
response packets will be delivered as needed.
|
||||
|
||||
Code in _eth_write and _eth_callback provide the special handling to
|
||||
perform the described loopback packet adjustments, and code in
|
||||
eth_filter_hash makes sure that the loopback response packets are received.
|
||||
|
||||
*/
|
||||
|
||||
/* build a loopback forward request packet */
|
||||
memset (&send, 0, sizeof(ETH_PACK));
|
||||
send.len = ETH_MIN_PACKET; /* minimum packet size */
|
||||
|
@ -1743,7 +1800,7 @@ if (status != SCPE_OK) {
|
|||
char *msg;
|
||||
msg = "Eth: Error Transmitting packet: %s\r\n"
|
||||
"You may need to run as root, or install a libpcap version\r\n"
|
||||
"which is at least 0.9 from www.tcpdump.org\r\n";
|
||||
"which is at least 0.9 from your OS vendor or www.tcpdump.org\r\n";
|
||||
printf(msg, strerror(errno));
|
||||
if (sim_log) fprintf (sim_log, msg, strerror(errno));
|
||||
return status;
|
||||
|
@ -1755,7 +1812,10 @@ sim_os_ms_sleep (300); /* time for a conflicting host to respond */
|
|||
do {
|
||||
memset (&recv, 0, sizeof(ETH_PACK));
|
||||
status = eth_read (dev, &recv, NULL);
|
||||
if (memcmp(send.msg, recv.msg, 14)== 0)
|
||||
if (((0 == memcmp(send.msg+12, recv.msg+12, 2)) && /* Protocol Match */
|
||||
(0 == memcmp(send.msg, recv.msg+6, 6)) && /* Source Match */
|
||||
(0 == memcmp(send.msg+6, recv.msg, 6))) || /* Destination Match */
|
||||
(0 == memcmp(send.msg, recv.msg, 14))) /* Packet Match (Reflection) */
|
||||
responses++;
|
||||
} while (recv.len > 0);
|
||||
|
||||
|
@ -1792,12 +1852,16 @@ if (!packet) return SCPE_ARG;
|
|||
|
||||
/* make sure packet is acceptable length */
|
||||
if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) {
|
||||
int loopback_self_frame = LOOPBACK_SELF_FRAME(dev->physical_addr, packet->msg);
|
||||
int loopback_self_frame = LOOPBACK_SELF_FRAME(packet->msg, packet->msg);
|
||||
|
||||
eth_packet_trace (dev, packet->msg, packet->len, "writing");
|
||||
|
||||
/* record sending of loopback packet (done before actual send to avoid race conditions with receiver) */
|
||||
if (loopback_self_frame) {
|
||||
if (dev->have_host_nic_phy_addr) {
|
||||
memcpy(&packet->msg[6], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC));
|
||||
memcpy(&packet->msg[18], dev->host_nic_phy_hw_addr, sizeof(ETH_MAC));
|
||||
}
|
||||
#ifdef USE_READER_THREAD
|
||||
pthread_mutex_lock (&dev->self_lock);
|
||||
#endif
|
||||
|
@ -1806,7 +1870,7 @@ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) {
|
|||
#ifdef USE_READER_THREAD
|
||||
pthread_mutex_unlock (&dev->self_lock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* dispatch write request (synchronous; no need to save write info to dev) */
|
||||
switch (dev->eth_api) {
|
||||
|
@ -2346,6 +2410,17 @@ int from_me = 0;
|
|||
int i;
|
||||
int bpf_used;
|
||||
|
||||
if ((dev->have_host_nic_phy_addr) &&
|
||||
(LOOPBACK_PHYSICAL_RESPONSE(dev->host_nic_phy_hw_addr, dev->physical_addr, data))) {
|
||||
u_char *datacopy = malloc(header->len);
|
||||
|
||||
memcpy(datacopy, data, header->len);
|
||||
memcpy(datacopy, dev->physical_addr, sizeof(ETH_MAC));
|
||||
memcpy(datacopy+18, dev->physical_addr, sizeof(ETH_MAC));
|
||||
_eth_callback(info, header, datacopy);
|
||||
free(datacopy);
|
||||
return;
|
||||
}
|
||||
switch (dev->eth_api) {
|
||||
case ETH_API_PCAP:
|
||||
#ifdef USE_BPF
|
||||
|
@ -2380,7 +2455,9 @@ switch (dev->eth_api) {
|
|||
}
|
||||
|
||||
/* detect reception of loopback packet to our physical address */
|
||||
if (LOOPBACK_SELF_FRAME(dev->physical_addr, data)) {
|
||||
if ((LOOPBACK_SELF_FRAME(dev->physical_addr, data)) ||
|
||||
(dev->have_host_nic_phy_addr &&
|
||||
LOOPBACK_PHYSICAL_REFLECTION(dev->host_nic_phy_hw_addr, data))) {
|
||||
#ifdef USE_READER_THREAD
|
||||
pthread_mutex_lock (&dev->self_lock);
|
||||
#endif
|
||||
|
@ -2397,7 +2474,7 @@ if (LOOPBACK_SELF_FRAME(dev->physical_addr, data)) {
|
|||
#ifdef USE_READER_THREAD
|
||||
pthread_mutex_unlock (&dev->self_lock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (bpf_used ? to_me : (to_me && !from_me)) {
|
||||
if (header->len > ETH_MIN_JUMBO_FRAME) {
|
||||
|
@ -2689,6 +2766,10 @@ if ((addr_count) && (dev->reflections > 0)) {
|
|||
memcpy(dev->physical_addr, &dev->filter_address[i], sizeof(ETH_MAC));
|
||||
/* let packets through where dst and src are the same as our physical address */
|
||||
sprintf (&buf[strlen(buf)], " or ((ether dst %s) and (ether src %s))", mac, mac);
|
||||
if (dev->have_host_nic_phy_addr) {
|
||||
eth_mac_fmt(&dev->host_nic_phy_hw_addr, mac);
|
||||
sprintf(&buf[strlen(buf)], "or ((ether dst %s) and (ether proto 0x9000))", mac);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2697,8 +2778,10 @@ if ((0 == strlen(buf)) && (!dev->promiscuous)) /* Empty filter means match nothi
|
|||
strcpy(buf, "ether host fe:ff:ff:ff:ff:ff"); /* this should be a good match nothing filter */
|
||||
sim_debug(dev->dbit, dev->dptr, "BPF string is: |%s|\n", buf);
|
||||
|
||||
/* get netmask, which is required for compiling */
|
||||
if ((dev->eth_api == ETH_API_PCAP) && (pcap_lookupnet(dev->handle, &bpf_subnet, &bpf_netmask, errbuf)<0))
|
||||
/* get netmask, which is a required argument for compiling. The value,
|
||||
in our case isn't actually interesting since the filters we generate
|
||||
aren't referencing IP fields, networks or values */
|
||||
if ((dev->eth_api == ETH_API_PCAP) && (pcap_lookupnet(dev->name, &bpf_subnet, &bpf_netmask, errbuf)<0))
|
||||
bpf_netmask = 0;
|
||||
|
||||
#ifdef USE_BPF
|
||||
|
@ -2823,7 +2906,6 @@ for (i=0; i<used; i++) {
|
|||
|
||||
#ifdef USE_TAP_NETWORK
|
||||
if (used < max) {
|
||||
list[used].num = used;
|
||||
#if defined(__OpenBSD__)
|
||||
sprintf(list[used].name, "%s", "tap:tunN");
|
||||
#else
|
||||
|
@ -2835,7 +2917,6 @@ if (used < max) {
|
|||
#endif
|
||||
#ifdef USE_VDE_NETWORK
|
||||
if (used < max) {
|
||||
list[used].num = used;
|
||||
sprintf(list[used].name, "%s", "vde:device");
|
||||
sprintf(list[used].desc, "%s", "Integrated VDE support");
|
||||
++used;
|
||||
|
@ -2853,6 +2934,7 @@ pcap_if_t* alldevs;
|
|||
pcap_if_t* dev;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
memset(list, 0, max*sizeof(*list));
|
||||
/* retrieve the device list */
|
||||
if (pcap_findalldevs(&alldevs, errbuf) == -1) {
|
||||
char* msg = "Eth: error in pcap_findalldevs: %s\r\n";
|
||||
|
@ -2861,15 +2943,13 @@ if (pcap_findalldevs(&alldevs, errbuf) == -1) {
|
|||
}
|
||||
else {
|
||||
/* copy device list into the passed structure */
|
||||
for (i=0, dev=alldevs; dev; dev=dev->next) {
|
||||
for (i=0, dev=alldevs; dev && (i < max); dev=dev->next, ++i) {
|
||||
if ((dev->flags & PCAP_IF_LOOPBACK) || (!strcmp("any", dev->name))) continue;
|
||||
list[i].num = i;
|
||||
sprintf(list[i].name, "%s", dev->name);
|
||||
strncpy(list[i].name, dev->name, sizeof(list[i].name)-1);
|
||||
if (dev->description)
|
||||
sprintf(list[i].desc, "%s", dev->description);
|
||||
strncpy(list[i].desc, dev->description, sizeof(list[i].desc)-1);
|
||||
else
|
||||
sprintf(list[i].desc, "%s", "No description available");
|
||||
if (i++ >= max) break;
|
||||
strncpy(list[i].desc, "No description available", sizeof(list[i].desc)-1);
|
||||
}
|
||||
|
||||
/* free device list */
|
||||
|
|
30
sim_ether.h
30
sim_ether.h
|
@ -130,19 +130,36 @@
|
|||
#define ETH_MIN_PACKET 60 /* minimum ethernet packet size */
|
||||
#define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */
|
||||
#define ETH_MAX_JUMBO_FRAME 65536 /* maximum ethernet jumbo frame size (or Offload Segment Size) */
|
||||
#define ETH_MAX_DEVICE 10 /* maximum ethernet devices */
|
||||
#define ETH_MAX_DEVICE 20 /* maximum ethernet devices */
|
||||
#define ETH_CRC_SIZE 4 /* ethernet CRC size */
|
||||
#define ETH_FRAME_SIZE (ETH_MAX_PACKET+ETH_CRC_SIZE) /* ethernet maximum frame size */
|
||||
#define ETH_MIN_JUMBO_FRAME ETH_MAX_PACKET /* Threshold size for Jumbo Frame Processing */
|
||||
|
||||
#define LOOPBACK_SELF_FRAME(phy_mac, msg) \
|
||||
((memcmp(phy_mac, msg , 6) == 0) && \
|
||||
(memcmp(phy_mac, msg+6, 6) == 0) && \
|
||||
((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \
|
||||
(((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \
|
||||
((msg)[14] == 0x00) && ((msg)[15] == 0x00) && \
|
||||
((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \
|
||||
(memcmp(phy_mac, msg+18, 6) == 0) && \
|
||||
((msg)[24] == 0x01) && ((msg)[25] == 0x00))
|
||||
((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \
|
||||
(memcmp(phy_mac, (msg), 6) == 0) && \
|
||||
(memcmp(phy_mac, (msg)+6, 6) == 0) && \
|
||||
(memcmp(phy_mac, (msg)+18, 6) == 0))
|
||||
|
||||
#define LOOPBACK_PHYSICAL_RESPONSE(host_phy, phy_mac, msg) \
|
||||
(((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \
|
||||
((msg)[14] == 0x08) && ((msg)[15] == 0x00) && \
|
||||
((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \
|
||||
((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \
|
||||
(memcmp(host_phy, (msg)+18, 6) == 0) && \
|
||||
(memcmp(host_phy, (msg), 6) == 0) && \
|
||||
(memcmp(phy_mac, (msg)+6, 6) == 0))
|
||||
|
||||
#define LOOPBACK_PHYSICAL_REFLECTION(host_phy, msg) \
|
||||
(((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \
|
||||
((msg)[14] == 0x00) && ((msg)[15] == 0x00) && \
|
||||
((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \
|
||||
((msg)[24] == 0x01) && ((msg)[25] == 0x00) && \
|
||||
(memcmp(host_phy, (msg)+6, 6) == 0) && \
|
||||
(memcmp(host_phy, (msg)+18, 6) == 0))
|
||||
|
||||
struct eth_packet {
|
||||
uint8 msg[ETH_FRAME_SIZE]; /* ethernet frame (message) */
|
||||
|
@ -168,7 +185,6 @@ struct eth_queue {
|
|||
};
|
||||
|
||||
struct eth_list {
|
||||
int num;
|
||||
char name[ETH_DEV_NAME_MAX];
|
||||
char desc[ETH_DEV_DESC_MAX];
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue