private void CreateChannel(int idx, RangeResource cmd, RangeResource ctrl, InterruptLine interrupt) { List <tysos.lib.File.Property> props = new List <tysos.lib.File.Property>(); string channel_name = ""; switch (idx) { case 0: channel_name = "Primary "; break; case 1: channel_name = "Secondary "; break; case 2: channel_name = "Tertiary "; break; case 3: channel_name = "Quaternary "; break; } props.Add(new tysos.lib.File.Property { Name = "driver", Value = "ata" }); props.Add(new tysos.lib.File.Property { Name = "name", Value = channel_name + "ATA Channel" }); props.Add(new tysos.lib.File.Property { Name = "manufacturer", Value = "Generic" }); props.Add(new tysos.lib.File.Property { Name = "io", Value = cmd }); props.Add(new tysos.lib.File.Property { Name = "io", Value = ctrl }); props.Add(new tysos.lib.File.Property { Name = "interrupt", Value = interrupt }); props.Add(new tysos.lib.File.Property { Name = "channel", Value = idx }); children["ata_" + idx.ToString()] = props; System.Diagnostics.Debugger.Log(0, "pciide", "Created ATA channel:"); foreach (var prop in props) { System.Diagnostics.Debugger.Log(0, "pciide", " " + prop.Name + ": " + prop.Value.ToString()); } }
public override bool InitServer() { System.Diagnostics.Debugger.Log(0, "pcnet32", "PCNET32 driver started"); while (Syscalls.ProcessFunctions.GetNet() == null) { ; } net = Syscalls.ProcessFunctions.GetNet() as net.INetInternal; /* Get our ports and interrupt */ foreach (var r in root) { if (r.Name == "interrupt" && (r.Value is tysos.Resources.InterruptLine)) { irq = r.Value as tysos.Resources.InterruptLine; } else if (r.Name == "vmem" && (r.Value is VirtualMemoryResource64)) { buf = r.Value as VirtualMemoryResource64; } } var pciconf = pci.PCIConfiguration.GetPCIConf(root); io = pciconf.GetBAR(0); if (io == null || irq == null || buf == null) { System.Diagnostics.Debugger.Log(0, "ata", "Insufficient resources provided"); return(false); } buf.Map(); System.Diagnostics.Debugger.Log(0, null, "Using " + io.ToString() + ", " + irq.ToString() + " and " + buf.ToString()); // Enable PCI IO space access uint c_04 = pciconf.ReadConfig(0x4); c_04 &= 0xffff0000U; c_04 |= 0x5; // IO space + bus mastering pciconf.WriteConfig(0x4, c_04); // Reset the controller - try both dword and word reads as we don't // know what mode the controller is currently in io.Read(io.Addr32 + 0x18, 4); io.Read(io.Addr32 + 0x14, 2); // wait 1 us - TODO: use timer for (int i = 0; i < 100000; i++) { ; } // Set DWORD mode io.Write(io.Addr32 + 0x10, 4, 0); // Read our MAC address uint mac03 = io.Read(io.Addr32 + 0x0, 4); uint mac47 = io.Read(io.Addr32 + 0x4, 4); hwaddr = new net.HWAddr(); byte[] mac = hwaddr.MAC; mac[0] = (byte)(mac03 & 0xff); mac[1] = (byte)((mac03 >> 8) & 0xff); mac[2] = (byte)((mac03 >> 16) & 0xff); mac[3] = (byte)((mac03 >> 24) & 0xff); mac[4] = (byte)(mac47 & 0xff); mac[5] = (byte)((mac47 >> 8) & 0xff); StringBuilder sb = new StringBuilder("MAC address: "); for (int i = 0; i < 6; i++) { if (i != 0) { sb.Append(":"); } sb.Append(mac[i].ToString("X2")); } System.Diagnostics.Debugger.Log(0, null, sb.ToString()); // Register interrupt handler irq.RegisterHandler(Interrupt); // Set SWSTYLE to 2 (PCnet-PCI II), 32 bit data accesses + addresses uint sstyle = ReadCSR(58); sstyle &= 0xfff0; sstyle |= 2; WriteCSR(58, sstyle); sstyle = ReadCSR(58); System.Diagnostics.Debugger.Log(0, null, "CSR58: " + sstyle.ToString("X4")); /* Set BCR2.ASEL to one (automatic link type detection - should * already be done by H_RESET, but force it to set incase firmware * has altered it). */ uint bcr2 = ReadBCR(2); bcr2 |= 0x2; WriteBCR(2, bcr2); /* Calculate how many buffers we can make */ ulong buf_size = 1548; // 1544 is used in linux - we round up to a multiple of 16 ulong rde_size = 16; ulong init_blk_size = 32; // actually 28, aligned to 16 bytes ulong buf_count = (buf.Length64 - init_blk_size) / (buf_size + rde_size); // split along the lines of 1 transmit buffer to 2 receive buffers ulong tx_count = buf_count / 3; // reduce it to be the greatest power of 2 less than current count int tx_bit_no = -1; for (int i = 31; i >= 0; i--) { if (((1UL << i) & tx_count) != 0) { tx_bit_no = i; break; } } if (tx_bit_no <= 0) { System.Diagnostics.Debugger.Log(0, null, "Insufficient buffer space provided"); return(false); } if (tx_bit_no > 9) { tx_bit_no = 9; } tx_count = 1UL << tx_bit_no; int rx_bit_no = tx_bit_no + 1; if (rx_bit_no > 9) { rx_bit_no = 9; } ulong rx_count = 1UL << rx_bit_no; System.Diagnostics.Debugger.Log(0, null, "Creating " + rx_count.ToString() + " receive buffers and " + tx_count.ToString() + " transmit buffers"); // set up ring buffers - see spec p. 62 uint rdra_offset; // Offset to start of receive ring buffer (within our own buffer) uint tdra_offset; // Offset to start of transmit ring buffer (within our own buffer) rdra_offset = (uint)init_blk_size; tdra_offset = (uint)(rdra_offset + rde_size * rx_count); uint rd_offset; // Offset to start of receive data uint td_offset; // Offset to start of transmit data rd_offset = (uint)(tdra_offset + rde_size * tx_count); td_offset = (uint)(rd_offset + buf_size * rx_count); rxbufs = new ReceiveRBE[(int)rx_count]; txbufs = new TransmitRBE[(int)tx_count]; for (int i = 0; i < (int)rx_count; i++) { rxbufs[i] = new ReceiveRBE(buf, (int)(rdra_offset + i * (int)rde_size), (int)(rd_offset + i * (int)buf_size), i, (int)buf_size); } for (int i = 0; i < (int)tx_count; i++) { txbufs[i] = new TransmitRBE(buf, (int)(tdra_offset + i * (int)rde_size), (int)(td_offset + i * (int)buf_size), i, (int)buf_size); } // Begin setting up the initialization block (p. 156 in spec) - SSIZE32 = 1 byte[] init_blk = buf.ToArray(); byte rlen = (byte)rx_bit_no; // RLEN = log2 of number of receive buffer entries (max = 9, i.e. 512 entries) byte tlen = (byte)tx_bit_no; // TLEN = log2 of number of receive buffer entries (max = 9, i.e. 512 entries) init_blk[0] = 0; // MODE = 0 init_blk[1] = 0; // MODE = 0 init_blk[2] = (byte)(0 | (rlen << 4)); // reserved / rlen init_blk[3] = (byte)(0 | (tlen << 4)); // reserved / tlen for (int i = 0; i < 6; i++) { init_blk[4 + i] = mac[i]; // PADR } init_blk[0xa] = 0; // reserved init_blk[0xb] = 0; // reserved for (int i = 0; i < 8; i++) { init_blk[0xc + i] = 0; // LADRF - disable logical addressing } byte[] rdra_arr = BitConverter.GetBytes(buf.MappedTo.Addr32 + rdra_offset); for (int i = 0; i < 4; i++) { init_blk[0x14 + i] = rdra_arr[i]; } byte[] tdra_arr = BitConverter.GetBytes(buf.MappedTo.Addr32 + tdra_offset); for (int i = 0; i < 4; i++) { init_blk[0x18 + i] = tdra_arr[i]; } // write init block address to CSR1 + 2 uint ibaddr = buf.MappedTo.Addr32; WriteCSR(1, ibaddr & 0xffffU); WriteCSR(2, (ibaddr >> 16) & 0xffffU); // mask out IDON interrupt, ensure little endian mode uint csr3 = (1U << 8); WriteCSR(3, csr3); // set automatic frame padding uint csr4 = ReadCSR(4); csr4 |= (1U << 11); WriteCSR(4, csr4); // set init and interrupt enable in CSR 0 uint csr0 = (1U << 0) | (1U << 6); WriteCSR(0, csr0); // poll until IDON set while ((csr0 & 1U << 8) == 0) { csr0 = ReadCSR(0); } // handle setting start and stop bits (CSR0) in separate Start/Stop functions root.Add(new File.Property { Name = "class", Value = "netdev" }); Tags.Add("class"); return(true); }