Warning, cross-references for /kernel/drivers/net/e1000e.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "drivers/pci/pci.h"
0021 #include "drivers/net/ethernet.h"
0022 #include "arch/i386.h"
0023 #include "util/printf.h"
0024 #include "smp/smp.h"
0025 #include "smp/apic.h"
0026 #include "mem/physical.h"
0027 #include "mem/virtual.h"
0028 #include "kernel.h"
0029
0030 #define DEBUG_E1000E
0031
0032 #ifdef DEBUG_E1000E
0033
0034 #define DLOG(fmt,...) printf("e1000e: "fmt"\n",##__VA_ARGS__)
0035 #else
0036 #define DLOG(fmt,...) ;
0037 #endif
0038
0039 #define E1000E_VECTOR 0x4D
0040
0041 #define RDESC_COUNT 8
0042 #define RDESC_COUNT_MOD_MASK (RDESC_COUNT - 1)
0043 #define RBUF_SIZE 2048
0044 #define RBUF_SIZE_MASK 0
0045
0046 #define TDESC_COUNT 8
0047 #define TDESC_COUNT_MOD_MASK (RDESC_COUNT - 1)
0048 #define TBUF_SIZE 2048
0049 #define TBUF_SIZE_MASK 0
0050 #define TCTL_CT_MASK 0x100
0051 #define TCTL_COLD_MASK 0x40000
0052 #define TIPG_MASK (10 | (10 << 10) | (10 << 20))
0053
0054
0055 static struct { uint16 vendor, device; } compatible_ids[] = {
0056 { 0x8086, 0x10F5 },
0057 { 0xFFFF, 0xFFFF }
0058 };
0059
0060 static uint8 hwaddr[ETH_ADDR_LEN];
0061 static uint device_index, mem_addr, flash_addr, irq_line, irq_pin, e1000e_phys;
0062 static volatile uint32 *mmio_base, *flash_base;
0063 #define E1000E_MMIO_PAGES 0x10
0064
0065
0066
0067
0068
0069 #define REG(x) (mmio_base[x])
0070
0071 #define CTRL (REG (0x00))
0072 #define CTRL_RST (1<<26)
0073 #define STATUS (REG (0x02))
0074 #define EERD (REG (0x05))
0075 #define ICR (REG (0x30))
0076 #define ICR_RXT (0x80)
0077 #define ICR_RXO (0x40)
0078 #define ICR_TXQE (0x02)
0079 #define IMS (REG (0x34))
0080 #define IMS_RXT (0x80)
0081 #define IMS_RXO (0x40)
0082 #define IMS_TXQE (0x02)
0083 #define IMC (REG (0x36))
0084 #define RCTL (REG (0x40))
0085 #define RCTL_EN (0x02)
0086 #define RCTL_BAM (1<<15)
0087 #define RCTL_BSIZE (0x30000)
0088 #define RCTL_BSEX (1<<25)
0089 #define TCTL (REG (0x100))
0090 #define TCTL_EN (0x02)
0091 #define TCTL_PSP (0x08)
0092 #define TCTL_CT (0xFF0)
0093 #define TCTL_COLD (0x3FF000)
0094 #define TIPG (REG (0x104))
0095 #define RDBAL (REG (0xA00))
0096 #define RDBAH (REG (0xA01))
0097 #define RDLEN (REG (0xA02))
0098 #define RDH (REG (0xA04))
0099 #define RDT (REG (0xA06))
0100 #define TDBAL (REG (0xE00))
0101 #define TDBAH (REG (0xE01))
0102 #define TDLEN (REG (0xE02))
0103 #define TDH (REG (0xE04))
0104 #define TDT (REG (0xE06))
0105 #define RAL (REG (0x1500))
0106 #define RAH (REG (0x1501))
0107
0108
0109
0110
0111 struct e1000e_rdesc {
0112 uint64 address;
0113 uint16 length;
0114 uint16 checksum;
0115 uint8 status;
0116 uint8 errors;
0117 uint16 special;
0118 } PACKED;
0119 #define RDESC_STATUS_DD 0x01
0120 #define RDESC_STATUS_EOP 0x02
0121
0122
0123
0124
0125 struct e1000e_tdesc {
0126 uint64 address;
0127 uint16 length;
0128 uint8 cso;
0129 uint8 cmd;
0130 uint8 sta:4;
0131 uint8 rsv:4;
0132 uint8 css;
0133 uint16 special;
0134 } PACKED;
0135 #define TDESC_STA_DD 0x01
0136 #define TDESC_CMD_EOP 0x01
0137 #define TDESC_CMD_RS 0x08
0138
0139
0140
0141 static struct e1000e_interface {
0142 struct e1000e_rdesc rdescs[RDESC_COUNT] ALIGNED(0x10);
0143 struct e1000e_tdesc tdescs[TDESC_COUNT] ALIGNED(0x10);
0144 uint8 rbufs[RDESC_COUNT][RBUF_SIZE];
0145 uint8 tbufs[TDESC_COUNT][TBUF_SIZE];
0146 uint rx_idx;
0147 uint tx_cnt;
0148 } *e1000e;
0149
0150
0151 #define V2P(ty,p) ((ty)((((uint) (p)) - ((uint) e1000e))+e1000e_phys))
0152
0153 #define P2V(ty,p) ((ty)((((uint) (p)) - e1000e_phys)+((uint) e1000e)))
0154
0155 static ethernet_device e1000e_ethdev;
0156
0157
0158
0159 extern bool
0160 e1000e_get_hwaddr (uint8 a[ETH_ADDR_LEN])
0161 {
0162 int i;
0163 for (i=0; i<ETH_ADDR_LEN; i++)
0164 a[i] = hwaddr[i];
0165 return TRUE;
0166 }
0167
0168 extern sint
0169 e1000e_transmit (uint8* buffer, sint len)
0170 {
0171 uint32 tdt = TDT;
0172 DLOG ("TX: (%p, %d) TDH=%d TDT=%d", buffer, len, TDH, tdt);
0173
0174 if (len > TBUF_SIZE)
0175 return 0;
0176
0177 if (e1000e->tx_cnt >= TDESC_COUNT - 1)
0178 return 0;
0179
0180
0181 memcpy (e1000e->tbufs[tdt], buffer, len);
0182 e1000e->tdescs[tdt].length = len;
0183 e1000e->tdescs[tdt].cmd = TDESC_CMD_RS | TDESC_CMD_EOP;
0184
0185
0186 tdt++;
0187 if (tdt >= TDESC_COUNT)
0188 tdt = 0;
0189 TDT = tdt;
0190
0191 e1000e->tx_cnt++;
0192
0193 return len;
0194 }
0195
0196 extern void
0197 e1000e_rx_poll (void)
0198 {
0199 uint32 entry, rdt;
0200 uint8 *ptr;
0201
0202 DLOG ("RX: %d %d %d %d %d %d %d %d",
0203 e1000e->rdescs[0].status & RDESC_STATUS_DD,
0204 e1000e->rdescs[1].status & RDESC_STATUS_DD,
0205 e1000e->rdescs[2].status & RDESC_STATUS_DD,
0206 e1000e->rdescs[3].status & RDESC_STATUS_DD,
0207 e1000e->rdescs[4].status & RDESC_STATUS_DD,
0208 e1000e->rdescs[5].status & RDESC_STATUS_DD,
0209 e1000e->rdescs[6].status & RDESC_STATUS_DD,
0210 e1000e->rdescs[7].status & RDESC_STATUS_DD);
0211
0212 entry = e1000e->rx_idx & RDESC_COUNT_MOD_MASK;
0213 while (e1000e->rdescs[entry].status & RDESC_STATUS_DD) {
0214 if (e1000e->rdescs[entry].status & RDESC_STATUS_EOP) {
0215 uint16 len;
0216
0217 ptr = e1000e->rbufs[entry];
0218 len = e1000e->rdescs[entry].length;
0219 DLOG ("RX: full packet@%p len=%d", ptr, len);
0220 if (e1000e_ethdev.recv_func)
0221 e1000e_ethdev.recv_func (&e1000e_ethdev, ptr, len);
0222 else
0223 DLOG ("recv_func is null");
0224 } else {
0225
0226 DLOG ("RX: error. status=%p", e1000e->rdescs[entry].status);
0227 }
0228
0229
0230 e1000e->rdescs[entry].status = 0;
0231
0232
0233 rdt = RDT;
0234 rdt++;
0235 if (rdt >= RDESC_COUNT)
0236 rdt = 0;
0237 RDT = rdt;
0238
0239
0240 entry = (++e1000e->rx_idx) & RDESC_COUNT_MOD_MASK;
0241 }
0242 }
0243
0244 static void
0245 handle_tx (uint32 icr)
0246 {
0247 uint i;
0248 DLOG ("TX: tx_cnt=%d", e1000e->tx_cnt);
0249
0250
0251 for (i=0; i<TDESC_COUNT; i++) {
0252 if (e1000e->tdescs[i].cmd && (e1000e->tdescs[i].sta & TDESC_STA_DD)) {
0253 e1000e->tdescs[i].cmd = 0;
0254 e1000e->tdescs[i].sta = 0;
0255 e1000e->tx_cnt--;
0256 }
0257 }
0258 }
0259
0260 extern void
0261 e1000e_poll (void)
0262 {
0263 e1000e_rx_poll ();
0264 handle_tx (ICR_TXQE);
0265 }
0266
0267 static uint32
0268 e1000e_irq_handler (uint8 vec)
0269 {
0270
0271
0272 uint32 icr = ICR;
0273 DLOG ("IRQ: ICR=%p", icr);
0274
0275 if (icr & ICR_RXT)
0276 e1000e_rx_poll ();
0277 if (icr & ICR_TXQE)
0278 handle_tx (icr);
0279
0280 return 0;
0281 }
0282
0283 static void
0284 reset (void)
0285 {
0286 uint i;
0287
0288
0289
0290 CTRL |= 0x4;
0291
0292
0293 IMC = (~0);
0294
0295
0296 RCTL = 0;
0297 TCTL = TCTL_PSP;
0298
0299
0300
0301 STATUS &= ~(0x600);
0302
0303
0304
0305
0306
0307 REG(0x3C0) |= 0x20;
0308
0309
0310
0311
0312
0313
0314
0315 DLOG ("CTRL=%p", CTRL);
0316
0317
0318 RAL =
0319 (hwaddr[0] << 0x00) |
0320 (hwaddr[1] << 0x08) |
0321 (hwaddr[2] << 0x10) |
0322 (hwaddr[3] << 0x18);
0323 RAH = 0x80000000L |
0324 (hwaddr[4] << 0x00) |
0325 (hwaddr[5] << 0x08);
0326
0327 DLOG ("RAL=%p RAH=%p", RAL, RAH);
0328
0329
0330 RCTL &= ~RCTL_BSIZE;
0331 RCTL |= RBUF_SIZE_MASK;
0332 RCTL &= ~RCTL_BSEX;
0333
0334
0335 for (i=0; i<RDESC_COUNT; i++) {
0336 e1000e->rdescs[i].address = V2P (uint64, e1000e->rbufs[i]);
0337 e1000e->rdescs[i].status = 0;
0338 }
0339
0340
0341 RDBAL = V2P (uint32, e1000e->rdescs);
0342 RDBAH = 0;
0343 RDLEN = RDESC_COUNT * sizeof (struct e1000e_rdesc);
0344
0345
0346 RDH = 0;
0347 RDT = RDESC_COUNT - 1;
0348
0349 e1000e->rx_idx = 0;
0350
0351 DLOG ("RDBAL=%p RDLEN=%p RDH=%d RDT=%d",
0352 V2P (uint32, e1000e->rdescs), RDESC_COUNT * sizeof (struct e1000e_rdesc),
0353 RDH, RDT);
0354
0355
0356 for (i=0; i<TDESC_COUNT; i++) {
0357 e1000e->tdescs[i].address = V2P (uint64, e1000e->tbufs[i]);
0358 e1000e->tdescs[i].sta = 0;
0359 }
0360
0361
0362 TDBAL = V2P (uint32, e1000e->tdescs);
0363 TDBAH = 0;
0364 TDLEN = TDESC_COUNT * sizeof (struct e1000e_tdesc);
0365
0366
0367 TDH = 0;
0368 TDT = 0;
0369
0370 e1000e->tx_cnt = 0;
0371
0372 DLOG ("TDBAL=%p TDLEN=%p TDH=%d TDT=%d",
0373 V2P (uint32, e1000e->tdescs), TDESC_COUNT * sizeof (struct e1000e_tdesc),
0374 TDH, TDT);
0375
0376
0377 IMS |= IMS_RXT;
0378
0379
0380 IMS |= IMS_TXQE;
0381
0382
0383 RCTL |= (RCTL_EN | RCTL_BAM);
0384
0385
0386 TCTL |= (TCTL_EN | TCTL_PSP | TCTL_COLD_MASK);
0387 TIPG = TIPG_MASK;
0388
0389
0390
0391
0392 CTRL &= (~0x4);
0393
0394
0395 REG(0x3C0) &= ~(0x20);
0396
0397 DLOG ("CTRL=%p STA=%p RCTL=%p TCTL=%p EXT=%p", CTRL, STATUS, RCTL, TCTL, REG(0x3C0));
0398
0399
0400 }
0401
0402 extern bool
0403 e1000e_init (void)
0404 {
0405 uint i, io_base, mask, frame_count;
0406
0407 if (mp_ISA_PC) {
0408 DLOG ("Requires PCI support");
0409 goto abort;
0410 }
0411
0412 for (i=0; compatible_ids[i].vendor != 0xFFFF; i++)
0413 if (pci_find_device (compatible_ids[i].vendor, compatible_ids[i].device,
0414 0xFF, 0xFF, 0, &device_index))
0415 break;
0416 else
0417 device_index = ~0;
0418
0419 if (device_index == (uint)(~0)) {
0420 DLOG ("Unable to detect compatible device.");
0421 goto abort;
0422 }
0423
0424 DLOG ("Found device_index=%d", device_index);
0425
0426 if (!pci_decode_bar (device_index, 0, &mem_addr, &io_base, &mask)) {
0427 DLOG ("Invalid PCI configuration or BAR0 not found");
0428 goto abort;
0429 }
0430
0431 if (mem_addr == 0) {
0432 DLOG ("Unable to detect memory mapped IO region");
0433 goto abort;
0434 }
0435
0436
0437 mmio_base = map_contiguous_virtual_pages (mem_addr | 3, E1000E_MMIO_PAGES);
0438
0439 if (mmio_base == NULL) {
0440 DLOG ("Unable to map page to phys=%p", mem_addr);
0441 goto abort;
0442 }
0443
0444 DLOG ("Using memory mapped IO at phys=%p virt=%p", mem_addr, mmio_base);
0445
0446
0447
0448 if (!pci_decode_bar (device_index, 1, &flash_addr, &io_base, &mask)) {
0449 DLOG ("Invalid PCI configuration or BAR1 not found");
0450 goto abort;
0451 }
0452
0453 if (flash_addr == 0) {
0454 DLOG ("Unable to detect memory mapped flash region");
0455 goto no_flash;
0456 }
0457
0458
0459 flash_base = map_contiguous_virtual_pages (flash_addr | 3, 1);
0460
0461 if (flash_base == NULL) {
0462 DLOG ("Unable to map page to phys=%p", flash_addr);
0463 goto abort;
0464 }
0465
0466 DLOG ("Using memory mapped FLASH at phys=%p virt=%p", flash_addr, flash_base);
0467 DLOG ("flash=%p %p %p %p",
0468 flash_base[0], flash_base[1], flash_base[2], flash_base[3]);
0469 no_flash:
0470
0471
0472
0473
0474
0475 frame_count = sizeof (struct e1000e_interface) >> 12;
0476 if (sizeof (struct e1000e_interface) & 0xFFF)
0477 frame_count++;
0478
0479
0480 e1000e_phys = alloc_phys_frames (frame_count);
0481
0482 if (e1000e_phys == -1) {
0483 DLOG ("Unable to allocate physical memory");
0484 goto abort_mmap;
0485 }
0486
0487
0488 e1000e = (struct e1000e_interface *)
0489 map_contiguous_virtual_pages (e1000e_phys | 3, frame_count);
0490
0491 if (e1000e == NULL) {
0492 DLOG ("Unable to allocate virtual memory");
0493 goto abort_phys;
0494 }
0495
0496
0497 memset (e1000e, 0, sizeof (struct e1000e_interface));
0498
0499 DLOG ("DMA region at virt=%p phys=%p count=%d", e1000e, e1000e_phys, frame_count);
0500
0501 if (!pci_get_interrupt (device_index, &irq_line, &irq_pin)) {
0502 DLOG ("Unable to get IRQ");
0503 goto abort_virt;
0504 }
0505
0506 DLOG ("Using IRQ line=%.02X pin=%X", irq_line, irq_pin);
0507
0508
0509 IOAPIC_map_GSI (IRQ_to_GSI (mp_ISA_bus_id, irq_line),
0510 E1000E_VECTOR, 0xFF00000000000800LL);
0511 set_vector_handler (E1000E_VECTOR, e1000e_irq_handler);
0512
0513 #if 0
0514
0515 EERD = 0x0001;
0516 while (!(EERD & 0x10)) asm volatile ("pause");
0517 hwaddr[0] = (EERD >> 16) & 0xFF;
0518 hwaddr[1] = (EERD >> 24) & 0xFF;
0519 EERD = 0x0101;
0520 while (!(EERD & 0x10)) asm volatile ("pause");
0521 hwaddr[2] = (EERD >> 16) & 0xFF;
0522 hwaddr[3] = (EERD >> 24) & 0xFF;
0523 EERD = 0x0201;
0524 while (!(EERD & 0x10)) asm volatile ("pause");
0525 hwaddr[4] = (EERD >> 16) & 0xFF;
0526 hwaddr[5] = (EERD >> 24) & 0xFF;
0527 #endif
0528 for (i=0;i<6;i++) hwaddr[i] = i;
0529
0530 DLOG ("hwaddr=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x",
0531 hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
0532
0533 reset ();
0534
0535
0536 e1000e_ethdev.recv_func = NULL;
0537 e1000e_ethdev.send_func = e1000e_transmit;
0538 e1000e_ethdev.get_hwaddr_func = e1000e_get_hwaddr;
0539 e1000e_ethdev.poll_func = e1000e_poll;
0540
0541 if (!net_register_device (&e1000e_ethdev)) {
0542 DLOG ("registration failed");
0543 goto abort_virt;
0544 }
0545
0546 return TRUE;
0547
0548 abort_virt:
0549 unmap_virtual_pages (e1000e, frame_count);
0550 abort_phys:
0551 free_phys_frames (e1000e_phys, frame_count);
0552 abort_mmap:
0553 unmap_virtual_pages ((void *)mmio_base, E1000E_MMIO_PAGES);
0554 abort:
0555 return FALSE;
0556 }
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567