This implements a new framebuffer console (based on efifb) for amd64
devices running Coreboot, which do not have otherwise working EFI,
VGA text, inteldrm, or serial console.  So mostly just Skylake
Chromebooks.

This is required for my HP Chromebook 13 (and would have previously
been required for the Broadwell Chromebook Pixel 2015) since SeaBIOS
only handles printing text on Coreboot's framebuffer while at the
bootloader.  Once the kernel loads and tries to find a vga device,
it would fail and print nothing on the screen.  With this driver I
get a fully working console and working X11 via the wsfb driver.

I've tested this on a couple non-Chromebook machines, including my
APU which is also using Coreboot, but since that has a serial
console, this driver does not try to attach.


Index: dev/wscons/wsconsio.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.74
diff -u -p -u -p -r1.74 wsconsio.h
--- dev/wscons/wsconsio.h       30 Mar 2016 23:34:12 -0000      1.74
+++ dev/wscons/wsconsio.h       10 Jun 2016 17:35:38 -0000
@@ -348,6 +348,7 @@ struct wsmouse_calibcoords {
 #define                WSDISPLAY_TYPE_INTELDRM 69      /* Intel KMS 
framebuffer */
 #define                WSDISPLAY_TYPE_RADEONDRM 70     /* ATI Radeon KMS 
framebuffer */
 #define                WSDISPLAY_TYPE_EFIFB    71      /* EFI framebuffer */
+#define                WSDISPLAY_TYPE_CBFB     72      /* Coreboot framebuffer 
*/
 
 /* Basic display information.  Not applicable to all display types. */
 struct wsdisplay_fbinfo {
Index: arch/amd64/amd64/cbfb.c
===================================================================
RCS file: arch/amd64/amd64/cbfb.c
diff -N arch/amd64/amd64/cbfb.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/amd64/amd64/cbfb.c     10 Jun 2016 17:35:38 -0000
@@ -0,0 +1,447 @@
+/*     $OpenBSD$ */
+
+/*
+ * Coreboot framebuffer console driver
+ *
+ * Copyright (c) 2016 joshua stein <j...@openbsd.org>
+ * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+#include <machine/bus.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/rasops/rasops.h>
+#include <dev/pci/pcivar.h>
+
+#include <machine/cbfbvar.h>
+
+/* coreboot tables */
+
+struct cb_header {
+       union {
+               uint8_t signature[4]; /* "LBIO" */
+               uint32_t signature32;
+       };
+       uint32_t        header_bytes;
+       uint32_t        header_checksum;
+       uint32_t        table_bytes;
+       uint32_t        table_checksum;
+       uint32_t        table_entries;
+};
+
+struct cb_framebuffer {
+       uint64_t        physical_address;
+       uint32_t        x_resolution;
+       uint32_t        y_resolution;
+       uint32_t        bytes_per_line;
+       uint8_t         bits_per_pixel;
+       uint8_t         red_mask_pos;
+       uint8_t         red_mask_size;
+       uint8_t         green_mask_pos;
+       uint8_t         green_mask_size;
+       uint8_t         blue_mask_pos;
+       uint8_t         blue_mask_size;
+       uint8_t         reserved_mask_pos;
+       uint8_t         reserved_mask_size;
+};
+
+struct cb_entry {
+       uint32_t        tag;
+#define CB_TAG_VERSION          0x0004
+#define CB_TAG_FORWARD          0x0011
+#define CB_TAG_FRAMEBUFFER      0x0012
+       uint32_t        size;
+       union {
+               char    string[0];
+               uint64_t forward;
+               struct cb_framebuffer fb;
+       } u;
+};
+
+struct cbfb {
+       struct rasops_info rinfo;
+       int              depth;
+       paddr_t          paddr;
+       psize_t          psize;
+
+       struct cb_framebuffer    table_cbfb;
+};
+
+struct cbfb_softc {
+       struct device    sc_dev;
+       struct cbfb     *sc_fb;
+};
+
+int     cbfb_match(struct device *, void *, void *);
+void    cbfb_attach(struct device *, struct device *, void *);
+void    cbfb_rasops_preinit(struct cbfb *);
+int     cbfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
+paddr_t         cbfb_mmap(void *, off_t, int);
+int     cbfb_alloc_screen(void *, const struct wsscreen_descr *, void **,
+           int *, int *, long *);
+void    cbfb_free_screen(void *, void *);
+int     cbfb_show_screen(void *, void *, int, void (*cb) (void *, int, int),
+           void *);
+int     cbfb_list_font(void *, struct wsdisplay_font *);
+int     cbfb_load_font(void *, void *, struct wsdisplay_font *);
+
+int     cb_parse_table(paddr_t);
+
+struct cfattach cbfb_ca = {
+       sizeof(struct cbfb_softc), cbfb_match, cbfb_attach, NULL
+};
+
+#define        CBFB_WIDTH      100
+#define        CBFB_HEIGHT     31
+
+struct wsdisplay_charcell cbfb_bs[CBFB_HEIGHT * CBFB_WIDTH];
+
+struct wsscreen_descr cbfb_std_descr = { "std" };
+
+const struct wsscreen_descr *cbfb_descrs[] = {
+       &cbfb_std_descr
+};
+
+const struct wsscreen_list cbfb_screen_list = {
+       nitems(cbfb_descrs), cbfb_descrs
+};
+
+struct wsdisplay_accessops cbfb_accessops = {
+       .ioctl = cbfb_ioctl,
+       .mmap = cbfb_mmap,
+       .alloc_screen = cbfb_alloc_screen,
+       .free_screen = cbfb_free_screen,
+       .show_screen = cbfb_show_screen,
+       .load_font = cbfb_load_font,
+       .list_font = cbfb_list_font
+};
+
+struct cfdriver cbfb_cd = {
+       NULL, "cbfb", DV_DULL
+};
+
+struct cbfb cbfb_console;
+
+int
+cbfb_match(struct device *parent, void *cf, void *aux)
+{
+       struct cbfb_attach_args *cbaa = aux;
+
+       if (strcmp(cbaa->cbfbaa_name, cbfb_cd.cd_name) == 0 && cbfb_found())
+               return (1);
+
+       return (0);
+}
+
+int
+cbfb_found(void)
+{
+       return !!(cbfb_console.paddr);
+}
+
+void
+cbfb_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct cbfb             *fb;
+       struct cbfb_softc       *sc = (struct cbfb_softc *)self;
+       struct wsemuldisplaydev_attach_args aa;
+       struct rasops_info      *ri;
+       int                      ccol = 0, crow = 0;
+       bus_space_tag_t          iot = X86_BUS_SPACE_MEM;
+       bus_space_handle_t       ioh;
+       long                     defattr;
+
+       printf(": %dx%d, %d bpp\n",
+           cbfb_console.table_cbfb.x_resolution,
+           cbfb_console.table_cbfb.y_resolution,
+           cbfb_console.table_cbfb.bits_per_pixel);
+
+       aa.console = 1;
+       fb = sc->sc_fb = &cbfb_console;
+       ri = &fb->rinfo;
+       ccol = ri->ri_ccol;
+       crow = ri->ri_crow;
+
+       if (bus_space_map(iot, fb->paddr, fb->psize,
+           BUS_SPACE_MAP_PREFETCHABLE | BUS_SPACE_MAP_LINEAR, &ioh) == 0)
+               ri->ri_origbits = bus_space_vaddr(iot, ioh);
+
+       cbfb_rasops_preinit(fb);
+       ri->ri_flg &= ~RI_CLEAR;
+       ri->ri_flg |= RI_VCONS | RI_WRONLY;
+
+       rasops_init(ri, cbfb_std_descr.nrows, cbfb_std_descr.ncols);
+
+       aa.scrdata = &cbfb_screen_list;
+       aa.accessops = &cbfb_accessops;
+       aa.accesscookie = sc;
+       aa.defaultscreens = 0;
+
+       ri->ri_ops.alloc_attr(ri->ri_active, 0, 0, 0, &defattr);
+       wsdisplay_cnattach(&cbfb_std_descr, ri->ri_active, ccol, crow, defattr);
+
+       config_found(self, &aa, wsemuldisplaydevprint);
+}
+
+void
+cbfb_rasops_preinit(struct cbfb *cbfb)
+{
+#define bmnum(_x) (fls(_x) - ffs(_x) + 1)
+#define bmpos(_x) (ffs(_x) - 1)
+       struct rasops_info      *ri = &cbfb->rinfo;
+
+       ri->ri_width = cbfb->table_cbfb.x_resolution;
+       ri->ri_height = cbfb->table_cbfb.y_resolution;
+       ri->ri_depth = cbfb->depth;
+       ri->ri_stride = cbfb->table_cbfb.bytes_per_line;
+       ri->ri_rnum = cbfb->table_cbfb.red_mask_size;
+       ri->ri_rpos = cbfb->table_cbfb.red_mask_pos;
+       ri->ri_gnum = cbfb->table_cbfb.green_mask_size;
+       ri->ri_gpos = cbfb->table_cbfb.green_mask_pos;
+       ri->ri_bnum = cbfb->table_cbfb.blue_mask_size;
+       ri->ri_bpos = cbfb->table_cbfb.blue_mask_pos;
+}
+
+int
+cbfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+       struct cbfb_softc       *sc = v;
+       struct cbfb             *fb = sc->sc_fb;
+       struct rasops_info      *ri = &fb->rinfo;
+       struct wsdisplay_fbinfo *wdf;
+
+       switch (cmd) {
+       case WSDISPLAYIO_GTYPE:
+               *(u_int *)data = WSDISPLAY_TYPE_CBFB;
+               break;
+       case WSDISPLAYIO_GINFO:
+               wdf = (struct wsdisplay_fbinfo *)data;
+               wdf->width = ri->ri_width;
+               wdf->height = ri->ri_height;
+               wdf->depth = ri->ri_depth;
+               wdf->cmsize = 0;        /* color map is unavailable */
+               break;
+       case WSDISPLAYIO_LINEBYTES:
+               *(u_int *)data = ri->ri_stride;
+               break;
+       case WSDISPLAYIO_SMODE:
+               break;
+       case WSDISPLAYIO_GETSUPPORTEDDEPTH:
+               switch (ri->ri_depth) {
+               case 32:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
+                       break;
+               case 24:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_24_24;
+                       break;
+               case 16:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_16;
+                       break;
+               case 15:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_15;
+                       break;
+               case 8:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_8;
+                       break;
+               case 4:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_4;
+                       break;
+               case 1:
+                       *(u_int *)data = WSDISPLAYIO_DEPTH_1;
+                       break;
+               default:
+                       return (-1);
+               }
+               break;
+       default:
+               return (-1);
+       }
+
+       return (0);
+}
+
+paddr_t
+cbfb_mmap(void *v, off_t off, int prot)
+{
+       struct cbfb_softc       *sc = v;
+
+       if (off < 0 || off >= sc->sc_fb->psize)
+               return (-1);
+
+       return ((sc->sc_fb->paddr + off) | PMAP_WC);
+}
+
+int
+cbfb_alloc_screen(void *v, const struct wsscreen_descr *descr,
+    void **cookiep, int *curxp, int *curyp, long *attrp)
+{
+       struct cbfb_softc       *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       return rasops_alloc_screen(ri, cookiep, curxp, curyp, attrp);
+}
+
+void
+cbfb_free_screen(void *v, void *cookie)
+{
+       struct cbfb_softc       *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       rasops_free_screen(ri, cookie);
+}
+
+int
+cbfb_show_screen(void *v, void *cookie, int waitok,
+    void (*cb) (void *, int, int), void *cb_arg)
+{
+       struct cbfb_softc       *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       return rasops_show_screen(ri, cookie, waitok, cb, cb_arg);
+}
+
+int
+cbfb_load_font(void *v, void *cookie, struct wsdisplay_font *font)
+{
+       struct cbfb_softc       *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       return (rasops_load_font(ri, cookie, font));
+}
+
+int
+cbfb_list_font(void *v, struct wsdisplay_font *font)
+{
+       struct cbfb_softc       *sc = v;
+       struct rasops_info      *ri = &sc->sc_fb->rinfo;
+
+       return (rasops_list_font(ri, font));
+}
+
+int
+cbfb_cnattach(void)
+{
+       if (cb_parse_table((paddr_t)0x0) || !cbfb_console.paddr)
+               return (-1);
+
+       return (0);
+}
+
+int
+cbfb_is_console(struct pci_attach_args *pa)
+{
+       return !!(cbfb_console.paddr);
+}
+
+void
+cbfb_cndetach(void)
+{
+       cbfb_console.paddr = 0;
+}
+
+static uint16_t
+cb_checksum(const void *addr, unsigned size)
+{
+       const uint16_t *p = addr;
+       unsigned i, n = size / 2;
+       uint32_t sum = 0;
+
+       for (i = 0; i < n; i++)
+               sum += p[i];
+
+       sum = (sum >> 16) + (sum & 0xffff);
+       sum += (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return (uint16_t)sum;
+}
+
+static void
+cb_fb_init(struct cb_framebuffer *table_cbfb)
+{
+       struct cbfb             *cbfb;
+       struct rasops_info      *ri = &cbfb->rinfo;
+       long                     defattr = 0;
+
+       memset(&cbfb_console, 0, sizeof(cbfb_console));
+       memcpy(&cbfb_console.table_cbfb, table_cbfb,
+           sizeof(struct cb_framebuffer));
+
+       cbfb = &cbfb_console;
+       cbfb->paddr = table_cbfb->physical_address;
+       cbfb->depth = table_cbfb->bits_per_pixel;
+       cbfb->psize = table_cbfb->y_resolution * table_cbfb->bytes_per_line;
+
+       ri->ri_bits = (u_char *)PMAP_DIRECT_MAP(cbfb->paddr);
+
+       cbfb_rasops_preinit(cbfb);
+
+       ri->ri_bs = cbfb_bs;
+       ri->ri_flg = RI_CLEAR | RI_CENTER | RI_WRONLY;
+       rasops_init(ri, CBFB_HEIGHT, CBFB_WIDTH);
+       cbfb_std_descr.ncols = ri->ri_cols;
+       cbfb_std_descr.nrows = ri->ri_rows;
+       cbfb_std_descr.textops = &ri->ri_ops;
+       cbfb_std_descr.fontwidth = ri->ri_font->fontwidth;
+       cbfb_std_descr.fontheight = ri->ri_font->fontheight;
+       cbfb_std_descr.capabilities = ri->ri_caps;
+
+       ri->ri_ops.alloc_attr(ri, 0, 0, 0, &defattr);
+       wsdisplay_cnattach(&cbfb_std_descr, ri, 0, 0, defattr);
+}
+
+int
+cb_parse_table(paddr_t addr)
+{
+       int i, j;
+
+       for (i = 0; i < (4 * 1024); i += 16) {
+               struct cb_header *cbh;
+               struct cb_entry *cbe;
+               void *cbtable;
+
+               cbh = (struct cb_header *)(PMAP_DIRECT_MAP(addr + i));
+               if (memcmp(cbh->signature, "LBIO", 4) != 0)
+                       continue;
+
+               if (!cbh->header_bytes)
+                       continue;
+
+               if (cb_checksum(cbh, sizeof(*cbh)) != 0)
+                       return (-1);
+
+               cbtable = (void *)PMAP_DIRECT_MAP(addr + i + cbh->header_bytes);
+
+               for (j = 0; j < cbh->table_bytes; j += cbe->size) {
+                       cbe = (struct cb_entry *)((char *)cbtable + j);
+
+                       switch (cbe->tag) {
+                       case CB_TAG_FORWARD:
+                               return cb_parse_table(cbe->u.forward);
+
+                       case CB_TAG_FRAMEBUFFER:
+                               cb_fb_init(&cbe->u.fb);
+                               break;
+                       }
+               }
+       }
+
+       return (0);
+}
Index: arch/amd64/amd64/mainbus.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/mainbus.c,v
retrieving revision 1.36
diff -u -p -u -p -r1.36 mainbus.c
--- arch/amd64/amd64/mainbus.c  12 Dec 2015 12:33:49 -0000      1.36
+++ arch/amd64/amd64/mainbus.c  10 Jun 2016 17:35:38 -0000
@@ -52,6 +52,7 @@
 #include "vmm.h"
 #include "pvbus.h"
 #include "efifb.h"
+#include "cbfb.h"
 
 #include <machine/cpuvar.h>
 #include <machine/i82093var.h>
@@ -74,6 +75,10 @@
 #include <machine/efifbvar.h>
 #endif
 
+#if NCBFB > 0
+#include <machine/cbfbvar.h>
+#endif
+
 int    mainbus_match(struct device *, void *, void *);
 void   mainbus_attach(struct device *, struct device *, void *);
 
@@ -105,6 +110,9 @@ union mainbus_attach_args {
 #if NEFIFB > 0
        struct efifb_attach_args mba_eaa;
 #endif
+#if NCBFB > 0
+       struct cbfb_attach_args mba_cbfbaa;
+#endif
 };
 
 /*
@@ -255,6 +263,13 @@ mainbus_attach(struct device *parent, st
 #if NEFIFB > 0
        if (bios_efiinfo != NULL) {
                mba.mba_eaa.eaa_name = "efifb";
+               config_found(self, &mba, mainbus_print);
+       }
+#endif
+
+#if NCBFB > 0
+       if (cbfb_found()) {
+               mba.mba_cbfbaa.cbfbaa_name = "cbfb";
                config_found(self, &mba, mainbus_print);
        }
 #endif
Index: arch/amd64/amd64/wscons_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/wscons_machdep.c,v
retrieving revision 1.12
diff -u -p -u -p -r1.12 wscons_machdep.c
--- arch/amd64/amd64/wscons_machdep.c   6 Mar 2016 22:41:24 -0000       1.12
+++ arch/amd64/amd64/wscons_machdep.c   10 Jun 2016 17:35:38 -0000
@@ -75,6 +75,10 @@
 #if NEFIFB > 0
 #include <machine/efifbvar.h>
 #endif
+#include "cbfb.h"
+#if NCBFB > 0
+#include <machine/cbfbvar.h>
+#endif
 
 int    wscn_video_init(void);
 void   wscn_input_init(int);
@@ -145,6 +149,10 @@ wscn_video_init(void)
 #endif
 #if (NVGA > 0)
        if (vga_cnattach(X86_BUS_SPACE_IO, X86_BUS_SPACE_MEM, -1, 1) == 0)
+               return (0);
+#endif
+#if (NCBFB > 0)
+       if (cbfb_cnattach() == 0)
                return (0);
 #endif
 #if (NPCDISPLAY > 0)
Index: arch/amd64/conf/GENERIC
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
retrieving revision 1.419
diff -u -p -u -p -r1.419 GENERIC
--- arch/amd64/conf/GENERIC     1 Jun 2016 09:48:20 -0000       1.419
+++ arch/amd64/conf/GENERIC     10 Jun 2016 17:35:38 -0000
@@ -358,6 +358,9 @@ lpt*        at puc?
 efifb0         at mainbus?             # EFI Framebuffer
 wsdisplay0     at efifb? console 1
 
+cbfb0          at mainbus?             # Coreboot Framebuffer
+wsdisplay0     at cbfb? console 1
+
 #bha*  at pci?                         # BusLogic [57]4X SCSI controllers
 ahc*   at pci?                         # Adaptec 2940 SCSI controllers
 jmb*   at pci?                         # JMicron JMB36x controllers
Index: arch/amd64/conf/files.amd64
===================================================================
RCS file: /cvs/src/sys/arch/amd64/conf/files.amd64,v
retrieving revision 1.85
diff -u -p -u -p -r1.85 files.amd64
--- arch/amd64/conf/files.amd64 8 Jan 2016 15:54:13 -0000       1.85
+++ arch/amd64/conf/files.amd64 10 Jun 2016 17:35:38 -0000
@@ -114,6 +114,13 @@ attach efifb at mainbus
 file arch/amd64/amd64/efifb.c                  efifb needs-flag
 
 #
+# Coreboot Framebuffer
+#
+device cbfb: wsemuldisplaydev, rasops32, rasops16, rasops8, rasops4
+attach cbfb at mainbus
+file arch/amd64/amd64/cbfb.c                   cbfb needs-flag
+
+#
 # PCI drivers
 #
 
Index: arch/amd64/include/cbfbvar.h
===================================================================
RCS file: arch/amd64/include/cbfbvar.h
diff -N arch/amd64/include/cbfbvar.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/amd64/include/cbfbvar.h        10 Jun 2016 17:35:38 -0000
@@ -0,0 +1,34 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2016 joshua stein <j...@openbsd.org>
+ * Copyright (c) 2015 YASUOKA Masahiko <yasu...@yasuoka.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_CBFB_H_
+#define _MACHINE_CBFB_H_
+
+struct cbfb_attach_args {
+       const char      *cbfbaa_name;
+};
+
+struct pci_attach_args;
+
+int cbfb_found(void);
+int cbfb_cnattach(void);
+int cbfb_is_console(struct pci_attach_args *);
+void cbfb_cndetach(void);
+
+#endif /* _MACHINE_CBFB_H_ */

Reply via email to