⛏️ index : haiku.git

/*
 * Copyright 2021, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 */


#include "FwCfg.h"

#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#include <ByteOrder.h>
#include <Htif.h>
#include <KernelExport.h>

#include "graphics.h"


FwCfgRegs *volatile gFwCfgRegs = NULL;


namespace FwCfg {

void
Select(uint16_t selector)
{
	// GCC, why are you so crazy?
	// gFwCfgRegs->selector = B_BENDIAN_TO_HOST_INT16(selector);
	*(uint16*)0x10100008 = B_BENDIAN_TO_HOST_INT16(selector);
}


void
DmaOp(uint8_t *bytes, size_t count, uint32_t op)
{
	__attribute__ ((aligned (8))) FwCfgDmaAccess volatile dma;
	dma.control = B_HOST_TO_BENDIAN_INT32(1 << op);
	dma.length = B_HOST_TO_BENDIAN_INT32(count);
	dma.address = B_HOST_TO_BENDIAN_INT64((addr_t)bytes);
	// gFwCfgRegs->dmaAdr = B_HOST_TO_BENDIAN_INT64((addr_t)&dma);
	*(uint64*)0x10100010 = B_HOST_TO_BENDIAN_INT64((addr_t)&dma);
	while (uint32_t control = B_BENDIAN_TO_HOST_INT32(dma.control) != 0) {
		if (((1 << fwCfgDmaFlagsError) & control) != 0)
			abort();
	}
}


void
ReadBytes(uint8_t *bytes, size_t count)
{
	DmaOp(bytes, count, fwCfgDmaFlagsRead);
}


void
WriteBytes(uint8_t *bytes, size_t count)
{
	DmaOp(bytes, count, fwCfgDmaFlagsWrite);
}


uint8_t  Read8 () {uint8_t  val; ReadBytes(          &val, sizeof(val)); return val;}
uint16_t Read16() {uint16_t val; ReadBytes((uint8_t*)&val, sizeof(val)); return val;}
uint32_t Read32() {uint32_t val; ReadBytes((uint8_t*)&val, sizeof(val)); return val;}
uint64_t Read64() {uint64_t val; ReadBytes((uint8_t*)&val, sizeof(val)); return val;}


void
ListDir()
{
	uint32_t count = B_BENDIAN_TO_HOST_INT32(Read32());
	dprintf("count: %" B_PRIu32 "\n", count);
	for (uint32_t i = 0; i < count; i++) {
		FwCfgFile file;
		ReadBytes((uint8_t*)&file, sizeof(file));
		file.size = B_BENDIAN_TO_HOST_INT32(file.size);
		file.select = B_BENDIAN_TO_HOST_INT16(file.select);
		file.reserved = B_BENDIAN_TO_HOST_INT16(file.reserved);
		dprintf("\n");
		dprintf("size: %" B_PRIu32 "\n", file.size);
		dprintf("select: %" B_PRIu32 "\n", file.select);
		dprintf("reserved: %" B_PRIu32 "\n", file.reserved);
		dprintf("name: %s\n", file.name);
	}
}


bool
ThisFile(FwCfgFile& file, uint16_t dir, const char *name)
{
	Select(dir);
	uint32_t count = B_BENDIAN_TO_HOST_INT32(Read32());
	for (uint32_t i = 0; i < count; i++) {
		ReadBytes((uint8_t*)&file, sizeof(file));
		file.size = B_BENDIAN_TO_HOST_INT32(file.size);
		file.select = B_BENDIAN_TO_HOST_INT16(file.select);
		file.reserved = B_BENDIAN_TO_HOST_INT16(file.reserved);
		if (strcmp(file.name, name) == 0)
			return true;
	}
	return false;
}


void
InitFramebuffer()
{
	FwCfgFile file;
	if (!ThisFile(file, fwCfgSelectFileDir, "etc/ramfb")) {
		dprintf("[!] ramfb not found\n");
		return;
	}
	dprintf("file.select: %" B_PRIu16 "\n", file.select);

	RamFbCfg cfg;
	uint32_t width = 1024, height = 768;

	gFramebuf.colors = (uint32_t*)malloc(4*width*height);
	gFramebuf.stride = width;
	gFramebuf.width = width;
	gFramebuf.height = height;

	cfg.addr = B_HOST_TO_BENDIAN_INT64((size_t)gFramebuf.colors);
	cfg.fourcc = B_HOST_TO_BENDIAN_INT32(ramFbFormatXrgb8888);
	cfg.flags = B_HOST_TO_BENDIAN_INT32(0);
	cfg.width = B_HOST_TO_BENDIAN_INT32(width);
	cfg.height = B_HOST_TO_BENDIAN_INT32(height);
	cfg.stride = B_HOST_TO_BENDIAN_INT32(4 * width);
	Select(file.select);
	WriteBytes((uint8_t*)&cfg, sizeof(cfg));
}


void
Init()
{
	dprintf("gFwCfgRegs: 0x%08" B_PRIx64 "\n", (addr_t)gFwCfgRegs);
	if (gFwCfgRegs == NULL)
		return;
	Select(fwCfgSelectSignature);
	dprintf("fwCfgSelectSignature: 0x%08" B_PRIx32 "\n", Read32());
	Select(fwCfgSelectId);
	dprintf("fwCfgSelectId: : 0x%08" B_PRIx32 "\n", Read32());
	Select(fwCfgSelectFileDir);
	ListDir();
	InitFramebuffer();
}


};