HelenOS sources
This source file includes following definitions.
- scr_init
#include <arch/drivers/scr.h>
#include <genarch/ofw/ofw_tree.h>
#include <genarch/ofw/pci.h>
#include <genarch/ofw/sbus.h>
#include <genarch/ofw/upa.h>
#include <genarch/fb/fb.h>
#include <abi/fb/visuals.h>
#include <console/chardev.h>
#include <console/console.h>
#include <stdint.h>
#include <str.h>
#include <align.h>
#include <log.h>
#define FFB_REG_24BPP 7
scr_type_t scr_type = SCR_UNKNOWN;
void scr_init(ofw_tree_node_t *node)
{
ofw_tree_property_t *prop;
ofw_pci_reg_t *pci_reg;
ofw_pci_reg_t pci_abs_reg;
ofw_upa_reg_t *upa_reg;
ofw_sbus_reg_t *sbus_reg;
const char *name;
name = ofw_tree_node_name(node);
if (str_cmp(name, "SUNW,m64B") == 0)
scr_type = SCR_ATYFB;
else if (str_cmp(name, "SUNW,XVR-100") == 0)
scr_type = SCR_XVR;
else if (str_cmp(name, "SUNW,ffb") == 0)
scr_type = SCR_FFB;
else if (str_cmp(name, "cgsix") == 0)
scr_type = SCR_CGSIX;
else if (str_cmp(name, "QEMU,VGA") == 0)
scr_type = SCR_QEMU_VGA;
if (scr_type == SCR_UNKNOWN) {
log(LF_ARCH, LVL_ERROR, "Unknown screen device.");
return;
}
uintptr_t fb_addr;
unsigned int fb_offset = 0;
uint32_t fb_width = 0;
uint32_t fb_height = 0;
uint32_t fb_depth = 0;
uint32_t fb_linebytes = 0;
uint32_t fb_scanline = 0;
unsigned int visual;
prop = ofw_tree_getprop(node, "width");
if (prop && prop->value)
fb_width = *((uint32_t *) prop->value);
prop = ofw_tree_getprop(node, "height");
if (prop && prop->value)
fb_height = *((uint32_t *) prop->value);
prop = ofw_tree_getprop(node, "depth");
if (prop && prop->value)
fb_depth = *((uint32_t *) prop->value);
prop = ofw_tree_getprop(node, "linebytes");
if (prop && prop->value)
fb_linebytes = *((uint32_t *) prop->value);
prop = ofw_tree_getprop(node, "reg");
if (!prop)
panic("Cannot find 'reg' property.");
switch (scr_type) {
case SCR_ATYFB:
if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
log(LF_ARCH, LVL_ERROR, "Too few screen registers.");
return;
}
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
log(LF_ARCH, LVL_ERROR,
"Failed to absolutize fb register.");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
log(LF_ARCH, LVL_ERROR,
"Failed to determine screen address.");
return;
}
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_INDIRECT_8;
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5_BE;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_BGR_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_0_8_8_8;
break;
default:
log(LF_ARCH, LVL_ERROR,
"Unsupported bits per pixel.");
return;
}
break;
case SCR_XVR:
if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
log(LF_ARCH, LVL_ERROR,
"Too few screen registers.");
return;
}
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
log(LF_ARCH, LVL_ERROR,
"Failed to absolutize fb register.");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
log(LF_ARCH, LVL_ERROR,
"Failed to determine screen address.");
return;
}
fb_offset = 4 * 0x2000;
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_INDIRECT_8;
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5_BE;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_BGR_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_0_8_8_8;
break;
default:
log(LF_ARCH, LVL_ERROR,
"Unsupported bits per pixel.");
return;
}
break;
case SCR_FFB:
fb_scanline = 8192;
visual = VISUAL_BGR_0_8_8_8;
upa_reg = &((ofw_upa_reg_t *) prop->value)[FFB_REG_24BPP];
if (!ofw_upa_apply_ranges(node->parent, upa_reg, &fb_addr)) {
log(LF_ARCH, LVL_ERROR,
"Failed to determine screen address.");
return;
}
break;
case SCR_CGSIX:
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes;
visual = VISUAL_INDIRECT_8;
break;
default:
log(LF_ARCH, LVL_WARN, "Not implemented.");
return;
}
sbus_reg = &((ofw_sbus_reg_t *) prop->value)[0];
if (!ofw_sbus_apply_ranges(node->parent, sbus_reg, &fb_addr)) {
log(LF_ARCH, LVL_ERROR,
"Failed to determine screen address.");
return;
}
break;
case SCR_QEMU_VGA:
if (prop->size / sizeof(ofw_pci_reg_t) < 2) {
log(LF_ARCH, LVL_ERROR, "Too few screen registers.");
return;
}
pci_reg = &((ofw_pci_reg_t *) prop->value)[1];
if (!ofw_pci_reg_absolutize(node, pci_reg, &pci_abs_reg)) {
log(LF_ARCH, LVL_ERROR,
"Failed to absolutize fb register.");
return;
}
if (!ofw_pci_apply_ranges(node->parent, &pci_abs_reg,
&fb_addr)) {
log(LF_ARCH, LVL_ERROR,
"Failed to determine screen address.");
return;
}
switch (fb_depth) {
case 8:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_INDIRECT_8;
break;
case 16:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_5_6_5_BE;
break;
case 24:
fb_scanline = fb_linebytes * 4;
visual = VISUAL_BGR_8_8_8_0;
break;
case 32:
fb_scanline = fb_linebytes * (fb_depth >> 3);
visual = VISUAL_RGB_0_8_8_8;
break;
default:
log(LF_ARCH, LVL_ERROR, "Unsupported bits per pixel.");
return;
}
break;
default:
panic("Unexpected type.");
}
fb_properties_t props = {
.addr = fb_addr,
.offset = fb_offset,
.x = fb_width,
.y = fb_height,
.scan = fb_scanline,
.visual = visual,
};
outdev_t *fbdev = fb_init(&props);
if (fbdev)
stdout_wire(fbdev);
}
HelenOS homepage, sources at GitHub