Viewing: blockdev.h
📄 blockdev.h (Read Only) ⬅ To go back
// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2018, Tulio A M Mendes <[email protected]>
 * All rights reserved.
 * See LICENSE for details.
 *
 * Source: https://github.com/tadryanom/AdrOS
 */

#ifndef BLOCKDEV_H
#define BLOCKDEV_H

#include <stdint.h>
#include <stddef.h>
#include "errno.h"
#include "spinlock.h"

/* Generic block device interface — abstracts ATA/virtio-blk/etc.
 * Filesystems (fat, ext2) use this instead of calling ATA directly,
 * so they work with any registered block device. */

#define BLOCKDEV_MAX 8

struct block_device;

struct block_device_ops {
    int (*read)(struct block_device* dev, uint32_t lba, void* buf);
    int (*write)(struct block_device* dev, uint32_t lba, const void* buf);
};

typedef struct block_device {
    char name[16];              /* e.g. "hda", "hdb" */
    uint32_t sector_size;       /* typically 512 */
    uint32_t sector_count;      /* total sectors (0 if unknown) */
    int drive_id;               /* opaque identifier passed to ops */
    int refcount;               /* number of filesystems using this device */
    const struct block_device_ops* ops;
} block_device_t;

/* Register a block device. Returns 0 on success, -ENOSPC if table full. */
int blockdev_register(const block_device_t* dev);

/* Look up a block device by name (e.g. "hda"). Returns pointer or NULL. */
block_device_t* blockdev_find(const char* name);

/* Look up a block device by drive_id. Returns pointer or NULL. */
block_device_t* blockdev_by_id(int drive_id);

/* Increment block device refcount (called when filesystem mounts). */
void blockdev_claim(block_device_t* dev);

/* Decrement block device refcount (called when filesystem unmounts). */
void blockdev_release(block_device_t* dev);

/* Convenience: read one sector from a block device. */
static inline int blockdev_read(block_device_t* dev, uint32_t lba, void* buf) {
    if (!dev || !dev->ops || !dev->ops->read) return -ENODEV;
    return dev->ops->read(dev, lba, buf);
}

/* Convenience: write one sector to a block device. */
static inline int blockdev_write(block_device_t* dev, uint32_t lba, const void* buf) {
    if (!dev || !dev->ops || !dev->ops->write) return -ENODEV;
    return dev->ops->write(dev, lba, buf);
}

/* Register all detected ATA drives as block devices. */
void blockdev_register_ata(void);

/* Initialize the blockdev lock (must be called before any blockdev operations). */
void blockdev_init_lock(void);

#endif