diff --git a/source/Tfe/Bittypes.h b/source/Tfe/Bittypes.h new file mode 100644 index 00000000..31815fc6 --- /dev/null +++ b/source/Tfe/Bittypes.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 1999 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BITTYPES_H +#define _BITTYPES_H + +#ifndef HAVE_U_INT8_T + +#if SIZEOF_CHAR == 1 +typedef unsigned char u_int8_t; +typedef signed char int8_t; +#elif SIZEOF_INT == 1 +typedef unsigned int u_int8_t; +typedef signed int int8_t; +#else /* XXX */ +#error "there's no appropriate type for u_int8_t" +#endif +#define HAVE_U_INT8_T 1 +#define HAVE_INT8_T 1 + +#endif /* HAVE_U_INT8_T */ + +#ifndef HAVE_U_INT16_T + +#if SIZEOF_SHORT == 2 +typedef unsigned short u_int16_t; +typedef signed short int16_t; +#elif SIZEOF_INT == 2 +typedef unsigned int u_int16_t; +typedef signed int int16_t; +#elif SIZEOF_CHAR == 2 +typedef unsigned char u_int16_t; +typedef signed char int16_t; +#else /* XXX */ +#error "there's no appropriate type for u_int16_t" +#endif +#define HAVE_U_INT16_T 1 +#define HAVE_INT16_T 1 + +#endif /* HAVE_U_INT16_T */ + +#ifndef HAVE_U_INT32_T + +#if SIZEOF_INT == 4 +typedef unsigned int u_int32_t; +typedef signed int int32_t; +#elif SIZEOF_LONG == 4 +typedef unsigned long u_int32_t; +typedef signed long int32_t; +#elif SIZEOF_SHORT == 4 +typedef unsigned short u_int32_t; +typedef signed short int32_t; +#else /* XXX */ +#error "there's no appropriate type for u_int32_t" +#endif +#define HAVE_U_INT32_T 1 +#define HAVE_INT32_T 1 + +#endif /* HAVE_U_INT32_T */ + +#endif /* _BITTYPES_H */ diff --git a/source/Tfe/Bpf.h b/source/Tfe/Bpf.h new file mode 100644 index 00000000..273f6f6d --- /dev/null +++ b/source/Tfe/Bpf.h @@ -0,0 +1,516 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header$ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int bpf_int32; +typedef u_int bpf_u_int32; + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If your using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSTCPF _IOW(B,114, struct bpf_program) +#define BIOCSUDPF _IOW(B,115, struct bpf_program) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSTCPF _IOW('B',114, struct bpf_program) +#define BIOCSUDPF _IOW('B',115, struct bpf_program) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + */ +#if defined(KERNEL) || defined(_KERNEL) +#define SIZEOF_BPF_HDR 18 +#endif + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer encapsulation */ +#define DLT_EN10MB 1 /* Ethernet (10Mb) */ +#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */ +#define DLT_AX25 3 /* Amateur Radio AX.25 */ +#define DLT_PRONET 4 /* Proteon ProNET Token Ring */ +#define DLT_CHAOS 5 /* Chaos */ +#define DLT_IEEE802 6 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#ifdef __NetBSD__ +#ifndef DLT_SLIP_BSDOS +#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */ +#endif +#else +#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */ +#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */ +#endif + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * These values are defined by NetBSD; other platforms should refrain from + * using them for other purposes, so that NetBSD savefiles with link + * types of 50 or 51 can be read as this type on all platforms. + */ +#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */ +#define DLT_PPP_ETHER 51 /* PPP over Ethernet */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 as a DLT_ value. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use. + */ +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * For future use with 802.11 captures - defined by AbsoluteValue + * Systems to store a number of bits of link-layer information: + * + * http://www.shaftnet.org/~pizza/software/capturefrm.txt + * + * but could and arguably should also be used by non-AVS Linux + * 802.11 drivers and BSD drivers; that may happen in the future. + */ +#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ + +/* + * Reserved for the TZSP encapsulation, as per request from + * Chris Waters + * TZSP is a generic encapsulation for any other link type, + * which includes a means to include meta-information + * with the packet, e.g. signal strength and channel + * for 802.11 packets. + */ +#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */ + +/* + * BSD's ARCNET headers have the source host, destination host, + * and type at the beginning of the packet; that's what's handed + * up to userland via BPF. + * + * Linux's ARCNET headers, however, have a 2-byte offset field + * between the host IDs and the type; that's what's handed up + * to userland via PF_PACKET sockets. + * + * We therefore have to have separate DLT_ values for them. + */ +#define DLT_ARCNET_LINUX 129 /* ARCNET */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else +extern void bpf_tap(); +extern void bpf_mtap(); +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(struct bpf_insn *, int); +extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/Tfe/Ip6_misc.h b/source/Tfe/Ip6_misc.h new file mode 100644 index 00000000..d76fb6e2 --- /dev/null +++ b/source/Tfe/Ip6_misc.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 1993, 1994, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header$ (LBL) + */ + +/* + * This file contains a collage of declarations for IPv6 from FreeBSD not present in Windows + */ + +#include + +#ifndef __MINGW32__ +#include +#endif /* __MINGW32__ */ + +#define IN_MULTICAST(a) IN_CLASSD(a) + +#define IN_EXPERIMENTAL(a) ((((u_int32_t) (a)) & 0xe0000000) == 0xe0000000) + +#define IN_LOOPBACKNET 127 + +#ifdef __MINGW32__ +/* IPv6 address */ +struct in6_addr + { + union + { + u_int8_t u6_addr8[16]; + u_int16_t u6_addr16[8]; + u_int32_t u6_addr32[4]; + } in6_u; +#define s6_addr in6_u.u6_addr8 +#define s6_addr16 in6_u.u6_addr16 +#define s6_addr32 in6_u.u6_addr32 +#define s6_addr64 in6_u.u6_addr64 + }; + +#define IN6ADDR_ANY_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +#define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } +#endif /* __MINGW32__ */ + + +#ifdef __MINGW32__ +typedef unsigned short sa_family_t; + +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + u_int16_t sin6_port; /* Transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + }; + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((u_int32_t *) (a))[0] == 0) && (((u_int32_t *) (a))[1] == 0) && \ + (((u_int32_t *) (a))[2] == htonl (0xffff))) + +#define IN6_IS_ADDR_MULTICAST(a) (((u_int8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((u_int32_t *) (a))[0] & htonl (0xffc00000)) == htonl (0xfe800000)) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((u_int32_t *) (a))[0] == 0 && ((u_int32_t *) (a))[1] == 0 && \ + ((u_int32_t *) (a))[2] == 0 && ((u_int32_t *) (a))[3] == htonl (1)) +#endif /* __MINGW32__ */ + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +/* + * IPV6 extension headers + */ +#define IPPROTO_HOPOPTS 0 /* IPv6 hop-by-hop options */ +#define IPPROTO_IPV6 41 /* IPv6 header. */ +#define IPPROTO_ROUTING 43 /* IPv6 routing header */ +#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */ +#define IPPROTO_ESP 50 /* encapsulating security payload */ +#define IPPROTO_AH 51 /* authentication header */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 */ +#define IPPROTO_NONE 59 /* IPv6 no next header */ +#define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ +#define IPPROTO_PIM 103 /* Protocol Independent Multicast. */ + +#define IPV6_RTHDR_TYPE_0 0 + +/* Option types and related macros */ +#define IP6OPT_PAD1 0x00 /* 00 0 00000 */ +#define IP6OPT_PADN 0x01 /* 00 0 00001 */ +#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ +#define IP6OPT_JUMBO_LEN 6 +#define IP6OPT_ROUTER_ALERT 0x05 /* 00 0 00101 */ + +#define IP6OPT_RTALERT_LEN 4 +#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ +#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ +#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ +#define IP6OPT_MINLEN 2 + +#define IP6OPT_BINDING_UPDATE 0xc6 /* 11 0 00110 */ +#define IP6OPT_BINDING_ACK 0x07 /* 00 0 00111 */ +#define IP6OPT_BINDING_REQ 0x08 /* 00 0 01000 */ +#define IP6OPT_HOME_ADDRESS 0xc9 /* 11 0 01001 */ +#define IP6OPT_EID 0x8a /* 10 0 01010 */ + +#define IP6OPT_TYPE(o) ((o) & 0xC0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xC0 + +#define IP6OPT_MUTABLE 0x20 + + +#ifdef __MINGW32__ +#ifndef EAI_ADDRFAMILY +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; +#endif +#endif /* __MINGW32__ */ diff --git a/source/Tfe/Pcap-stdinc.h b/source/Tfe/Pcap-stdinc.h new file mode 100644 index 00000000..b5503628 --- /dev/null +++ b/source/Tfe/Pcap-stdinc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002 + * Politecnico di Torino. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the Politecnico + * di Torino, and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header$ (LBL) + */ + +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 + +#define _WINSOCKAPI_ +#include + +#include +#include "bittypes.h" +#include +#include + +#ifndef __MINGW32__ +#include "IP6_misc.h" +#endif + +#define caddr_t char* + +#define snprintf _snprintf +#define vsnprintf _vsnprintf + diff --git a/source/Tfe/Pcap.h b/source/Tfe/Pcap.h new file mode 100644 index 00000000..9982499f --- /dev/null +++ b/source/Tfe/Pcap.h @@ -0,0 +1,273 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ +/* + * Copyright (c) 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header$ (LBL) + */ + +#ifndef lib_pcap_h +#define lib_pcap_h + +#ifdef WIN32 +/* RGJ Changed it to "pcap-stdinc.h" for AppleWin */ +#include "pcap-stdinc.h" +#else /* WIN32 */ +#include +#include +#endif /* WIN32 */ + +/* RGJ Changed it to "bpf.h" for AppleWin */ +#include "bpf.h" + +#include + +#ifdef REMOTE + // We have to define the SOCKET here, although it has been defined in sockutils.h + // This is to avoid the distribution of the 'sockutils.h' file around + // (for example in the WinPcap developer's pack) + #ifndef SOCKET + #ifdef WIN32 + #define SOCKET unsigned int + #else + #define SOCKET int + #endif + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@tcpdump.org", requesting a new + * magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ +}; + +/* + * Each packet in the dump file is prepended with this generic header. + * This gets around the problem of different headers for different + * packet interfaces. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface XXX not yet supported */ +#ifdef REMOTE +#ifdef WIN32 +// u_int bs_capt; /* number of packets that reach the application */ +#endif /* WIN32 */ + u_int ps_capt; /* number of packets that reach the application; please get rid off the Win32 ifdef */ + u_int ps_sent; /* number of packets sent by the server on the network */ + u_int ps_netdrop; /* number of packets lost on the network */ +#endif +}; + +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + bpf_u_int32 flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +char *pcap_lookupdev(char *); +int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *); +pcap_t *pcap_open_live(const char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_offline(const char *, char *); +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); +void pcap_perror(pcap_t *, char *); +char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +int pcap_compile(pcap_t *, struct bpf_program *, char *, int, + bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + char *, int, bpf_u_int32); +void pcap_freecode(struct bpf_program *); +int pcap_datalink(pcap_t *); +int pcap_list_datalinks(pcap_t *, int **); +int pcap_set_datalink(pcap_t *, int); +int pcap_datalink_name_to_val(const char *); +const char *pcap_datalink_val_to_name(int); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +int pcap_dump_flush(pcap_dumper_t *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + +/* To avoid callback, this returns one packet at a time */ +int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data); + +/* XXX this guy lives in the bpf tree */ +u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +int bpf_validate(struct bpf_insn *f, int len); +char *bpf_image(struct bpf_insn *, int); +void bpf_dump(struct bpf_program *, int); + +#ifdef WIN32 +/* + * Win32 definitions + */ + +int pcap_setbuff(pcap_t *p, int dim); +int pcap_setmode(pcap_t *p, int mode); +int pcap_sendpacket(pcap_t *p, u_char *buf, int size); +int pcap_setmintocopy(pcap_t *p, int size); + +#ifdef WPCAP +/* Include file with the wpcap-specific extensions */ +#include +#endif + +#define MODE_CAPT 0 +#define MODE_STAT 1 +#define MODE_MON 2 + +#endif /* WIN32 */ + +#ifdef REMOTE +/* Includes most of the public stuff that is needed for the remote capture */ +#include "remote-ext.h" +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/Tfe/Tfe.cpp b/source/Tfe/Tfe.cpp new file mode 100644 index 00000000..a537bf25 --- /dev/null +++ b/source/Tfe/Tfe.cpp @@ -0,0 +1,1533 @@ +/* + * tfe.c - TFE ("The final ethernet") emulation. + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + +#include +#include +#include +#include +#ifdef DOS_TFE +#include +#endif + +#include "tfe.h" +#include "tfearch.h" +#include "tfesupp.h" + + +/**/ +/** #define TFE_DEBUG_DUMP 1 **/ + +/* #define TFE_DEBUG_FRAMES - might be defined in TFE.H! */ + +#define TFE_DEBUG_WARN 1 /* this should not be deactivated */ +#define TFE_DEBUG_INIT 1 +/** #define TFE_DEBUG_LOAD 1 **/ +/** #define TFE_DEBUG_STORE 1 **/ +/**/ + +/* ------------------------------------------------------------------------- */ +/* variables needed */ + +/* + This variable is used when we need to postpone the initialization + because tfe_init() is not yet called +*/ +static int should_activate = 0; + + +static int init_tfe_flag = 0; + +/* status which received packages to accept + This is used in tfe_should_accept(). +*/ +static BYTE tfe_ia_mac[6]; + +/* remember the value of the hash mask */ +static DWORD tfe_hash_mask[2]; + +static int tfe_recv_broadcast = 0; /* broadcast */ +static int tfe_recv_mac = 0; /* individual address (IA) */ +static int tfe_recv_multicast = 0; /* multicast if address passes the hash filter */ +static int tfe_recv_correct = 0; /* accept correct frames */ +static int tfe_recv_promiscuous = 0; /* promiscuous mode */ +static int tfe_recv_hashfilter = 0; /* accept if IA passes the hash filter */ + + +#ifdef TFE_DEBUG_WARN +/* remember if the TXCMD has been completed before a new one is issued */ +static int tfe_started_tx = 0; +#endif + + +/* Flag: Can we even use TFE, or is the hardware not available? */ +static int tfe_cannot_use = 0; + +/* Flag: Do we have the TFE enabled? */ +int tfe_enabled = 0; + +/* Flag: Do we use the "original" memory map or the memory map of the RR-Net? */ +//static int tfe_as_rr_net = 0; + +char *tfe_interface = NULL; + +/* TFE registers */ +/* these are the 8 16-bit-ports for "I/O space configuration" + (see 4.10 on page 75 of cs8900a-4.pdf, the cs8900a data sheet) + + REMARK: The TFE operatoes the cs8900a in IO space configuration, as + it generates I/OW and I/OR signals. +*/ +#define TFE_COUNT_IO_REGISTER 0x10 /* we have 16 I/O register */ + +static BYTE *tfe = NULL; +/* + RW: RXTXDATA = DE00/DE01 + RW: RXTXDATA2 = DE02/DE03 (for 32-bit-operation) + -W: TXCMD = DE04/DE05 (TxCMD, Transmit Command) mapped to PP + 0144 (Reg. 9, Sec. 4.4, page 46) + -W: TXLENGTH = DE06/DE07 (TxLenght, Transmit Length) mapped to PP + 0146 + R-: INTSTQUEUE = DE08/DE09 (Interrupt Status Queue) mapped to PP + 0120 (ISQ, Sec. 5.1, page 78) + RW: PP_PTR = DE0A/DE0B (PacketPage Pointer) (see. page 75p: Read -011.---- ----.----) + RW: PP_DATA0 = DE0C/DE0D (PacketPage Data (Port 0)) + RW: PP_DATA1 = DE0E/DE0F (PacketPage Data (Port 1)) (for 32 bit only) +*/ + +#define TFE_ADDR_RXTXDATA 0x00 /* RW */ +#define TFE_ADDR_RXTXDATA2 0x02 /* RW 32 bit only! */ +#define TFE_ADDR_TXCMD 0x04 /* -W Maps to PP+0144 */ +#define TFE_ADDR_TXLENGTH 0x06 /* -W Maps to PP+0146 */ +#define TFE_ADDR_INTSTQUEUE 0x08 /* R- Interrupt status queue, maps to PP + 0120 */ +#define TFE_ADDR_PP_PTR 0x0a /* RW PacketPage Pointer */ +#define TFE_ADDR_PP_DATA 0x0c /* RW PacketPage Data, Port 0 */ +#define TFE_ADDR_PP_DATA2 0x0e /* RW PacketPage Data, Port 1 - 32 bit only */ + +/* Makros for reading and writing the visible TFE register: */ +#define GET_TFE_8( _xxx_ ) \ + ( assert(_xxx_> 8) & 0xff; \ + } while (0) + +/* The PacketPage register */ +/* note: The locations 0 to MAX_PACKETPAGE_ARRAY-1 are handled in this array. */ + +#define MAX_PACKETPAGE_ARRAY 0x1000 /* 4 KB */ + +static BYTE *tfe_packetpage = NULL; + +static WORD tfe_packetpage_ptr = 0; + +/* Makros for reading and writing the PacketPage register: */ + +#define GET_PP_8( _xxx_ ) \ + (assert(_xxx_> 8) & 0xFF; \ + } while (0) + +#define SET_PP_32( _xxx_, _val_ ) \ + do { \ + assert(_xxx_> 8) & 0xFF; \ + tfe_packetpage[_xxx_+2] = (_val_>>16) & 0xFF; \ + tfe_packetpage[_xxx_+3] = (_val_>>24) & 0xFF; \ + } while (0) + + +/* The packetpage register: see p. 39f */ +#define TFE_PP_ADDR_PRODUCTID 0x0000 /* R- - 4.3., p. 41 */ +#define TFE_PP_ADDR_IOBASE 0x0020 /* i RW - 4.3., p. 41 - 4.7., p. 72 */ +#define TFE_PP_ADDR_INTNO 0x0022 /* i RW - 3.2., p. 17 - 4.3., p. 41 */ +#define TFE_PP_ADDR_DMA_CHAN 0x0024 /* i RW - 3.2., p. 17 - 4.3., p. 41 */ +#define TFE_PP_ADDR_DMA_SOF 0x0026 /* ? R- - 4.3., p. 41 - 5.4., p. 89 */ +#define TFE_PP_ADDR_DMA_FC 0x0028 /* ? R- - 4.3., p. 41, "Receive DMA" */ +#define TFE_PP_ADDR_RXDMA_BC 0x002a /* ? R- - 4.3., p. 41 - 5.4., p. 89 */ +#define TFE_PP_ADDR_MEMBASE 0x002c /* i RW - 4.3., p. 41 - 4.9., p. 73 */ +#define TFE_PP_ADDR_BPROM_BASE 0x0030 /* i RW - 3.6., p. 24 - 4.3., p. 41 */ +#define TFE_PP_ADDR_BPROM_MASK 0x0034 /* i RW - 3.6., p. 24 - 4.3., p. 41 */ +/* 0x0038 - 0x003F: reserved */ +#define TFE_PP_ADDR_EEPROM_CMD 0x0040 /* i RW - 3.5., p. 23 - 4.3., p. 41 */ +#define TFE_PP_ADDR_EEPROM_DATA 0x0042 /* i RW - 3.5., p. 23 - 4.3., p. 41 */ +/* 0x0044 - 0x004F: reserved */ +#define TFE_PP_ADDR_REC_FRAME_BC 0x0050 /* RW - 4.3., p. 41 - 5.2.9., p. 86 */ +/* 0x0052 - 0x00FF: reserved */ +#define TFE_PP_ADDR_CONF_CTRL 0x0100 /* - RW - 4.4., p. 46; see below */ +#define TFE_PP_ADDR_STATUS_EVENT 0x0120 /* - R- - 4.4., p. 46; see below */ +/* 0x0140 - 0x0143: reserved */ +#define TFE_PP_ADDR_TXCMD 0x0144 /* # -W - 4.5., p. 70 - 5.7., p. 98 */ +#define TFE_PP_ADDR_TXLENGTH 0x0146 /* # -W - 4.5., p. 70 - 5.7., p. 98 */ +/* 0x0148 - 0x014F: reserved */ +#define TFE_PP_ADDR_LOG_ADDR_FILTER 0x0150 /* RW - 4.6., p. 71 - 5.3., p. 86 */ +#define TFE_PP_ADDR_MAC_ADDR 0x0158 /* # RW - 4.6., p. 71 - 5.3., p. 86 */ +/* 0x015E - 0x03FF: reserved */ +#define TFE_PP_ADDR_RXSTATUS 0x0400 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +#define TFE_PP_ADDR_RXLENGTH 0x0402 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +#define TFE_PP_ADDR_RX_FRAMELOC 0x0404 /* R- - 4.7., p. 72 - 5.2., p. 78 */ +/* here, the received frame is stored */ +#define TFE_PP_ADDR_TX_FRAMELOC 0x0A00 /* -W - 4.7., p. 72 - 5.7., p. 98 */ +/* here, the frame to transmit is stored */ +#define TFE_PP_ADDR_END 0x1000 /* memory to TFE_PP_ADDR_END-1 is used */ + + +/* TFE_PP_ADDR_CONF_CTRL is subdivided: */ +#define TFE_PP_ADDR_CC_RXCFG 0x0102 /* # RW - 4.4.6., p. 52 - 0003 */ +#define TFE_PP_ADDR_CC_RXCTL 0x0104 /* # RW - 4.4.8., p. 54 - 0005 */ +#define TFE_PP_ADDR_CC_TXCFG 0x0106 /* RW - 4.4.9., p. 55 - 0007 */ +#define TFE_PP_ADDR_CC_TXCMD 0x0108 /* R- - 4.4.11., p. 57 - 0009 */ +#define TFE_PP_ADDR_CC_BUFCFG 0x010A /* RW - 4.4.12., p. 58 - 000B */ +#define TFE_PP_ADDR_CC_LINECTL 0x0112 /* # RW - 4.4.16., p. 62 - 0013 */ +#define TFE_PP_ADDR_CC_SELFCTL 0x0114 /* RW - 4.4.18., p. 64 - 0015 */ +#define TFE_PP_ADDR_CC_BUSCTL 0x0116 /* RW - 4.4.20., p. 66 - 0017 */ +#define TFE_PP_ADDR_CC_TESTCTL 0x0118 /* RW - 4.4.22., p. 68 - 0019 */ + +/* TFE_PP_ADDR_STATUS_EVENT is subdivided: */ +#define TFE_PP_ADDR_SE_ISQ 0x0120 /* R- - 4.4.5., p. 51 - 0000 */ +#define TFE_PP_ADDR_SE_RXEVENT 0x0124 /* # R- - 4.4.7., p. 53 - 0004 */ +#define TFE_PP_ADDR_SE_TXEVENT 0x0128 /* R- - 4.4.10., p. 56 - 0008 */ +#define TFE_PP_ADDR_SE_BUFEVENT 0x012C /* R- - 4.4.13., p. 59 - 000C */ +#define TFE_PP_ADDR_SE_RXMISS 0x0130 /* R- - 4.4.14., p. 60 - 0010 */ +#define TFE_PP_ADDR_SE_TXCOL 0x0132 /* R- - 4.4.15., p. 61 - 0012 */ +#define TFE_PP_ADDR_SE_LINEST 0x0134 /* R- - 4.4.17., p. 63 - 0014 */ +#define TFE_PP_ADDR_SE_SELFST 0x0136 /* R- - 4.4.19., p. 65 - 0016 */ +#define TFE_PP_ADDR_SE_BUSST 0x0138 /* # R- - 4.4.21., p. 67 - 0018 */ +#define TFE_PP_ADDR_SE_TDR 0x013C /* R- - 4.4.23., p. 69 - 001C */ + + +/* ------------------------------------------------------------------------- */ +/* more variables needed */ + +static WORD txcollect_buffer = TFE_PP_ADDR_TX_FRAMELOC; +static WORD rx_buffer = TFE_PP_ADDR_RXSTATUS; + + + +/* ------------------------------------------------------------------------- */ +/* some parameter definitions */ + +#define MAX_TXLENGTH 1518 +#define MIN_TXLENGTH 4 + +#define MAX_RXLENGTH 1518 +#define MIN_RXLENGTH 64 + + +/* ------------------------------------------------------------------------- */ +/* debugging functions */ + +#ifdef TFE_DEBUG_FRAMES + +static int TfeDebugMaxFrameLengthToDump = 150; + +char *debug_outbuffer(const int length, const unsigned char * const buffer) +{ +#define MAXLEN_DEBUG 1600 + + int i; + static char outbuffer[MAXLEN_DEBUG*4+1]; + char *p = outbuffer; + + assert( TfeDebugMaxFrameLengthToDump <= MAXLEN_DEBUG ); + + *p = 0; + + for (i=0; i=length) + break; + + sprintf( p, "%02X%c", buffer[i], ((i+1)%16==0)?'*':(((i+1)%8==0)?'-':' ')); + p+=3; + } + + return outbuffer; +} + +#endif + + +#ifdef TFE_DEBUG_DUMP + +#define NUMBER_PER_LINE 8 + +static +void tfe_debug_output_general( char *what, WORD (*getFunc)(int), int count ) +{ + int i; + char buffer[7+(6*NUMBER_PER_LINE)+2]; + + if(g_fh) fprintf(g_fh, "%s contents:", what ); + for (i=0; i=6); /* we need at least 6 octets since the DA has this length */ + + /* first of all, delete any status */ + *phashed = 0; + *phash_index = 0; + *pcorrect_mac = 0; + *pbroadcast = 0; + *pmulticast = 0; + +#ifdef TFE_DEBUG_FRAMES + if(g_fh) fprintf(g_fh, "tfe_should_accept called with %02X:%02X:%02X:%02X:%02X:%02X, length=%4u and buffer %s", + tfe_ia_mac[0], tfe_ia_mac[1], tfe_ia_mac[2], + tfe_ia_mac[3], tfe_ia_mac[4], tfe_ia_mac[5], + length, + debug_outbuffer(length, buffer) + ); +#endif + + + if ( buffer[0]==tfe_ia_mac[0] + && buffer[1]==tfe_ia_mac[1] + && buffer[2]==tfe_ia_mac[2] + && buffer[3]==tfe_ia_mac[3] + && buffer[4]==tfe_ia_mac[4] + && buffer[5]==tfe_ia_mac[5] + ) { + /* this is our individual address (IA) */ + + *pcorrect_mac = 1; + + /* if we don't want "correct MAC", we might have the chance + * that this address fits the hash index + */ + if (tfe_recv_mac || tfe_recv_promiscuous) + return(1); + } + + if ( buffer[0]==0xFF + && buffer[1]==0xFF + && buffer[2]==0xFF + && buffer[3]==0xFF + && buffer[4]==0xFF + && buffer[5]==0xFF + ) { + /* this is a broadcast address */ + *pbroadcast = 1; + + /* broadcasts cannot be accepted by the hash filter */ + return((tfe_recv_broadcast || tfe_recv_promiscuous) ? 1 : 0); + } + + /* now check if DA passes the hash filter */ + /* RGJ added (const char *) for AppleWin */ + hashreg = (~crc32_buf((const char *)buffer,6) >> 26) & 0x3F; + + *phashed = (tfe_hash_mask[(hashreg>=32)?1:0] & (1 << (hashreg&0x1F))) ? 1 : 0; + if (*phashed) { + *phash_index = hashreg; + + if (buffer[0] & 0x80) { + /* we have a multicast address */ + *pmulticast = 1; + + /* if the multicast address fits into the hash filter, + * the hashed bit has to be clear + */ + *phashed = 0; + + return((tfe_recv_multicast || tfe_recv_promiscuous) ? 1 : 0); + } + return((tfe_recv_hashfilter || tfe_recv_promiscuous) ? 1 : 0); + } + + return(tfe_recv_promiscuous ? 1 : 0); +} + +#ifdef TFE_DEBUG_FRAMES + #undef return +#endif + +static +WORD tfe_receive(void) +{ + WORD ret_val = 0x0004; + + BYTE buffer[MAX_RXLENGTH]; + + int len; + int hashed; + int hash_index; + int rx_ok; + int correct_mac; + int broadcast; + int multicast; + int crc_error; + + int newframe; + + int ready; + +#ifdef TFE_DEBUG_FRAMES + if(g_fh) fprintf( g_fh, ""); +#endif + + do { + len = MAX_RXLENGTH; + + ready = 1 ; /* assume we will find a good frame */ + + newframe = tfe_arch_receive( + buffer, /* where to store a frame */ + &len, /* length of received frame */ + &hashed, /* set if the dest. address is accepted by the hash filter */ + &hash_index, /* hash table index if hashed == TRUE */ + &rx_ok, /* set if good CRC and valid length */ + &correct_mac, /* set if dest. address is exactly our IA */ + &broadcast, /* set if dest. address is a broadcast address */ + &crc_error /* set if received frame had a CRC error */ + ); + + assert((len&1) == 0); /* length has to be even! */ + + if (newframe) { + if (hashed || correct_mac || broadcast) { + /* we already know the type of frame: Trust it! */ +#ifdef TFE_DEBUG_FRAMES + if(g_fh) fprintf( g_fh, "+++ tfe_receive(): *** hashed=%u, correct_mac=%u, " + "broadcast=%u", hashed, correct_mac, broadcast); +#endif + } + else { + /* determine ourself the type of frame */ + if (!tfe_should_accept(buffer, + len, &hashed, &hash_index, &correct_mac, &broadcast, &multicast)) { + + /* if we should not accept this frame, just do nothing + * now, look for another one */ + ready = 0; /* try another frame */ + continue; + } + } + + + /* we did receive a frame, return that status */ + ret_val |= rx_ok ? 0x0100 : 0; + ret_val |= multicast ? 0x0200 : 0; + + if (!multicast) { + ret_val |= hashed ? 0x0040 : 0; + } + + if (hashed && rx_ok) { + /* we have the 2nd, special format with hash index: */ + assert(hash_index < 64); + ret_val |= hash_index << 9; + } + else { + /* we have the regular format */ + ret_val |= correct_mac ? 0x0400 : 0; + ret_val |= broadcast ? 0x0800 : 0; + ret_val |= crc_error ? 0x1000 : 0; + ret_val |= (lenMAX_RXLENGTH) ? 0x4000 : 0; + } + + /* discard any octets that are beyond the MAX_RXLEN */ + if (len>MAX_RXLENGTH) { + len = MAX_RXLENGTH; + } + + if (rx_ok) { + int i; + + /* set relevant parts of the PP area to correct values */ + SET_PP_16(TFE_PP_ADDR_RXLENGTH, len); + + for (i=0;iMAX_TXLENGTH) + || ((txlen>MAX_TXLENGTH-4) && (!(txcmd&0x1000))) + || (txlenMAX_TXLENGTH) + || ((txlength>MAX_TXLENGTH-4) && (!(txcommand&0x1000))) + ) { + /* txlength too big, mark an error */ + SET_PP_16(TFE_PP_ADDR_SE_BUSST, (GET_PP_16(TFE_PP_ADDR_SE_BUSST) | 0x80) & ~0x100); + } + else { + /* all right, signal that we're ready for the next frame */ + SET_PP_16(TFE_PP_ADDR_SE_BUSST, (GET_PP_16(TFE_PP_ADDR_SE_BUSST) & ~0x80) | 0x100); + } + } + break; + + case TFE_PP_ADDR_LOG_ADDR_FILTER: + case TFE_PP_ADDR_LOG_ADDR_FILTER+2: + case TFE_PP_ADDR_LOG_ADDR_FILTER+4: + case TFE_PP_ADDR_LOG_ADDR_FILTER+6: + { + unsigned int pos = 8 * (ppaddress - TFE_PP_ADDR_LOG_ADDR_FILTER + oddaddress); + DWORD *p = (pos < 32) ? &tfe_hash_mask[0] : &tfe_hash_mask[1]; + + *p &= ~(0xFF << pos); /* clear out relevant bits */ + *p |= GET_PP_8(ppaddress+oddaddress) << pos; + + tfe_arch_set_hashfilter(tfe_hash_mask); + } + break; + + case TFE_PP_ADDR_MAC_ADDR: + case TFE_PP_ADDR_MAC_ADDR+2: + case TFE_PP_ADDR_MAC_ADDR+4: + /* the MAC address has been changed */ + tfe_ia_mac[ppaddress-TFE_PP_ADDR_MAC_ADDR+oddaddress] = + GET_PP_8(ppaddress+oddaddress); + tfe_arch_set_mac(tfe_ia_mac); + break; + } +} + +/* + This is called *before* the relevant octets are read +*/ +static +void tfe_sideeffects_read_pp(WORD ppaddress) +{ + assert((ppaddress & 1) == 0); + + switch (ppaddress) + { + case TFE_PP_ADDR_SE_RXEVENT: + /* reading this before all octets of the frame are read + performs an "implied skip" */ + { + WORD ret_val = tfe_receive(); + + /* + RXSTATUS and RXEVENT are the same, except that RXSTATUS buffers + the old value while RXEVENT sets a new value whenever it is called + */ + SET_PP_16(TFE_PP_ADDR_RXSTATUS, ret_val); + SET_PP_16(TFE_PP_ADDR_SE_RXEVENT, ret_val); + } + + break; + + case TFE_PP_ADDR_SE_BUSST: + break; + + case TFE_PP_ADDR_TXCMD: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Read write-only register TFE_PP_ADDR_TXCMD: IGNORED"); +#endif + break; + + case TFE_PP_ADDR_TXLENGTH: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Read write-only register TFE_PP_ADDR_TXLENGTH: IGNORED"); +#endif + break; + } +} + + +void tfe_proceed_rx_buffer(int oddaddress) { + /* + According to the CS8900 spec, the handling is the following: + first read H, then L, then H, then L. + Now, we're inside the RX frame, now, we always get L then H, until the end is reached. + + even odd + TFE_PP_ADDR_RXSTATUS: - proceed 1) + TFE_PP_ADDR_RXLENGTH: - proceed + TFE_PP_ADDR_RX_FRAMELOC: 2),3) - + TFE_PP_ADDR_RX_FRAMELOC+2: proceed - + TFE_PP_ADDR_RX_FRAMELOC+4: like TFE_PP_ADDR_RX_FRAMELOC+2 + + 1) set status "Inside FRAMELOC" FALSE + 2) set status "Inside FRAMELOC" TRUE if it is not already + 3) if "Inside FRAMELOC", proceed + + */ + + static int inside_frameloc; + int proceed = 0; + + if (rx_buffer==TFE_PP_ADDR_RX_FRAMELOC+GET_PP_16(TFE_PP_ADDR_RXLENGTH)) { + /* we've read all that is available, go to start again */ + rx_buffer = TFE_PP_ADDR_RXSTATUS; + inside_frameloc = 0; + } + else { + switch (rx_buffer) { + case TFE_PP_ADDR_RXSTATUS: + if (oddaddress) { + proceed = 1; + inside_frameloc = 0; + } + break; + + case TFE_PP_ADDR_RXLENGTH: + if (oddaddress) { + proceed = 1; + } + break; + + case TFE_PP_ADDR_RX_FRAMELOC: + if (oddaddress==0) { + if (inside_frameloc) { + proceed = 1; + } + else { + inside_frameloc = 1; + } + } + break; + + default: + proceed = (oddaddress==0) ? 1 : 0; + break; + } + } + + if (proceed) { + SET_TFE_16(TFE_ADDR_RXTXDATA, GET_PP_16(rx_buffer)); + rx_buffer += 2; + } +} + + +BYTE REGPARM1 tfe_read(WORD ioaddress) +{ + BYTE retval; + + assert( tfe ); + assert( tfe_packetpage ); + + assert( ioaddress < 0x10); + + switch (ioaddress) { + + case TFE_ADDR_TXCMD: + case TFE_ADDR_TXCMD+1: + case TFE_ADDR_TXLENGTH: + case TFE_ADDR_TXLENGTH+1: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Reading write-only TFE register $%02X!", ioaddress); +#endif + /* @SRT TODO: Verify with reality */ + retval = GET_TFE_8(ioaddress); + break; + + case TFE_ADDR_RXTXDATA2: + case TFE_ADDR_RXTXDATA2+1: + case TFE_ADDR_PP_DATA2: + case TFE_ADDR_PP_DATA2+1: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Reading not supported TFE register $%02X!", ioaddress); +#endif + /* @SRT TODO */ + retval = GET_TFE_8(ioaddress); + break; + + case TFE_ADDR_PP_DATA: + case TFE_ADDR_PP_DATA+1: + /* make sure the TFE register have the correct content */ + { + WORD ppaddress = tfe_packetpage_ptr & (MAX_PACKETPAGE_ARRAY-1); + + /* perform side-effects the read may perform */ + tfe_sideeffects_read_pp( ppaddress ); + + /* [3] make sure the data matches the real value - [1] assumes this! */ + SET_TFE_16( TFE_ADDR_PP_DATA, GET_PP_16(ppaddress) ); + } + + +#ifdef TFE_DEBUG_LOAD + if(g_fh) fprintf(g_fh, "reading PP Ptr: $%04X => $%04X.", + tfe_packetpage_ptr, GET_PP_16(tfe_packetpage_ptr) ); +#endif + + retval = GET_TFE_8(ioaddress); + break; + + case TFE_ADDR_INTSTQUEUE: + case TFE_ADDR_INTSTQUEUE+1: + SET_TFE_16( TFE_ADDR_INTSTQUEUE, GET_PP_16(0x0120) ); + retval = GET_TFE_8(ioaddress); + break; + + case TFE_ADDR_RXTXDATA: + case TFE_ADDR_RXTXDATA+1: + /* we're trying to read a new 16 bit word, get it from the + receive buffer + */ + tfe_proceed_rx_buffer(ioaddress & 0x01); + retval = GET_TFE_8(ioaddress); + break; + + default: + retval = GET_TFE_8(ioaddress); + break; + }; + +#ifdef TFE_DEBUG_LOAD + if(g_fh) fprintf(g_fh, "read [$%02X] => $%02X.", ioaddress, retval); +#endif + return retval; +} + +void REGPARM2 tfe_store(WORD ioaddress, BYTE byte) +{ + assert( tfe ); + assert( tfe_packetpage ); + + assert( ioaddress < 0x10); + + switch (ioaddress) + { + case TFE_ADDR_RXTXDATA: + case TFE_ADDR_RXTXDATA+1: + SET_PP_8(txcollect_buffer, byte); + tfe_sideeffects_write_pp_on_txframe(txcollect_buffer++); + break; + + case TFE_ADDR_INTSTQUEUE: + case TFE_ADDR_INTSTQUEUE+1: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Writing read-only TFE register $%02X!", ioaddress); +#endif + /* @SRT TODO: Verify with reality */ + /* do nothing */ + return; + + case TFE_ADDR_RXTXDATA2: + case TFE_ADDR_RXTXDATA2+1: + case TFE_ADDR_PP_DATA2: + case TFE_ADDR_PP_DATA2+1: +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, "WARNING! Writing not supported TFE register $%02X!", ioaddress); +#endif + /* do nothing */ + return; + + case TFE_ADDR_TXCMD: + case TFE_ADDR_TXCMD+1: + SET_TFE_8(ioaddress, byte); + SET_PP_8((ioaddress-TFE_ADDR_TXCMD)+TFE_PP_ADDR_TXCMD, byte); /* perform the mapping to PP+0144 */ + tfe_sideeffects_write_pp(TFE_PP_ADDR_TXCMD, ioaddress-TFE_ADDR_TXCMD); + break; + + case TFE_ADDR_TXLENGTH: + case TFE_ADDR_TXLENGTH+1: + + SET_TFE_8(ioaddress, byte); + SET_PP_8((ioaddress-TFE_ADDR_TXLENGTH)+TFE_PP_ADDR_TXLENGTH, byte ); /* perform the mapping to PP+0144 */ + + tfe_sideeffects_write_pp(TFE_PP_ADDR_TXLENGTH, ioaddress-TFE_ADDR_TXLENGTH); + break; + +/* +#define TFE_ADDR_TXCMD 0x04 * -W Maps to PP+0144 * +#define TFE_ADDR_TXLENGTH 0x06 * -W Maps to PP+0146 * +#define TFE_ADDR_INTSTQUEUE 0x08 * R- Interrupt status queue, maps to PP + 0120 * +*/ + case TFE_ADDR_PP_DATA: + case TFE_ADDR_PP_DATA+1: + + /* [2] make sure the data matches the real value - [1] assumes this! */ + SET_TFE_16(TFE_ADDR_PP_DATA, GET_PP_16(tfe_packetpage_ptr)); + /* FALL THROUGH */ + + default: + SET_TFE_8(ioaddress, byte); + } + +#ifdef TFE_DEBUG_STORE + if(g_fh) fprintf(g_fh, "store [$%02X] <= $%02X.", ioaddress, (int)byte); +#endif + + /* now check if we have to do any side-effects */ + switch (ioaddress) + { + case TFE_ADDR_PP_PTR: + case TFE_ADDR_PP_PTR+1: + tfe_packetpage_ptr = GET_TFE_16(TFE_ADDR_PP_PTR); + +#ifdef TFE_DEBUG_STORE + if(g_fh) fprintf(g_fh, "set PP Ptr to $%04X.", tfe_packetpage_ptr); +#endif + + if ((tfe_packetpage_ptr & 1) != 0) { + +#ifdef TFE_DEBUG_WARN + if(g_fh) fprintf(g_fh, + "WARNING! PacketPage register set to odd address $%04X (not allowed!)", + tfe_packetpage_ptr ); +#endif /* #ifdef TFE_DEBUG_WARN */ + + /* "correct" the address to the next lower address + REMARK: I don't know how a real cs8900a will behave in this case, + since it is not allowed. Nevertheless, this "correction" + prevents assert()s to fail. + */ + tfe_packetpage_ptr -= 1; + } + + /* + [1] The TFE_ADDR_PP_DATA does not need to be modified here, + since it will be modified just before a read or store operation + is to be performed. + See [2] and [3] + */ + break; + + case TFE_ADDR_PP_DATA: + case TFE_ADDR_PP_DATA+1: + + { + WORD ppaddress = tfe_packetpage_ptr & (MAX_PACKETPAGE_ARRAY-1); + +#ifdef TFE_DEBUG_STORE + if(g_fh) fprintf(g_fh, "before writing to PP Ptr: $%04X <= $%04X.", + ppaddress, GET_PP_16(ppaddress) ); +#endif + { + register WORD tmpIoAddr = ioaddress & ~1; /* word-align the address */ + SET_PP_16(ppaddress, GET_TFE_16(tmpIoAddr)); + } + + /* perform side-effects the write may perform */ + /* the addresses are always aligned on the whole 16-bit-word */ + tfe_sideeffects_write_pp(ppaddress, ioaddress-TFE_ADDR_PP_DATA); + +#ifdef TFE_DEBUG_STORE + if(g_fh) fprintf(g_fh, "after writing to PP Ptr: $%04X <= $%04X.", + ppaddress, GET_PP_16(ppaddress) ); +#endif + } + break; + } + + TFE_DEBUG_OUTPUT_REG(); +} + + + +static +int set_tfe_disabled(void *v, void *param) +{ + /* dummy function since we don't want "disabled" to be stored on disk */ + return 0; +} + + +static +int set_tfe_enabled(void *v, void *param) +{ + if (!tfe_cannot_use) { + + if (!(int)v) { + /* TFE should be deactived */ + if (tfe_enabled) { + tfe_enabled = 0; + /* RGJ Commented out forAppleWin */ + //c64export_remove(&export_res); + if (tfe_deactivate() < 0) { + return -1; + } + } + return 0; + } else { + if (!tfe_enabled) { + /* RGJ Commented out forAppleWin */ + //if (c64export_query(&export_res) < 0) + // return -1; + + tfe_enabled = 1; + if (tfe_activate() < 0) { + return -1; + } + /* RGJ Commented out forAppleWin */ + //if (c64export_add(&export_res) < 0) + // return -1; + + } + + return 0; + } + + } + return 0; +} + + +static +int set_tfe_interface(void *v, void *param) +{ + const char *name = (const char *)v; + + if (tfe_interface != NULL && name != NULL + && strcmp(name, tfe_interface) == 0) + return 0; + + util_string_set(&tfe_interface, name); + + if (tfe_enabled) { + /* ethernet is enabled, make sure that the new name is + taken account of + */ + if (tfe_deactivate() < 0) { + return -1; + } + if (tfe_activate() < 0) { + return -1; + } + + /* virtually reset the LAN chip */ + if (tfe) { + tfe_reset(); + } + } + return 0; +} + + + +/* ------------------------------------------------------------------------- */ +/* commandline support functions */ + +//#ifdef HAS_TRANSLATION +//static const cmdline_option_t cmdline_options[] = +//{ +// { "-tfe", SET_RESOURCE, 0, NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)1, +// 0, IDCLS_ENABLE_TFE }, +// { "+tfe", SET_RESOURCE, 0, NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)0, +// 0, IDCLS_DISABLE_TFE }, +// { NULL } +//}; +//#else +//static const cmdline_option_t cmdline_options[] = +//{ +// { "-tfe", SET_RESOURCE, 0, NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)1, +// NULL, N_("Enable the TFE (\"the final ethernet\") unit") }, +// { "+tfe", SET_RESOURCE, 0, NULL, NULL, "ETHERNET_ACTIVE", (resource_value_t)0, +// NULL, N_("Disable the TFE (\"the final ethernet\") unit") }, +// { NULL } +//}; +//#endif + +//int tfe_cmdline_options_init(void) +//{ +// return cmdline_register_options(cmdline_options); +//} + + +/* ------------------------------------------------------------------------- */ +/* snapshot support functions */ + +#if 0 + +static char snap_module_name[] = "TFE1764"; +#define SNAP_MAJOR 0 +#define SNAP_MINOR 0 + +int tfe_read_snapshot_module(struct snapshot_s *s) +{ + /* @SRT TODO: not yet implemented */ + return -1; +} + +int tfe_write_snapshot_module(struct snapshot_s *s) +{ + /* @SRT TODO: not yet implemented */ + return -1; +} + +#endif /* #if 0 */ + +/* ------------------------------------------------------------------------- */ +/* functions for selecting and querying available NICs */ + +int tfe_enumadapter_open(void) +{ + if (!tfe_arch_enumadapter_open()) { + tfe_cannot_use = 1; + return 0; + } + return 1; +} + +int tfe_enumadapter(char **ppname, char **ppdescription) +{ + return tfe_arch_enumadapter(ppname, ppdescription); +} + +int tfe_enumadapter_close(void) +{ + return tfe_arch_enumadapter_close(); +} + + +BYTE __stdcall TfeIo (WORD programcounter, BYTE address, BYTE write, BYTE value, ULONG nCycles) +{ + BYTE ret = 0; + + if (write) { + if (tfe_enabled) + tfe_store((WORD)(address & 0x0f), value); + } + else { + if (tfe_enabled) + ret = tfe_read((WORD)(address & 0x0f)); + } + +return ret; + +} + +void get_disabled_state(int * param) +{ + +*param = tfe_cannot_use; + +} + +int update_tfe_interface(void *v, void *param) +{ + return set_tfe_interface(v,param); +} + +void * get_tfe_interface(void) +{ + void *v; + v = tfe_interface; + return v; +} + +void get_tfe_enabled(int * param) +{ + *param = tfe_enabled; +} + +//#endif /* #ifdef HAVE_TFE */ diff --git a/source/Tfe/Tfe.h b/source/Tfe/Tfe.h new file mode 100644 index 00000000..26ff5602 --- /dev/null +++ b/source/Tfe/Tfe.h @@ -0,0 +1,84 @@ +/* + * tfe.h - TFE ("The final ethernet" emulation. + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _TFE_H +#define _TFE_H + +#include "types.h" +#include + +/* define this only if VICE should write each and every frame received + and send into the VICE log + WARNING: The log grows very fast! +*/ +/** #define TFE_DEBUG_FRAMES **/ + +struct snapshot_s; + +extern int tfe_enabled; + +extern void tfe_init(void); +extern int tfe_resources_init(void); +extern int tfe_cmdline_options_init(void); +extern int update_tfe_interface(void *v, void *param); +void get_disabled_state(int * param); + +extern void tfe_reset(void); +extern void tfe_shutdown(void); +extern BYTE REGPARM1 tfe_read(WORD addr); +extern void REGPARM2 tfe_store(WORD addr, BYTE byte); +extern int tfe_read_snapshot_module(struct snapshot_s *s); +extern int tfe_write_snapshot_module(struct snapshot_s *s); +extern BYTE __stdcall TfeIo (WORD programcounter, BYTE address, BYTE write, BYTE value, ULONG nCycles); + +/* + These functions let the UI enumerate the available interfaces. + + First, tfe_enumadapter_open() is used to start enumeration. + + tfe_enum_adapter is then used to gather information for each adapter present + on the system, where: + + ppname points to a pointer which will hold the name of the interface + ppdescription points to a pointer which will hold the description of the interface + + For each of these parameters, new memory is allocated, so it has to be + freed with lib_free(). + + tfe_enumadapter_close() must be used to stop processing. + + Each function returns 1 on success, and 0 on failure. + tfe_enumadapter() only fails if there is no more adpater; in this case, + *ppname and *ppdescription are not altered. +*/ +extern int tfe_enumadapter_open(void); +extern int tfe_enumadapter(char **ppname, char **ppdescription); +extern int tfe_enumadapter_close(void); + + +extern FILE* g_fh; // Filehandle for log file + +#endif diff --git a/source/Tfe/Tfearch.cpp b/source/Tfe/Tfearch.cpp new file mode 100644 index 00000000..fa4dbf0b --- /dev/null +++ b/source/Tfe/Tfearch.cpp @@ -0,0 +1,564 @@ +/* + * tfearch.c - TFE ("The final ethernet") emulation, + * architecture-dependant stuff + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +/* #define WPCAP */ + +#include "pcap.h" + +#include +#include +#include +#include + +#include "tfe.h" +#include "tfearch.h" +#include "tfesupp.h" + + +typedef pcap_t *(*pcap_open_live_t)(const char *, int, int, int, char *); +typedef int (*pcap_dispatch_t)(pcap_t *, int, pcap_handler, u_char *); +typedef int (*pcap_setnonblock_t)(pcap_t *, int, char *); +typedef int (*pcap_datalink_t)(pcap_t *); +typedef int (*pcap_findalldevs_t)(pcap_if_t **, char *); +typedef void (*pcap_freealldevs_t)(pcap_if_t *); +typedef int (*pcap_sendpacket_t)(pcap_t *p, u_char *buf, int size); + +/** #define TFE_DEBUG_ARCH 1 **/ +/** #define TFE_DEBUG_PKTDUMP 1 **/ + +/* #define TFE_DEBUG_FRAMES - might be defined in TFE.H! */ + +#define TFE_DEBUG_WARN 1 /* this should not be deactivated */ + +static pcap_open_live_t p_pcap_open_live; +static pcap_dispatch_t p_pcap_dispatch; +static pcap_setnonblock_t p_pcap_setnonblock; +static pcap_findalldevs_t p_pcap_findalldevs; +static pcap_freealldevs_t p_pcap_freealldevs; +static pcap_sendpacket_t p_pcap_sendpacket; +static pcap_datalink_t p_pcap_datalink; + +static HINSTANCE pcap_library = NULL; + + +/* ------------------------------------------------------------------------- */ +/* variables needed */ + + +//static log_t g_fh = g_fh; + + +static pcap_if_t *TfePcapNextDev = NULL; +static pcap_if_t *TfePcapAlldevs = NULL; +static pcap_t *TfePcapFP = NULL; + +static char TfePcapErrbuf[PCAP_ERRBUF_SIZE]; + +#ifdef TFE_DEBUG_PKTDUMP + +static +void debug_output( const char *text, BYTE *what, int count ) +{ + char buffer[256]; + char *p = buffer; + char *pbuffer1 = what; + int len1 = count; + int i; + + sprintf(buffer, "\n%s: length = %u\n", text, len1); + OutputDebugString(buffer); + do { + p = buffer; + for (i=0; (i<8) && len1>0; len1--, i++) { + sprintf( p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++); + p += 3; + } + *(p-1) = '\n'; *p = 0; + OutputDebugString(buffer); + } while (len1>0); +} +#endif // #ifdef TFE_DEBUG_PKTDUMP + + +static +void TfePcapFreeLibrary(void) +{ + if (pcap_library) { + if (!FreeLibrary(pcap_library)) { + if(g_fh) fprintf(g_fh, "FreeLibrary WPCAP.DLL failed!"); + } + pcap_library = NULL; + + p_pcap_open_live = NULL; + p_pcap_dispatch = NULL; + p_pcap_setnonblock = NULL; + p_pcap_findalldevs = NULL; + p_pcap_freealldevs = NULL; + p_pcap_sendpacket = NULL; + p_pcap_datalink = NULL; + } +} + +/* since I don't like typing too much... */ +#define GET_PROC_ADDRESS_AND_TEST( _name_ ) \ + p_##_name_ = (_name_##_t) GetProcAddress(pcap_library, #_name_ ); \ + if (!p_##_name_ ) { \ + if(g_fh) fprintf(g_fh, "GetProcAddress " #_name_ " failed!"); \ + TfePcapFreeLibrary(); \ + return FALSE; \ + } + +static +BOOL TfePcapLoadLibrary(void) +{ + if (!pcap_library) { + pcap_library = LoadLibrary("wpcap.dll"); + + if (!pcap_library) { + if(g_fh) fprintf(g_fh, "LoadLibrary WPCAP.DLL failed!" ); + return FALSE; + } + + GET_PROC_ADDRESS_AND_TEST(pcap_open_live); + GET_PROC_ADDRESS_AND_TEST(pcap_dispatch); + GET_PROC_ADDRESS_AND_TEST(pcap_setnonblock); + GET_PROC_ADDRESS_AND_TEST(pcap_findalldevs); + GET_PROC_ADDRESS_AND_TEST(pcap_freealldevs); + GET_PROC_ADDRESS_AND_TEST(pcap_sendpacket); + GET_PROC_ADDRESS_AND_TEST(pcap_datalink); + } + + return TRUE; +} + +#undef GET_PROC_ADDRESS_AND_TEST + + + +static +void TfePcapCloseAdapter(void) +{ + if (TfePcapAlldevs) { + (*p_pcap_freealldevs)(TfePcapAlldevs); + TfePcapAlldevs = NULL; + } +} + +/* + These functions let the UI enumerate the available interfaces. + + First, TfeEnumAdapterOpen() is used to start enumeration. + + TfeEnumAdapter is then used to gather information for each adapter present + on the system, where: + + ppname points to a pointer which will hold the name of the interface + ppdescription points to a pointer which will hold the description of the interface + + For each of these parameters, new memory is allocated, so it has to be + freed with lib_free(). + + TfeEnumAdapterClose() must be used to stop processing. + + Each function returns 1 on success, and 0 on failure. + TfeEnumAdapter() only fails if there is no more adpater; in this case, + *ppname and *ppdescription are not altered. +*/ +int tfe_arch_enumadapter_open(void) +{ + if (!TfePcapLoadLibrary()) { + return 0; + } + + if ((*p_pcap_findalldevs)(&TfePcapAlldevs, TfePcapErrbuf) == -1) + { + if(g_fh) fprintf(g_fh, "ERROR in TfeEnumAdapterOpen: pcap_findalldevs: '%s'", TfePcapErrbuf); + return 0; + } + + if (!TfePcapAlldevs) { + if(g_fh) fprintf(g_fh, "ERROR in TfeEnumAdapterOpen, finding all pcap devices - " + "Do we have the necessary privilege rights?"); + return 0; + } + + TfePcapNextDev = TfePcapAlldevs; + + return 1; +} + +int tfe_arch_enumadapter(char **ppname, char **ppdescription) +{ + if (!TfePcapNextDev) + return 0; + + *ppname = lib_stralloc(TfePcapNextDev->name); + *ppdescription = lib_stralloc(TfePcapNextDev->description); + + TfePcapNextDev = TfePcapNextDev->next; + + return 1; +} + +int tfe_arch_enumadapter_close(void) +{ + if (TfePcapAlldevs) { + (*p_pcap_freealldevs)(TfePcapAlldevs); + TfePcapAlldevs = NULL; + } + return 1; +} + +static +BOOL TfePcapOpenAdapter(const char *interface_name) +{ + pcap_if_t *TfePcapDevice = NULL; + + if (!tfe_enumadapter_open()) { + return FALSE; + } + else { + /* look if we can find the specified adapter */ + char *pname; + char *pdescription; + BOOL found = FALSE; + + if (interface_name) { + /* we have an interface name, try it */ + TfePcapDevice = TfePcapAlldevs; + + while (tfe_enumadapter(&pname, &pdescription)) { + if (strcmp(pname, interface_name)==0) { + found = TRUE; + } + lib_free(pname); + lib_free(pdescription); + if (found) break; + TfePcapDevice = TfePcapNextDev; + } + } + + if (!found) { + /* just take the first adapter */ + TfePcapDevice = TfePcapAlldevs; + } + } + + TfePcapFP = (*p_pcap_open_live)(TfePcapDevice->name, 1700, 1, 20, TfePcapErrbuf); + if ( TfePcapFP == NULL) + { + if(g_fh) fprintf(g_fh, "ERROR opening adapter: '%s'", TfePcapErrbuf); + tfe_enumadapter_close(); + return FALSE; + } + + if ((*p_pcap_setnonblock)(TfePcapFP, 1, TfePcapErrbuf)<0) + { + if(g_fh) fprintf(g_fh, "WARNING: Setting PCAP to non-blocking failed: '%s'", TfePcapErrbuf); + } + + /* Check the link layer. We support only Ethernet for simplicity. */ + if((*p_pcap_datalink)(TfePcapFP) != DLT_EN10MB) + { + if(g_fh) fprintf(g_fh, "ERROR: TFE works only on Ethernet networks."); + tfe_enumadapter_close(); + return FALSE; + } + + tfe_enumadapter_close(); + return TRUE; +} + + +/* ------------------------------------------------------------------------- */ +/* the architecture-dependend functions */ + + +int tfe_arch_init(void) +{ + // g_fh = log_open("TFEARCH"); + + if (!TfePcapLoadLibrary()) { + return 0; + } + + return 1; +} + +void tfe_arch_pre_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_pre_reset()." ); +#endif +} + +void tfe_arch_post_reset( void ) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_post_reset()." ); +#endif +} + +int tfe_arch_activate(const char *interface_name) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_activate()." ); +#endif + if (!TfePcapOpenAdapter(interface_name)) { + return 0; + } + return 1; +} + +void tfe_arch_deactivate( void ) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_deactivate()." ); +#endif +} + +void tfe_arch_set_mac( const BYTE mac[6] ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + if(g_fh) fprintf( g_fh, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] ); +#endif +} + +void tfe_arch_set_hashfilter(const DWORD hash_mask[2]) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + if(g_fh) fprintf( g_fh, "New hash filter set: %08X:%08X.", + hash_mask[1], hash_mask[0]); +#endif +} + + +/* +void tfe_arch_receive_remove_committed_frame(void) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_receive_remove_committed_frame()." ); +#endif +} +*/ + +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + if(g_fh) { + fprintf( g_fh, "tfe_arch_recv_ctl() called with the following parameters:" ); + fprintf( g_fh, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbIA = %s", bIA ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE" ); + } +#endif +} + +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver ) +{ +#if defined(TFE_DEBUG_ARCH) || defined(TFE_DEBUG_FRAMES) + if(g_fh) { + fprintf( g_fh, "tfe_arch_line_ctl() called with the following parameters:" ); + fprintf( g_fh, "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE" ); + fprintf( g_fh, "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE" ); + } +#endif +} + + +typedef struct TFE_PCAP_INTERNAL_tag { + + unsigned int len; + BYTE *buffer; + +} TFE_PCAP_INTERNAL; + +/* Callback function invoked by libpcap for every incoming packet */ +static +void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) +{ + /* RGJ changed from void to TFE_PCAP_INTERNAL for AppleWin */ + TFE_PCAP_INTERNAL *pinternal = (TFE_PCAP_INTERNAL *)param; + + /* determine the count of bytes which has been returned, + * but make sure not to overrun the buffer + */ + if (header->caplen < pinternal->len) + pinternal->len = header->caplen; + + memcpy(pinternal->buffer, pkt_data, pinternal->len); +} + +/* the following function receives a frame. + + If there's none, it returns a -1. + If there is one, it returns the length of the frame in bytes. + + It copies the frame to *buffer and returns the number of copied + bytes as return value. + + At most 'len' bytes are copied. +*/ +static +int tfe_arch_receive_frame(TFE_PCAP_INTERNAL *pinternal) +{ + int ret = -1; + + /* check if there is something to receive */ + /* RGJ changed from void to u_char for AppleWin */ + if ((*p_pcap_dispatch)(TfePcapFP, 1, TfePcapPacketHandler, (u_char *)pinternal)!=0) { + /* Something has been received */ + ret = pinternal->len; + } + +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_receive_frame() called, returns %d.", ret ); +#endif + + return ret; +} + +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + BYTE *txframe /* Pointer to the frame to be transmitted */ + ) +{ +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_transmit() called, with: " + "force = %s, onecoll = %s, inhibit_crc=%s, tx_pad_dis=%s, txlength=%u", + force ? "TRUE" : "FALSE", + onecoll ? "TRUE" : "FALSE", + inhibit_crc ? "TRUE" : "FALSE", + tx_pad_dis ? "TRUE" : "FALSE", + txlength + ); +#endif + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Transmit frame: ", txframe, txlength); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if ((*p_pcap_sendpacket)(TfePcapFP, txframe, txlength) == -1) { + if(g_fh) fprintf(g_fh, "WARNING! Could not send packet!"); + } +} + +/* + tfe_arch_receive() + + This function checks if there was a frame received. + If so, it returns 1, else 0. + + If there was no frame, none of the parameters is changed! + + If there was a frame, the following actions are done: + + - at maximum *plen byte are transferred into the buffer given by pbuffer + - *plen gets the length of the received frame, EVEN if this is more + than has been copied to pbuffer! + - if the dest. address was accepted by the hash filter, *phashed is set, else + cleared. + - if the dest. address was accepted by the hash filter, *phash_index is + set to the number of the rule leading to the acceptance + - if the receive was ok (good CRC and valid length), *prx_ok is set, + else cleared. + - if the dest. address was accepted because it's exactly our MAC address + (set by tfe_arch_set_mac()), *pcorrect_mac is set, else cleared. + - if the dest. address was accepted since it was a broadcast address, + *pbroadcast is set, else cleared. + - if the received frame had a crc error, *pcrc_error is set, else cleared +*/ +int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ) +{ + int len; + + TFE_PCAP_INTERNAL internal = { *plen, pbuffer }; + + +#ifdef TFE_DEBUG_ARCH + if(g_fh) fprintf( g_fh, "tfe_arch_receive() called, with *plen=%u.", *plen ); +#endif + + assert((*plen&1)==0); + + len = tfe_arch_receive_frame(&internal); + + if (len!=-1) { + +#ifdef TFE_DEBUG_PKTDUMP + debug_output( "Received frame: ", internal.buffer, internal.len ); +#endif // #ifdef TFE_DEBUG_PKTDUMP + + if (len&1) + ++len; + + *plen = len; + + /* we don't decide if this frame fits the needs; + * by setting all zero, we let tfe.c do the work + * for us + */ + *phashed = + *phash_index = + *pbroadcast = + *pcorrect_mac = + *pcrc_error = 0; + + /* this frame has been received correctly */ + *prx_ok = 1; + + return 1; + } + + return 0; +} + +//#endif /* #ifdef HAVE_TFE */ diff --git a/source/Tfe/Tfearch.h b/source/Tfe/Tfearch.h new file mode 100644 index 00000000..13e625ab --- /dev/null +++ b/source/Tfe/Tfearch.h @@ -0,0 +1,91 @@ +/* + * tfearch.h - TFE ("The final ethernet") emulation. + * architecture-dependant stuff + * + * Written by + * Spiro Trikaliotis + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _TFEARCH_H +#define _TFEARCH_H + +#include "types.h" + +extern int tfe_arch_init(void); +extern void tfe_arch_pre_reset(void); +extern void tfe_arch_post_reset(void); +extern int tfe_arch_activate(const char *interface_name); +extern void tfe_arch_deactivate(void); +extern void tfe_arch_set_mac(const BYTE mac[6]); +extern void tfe_arch_set_hashfilter(const DWORD hash_mask[2]); + +extern +void tfe_arch_recv_ctl( int bBroadcast, /* broadcast */ + int bIA, /* individual address (IA) */ + int bMulticast, /* multicast if address passes the hash filter */ + int bCorrect, /* accept correct frames */ + int bPromiscuous, /* promiscuous mode */ + int bIAHash /* accept if IA passes the hash filter */ + ); + +extern +void tfe_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver); + +extern +void tfe_arch_transmit(int force, /* FORCE: Delete waiting frames in transmit buffer */ + int onecoll, /* ONECOLL: Terminate after just one collision */ + int inhibit_crc, /* INHIBITCRC: Do not append CRC to the transmission */ + int tx_pad_dis, /* TXPADDIS: Disable padding to 60 Bytes */ + int txlength, /* Frame length */ + BYTE *txframe /* Pointer to the frame to be transmitted */ + ); + +extern +int tfe_arch_receive(BYTE *pbuffer , /* where to store a frame */ + int *plen, /* IN: maximum length of frame to copy; + OUT: length of received frame + OUT can be bigger than IN if received frame was + longer than supplied buffer */ + int *phashed, /* set if the dest. address is accepted by the hash filter */ + int *phash_index, /* hash table index if hashed == TRUE */ + int *prx_ok, /* set if good CRC and valid length */ + int *pcorrect_mac, /* set if dest. address is exactly our IA */ + int *pbroadcast, /* set if dest. address is a broadcast address */ + int *pcrc_error /* set if received frame had a CRC error */ + ); + +/* + This is a helper for tfe_receive() to determine if the received frame should be accepted + according to the settings. + + This function is even allowed to be called in tfearch.c from tfe_arch_receive() if + necessary, which is the reason why its prototype is included here in tfearch.h. +*/ +extern +int tfe_should_accept(unsigned char *buffer, int length, int *phashed, int *phash_index, + int *pcorrect_mac, int *pbroadcast, int *pmulticast); + +extern int tfe_arch_enumadapter_open(void); +extern int tfe_arch_enumadapter(char **ppname, char **ppdescription); +extern int tfe_arch_enumadapter_close(void); + +#endif diff --git a/source/Tfe/Tfesupp.cpp b/source/Tfe/Tfesupp.cpp new file mode 100644 index 00000000..ee845401 --- /dev/null +++ b/source/Tfe/Tfesupp.cpp @@ -0,0 +1,188 @@ +/* + * This file is a consolidation of functions required for tfe + * emulation taken from the following files + * + * lib.c - Library functions. + * util.c - Miscellaneous utility functions. + * crc32.c + * + * Written by + * Andreas Boose + * Ettore Perazzoli + * Andreas Matthies + * Tibor Biczo + * Spiro Trikaliotis * + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tfesupp.h" + + +// Lib Stuff +/* #define LIB_DEBUG*/ + + +#ifdef LIB_DEBUG +#define LIB_DEBUG_SIZE 0x10000 +#define LIB_DEBUG_GUARD 0x1000 +#endif + +#define CRC32_POLY 0xedb88320 +static unsigned long crc32_table[256]; +static int crc32_is_initialized = 0; + +void lib_free(void *ptr) +{ +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 1); +#endif + +#ifdef LIB_DEBUG + lib_debug_libc_free(ptr); +#else + free(ptr); +#endif +} + +void *lib_malloc(size_t size) +{ +#ifdef LIB_DEBUG + void *ptr = lib_debug_libc_malloc(size); +#else + void *ptr = malloc(size); +#endif + +#ifndef __OS2__ + if (ptr == NULL && size > 0) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_alloc(ptr, size, 3); +#endif + + return ptr; +} + +/*-----------------------------------------------------------------------*/ + +/* Malloc enough space for `str', copy `str' into it and return its + address. */ +char *lib_stralloc(const char *str) +{ + size_t size; + char *ptr; + + if (str == NULL) + exit(-1); + + size = strlen(str) + 1; + ptr = (char *)lib_malloc(size); + + memcpy(ptr, str, size); + return ptr; +} + + + +/* Like realloc, but abort if not enough memory is available. */ +void *lib_realloc(void *ptr, size_t size) +{ +#ifdef LIB_DEBUG + void *new_ptr = lib_debug_libc_realloc(ptr, size); +#else + void *new_ptr = realloc(ptr, size); +#endif + +#ifndef __OS2__ + if (new_ptr == NULL) + exit(-1); +#endif +#ifdef LIB_DEBUG + lib_debug_free(ptr, 1, 0); + lib_debug_alloc(new_ptr, size, 1); +#endif + + return new_ptr; +} + +// Util Stuff + +/* Set a new value to the dynamically allocated string *str. + Returns `-1' if nothing has to be done. */ +int util_string_set(char **str, const char *new_value) +{ + if (*str == NULL) { + if (new_value != NULL) + *str = lib_stralloc(new_value); + } else { + if (new_value == NULL) { + lib_free(*str); + *str = NULL; + } else { + /* Skip copy if src and dest are already the same. */ + if (strcmp(*str, new_value) == 0) + return -1; + + *str = (char *)lib_realloc(*str, strlen(new_value) + 1); + strcpy(*str, new_value); + } + } + return 0; +} + + +// crc32 Stuff + +unsigned long crc32_buf(const char *buffer, unsigned int len) +{ + int i, j; + unsigned long crc, c; + const char *p; + + if (!crc32_is_initialized) { + for (i = 0; i < 256; i++) { + c = (unsigned long) i; + for (j = 0; j < 8; j++) + c = c & 1 ? CRC32_POLY ^ (c >> 1) : c >> 1; + crc32_table[i] = c; + } + crc32_is_initialized = 1; + } + + crc = 0xffffffff; + for (p = buffer; len > 0; ++p, --len) + crc = (crc >> 8) ^ crc32_table[(crc ^ *p) & 0xff]; + + return ~crc; +} + diff --git a/source/Tfe/Tfesupp.h b/source/Tfe/Tfesupp.h new file mode 100644 index 00000000..67c54651 --- /dev/null +++ b/source/Tfe/Tfesupp.h @@ -0,0 +1,53 @@ +/* + * This file is a consolidation of functions required for tfe + * emulation taken from the following files + * + * lib.h - Library functions. + * util.h - Miscellaneous utility functions. + * crc32.h + * + * Written by + * Andreas Boose + * Ettore Perazzoli + * Manfred Spraul + * Andreas Matthies + * Tibor Biczo + * Spiro Trikaliotis * + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + + + +#ifndef _TFESUPP_H +#define _TFESUPP_H + +extern FILE* g_fh; // Filehandle for log file + +extern void *lib_malloc(size_t size); +extern void *lib_realloc(void *p, size_t size); +extern void lib_free(void *ptr); +extern char *lib_stralloc(const char *str); + +extern int util_string_set(char **str, const char *new_value); + +extern unsigned long crc32_buf(const char *buffer, unsigned int len); + +#endif diff --git a/source/Tfe/Types.h b/source/Tfe/Types.h new file mode 100644 index 00000000..ceb9b4ea --- /dev/null +++ b/source/Tfe/Types.h @@ -0,0 +1,73 @@ +/* + * types.h - Type definitions for VICE. + * + * Written by + * Ettore Perazzoli + * André Fachat + * Teemu Rantanen + * Andreas Boose + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _TYPES_H +#define _TYPES_H + +#ifndef BYTE +#define BYTE unsigned char +#endif + +#ifndef WORD +#define WORD unsigned short +#endif + +#ifndef DWORD + //#ifdef DWORD_IS_LONG + #define DWORD unsigned long + //#else + //#define DWORD unsigned int + //#endif +#endif + +/* RGJ added for AppleWin */ +#ifndef ULONG +typedef unsigned long ULONG; +#endif + +typedef signed char SIGNED_CHAR; +typedef signed short SWORD; +typedef signed int SDWORD; + +typedef DWORD CLOCK; +/* Maximum value of a CLOCK. */ +#define CLOCK_MAX (~((CLOCK)0)) + +#if defined(__GNUC__) && defined(__i386__) && !defined(NO_REGPARM) +#define REGPARM1 __attribute__((regparm(1))) +#define REGPARM2 __attribute__((regparm(2))) +#define REGPARM3 __attribute__((regparm(3))) +#else +#define REGPARM1 +#define REGPARM2 +#define REGPARM3 +#endif + +#endif + diff --git a/source/Tfe/Uilib.cpp b/source/Tfe/Uilib.cpp new file mode 100644 index 00000000..262c5883 --- /dev/null +++ b/source/Tfe/Uilib.cpp @@ -0,0 +1,128 @@ +/* + * uilib.c - Common UI elements for the Windows user interface. + * + * Written by + * Ettore Perazzoli + * Andreas Boose + * Manfred Spraul + * Andreas Matthies + * Tibor Biczo + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "uilib.h" + + + + +/* Mingw & pre VC 6 headers doesn't have this definition */ +#ifndef OFN_ENABLESIZING +#define OFN_ENABLESIZING 0x00800000 +#endif + +void uilib_get_general_window_extents(HWND hwnd, int *xsize, int *ysize) +{ + HDC hdc; + HFONT hFont; + HFONT hOldFont; + int strlen; + char *buffer; + SIZE size; + + hFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); + strlen = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0); + /* RGJ added cast for AppleWin */ + buffer = (char *) malloc(strlen + 1); + GetWindowText(hwnd, buffer, strlen + 1); + + hdc = GetDC(hwnd); + hOldFont = (HFONT)SelectObject(hdc, hFont); + + GetTextExtentPoint32(hdc, buffer, strlen, &size); + + free(buffer); + + SelectObject(hdc, hOldFont); + ReleaseDC(hwnd, hdc); + + *xsize = size.cx; + *ysize = size.cy; +} + +void uilib_get_group_extent(HWND hwnd, uilib_dialog_group *group, int *xsize, int *ysize) +{ +HWND element; +int x; +int y; + + if (xsize && ysize) { + *xsize = 0; + *ysize = 0; + while (group->idc) { + element = GetDlgItem(hwnd, group->idc); + uilib_get_general_window_extents(element, &x, &y); + if (group->element_type == 1) x += 20; + if (*xsize < x) *xsize = x; + *ysize += y; + group++; + } + } +} + + +void uilib_move_group(HWND hwnd, uilib_dialog_group *group, int xpos) +{ +HWND element; +RECT element_rect; + + while (group->idc) { + element = GetDlgItem(hwnd, group->idc); + GetClientRect(element, &element_rect); + MapWindowPoints(element, hwnd, (POINT*)&element_rect, 2); + MoveWindow(element, xpos, element_rect.top, element_rect.right - element_rect.left, element_rect.bottom - element_rect.top, TRUE); + group++; + } +} + +void uilib_adjust_group_width(HWND hwnd, uilib_dialog_group *group) +{ +HWND element; +RECT element_rect; +int xsize; +int ysize; + + while (group->idc) { + element = GetDlgItem(hwnd, group->idc); + GetClientRect(element, &element_rect); + MapWindowPoints(element, hwnd, (POINT*)&element_rect, 2); + uilib_get_general_window_extents(element, &xsize, &ysize); + if (group->element_type == 1) xsize += 20; + MoveWindow(element, element_rect.left, element_rect.top, xsize, element_rect.bottom - element_rect.top, TRUE); + group++; + } +} diff --git a/source/Tfe/Uilib.h b/source/Tfe/Uilib.h new file mode 100644 index 00000000..f8ec8c8e --- /dev/null +++ b/source/Tfe/Uilib.h @@ -0,0 +1,53 @@ +/* + * uilib.h - Common UI elements for the Windows user interface. + * + * Written by + * Ettore Perazzoli + * Andreas Boose + * Manfred Spraul + * + * This file is part of VICE, the Versatile Commodore Emulator. + * See README for copyright notice. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _UILIB_H +#define _UILIB_H + +#include +#include + +extern void uilib_get_general_window_extents(HWND hwnd, int *xsize, int *ysize); + +typedef struct { + unsigned int idc; + int element_type; +} uilib_dialog_group; + +extern void uilib_get_group_extent(HWND hwnd, uilib_dialog_group *group, int *xsize, int *ysize); +extern void uilib_move_group(HWND hwnd, uilib_dialog_group *group, int xpos); +extern void uilib_adjust_group_width(HWND hwnd, uilib_dialog_group *group); + +typedef struct { + unsigned int idc; + unsigned int ids; + int element_type; +} uilib_localize_dialog_param; + +#endif +