feat: map pci, clock, cake allocator and block devices into filesystem.
chore: fixes and clean up
struct pci_device* ahci_dev = pci_get_device_by_class(AHCI_HBA_CLASS);
assert_msg(ahci_dev, "AHCI: Not found.");
- uintptr_t bar6, size;
- size = pci_bar_sizing(ahci_dev, &bar6, 6);
- assert_msg(bar6 && PCI_BAR_MMIO(bar6), "AHCI: BAR#6 is not MMIO.");
+ struct pci_base_addr* bar6 = &ahci_dev->bar[5];
+ assert_msg(bar6->type & BAR_TYPE_MMIO, "AHCI: BAR#6 is not MMIO.");
pci_reg_t cmd = pci_read_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD);
memset(&hba, 0, sizeof(hba));
- hba.base = (hba_reg_t*)ioremap(PCI_BAR_ADDR_MM(bar6), size);
+ hba.base = (hba_reg_t*)ioremap(bar6->start, bar6->size);
#ifdef DO_HBA_FULL_RESET
// 重置HBA
pci_reg_t intr = pci_read_cspace(base, 0x3c);
pci_reg_t class = pci_read_cspace(base, 0x8);
- struct pci_device* device = valloc(sizeof(struct pci_device));
+ struct pci_device* device = vzalloc(sizeof(struct pci_device));
*device = (struct pci_device){ .cspace_base = base,
.class_info = class,
.device_info = reg1,
.intr_info = intr };
pci_probe_msi_info(device);
+ pci_probe_bar_info(device);
llist_append(&pci_devices, &device->dev_chain);
}
}
}
+void
+pci_probe_bar_info(struct pci_device* device)
+{
+ uint32_t bar;
+ struct pci_base_addr* ba;
+ for (size_t i = 0; i < 6; i++) {
+ ba = &device->bar[i];
+ ba->size = pci_bar_sizing(device, &bar, i + 1);
+ if (PCI_BAR_MMIO(bar)) {
+ ba->start = PCI_BAR_ADDR_MM(bar);
+ ba->type |= PCI_BAR_CACHEABLE(bar) ? BAR_TYPE_CACHABLE : 0;
+ ba->type |= BAR_TYPE_MMIO;
+ } else {
+ ba->start = PCI_BAR_ADDR_IO(bar);
+ }
+ }
+}
+
void
pci_probe_msi_info(struct pci_device* device)
{
}
}
-#define PCI_PRINT_BAR_LISTING
+void
+__pci_read_cspace(struct twimap* map)
+{
+ struct pci_device* pcidev = (struct pci_device*)(map->data);
-int
-__pci_read_cspace(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+ for (size_t i = 0; i < 256; i += sizeof(pci_reg_t)) {
+ *(pci_reg_t*)(map->buffer + i) =
+ pci_read_cspace(pcidev->cspace_base, i);
+ }
+
+ map->size_acc = 256;
+}
+
+void
+__pci_read_revid(struct twimap* map)
+{
+ int class = twimap_data(map, struct pci_device*)->class_info;
+ twimap_printf(map, "0x%x", PCI_DEV_REV(class));
+}
+
+void
+__pci_read_class(struct twimap* map)
{
- if (len < 256) {
- return ERANGE;
+ int class = twimap_data(map, struct pci_device*)->class_info;
+ twimap_printf(map, "0x%x", PCI_DEV_CLASS(class));
+}
+
+void
+__pci_bar_read(struct twimap* map)
+{
+ struct pci_device* pcidev = twimap_data(map, struct pci_device*);
+ int bar_index = twimap_index(map, int);
+
+ struct pci_base_addr* bar = &pcidev->bar[bar_index];
+
+ if (!bar->start && !bar->size) {
+ twimap_printf(map, "[%d] not present \n", bar_index);
+ return;
}
- struct twifs_node* node = (struct twifs_node*)(inode->data);
- struct pci_device* pcidev = (struct pci_device*)(node->data);
+ twimap_printf(
+ map, "[%d] base=%p, size=%p, ", bar_index, bar->start, bar->size);
- for (size_t i = 0; i < 256; i += sizeof(pci_reg_t)) {
- *(pci_reg_t*)(buffer + i) = pci_read_cspace(pcidev->cspace_base, i);
+ if ((bar->type & BAR_TYPE_MMIO)) {
+ twimap_printf(map, "mmio");
+ if ((bar->type & BAR_TYPE_CACHABLE)) {
+ twimap_printf(map, ", cachable");
+ }
+ } else {
+ twimap_printf(map, "io");
}
- return 256;
+ twimap_printf(map, "\n");
+}
+
+int
+__pci_bar_gonext(struct twimap* map)
+{
+ if (twimap_index(map, int) >= 5) {
+ return 0;
+ }
+ map->index += 1;
+ return 1;
}
void
{
struct twifs_node *pci_class = twifs_dir_node(NULL, "pci"), *pci_dev;
struct pci_device *pos, *n;
+ struct twimap* map;
llist_for_each(pos, n, &pci_devices, dev_chain)
{
pci_dev = twifs_dir_node(pci_class,
- "B%d:D%d:F%d.%x:%x",
+ "%.2d:%.2d:%.2d.%.4x:%.4x",
PCI_BUS_NUM(pos->cspace_base),
PCI_SLOT_NUM(pos->cspace_base),
PCI_FUNCT_NUM(pos->cspace_base),
PCI_DEV_VENDOR(pos->device_info),
PCI_DEV_DEVID(pos->device_info));
- struct twifs_node* fnode = twifs_file_node(pci_dev, "cspace");
- fnode->data = pos;
- fnode->ops.read = __pci_read_cspace;
+
+ map = twifs_mapping(pci_dev, pos, "config");
+ map->read = __pci_read_cspace;
+
+ map = twifs_mapping(pci_dev, pos, "revision");
+ map->read = __pci_read_revid;
+
+ map = twifs_mapping(pci_dev, pos, "class");
+ map->read = __pci_read_class;
+
+ map = twifs_mapping(pci_dev, pos, "io_bases");
+ map->read = __pci_bar_read;
+ map->go_next = __pci_bar_gonext;
}
}
// PCI device header format
// Ref: "PCI Local Bus Specification, Rev.3, Section 6.1"
+#define BAR_TYPE_MMIO 0x1
+#define BAR_TYPE_CACHABLE 0x2
+
+struct pci_base_addr
+{
+ uint32_t start;
+ uint32_t size;
+ uint32_t type;
+};
+
struct pci_device
{
struct llist_header dev_chain;
uint32_t cspace_base;
uint32_t msi_loc;
uint16_t intr_info;
+ struct pci_base_addr bar[6];
};
// PCI Configuration Space (C-Space) r/w:
int
block_mount_disk(struct hba_device* hd_dev);
+void
+blk_mapping_init();
+
+void
+blk_set_blkmapping(struct block_dev* bdev);
+
#endif /* __LUNAIX_BLOCK_H */
#define __LUNAIX_TWIFS_H
#include <lunaix/fs.h>
+#include <lunaix/spike.h>
struct twifs_node
{
} ops;
};
+struct twimap
+{
+ void* index;
+ void* buffer;
+ void* data;
+ size_t size_acc;
+ void (*read)(struct twimap* mapping);
+ int (*go_next)(struct twimap* mapping);
+ void (*reset)(struct twimap* mapping);
+};
+
+#define twinode_getdata(inode, type) \
+ ({ \
+ struct twifs_node* twinode = (struct twifs_node*)(inode)->data; \
+ assert(twinode); \
+ (type) twinode->data; \
+ })
+
void
twifs_init();
+struct twifs_node*
+twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args);
+
struct twifs_node*
twifs_file_node(struct twifs_node* parent, const char* fmt, ...);
int
twifs_rm_node(struct twifs_node* node);
+#define twimap_index(twimap, type) ((type)((twimap)->index))
+#define twimap_data(twimap, type) ((type)((twimap)->data))
+
+struct twimap*
+twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...);
+
+void
+twimap_printf(struct twimap* mapping, const char* fmt, ...);
+
+int
+twimap_memcpy(struct twimap* mapping, const void* src, const size_t len);
+
+int
+twimap_memappend(struct twimap* mapping, const void* src, const size_t len);
+
#endif /* __LUNAIX_TWIFS_H */
void
cake_init();
-/**
- * @brief 统计蛋糕数量 - 问问Pinkie :D
- *
- */
void
-cake_stats();
+cake_export();
#endif /* __LUNAIX_VALLOC_H */
--- /dev/null
+#include <lunaix/block.h>
+#include <lunaix/fs/twifs.h>
+
+static struct twifs_node* blk_root;
+
+void
+blk_mapping_init()
+{
+ blk_root = twifs_dir_node(NULL, "block");
+}
+
+void
+__blk_rd_size(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ size_t secsize = bdev->hd_dev->block_size;
+ twimap_printf(map, "%u", (bdev->end_lba - bdev->base_lba) * secsize);
+}
+
+void
+__blk_rd_secsize(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ size_t secsize = bdev->hd_dev->block_size;
+ twimap_printf(map, "%u", secsize);
+}
+
+void
+__blk_rd_range(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(
+ map, "%u,%u", (uint32_t)bdev->base_lba, (uint32_t)bdev->end_lba);
+}
+
+void
+__blk_rd_model(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%s", bdev->hd_dev->model);
+}
+
+void
+__blk_rd_serial(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%s", bdev->hd_dev->serial_num);
+}
+
+void
+__blk_rd_status(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%p", bdev->hd_dev->last_result.status);
+}
+
+void
+__blk_rd_error(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%p", bdev->hd_dev->last_result.error);
+}
+
+void
+__blk_rd_sense_key(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ twimap_printf(map, "%p", bdev->hd_dev->last_result.sense_key);
+}
+
+void
+__blk_rd_wwid(struct twimap* map)
+{
+ struct block_dev* bdev = twimap_data(map, struct block_dev*);
+ uint32_t h = bdev->hd_dev->wwn >> 32;
+ uint32_t l = (uint32_t)bdev->hd_dev->wwn;
+ twimap_printf(map, "%x%x", h, l);
+}
+
+void
+blk_set_blkmapping(struct block_dev* bdev)
+{
+ struct twifs_node* dev_root = twifs_dir_node(blk_root, bdev->bdev_id);
+
+ struct twimap* map = twifs_mapping(dev_root, bdev, "size");
+ map->read = __blk_rd_size;
+
+ map = twifs_mapping(dev_root, bdev, "secsize");
+ map->read = __blk_rd_secsize;
+
+ map = twifs_mapping(dev_root, bdev, "range");
+ map->read = __blk_rd_range;
+
+ map = twifs_mapping(dev_root, bdev, "model");
+ map->read = __blk_rd_model;
+
+ map = twifs_mapping(dev_root, bdev, "serial");
+ map->read = __blk_rd_serial;
+
+ map = twifs_mapping(dev_root, bdev, "status");
+ map->read = __blk_rd_status;
+
+ map = twifs_mapping(dev_root, bdev, "error");
+ map->read = __blk_rd_error;
+
+ map = twifs_mapping(dev_root, bdev, "sense-key");
+ map->read = __blk_rd_sense_key;
+
+ map = twifs_mapping(dev_root, bdev, "wwid");
+ map->read = __blk_rd_wwid;
+}
\ No newline at end of file
lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
free_slot = 0;
+
+ blk_mapping_init();
}
int
goto error;
}
+ blk_set_blkmapping(bdev);
return errno;
error:
hd_dev->model,
hd_dev->serial_num,
-errno);
+ return errno;
}
int
dev->read = __block_read;
bdev->dev = dev;
+ strcpy(bdev->bdev_id, dev->name_val);
dev_registry[free_slot++] = bdev;
return 1;
}
\ No newline at end of file
while (1) {
getcwd(pwd, 512);
- printf("%s$ ", pwd);
+ printf("[\033[2m%s\033[39;49m]$ ", pwd);
size_t sz = read(stdin, buf, 512);
if (sz < 0) {
printf("fail to read user input (%d)\n", geterrno());
write(stdout, cat_buf, sz);
}
close(fd);
+ printf("\n");
}
} else {
printf("unknow command");
return 0;
}
+struct twifs_node*
+twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args)
+{
+ char buf[VFS_NAME_MAXLEN];
+ size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args);
+
+ return __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFSEQDEV);
+}
+
struct twifs_node*
twifs_file_node(struct twifs_node* parent, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
- char buf[VFS_NAME_MAXLEN];
- size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args);
- struct twifs_node* twi_node =
- __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFSEQDEV);
+ struct twifs_node* twi_node = twifs_file_node_vargs(parent, fmt, args);
va_end(args);
--- /dev/null
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/valloc.h>
+
+#include <klibc/stdio.h>
+#include <klibc/string.h>
+
+#define TWIMAP_BUFFER_SIZE 1024
+
+void
+__twimap_default_reset(struct twimap* map)
+{
+ map->index = NULL;
+}
+
+int
+__twimap_default_gonext(struct twimap* map)
+{
+ return 0;
+}
+
+int
+__twimap_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+ struct twimap* map = twinode_getdata(inode, struct twimap*);
+ map->buffer = valloc(TWIMAP_BUFFER_SIZE);
+ map->reset(map);
+
+ // FIXME what if TWIMAP_BUFFER_SIZE is not big enough?
+
+ size_t pos = 0;
+ do {
+ map->size_acc = 0;
+ map->read(map);
+ pos += map->size_acc;
+ } while (pos < fpos && map->go_next(map));
+
+ if (pos < fpos) {
+ vfree(map->buffer);
+ return 0;
+ }
+
+ if (!fpos) {
+ pos = 0;
+ }
+
+ size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size;
+ memcpy(buffer, map->buffer + (pos - fpos), acc_size);
+
+ while (acc_size < len && map->go_next(map)) {
+ map->size_acc = 0;
+ map->read(map);
+ rdlen = MIN(len - acc_size, map->size_acc);
+ memcpy(buffer + acc_size, map->buffer, rdlen);
+ acc_size += rdlen;
+ }
+
+ vfree(map->buffer);
+ return acc_size;
+}
+
+struct twimap*
+twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ struct twimap* map = vzalloc(sizeof(struct twimap));
+ struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args);
+ node->ops.read = __twimap_read;
+ node->data = map;
+
+ map->reset = __twimap_default_reset;
+ map->go_next = __twimap_default_gonext;
+ map->data = data;
+
+ return map;
+}
+
+void
+twimap_printf(struct twimap* mapping, const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ char* buf = mapping->buffer + mapping->size_acc;
+
+ mapping->size_acc +=
+ __ksprintf_internal(buf, fmt, TWIMAP_BUFFER_SIZE, args);
+
+ va_end(args);
+}
+
+int
+twimap_memcpy(struct twimap* mapping, const void* src, const size_t len)
+{
+ mapping->size_acc = MIN(TWIMAP_BUFFER_SIZE, len);
+ memcpy(mapping->buffer, src, mapping->size_acc);
+
+ return mapping->size_acc;
+}
+
+int
+twimap_memappend(struct twimap* mapping, const void* src, const size_t len)
+{
+ size_t cpy_len = MIN(TWIMAP_BUFFER_SIZE - mapping->size_acc, len);
+ memcpy(mapping->buffer + mapping->size_acc, src, cpy_len);
+ mapping->size_acc += cpy_len;
+
+ return cpy_len;
+}
\ No newline at end of file
cake->first_piece = (void*)((uintptr_t)cake + pile->offset);
cake->next_free = 0;
+ pile->cakes_count++;
piece_index_t* free_list = cake->free_list;
for (size_t i = 0; i < max_piece - 1; i++) {
}
return 1;
-}
-
-void
-cake_stats()
-{
- kprintf(KDEBUG "<name> <cake> <pg/c> <p/c> <alloced>\n");
-
- struct cake_pile *pos, *n;
- llist_for_each(pos, n, &piles, piles)
- {
- kprintf("%s %d %d %d %d\n",
- pos->pile_name,
- pos->cakes_count,
- pos->pg_per_cake,
- pos->pieces_per_cake,
- pos->alloced_pieces);
- }
}
\ No newline at end of file
--- /dev/null
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/cake.h>
+
+extern struct llist_header piles;
+
+int
+__cake_stat_gonext(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_index(map, struct cake_pile*);
+ if (pile->piles.next == &piles) {
+ return 0;
+ }
+ map->index = list_entry(pile->piles.next, struct cake_pile, piles);
+ return 1;
+}
+
+void
+__cake_stat_reset(struct twimap* map)
+{
+ map->index = container_of(piles.next, struct cake_pile, piles);
+}
+
+void
+__cake_rd_stat(struct twimap* map)
+{
+ struct cake_pile* pos = twimap_index(map, struct cake_pile*);
+ twimap_printf(map,
+ "%s %d %d %d %d\n",
+ pos->pile_name,
+ pos->cakes_count,
+ pos->pg_per_cake,
+ pos->pieces_per_cake,
+ pos->alloced_pieces);
+}
+
+void
+__cake_rd_psize(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+ twimap_printf(map, "%u", pile->piece_size);
+}
+
+void
+__cake_rd_ccount(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+ twimap_printf(map, "%u", pile->cakes_count);
+}
+
+void
+__cake_rd_alloced(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+ twimap_printf(map, "%u", pile->alloced_pieces);
+}
+
+void
+__cake_rd_ppc(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+ twimap_printf(map, "%u", pile->pieces_per_cake);
+}
+
+void
+__cake_rd_ppg(struct twimap* map)
+{
+ struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+ twimap_printf(map, "%u", pile->pg_per_cake);
+}
+
+void
+cake_export_pile(struct twifs_node* root, struct cake_pile* pile)
+{
+ struct twifs_node* pile_rt = twifs_dir_node(root, pile->pile_name);
+
+ struct twimap* map = twifs_mapping(pile_rt, pile, "piece_size");
+ map->read = __cake_rd_psize;
+
+ map = twifs_mapping(pile_rt, pile, "cake_count");
+ map->read = __cake_rd_ccount;
+
+ map = twifs_mapping(pile_rt, pile, "grabbed");
+ map->read = __cake_rd_alloced;
+
+ map = twifs_mapping(pile_rt, pile, "pieces_per_cake");
+ map->read = __cake_rd_ppc;
+
+ map = twifs_mapping(pile_rt, pile, "page_per_cake");
+ map->read = __cake_rd_ppg;
+}
+
+void
+cake_export()
+{
+ struct twifs_node* cake_root = twifs_dir_node(NULL, "cake");
+
+ struct twimap* map = twifs_mapping(cake_root, NULL, "pinkiepie");
+ map->reset = __cake_stat_reset;
+ map->go_next = __cake_stat_gonext;
+ map->read = __cake_rd_stat;
+ __cake_stat_reset(map);
+
+ struct cake_pile *pos, *n;
+ llist_for_each(pos, n, &piles, piles)
+ {
+ cake_export_pile(cake_root, pos);
+ }
+}
\ No newline at end of file
console_start_flushing();
console_flush();
+ cake_export();
unlock_reserved_memory();
for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
#include <hal/rtc.h>
#include <lunaix/clock.h>
+#include <lunaix/fs/twifs.h>
#include <lunaix/spike.h>
#include <lunaix/timer.h>
void
clock_systime_counter(void* arg);
+void
+__clock_read_systime(struct twimap* map)
+{
+ time_t save = sys_time;
+ twimap_printf(map, "%u", save);
+}
+
+void
+__clock_read_datetime(struct twimap* map)
+{
+ datetime_t dt;
+ clock_walltime(&dt);
+ twimap_printf(map,
+ "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+ dt.year,
+ dt.month,
+ dt.day,
+ dt.hour,
+ dt.minute,
+ dt.second);
+}
+
+void
+__clock_read_unix(struct twimap* map)
+{
+ datetime_t dt;
+ clock_walltime(&dt);
+ twimap_printf(map, "%u", clock_tounixtime(&dt));
+}
+
+void
+clock_build_mapping()
+{
+ struct twifs_node* root = twifs_dir_node(NULL, "clock");
+ struct twimap* map;
+
+ map = twifs_mapping(root, NULL, "systime");
+ map->read = __clock_read_systime;
+
+ map = twifs_mapping(root, NULL, "unix");
+ map->read = __clock_read_unix;
+
+ map = twifs_mapping(root, NULL, "datetime");
+ map->read = __clock_read_datetime;
+}
+
void
clock_init()
{
// 系统计时器每毫秒累加。
timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC);
+
+ clock_build_mapping();
}
void