Files
lk/dev/net/e1000/e1000_hw.h
Travis Geiselbrecht caafb3e2ad [dev][net][e1000] First stab at a working e1000 driver.
-Works against qemu's e1000 and e1000e driver.
-Untested on real hardware yet.
2021-12-27 22:24:31 -08:00

129 lines
2.5 KiB
C++

//
// Copyright (c) 2021 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#pragma once
#include <stdint.h>
#include <stdio.h>
// from 8254x Family SDM Table 13-2
enum class e1000_reg {
// general
CTRL = 0x0,
STATUS = 0x8,
EECD = 0x10,
EERD = 0x14,
CTL_EXT = 0x18,
MDIC = 0x20,
FACL = 0x28,
FACH = 0x2c,
FCT = 0x30,
VET = 0x38,
FCTTV = 0x170,
TXCW = 0x178,
RXCW = 0x180,
LEDCTL = 0xe00,
// DMA
DMA = 0x1000,
// interrupt
ICR = 0xc0,
ITR = 0xc4,
IMS = 0xd0,
IMC = 0xd8,
IAM = 0xe0,
EITR0 = 0x1680, // e1000e only (i210)+
EITR1 = 0x1684,
EITR2 = 0x1688,
EITR3 = 0x168c,
EITR4 = 0x1690,
// receive
RCTL = 0x100,
FCRTL = 0x2160,
FCRTH = 0x2168,
RDBAL = 0x2800,
RDBAH = 0x2804,
RDLEN = 0x2808,
RDH = 0x2810,
RDT = 0x2818,
RDTR = 0x2820,
RADV = 0x282c,
RSRPD = 0x2c00,
// transmit
TCTL = 0x400,
TIPG = 0x410,
AIFS = 0x458,
TDBAL = 0x3800,
TDBAH = 0x3804,
TDLEN = 0x3808,
TDH = 0x3810,
TDT = 0x3818,
TIDV = 0x3820,
// tx dma
TXDMAC = 0x3000,
TXDCTL = 0x3828,
TADV = 0x382c,
TSPMT = 0x3830,
// rx dma
RXDCTL = 0x2828,
RXCSUM = 0x5000,
};
// receive descriptor
struct rdesc {
uint64_t addr;
uint16_t length;
uint16_t checksum;
uint8_t status;
uint8_t errors;
uint16_t special;
void dump() {
printf("rdsec %p: addr %#llx len %hu cksum %#hx stat %#hhx err %#hhx spec %#hx\n",
this, addr, length, checksum, status, errors, special);
}
};
static_assert(sizeof(rdesc) == 16, "");
// transmit descriptor (legacy)
struct tdesc {
uint64_t addr;
uint16_t length;
uint8_t cso;
uint8_t cmd;
uint8_t sta_rsv;
uint8_t css;
uint16_t special;
void dump() {
printf("tdsec %p: addr %#llx len %hu cso %#hhx cmd %#hhx sta_rsv %#hhx css %#hhx spec %#hx\n",
this, addr, length, cso, cmd, sta_rsv, css, special);
}
};
static_assert(sizeof(tdesc) == 16, "");
// efficient copy for rx/tx descriptors out/into uncached memory
template <typename T>
inline void copy(T *_dst, const T *_src) {
// only allow this for structs that are precisely 16 bytes long
static_assert(sizeof(T) == 16, "");
// treat as two 8 byte copies
uint64_t *dst = (uint64_t *)_dst;
const uint64_t *src = (uint64_t *)_src;
dst[0] = src[0];
dst[1] = src[1];
}