Skip to main content

godspeed/driver/
device.rs

1// SPDX-License-Identifier: Apache-2.0
2//! What the kernel knows about a driver's DEVICE that the driver cannot read for itself.
3//!
4//! # Why this exists
5//!
6//! A driver holds its own register window and nothing else, so a fact about its device that lives
7//! elsewhere - the board's MAC in the firmware's mailbox, the PCI identity of the NIC, a controller's
8//! base clock that its own capability register reports wrongly, the configuration space of a bus - has
9//! to be asked of the kernel. Drivers asked the SDK directly; these are the same answers, in the shape
10//! the promise covers (`docs/driver-library.md`, step 5).
11//!
12//! # What it is, and is not
13//!
14//! Queries, no authority: each answers what the kernel already reports, and none changes the device.
15//! What the answer MEANS for the device - which chip a PCI identity is, what divider a clock gives - is
16//! the driver's.
17
18#[cfg(not(test))]
19use godspeed_sdk::service_context::ServiceContext;
20
21/// The board's own MAC address, or `None` where the board cannot say. A NIC driver uses it rather than
22/// inventing one, since an invented address is the same on every board.
23#[cfg(not(test))]
24#[inline(always)]
25pub fn board_mac(ctx: &ServiceContext) -> Option<[u8; 6]> {
26    ctx.board_mac()
27}
28
29/// The discovered NIC's PCI identity as `vendor | device << 16`, or 0 when there is none.
30#[cfg(not(test))]
31#[inline(always)]
32pub fn nic_vendor_device(ctx: &ServiceContext) -> u32 {
33    ctx.nic_vendor_device()
34}
35
36/// The SD/EMMC controller's base clock in Hz, or 0 when the platform does not report one. A driver that
37/// gets 0 says so rather than guessing a divider.
38#[cfg(not(test))]
39#[inline(always)]
40pub fn emmc_base_clock_hz(ctx: &ServiceContext) -> u32 {
41    ctx.emmc_base_clock_hz()
42}
43
44/// Read one 32-bit register of a PCI function's configuration space. `sel` is the platform's own
45/// bus/device/function encoding, which is the caller's knowledge. `None` when the capability is missing
46/// or the machine will not admit the access; `Some(0xFFFF_FFFF)` is a successful read of an absent
47/// device, which is data.
48#[cfg(not(test))]
49#[inline(always)]
50pub fn pci_cfg_read(ctx: &ServiceContext, sel: u32, offset: u16) -> Option<u32> {
51    ctx.pci_cfg_read(sel, offset)
52}