mirror of
https://github.com/dschmenk/VM02.git
synced 2024-06-10 08:29:36 +00:00
204 lines
6.6 KiB
Java
Executable File
204 lines
6.6 KiB
Java
Executable File
package apple2;
|
|
/*
|
|
* This class interfaces to the ethernet device.
|
|
*/
|
|
public class Ethernet extends java.net.NetworkDevice
|
|
{
|
|
static private int ethSlot, ethOutputBuff, ethInputBuff, ethRecvPacket, ethSendPacket, ethHeaderLen, ethPacketDone, ethCtrl, ethWrite, ethRead;
|
|
static private byte[] MAC = {(byte)0x00,(byte)0x0a,(byte)0x99,(byte)0x1e,(byte)0x02,(byte)0x00};
|
|
static final int MIN_DATA_SIZE = 46;
|
|
static final int MAX_DATA_SIZE = 1500;
|
|
|
|
private static void copyBytes(byte[] src, int srcOfst, byte[] dst, int dstOfst, int count)
|
|
{
|
|
while (count-- != 0)
|
|
dst[dstOfst++] = src[srcOfst++];
|
|
}
|
|
public static boolean enable()
|
|
{
|
|
//
|
|
// Search for ethernet card.
|
|
//
|
|
for (int slot = 1; slot < 8; slot++)
|
|
{
|
|
//
|
|
// ID device
|
|
//
|
|
if (((vm02.call((1 << 19), 0x90 + (slot << 1))) & 0x010000FF) == 0xE1) // CARRY clear == valid device IOCTL, 0xE1 == ethernet card ID
|
|
{
|
|
ethCtrl = 0x90 + (slot << 1);
|
|
ethWrite = 0x80 + (slot << 1);
|
|
ethRead = 0x70 + (slot << 1);
|
|
ethSlot = slot << 16;
|
|
ethInputBuff = ethSlot | ( 7 << 19);
|
|
ethOutputBuff = ethSlot | ( 9 << 19);
|
|
ethRecvPacket = ethSlot | (16 << 19);
|
|
ethSendPacket = ethSlot | (17 << 19);
|
|
ethPacketDone = ethSlot | (18 << 19);
|
|
ethHeaderLen = ethSlot | 14;
|
|
for (int oct = 0; oct < 3; oct++)
|
|
vm02.call(ethSlot
|
|
| ((19 + oct) << 19)
|
|
| ( MAC[oct*2] & 0x00FF)
|
|
| ((MAC[oct*2 + 1] << 8) & 0xFF00), ethCtrl); // set MAC address
|
|
if ((vm02.call(ethSlot | (3 << 19), ethCtrl) & 0x01000000) == 0) // open port
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
public static void disable()
|
|
{
|
|
vm02.call(ethSlot | 4, ethCtrl); // close port
|
|
}
|
|
public static byte[] localAddr()
|
|
{
|
|
return MAC;
|
|
}
|
|
public static byte[] broadcastAddr()
|
|
{
|
|
byte[] addr = new byte[6];
|
|
addr[0] = (byte)0xFF;
|
|
addr[1] = (byte)0xFF;
|
|
addr[2] = (byte)0xFF;
|
|
addr[3] = (byte)0xFF;
|
|
addr[4] = (byte)0xFF;
|
|
addr[5] = (byte)0xFF;
|
|
return addr;
|
|
}
|
|
public static byte[] newAddr()
|
|
{
|
|
return new byte[6];
|
|
}
|
|
public static boolean isEqualAddr(byte[] addr1, byte[] addr2)
|
|
{
|
|
return ((addr1[5] == addr2[5])
|
|
&& (addr1[4] == addr2[4])
|
|
&& (addr1[3] == addr2[3])
|
|
&& (addr1[2] == addr2[2])
|
|
&& (addr1[1] == addr2[1])
|
|
&& (addr1[0] == addr2[0]));
|
|
}
|
|
public static void copyAddr(byte[] src, byte[] dst)
|
|
{
|
|
copyBytes(src, 0, dst, 0, 6);
|
|
}
|
|
public static byte[] newHeader()
|
|
{
|
|
return new byte[14];
|
|
}
|
|
public static void setHeaderSrcAddr(byte[] header, byte[] addr)
|
|
{
|
|
copyBytes(addr, 0, header, 6, 6);
|
|
}
|
|
public static void setHeaderDstAddr(byte[] header, byte[] addr)
|
|
{
|
|
copyBytes(addr, 0, header, 0, 6);
|
|
}
|
|
public static void copyHeaderSrcAddr(byte[] header, byte[] addr)
|
|
{
|
|
copyBytes(header, 6, addr, 0, 6);
|
|
}
|
|
public static void copyHeaderDstAddr(byte[] header, byte[] addr)
|
|
{
|
|
copyBytes(header, 0, addr, 0, 6);
|
|
}
|
|
public static byte[] getHeaderSrcAddr(byte[] header)
|
|
{
|
|
byte[] addr = new byte[6];
|
|
copyBytes(header, 6, addr, 0, 6);
|
|
return addr;
|
|
}
|
|
public static byte[] getHeaderDstAddr(byte[] header)
|
|
{
|
|
byte[] addr = new byte[6];
|
|
copyBytes(header, 0, addr, 0, 6);
|
|
return addr;
|
|
}
|
|
public static int getHeaderType(byte[] header)
|
|
{
|
|
if (header == null || header.length < 14)
|
|
{
|
|
System.out.println("Bad header in getHeaderType!");
|
|
return 0;
|
|
}
|
|
return ((header[12] << 8) & 0xFF00) | (header[13] & 0x00FF);
|
|
}
|
|
public static void setHeaderType(byte[] header, int type)
|
|
{
|
|
header[12] = (byte)(type >> 8);
|
|
header[13] = (byte)type;
|
|
}
|
|
public static boolean sendHeader(byte[] header, int dataSize)
|
|
{
|
|
boolean success;
|
|
int hmem = vm02.refAsBits((Object)header) & 0xFFFF;
|
|
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK header IOCTL_OUTBUFF
|
|
success = (vm02.call(ethSendPacket | dataSize + 14, ethCtrl) & 0x01000000) == 0;
|
|
if (success) // prepare to write packet of length len
|
|
vm02.call(ethHeaderLen, ethWrite); // write 14 byte ethernet header
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
|
|
return success;
|
|
}
|
|
public static boolean sendHeader(byte[] dst, int type, int dataSize)
|
|
{
|
|
byte[] header = new byte[14];
|
|
copyBytes(dst, 0, header, 0, 6);
|
|
copyBytes(MAC, 0, header, 6, 6);
|
|
header[12] = (byte)(type >> 8);
|
|
header[13] = (byte)type;
|
|
return sendHeader(header, dataSize);
|
|
}
|
|
public static void sendData(byte[] data, int offset, int size)
|
|
{
|
|
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
|
|
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2 + offset, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
|
|
vm02.call(ethSlot | size, ethWrite); // write data
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
|
|
}
|
|
public static void sendData(byte[] data)
|
|
{
|
|
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
|
|
vm02.call(ethOutputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
|
|
vm02.call(ethSlot | data.length, ethWrite); // write data
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
|
|
}
|
|
public static int recvHeader(byte[] header)
|
|
{
|
|
int len;
|
|
|
|
if (header == null || header.length < 14)
|
|
{
|
|
System.out.println("Bad header in recvHeader!");
|
|
return 0;
|
|
}
|
|
int hmem = vm02.refAsBits((Object)header) & 0xFFFF;
|
|
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK header IOCTL_INBUFF
|
|
if ((len = vm02.call(ethRecvPacket, ethCtrl) & 0xFFFF) >= 14) // ETHRCTRL_RECVPKT
|
|
{
|
|
vm02.call(ethHeaderLen, ethRead); // read 14 byte ethernet header
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
|
|
return len - 14;
|
|
}
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK header
|
|
return 0;
|
|
}
|
|
public static void recvData(byte[] data, int offset, int size)
|
|
{
|
|
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
|
|
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2 + offset, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
|
|
vm02.call(ethSlot | size, ethRead); // write data
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
|
|
}
|
|
public static void recvData(byte[] data)
|
|
{
|
|
int hmem = vm02.refAsBits((Object)data) & 0xFFFF;
|
|
vm02.call(ethInputBuff | (vm02.call(hmem, 0x0E) & 0xFFFF) + 2, ethCtrl); // HMEM_LOCK data IOCTL_OUTBUFF
|
|
vm02.call(ethSlot | data.length, ethRead); // write data
|
|
vm02.call(hmem, 0x10); // HMEM_UNLOCK data
|
|
}
|
|
public static void xferComplete()
|
|
{
|
|
vm02.call(ethPacketDone, ethCtrl); // ETHRCRL_DONEPKT
|
|
}
|
|
} |