Пример #1
0
        public RPCResult <bool> TransmitPacket(byte[] packet, int dev_no, int packet_offset,
                                               int packet_len, net.p_addr dest)
        {
            if (txbufs[cur_tx_buf].DriverOwns == false)
            {
                /* No free transmit buffers.  Signal the driver to try and
                 * send now, but fail the current packet */
                uint csr0 = ReadCSR(0);
                csr0 |= (1U << 3);
                WriteCSR(0, csr0);
                return(false);
            }

            TransmitRBE t = txbufs[cur_tx_buf];

            t.Reset();
            uint len = (uint)packet_len;

            byte[] b = t.Buffer;
            for (uint i = 0; i < len; i++)
            {
                b[i] = packet[packet_offset + i];
            }
            t.STP        = true;
            t.ENP        = true;
            t.BCNT       = len;
            t.DriverOwns = false;

            cur_tx_buf = next_tx_buf(cur_tx_buf);

            return(true);
        }
Пример #2
0
        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);
        }