1
0
Fork 0

ipx-update (h-a-l-9000)

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2291
This commit is contained in:
Sebastian Strohhäcker 2005-08-26 19:16:20 +00:00
parent 147e30b948
commit 2428a80321

View file

@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* $Id: ipx.cpp,v 1.7 2005-07-30 10:02:39 qbix79 Exp $ */
/* $Id: ipx.cpp,v 1.8 2005-08-26 19:16:20 c2woody Exp $ */
#include "dosbox.h"
@ -28,7 +28,6 @@
#include "cross.h"
#include "support.h"
#include "cpu.h"
#include "SDL_net.h"
#include "regs.h"
#include "inout.h"
#include "setup.h"
@ -45,20 +44,16 @@
#define SOCKTABLESIZE 150 // DOS IPX driver was limited to 150 open sockets
struct ipxnetaddr {
Uint8 netnum[4]; // Both are big endian
Uint8 netnode[6];
} localIpxAddr;
Bit32u tcpPort;
bool isIpxServer;
bool isIpxConnected;
IPaddress ipxClientIp; // IPAddress for client connection to server
IPaddress ipxServConnIp; // IPAddress for client connection to server
//TCPsocket ipxTCPClientSocket;
UDPsocket ipxClientSocket;
int UDPChannel; // Channel used by UDP connection
Bit8u recvBuffer[IPXBUFFERSIZE]; // Incoming packet buffer
@ -67,10 +62,11 @@ static RealPt ipx_callback;
SDLNet_SocketSet clientSocketSet;
static bool ESRnotificationRequired = false;
packetBuffer incomingPacket;
static Bit16u socketCount;
static Bit16u opensockets[SOCKTABLESIZE];
static Bit16u swapByte(Bit16u sockNum) {
return (((sockNum>> 8)) | (sockNum << 8));
}
@ -166,7 +162,6 @@ RealPt ECBClass::getESRAddr(void) {
void ECBClass::NotifyESR(void) {
Bit32u ESRval = real_readd(RealSeg(ECBAddr), RealOff(ECBAddr)+4);
if(ESRval) {
#ifdef IPX_DEBUGMSG
LOG_MSG("ECB: SN%7d to be notified.", SerialNumber);
@ -227,8 +222,7 @@ ECBClass::~ECBClass() {
}
}
static Bit16u socketCount;
static Bit16u opensockets[SOCKTABLESIZE];
static bool sockInUse(Bit16u sockNum) {
for(Bitu i=0;i<socketCount;i++) {
@ -292,6 +286,7 @@ static void CloseSocket(void) {
tmp2ECB = tmpECB->nextECB;
if(tmpECB->getSocket()==sockNum) {
tmpECB->setCompletionFlag(COMP_CANCELLED);
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
delete tmpECB;
}
tmpECB = tmp2ECB;
@ -311,7 +306,6 @@ static bool IPX_Multiplex(void) {
return true;
}
//static void sendPackets();
static void sendPacket(ECBClass* sendecb);
static void handleIpxRequest(void) {
@ -320,10 +314,14 @@ static void handleIpxRequest(void) {
switch (reg_bx) {
case 0x0000: // Open socket
OpenSocket();
#ifdef IPX_DEBUGMSG
LOG_MSG("IPX: Open socket %4x", swapByte(reg_dx));
#endif
break;
case 0x0001: // Close socket
#ifdef IPX_DEBUGMSG
LOG_MSG("IPX: Close socket %4x", swapByte(reg_dx));
#endif
CloseSocket();
break;
case 0x0002: // get local target
@ -332,26 +330,24 @@ static void handleIpxRequest(void) {
case 0x0003: // Send packet
if(!incomingPacket.connected) {
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),true);
tmpECB = new ECBClass(SegValue(es),reg_si);
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
tmpECB->setCompletionFlag(COMP_UNDELIVERABLE);
delete tmpECB; // not notify?
//DeleteECB(tmpECB);
reg_al = 0xff; // Failure
} else {
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),true);
tmpECB = new ECBClass(SegValue(es),reg_si);
tmpECB->setInUseFlag(USEFLAG_SENDING);
//LOG_MSG("IPX: Sending packet on %4x", tmpECB->getSocket());
reg_al = 0x00; // Success
sendPacket(tmpECB);
}
//sendPackets();
break;
case 0x0004: // Listen for packet
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),false);
if(!sockInUse(tmpECB->getSocket())) {
reg_al = 0xff; // Socket is not open
tmpECB = new ECBClass(SegValue(es),reg_si);
if(!sockInUse(tmpECB->getSocket())) { // Socket is not open
reg_al = 0xff;
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
tmpECB->setCompletionFlag(COMP_HARDWAREERROR);
delete tmpECB;
@ -374,14 +370,18 @@ static void handleIpxRequest(void) {
while(tmpECB) {
tmp2ECB=tmpECB->nextECB;
if(tmpECB->ECBAddr == ecbaddress) {
delete tmpECB; // TODO: invoke flags... check if it can be canceled
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
tmpECB->setCompletionFlag(COMP_CANCELLED);
delete tmpECB;
reg_al=0; // Success
#ifdef IPX_DEBUGMSG
LOG_MSG("IPX: ECB canceled.");
#endif
return;
}
tmpECB=tmp2ECB;
}
reg_al=0; // Success
reg_al=0xff; // Fail
break;
}
case 0x0008: // Get interval marker
@ -389,12 +389,11 @@ static void handleIpxRequest(void) {
break;
case 0x0009: // Get internetwork address
{
#ifdef IPX_DEBUGMSG
LOG_MSG("IPX: Get internetwork address %2x:%2x:%2x:%2x:%2x:%2x", localIpxAddr.netnode[5], localIpxAddr.netnode[4], localIpxAddr.netnode[3], localIpxAddr.netnode[2], localIpxAddr.netnode[1], localIpxAddr.netnode[0]);
Bit8u * addrptr;
Bits i;
addrptr = (Bit8u *)&localIpxAddr;
for(i=0;i<10;i++) {
#endif
Bit8u * addrptr = (Bit8u *)&localIpxAddr;
for(Bit16u i=0;i<10;i++) {
real_writeb(SegValue(es),reg_si+i,addrptr[i]);
}
break;
@ -426,12 +425,6 @@ Bitu IPX_IntHandler(void) {
return CBRET_NONE;
}
static void disconnectServer(bool unexpected) {
// There is no Timer remove code, hence this has to be done manually
incomingPacket.connected = false;
if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly");
}
static void pingAck(IPaddress retAddr) {
IPXHeader regHeader;
UDPpacket regPacket;
@ -503,7 +496,7 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
// Check to see if ping packet
if(useSocket == 0x2) {
// Is this a broadcast?
if((tmpHeader->dest.addr.byIP.host == 0xffffffff) && (tmpHeader->dest.addr.byIP.port = 0xffff)) {
if((tmpHeader->dest.addr.byIP.host == 0xffffffff) && (tmpHeader->dest.addr.byIP.port == 0xffff)) {
// Yes. We should return the ping back to the sender
IPaddress tmpAddr;
UnpackIP(tmpHeader->src.addr.byIP, &tmpAddr);
@ -530,13 +523,10 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
useECB->setCompletionFlag(COMP_SUCCESS);
useECB->setImmAddress(&buffer[22]); // Write in source node
hostaddr = *((Bit32u *)&buffer[24]);
#ifdef IPX_DEBUGMSG
LOG_MSG("IPX: Received packet of %d bytes from %d.%d.%d.%d (%x CRC)", bufSize, CONVIP(hostaddr), packetCRC(&buffer[30], bufSize-30));
#endif
#endif
useECB->NotifyESR();
//DeleteECB(useECB);
return;
}
}
@ -544,7 +534,6 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
if(bufoffset < bufSize) {
useECB->setCompletionFlag(COMP_MALFORMED);
useECB->NotifyESR();
//DeleteECB(useECB);
return;
}
}
@ -556,7 +545,7 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
#endif
}
static void IPX_UDPClientLoop(void) {
static void IPX_ClientLoop(void) {
int numrecv;
UDPpacket inPacket;
inPacket.data = (Uint8 *)recvBuffer;
@ -570,190 +559,127 @@ static void IPX_UDPClientLoop(void) {
if(numrecv) receivePacket(inPacket.data, inPacket.len);
//}while(numrecv>0);
}
// don't waste time scanning the list
static void sendPacket(ECBClass* sendecb) {
char outbuffer[IPXBUFFERSIZE];
fragmentDescriptor tmpFrag;
Bit16u i, fragCount,t;
Bit16s packetsize;
Bit16u *wordptr;
Bits result;
UDPpacket outPacket;
//if(useECB->getInUseFlag() == USEFLAG_SENDING)
// {
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
packetsize = 0;
fragCount = sendecb->getFragCount();
for(i=0;i<fragCount;i++) {
sendecb->getFragDesc(i,&tmpFrag);
if(i==0) {
// Fragment containing IPX header
// Must put source address into header
Bit8u * addrptr;
Bits m;
addrptr = (Bit8u *)&localIpxAddr.netnode;
for(m=0;m<6;m++) {
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
}
}
for(t=0;t<tmpFrag.size;t++) {
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
packetsize++;
if(packetsize>=IPXBUFFERSIZE) {
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
sendecb->NotifyESR();
//DeleteECB(useECB);
return;
}
}
}
// Add length and source socket to IPX header
wordptr = (Bit16u *)&outbuffer[0];
// Blank CRC
wordptr[0] = 0xffff;
// Length
wordptr[1] = swapByte(packetsize);
// Source socket
wordptr[14] = swapByte(sendecb->getSocket());
outPacket.channel = UDPChannel;
outPacket.data = (Uint8 *)&outbuffer[0];
outPacket.len = packetsize;
outPacket.maxlen = packetsize;
// Since we're using a channel, we won't send the IP address again
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
if(result == 0) {
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
sendecb->NotifyESR();
//DeleteECB(useECB);
disconnectServer(true);
//return;
} else {
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
sendecb->setCompletionFlag(COMP_SUCCESS);
#ifdef IPX_DEBUGMSG
LOG_MSG("Packet sent: size: %d",packetsize);
#endif
sendecb->NotifyESR();
}
//}
}
static void sendPackets() {
ECBClass *useECB;
ECBClass *nextECB;
char outbuffer[IPXBUFFERSIZE];
fragmentDescriptor tmpFrag;
Bit16u i, fragCount,t;
Bit16s packetsize;
Bit16u *wordptr;
Bits result;
UDPpacket outPacket;
useECB = ECBList;
while(useECB != NULL) {
nextECB = useECB->nextECB;
if(useECB->getInUseFlag() == USEFLAG_SENDING) {
useECB->setInUseFlag(USEFLAG_AVAILABLE);
packetsize = 0;
fragCount = useECB->getFragCount();
for(i=0;i<fragCount;i++) {
useECB->getFragDesc(i,&tmpFrag);
if(i==0) {
// Fragment containing IPX header
// Must put source address into header
Bit8u * addrptr;
Bits m;
addrptr = (Bit8u *)&localIpxAddr.netnode;
for(m=0;m<6;m++) {
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
}
}
for(t=0;t<tmpFrag.size;t++) {
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
packetsize++;
if(packetsize>=IPXBUFFERSIZE) {
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
useECB->setCompletionFlag(COMP_UNDELIVERABLE);
useECB->NotifyESR();
//DeleteECB(useECB);
goto nextECB;
}
}
}
// Add length and source socket to IPX header
wordptr = (Bit16u *)&outbuffer[0];
// Blank CRC
wordptr[0] = 0xffff;
// Length
wordptr[1] = swapByte(packetsize);
// Source socket
wordptr[14] = swapByte(useECB->getSocket());
outPacket.channel = UDPChannel;
outPacket.data = (Uint8 *)&outbuffer[0];
outPacket.len = packetsize;
outPacket.maxlen = packetsize;
// Since we're using a channel, we won't send the IP address again
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
if(result == 0) {
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
useECB->setCompletionFlag(COMP_UNDELIVERABLE);
useECB->NotifyESR();
//DeleteECB(useECB);
disconnectServer(true);
//return;
} else {
useECB->setInUseFlag(USEFLAG_AVAILABLE);
useECB->setCompletionFlag(COMP_SUCCESS);
//LOG_MSG("Packet sent: size: %d",packetsize);
useECB->NotifyESR();
//DeleteECB(useECB);
}
}
nextECB:
useECB = nextECB;
void DisconnectFromServer(bool unexpected) {
if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly");
if(incomingPacket.connected) {
incomingPacket.connected = false;
TIMER_DelTickHandler(&IPX_ClientLoop);
SDLNet_UDP_Close(ipxClientSocket);
}
}
//RealPt ESRJmpDisplacementAddr;
//RealPt ESRTargetAddr;
//RealPt ESRDummyRetAddr;
/*
void repeatESR(bool rep)
{
if(rep) real_writeb(
RealSeg(ESRJmpDisplacementAddr),
RealOff(ESRJmpDisplacementAddr),
(Bit8u)0xF5);
else real_writeb(
RealSeg(ESRJmpDisplacementAddr),
RealOff(ESRJmpDisplacementAddr),
(Bit8u)0);
}
*/
ECBClass* ESRHANDLER_useECB;
static void IPX_ClientLoop(void) {
static void sendPacket(ECBClass* sendecb) {
Bit8u outbuffer[IPXBUFFERSIZE];
fragmentDescriptor tmpFrag;
Bit16u i, fragCount,t;
Bit16s packetsize;
Bit16u *wordptr;
Bits result;
UDPpacket outPacket;
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
packetsize = 0;
fragCount = sendecb->getFragCount();
for(i=0;i<fragCount;i++) {
sendecb->getFragDesc(i,&tmpFrag);
if(i==0) {
// Fragment containing IPX header
// Must put source address into header
Bit8u * addrptr;
addrptr = (Bit8u *)&localIpxAddr.netnum;
for(Bit16u m=0;m<4;m++) {
real_writeb(tmpFrag.segment,tmpFrag.offset+m+18,addrptr[m]);
}
addrptr = (Bit8u *)&localIpxAddr.netnode;
for(Bit16u m=0;m<6;m++) {
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
}
}
for(t=0;t<tmpFrag.size;t++) {
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
packetsize++;
if(packetsize>=IPXBUFFERSIZE) {
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
sendecb->NotifyESR();
return;
}
}
}
// Add length and source socket to IPX header
wordptr = (Bit16u *)&outbuffer[0];
// Blank CRC
wordptr[0] = 0xffff;
// Length
wordptr[1] = swapByte(packetsize);
// Source socket
wordptr[14] = swapByte(sendecb->getSocket());
IPX_UDPClientLoop();
// Send outgoing packets
//sendPackets();
}
// filter out broadcasts and local loopbacks
// ok, the situation is:
// Warcraft1 is allergic to having broadcast packets looped back.
// C&C1 is allergic to not having broadcast packets looped back.
// Warcraft1 broadcasts to 00 00 00 00 : FF FF FF FF FF FF
// C&C1 broadcasts to FF FF FF FF : FF FF FF FF FF FF
// Some other games don't care.
// I assume FF... does local loopback, 00... doesn't.
// Let's hope the bug isn't somewhere else..
bool islocalbroadcast=true;
bool isloopback=true;
Bit8u * addrptr;
addrptr = (Bit8u *)&localIpxAddr.netnum;
for(Bitu m=0;m<4;m++) {
if(addrptr[m]!=outbuffer[m+0x6])isloopback=false;
if(outbuffer[m+0x6]!=0xff) islocalbroadcast=false;
}
addrptr = (Bit8u *)&localIpxAddr.netnode;
for(Bitu m=0;m<6;m++) {
if(addrptr[m]!=outbuffer[m+0xa])isloopback=false;
if(outbuffer[m+0xa]!=0xff) islocalbroadcast=false;
}
if(!isloopback) {
outPacket.channel = UDPChannel;
outPacket.data = (Uint8 *)&outbuffer[0];
outPacket.len = packetsize;
outPacket.maxlen = packetsize;
// Since we're using a channel, we won't send the IP address again
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
if(result == 0) {
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
sendecb->setCompletionFlag(COMP_HARDWAREERROR);
sendecb->NotifyESR();
DisconnectFromServer(true);
return;
} else {
sendecb->setCompletionFlag(COMP_SUCCESS);
#ifdef IPX_DEBUGMSG
LOG_MSG("Packet sent: size: %d",packetsize);
#endif
}
}
if(isloopback||islocalbroadcast) {
receivePacket(&outbuffer[0],packetsize);
#ifdef IPX_DEBUGMSG
LOG_MSG("Packet back: loopback:%d, broadcast:%d",isloopback,isbroadcast);
#endif
}
sendecb->NotifyESR();
}
static bool pingCheck(IPXHeader * outHeader) {
char buffer[1024];
Bits result;
UDPpacket regPacket;
IPXHeader *regHeader;
regPacket.data = (Uint8 *)buffer;
regPacket.maxlen = sizeof(buffer);
@ -766,8 +692,6 @@ static bool pingCheck(IPXHeader * outHeader) {
return true;
}
return false;
}
bool ConnectToServer(char *strAddr) {
@ -776,7 +700,12 @@ bool ConnectToServer(char *strAddr) {
IPXHeader regHeader;
if(!SDLNet_ResolveHost(&ipxServConnIp, strAddr, (Bit16u)tcpPort)) {
// Generate the MAC address. This is made by zeroing out the first two
// octets and then using the actual IP address for the last 4 octets.
// This idea is from the IPX over IP implementation as specified in RFC 1234:
// http://www.faqs.org/rfcs/rfc1234.html
// Select an anonymous UDP port
ipxClientSocket = SDLNet_UDP_Open(0);
if(ipxClientSocket) {
@ -848,45 +777,21 @@ bool ConnectToServer(char *strAddr) {
return false;
}
void DisconnectFromServer(void) {
void IPX_NetworkInit() {
if(incomingPacket.connected) {
incomingPacket.connected = false;
TIMER_DelTickHandler(&IPX_ClientLoop);
SDLNet_UDP_Close(ipxClientSocket);
}
}
bool IPX_NetworkInit() {
localIpxAddr.netnum[0] = 0x0; localIpxAddr.netnum[1] = 0x0; localIpxAddr.netnum[2] = 0x0; localIpxAddr.netnum[3] = 0x1;
/*
if(SDLNet_ResolveHost(&ipxClientIp, localhostname, tcpPort)) {
LOG_MSG("IPX: Unable to resolve localname: \"%s\". IPX disabled.", localhostname);
return false;
} else {
LOG_MSG("IPX: Using localname: %s IP is: %d.%d.%d.%d", localhostname, CONVIP(ipxClientIp.host));
}
*/
// Generate the MAC address. This is made by zeroing out the first two octets and then using the actual IP address for
// the last 4 octets. This idea is from the IPX over IP implementation as specified in RFC 1234:
// http://www.faqs.org/rfcs/rfc1234.html
localIpxAddr.netnum[0] = 0x0;
localIpxAddr.netnum[1] = 0x0;
localIpxAddr.netnum[2] = 0x0;
localIpxAddr.netnum[3] = 0x1;
localIpxAddr.netnode[0] = 0x00;
localIpxAddr.netnode[1] = 0x00;
//localIpxAddr.netnode[5] = (ipxClientIp.host >> 24) & 0xff;
//localIpxAddr.netnode[4] = (ipxClientIp.host >> 16) & 0xff;
//localIpxAddr.netnode[3] = (ipxClientIp.host >> 8) & 0xff;
//localIpxAddr.netnode[2] = (ipxClientIp.host & 0xff);
//To be filled in on response from server
localIpxAddr.netnode[2] = 0x00;
localIpxAddr.netnode[3] = 0x00;
localIpxAddr.netnode[4] = 0x00;
localIpxAddr.netnode[5] = 0x00;
socketCount = 0;
return true;
return;
}
class IPXNET : public Program {
@ -1003,7 +908,7 @@ public:
WriteOut("IPX Tunneling Server not running in this DosBox session.\n");
} else {
isIpxServer = false;
DisconnectFromServer();
DisconnectFromServer(false);
IPX_StopServer();
WriteOut("IPX Tunneling Server stopped.");
// Don't know how to stop the timer just yet.
@ -1044,7 +949,7 @@ public:
// TODO: Send a packet to the server notifying of disconnect
WriteOut("IPX Tunneling Client disconnected from server.\n");
DisconnectFromServer();
DisconnectFromServer(false);
return;
}
@ -1093,19 +998,6 @@ public:
return;
}
}
/*
WriteOut("IPX Status\n\n");
if(!incomingPacket.connected) {
WriteOut("IPX tunneling client not presently connected");
return;
}
if(isIpxServer) {
WriteOut("This DosBox session is an IPX tunneling server running on port %d", tcpPort);
} else {
WriteOut("This DosBox session is an IPX tunneling client connected to: %s",SDLNet_ResolveIP(&ipxServConnIp));
}
*/
}
};
@ -1126,17 +1018,12 @@ Bitu IPX_ESRHandler1(void) {
SegSet16(es, RealSeg(ESRList->ECBAddr));
reg_si = RealOff(ESRList->ECBAddr);
reg_al = 0xff;
CALLBACK_RunRealFar(RealSeg(ESRList->getESRAddr()), RealOff(ESRList->getESRAddr()));
delete ESRList;
} // while
// PIC_DeActivateIRQ(11);
IO_WriteB(0xa0,0x63); //EOI11
IO_WriteB(0x20,0x62); //EOI2
// IO_WriteB(0xa0,0x20); //EOI
//IO_WriteB(0x20,0x20); //EOI
#ifdef IPX_DEBUGMSG
LOG_MSG("ESR loop done.");
@ -1192,14 +1079,12 @@ public:
LOG_MSG("ESR callback address: %x, HandlerID %d", phyDospage,call_ipxesr1);
#endif
//save registers
phys_writeb(phyDospage+0,(Bit8u)0xFA); // CLI
phys_writeb(phyDospage+1,(Bit8u)0x60); // PUSHA
phys_writeb(phyDospage+2,(Bit8u)0x1E); // PUSH DS
phys_writeb(phyDospage+3,(Bit8u)0x06); // PUSH ES
phys_writeb(phyDospage+4,(Bit8u)0x0F); // PUSH..
phys_writeb(phyDospage+5,(Bit8u)0xA0); // FS
phys_writeb(phyDospage+6,(Bit8u)0x0F); // PUSH..
phys_writeb(phyDospage+7,(Bit8u)0xA8); // GS
phys_writeb(phyDospage+0,(Bit8u)0xFA); // CLI
phys_writeb(phyDospage+1,(Bit8u)0x60); // PUSHA
phys_writeb(phyDospage+2,(Bit8u)0x1E); // PUSH DS
phys_writeb(phyDospage+3,(Bit8u)0x06); // PUSH ES
phys_writew(phyDospage+4,(Bit16u)0xA00F); // PUSH FS
phys_writew(phyDospage+6,(Bit16u)0xA80F); // PUSH GS
// callback
phys_writeb(phyDospage+8,(Bit8u)0xFE); // GRP 4
@ -1207,14 +1092,12 @@ public:
phys_writew(phyDospage+10,call_ipxesr1); // Callback identifier
// register recreation
phys_writeb(phyDospage+12,(Bit8u)0x0F);// POP..
phys_writeb(phyDospage+13,(Bit8u)0xA9); // GS
phys_writeb(phyDospage+14,(Bit8u)0x0F);// POP..
phys_writeb(phyDospage+15,(Bit8u)0xA1); // FS
phys_writeb(phyDospage+16,(Bit8u)0x07); // POP ES
phys_writeb(phyDospage+17,(Bit8u)0x1F); // POP DS
phys_writeb(phyDospage+18,(Bit8u)0x61); //POPA
phys_writeb(phyDospage+19,(Bit8u)0xCF); //IRET: restores flags, CS, IP
phys_writew(phyDospage+12,(Bit16u)0xA90F); // POP GS
phys_writew(phyDospage+14,(Bit16u)0xA10F); // POP FS
phys_writeb(phyDospage+16,(Bit8u)0x07); // POP ES
phys_writeb(phyDospage+17,(Bit8u)0x1F); // POP DS
phys_writeb(phyDospage+18,(Bit8u)0x61); // POPA
phys_writeb(phyDospage+19,(Bit8u)0xCF); // IRET: restores flags, CS, IP
// IPX version 2.12
//phys_writeb(phyDospage+27,(Bit8u)0x2);
@ -1224,10 +1107,8 @@ public:
RealPt ESRRoutineBase = RealMake(dospage, 0);
// Interrupt enabling
RealSetVec(0x73,ESRRoutineBase,old_73_vector); // IRQ11
Bit8u irqmask=IO_ReadB(0xa1);
irqmask &= ~8; // enable IRQ11
IO_WriteB(0xa1,irqmask);
RealSetVec(0x73,ESRRoutineBase,old_73_vector); // IRQ11
IO_WriteB(0xa1,IO_ReadB(0xa1)&(~8)); // enable IRQ11
PROGRAMS_MakeFile("IPXNET.COM",IPXNET_ProgramStart);
}
@ -1238,16 +1119,13 @@ public:
if(isIpxServer) {
isIpxServer = false;
DisconnectFromServer();
IPX_StopServer();
}
disconnectServer(false);
DisconnectFromServer(false);
DOS_DelMultiplexHandler(IPX_Multiplex);
RealSetVec(0x73,old_73_vector);
Bit8u irqmask=IO_ReadB(0xa1);
irqmask |= 8; // disable IRQ11
IO_WriteB(0xa1,irqmask);
IO_WriteB(0xa1,IO_ReadB(0xa1)|8); // disable IRQ11
PhysPt phyDospage = PhysMake(dospage,0);
for(Bitu i = 0;i < 32;i++)