Switch fb and efifb drivers to use names and new vt(4) driver probe method.

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
ray 2014-05-05 21:48:19 +00:00
parent 33c335d9af
commit cc38cb22e9
4 changed files with 157 additions and 37 deletions

View File

@ -51,35 +51,57 @@ __FBSDID("$FreeBSD$");
#include <dev/vt/hw/fb/vt_fb.h>
#include <dev/vt/colors/vt_termcolors.h>
static vd_init_t vt_efb_init;
static vd_init_t vt_efifb_init;
static vd_probe_t vt_efifb_probe;
static struct vt_driver vt_efb_driver = {
.vd_init = vt_efb_init,
static struct vt_driver vt_efifb_driver = {
.vd_name = "efifb",
.vd_probe = vt_efifb_probe,
.vd_init = vt_efifb_init,
.vd_blank = vt_fb_blank,
.vd_bitbltchr = vt_fb_bitbltchr,
.vd_maskbitbltchr = vt_fb_maskbitbltchr,
/* Better than VGA, but still generic driver. */
.vd_priority = VD_PRIORITY_GENERIC + 1,
};
static struct fb_info info;
VT_CONSDEV_DECLARE(vt_efb_driver,
MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)),
MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info);
static struct fb_info local_info;
VT_DRIVER_DECLARE(vt_efifb, vt_efifb_driver);
static int
vt_efb_init(struct vt_device *vd)
vt_efifb_probe(struct vt_device *vd)
{
int depth, d, disable, i, len;
int disabled;
struct efi_fb *efifb;
caddr_t kmdp;
disabled = 0;
TUNABLE_INT_FETCH("hw.syscons.disable", &disabled);
if (disabled != 0)
return (CN_DEAD);
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
efifb = (struct efi_fb *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_EFI_FB);
if (efifb == NULL)
return (CN_DEAD);
return (CN_INTERNAL);
}
static int
vt_efifb_init(struct vt_device *vd)
{
int depth, d, i, len;
struct fb_info *info;
struct efi_fb *efifb;
caddr_t kmdp;
info = vd->vd_softc;
disable = 0;
TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
if (disable != 0)
return (CN_DEAD);
if (info == NULL)
info = vd->vd_softc = (void *)&local_info;
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
@ -136,7 +158,8 @@ vt_efb_init(struct vt_device *vd)
fb_probe(info);
vt_fb_init(vd);
/* Clear the screen. */
vt_fb_blank(vd, TC_BLACK);
return (CN_INTERNAL);
}

View File

@ -52,18 +52,19 @@ __FBSDID("$FreeBSD$");
#include <dev/vt/colors/vt_termcolors.h>
static vd_init_t vt_efb_init;
static vd_probe_t vt_efb_probe;
static struct vt_driver vt_fb_early_driver = {
.vd_name = "efb",
.vd_probe = vt_efb_probe,
.vd_init = vt_efb_init,
.vd_blank = vt_fb_blank,
.vd_bitbltchr = vt_fb_bitbltchr,
.vd_priority = VD_PRIORITY_GENERIC,
};
static struct fb_info info;
VT_CONSDEV_DECLARE(vt_fb_early_driver,
MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)),
MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info);
static struct fb_info local_info;
VT_DRIVER_DECLARE(vt_efb, vt_fb_early_driver);
static void
#ifdef FDT
@ -126,30 +127,62 @@ vt_efb_initialize(struct fb_info *info)
}
}
static phandle_t
vt_efb_get_fbnode()
{
phandle_t chosen, node;
ihandle_t stdout;
char type[64];
chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
node = OF_instance_to_package(stdout);
if (node != -1) {
/* The "/chosen/stdout" present. */
OF_getprop(node, "device_type", type, sizeof(type));
/* Check if it has "display" type. */
if (strcmp(type, "display") == 0)
return (node);
}
/* Try device with name "screen". */
node = OF_finddevice("screen");
return (node);
}
static int
vt_efb_probe(struct vt_device *vd)
{
phandle_t node;
node = vt_efb_get_fbnode();
if (node == -1)
return (CN_DEAD);
if ((OF_getproplen(node, "height") <= 0) ||
(OF_getproplen(node, "width") <= 0) ||
(OF_getproplen(node, "depth") <= 0) ||
(OF_getproplen(node, "linebytes") <= 0))
return (CN_DEAD);
return (CN_INTERNAL);
}
static int
vt_efb_init(struct vt_device *vd)
{
struct ofw_pci_register pciaddrs[8];
struct fb_info *info;
int i, len, n_pciaddrs;
phandle_t chosen, node;
ihandle_t stdout;
char type[64];
phandle_t node;
if (vd->vd_softc == NULL)
vd->vd_softc = (void *)&local_info;
info = vd->vd_softc;
chosen = OF_finddevice("/chosen");
OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
node = OF_instance_to_package(stdout);
if (node == -1) {
/*
* The "/chosen/stdout" does not exist try
* using "screen" directly.
*/
node = OF_finddevice("screen");
}
OF_getprop(node, "device_type", type, sizeof(type));
if (strcmp(type, "display") != 0)
node = vt_efb_get_fbnode();
if (node == -1)
return (CN_DEAD);
#define GET(name, var) \
@ -249,7 +282,6 @@ vt_efb_init(struct vt_device *vd)
#endif
}
/* blank full size */
len = info->fb_size / 4;
for (i = 0; i < len; i++) {
@ -274,6 +306,5 @@ vt_efb_init(struct vt_device *vd)
fb_probe(info);
vt_fb_init(vd);
return (CN_INTERNAL);
}

