1/* @title: e1000 */
2#include <compiler.h>
3#include <drivers/pci.h>
4#include <log.h>
5#include <stdbool.h>
6#include <stdint.h>
7#pragma once
8// Register offsets
9#define E1000_REG_CTRL 0x0000
10#define E1000_REG_STATUS 0x0008
11#define E1000_REG_TCTL 0x0400
12#define E1000_REG_TDBAL 0x03800
13#define E1000_REG_TDBAH 0x03804
14#define E1000_REG_TDLEN 0x03808
15#define E1000_REG_TDH 0x03810
16#define E1000_REG_TDT 0x03818
17
18#define E1000_REG_RCTL 0x0100
19#define E1000_REG_RDBAL 0x02800
20#define E1000_REG_RDBAH 0x02804
21#define E1000_REG_RDLEN 0x02808
22#define E1000_REG_RDH 0x02810
23#define E1000_REG_RDT 0x02818
24
25#define E1000_REG_IMS 0x00D0
26#define E1000_REG_ICR 0x00C0
27
28// Transmit Control Register
29#define E1000_TCTL_EN (1 << 1)
30#define E1000_TCTL_PSP (1 << 3)
31#define E1000_TCTL_CT_SHIFT 4
32#define E1000_TCTL_COLD_SHIFT 12
33
34// Receive Control Register
35#define E1000_RCTL_EN (1 << 1)
36#define E1000_RCTL_BAM (1 << 15)
37#define E1000_RCTL_SECRC (1 << 26)
38
39#define E1000_NUM_RX_DESC 64
40#define E1000_NUM_TX_DESC 64
41
42struct e1000_device {
43 uint32_t *regs; // MMIO virtual base
44
45 // TX
46 struct e1000_tx_desc *tx_descs;
47 uintptr_t tx_descs_phys;
48 uint32_t tx_tail;
49 void *tx_buffers[E1000_NUM_TX_DESC]; // one per desc
50
51 // RX
52 struct e1000_rx_desc *rx_descs;
53 uintptr_t rx_descs_phys;
54 uint32_t rx_tail;
55 void *rx_buffers[E1000_NUM_RX_DESC];
56
57 // PCI location
58 uint8_t bus, device, function;
59};
60
61struct e1000_tx_desc {
62 uint64_t addr;
63 uint16_t length;
64 uint8_t cso;
65 union {
66 uint8_t cmd;
67 struct {
68 uint8_t eop : 1;
69 uint8_t ifcs : 1;
70 uint8_t ic : 1;
71 uint8_t rs : 1;
72 uint8_t rsvd : 1;
73 uint8_t dext : 1;
74 uint8_t vlei : 1;
75 uint8_t ide : 1;
76 };
77 };
78 union {
79 uint8_t status;
80 struct {
81 uint8_t dd : 1;
82 uint8_t ec : 1;
83 uint8_t lc : 1;
84 uint8_t rsvd0 : 5;
85 };
86 };
87 uint8_t css;
88 uint16_t special;
89} __packed;
90
91struct e1000_rx_desc {
92 uint64_t addr;
93 uint16_t length;
94 uint16_t checksum;
95 union {
96 uint8_t status;
97 struct {
98 uint8_t dd : 1;
99 uint8_t eop : 1;
100 uint8_t ixsm : 1;
101 uint8_t vp : 1;
102 uint8_t rsvd : 4;
103 };
104 };
105 uint8_t errors;
106 uint16_t special;
107} __packed;
108
109// Ethernet header (14 bytes)
110struct eth_hdr {
111 uint8_t dest[6];
112 uint8_t src[6];
113 uint16_t ethertype;
114} __packed;
115
116// IPv4 header (20 bytes)
117struct ipv4_hdr {
118 uint8_t version_ihl;
119 uint8_t tos;
120 uint16_t total_length;
121 uint16_t id;
122 uint16_t flags_fragment;
123 uint8_t ttl;
124 uint8_t protocol;
125 uint16_t checksum;
126 uint32_t src_ip;
127 uint32_t dest_ip;
128} __packed;
129
130struct icmp_hdr {
131 uint8_t type;
132 uint8_t code;
133 uint16_t checksum;
134 uint16_t identifier;
135 uint16_t sequence;
136} __packed;
137
138#define E1000_TXD_CMD_EOP (1 << 0)
139#define E1000_TXD_CMD_IFCS (1 << 1)
140#define E1000_TXD_CMD_RS (1 << 3)
141#define E1000_TXD_STAT_DD (1 << 0)
142
143#define E1000_RXD_STAT_DD (1 << 0)
144#define E1000_RXD_STAT_EOP (1 << 1)
145#define E1000_CTRL_RST (1 << 26) // Software reset
146
147#define E1000_BAR_INDEX 0
148#define PCI_BAR0 0x10
149
150#define E1000_RX_BUF_SIZE 2048
151
152bool e1000_init(struct pci_device *dev, struct e1000_device *out);
153#define E1000_MAX_TX_PACKET_SIZE 1518 // Standard Ethernet frame
154
155LOG_SITE_EXTERN(e1000);
156LOG_HANDLE_EXTERN(e1000);
157#define e1000_log(log_level, fmt, ...) \
158 log(LOG_SITE(e1000), LOG_HANDLE(e1000), log_level, fmt, ##__VA_ARGS__)
159