Exemple #1
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);
        }
Exemple #2
0
        bool Interrupt()
        {
            uint csr0 = ReadCSR(0);
            uint csr4 = ReadCSR(4);
            uint ints = csr0;

            System.Diagnostics.Debugger.Log(0, "pcnet", "INTERRUPT: CSR0: " + csr0.ToString("X4") +
                                            ", CSR4: " + csr4.ToString("X4"));


            // Is RINT set?
            if ((ints & 0x0400) != 0)
            {
                /* Loop through those buffers we own */
                int i = cur_rx_buf;

                do
                {
                    ReceiveRBE b = rxbufs[i];

                    if (b.DriverOwns)
                    {
                        uint   dlen  = b.MCNT;
                        ushort flags = b.Flags;

                        System.Diagnostics.Debugger.Log(0, "pcnet", "Receive buffer " +
                                                        i.ToString() + " has message of length " + dlen.ToString() +
                                                        ", flags: " + flags.ToString("X4"));

                        /*
                         * byte[] d = b.Buffer;
                         * StringBuilder sb = null;
                         * for(uint j = 0; j < dlen; j++)
                         * {
                         *  if((j % 8) == 0)
                         *  {
                         *      if (sb != null)
                         *          System.Diagnostics.Debugger.Log(0, "pcnet", sb.ToString());
                         *
                         *      sb = new StringBuilder(j.ToString("X4"));
                         *      sb.Append(":");
                         *  }
                         *
                         *  sb.Append(" ");
                         *  sb.Append(d[j].ToString("X2"));
                         * }
                         * if (sb != null)
                         *  System.Diagnostics.Debugger.Log(0, "pcnet", sb.ToString()); */

                        // Send the message to the net process
                        if (b.Error == false)
                        {
                            byte[] msg = new byte[dlen];
                            for (uint j = 0; j < dlen; j++)
                            {
                                msg[j] = b.Buffer[j];
                            }
                            net.PacketReceived(msg, dev_no, 0, msg.Length, null);
                        }

                        // reset the descriptor entry
                        b.Reset();
                    }
                    else
                    {
                        break;
                    }

                    i = next_rx_buf(i);
                } while (i != cur_rx_buf);

                // advance rx pointer
                cur_rx_buf = i;
            }

            // Mark all interrupts as handled
            csr0 |= 0x7f00;
            WriteCSR(0, csr0);
            csr4 |= 0x26a;
            WriteCSR(4, csr4);

            return(true);
        }