summaryrefslogtreecommitdiff
path: root/kernel/e1000.c
diff options
context:
space:
mode:
authorSanjit Bhat <[email protected]>2023-10-26 06:44:48 -0400
committerSanjit Bhat <[email protected]>2023-10-26 06:44:48 -0400
commitcfae93475dfb4cb5cfe264f4c029136e1447c262 (patch)
tree699903e093e3a23caf7ce3899e7c80e48511f900 /kernel/e1000.c
parent1ed40716eb54e371df9d1814b9129666b3fe4f09 (diff)
downloadxv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.tar.gz
xv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.tar.bz2
xv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.zip
net add missing files
Diffstat (limited to 'kernel/e1000.c')
-rw-r--r--kernel/e1000.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/kernel/e1000.c b/kernel/e1000.c
new file mode 100644
index 0000000..70a2adf
--- /dev/null
+++ b/kernel/e1000.c
@@ -0,0 +1,129 @@
+#include "types.h"
+#include "param.h"
+#include "memlayout.h"
+#include "riscv.h"
+#include "spinlock.h"
+#include "proc.h"
+#include "defs.h"
+#include "e1000_dev.h"
+#include "net.h"
+
+#define TX_RING_SIZE 16
+static struct tx_desc tx_ring[TX_RING_SIZE] __attribute__((aligned(16)));
+static struct mbuf *tx_mbufs[TX_RING_SIZE];
+
+#define RX_RING_SIZE 16
+static struct rx_desc rx_ring[RX_RING_SIZE] __attribute__((aligned(16)));
+static struct mbuf *rx_mbufs[RX_RING_SIZE];
+
+// remember where the e1000's registers live.
+static volatile uint32 *regs;
+
+struct spinlock e1000_lock;
+
+// called by pci_init().
+// xregs is the memory address at which the
+// e1000's registers are mapped.
+void
+e1000_init(uint32 *xregs)
+{
+ int i;
+
+ initlock(&e1000_lock, "e1000");
+
+ regs = xregs;
+
+ // Reset the device
+ regs[E1000_IMS] = 0; // disable interrupts
+ regs[E1000_CTL] |= E1000_CTL_RST;
+ regs[E1000_IMS] = 0; // redisable interrupts
+ __sync_synchronize();
+
+ // [E1000 14.5] Transmit initialization
+ memset(tx_ring, 0, sizeof(tx_ring));
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ tx_ring[i].status = E1000_TXD_STAT_DD;
+ tx_mbufs[i] = 0;
+ }
+ regs[E1000_TDBAL] = (uint64) tx_ring;
+ if(sizeof(tx_ring) % 128 != 0)
+ panic("e1000");
+ regs[E1000_TDLEN] = sizeof(tx_ring);
+ regs[E1000_TDH] = regs[E1000_TDT] = 0;
+
+ // [E1000 14.4] Receive initialization
+ memset(rx_ring, 0, sizeof(rx_ring));
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ rx_mbufs[i] = mbufalloc(0);
+ if (!rx_mbufs[i])
+ panic("e1000");
+ rx_ring[i].addr = (uint64) rx_mbufs[i]->head;
+ }
+ regs[E1000_RDBAL] = (uint64) rx_ring;
+ if(sizeof(rx_ring) % 128 != 0)
+ panic("e1000");
+ regs[E1000_RDH] = 0;
+ regs[E1000_RDT] = RX_RING_SIZE - 1;
+ regs[E1000_RDLEN] = sizeof(rx_ring);
+
+ // filter by qemu's MAC address, 52:54:00:12:34:56
+ regs[E1000_RA] = 0x12005452;
+ regs[E1000_RA+1] = 0x5634 | (1<<31);
+ // multicast table
+ for (int i = 0; i < 4096/32; i++)
+ regs[E1000_MTA + i] = 0;
+
+ // transmitter control bits.
+ regs[E1000_TCTL] = E1000_TCTL_EN | // enable
+ E1000_TCTL_PSP | // pad short packets
+ (0x10 << E1000_TCTL_CT_SHIFT) | // collision stuff
+ (0x40 << E1000_TCTL_COLD_SHIFT);
+ regs[E1000_TIPG] = 10 | (8<<10) | (6<<20); // inter-pkt gap
+
+ // receiver control bits.
+ regs[E1000_RCTL] = E1000_RCTL_EN | // enable receiver
+ E1000_RCTL_BAM | // enable broadcast
+ E1000_RCTL_SZ_2048 | // 2048-byte rx buffers
+ E1000_RCTL_SECRC; // strip CRC
+
+ // ask e1000 for receive interrupts.
+ regs[E1000_RDTR] = 0; // interrupt after every received packet (no timer)
+ regs[E1000_RADV] = 0; // interrupt after every packet (no timer)
+ regs[E1000_IMS] = (1 << 7); // RXDW -- Receiver Descriptor Write Back
+}
+
+int
+e1000_transmit(struct mbuf *m)
+{
+ //
+ // Your code here.
+ //
+ // the mbuf contains an ethernet frame; program it into
+ // the TX descriptor ring so that the e1000 sends it. Stash
+ // a pointer so that it can be freed after sending.
+ //
+
+ return 0;
+}
+
+static void
+e1000_recv(void)
+{
+ //
+ // Your code here.
+ //
+ // Check for packets that have arrived from the e1000
+ // Create and deliver an mbuf for each packet (using net_rx()).
+ //
+}
+
+void
+e1000_intr(void)
+{
+ // tell the e1000 we've seen this interrupt;
+ // without this the e1000 won't raise any
+ // further interrupts.
+ regs[E1000_ICR] = 0xffffffff;
+
+ e1000_recv();
+}