View File

@ -50,9 +50,11 @@ void vt_fb_drawrect(struct vt_device *vd, int x1, int y1, int x2, int y2,
void vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color);
static struct vt_driver vt_fb_driver = {
.vd_name = "fb",
.vd_init = vt_fb_init,
.vd_blank = vt_fb_blank,
.vd_bitbltchr = vt_fb_bitbltchr,
.vd_maskbitbltchr = vt_fb_maskbitbltchr,
.vd_drawrect = vt_fb_drawrect,
.vd_setpixel = vt_fb_setpixel,
.vd_postswitch = vt_fb_postswitch,
@ -61,6 +63,8 @@ static struct vt_driver vt_fb_driver = {
.vd_fb_mmap = vt_fb_mmap,
};
VT_DRIVER_DECLARE(vt_fb, vt_fb_driver);
static int
vt_fb_ioctl(struct vt_device *vd, u_long cmd, caddr_t data, struct thread *td)
{
@ -184,6 +188,68 @@ void
vt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
unsigned int height, term_color_t fg, term_color_t bg)
{
struct fb_info *info;
uint32_t fgc, bgc, cc, o;
int c, l, bpp;
u_long line;
uint8_t b;
const uint8_t *ch;
info = vd->vd_softc;
bpp = FBTYPE_GET_BYTESPP(info);
fgc = info->fb_cmap[fg];
bgc = info->fb_cmap[bg];
b = 0;
if (bpl == 0)
bpl = (width + 7) >> 3; /* Bytes per sorce line. */
/* Don't try to put off screen pixels */
if (((left + width) > info->fb_width) || ((top + height) >
info->fb_height))
return;
line = (info->fb_stride * top) + (left * bpp);
for (l = 0; l < height; l++) {
ch = src;
for (c = 0; c < width; c++) {
if (c % 8 == 0)
b = *ch++;
else
b <<= 1;
o = line + (c * bpp);
cc = b & 0x80 ? fgc : bgc;
switch(bpp) {
case 1:
info->wr1(info, o, cc);
break;
case 2:
info->wr2(info, o, cc);
break;
case 3:
/* Packed mode, so unaligned. Byte access. */
info->wr1(info, o, (cc >> 16) & 0xff);
info->wr1(info, o + 1, (cc >> 8) & 0xff);
info->wr1(info, o + 2, cc & 0xff);
break;
case 4:
info->wr4(info, o, cc);
break;
default:
/* panic? */
break;
}
}
line += info->fb_stride;
src += bpl;
}
}
void
vt_fb_maskbitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
unsigned int height, term_color_t fg, term_color_t bg)
{
struct fb_info *info;
uint32_t fgc, bgc, cc, o;

View File

@ -41,7 +41,7 @@ int fb_probe(struct fb_info *info);
vd_init_t vt_fb_init;
vd_blank_t vt_fb_blank;
vd_bitbltchr_t vt_fb_bitbltchr;
vd_maskbitbltchr_t vt_fb_maskbitbltchr;
vd_postswitch_t vt_fb_postswitch;
#endif /* _DEV_VT_HW_FB_VT_FB_H_ */