SchOS/kernel/drivers/net/e1000/e1000.h
Nexoniarz 57aff40228 docs: four directories, and a rule for when a thing leaves the roadmap
docs/ was ten files where a plan, a description, a guide and a bug report all
sat next to each other. It is now architecture/ (what SchOS is), plan/ (what it
will be), guides/ (how to work on it) and history/ (why it is like this), with
an index that states the one rule holding it together: when something is
finished it moves from plan/ to architecture/ and is rewritten as a description
of the thing rather than a record of building it.

A ticked checkbox says the work happened. It does not say what the work
*produced*, and six months later the checkbox is all that is left. The network
stack proved the point: finished, verified end to end, and for a month the only
description of it anywhere was a checkbox four levels of indentation deep.

So roadmap.md went from 534 lines to 181 -- nothing deleted, the done work
graduated. Seven subsystems that were finished and undescribed now have
descriptions: boot, kernel, syscalls, filesystem, networking, graphics, usb,
init. Every one ends with "What it does not do", which is the section that pays;
a document listing only strengths is marketing, and the reader who needs it most
is the one about to trip over a limitation nobody wrote down.

schfs.md still opened with "phases 1 through 3 1/2 are done, phase 4 is next"
long after all five had landed. It is a description now, with the phase record
and the hard-won bugs moved to history/.

Three corrections found on the way, all load-bearing:

  * projects/schcom/README.md claimed SCM_RIGHTS was done. There is no
    sendmsg/recvmsg in the kernel at all, and an entire GUI plan rested on it.
  * The root README said "No TCP/IP" months after the stack landed.
  * history/kernel.md sec.7 was marked "in progress" on a problem that process
    groups solved.

Also adds plan/1.0.md, which draws a finish line so the open list stops being
infinite, and marks schwm/ and schde/ superseded: in Wayland the compositor is
the window manager, so that split dissolves rather than being abandoned.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VQ7Qx8E1q1M1bbCq8QLHS2
2026-09-12 17:13:35 +02:00

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/guides/adding-a-driver.md.
//
// 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