mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-29 12:20:36 +00:00
Fixed PCIDevice so that Command and Status are dynamic properties. Also added Claimed to mark a Device as handled by a driver Also added an EnableDevice call to PCIDeviceNormal that enables the PCI Device on the bus
296 lines
9.9 KiB
C#
296 lines
9.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Cosmos.Core;
|
|
|
|
namespace SSchockeTest
|
|
{
|
|
public class AMDPCNetII : NetworkDevice
|
|
{
|
|
protected class IOGroup : Cosmos.Core.IOGroup.IOGroup
|
|
{
|
|
public readonly IOPort RegisterAddress;
|
|
public readonly IOPort RegisterData;
|
|
public readonly IOPort BusData;
|
|
public readonly IOPortRead MAC1;
|
|
public readonly IOPortRead MAC2;
|
|
public IOGroup(PCIDeviceNormal device)
|
|
{
|
|
RegisterAddress = new IOPort((ushort)device.BaseAddresses[0].BaseAddress(), 0x14);
|
|
RegisterData = new IOPort((ushort)device.BaseAddresses[0].BaseAddress(), 0x10);
|
|
BusData = new IOPort((ushort)device.BaseAddresses[0].BaseAddress(), 0x1C);
|
|
MAC1 = new IOPortRead((ushort)device.BaseAddresses[0].BaseAddress(), 0x00);
|
|
MAC2 = new IOPortRead((ushort)device.BaseAddresses[0].BaseAddress(), 0x04);
|
|
}
|
|
}
|
|
|
|
protected PCIDeviceNormal pciCard;
|
|
protected IOGroup io;
|
|
protected MACAddress mac;
|
|
protected bool mInitDone;
|
|
|
|
protected ManagedMemoryBlock mInitBlock;
|
|
protected ManagedMemoryBlock mRxDescriptor;
|
|
protected ManagedMemoryBlock mTxDescriptor;
|
|
protected List<ManagedMemoryBlock> mRxBuffers;
|
|
protected List<ManagedMemoryBlock> mTxBuffers;
|
|
protected Queue<byte[]> mRecvBuffer;
|
|
protected Queue<byte[]> mTransmitBuffer;
|
|
private int mNextTXDesc;
|
|
|
|
public AMDPCNetII(PCIDeviceNormal device)
|
|
: base()
|
|
{
|
|
if (device == null)
|
|
{
|
|
throw new ArgumentException("PCI Device is null. Unable to get AMD PCNet card");
|
|
}
|
|
|
|
this.pciCard = device;
|
|
this.pciCard.Claimed = true;
|
|
this.pciCard.EnableDevice();
|
|
|
|
this.io = new IOGroup(this.pciCard);
|
|
this.io.RegisterData.DWord = 0;
|
|
|
|
// Get the EEPROM MAC Address and set it as the devices MAC
|
|
byte[] eeprom_mac = new byte[6];
|
|
UInt32 result = io.MAC1.DWord;
|
|
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.MAC2.DWord;
|
|
eeprom_mac[4] = BinaryHelper.GetByteFrom32bit(result, 0);
|
|
eeprom_mac[5] = BinaryHelper.GetByteFrom32bit(result, 8);
|
|
|
|
mac = new MACAddress(eeprom_mac);
|
|
|
|
mInitBlock = new ManagedMemoryBlock(28, 4);
|
|
mRxDescriptor = new ManagedMemoryBlock(256, 16);
|
|
mTxDescriptor = new ManagedMemoryBlock(256, 16);
|
|
|
|
mInitBlock.Write32(0x00, (0x4 << 28) | (0x4 << 20));
|
|
mInitBlock.Write32(0x04, (UInt32)(eeprom_mac[0] | (eeprom_mac[1] << 8) | (eeprom_mac[2] << 16) | (eeprom_mac[3] << 24)));
|
|
mInitBlock.Write32(0x08, (UInt32)(eeprom_mac[4] | (eeprom_mac[5] << 8)));
|
|
mInitBlock.Write32(0x0C, 0x0);
|
|
mInitBlock.Write32(0x10, 0x0);
|
|
mInitBlock.Write32(0x14, mRxDescriptor.Offset);
|
|
mInitBlock.Write32(0x18, mTxDescriptor.Offset);
|
|
|
|
InitializationBlockAddress = mInitBlock.Offset;
|
|
SoftwareStyleRegister = 0x03;
|
|
|
|
mRxBuffers = new List<ManagedMemoryBlock>();
|
|
mTxBuffers = new List<ManagedMemoryBlock>();
|
|
for (uint rxd = 0; rxd < 16; rxd++)
|
|
{
|
|
uint xOffset = rxd * 16;
|
|
|
|
ManagedMemoryBlock buffer = new ManagedMemoryBlock(2048);
|
|
mRxDescriptor.Write32(xOffset + 8, buffer.Offset);
|
|
UInt16 buffer_len = (UInt16)(~buffer.Size);
|
|
buffer_len++;
|
|
UInt32 flags = (UInt32)(buffer_len & 0x0FFF) | 0xF000 | 0x80000000;
|
|
mRxDescriptor.Write32(xOffset + 4, flags);
|
|
mRxBuffers.Add(buffer);
|
|
}
|
|
for (uint txd = 0; txd < 16; txd++)
|
|
{
|
|
uint xOffset = txd * 16;
|
|
|
|
ManagedMemoryBlock buffer = new ManagedMemoryBlock(2048);
|
|
mTxDescriptor.Write32(xOffset + 8, buffer.Offset);
|
|
mTxBuffers.Add(buffer);
|
|
}
|
|
|
|
mNextTXDesc = 0;
|
|
|
|
// Setup our Receive and Transmit Queues
|
|
mTransmitBuffer = new Queue<byte[]>();
|
|
mRecvBuffer = new Queue<byte[]>();
|
|
|
|
INTs.SetIrqHandler(device.InterruptLine, HandleNetworkInterrupt);
|
|
}
|
|
|
|
protected void HandleNetworkInterrupt(ref INTs.IRQContext aContext)
|
|
{
|
|
UInt32 cur_status = StatusRegister;
|
|
|
|
Console.WriteLine("AMD PCNet IRQ raised!");
|
|
|
|
if ((cur_status & 0x100) != 0)
|
|
{
|
|
mInitDone = true;
|
|
}
|
|
if ((cur_status & 0x200) != 0)
|
|
{
|
|
if (mTransmitBuffer.Count > 0)
|
|
{
|
|
byte[] data = mTransmitBuffer.Peek();
|
|
//if (SendBytes(ref data) == true)
|
|
//{
|
|
// mTransmitBuffer.Dequeue();
|
|
//}
|
|
}
|
|
}
|
|
if ((cur_status & 0x400) != 0)
|
|
{
|
|
ReadRawData();
|
|
}
|
|
|
|
StatusRegister = cur_status;
|
|
Global.PIC.EoiSlave();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieve all AMD PCNetII network cards found on computer.
|
|
/// </summary>
|
|
public static void FindAll()
|
|
{
|
|
Console.WriteLine("Scanning for AMD PCNetII cards...");
|
|
PCIDevice device = PCI.GetDevice(0x1022, 0x2000);
|
|
if (device != null)
|
|
{
|
|
AMDPCNetII nic = new AMDPCNetII((PCIDeviceNormal)device);
|
|
|
|
Console.WriteLine("Found AMD PCNetII NIC on PCI " + device.bus + ":" + device.slot + ":" + device.function);
|
|
Console.WriteLine("NIC IRQ: " + device.InterruptLine);
|
|
Console.WriteLine("NIC MAC Address: " + nic.MACAddress.ToString());
|
|
}
|
|
}
|
|
|
|
#region Register Access Properties
|
|
protected UInt32 StatusRegister
|
|
{
|
|
get
|
|
{
|
|
io.RegisterAddress.DWord = 0x00;
|
|
return io.RegisterData.DWord;
|
|
}
|
|
set
|
|
{
|
|
io.RegisterAddress.DWord = 0x00;
|
|
io.RegisterData.DWord = value;
|
|
}
|
|
}
|
|
protected UInt32 InitializationBlockAddress
|
|
{
|
|
get
|
|
{
|
|
UInt32 result;
|
|
|
|
io.RegisterAddress.DWord = 0x01;
|
|
result = io.RegisterData.DWord;
|
|
io.RegisterAddress.DWord = 0x02;
|
|
result |= (io.RegisterData.DWord << 16);
|
|
|
|
return result;
|
|
}
|
|
set
|
|
{
|
|
io.RegisterAddress.DWord = 0x01;
|
|
io.RegisterData.DWord = (value & 0xFFFF);
|
|
io.RegisterAddress.DWord = 0x02;
|
|
io.RegisterData.DWord = (value >> 16);
|
|
}
|
|
}
|
|
protected UInt32 SoftwareStyleRegister
|
|
{
|
|
get
|
|
{
|
|
io.RegisterAddress.DWord = 0x14;
|
|
return io.BusData.DWord;
|
|
}
|
|
set
|
|
{
|
|
io.RegisterAddress.DWord = 0x14;
|
|
io.BusData.DWord = value;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Network Device Implementation
|
|
public override MACAddress MACAddress
|
|
{
|
|
get { return mac; }
|
|
}
|
|
|
|
public override bool Ready
|
|
{
|
|
get { return mInitDone; }
|
|
}
|
|
|
|
public override bool Enable()
|
|
{
|
|
StatusRegister = 0x43;
|
|
|
|
return true;
|
|
}
|
|
|
|
public override bool QueueBytes(byte[] buffer, int offset, int length)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override bool ReceiveBytes(byte[] buffer, int offset, int max)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override byte[] ReceivePacket()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override int BytesAvailable()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override bool IsSendBufferFull()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override bool IsReceiveBufferFull()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
#endregion
|
|
|
|
private void ReadRawData()
|
|
{
|
|
uint status;
|
|
UInt16 recv_size;
|
|
byte[] recv_data;
|
|
|
|
for (int rxd = 0; rxd < 16; rxd++)
|
|
{
|
|
uint xOffset = (uint)(rxd * 16);
|
|
status = mRxDescriptor.Read32(xOffset + 4);
|
|
if ((status & 0x80000000) == 0)
|
|
{
|
|
recv_size = (UInt16)(mRxDescriptor[xOffset + 0] & 0xFFF);
|
|
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);
|
|
}
|
|
|
|
mRxDescriptor.Write32(xOffset + 4, status | 0x80000000);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|