Merge native support for Uthernet II from AppleWin.

Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2022-02-27 20:42:40 +00:00
parent 9006e39eaa
commit bbb5783fa6
16 changed files with 96 additions and 1385 deletions

View file

@ -31,9 +31,10 @@ endif()
find_package(Boost REQUIRED)
set(SOURCE_FILES
Tfe/tfe.cpp
Tfe/tfearch.cpp
Tfe/tfesupp.cpp
Tfe/NetworkBackend.cpp
Tfe/PCapBackend.cpp
Debugger/Debug.cpp
Debugger/Debugger_Help.cpp
@ -48,6 +49,8 @@ set(SOURCE_FILES
Debugger/Debugger_Commands.cpp
Debugger/Util_MemoryTextFile.cpp
Uthernet1.cpp
Uthernet2.cpp
StrFormat.cpp
6522.cpp
VidHD.cpp
@ -99,8 +102,6 @@ set(SOURCE_FILES
linux/linuxframe.cpp
linux/context.cpp
linux/tape.cpp
linux/network/uthernet2.cpp
linux/network/tfe2.cpp
linux/network/slirp2.cpp
linux/duplicates/Debugger_Display.cpp
@ -119,6 +120,14 @@ set(SOURCE_FILES
)
set(HEADER_FILES
Tfe/tfearch.h
Tfe/tfesupp.h
Tfe/NetworkBackend.h
Tfe/PCapBackend.h
Uthernet1.h
Uthernet2.h
W5100.h
6522.h
VidHD.h
SSI263.h
@ -195,10 +204,7 @@ set(HEADER_FILES
linux/keyboard.h
linux/linuxframe.h
linux/tape.h
linux/network/uthernet2.h
linux/network/tfe2.h
linux/network/slirp2.h
linux/network/registers.h
Z80VICE/z80.h
Z80VICE/z80mem.h

View file

@ -43,7 +43,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Uthernet1.h"
#include "Uthernet2.h"
#include "VidHD.h"
#include "linux/network/uthernet2.h"
#include "LanguageCard.h"
#include "Memory.h"
@ -96,9 +95,6 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
case CT_Uthernet:
m_slot[slot] = new Uthernet1(slot);
break;
case CT_Uthernet2:
m_slot[slot] = new Uthernet2(slot);
break;
case CT_FourPlay:
m_slot[slot] = new FourPlayCard(slot);
break;

View file

@ -71,6 +71,7 @@ typedef UINT64 uint64_t;
#include <algorithm>
#include <string>
#include <vector>
#include <cassert>
#include "windows.h"

View file

@ -438,7 +438,7 @@ void TfePcapPacketHandler(u_char *param, const struct pcap_pkthdr *header, const
/* determine the count of bytes which has been returned,
* but make sure not to overrun the buffer
*/
pinternal->rxlength = min(pinternal->size, header->caplen);
pinternal->rxlength = std::min(pinternal->size, header->caplen);
memcpy(pinternal->buffer, pkt_data, pinternal->rxlength);
}

View file

@ -23,8 +23,8 @@
#include "Debugger/Debugger_Types.h"
#include "Tfe/tfe.h"
#include "Tfe/tfesupp.h"
#include "Tfe/PCapBackend.h"
namespace
{
@ -359,22 +359,22 @@ namespace sa2
ImGui::Separator();
const std::string current_interface = get_tfe_interface();
const std::string current_interface = PCapBackend::tfe_interface;
if (ImGui::BeginCombo("pcap", current_interface.c_str()))
{
std::vector<char *> ifaces;
if (tfe_enumadapter_open())
if (PCapBackend::tfe_enumadapter_open())
{
char *pname;
char *pdescription;
while (tfe_enumadapter(&pname, &pdescription))
while (PCapBackend::tfe_enumadapter(&pname, &pdescription))
{
ifaces.push_back(pname);
lib_free(pdescription);
}
tfe_enumadapter_close();
PCapBackend::tfe_enumadapter_close();
for (const auto & iface : ifaces)
{
@ -382,8 +382,8 @@ namespace sa2
if (ImGui::Selectable(iface, isSelected))
{
// the following line interacts with tfe_enumadapter, so we must run it outside the above loop
update_tfe_interface(iface);
tfe_SetRegistryInterface(SLOT3, iface);
PCapBackend::tfe_interface = iface;
PCapBackend::tfe_SetRegistryInterface(SLOT3, PCapBackend::tfe_interface);
}
if (isSelected)
{

View file

@ -7,7 +7,6 @@
#include "Interface.h"
#include "Debugger/Debug.h"
#include "Tfe/tfe.h"
#include "frontends/sdl/imgui/settingshelper.h"
#include "frontends/sdl/imgui/glselector.h"

View file

@ -6,6 +6,8 @@
#include "linux/paddle.h"
#include "linux/duplicates/PropertySheet.h"
#include "Debugger/Debug.h"
#include "Interface.h"
#include "Log.h"
#include "Utilities.h"
@ -17,8 +19,9 @@
#include "Memory.h"
#include "Speaker.h"
#include "MouseInterface.h"
#include "Debugger/Debug.h"
#include "Mockingboard.h"
#include "Uthernet1.h"
#include "Uthernet2.h"
namespace
@ -147,11 +150,20 @@ void DestroyEmulator()
MB_Destroy();
DSUninit();
tfe_shutdown();
if (cardManager.QuerySlot(SLOT7) == CT_GenericHDD)
for (UINT i = 0; i < NUM_SLOTS; ++i)
{
dynamic_cast<HarddiskInterfaceCard&>(cardManager.GetRef(SLOT7)).Destroy();
switch (cardManager.QuerySlot(i))
{
case CT_GenericHDD:
dynamic_cast<HarddiskInterfaceCard&>(cardManager.GetRef(i)).Destroy();
break;
case CT_Uthernet:
dynamic_cast<Uthernet1&>(cardManager.GetRef(i)).Destroy();
break;
case CT_Uthernet2:
dynamic_cast<Uthernet2&>(cardManager.GetRef(i)).Destroy();
break;
}
}
PrintDestroy();

View file

@ -1,6 +1,8 @@
#include "StdAfx.h"
#include "linux/linuxframe.h"
#include "linux/context.h"
#include "linux/network/slirp2.h"
#include "Tfe/PCapBackend.h"
#include "Interface.h"
#include "Log.h"
#include "Core.h"
@ -128,6 +130,15 @@ void LinuxFrame::Restart()
Begin();
}
std::shared_ptr<NetworkBackend> LinuxFrame::CreateNetworkBackend()
{
#ifdef U2_USE_SLIRP
return std::make_shared<SlirpBackend>();
#else
return std::make_shared<PCapBackend>(PCapBackend::tfe_interface);
#endif
}
int MessageBox(HWND, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
return GetFrame().FrameMessageBox(lpText, lpCaption, uType);

View file

@ -27,6 +27,8 @@ public:
void Restart() override; // calls End() - Begin()
void GetBitmap(LPCSTR lpBitmapName, LONG cb, LPVOID lpvBits) override;
std::shared_ptr<NetworkBackend> CreateNetworkBackend() override;
void CycleVideoType();
void Cycle50ScanLines();

View file

@ -1,83 +0,0 @@
#pragma once
// Uthernet II registers
#define C0X_MODE_REGISTER 0x04
#define C0X_ADDRESS_HIGH 0x05
#define C0X_ADDRESS_LOW 0x06
#define C0X_DATA_PORT 0x07
// W5100 registers and values
#define MR 0x0000
#define GAR0 0x0001
#define GAR3 0x0004
#define SUBR0 0x0005
#define SUBR3 0x0008
#define SHAR0 0x0009
#define SHAR5 0x000E
#define SIPR0 0x000F
#define SIPR3 0x0012
#define RTR0 0x0017
#define RTR1 0x0018
#define RMSR 0x001A
#define TMSR 0x001B
#define UPORT1 0x002F
#define S0_BASE 0x0400
#define S3_MAX 0x07FF
#define TX_BASE 0x4000
#define RX_BASE 0x6000
#define MEM_MAX 0x7FFF
#define MEM_SIZE 0x8000
#define MR_IND 0x01 // 0
#define MR_AI 0x02 // 1
#define MR_PPOE 0x08 // 3
#define MR_PB 0x10 // 4
#define MR_RST 0x80 // 7
#define SN_MR_PROTO_MASK 0x0F
#define SN_MR_CLOSED 0x00
#define SN_MR_TCP 0x01
#define SN_MR_UDP 0x02
#define SN_MR_IPRAW 0x03
#define SN_MR_MACRAW 0x04
#define SN_MR_PPPOE 0x05
#define SN_CR_OPEN 0x01
#define SN_CR_LISTENT 0x02
#define SN_CR_CONNECT 0x04
#define SN_CR_DISCON 0x08
#define SN_CR_CLOSE 0x10
#define SN_CR_SEND 0x20
#define SN_CR_RECV 0x40
#define SN_MR 0x00
#define SN_CR 0x01
#define SN_SR 0x03
#define SN_PORT0 0x04
#define SN_PORT1 0x05
#define SN_DIPR0 0x0C
#define SN_DIPR3 0x0F
#define SN_DPORT0 0x10
#define SN_DPORT1 0x11
#define SN_PROTO 0x14
#define SN_TOS 0x15
#define SN_TTL 0x16
#define SN_TX_FSR0 0x20
#define SN_TX_FSR1 0x21
#define SN_TX_RD0 0x22
#define SN_TX_RD1 0x23
#define SN_TX_WR0 0x24
#define SN_TX_WR1 0x25
#define SN_RX_RSR0 0x26
#define SN_RX_RSR1 0x27
#define SN_RX_RD0 0x28
#define SN_RX_RD1 0x29
#define SN_SR_CLOSED 0x00
#define SN_SR_SOCK_INIT 0x13
#define SN_SR_ESTABLISHED 0x17
#define SN_SR_SOCK_UDP 0x22
#define SN_SR_SOCK_IPRAW 0x32
#define SN_SR_SOCK_MACRAW 0x42

View file

@ -39,7 +39,7 @@ namespace
ssize_t net_slirp_send_packet(const void *buf, size_t len, void *opaque)
{
SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
SlirpBackend * slirp = reinterpret_cast<SlirpBackend *>(opaque);
slirp->sendToGuest(reinterpret_cast<const uint8_t *>(buf), len);
return len;
}
@ -88,19 +88,19 @@ namespace
int net_slirp_add_poll(int fd, int events, void *opaque)
{
SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
SlirpBackend * slirp = reinterpret_cast<SlirpBackend *>(opaque);
return slirp->addPoll(fd, events);
}
int net_slirp_get_revents(int idx, void *opaque)
{
const SlirpNet * slirp = reinterpret_cast<SlirpNet *>(opaque);
const SlirpBackend * slirp = reinterpret_cast<SlirpBackend *>(opaque);
return slirp->getREvents(idx);
}
}
SlirpNet::SlirpNet()
SlirpBackend::SlirpBackend()
{
const SlirpConfig cfg =
{
@ -128,12 +128,33 @@ SlirpNet::SlirpNet()
mySlirp.reset(slirp, slirp_cleanup);
}
void SlirpNet::sendFromGuest(const uint8_t *pkt, const int pkt_len)
void SlirpBackend::transmit(const int txlength, uint8_t *txframe)
{
slirp_input(mySlirp.get(), pkt, pkt_len);
slirp_input(mySlirp.get(), txframe, txlength);
}
void SlirpNet::sendToGuest(const uint8_t *pkt, int pkt_len)
int SlirpBackend::receive(const int size, uint8_t * rxframe)
{
if (!myQueue.empty())
{
const std::vector<uint8_t> & packet = myQueue.front();
int received = std::min(static_cast<int>(packet.size()), size);
memcpy(rxframe, packet.data(), received);
if (received & 1)
{
rxframe[received] = 0;
++received;
}
myQueue.pop();
return received;
}
else
{
return -1;
}
}
void SlirpBackend::sendToGuest(const uint8_t *pkt, int pkt_len)
{
if (myQueue.size() < ourQueueSize)
{
@ -145,8 +166,9 @@ void SlirpNet::sendToGuest(const uint8_t *pkt, int pkt_len)
}
}
void SlirpNet::process(uint32_t timeout)
void SlirpBackend::update(const ULONG /* nExecutedCycles */)
{
uint32_t timeout = 0;
myFDs.clear();
slirp_pollfds_fill(mySlirp.get(), &timeout, net_slirp_add_poll, this);
int pollout;
@ -161,26 +183,21 @@ void SlirpNet::process(uint32_t timeout)
slirp_pollfds_poll(mySlirp.get(), (pollout <= 0), net_slirp_get_revents, this);
}
int SlirpNet::addPoll(const int fd, const int events)
int SlirpBackend::addPoll(const int fd, const int events)
{
const pollfd ff = { .fd = fd, .events = vdeslirp_slirp_to_poll(events) };
myFDs.push_back(ff);
return myFDs.size() - 1;
}
int SlirpNet::getREvents(const int idx) const
int SlirpBackend::getREvents(const int idx) const
{
return vdeslirp_poll_to_slirp(myFDs[idx].revents);
}
std::queue<std::vector<uint8_t>> & SlirpNet::getQueue()
bool SlirpBackend::isValid()
{
return myQueue;
}
void SlirpNet::clearQueue()
{
std::queue<std::vector<uint8_t>>().swap(myQueue);
return true;
}
#endif

View file

@ -1,5 +1,7 @@
#pragma once
#include "Tfe/NetworkBackend.h"
#include "linux/config.h"
#ifdef SLIRP_FOUND
@ -17,19 +19,21 @@
struct Slirp;
class SlirpNet
class SlirpBackend : public NetworkBackend
{
public:
SlirpNet();
void sendFromGuest(const uint8_t *pkt, int pkt_len);
SlirpBackend();
void transmit(const int txlength, uint8_t *txframe) override;
int receive(const int size, uint8_t * rxframe) override;
void update(const ULONG nExecutedCycles) override;
bool isValid() override;
void sendToGuest(const uint8_t *pkt, int pkt_len);
void process(const uint32_t timeout);
int addPoll(const int fd, const int events);
int getREvents(const int idx) const;
std::queue<std::vector<uint8_t>> & getQueue();
void clearQueue();
private:
static constexpr size_t ourQueueSize = 10;

View file

@ -1,96 +0,0 @@
#include "StdAfx.h"
#include "linux/network/tfe2.h"
#include "Tfe/tfearch.h"
#include "Tfe/tfe.h"
namespace
{
bool shouldAccept(const uint8_t * mac, const BYTE *buffer, const int len)
{
if (len < 6)
{
return false;
}
if (buffer[0] == mac[0] &&
buffer[1] == mac[1] &&
buffer[2] == mac[2] &&
buffer[3] == mac[3] &&
buffer[4] == mac[4] &&
buffer[5] == mac[5])
{
return true;
}
if (buffer[0] == 0xFF &&
buffer[1] == 0xFF &&
buffer[2] == 0xFF &&
buffer[3] == 0xFF &&
buffer[4] == 0xFF &&
buffer[5] == 0xFF)
{
return true;
}
return false;
}
}
void tfeTransmitOnePacket(const BYTE * buffer, const int len)
{
if (tfe_enabled)
{
tfe_arch_transmit(0, 0, 0, 0, len, const_cast<BYTE *>(buffer));
}
}
bool tfeReceiveOnePacket(const uint8_t * mac, const int size, BYTE * buffer, int & len)
{
if (!tfe_enabled)
{
return false;
}
bool done;
do
{
done = true;
int hashed;
int hash_index;
int rx_ok;
int correct_mac;
int broadcast;
int multicast = 0;
int crc_error;
len = size;
const int 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 */
);
if (newframe)
{
/* determine ourself the type of frame */
if (shouldAccept(mac, buffer, len))
{
return true;
}
else
{
done = false; /* try another frame */
}
}
} while (!done);
return false;
}

View file

@ -1,4 +0,0 @@
#pragma once
bool tfeReceiveOnePacket(const uint8_t * mac, const int size, BYTE * buffer, int & len);
void tfeTransmitOnePacket(const BYTE * buffer, const int len);

File diff suppressed because it is too large Load diff

View file

@ -1,100 +0,0 @@
#pragma once
#include "Card.h"
#include <vector>
class SlirpNet;
struct Socket
{
uint16_t transmitBase;
uint16_t transmitSize;
uint16_t receiveBase;
uint16_t receiveSize;
uint16_t registers;
uint16_t sn_rx_wr;
uint16_t sn_rx_rsr;
uint8_t sn_sr;
int myFD;
int myErrno;
void clearFD();
void setFD(const int fd, const int status);
void process();
bool isThereRoomFor(const size_t len, const size_t header) const;
uint16_t getFreeRoom() const;
Socket();
~Socket();
};
class Uthernet2 : public Card
{
public:
Uthernet2(UINT slot);
virtual void InitializeIO(LPBYTE pCxRomPeripheral);
virtual void Init();
virtual void Reset(const bool powerCycle);
virtual void Update(const ULONG nExecutedCycles);
virtual void SaveSnapshot(YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version);
BYTE IO_C0(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
private:
std::vector<uint8_t> myMemory;
std::vector<Socket> mySockets;
uint8_t myModeRegister;
uint16_t myDataAddress;
std::shared_ptr<SlirpNet> mySlirp;
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
void setTXSizes(const uint16_t address, uint8_t value);
void setRXSizes(const uint16_t address, uint8_t value);
uint16_t getTXDataSize(const size_t i) const;
uint8_t getTXFreeSizeRegister(const size_t i, const size_t shift) const;
uint8_t getRXDataSizeRegister(const size_t i, const size_t shift) const;
void receiveOnePacketMacRaw(const size_t i);
void receiveOnePacketFromSocket(const size_t i);
void receiveOnePacket(const size_t i);
void sendDataMacRaw(const size_t i, const std::vector<uint8_t> & data) const;
void sendDataToSocket(const size_t i, std::vector<uint8_t> & data);
void sendData(const size_t i);
void resetRXTXBuffers(const size_t i);
void updateRSR(const size_t i);
void openSystemSocket(const size_t i, const int type, const int protocol, const int state);
void openSocket(const size_t i);
void closeSocket(const size_t i);
void connectSocket(const size_t i);
void setCommandRegister(const size_t i, const uint8_t value);
uint8_t readSocketRegister(const uint16_t address);
uint8_t readValueAt(const uint16_t address);
void autoIncrement();
uint8_t readValue();
void setIPProtocol(const size_t i, const uint16_t address, const uint8_t value);
void setIPTypeOfService(const size_t i, const uint16_t address, const uint8_t value);
void setIPTTL(const size_t i, const uint16_t address, const uint8_t value);
void writeSocketRegister(const uint16_t address, const uint8_t value);
void setModeRegister(const uint16_t address, const uint8_t value);
void writeCommonRegister(const uint16_t address, const uint8_t value);
void writeValueAt(const uint16_t address, const uint8_t value);
void writeValue(const uint8_t value);
void processEvents(uint32_t timeout);
};