summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorray <ray@FreeBSD.org>2014-05-05 21:48:19 +0000
committerray <ray@FreeBSD.org>2014-05-05 21:48:19 +0000
commitcc38cb22e907092934f43ebdcc910d0ac1ebd4d6 (patch)
treed21449cdd5e635add5de19422981ed5055395428
parent33c335d9afb25bdeb054d9bea8222a45f4f25848 (diff)
downloadFreeBSD-src-cc38cb22e907092934f43ebdcc910d0ac1ebd4d6.zip
FreeBSD-src-cc38cb22e907092934f43ebdcc910d0ac1ebd4d6.tar.gz
Switch fb and efifb drivers to use names and new vt(4) driver probe method.
Sponsored by: The FreeBSD Foundation
-rw-r--r--sys/dev/vt/hw/efifb/efifb.c53
-rw-r--r--sys/dev/vt/hw/fb/vt_early_fb.c73
-rw-r--r--sys/dev/vt/hw/fb/vt_fb.c66
-rw-r--r--sys/dev/vt/hw/fb/vt_fb.h2
4 files changed, 157 insertions, 37 deletions
diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c
index 4a6eeb7..683cecb 100644
--- a/sys/dev/vt/hw/efifb/efifb.c
+++ b/sys/dev/vt/hw/efifb/efifb.c
@@ -51,36 +51,58 @@ __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;
- struct fb_info *info;
+ int disabled;
struct efi_fb *efifb;
caddr_t kmdp;
- info = vd->vd_softc;
+ disabled = 0;
+ TUNABLE_INT_FETCH("hw.syscons.disable", &disabled);
+ if (disabled != 0)
+ return (CN_DEAD);
- disable = 0;
- TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
- if (disable != 0)
+ 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;
+ if (info == NULL)
+ info = vd->vd_softc = (void *)&local_info;
+
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
@@ -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);
}
-
diff --git a/sys/dev/vt/hw/fb/vt_early_fb.c b/sys/dev/vt/hw/fb/vt_early_fb.c
index 4a81f4f..8ca2338 100644
--- a/sys/dev/vt/hw/fb/vt_early_fb.c
+++ b/sys/dev/vt/hw/fb/vt_early_fb.c
@@ -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 int
-vt_efb_init(struct vt_device *vd)
+static phandle_t
+vt_efb_get_fbnode()
{
- 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];
- 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");
+ 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);
}
- OF_getprop(node, "device_type", type, sizeof(type));
- if (strcmp(type, "display") != 0)
+ /* 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 node;
+
+ if (vd->vd_softc == NULL)
+ vd->vd_softc = (void *)&local_info;
+
+ info = vd->vd_softc;
+
+ 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);
}
diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c
index 7163bdc..3ffba40 100644
--- a/sys/dev/vt/hw/fb/vt_fb.c
+++ b/sys/dev/vt/hw/fb/vt_fb.c
@@ -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)
{
@@ -189,6 +193,68 @@ vt_fb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
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;
+ int c, l, bpp;
+ u_long line;
uint8_t b, m;
const uint8_t *ch;
diff --git a/sys/dev/vt/hw/fb/vt_fb.h b/sys/dev/vt/hw/fb/vt_fb.h
index 9b3aa0d..10dd238 100644
--- a/sys/dev/vt/hw/fb/vt_fb.h
+++ b/sys/dev/vt/hw/fb/vt_fb.h
@@ -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_ */
OpenPOWER on IntegriCloud