> ## Documentation Index
> Fetch the complete documentation index at: https://kernel.mvhcloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MVH Kernel PCI Config and CMOS RTC Driver Reference

> MVH Kernel's PCI driver scans config space and lists devices via lspci. The CMOS RTC driver reads the hardware clock, accessible through the date command.

MVH Kernel includes two hardware interface drivers that give you visibility into attached devices and the current time: the PCI configuration space driver (`pci-config`) and the CMOS real-time clock driver (`cmos-rtc`). The PCI driver scans the configuration space to enumerate every device on the bus and exposes the results via the `lspci` shell command. The RTC driver reads the hardware clock from CMOS and makes it available through the `date` command. Both drivers are active at boot and registered with the device manager.

***

## PCI Configuration Space Driver

The `pci-config` driver enumerates PCI devices by probing configuration space through the standard indirect I/O mechanism — writing a configuration address to port `0xCF8` and reading data from port `0xCFC`. It scans every bus, slot, and function combination and returns a list of `pci_device_t` records for all devices that respond with a valid vendor ID.

### Shell Command

```
mvh> lspci
```

The `lspci` command prints a formatted table of every discovered PCI device, showing bus/slot/function address, vendor ID, device ID, and the human-readable class name.

### API Reference

```c theme={null}
// Scan the full PCI configuration space.
// Writes up to 'capacity' pci_device_t records into 'devices'.
// Returns the total number of devices found.
uint32_t pci_scan(pci_device_t *devices, uint32_t capacity);

// Read a 32-bit value from PCI configuration space.
uint32_t pci_config_read32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);

// Write a 32-bit value to PCI configuration space.
void pci_config_write32(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset,
                        uint32_t value);

// Return a human-readable class name for a PCI class code byte.
const char *pci_class_name(uint8_t class_code);
```

Call `pci_scan()` with a pre-allocated array of `pci_device_t` and its capacity. The function returns the number of devices written. If the bus contains more devices than `capacity`, only the first `capacity` entries are written.

### `pci_device_t` Struct

```c theme={null}
typedef struct {
    uint8_t  bus;        // PCI bus number (0–255)
    uint8_t  slot;       // PCI slot / device number (0–31)
    uint8_t  function;   // PCI function number (0–7)
    uint8_t  class_code; // Base class code (e.g., 0x01 = mass storage)
    uint8_t  subclass;   // Subclass code
    uint16_t vendor;     // Vendor ID (e.g., 0x8086 = Intel, 0x1022 = AMD)
    uint16_t device;     // Device ID assigned by the vendor
} pci_device_t;
```

Use `pci_class_name(device.class_code)` to convert the class code byte to a human-readable string such as `"Display Controller"` or `"Mass Storage Controller"`.

### Example: Scanning PCI Devices

```c theme={null}
#include <mvh/pci.h>

pci_device_t devices[64];
uint32_t count = pci_scan(devices, 64);

for (uint32_t i = 0; i < count; i++) {
    // devices[i].vendor, devices[i].device, devices[i].class_code ...
}
```

### Driver ID

The device manager registers this driver under the ID `pci-config`. Run `devices` in the shell to confirm it is online.

***

## CMOS Real-Time Clock Driver

The `cmos-rtc` driver reads the current date and time from the CMOS RTC chip by issuing indexed reads to I/O ports `0x70` (index) and `0x71` (data). It waits for the RTC update cycle to complete before reading to avoid torn values, then converts BCD-encoded registers to binary and stores the result in an `rtc_time_t`.

### Shell Command

```
mvh> date
```

The `date` command calls `rtc_read()` and prints the current date and time in a human-readable format.

### API Reference

```c theme={null}
// Read the current date and time from the CMOS RTC.
// Populates all fields of the rtc_time_t pointed to by 'time'.
void rtc_read(rtc_time_t *time);
```

### `rtc_time_t` Struct

```c theme={null}
typedef struct {
    uint16_t year;    // Full four-digit year (e.g., 2025)
    uint8_t  month;   // Month: 1–12
    uint8_t  day;     // Day of the month: 1–31
    uint8_t  hour;    // Hour: 0–23 (24-hour format)
    uint8_t  minute;  // Minute: 0–59
    uint8_t  second;  // Second: 0–59
} rtc_time_t;
```

### Example: Reading the Current Time

```c theme={null}
#include <mvh/rtc.h>

rtc_time_t now;
rtc_read(&now);
// now.year, now.month, now.day, now.hour, now.minute, now.second
```

<Note>
  The CMOS RTC reflects the hardware clock set in your system firmware (or QEMU's emulated clock). It does not perform timezone conversion — the value returned is whatever the RTC hardware stores, typically UTC on most systems.
</Note>

### Driver ID

The device manager registers this driver under the ID `cmos-rtc`. Run `devices` in the shell to confirm it is online.
