Write boot milestones directly to VGA text buffer (0xB8000) at each init stage so the user can see exactly where the kernel stops on platforms where the VGA driver may not initialize. Milestones: Magic OK, GDT, IDT, PIC, PMM, PAGING, HEAP, CPIO, VFS, INITRD, TSS. Each appears as white-on-blue text. If the multiboot2 magic check fails, display the received magic value in red-on-white on screen and halt (instead of silently returning). This helps diagnose if GRUB matched the multiboot1 header instead.
136 lines
4.5 KiB
C
136 lines
4.5 KiB
C
/**
|
|
* @file devicefs.h
|
|
* @brief Device filesystem (devicefs) subsystem.
|
|
*
|
|
* Provides a VFS interface at /dev for exposing block and character devices.
|
|
* Drivers register devices through the devicefs API, and each device is
|
|
* assigned a sequential number by device class (e.g., hdd1, hdd2, cd1).
|
|
*
|
|
* The devicefs owns device naming — drivers specify a class name (e.g., "hdd")
|
|
* and the devicefs appends a sequential number.
|
|
*/
|
|
|
|
#ifndef DEVICEFS_H
|
|
#define DEVICEFS_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
/** Maximum number of registered devices. */
|
|
#define DEVICEFS_MAX_DEVICES 32
|
|
|
|
/** Maximum length of a device class name (e.g., "hdd", "cd", "floppy"). */
|
|
#define DEVICEFS_MAX_CLASS_NAME 16
|
|
|
|
/** Maximum length of a full device name (class + number, e.g., "hdd1"). */
|
|
#define DEVICEFS_MAX_DEV_NAME 32
|
|
|
|
/** Device types. */
|
|
#define DEVICEFS_BLOCK 0x01 /**< Block device (e.g., hard drives, CDs). */
|
|
#define DEVICEFS_CHAR 0x02 /**< Character device (e.g., serial ports). */
|
|
|
|
/**
|
|
* Block device operations.
|
|
*
|
|
* Block devices transfer data in fixed-size sectors.
|
|
*/
|
|
typedef struct devicefs_block_ops {
|
|
/** Read `count` sectors starting at `lba` into `buf`. Returns 0 on success. */
|
|
int (*read_sectors)(void *dev_data, uint32_t lba, uint32_t count, void *buf);
|
|
|
|
/** Write `count` sectors from `buf` starting at `lba`. Returns 0 on success. */
|
|
int (*write_sectors)(void *dev_data, uint32_t lba, uint32_t count, const void *buf);
|
|
|
|
/** Get the sector size in bytes. */
|
|
uint32_t (*sector_size)(void *dev_data);
|
|
|
|
/** Get total number of sectors. */
|
|
uint32_t (*sector_count)(void *dev_data);
|
|
} devicefs_block_ops_t;
|
|
|
|
/**
|
|
* Character device operations.
|
|
*
|
|
* Character devices transfer data as byte streams.
|
|
*/
|
|
typedef struct devicefs_char_ops {
|
|
/** Read up to `size` bytes into `buf`. Returns bytes read, or -1. */
|
|
int32_t (*read)(void *dev_data, uint32_t size, void *buf);
|
|
|
|
/** Write `size` bytes from `buf`. Returns bytes written, or -1. */
|
|
int32_t (*write)(void *dev_data, uint32_t size, const void *buf);
|
|
} devicefs_char_ops_t;
|
|
|
|
/**
|
|
* Registered device entry.
|
|
*/
|
|
typedef struct devicefs_device {
|
|
char name[DEVICEFS_MAX_DEV_NAME]; /**< Full device name (e.g., "hdd1"). */
|
|
char class_name[DEVICEFS_MAX_CLASS_NAME]; /**< Device class (e.g., "hdd"). */
|
|
uint8_t type; /**< DEVICEFS_BLOCK or DEVICEFS_CHAR. */
|
|
uint32_t number; /**< Assigned device number within class. */
|
|
int active; /**< 1 if registered, 0 if free. */
|
|
|
|
/** Device-specific operations (union of block/char). */
|
|
union {
|
|
devicefs_block_ops_t *block_ops;
|
|
devicefs_char_ops_t *char_ops;
|
|
};
|
|
|
|
/** Opaque driver-specific data passed to operation callbacks. */
|
|
void *dev_data;
|
|
} devicefs_device_t;
|
|
|
|
/**
|
|
* Initialize the devicefs subsystem and mount at /dev.
|
|
*
|
|
* @return 0 on success, -1 on failure.
|
|
*/
|
|
int init_devicefs(void);
|
|
|
|
/**
|
|
* Register a new block device.
|
|
*
|
|
* The devicefs assigns a sequential number within the class. For example,
|
|
* registering class "hdd" twice yields "hdd1" and "hdd2".
|
|
*
|
|
* @param class_name Device class name (e.g., "hdd", "cd").
|
|
* @param ops Block device operations.
|
|
* @param dev_data Opaque data passed to operation callbacks.
|
|
* @return Pointer to the device entry, or NULL on failure.
|
|
*/
|
|
devicefs_device_t *devicefs_register_block(const char *class_name,
|
|
devicefs_block_ops_t *ops,
|
|
void *dev_data);
|
|
|
|
/**
|
|
* Register a new character device.
|
|
*
|
|
* @param class_name Device class name (e.g., "tty", "serial").
|
|
* @param ops Character device operations.
|
|
* @param dev_data Opaque data passed to operation callbacks.
|
|
* @return Pointer to the device entry, or NULL on failure.
|
|
*/
|
|
devicefs_device_t *devicefs_register_char(const char *class_name,
|
|
devicefs_char_ops_t *ops,
|
|
void *dev_data);
|
|
|
|
/**
|
|
* Find a device by its full name (e.g., "hdd1").
|
|
*
|
|
* @param name Device name.
|
|
* @return Pointer to the device entry, or NULL if not found.
|
|
*/
|
|
devicefs_device_t *devicefs_find(const char *name);
|
|
|
|
/**
|
|
* Get the next device number for a given class.
|
|
* This is called internally but may be useful for drivers.
|
|
*
|
|
* @param class_name Device class name.
|
|
* @return Next sequential number (starting from 1).
|
|
*/
|
|
uint32_t devicefs_next_number(const char *class_name);
|
|
|
|
#endif /* DEVICEFS_H */
|