CS350 COS
COS
Loading...
Searching...
No Matches
e1000.c
Go to the documentation of this file.
1
2#include <stdbool.h>
3#include <stdint.h>
4#include <string.h>
5
6#include <sys/kassert.h>
7#include <sys/kdebug.h>
8#include <sys/kmem.h>
9#include <sys/semaphore.h>
10#include <sys/pci.h>
11#include <sys/irq.h>
12#include <sys/mbuf.h>
13#include <sys/nic.h>
14
15#include <machine/pmap.h>
16
17typedef struct E1000Device
18{
20 const char *name;
23
25{
26 { 0x8086100e, "E1000", 0 }, // EERD is not supported
27 // { 0x80861209, "i82551", 0 }, // Doesn't seem to work on my qemu build
28 { 0, "", 0 },
29};
30
32
33/*
34 * Hardware Structures
35 */
36
37#define E1000_REG_CTRL 0x0000
38#define E1000_REG_STATUS 0x0008
39#define E1000_REG_EECD 0x0010
40#define E1000_REG_EERD 0x0014
41#define E1000_REG_ICR 0x00C0
42#define E1000_REG_ICS 0x00C8
43#define E1000_REG_IMS 0x00D0
44#define E1000_REG_IMC 0x00D8
45#define E1000_REG_RCTL 0x0100
46#define E1000_REG_TCTL 0x0400
47
48#define E1000_REG_RDBAL 0x2800
49#define E1000_REG_RDBAH 0x2804
50#define E1000_REG_RDLEN 0x2808
51#define E1000_REG_RDH 0x2810
52#define E1000_REG_RDT 0x2818
53#define E1000_REG_RDTR 0x2820
54
55#define E1000_REG_TDBAL 0x3800
56#define E1000_REG_TDBAH 0x3804
57#define E1000_REG_TDLEN 0x3808
58#define E1000_REG_TDH 0x3810
59#define E1000_REG_TDT 0x3818
60#define E1000_REG_TIDV 0x3820
61#define E1000_REG_TADV 0x382C
62
63#define E1000_REG_MTABASE 0x5200
64
65// EEPROM Offsets
66#define NVM_MAC_ADDR 0x0000
67#define NVM_DEVICE_ID 0x000D
68#define NVM_VENDOR_ID 0x000E
69
70// Control Flags
71#define CTRL_SLU (1 << 6)
72
73// Recieve Control Flags
74#define RCTL_EN (1 << 1)
75#define RCTL_SBP (1 << 2)
76#define RCTL_UPE (1 << 3)
77#define RCTL_MPE (1 << 4)
78#define RCTL_LPE (1 << 5)
79#define RCTL_BSIZE_1K (0x1 << 16)
80#define RCTL_BSIZE_2K (0x0 << 16)
81#define RCTL_BSIZE_4K ((1 << 25) | (0x3 << 16))
82#define RCTL_BSIZE_8K ((1 << 25) | (0x2 << 16))
83#define RCTL_BSIZE_16K ((1 << 25) | (0x1 << 16))
84
85// Transmit Control Flags
86#define TCTL_EN (1 << 1)
87#define TCTL_PSP (1 << 3)
88
89// Interrupt Control Register
90#define ICR_TXDW (1 << 0)
91#define ICR_LSC (1 << 2)
92#define ICR_RXO (1 << 6)
93#define ICR_RXT0 (1 << 7)
94
95typedef struct PACKED E1000RXDesc {
96 volatile uint64_t addr; // Address
97 volatile uint16_t len; // Length
98 volatile uint16_t csum; // Checksum
99 volatile uint8_t status; // Status
100 volatile uint8_t errors; // Errors
103
104#define RDESC_STATUS_EOP (1 << 1)
105#define RDESC_STATUS_DD (1 << 0)
106
107#define RDESC_ERROR_RDE (1 << 7) /* Receive Data Error */
108#define RDESC_ERROR_CE (1 << 0) /* CRC Error */
109
110typedef struct PACKED E1000TXDesc {
111 volatile uint64_t addr; // Address
112 volatile uint16_t len; // Length
113 volatile uint8_t cso; // Checksum Offset
114 volatile uint8_t cmd; // Command
115 volatile uint8_t status; // Status
116 volatile uint8_t css; // Checksum start
119
120#define TDESC_CMD_RS (1 << 3) /* Report Status */
121#define TDESC_CMD_IC (1 << 2) /* Insert Checksum */
122#define TDESC_CMD_IFCS (1 << 1) /* Insert Ethernet FCS/CRC */
123#define TDESC_CMD_EOP (1 << 0) /* End-of-Packet */
124
125/*
126 * Driver Configuration and Structures
127 */
128
129typedef struct E1000Dev {
130 NIC nic; // Must be first
141
142#define E1000_TX_QLEN 128
143#define E1000_RX_QLEN 128
144
145#define E1000_MAX_MTU 9000
146
147// Memory Resources
148static bool runOnce = false;
154
155void *
157{
158 return Slab_Alloc(&rxPool);
159}
160
161void
163{
165}
166
167void
169{
170 PCIDevice dev;
171
172 dev.bus = bus;
173 dev.slot = slot;
174 dev.func = func;
175 dev.vendor = PCI_GetVendorID(&dev);
176 dev.device = PCI_GetDeviceID(&dev);
177
178 uint32_t device = dev.vendor << 16 | dev.device;
179
180 int deviceIdx = 0;
181 while (deviceList[deviceIdx].device != 0x0) {
182 if (deviceList[deviceIdx].device == device) {
183 kprintf("E1000: Found %s\n", deviceList[deviceIdx].name);
184 // Configure and add disks
185 E1000_Configure(dev);
186 }
187
188 deviceIdx++;
189 }
190}
191
192static inline uint32_t
194{
195 return *(uint32_t volatile *)(dev->mmiobase + addr);
196}
197
198static inline void
200{
201 *(uint32_t *)(dev->mmiobase + addr) = val;
202}
203
204static uint16_t
206{
207 uint16_t val;
208
209 // Write Address
210 MMIO_Write32(dev, E1000_REG_EERD, ((uint32_t)addr << 8) | 1);
211
212 // Wait for ready bit
213 while (1) {
214 val = MMIO_Read32(dev, E1000_REG_EERD);
215 if (val & 0x10)
216 break;
217 }
218
219 kprintf("%08x\n", val);
220
221 return (uint16_t)((val >> 16) & 0x0000FFFF);
222}
223
224void
226{
227 // Free memory
228 kprintf("TXPOLL\n");
229}
230
231void
233{
234 while (dev->rxDesc[dev->rxTail].status & RDESC_STATUS_DD) {
235 //void *data = (void *)DMPA2VA(dev->rxDesc[dev->rxTail].addr);
236 //uint16_t len = dev->rxDesc[dev->rxTail].len;
237
238 // Look for packet fragments up to EOP set in status
239 if ((dev->rxDesc[dev->rxTail].status & RDESC_STATUS_EOP) &&
240 (dev->rxDesc[dev->rxTail].errors == 0)) {
241 // Process packet
242 /*
243 * XXX: Need to create a queue and copyout packets here, because
244 * I'm seeing multiple interrupts.
245 *
246 * kprintf("E1000: Int\n");
247 */
249 }
250
251 if (dev->rxDesc[dev->rxTail].errors) {
252 kprintf("E1000: Error in RX Queue %x\n",
253 dev->rxDesc[dev->rxTail].errors);
254 dev->rxDesc[dev->rxTail].status = 0;
255 dev->rxDesc[dev->rxTail].errors = 0;
257 dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
258 }
259
260 /*
261 dev->rxDesc[dev->rxTail].status = 0;
262 dev->rxDesc[dev->rxTail].errors = 0;
263 // XXX: Should write this only once
264 MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
265 dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
266 */
267 }
268}
269
270void
272{
273 E1000Dev *dev = (E1000Dev *)arg;
274
275 kprintf("E1000 (%d:%d) Interrupt\n",
276 dev->dev.bus, dev->dev.slot);
277
278 uint32_t cause = MMIO_Read32(dev, E1000_REG_ICR);
279
280 // Link Status
281 if (cause & ICR_LSC) {
282 cause &= ~ICR_LSC;
284 }
285
286 // Transmit Queue Empty
287 if (cause & 3) {
288 cause &= ~3;
289 E1000_TXPoll(dev);
290 }
291
292 // Receive Overrun
293 if (cause & ICR_RXO) {
294 cause &= ~ICR_RXO;
295 kprintf("underrun %u %u\n", MMIO_Read32(dev, E1000_REG_RDH), dev->rxTail);
296
297 E1000_RXPoll(dev);
298 }
299
300 // Receive Timer
301 if (cause & ICR_RXT0) {
302 cause &= ~ICR_RXT0;
303 E1000_RXPoll(dev);
304 }
305
306 if (cause != 0) {
307 kprintf("E1000: Unhandled cause %08x\n", cause);
308 }
309
311}
312
313/*
314 * Read packets from NIC
315 */
316int
317E1000_Dequeue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
318{
319 E1000Dev *dev = (E1000Dev *)nic;
320
321retry:
323
324 Spinlock_Lock(&dev->lock);
325 if ((dev->rxDesc[dev->rxTail].status & RDESC_STATUS_EOP) &&
326 (dev->rxDesc[dev->rxTail].errors == 0)) {
327 void *data = (void *)DMPA2VA(dev->rxDesc[dev->rxTail].addr);
328 uint16_t len = dev->rxDesc[dev->rxTail].len;
329
330 //Debug_PrintHex(data, len, 0, len);
331 // Use CB instead
332 memcpy((void *)mbuf->vaddr, data, len);
333
334 dev->rxDesc[dev->rxTail].status = 0;
335 dev->rxDesc[dev->rxTail].errors = 0;
336 // XXX: Should write this only once
338 dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
339 } else {
340 /*
341 * XXX: Need to remove this once I do the copyout inside the interrupt
342 * handler.
343 */
344 /*kprintf("Packet not ready %d %x %x\n",
345 dev->rxTail,
346 dev->rxDesc[dev->rxTail].status,
347 dev->rxDesc[dev->rxTail].errors);*/
348 Spinlock_Unlock(&dev->lock);
349 goto retry;
350 }
351 Spinlock_Unlock(&dev->lock);
352
353 return 0;
354}
355
356/*
357 * Transmit packets
358 */
359int
360E1000_Enqueue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
361{
362 E1000Dev *dev = (E1000Dev *)nic;
363 void *data = (void *)DMPA2VA(dev->txDesc[dev->txTail].addr);
364
365 // Copy data
366 memcpy(data, (void *)mbuf->vaddr, mbuf->len);
367 dev->txDesc[dev->txTail].len = mbuf->len;
368
371 dev->txTail = (dev->txTail + 1) % E1000_TX_QLEN;
372
373 // Wait for transmit to complete
374
375 return 0;
376}
377
378void
380{
381 int i;
382
383 // Zero out Multicast Table Array
384 for (i = 0; i < 128; i++) {
385 MMIO_Write32(dev, E1000_REG_MTABASE + (i * 4), 0);
386 }
387
388 dev->rxDesc = (E1000RXDesc *)E1000RXDesc_Alloc();
389 for (i = 0; i < E1000_RX_QLEN; i++) {
390 dev->rxDesc[i].addr = VA2PA((uintptr_t)PAlloc_AllocPage()); // LOOKUP IN PMAP
391 dev->rxDesc[i].status = 0;
392 }
393
394 // Setup base and length of recieve descriptors
397 MMIO_Write32(dev, E1000_REG_RDBAL, (uint32_t)(base & 0xFFFFFFFF));
399
402 dev->rxTail = 0;
403
406}
407
408void
410{
411 int i;
412
413 dev->txDesc = (E1000TXDesc *)E1000RXDesc_Alloc();
414 for (i = 0; i < E1000_TX_QLEN; i++) {
415 dev->txDesc[i].addr = VA2PA((uintptr_t)PAlloc_AllocPage()); // LOOKUP IN PMAP
416 dev->txDesc[i].cmd = 0;
417 }
418
419 // Setup base and length of recieve descriptors
422 MMIO_Write32(dev, E1000_REG_TDBAL, (uint32_t)(base & 0xFFFFFFFF));
424
427 dev->txTail = 0;
428
429 // Interrupt Delay Timers
432
434}
435
436void
438{
439 E1000Dev *ethDev = (E1000Dev *)PAlloc_AllocPage();
440 PCI_Configure(&dev);
441
442 // Ensure that the NIC structure is the first thing inside E1000Dev
443 ASSERT((void *)ethDev == (void *)&ethDev->nic);
444
445 if (!runOnce) {
446 runOnce = true;
447
448 //E1000_MAX_MTU + 14 + 4, 4096);
449 Slab_Init(&rxPool, "E1000 RX Pool", 4096, 4096);
450 Slab_Init(&rxDescPool, "E1000 RX Descriptors", E1000_RX_QLEN*sizeof(E1000RXDesc), 16);
451 Slab_Init(&txDescPool, "E1000 TX Descriptors", E1000_TX_QLEN*sizeof(E1000TXDesc), 16);
452 }
453
454 // Copy PCIDevice structure
455 memcpy(&ethDev->dev, &dev, sizeof(dev));
456
457 // MMIO
458 int bar;
459 for (bar = 0; bar < PCI_MAX_BARS; bar++) {
460 if (dev.bars[bar].size == 0)
461 continue;
462
463 kprintf("E1000: BAR%d base=%08x size=%08x %s\n",
464 bar, dev.bars[bar].base, dev.bars[bar].size,
465 dev.bars[bar].type == PCIBAR_TYPE_IO ? "IO" : "Mem");
466 }
467
468 ethDev->mmiobase = (uint8_t *)DMPA2VA(dev.bars[0].base);
469
470 // Enable Link
472
473 // Register IRQs
474 kprintf("E1000: IRQ %d\n", dev.irq);
475 ethDev->irqHandle.irq = dev.irq;
476 ethDev->irqHandle.cb = &E1000_Interrupt;
477 ethDev->irqHandle.arg = ethDev;
478 IRQ_Register(dev.irq, &ethDev->irqHandle);
479
480 kprintf("E1000: MAC XX:XX:XX:XX:XX:XX\n");
481 for (int i = 0; i < 3; i++) {
482 E1000_EEPROM_Read(ethDev, NVM_MAC_ADDR + 2*i);
483 }
484
485 // Device lock
486 Spinlock_Init(&ethDev->lock, "E1000 Spinlock", SPINLOCK_TYPE_NORMAL);
487
488 // IO Semaphore
489 Semaphore_Init(&ethDev->ioSema, 0, "E1000 Semaphore");
490 ethDev->nic.tx = &E1000_Enqueue;
491 ethDev->nic.rx = &E1000_Dequeue;
492
493 // Enable interrupts
494 //MMIO_Write32(ethDev, E1000_REG_IMC, ~0);
495 MMIO_Write32(ethDev, E1000_REG_IMS, 0x1F6DC); //ICR_TXDW | ICR_RXO | ICR_RXT0);
496 MMIO_Read32(ethDev, E1000_REG_ICR); // Clear pending interrupts
497
498 E1000_RXInit(ethDev);
499 E1000_TXInit(ethDev);
500
501 ethDev->nic.handle = ethDev;
502 // XXX: Fill in callbacks
503 NIC_AddNIC(&ethDev->nic);
504}
505
#define PACKED
Definition: cdefs.h:7
uint16_t PCI_GetVendorID(PCIDevice *dev)
Definition: pci.c:107
uint16_t PCI_GetDeviceID(PCIDevice *dev)
Definition: pci.c:101
void PCI_Configure(PCIDevice *dev)
Definition: pci.c:249
#define E1000_REG_MTABASE
Definition: e1000.c:63
E1000RXDesc * rxDesc
Definition: e1000.c:134
#define E1000_REG_IMS
Definition: e1000.c:43
#define CTRL_SLU
Definition: e1000.c:71
volatile uint8_t cmd
Definition: e1000.c:114
#define E1000_REG_RDLEN
Definition: e1000.c:50
#define E1000_REG_TCTL
Definition: e1000.c:46
#define E1000_REG_RDBAH
Definition: e1000.c:49
static Slab rxPool
Definition: e1000.c:149
volatile uint64_t addr
Definition: e1000.c:96
#define E1000_REG_RCTL
Definition: e1000.c:45
void E1000_TXPoll(E1000Dev *dev)
Definition: e1000.c:225
static void MMIO_Write32(E1000Dev *dev, uint64_t addr, uint32_t val)
Definition: e1000.c:199
#define E1000_REG_TDT
Definition: e1000.c:59
static Slab txDescPool
Definition: e1000.c:151
static uint16_t E1000_EEPROM_Read(E1000Dev *dev, uint8_t addr)
Definition: e1000.c:205
static E1000Device deviceList[]
Definition: e1000.c:24
#define TDESC_CMD_RS
Definition: e1000.c:120
uint32_t flags
Definition: e1000.c:21
IRQHandler irqHandle
Definition: e1000.c:132
#define ICR_LSC
Definition: e1000.c:91
volatile uint16_t special
Definition: e1000.c:101
#define ICR_RXO
Definition: e1000.c:92
E1000TXDesc * txDesc
Definition: e1000.c:135
void E1000_RXPoll(E1000Dev *dev)
Definition: e1000.c:232
#define E1000_RX_QLEN
Definition: e1000.c:143
uint8_t * mmiobase
Definition: e1000.c:133
volatile uint8_t status
Definition: e1000.c:99
#define TCTL_PSP
Definition: e1000.c:87
#define RCTL_EN
Definition: e1000.c:74
static uint32_t MMIO_Read32(E1000Dev *dev, uint64_t addr)
Definition: e1000.c:193
const char * name
Definition: e1000.c:20
#define E1000_REG_ICR
Definition: e1000.c:41
volatile uint8_t errors
Definition: e1000.c:100
int E1000_Enqueue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
Definition: e1000.c:360
#define E1000_REG_TDH
Definition: e1000.c:58
#define RCTL_MPE
Definition: e1000.c:77
#define E1000_REG_RDBAL
Definition: e1000.c:48
volatile uint64_t addr
Definition: e1000.c:111
uint32_t txTail
Definition: e1000.c:137
PCIDevice dev
Definition: e1000.c:131
NIC nic
Definition: e1000.c:130
static Slab rxDescPool
Definition: e1000.c:150
#define TDESC_CMD_IFCS
Definition: e1000.c:122
void E1000_Configure(PCIDevice dev)
Definition: e1000.c:437
void * RXPOOL_Alloc()
Definition: e1000.c:156
void E1000_TXInit(E1000Dev *dev)
Definition: e1000.c:409
#define E1000_REG_TDBAH
Definition: e1000.c:56
#define RCTL_BSIZE_4K
Definition: e1000.c:81
void RXPOOL_Free(void *buf)
Definition: e1000.c:162
int E1000_Dequeue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
Definition: e1000.c:317
Semaphore ioSema
Definition: e1000.c:139
#define E1000_REG_RDH
Definition: e1000.c:51
Spinlock lock
Definition: e1000.c:138
volatile uint16_t len
Definition: e1000.c:112
#define TCTL_EN
Definition: e1000.c:86
#define RDESC_STATUS_EOP
Definition: e1000.c:104
volatile uint8_t cso
Definition: e1000.c:113
#define TDESC_CMD_EOP
Definition: e1000.c:123
volatile uint16_t len
Definition: e1000.c:97
#define E1000_REG_TIDV
Definition: e1000.c:60
#define E1000_REG_EERD
Definition: e1000.c:40
#define E1000_REG_TDLEN
Definition: e1000.c:57
#define E1000_REG_CTRL
Definition: e1000.c:37
void E1000_Init(uint32_t bus, uint32_t slot, uint32_t func)
Definition: e1000.c:168
uint32_t device
Definition: e1000.c:19
void E1000_Interrupt(void *arg)
Definition: e1000.c:271
uint32_t rxTail
Definition: e1000.c:136
volatile uint16_t csum
Definition: e1000.c:98
#define RCTL_UPE
Definition: e1000.c:76
#define ICR_RXT0
Definition: e1000.c:93
volatile uint8_t status
Definition: e1000.c:115
#define E1000_TX_QLEN
Definition: e1000.c:142
#define RDESC_STATUS_DD
Definition: e1000.c:105
volatile uint8_t css
Definition: e1000.c:116
#define E1000_REG_TDBAL
Definition: e1000.c:55
volatile uint16_t special
Definition: e1000.c:117
#define E1000_REG_TADV
Definition: e1000.c:61
void E1000_RXInit(E1000Dev *dev)
Definition: e1000.c:379
#define E1000_REG_RDT
Definition: e1000.c:52
static bool runOnce
Definition: e1000.c:148
#define NVM_MAC_ADDR
Definition: e1000.c:66
static char buf[4096]
Definition: ethdump.c:10
static MBuf mbuf
Definition: ethdump.c:11
void IRQ_Register(int irq, struct IRQHandler *h)
Definition: irq.c:35
#define ASSERT(_x)
Definition: kassert.h:8
int kprintf(const char *fmt,...)
Definition: printf.c:210
void Slab_Free(Slab *slab, void *obj)
Definition: slab.c:135
void * PAlloc_AllocPage()
Definition: palloc.c:188
void * Slab_Alloc(Slab *slab) __attribute__((malloc))
Definition: slab.c:105
#define DEFINE_SLAB(_type, _pool)
Definition: kmem.h:69
void Slab_Init(Slab *slab, const char *name, uintptr_t objsz, uintptr_t align)
uint64_t vaddr
Definition: mbuf.h:15
uint32_t len
Definition: mbuf.h:17
Definition: mbuf.h:14
uint64_t addr
Definition: multiboot.h:1
uint64_t len
Definition: multiboot.h:2
void NIC_AddNIC(NIC *nic)
void(* NICCB)(int, void *)
Definition: nic.h:8
#define PCI_MAX_BARS
Definition: pci.h:24
uint8_t irq
Definition: pci.h:64
uint8_t slot
Definition: pci.h:61
#define PCIBAR_TYPE_IO
Definition: pci.h:45
PCIBAR bars[PCI_MAX_BARS]
Definition: pci.h:66
uint16_t device
Definition: pci.h:58
uint8_t func
Definition: pci.h:62
uint16_t vendor
Definition: pci.h:57
uint32_t base
Definition: pci.h:50
uint32_t size
Definition: pci.h:51
uint8_t bus
Definition: pci.h:60
uint32_t type
Definition: pci.h:52
Definition: pci.h:56
#define VA2PA(va)
Definition: pmap.h:49
#define DMPA2VA(pa)
Definition: pmap.h:48
void Semaphore_Release(Semaphore *sema)
Definition: semaphore.c:72
void Semaphore_Acquire(Semaphore *sema)
Definition: semaphore.c:49
void Semaphore_Init(Semaphore *sema, int count, const char *name)
static uint16_t base
Definition: sercons.c:37
void Spinlock_Unlock(Spinlock *lock) __UNLOCK_EX(*lock)
Definition: spinlock.c:109
#define SPINLOCK_TYPE_NORMAL
Definition: spinlock.h:12
void Spinlock_Lock(Spinlock *lock) __LOCK_EX(*lock)
Definition: spinlock.c:75
void Spinlock_Init(Spinlock *lock, const char *name, uint64_t type)
Definition: spinlock.c:43
void * memcpy(void *dst, const void *src, size_t len)
Definition: string.c:177
Definition: irq.h:7
void * arg
Definition: irq.h:10
int irq
Definition: irq.h:8
void(* cb)(void *)
Definition: irq.h:9
Definition: nic.h:11
void * handle
Definition: nic.h:12
int(* tx)(NIC *, MBuf *, NICCB, void *)
Definition: nic.h:15
int(* rx)(NIC *, MBuf *, NICCB, void *)
Definition: nic.h:16
Definition: kmem.h:46
unsigned short uint16_t
Definition: types.h:11
unsigned int uint32_t
Definition: types.h:12
uint64_t uintptr_t
Definition: types.h:16
unsigned long uint64_t
Definition: types.h:13
unsigned char uint8_t
Definition: types.h:10