Meta: Add files to repository

This commit is contained in:
Alec Murphy 2025-02-16 15:21:19 -05:00
parent 6d27d43268
commit 52cb92f587
120 changed files with 71820 additions and 0 deletions

View file

@ -0,0 +1,473 @@
// Virtio.HC
//
// PCI virtio I/O registers.
//
#define VIRTIO_PCI_HOST_FEATURES 0 // Features supported by the host
#define VIRTIO_PCI_GUEST_FEATURES 4 // Features activated by the guest
#define VIRTIO_PCI_QUEUE_PFN 8 // PFN for the currently selected queue
#define VIRTIO_PCI_QUEUE_SIZE 12 // Queue size for the currently selected queue
#define VIRTIO_PCI_QUEUE_SEL 14 // Queue selector
#define VIRTIO_PCI_QUEUE_NOTIFY 16 // Queue notifier
#define VIRTIO_PCI_STATUS 18 // Device status register
#define VIRTIO_PCI_ISR 19 // Interrupt status register
#define VIRTIO_PCI_CONFIG 20 // Configuration data block
//
// PCI virtio status register bits
//
#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
#define VIRTIO_CONFIG_S_DRIVER 2
#define VIRTIO_CONFIG_S_DRIVER_OK 4
#define VIRTIO_CONFIG_S_FAILED 0x80
//
// Ring descriptor flags
//
#define VRING_DESC_F_NEXT 1 // Buffer continues via the next field
#define VRING_DESC_F_WRITE 2 // Buffer is write-only (otherwise read-only)
#define VRING_DESC_F_INDIRECT 4 // Buffer contains a list of buffer descriptors
class @virtio_queue_buf
{
U64 address;
U32 length;
U16 flags;
U16 next;
};
class @virtio_avail
{
U16 flags;
U16 index;
U16 ring[256];
U16 int_index;
};
class @virtio_used_item
{
U32 index;
U32 length;
};
class @virtio_used
{
U16 flags;
U16 index;
@virtio_used_item ring[256];
U16 int_index;
};
class @virtio_queue
{
@virtio_queue_buf buffers[256];
@virtio_avail available;
U8 padding[3578];
@virtio_used used;
};
class @virtio_avail_buf
{
U32 index;
U64 address;
U32 length;
};
class @virtio_buf_info
{
U8* buffer;
U64 size;
U8 flags;
// If the user wants to keep same buffer as passed in this struct, use "true".
// otherwise, the supplied buffer will be copied in the queues' buffer
Bool copy;
};
// Virtio-blk.HC
#define BDT_VIRTIO_BLK 10
#define VIRTIO_BLK_T_IN 0
#define VIRTIO_BLK_T_OUT 1
#define VIRTIO_BLK_T_FLUSH 4
#define VIRTIO_BLK_MAX_BLK 0x400000 // Limit blkdev to 2G max, set to NULL to use entire disk (not recommended for RedSea)
class @virtio_blk
{
U16 port;
U32 blks;
@virtio_queue* vq;
I64 vq_size;
I64 vq_index;
U8 status;
};
class @virtio_blk_request
{
U32 type;
U32 priority;
U64 sector;
};
@virtio_blk virtio_blk;
MemSet(&virtio_blk, 0, sizeof(@virtio_blk));
I64 VirtioBlkInit()
{
I64 j;
// Scan for device
j = PCIClassFind(0x010000, 0);
if (j < 0) {
"\n[virtio-blk] No device found\n";
return -1;
}
virtio_blk.port = PCIReadU32(j.u8[2],
j.u8[1], j.u8[0], 0x10)
& 0xFFFFFFFC;
virtio_blk.blks = InU32(virtio_blk.port + VIRTIO_PCI_CONFIG);
// Reset Device
OutU8(virtio_blk.port + VIRTIO_PCI_STATUS, 0);
// Found Driver
OutU8(virtio_blk.port + VIRTIO_PCI_STATUS, InU8(virtio_blk.port + VIRTIO_PCI_STATUS) | VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER);
// Set up virt queue
OutU16(virtio_blk.port + VIRTIO_PCI_QUEUE_SEL, 0);
virtio_blk.vq_size = InU16(virtio_blk.port + VIRTIO_PCI_QUEUE_SIZE); // 256
virtio_blk.vq = CAllocAligned(sizeof(@virtio_queue), 4096, adam_task->code_heap);
OutU32(virtio_blk.port + VIRTIO_PCI_QUEUE_PFN, virtio_blk.vq / 4096);
// Init OK
OutU8(virtio_blk.port + VIRTIO_PCI_STATUS, InU8(virtio_blk.port + VIRTIO_PCI_STATUS) | VIRTIO_CONFIG_S_DRIVER_OK);
virtio_blk.vq_index = 0;
}
// DskVIO.HC
U0 VIOFlush()
{
I64 j;
I64 vq_idx;
@virtio_blk_request* brq = CAlloc(sizeof(@virtio_blk_request), adam_task);
brq->type = VIRTIO_BLK_T_FLUSH;
brq->sector = NULL;
vq_idx = virtio_blk.vq->available.index % 256;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].address = brq;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].length = sizeof(@virtio_blk_request);
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].flags = VRING_DESC_F_NEXT;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].next = (virtio_blk.vq_index + 1) % 256;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].address = &virtio_blk.status;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].length = 1;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].flags = VRING_DESC_F_WRITE;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].next = 0;
virtio_blk.vq->available.ring[vq_idx] = virtio_blk.vq_index % 256;
virtio_blk.vq_index += 2;
j = virtio_blk.vq->used.index;
virtio_blk.vq->available.index++;
OutU16(virtio_blk.port + VIRTIO_PCI_QUEUE_NOTIFY, 0);
while (j == virtio_blk.vq->used.index) {
Yield;
}
Free(brq);
}
Bool VIORBlks(CDrv* dv, U8* buf, I64 blk, I64 cnt)
{
no_warn dv;
I64 i, j;
I64 vq_idx;
U64 addr;
@virtio_blk_request* brq = CAlloc(sizeof(@virtio_blk_request), adam_task);
for (i = 0; i < cnt; i++) {
brq->type = VIRTIO_BLK_T_IN;
brq->sector = blk + i;
vq_idx = virtio_blk.vq->available.index % 256;
addr = buf + (BLK_SIZE * i);
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].address = brq;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].length = sizeof(@virtio_blk_request);
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].flags = VRING_DESC_F_NEXT;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].next = (virtio_blk.vq_index + 1) % 256;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].address = addr;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].length = BLK_SIZE;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].flags = VRING_DESC_F_WRITE | VRING_DESC_F_NEXT;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].next = (virtio_blk.vq_index + 2) % 256;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].address = &virtio_blk.status;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].length = 1;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].flags = VRING_DESC_F_WRITE;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].next = 0;
virtio_blk.vq->available.ring[vq_idx] = virtio_blk.vq_index % 256;
virtio_blk.vq_index += 3;
j = virtio_blk.vq->used.index;
virtio_blk.vq->available.index++;
OutU16(virtio_blk.port + VIRTIO_PCI_QUEUE_NOTIFY, 0);
while (j == virtio_blk.vq->used.index) {
Yield;
}
}
Free(brq);
return TRUE;
}
Bool VIOWBlks(CDrv* dv, U8* buf, I64 blk, I64 cnt)
{
no_warn dv;
I64 i, j;
I64 vq_idx;
U64 addr;
@virtio_blk_request* brq = CAlloc(sizeof(@virtio_blk_request), adam_task);
for (i = 0; i < cnt; i++) {
brq->type = VIRTIO_BLK_T_OUT;
brq->sector = blk + i;
vq_idx = virtio_blk.vq->available.index % 256;
addr = buf + (BLK_SIZE * i);
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].address = brq;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].length = sizeof(@virtio_blk_request);
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].flags = VRING_DESC_F_NEXT;
virtio_blk.vq->buffers[virtio_blk.vq_index % 256].next = (virtio_blk.vq_index + 1) % 256;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].address = addr;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].length = BLK_SIZE;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].flags = VRING_DESC_F_NEXT;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 1) % 256].next = (virtio_blk.vq_index + 2) % 256;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].address = &virtio_blk.status;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].length = 1;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].flags = VRING_DESC_F_WRITE;
virtio_blk.vq->buffers[(virtio_blk.vq_index + 2) % 256].next = 0;
virtio_blk.vq->available.ring[vq_idx] = virtio_blk.vq_index % 256;
virtio_blk.vq_index += 3;
j = virtio_blk.vq->used.index;
virtio_blk.vq->available.index++;
OutU16(virtio_blk.port + VIRTIO_PCI_QUEUE_NOTIFY, 0);
while (j == virtio_blk.vq->used.index) {
Yield;
}
}
Free(brq);
VIOFlush;
return TRUE;
}
U0 RedSeaTryInit(CDrv* dv)
{
CRedSeaBoot br;
Bool unlock;
try {
unlock = DrvLock(dv);
BlkRead(dv, &br, dv->drv_offset, 1);
if (br.signature != MBR_PT_REDSEA || br.signature2 != 0xAA55)
return;
dv->fs_type = FSt_REDSEA;
CallExtStr("RedSeaFreeFreeLst", dv);
dv->spc = 1;
dv->size = br.sects;
dv->data_area = dv->drv_offset + br.bitmap_sects;
dv->root_clus = br.root_clus;
dv->fat1 = dv->fat2 = dv->drv_offset + 1;
CallExtStr("DrvFATBlkAlloc", dv);
if (unlock)
DrvUnlock(dv);
} catch if (unlock)
DrvUnlock(dv);
}
U8 MountVirtioBlk()
{ // Mount Virtio-blk device
CDrv* dv = DrvMakeFreeSlot(DrvNextFreeLet('A'));
CBlkDev* bd = BlkDevNextFreeSlot(dv->drv_let, BDT_RAM);
CRedSeaBoot* bs = CAlloc(BLK_SIZE, adam_task);
bd->max_blk = 512;
BlkDevAdd(bd, , TRUE, TRUE);
bd->type = BDT_VIRTIO_BLK;
if (VIRTIO_BLK_MAX_BLK) {
bd->max_blk = Min(VIRTIO_BLK_MAX_BLK, virtio_blk.blks);
} else {
bd->max_blk = virtio_blk.blks;
}
Free(bd->RAM_dsk);
dv->size = bd->max_blk + 1 - bd->drv_offset;
VIORBlks(dv, bs, 0, 1);
dv->root_clus = bs->root_clus;
dv->data_area = bs->bitmap_sects;
dv->next_free = NULL;
dv->last_free = NULL;
Free(bs);
RedSeaTryInit(dv);
return dv->drv_let;
}
// DskBlk2.HC
Bool BlkRead2(CDrv* dv, U8* buf, I64 blk, I64 cnt)
{ // Read blk cnt from Drv to buf.
Bool res = TRUE, unlock;
CBlkDev* bd = dv->bd;
if (cnt <= 0)
return TRUE;
DrvChk(dv);
try {
unlock = DrvLock(dv);
CallExtStr("BlkDevInit", bd);
if (dv->drv_offset && blk < dv->drv_offset || blk + cnt > dv->drv_offset + dv->size)
throw('Drv');
if (bd->flags & BDF_READ_CACHE)
CallExtStr("RCache", dv, &buf, &blk, &cnt);
if (cnt > 0) {
switch (bd->type) {
case BDT_RAM:
MemCpy(buf, bd->RAM_dsk + blk << BLK_SIZE_BITS, cnt << BLK_SIZE_BITS);
break;
case BDT_ISO_FILE_READ:
case BDT_ISO_FILE_WRITE:
FBlkRead(bd->file_dsk, buf, blk, cnt);
break;
case BDT_ATA:
case BDT_ATAPI:
res = CallExtStr("ATARBlks", dv, buf, blk, cnt);
break;
case BDT_VIRTIO_BLK:
res = VIORBlks(dv, buf, blk, cnt);
break;
}
bd->last_time = tS;
if (bd->flags & BDF_READ_CACHE)
CallExtStr("DskCacheAdd", dv, buf, blk, cnt);
}
if (unlock)
DrvUnlock(dv);
} catch if (unlock)
DrvUnlock(dv);
return res;
}
Bool BlkWrite2(CDrv* dv, U8* buf, I64 blk, I64 cnt)
{ // Write blk cnt from buf to Drv.
Bool res = TRUE, unlock;
CBlkDev* bd = dv->bd;
if (cnt <= 0)
return TRUE;
DrvChk(dv);
try {
unlock = DrvLock(dv);
CallExtStr("BlkDevInit", bd);
if (bd->flags & BDF_READ_ONLY && !(bd->flags & BDF_READ_ONLY_OVERRIDE))
throw('BlkDev');
if (dv->drv_offset && blk < dv->drv_offset || blk + cnt > dv->drv_offset + dv->size)
throw('Drv');
if (cnt > 0) {
switch (bd->type) {
case BDT_RAM:
MemCpy(bd->RAM_dsk + blk << BLK_SIZE_BITS, buf, cnt << BLK_SIZE_BITS);
break;
case BDT_ISO_FILE_READ:
case BDT_ISO_FILE_WRITE:
FBlkWrite(bd->file_dsk, buf, blk, cnt);
break;
case BDT_ATA:
case BDT_ATAPI:
res = CallExtStr("ATAWBlks", dv, buf, blk, cnt);
break;
case BDT_VIRTIO_BLK:
res = VIOWBlks(dv, buf, blk, cnt);
break;
}
bd->last_time = tS;
if (bd->flags & BDF_READ_CACHE)
CallExtStr("DskCacheAdd", dv, buf, blk, cnt);
}
if (unlock)
DrvUnlock(dv);
} catch if (unlock)
DrvUnlock(dv);
return res;
}
@patch_jmp_rel32(&BlkRead, &BlkRead2);
@patch_jmp_rel32(&BlkWrite, &BlkWrite2);
// DskBlkDev2.HC
CBlkDev* BlkDevChk2(CBlkDev* bd, Bool except = TRUE)
{ // Check for valid BlkDev. Throw exception.
if (bd->type == BDT_VIRTIO_BLK)
return bd;
if (!bd || bd->bd_signature != BD_SIGNATURE_VAL || !(BDT_NULL < bd->type < BDT_TYPES_NUM)) {
if (except)
throw('BlkDev');
else
return NULL;
} else
return bd;
}
@patch_jmp_rel32(&BlkDevChk, &BlkDevChk2);
// DskDrv2.HC
DefineLstLoad("ST_BLKDEV_TYPES2",
"NULL\0RAM\0ATA\0FILE_READ\0FILE_WRITE\0ATAPI\0NULL\0NULL\0NULL\0NULL\0VIRTIO\0");
U8 DrvTextAttrGet2(U8 drv_let = 0)
{ // Get color of drive.
U8* blkdev_text_attr2 = blkdev_text_attr;
U8* drv_text_attr2 = drv_text_attr;
I64 dta_size = 3;
drv_let = Let2Let(drv_let);
if (drv_let == 'A')
return BLACK << 4 | WHITE;
if ('A' <= drv_let <= 'Z')
return blkdev_text_attr2[Let2BlkDevType(drv_let)] << 4 | drv_text_attr2[drv_let % dta_size];
else
return BLACK << 4 | WHITE;
}
U0 DrvRep2()
{ // Drive report.
CDrv* dv;
CBlkDev* bd;
I64 ch, i, drv_let, attr;
U8* st;
"\nDefined Drives:\n";
for (i = 0, dv = blkdev.drvs; i < DRVS_NUM; i++, dv++) {
if (dv->dv_signature == DRV_SIGNATURE_VAL) {
bd = dv->bd;
drv_let = Drv2Let(dv);
if (Bt(&dv->fs_type, FStf_DISABLE))
ch = '-';
else if (drv_let == blkdev.boot_drv_let)
ch = ':';
else
ch = '+';
attr = DrvTextAttrGet(drv_let);
"\dFG,%d\d\dBG,%d\d%C %-8Z %-10Z %04X %04X %02X\n",
attr & 15, attr >> 4, drv_let, dv->fs_type &FSG_TYPE_MASK, "ST_DRV_TYPES",
bd->type, "ST_BLKDEV_TYPES2", bd->base0, bd->base1, bd->unit;
if (st = DrvModelNum(drv_let)) {
"Model#:%s\n", st;
Free(st);
}
if (st = DrvSerialNum(drv_let)) {
"Serial#:%s\n", st;
Free(st);
}
if (bd->type == BDT_ISO_FILE_READ || bd->type == BDT_ISO_FILE_WRITE)
"File=\"%s\"\n", bd->file_dsk_name;
"%016X-%016X\n\dFG\d\dBG\d", dv->drv_offset, dv->drv_offset + dv->size - 1;
}
}
"Home Dir:\"%s\"\n", blkdev.home_dir;
}
@patch_jmp_rel32(&DrvTextAttrGet, &DrvTextAttrGet2);
@patch_jmp_rel32(&DrvRep, &DrvRep2);
VirtioBlkInit;
MountVirtioBlk;
if (Let2Drv('A', 0) && !Let2Drv('A')->root_clus) {
"[virtio-blk] RedSea filesystem not initialized, formatting.\n";
Fmt('A', , FALSE, FSt_REDSEA);
Cd("M:/System/");
}