An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
165 lines
6.6 KiB
C
165 lines
6.6 KiB
C
#pragma once
|
|
|
|
// Intel 8254x gigabit Ethernet — the register and descriptor layout.
|
|
//
|
|
// From Intel's public "PCI/PCI-X Family of Gigabit Ethernet Controllers
|
|
// Software Developer's Manual" (317453). A public document with no licence on
|
|
// what you write from it, which is why this is written rather than ported: see
|
|
// docs/licensing.md and docs/roadmap.md §1.
|
|
//
|
|
// QEMU's `-device e1000` is an 82540EM and implements enough of the manual to
|
|
// be worth targeting; it is also what the default `-net nic` gives you.
|
|
|
|
#define E1000_VENDOR 0x8086
|
|
|
|
// The 8254x family: PCI/PCI-X gigabit controllers that share the register map,
|
|
// descriptor format and EEPROM interface this driver implements.
|
|
//
|
|
// The device IDs are transcribed from FreeBSD's `sys/dev/e1000/e1000_hw.h`
|
|
// (Copyright (c) 2001-2020, Intel Corporation, BSD 3-clause -- verified to
|
|
// carry no advertising clause; see docs/licensing.md and NOTICE). They are
|
|
// data, not logic: the driver below is still written from Intel's manual
|
|
// 317453, and nothing of FreeBSD's implementation is used.
|
|
//
|
|
// This matters more than it looks. The driver bound exactly one device -- the
|
|
// 82540EM QEMU emulates -- which is fine for a virtual machine and useless on
|
|
// the sort of second-hand hardware a system like this actually gets run on.
|
|
// These are the cards in every desktop and server of that generation.
|
|
//
|
|
// Deliberately *not* included: the PCIe 8257x parts (82571-82574) and anything
|
|
// newer. They present a similar register map but differ in NVM access and
|
|
// initialisation, and claiming a device this driver has not been shown to
|
|
// initialise is worse than not claiming it -- the card binds, reports a MAC of
|
|
// nonsense, and nothing works for reasons that look nothing like the cause.
|
|
#define E1000_DEV_82540EM 0x100E
|
|
#define E1000_DEV_82540EM_LOM 0x1015
|
|
#define E1000_DEV_82540EP_LOM 0x1016
|
|
#define E1000_DEV_82540EP 0x1017
|
|
#define E1000_DEV_82540EP_LP 0x101E
|
|
#define E1000_DEV_82541EI 0x1013
|
|
#define E1000_DEV_82541EI_MOBILE 0x1018
|
|
#define E1000_DEV_82541ER_LOM 0x1014
|
|
#define E1000_DEV_82541ER 0x1078
|
|
#define E1000_DEV_82541GI 0x1076
|
|
#define E1000_DEV_82541GI_MOBILE 0x1077
|
|
#define E1000_DEV_82541GI_LF 0x107C
|
|
#define E1000_DEV_82544EI_FIBER 0x1009
|
|
#define E1000_DEV_82544GC_COPPER 0x100C
|
|
#define E1000_DEV_82544GC_LOM 0x100D
|
|
#define E1000_DEV_82545EM_COPPER 0x100F
|
|
#define E1000_DEV_82545EM_FIBER 0x1011
|
|
#define E1000_DEV_82545GM_COPPER 0x1026
|
|
#define E1000_DEV_82545GM_FIBER 0x1027
|
|
#define E1000_DEV_82545GM_SERDES 0x1028
|
|
#define E1000_DEV_82546EB_COPPER 0x1010
|
|
#define E1000_DEV_82546EB_FIBER 0x1012
|
|
#define E1000_DEV_82546EB_QUAD 0x101D
|
|
#define E1000_DEV_82546GB_COPPER 0x1079
|
|
#define E1000_DEV_82546GB_FIBER 0x107A
|
|
#define E1000_DEV_82546GB_SERDES 0x107B
|
|
#define E1000_DEV_82547EI 0x1019
|
|
|
|
// --- registers, byte offsets into BAR 0 ------------------------------------
|
|
|
|
#define E1000_CTRL 0x0000 // device control
|
|
#define E1000_STATUS 0x0008 // device status
|
|
#define E1000_EERD 0x0014 // EEPROM read
|
|
#define E1000_ICR 0x00C0 // interrupt cause read
|
|
#define E1000_IMS 0x00D0 // interrupt mask set
|
|
#define E1000_IMC 0x00D8 // interrupt mask clear
|
|
|
|
#define E1000_RCTL 0x0100 // receive control
|
|
#define E1000_TCTL 0x0400 // transmit control
|
|
#define E1000_TIPG 0x0410 // transmit inter-packet gap
|
|
|
|
#define E1000_RDBAL 0x2800 // receive descriptor base, low
|
|
#define E1000_RDBAH 0x2804 // receive descriptor base, high
|
|
#define E1000_RDLEN 0x2808 // receive descriptor length, in bytes
|
|
#define E1000_RDH 0x2810 // receive descriptor head
|
|
#define E1000_RDT 0x2818 // receive descriptor tail
|
|
|
|
#define E1000_TDBAL 0x3800
|
|
#define E1000_TDBAH 0x3804
|
|
#define E1000_TDLEN 0x3808
|
|
#define E1000_TDH 0x3810
|
|
#define E1000_TDT 0x3818
|
|
|
|
#define E1000_MTA 0x5200 // multicast table array, 128 entries
|
|
#define E1000_RAL 0x5400 // receive address low (the MAC filter)
|
|
#define E1000_RAH 0x5404 // receive address high
|
|
|
|
// CTRL
|
|
#define E1000_CTRL_RST (1 << 26)
|
|
#define E1000_CTRL_ASDE (1 << 5) // auto-speed detection
|
|
#define E1000_CTRL_SLU (1 << 6) // set link up
|
|
|
|
// STATUS
|
|
#define E1000_STATUS_LU (1 << 1) // link up
|
|
|
|
// EERD
|
|
#define E1000_EERD_START (1 << 0)
|
|
#define E1000_EERD_DONE (1 << 4)
|
|
#define E1000_EERD_ADDR_SHIFT 8
|
|
#define E1000_EERD_DATA_SHIFT 16
|
|
|
|
// RCTL
|
|
#define E1000_RCTL_EN (1 << 1) // receiver enable
|
|
#define E1000_RCTL_SBP (1 << 2) // store bad packets
|
|
#define E1000_RCTL_UPE (1 << 3) // unicast promiscuous
|
|
#define E1000_RCTL_MPE (1 << 4) // multicast promiscuous
|
|
#define E1000_RCTL_LBM_NONE (0 << 6)
|
|
#define E1000_RCTL_BAM (1 << 15) // accept broadcast
|
|
#define E1000_RCTL_SZ_2048 (0 << 16) // buffer size, with BSEX clear
|
|
#define E1000_RCTL_SECRC (1 << 26) // strip the Ethernet CRC
|
|
|
|
// TCTL
|
|
#define E1000_TCTL_EN (1 << 1)
|
|
#define E1000_TCTL_PSP (1 << 3) // pad short packets
|
|
#define E1000_TCTL_CT_SHIFT 4 // collision threshold
|
|
#define E1000_TCTL_COLD_SHIFT 12 // collision distance
|
|
|
|
// Transmit descriptor command bits
|
|
#define E1000_TXD_CMD_EOP (1 << 0) // end of packet
|
|
#define E1000_TXD_CMD_IFCS (1 << 1) // insert FCS/CRC
|
|
#define E1000_TXD_CMD_RS (1 << 3) // report status
|
|
#define E1000_TXD_STAT_DD (1 << 0) // descriptor done
|
|
|
|
// Receive descriptor status bits
|
|
#define E1000_RXD_STAT_DD (1 << 0)
|
|
#define E1000_RXD_STAT_EOP (1 << 1)
|
|
|
|
// Interrupt causes worth unmasking.
|
|
#define E1000_ICR_TXDW (1 << 0) // transmit descriptor written back
|
|
#define E1000_ICR_LSC (1 << 2) // link status change
|
|
#define E1000_ICR_RXDMT0 (1 << 4) // receive descriptor minimum threshold
|
|
#define E1000_ICR_RXT0 (1 << 7) // receiver timer
|
|
|
|
// --- descriptors -----------------------------------------------------------
|
|
//
|
|
// Both are 16 bytes and the hardware reads them by physical address, so the
|
|
// rings must be physically contiguous and 16-byte aligned.
|
|
|
|
struct e1000_tx_desc {
|
|
uint64 addr;
|
|
uint16 length;
|
|
uint8 cso; // checksum offset
|
|
uint8 cmd;
|
|
uint8 status;
|
|
uint8 css; // checksum start
|
|
uint16 special;
|
|
} __attribute__((packed));
|
|
|
|
struct e1000_rx_desc {
|
|
uint64 addr;
|
|
uint16 length;
|
|
uint16 checksum;
|
|
uint8 status;
|
|
uint8 errors;
|
|
uint16 special;
|
|
} __attribute__((packed));
|
|
|
|
// Ring sizes. The manual requires the descriptor ring length to be a multiple
|
|
// of 128 bytes, i.e. a multiple of 8 descriptors.
|
|
#define E1000_NTX 16
|
|
#define E1000_NRX 16
|
|
#define E1000_BUFSZ 2048
|