mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-21 21:38:52 +00:00
338 lines
10 KiB
C#
338 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Cosmos.Kernel;
|
|
|
|
namespace Cosmos.Hardware2.Network.Devices.ViaRhine
|
|
{
|
|
public class VT6102 : NetworkDevice
|
|
{
|
|
protected PCIDevice pciCard;
|
|
protected IOAddressSpace io;
|
|
protected MACAddress mac;
|
|
|
|
protected List<ManagedMemorySpace> mRxBuffers;
|
|
private ManagedMemorySpace mRxDescriptors;
|
|
private ManagedMemorySpace mTxDescriptors;
|
|
protected Queue<byte[]> mRecvBuffer;
|
|
protected Queue<byte[]> mTransmitBuffer;
|
|
private int mNextTXDesc;
|
|
|
|
public VT6102(PCIDevice device)
|
|
{
|
|
if (device == null)
|
|
{
|
|
throw new ArgumentException("PCI Device is null. Unable to get VIA Rhine-II card");
|
|
}
|
|
pciCard = device;
|
|
|
|
// We are handling this device
|
|
pciCard.Claimed = true;
|
|
|
|
// Setup interrupt handling
|
|
//Interrupts.IRQ10 += HandleNetworkInterrupt;
|
|
//Interrupts.AddIRQHandler(device.InterruptLine, HandleNetworkInterrupt);
|
|
|
|
// Get IO Address from PCI Bus
|
|
io = pciCard.GetAddressSpace(0) as Kernel.IOAddressSpace;
|
|
|
|
// Enable the card
|
|
pciCard.EnableDevice();
|
|
|
|
// Get the EEPROM MAC Address and set it as the devices MAC
|
|
byte[] eeprom_mac = new byte[6];
|
|
UInt32 result = io.Read32(0x00);
|
|
eeprom_mac[0] = BinaryHelper.GetByteFrom32bit(result, 0);
|
|
eeprom_mac[1] = BinaryHelper.GetByteFrom32bit(result, 8);
|
|
eeprom_mac[2] = BinaryHelper.GetByteFrom32bit(result, 16);
|
|
eeprom_mac[3] = BinaryHelper.GetByteFrom32bit(result, 24);
|
|
result = io.Read32(0x04);
|
|
eeprom_mac[4] = BinaryHelper.GetByteFrom32bit(result, 0);
|
|
eeprom_mac[5] = BinaryHelper.GetByteFrom32bit(result, 8);
|
|
|
|
mac = new MACAddress(eeprom_mac);
|
|
|
|
// Software Reset device
|
|
SoftwareReset();
|
|
|
|
// Configure Receive Config
|
|
ReceiveConfigRegister = 0x1C;
|
|
// Configure Transmit Config
|
|
TransmitConfigRegister = 0x04;
|
|
|
|
// Setup RX Descriptors
|
|
mRxDescriptors = new ManagedMemorySpace(256, 16);
|
|
|
|
// Setup TX Descriptors
|
|
mTxDescriptors = new ManagedMemorySpace(256, 16);
|
|
|
|
/* Initialize the RX and TX buffers, and set up the RX descriptors to point
|
|
to the buffers. Also, mark the RX descriptors as being owned by the card so data
|
|
can be received in them */
|
|
mRxBuffers = new List<ManagedMemorySpace>();
|
|
for (uint rxd = 0; rxd < 16; rxd++)
|
|
{
|
|
uint xOffset = rxd * 16;
|
|
|
|
ManagedMemorySpace buffer = new ManagedMemorySpace(2048);
|
|
mRxDescriptors.Write32(xOffset + 12, mRxDescriptors.Offset + xOffset + 16);
|
|
mRxDescriptors.Write32(xOffset + 8, buffer.Offset);
|
|
mRxDescriptors.Write32(xOffset + 4, buffer.Size);
|
|
mRxDescriptors.Write32(xOffset, 0x80000000);
|
|
mRxBuffers.Add(buffer);
|
|
}
|
|
mRxDescriptors.Write32(252, mRxDescriptors.Offset);
|
|
for (uint txd = 0; txd < 16; txd++)
|
|
{
|
|
uint xOffset = txd * 16;
|
|
|
|
mTxDescriptors.Write32(xOffset + 12, mTxDescriptors.Offset + xOffset + 16);
|
|
mTxDescriptors.Write32(xOffset + 8, 0);
|
|
mTxDescriptors.Write32(xOffset + 4, 0);
|
|
mTxDescriptors.Write32(xOffset, 0);
|
|
}
|
|
mTxDescriptors.Write32(252, mTxDescriptors.Offset);
|
|
|
|
mNextTXDesc = 0;
|
|
|
|
RxDescAddressRegister = mRxDescriptors.Offset;
|
|
TxDescAddressRegister = mTxDescriptors.Offset;
|
|
|
|
// Setup and clear interrupts
|
|
IntMaskRegister = 0xFFFF;
|
|
IntStatusRegister = 0xFFFF;
|
|
|
|
// Setup our Receive and Transmit Queues
|
|
mTransmitBuffer = new Queue<byte[]>();
|
|
mRecvBuffer = new Queue<byte[]>();
|
|
}
|
|
|
|
private void SoftwareReset()
|
|
{
|
|
io.Write16(0x08, 0x8000);
|
|
while ((io.Read16(0x08) & 0x8000) != 0)
|
|
{
|
|
// Wait for device to reset
|
|
}
|
|
}
|
|
|
|
public static void InitDriver()
|
|
{
|
|
Device.AddDriverInit(FindAll);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve all VIA Rhine-II network cards found on computer.
|
|
/// </summary>
|
|
/// <returns>List of all VIA Rhine-II cards</returns>
|
|
public static void FindAll()
|
|
{
|
|
Console.WriteLine("Scanning for VIA Rhine-II cards...");
|
|
foreach (PCIDevice device in Cosmos.Hardware2.PCIBus.Devices)
|
|
{
|
|
if ((device.VendorID == 0x1106) && (device.DeviceID == 0x3065) && (device.Claimed == false))
|
|
{
|
|
VT6102 nic = new VT6102(device);
|
|
|
|
Console.WriteLine("Found VIA Rhine-II NIC on PCI " + device.Bus + ":" + device.Slot + ":" + device.Function);
|
|
Console.WriteLine("NIC IRQ: " + device.InterruptLine);
|
|
Console.WriteLine("NIC MAC Address: " + nic.MACAddress.ToString());
|
|
|
|
NetworkDevice.Add(nic);
|
|
}
|
|
}
|
|
}
|
|
|
|
//protected void HandleNetworkInterrupt(ref IRQContext aContext)
|
|
//{
|
|
// UInt16 cur_status = IntStatusRegister;
|
|
|
|
// if ((cur_status & 0x01) != 0)
|
|
// {
|
|
// ReadRawData();
|
|
// }
|
|
|
|
// IntStatusRegister = cur_status;
|
|
//}
|
|
|
|
#region Register Access
|
|
protected UInt16 CommandRegister
|
|
{
|
|
get { return io.Read16(0x08); }
|
|
set { io.Write16(0x08, value); }
|
|
}
|
|
protected UInt16 IntStatusRegister
|
|
{
|
|
get { return io.Read16(0x0C); }
|
|
set { io.Write16(0x0C, value); }
|
|
}
|
|
protected UInt16 IntMaskRegister
|
|
{
|
|
get { return io.Read16(0x0E); }
|
|
set { io.Write16(0x0E, value); }
|
|
}
|
|
protected byte ReceiveConfigRegister
|
|
{
|
|
get { return io.Read8(0x06); }
|
|
set { io.Write8(0x06, value); }
|
|
}
|
|
protected byte TransmitConfigRegister
|
|
{
|
|
get { return io.Read8(0x07); }
|
|
set { io.Write8(0x07, value); }
|
|
}
|
|
protected UInt32 RxDescAddressRegister
|
|
{
|
|
get { return io.Read32(0x18); }
|
|
set { io.Write32(0x18, value); }
|
|
}
|
|
protected UInt32 TxDescAddressRegister
|
|
{
|
|
get { return io.Read32(0x1C); }
|
|
set { io.Write32(0x1C, value); }
|
|
}
|
|
#endregion
|
|
|
|
#region Network Device Implementation
|
|
public override MACAddress MACAddress
|
|
{
|
|
get { return this.mac; }
|
|
}
|
|
|
|
public override bool Enable()
|
|
{
|
|
// Set start,rxon and txon bit on card
|
|
CommandRegister = 0x1A;
|
|
|
|
return base.Enable();
|
|
}
|
|
public override bool Ready
|
|
{
|
|
get { return ((CommandRegister & 0x02) != 0); }
|
|
}
|
|
|
|
public override bool QueueBytes(byte[] buffer, int offset, int length)
|
|
{
|
|
byte[] data = new byte[length];
|
|
for (int b = 0; b < length; b++)
|
|
{
|
|
data[b] = buffer[b + offset];
|
|
}
|
|
|
|
if (SendBytes(ref data) == false)
|
|
{
|
|
mTransmitBuffer.Enqueue(data);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool ReceiveBytes(byte[] buffer, int offset, int max)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override byte[] ReceivePacket()
|
|
{
|
|
if (mRecvBuffer.Count < 1)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
byte[] data = mRecvBuffer.Dequeue();
|
|
return data;
|
|
}
|
|
|
|
public override int BytesAvailable()
|
|
{
|
|
if (mRecvBuffer.Count < 1)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return mRecvBuffer.Peek().Length;
|
|
}
|
|
|
|
public override bool IsSendBufferFull()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override bool IsReceiveBufferFull()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public override string Name
|
|
{
|
|
get { return "VIA Rhine-II Ethernet Adapter"; }
|
|
}
|
|
#endregion
|
|
|
|
#region Helper Functions
|
|
protected bool SendBytes(ref byte[] aData)
|
|
{
|
|
int txd = mNextTXDesc++;
|
|
if (mNextTXDesc >= 16)
|
|
{
|
|
mNextTXDesc = 0;
|
|
}
|
|
|
|
uint xOffset = (uint)(txd * 16);
|
|
UInt32 status = mTxDescriptors.Read32(xOffset);
|
|
ManagedMemorySpace txBuffer = new ManagedMemorySpace(aData);
|
|
if (((txBuffer.Offset % 4) != 0) || (txBuffer.Size < 64) )
|
|
{
|
|
txBuffer = new ManagedMemorySpace((uint)(aData.Length < 64 ? 64 : aData.Length), 4);
|
|
for (uint b = 0; b < aData.Length; b++)
|
|
{
|
|
txBuffer[b] = aData[b];
|
|
}
|
|
}
|
|
if ((status & 0x80000000) == 0)
|
|
{
|
|
mTxDescriptors.Write32(xOffset + 8, txBuffer.Offset);
|
|
mTxDescriptors.Write32(xOffset + 4, txBuffer.Size | 0x600000 );
|
|
|
|
mTxDescriptors.Write32(xOffset, status | 0x80000000);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void ReadRawData()
|
|
{
|
|
uint status;
|
|
UInt16 recv_size;
|
|
byte[] recv_data;
|
|
|
|
for (int rxd = 0; rxd < 16; rxd++)
|
|
{
|
|
uint xOffset = (uint)(rxd * 16);
|
|
status = mRxDescriptors.Read32(xOffset);
|
|
if ((status & 0x80000000) == 0)
|
|
{
|
|
recv_size = (UInt16)((status & 0xFFFF0000) >> 16);
|
|
recv_data = new byte[recv_size];
|
|
for (uint b = 0; b < recv_size; b++)
|
|
{
|
|
recv_data[b] = mRxBuffers[rxd][b];
|
|
}
|
|
|
|
if (DataReceived != null)
|
|
{
|
|
DataReceived(recv_data);
|
|
}
|
|
else
|
|
{
|
|
mRecvBuffer.Enqueue(recv_data);
|
|
}
|
|
|
|
mRxDescriptors.Write32(xOffset, status | 0x80000000);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|