1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-25 11:37:56 +00:00

Merge VT(9) project (a.k.a. newcons).

Reviewed by:	nwhitehorn
MFC_to_10_after:	re approval

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Aleksandr Rybalko 2013-12-05 22:38:53 +00:00
parent 5c79f1f9df
commit 27cf7d04ef
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=259016
48 changed files with 10217 additions and 103 deletions

View File

@ -82,7 +82,7 @@ pccarddevs.h standard \
compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \
no-obj no-implicit-rule before-depend \
clean "pccarddevs.h"
teken_state.h optional sc \
teken_state.h optional sc | vt \
dependency "$S/teken/gensequences $S/teken/sequences" \
compile-with "${AWK} -f $S/teken/gensequences $S/teken/sequences > teken_state.h" \
no-obj no-implicit-rule before-depend \
@ -1396,6 +1396,8 @@ dev/ex/if_ex_isa.c optional ex isa
dev/ex/if_ex_pccard.c optional ex pccard
dev/exca/exca.c optional cbb
dev/fatm/if_fatm.c optional fatm pci
dev/fb/fbd.c optional fbd | vt
dev/fb/fb_if.m optional fbd | vt
dev/fb/splash.c optional splash
dev/fdt/fdt_common.c optional fdt
dev/fdt/fdt_ic_if.m optional fdt
@ -2461,6 +2463,17 @@ dev/vge/if_vge.c optional vge
dev/vkbd/vkbd.c optional vkbd
dev/vr/if_vr.c optional vr pci
dev/vt/colors/vt_termcolors.c optional vt
dev/vt/font/vt_font_default.c optional vt
dev/vt/font/vt_mouse_cursor.c optional vt
dev/vt/hw/fb/vt_fb.c optional vt
dev/vt/hw/vga/vga.c optional vt vt_vga
dev/vt/logo/logo_freebsd.c optional vt
dev/vt/vt_buf.c optional vt
dev/vt/vt_consolectl.c optional vt
dev/vt/vt_core.c optional vt
dev/vt/vt_font.c optional vt
dev/vt/vt_sysmouse.c optional vt
dev/vte/if_vte.c optional vte pci
dev/vx/if_vx.c optional vx
dev/vx/if_vx_eisa.c optional vx eisa
@ -2897,6 +2910,7 @@ kern/subr_sleepqueue.c standard
kern/subr_smp.c standard
kern/subr_stack.c optional ddb | stack | ktr
kern/subr_taskqueue.c standard
kern/subr_terminal.c optional vt
kern/subr_trap.c standard
kern/subr_turnstile.c standard
kern/subr_uio.c standard
@ -3796,7 +3810,7 @@ security/mac_portacl/mac_portacl.c optional mac_portacl
security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids
security/mac_stub/mac_stub.c optional mac_stub
security/mac_test/mac_test.c optional mac_test
teken/teken.c optional sc
teken/teken.c optional sc | vt
ufs/ffs/ffs_alloc.c optional ffs
ufs/ffs/ffs_balloc.c optional ffs
ufs/ffs/ffs_inode.c optional ffs

View File

@ -241,7 +241,7 @@ dev/hyperv/vmbus/hv_connection.c optional hyperv
dev/hyperv/vmbus/hv_hv.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
dev/kbd/kbd.c optional atkbd | sc | ukbd
dev/kbd/kbd.c optional atkbd | sc | ukbd | vt
dev/lindev/full.c optional lindev
dev/lindev/lindev.c optional lindev
dev/nfe/if_nfe.c optional nfe pci

View File

@ -62,7 +62,7 @@ crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
dev/fb/fb.c optional sc
dev/hwpmc/hwpmc_arm.c optional hwpmc
dev/kbd/kbd.c optional sc
dev/kbd/kbd.c optional sc | vt
dev/syscons/scgfbrndr.c optional sc
dev/syscons/scterm-teken.c optional sc
dev/syscons/scvtb.c optional sc

View File

@ -249,7 +249,7 @@ dev/ipmi/ipmi_smbios.c optional ipmi
dev/ipmi/ipmi_ssif.c optional ipmi smbus
dev/ipmi/ipmi_pci.c optional ipmi pci
dev/ipmi/ipmi_linux.c optional ipmi compat_linux
dev/kbd/kbd.c optional atkbd | sc | ukbd
dev/kbd/kbd.c optional atkbd | sc | ukbd | vt
dev/le/if_le_isa.c optional le isa
dev/lindev/full.c optional lindev
dev/lindev/lindev.c optional lindev
@ -293,6 +293,7 @@ dev/viawd/viawd.c optional viawd
dev/vmware/vmxnet3/if_vmx.c optional vmx
dev/acpica/acpi_if.m standard
dev/acpi_support/acpi_wmi_if.m standard
dev/vt/hw/xboxfb/xboxfb.c optional vt_xboxfb
dev/wbwd/wbwd.c optional wbwd
dev/wpi/if_wpi.c optional wpi
dev/isci/isci.c optional isci

View File

@ -35,7 +35,7 @@ dev/iicbus/ad7417.c optional ad7417 powermac
dev/iicbus/ds1631.c optional ds1631 powermac
dev/iicbus/ds1775.c optional ds1775 powermac
dev/iicbus/max6690.c optional max6690 powermac
dev/kbd/kbd.c optional sc
dev/kbd/kbd.c optional sc | vt
dev/nand/nfc_fsl.c optional nand mpc85xx
# ofw can be either aim or fdt: fdt case handled in files. aim only powerpc specific.
dev/ofw/openfirm.c optional aim
@ -65,6 +65,7 @@ dev/tsec/if_tsec.c optional tsec
dev/tsec/if_tsec_fdt.c optional tsec fdt
dev/uart/uart_cpu_powerpc.c optional uart
dev/usb/controller/ehci_fsl.c optional ehci mpc85xx
dev/vt/hw/ofwfb/ofwfb.c optional vt aim
kern/kern_clocksource.c standard
kern/subr_dummy_vdso_tc.c standard
kern/syscalls.c optional ktr

View File

@ -39,7 +39,7 @@ dev/fb/fb.c optional sc
dev/fb/gallant12x22.c optional sc
dev/fb/machfb.c optional machfb sc
dev/hwpmc/hwpmc_sparc64.c optional hwpmc
dev/kbd/kbd.c optional atkbd | sc | ukbd
dev/kbd/kbd.c optional atkbd | sc | ukbd | vt
dev/le/if_le_lebuffer.c optional le sbus
dev/le/if_le_ledma.c optional le sbus
dev/le/lebuffer_sbus.c optional le sbus
@ -59,7 +59,8 @@ dev/syscons/scgfbrndr.c optional sc
dev/syscons/scterm-teken.c optional sc
dev/syscons/scvtb.c optional sc
dev/uart/uart_cpu_sparc64.c optional uart
dev/uart/uart_kbd_sun.c optional uart sc
dev/uart/uart_kbd_sun.c optional uart sc | vt
dev/vt/hw/ofwfb/ofwfb.c optional vt
kern/kern_clocksource.c standard
kern/subr_dummy_vdso_tc.c standard
kern/syscalls.c optional ktr

View File

@ -340,7 +340,7 @@ CFLAGS+= ${CONF_CFLAGS}
MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \
dev/agp/agp_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
dev/gpio/gpio_if.m dev/gpio/gpiobus_if.m \
dev/fb/fb_if.m dev/gpio/gpio_if.m dev/gpio/gpiobus_if.m \
dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \
dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \

View File

@ -731,8 +731,10 @@ SAFE_DEBUG opt_safe.h
SAFE_NO_RNG opt_safe.h
SAFE_RNDTEST opt_safe.h
# syscons options
# syscons/vt options
MAXCONS opt_syscons.h
VT_FB_DEFAULT_WIDTH opt_syscons.h
VT_FB_DEFAULT_HEIGHT opt_syscons.h
SC_ALT_MOUSE_IMAGE opt_syscons.h
SC_CUT_SPACES2TABS opt_syscons.h
SC_CUT_SEPCHARS opt_syscons.h

View File

@ -36,6 +36,41 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drm_fb_helper.h>
#include <dev/drm2/drm_crtc_helper.h>
#if defined(__FreeBSD__)
struct vt_kms_softc {
struct drm_fb_helper *fb_helper;
struct task fb_mode_task;
};
static fb_enter_t vt_kms_postswitch;
static void vt_restore_fbdev_mode(void *, int);
/* Call restore out of vt(9) locks. */
static void
vt_restore_fbdev_mode(void *arg, int pending)
{
struct drm_fb_helper *fb_helper;
struct vt_kms_softc *sc;
sc = (struct vt_kms_softc *)arg;
fb_helper = sc->fb_helper;
sx_xlock(&fb_helper->dev->mode_config.mutex);
drm_fb_helper_restore_fbdev_mode(fb_helper);
sx_xunlock(&fb_helper->dev->mode_config.mutex);
}
static int
vt_kms_postswitch(void *arg)
{
struct vt_kms_softc *sc;
sc = (struct vt_kms_softc *)arg;
taskqueue_enqueue_fast(taskqueue_thread, &sc->fb_mode_task);
return (0);
}
#endif
static DRM_LIST_HEAD(kernel_fb_helper_list);
/* simple single crtc case helper function */
@ -216,6 +251,10 @@ static int
fb_get_options(const char *connector_name, char **option)
{
/*
* TODO: store mode options pointer in ${option} for connector with
* name ${connector_name}
*/
return (1);
}
@ -892,11 +931,13 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
int new_fb = 0;
int crtc_count = 0;
int i;
#if 0
struct fb_info *info;
#endif
struct drm_fb_helper_surface_size sizes;
int gamma_size = 0;
#if defined(__FreeBSD__)
struct vt_kms_softc *sc;
device_t kdev;
#endif
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
sizes.surface_depth = 24;
@ -973,8 +1014,21 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (new_fb < 0)
return new_fb;
#if 0
#if defined(__FreeBSD__)
sc = malloc(sizeof(struct vt_kms_softc), DRM_MEM_KMS,
M_WAITOK | M_ZERO);
sc->fb_helper = fb_helper;
TASK_INIT(&sc->fb_mode_task, 0, vt_restore_fbdev_mode, sc);
info = fb_helper->fbdev;
info->fb_name = device_get_nameunit(fb_helper->dev->device);
info->fb_depth = fb_helper->fb->bits_per_pixel;
info->fb_height = fb_helper->fb->height;
info->fb_width = fb_helper->fb->width;
info->fb_stride = fb_helper->fb->pitches[0];
info->fb_priv = sc;
info->enter = &vt_kms_postswitch;
#endif
/* set the fb pointer */
@ -982,7 +1036,18 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
}
#if 0
#if defined(__FreeBSD__)
if (new_fb) {
device_t fbd;
int ret;
kdev = fb_helper->dev->device;
fbd = device_add_child(kdev, "fbd", device_get_unit(kdev));
ret = device_probe_and_attach(fbd);
if (ret != 0)
DRM_ERROR("Failed to attach fbd device: %d\n", ret);
}
#else
if (new_fb) {
info->var.pixclock = 0;
if (register_framebuffer(info) < 0) {
@ -1006,7 +1071,6 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
if (new_fb)
list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
#endif
return 0;
}

View File

@ -6,6 +6,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/fbio.h>
#if _BYTE_ORDER == _BIG_ENDIAN
#define __BIG_ENDIAN 4321
#else

View File

@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drm_pciids.h>
#include <dev/drm2/i915/intel_drv.h>
#include "fb_if.h"
/* drv_PCI_IDs comes from drm_pciids.h, generated from drm_pciids.txt. */
static drm_pci_id_list_t i915_pciidlist[] = {
i915_PCI_IDS
@ -380,6 +382,25 @@ i915_attach(device_t kdev)
return (drm_attach(kdev, i915_pciidlist));
}
static struct fb_info *
i915_fb_helper_getinfo(device_t kdev)
{
struct intel_fbdev *ifbdev;
drm_i915_private_t *dev_priv;
struct drm_device *dev;
struct fb_info *info;
dev = device_get_softc(kdev);
dev_priv = dev->dev_private;
ifbdev = dev_priv->fbdev;
if (ifbdev == NULL)
return (NULL);
info = ifbdev->helper.fbdev;
return (info);
}
const struct intel_device_info *
i915_get_device_id(int device)
{
@ -400,6 +421,10 @@ static device_method_t i915_methods[] = {
DEVMETHOD(device_suspend, i915_suspend),
DEVMETHOD(device_resume, i915_resume),
DEVMETHOD(device_detach, drm_detach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, i915_fb_helper_getinfo),
DEVMETHOD_END
};

View File

@ -41,8 +41,8 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
struct drm_device *dev = ifbdev->helper.dev;
#if 0
struct drm_i915_private *dev_priv = dev->dev_private;
struct fb_info *info;
#endif
struct fb_info *info;
struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd;
struct drm_i915_gem_object *obj;
@ -86,6 +86,16 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
}
info->par = ifbdev;
#else
info = malloc(sizeof(struct fb_info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
info->fb_size = size;
info->fb_bpp = sizes->surface_bpp;
info->fb_width = sizes->fb_width;
info->fb_height = sizes->fb_height;
info->fb_pbase = dev->agp->base + obj->gtt_offset;
info->fb_vbase = (vm_offset_t)pmap_mapdev_attr(info->fb_pbase, size,
PAT_WRITE_COMBINING);
#endif
ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
@ -95,8 +105,8 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
fb = &ifbdev->ifb.base;
ifbdev->helper.fb = fb;
#if 0
ifbdev->helper.fbdev = info;
#if 0
strcpy(info->fix.id, "inteldrmfb");
@ -135,9 +145,8 @@ static int intelfb_create(struct intel_fbdev *ifbdev,
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
#endif
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n",
fb->width, fb->height,
DRM_DEBUG_KMS("allocated %dx%d (s %dbits) fb: 0x%08x, bo %p\n",
fb->width, fb->height, fb->depth,
obj->gtt_offset, obj);
DRM_UNLOCK(dev);

View File

@ -2041,6 +2041,9 @@ void radeon_pm_acpi_event_handler(struct radeon_device *rdev);
int radeon_ttm_init(struct radeon_device *rdev);
void radeon_ttm_fini(struct radeon_device *rdev);
/* radeon_fb.c */
struct fb_info * radeon_fb_helper_getinfo(device_t kdev);
/* r600.c */
int r600_ih_ring_alloc(struct radeon_device *rdev);
void r600_ih_ring_fini(struct radeon_device *rdev);

View File

@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/drm_pciids.h>
#include "fb_if.h"
/*
* KMS wrapper.
@ -495,6 +496,8 @@ radeon_resume(device_t kdev)
return (-ret);
}
extern struct fb_info * radeon_fb_helper_getinfo(device_t kdev);
static device_method_t radeon_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, radeon_probe),
@ -502,6 +505,10 @@ static device_method_t radeon_methods[] = {
DEVMETHOD(device_suspend, radeon_suspend),
DEVMETHOD(device_resume, radeon_resume),
DEVMETHOD(device_detach, drm_detach),
/* Framebuffer service methods */
DEVMETHOD(fb_getinfo, radeon_fb_helper_getinfo),
DEVMETHOD_END
};

View File

@ -27,6 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <machine/_inttypes.h>
#include <dev/drm2/drmP.h>
#include <dev/drm2/drm_crtc.h>
#include <dev/drm2/drm_crtc_helper.h>
@ -46,7 +48,7 @@ struct radeon_fbdev {
struct radeon_device *rdev;
};
#ifdef DUMBBELL_WIP
#if defined(__linux__)
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
@ -60,7 +62,7 @@ static struct fb_ops radeonfb_ops = {
.fb_debug_enter = drm_fb_helper_debug_enter,
.fb_debug_leave = drm_fb_helper_debug_leave,
};
#endif /* DUMBBELL_WIP */
#endif
int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
@ -191,20 +193,13 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
struct drm_fb_helper_surface_size *sizes)
{
struct radeon_device *rdev = rfbdev->rdev;
#ifdef DUMBBELL_WIP
struct fb_info *info;
#endif /* DUMBBELL_WIP */
struct drm_framebuffer *fb = NULL;
struct drm_mode_fb_cmd2 mode_cmd;
struct drm_gem_object *gobj = NULL;
struct radeon_bo *rbo = NULL;
#ifdef DUMBBELL_WIP
device_t device = rdev->dev;
#endif /* DUMBBELL_WIP */
int ret;
#ifdef DUMBBELL_WIP
unsigned long tmp;
#endif /* DUMBBELL_WIP */
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
@ -224,16 +219,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
rbo = gem_to_radeon_bo(gobj);
#ifdef DUMBBELL_WIP
/* okay we have an object now allocate the framebuffer */
info = framebuffer_alloc(0, device);
if (info == NULL) {
ret = -ENOMEM;
goto out_unref;
}
info->par = rfbdev;
#endif /* DUMBBELL_WIP */
info = malloc(sizeof(*info), DRM_MEM_KMS, M_WAITOK | M_ZERO);
ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
if (ret) {
@ -245,61 +231,29 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
/* setup helper */
rfbdev->helper.fb = fb;
#ifdef DUMBBELL_WIP
rfbdev->helper.fbdev = info;
memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
strcpy(info->fix.id, "radeondrmfb");
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &radeonfb_ops;
memset(rbo->kptr, 0x0, radeon_bo_size(rbo));
tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
info->fix.smem_start = rdev->mc.aper_base + tmp;
info->fix.smem_len = radeon_bo_size(rbo);
info->screen_base = rbo->kptr;
info->screen_size = radeon_bo_size(rbo);
info->fb_size = radeon_bo_size(rbo);
info->fb_bpp = sizes->surface_bpp;
info->fb_width = sizes->surface_width;
info->fb_height = sizes->surface_height;
info->fb_pbase = rdev->mc.aper_base + tmp;
info->fb_vbase = (vm_offset_t)rbo->kptr;
drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
/* setup aperture base/size for vesafb takeover */
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto out_unref;
}
info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
info->apertures->ranges[0].size = rdev->mc.aper_size;
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
if (info->screen_base == NULL) {
ret = -ENOSPC;
goto out_unref;
}
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
ret = -ENOMEM;
goto out_unref;
}
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
DRM_INFO("fb mappable at 0x%" PRIXPTR "\n", info->fb_pbase);
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base);
DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo));
DRM_INFO("fb depth is %d\n", fb->depth);
DRM_INFO(" pitch is %d\n", fb->pitches[0]);
vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
#endif /* DUMBBELL_WIP */
return 0;
out_unref:
if (rbo) {
/* TODO? dumbbell@ */
}
if (fb && ret) {
drm_gem_object_unreference(gobj);
@ -332,21 +286,13 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev)
static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
{
#ifdef DUMBBELL_WIP
struct fb_info *info;
#endif /* DUMBBELL_WIP */
struct radeon_framebuffer *rfb = &rfbdev->rfb;
#ifdef DUMBBELL_WIP
if (rfbdev->helper.fbdev) {
info = rfbdev->helper.fbdev;
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
free(info, DRM_MEM_KMS);
}
#endif /* DUMBBELL_WIP */
if (rfb->obj) {
DRM_UNLOCK(dev); /* Work around lock recursion. dumbbell@ */
@ -431,3 +377,22 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
return true;
return false;
}
struct fb_info *
radeon_fb_helper_getinfo(device_t kdev)
{
struct drm_device *dev;
struct radeon_device *rdev;
struct radeon_fbdev *rfbdev;
struct fb_info *info;
dev = device_get_softc(kdev);
rdev = dev->dev_private;
rfbdev = rdev->mode_info.rfbdev;
if (rfbdev == NULL)
return (NULL);
info = rfbdev->helper.fbdev;
return (info);
}

View File

@ -248,7 +248,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
(rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index))
return;
DRM_LOCK(rdev->ddev);
//DRM_LOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
sx_xlock(&rdev->pm.mclk_lock);
sx_xlock(&rdev->ring_lock);
@ -263,7 +263,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
/* needs a GPU reset dont reset here */
sx_xunlock(&rdev->ring_lock);
sx_xunlock(&rdev->pm.mclk_lock);
DRM_UNLOCK(rdev->ddev);
//DRM_UNLOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
return;
}
}
@ -299,7 +299,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev)
sx_xunlock(&rdev->ring_lock);
sx_xunlock(&rdev->pm.mclk_lock);
DRM_UNLOCK(rdev->ddev);
//DRM_UNLOCK(rdev->ddev); XXX Recursion, already locked in drm_attach/drm_load -- dumbbell@
}
static void radeon_pm_print_states(struct radeon_device *rdev)

13
sys/dev/fb/fb_if.m Normal file
View File

@ -0,0 +1,13 @@
#include <sys/bus.h>
#include <sys/fbio.h>
INTERFACE fb;
METHOD int pin_max {
device_t dev;
int *npins;
};
METHOD struct fb_info * getinfo {
device_t dev;
};

467
sys/dev/fb/fbd.c Normal file
View File

@ -0,0 +1,467 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/* Generic framebuffer */
/* TODO unlink from VT(9) */
/* TODO done normal /dev/fb methods */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/fbio.h>
#include <machine/bus.h>
#include <dev/vt/vt.h>
#include <dev/vt/hw/fb/vt_fb.h>
#include "fb_if.h"
LIST_HEAD(fb_list_head_t, fb_list_entry) fb_list_head =
LIST_HEAD_INITIALIZER(fb_list_head);
struct fb_list_entry {
struct fb_info *fb_info;
struct cdev *fb_si;
LIST_ENTRY(fb_list_entry) fb_list;
};
struct fbd_softc {
device_t sc_dev;
struct fb_info *sc_info;
};
static void fbd_evh_init(void *);
/* SI_ORDER_SECOND, just after EVENTHANDLERs initialized. */
SYSINIT(fbd_evh_init, SI_SUB_CONFIGURE, SI_ORDER_SECOND, fbd_evh_init, NULL);
static d_open_t fb_open;
static d_close_t fb_close;
static d_read_t fb_read;
static d_write_t fb_write;
static d_ioctl_t fb_ioctl;
static d_mmap_t fb_mmap;
static struct cdevsw fb_cdevsw = {
.d_version = D_VERSION,
.d_flags = D_NEEDGIANT,
.d_open = fb_open,
.d_close = fb_close,
.d_read = fb_read,
.d_write = fb_write,
.d_ioctl = fb_ioctl,
.d_mmap = fb_mmap,
.d_name = "fb",
};
static int framebuffer_dev_unit = 0;
static int
fb_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
return (0);
}
static int
fb_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
return (0);
}
static int
fb_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
struct fb_info *info;
int error;
error = 0;
info = dev->si_drv1;
switch (cmd) {
case FBIOGTYPE:
bcopy(info, (struct fbtype *)data, sizeof(struct fbtype));
break;
case FBIO_GETWINORG: /* get frame buffer window origin */
*(u_int *)data = 0;
break;
case FBIO_GETDISPSTART: /* get display start address */
((video_display_start_t *)data)->x = 0;
((video_display_start_t *)data)->y = 0;
break;
case FBIO_GETLINEWIDTH: /* get scan line width in bytes */
*(u_int *)data = info->fb_stride;
break;
case FBIO_BLANK: /* blank display */
error = 0; /* TODO */
break;
default:
error = ENOIOCTL;
break;
}
return (error);
}
static int
fb_read(struct cdev *dev, struct uio *uio, int ioflag)
{
return (0); /* XXX nothing to read, yet */
}
static int
fb_write(struct cdev *dev, struct uio *uio, int ioflag)
{
return (0); /* XXX nothing written */
}
static int
fb_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr, int nprot,
vm_memattr_t *memattr)
{
struct fb_info *info;
info = dev->si_drv1;
if (offset < info->fb_size) {
*paddr = info->fb_pbase + offset;
return (0);
}
return (EINVAL);
}
static void
vt_fb_mem_wr1(struct fb_info *sc, uint32_t o, uint8_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
*(uint8_t *)(sc->fb_vbase + o) = v;
}
static void
vt_fb_mem_wr2(struct fb_info *sc, uint32_t o, uint16_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
*(uint16_t *)(sc->fb_vbase + o) = v;
}
static void
vt_fb_mem_wr4(struct fb_info *sc, uint32_t o, uint32_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
*(uint32_t *)(sc->fb_vbase + o) = v;
}
static void
vt_fb_mem_copy(struct fb_info *sc, uint32_t offset_to, uint32_t offset_from,
uint32_t size)
{
memmove((void *)(sc->fb_vbase + offset_to), (void *)(sc->fb_vbase +
offset_from), size);
}
static void
vt_fb_indir_wr1(struct fb_info *sc, uint32_t o, uint8_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
sc->fb_write(sc->fb_priv, o, &v, 1);
}
static void
vt_fb_indir_wr2(struct fb_info *sc, uint32_t o, uint16_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
sc->fb_write(sc->fb_priv, o, &v, 2);
}
static void
vt_fb_indir_wr4(struct fb_info *sc, uint32_t o, uint32_t v)
{
KASSERT((o < sc->fb_size), ("Offset %#08x out of fb size", o));
sc->fb_write(sc->fb_priv, o, &v, 4);
}
static void
vt_fb_indir_copy(struct fb_info *sc, uint32_t offset_to, uint32_t offset_from,
uint32_t size)
{
sc->copy(sc->fb_priv, offset_to, offset_from, size);
}
int
fb_probe(struct fb_info *info)
{
if (info->fb_size == 0)
return (ENXIO);
if (info->fb_write != NULL) {
if (info->fb_write == NULL) {
return (EINVAL);
}
info->fb_flags |= FB_FLAG_NOMMAP;
info->wr1 = &vt_fb_indir_wr1;
info->wr2 = &vt_fb_indir_wr2;
info->wr4 = &vt_fb_indir_wr4;
info->copy = &vt_fb_indir_copy;
} else if (info->fb_vbase != 0) {
if (info->fb_pbase == 0)
info->fb_flags |= FB_FLAG_NOMMAP;
info->wr1 = &vt_fb_mem_wr1;
info->wr2 = &vt_fb_mem_wr2;
info->wr4 = &vt_fb_mem_wr4;
info->copy = &vt_fb_mem_copy;
} else
return (ENXIO);
return (0);
}
static int
fb_init(struct fb_list_entry *entry, int unit)
{
struct fb_info *info;
info = entry->fb_info;
entry->fb_si = make_dev(&fb_cdevsw, unit, UID_ROOT, GID_WHEEL,
0600, "fb%d", unit);
entry->fb_si->si_drv1 = info;
return (0);
}
int
fbd_list()
{
struct fb_list_entry *entry;
if (LIST_EMPTY(&fb_list_head))
return (ENOENT);
LIST_FOREACH(entry, &fb_list_head, fb_list) {
printf("FB %s @%p\n", entry->fb_info->fb_name,
(void *)entry->fb_info->fb_pbase);
}
return (0);
}
static struct fb_list_entry *
fbd_find(struct fb_info* info)
{
struct fb_list_entry *entry, *tmp;
LIST_FOREACH_SAFE(entry, &fb_list_head, fb_list, tmp) {
if (entry->fb_info == info) {
return (entry);
}
}
return (NULL);
}
int
fbd_register(struct fb_info* info)
{
struct fb_list_entry *entry;
int err, first;
first = 0;
if (LIST_EMPTY(&fb_list_head))
first++;
entry = fbd_find(info);
if (entry != NULL) {
/* XXX Update framebuffer params */
return (0);
}
err = fb_probe(info);
if (err)
return (err);
entry = malloc(sizeof(struct fb_list_entry), M_DEVBUF, M_WAITOK|M_ZERO);
entry->fb_info = info;
LIST_INSERT_HEAD(&fb_list_head, entry, fb_list);
err = fb_init(entry, framebuffer_dev_unit++);
if (err)
return (err);
if (first)
vt_fb_attach(info);
return (0);
}
int
fbd_unregister(struct fb_info* info)
{
struct fb_list_entry *entry, *tmp;
LIST_FOREACH_SAFE(entry, &fb_list_head, fb_list, tmp) {
if (entry->fb_info == info) {
LIST_REMOVE(entry, fb_list);
free(entry, M_DEVBUF);
return (0);
}
}
return (ENOENT);
}
static void
register_fb_wrap(void *arg, void *ptr)
{
fbd_register((struct fb_info *)ptr);
}
static void
unregister_fb_wrap(void *arg, void *ptr)
{
fbd_unregister((struct fb_info *)ptr);
}
static void
fbd_evh_init(void *ctx)
{
EVENTHANDLER_REGISTER(register_framebuffer, register_fb_wrap, NULL,
EVENTHANDLER_PRI_ANY);
EVENTHANDLER_REGISTER(unregister_framebuffer, unregister_fb_wrap, NULL,
EVENTHANDLER_PRI_ANY);
}
/* Newbus methods. */
static int
fbd_probe(device_t dev)
{
return (BUS_PROBE_NOWILDCARD);
}
static int
fbd_attach(device_t dev)
{
struct fbd_softc *sc;
int err;
sc = device_get_softc(dev);
sc->sc_dev = dev;
sc->sc_info = FB_GETINFO(device_get_parent(dev));
if (sc->sc_info == NULL)
return (ENXIO);
err = fbd_register(sc->sc_info);
return (err);
}
static int
fbd_detach(device_t dev)
{
struct fbd_softc *sc;
int err;
sc = device_get_softc(dev);
err = fbd_unregister(sc->sc_info);
return (err);
}
static int
fbd_suspend(device_t dev)
{
vt_fb_suspend();
return (bus_generic_suspend(dev));
}
static int
fbd_resume(device_t dev)
{
vt_fb_resume();
return (bus_generic_resume(dev));
}
static device_method_t fbd_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, fbd_probe),
DEVMETHOD(device_attach, fbd_attach),
DEVMETHOD(device_detach, fbd_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, fbd_suspend),
DEVMETHOD(device_resume, fbd_resume),
{ 0, 0 }
};
driver_t fbd_driver = {
"fbd",
fbd_methods,
sizeof(struct fbd_softc)
};
devclass_t fbd_devclass;
DRIVER_MODULE(fbd, fb, fbd_driver, fbd_devclass, 0, 0);
DRIVER_MODULE(fbd, drmn, fbd_driver, fbd_devclass, 0, 0);
MODULE_VERSION(fbd, 1);

View File

@ -0,0 +1,80 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <dev/vt/colors/vt_termcolors.h>
static struct {
unsigned char r; /* Red percentage value. */
unsigned char g; /* Green percentage value. */
unsigned char b; /* Blue percentage value. */
} color_def[16] = {
{0, 0, 0}, /* black */
{0, 0, 50}, /* dark blue */
{0, 50, 0}, /* dark green */
{0, 50, 50}, /* dark cyan */
{50, 0, 0}, /* dark red */
{50, 0, 50}, /* dark magenta */
{50, 50, 0}, /* brown */
{75, 75, 75}, /* light gray */
{50, 50, 50}, /* dark gray */
{0, 0, 100}, /* light blue */
{0, 100, 0}, /* light green */
{0, 100, 100}, /* light cyan */
{100, 0, 0}, /* light red */
{100, 0, 100}, /* light magenta */
{100, 100, 0}, /* yellow */
{100, 100, 100}, /* white */
};
int
vt_generate_vga_palette(uint32_t *palette, int format, uint32_t rmax, int roffset,
uint32_t gmax, int goffset, uint32_t bmax, int boffset)
{
int i;
#define CF(_f, _i) ((_f ## max * color_def[(_i)]._f / 100) << _f ## offset)
for (i = 0; i < 16; i++) {
switch (format) {
case COLOR_FORMAT_VGA:
palette[i] = i;
break;
case COLOR_FORMAT_RGB:
palette[i] = CF(r, i) | CF(g, i) | CF(b, i);
break;
default:
return (ENODEV);
}
}
#undef CF
return (0);
}

View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
enum vt_color_format {
COLOR_FORMAT_BW = 0,
COLOR_FORMAT_GRAY,
COLOR_FORMAT_VGA, /* Color Index. */
COLOR_FORMAT_RGB,
COLOR_FORMAT_ARGB,
COLOR_FORMAT_CMYK,
COLOR_FORMAT_HSL,
COLOR_FORMAT_YUV,
COLOR_FORMAT_YCbCr,
COLOR_FORMAT_YPbPr,
COLOR_FORMAT_MAX = 15,
};
/* Helper to fill color map used by driver */
int vt_generate_vga_palette(uint32_t *palette, int format, uint32_t rmax,
int roffset, uint32_t gmax, int goffset, uint32_t bmax, int boffset);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <dev/vt/vt.h>
struct mouse_cursor vt_default_mouse_pointer = {
.map = {
0x00, /* "__ " */
0x40, /* "_*_ " */
0x60, /* "_**_ " */
0x70, /* "_***_ " */
0x78, /* "_****_ " */
0x7c, /* "_*****_ " */
0x7e, /* "_******_" */
0x68, /* "_**_****" */
0x4c, /* "_*__**__" */
0x0c, /* " _ _**_ " */
0x06, /* " _**_" */
0x06, /* " _**_" */
0x00, /* " ____" */
},
.mask = {
0xc0, /* "__ " */
0xe0, /* "___ " */
0xf0, /* "____ " */
0xf8, /* "_____ " */
0xfc, /* "______ " */
0xfe, /* "_______ " */
0xff, /* "________" */
0xff, /* "________" */
0xff, /* "________" */
0x1e, /* " ____ " */
0x0f, /* " ____" */
0x0f, /* " ____" */
0x0f, /* " ____" */
},
.w = 8,
.h = 13,
};

View File

@ -0,0 +1,278 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/fbio.h>
#include "opt_platform.h"
#ifdef FDT
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_pci.h>
#endif
#include <dev/vt/vt.h>
#include <dev/vt/hw/fb/vt_fb.h>
#include <dev/vt/colors/vt_termcolors.h>
static vd_init_t vt_efb_init;
static struct vt_driver vt_fb_early_driver = {
.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 void
#ifdef FDT
vt_efb_initialize(struct fb_info *info, phandle_t node)
#else
vt_efb_initialize(struct fb_info *info)
#endif
{
#ifdef FDT
char name[64];
cell_t retval;
ihandle_t ih;
int i;
/* Open display device, thereby initializing it */
memset(name, 0, sizeof(name));
OF_package_to_path(node, name, sizeof(name));
ih = OF_open(name);
#endif
/*
* Set up the color map
*/
switch (info->fb_depth) {
case 8:
vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0);
break;
case 15:
vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0);
break;
case 16:
vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0);
break;
case 24:
case 32:
#if BYTE_ORDER == BIG_ENDIAN
vt_generate_vga_palette(info->fb_cmap,
COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
#else
vt_generate_vga_palette(info->fb_cmap,
COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
#endif
#ifdef FDT
for (i = 0; i < 16; i++) {
OF_call_method("color!", ih, 4, 1,
(cell_t)((info->fb_cmap[i] >> 16) & 0xff),
(cell_t)((info->fb_cmap[i] >> 8) & 0xff),
(cell_t)((info->fb_cmap[i] >> 0) & 0xff),
(cell_t)i, &retval);
}
#endif
break;
default:
panic("Unknown color space fb_depth %d", info->fb_depth);
break;
}
}
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];
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)
return (CN_DEAD);
#define GET(name, var) \
if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \
return (CN_DEAD); \
OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \
if (info->fb_##var == 0) \
return (CN_DEAD);
GET("height", height)
GET("width", width)
GET("depth", depth)
GET("linebytes", stride)
#undef GET
info->fb_size = info->fb_height * info->fb_stride;
/*
* Get the PCI addresses of the adapter, if present. The node may be the
* child of the PCI device: in that case, try the parent for
* the assigned-addresses property.
*/
len = OF_getprop(node, "assigned-addresses", pciaddrs,
sizeof(pciaddrs));
if (len == -1) {
len = OF_getprop(OF_parent(node), "assigned-addresses",
pciaddrs, sizeof(pciaddrs));
}
if (len == -1)
len = 0;
n_pciaddrs = len / sizeof(struct ofw_pci_register);
/*
* Grab the physical address of the framebuffer, and then map it
* into our memory space. If the MMU is not yet up, it will be
* remapped for us when relocation turns on.
*/
if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) {
/* XXX We assume #address-cells is 1 at this point. */
OF_getencprop(node, "address", &info->fb_pbase,
sizeof(info->fb_pbase));
#if defined(__powerpc__)
sc->sc_memt = &bs_be_tag;
bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size,
BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase);
#elif defined(__sparc64__)
OF_decode_addr(node, 0, &space, &phys);
sc->sc_memt = &vt_efb_memt[0];
info->addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
#else
bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
BUS_SPACE_MAP_PREFETCHABLE,
(bus_space_handle_t *)&info->fb_vbase);
#endif
} else {
/*
* Some IBM systems don't have an address property. Try to
* guess the framebuffer region from the assigned addresses.
* This is ugly, but there doesn't seem to be an alternative.
* Linux does the same thing.
*/
info->fb_pbase = n_pciaddrs;
for (i = 0; i < n_pciaddrs; i++) {
/* If it is too small, not the framebuffer */
if (pciaddrs[i].size_lo < info->fb_size)
continue;
/* If it is not memory, it isn't either */
if (!(pciaddrs[i].phys_hi &
OFW_PCI_PHYS_HI_SPACE_MEM32))
continue;
/* This could be the framebuffer */
info->fb_pbase = i;
/* If it is prefetchable, it certainly is */
if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
break;
}
if (info->fb_pbase == n_pciaddrs) /* No candidates found */
return (CN_DEAD);
#if defined(__powerpc__)
OF_decode_addr(node, info->fb_pbase, &sc->sc_memt,
&info->fb_vbase);
#elif defined(__sparc64__)
OF_decode_addr(node, info->fb_pbase, &space, &info->fb_pbase);
sc->sc_memt = &vt_efb_memt[0];
info->fb_vbase = sparc64_fake_bustag(space, info->fb_pbase,
sc->sc_memt);
#else
bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size,
BUS_SPACE_MAP_PREFETCHABLE,
(bus_space_handle_t *)&info->fb_vbase);
#endif
}
/* blank full size */
len = info->fb_size / 4;
for (i = 0; i < len; i++) {
((uint32_t *)info->fb_vbase)[i] = 0;
}
/* Get pixel storage size. */
info->fb_bpp = info->fb_stride / info->fb_width * 8;
/*
* Early FB driver work with static window buffer 80x25, so reduce
* size to 640x480.
*/
info->fb_width = VT_FB_DEFAULT_WIDTH;
info->fb_height = VT_FB_DEFAULT_HEIGHT;
#ifdef FDT
vt_efb_initialize(info, node);
#else
vt_efb_initialize(info);
#endif
fb_probe(info);
vt_fb_init(vd);
return (CN_INTERNAL);
}

246
sys/dev/vt/hw/fb/vt_fb.c Normal file
View File

@ -0,0 +1,246 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/fbio.h>
#include <dev/vt/vt.h>
#include <dev/vt/hw/fb/vt_fb.h>
#include <dev/vt/colors/vt_termcolors.h>
static struct vt_driver vt_fb_driver = {
.vd_init = vt_fb_init,
.vd_blank = vt_fb_blank,
.vd_bitbltchr = vt_fb_bitbltchr,
.vd_postswitch = vt_fb_postswitch,
.vd_priority = VD_PRIORITY_GENERIC+10,
};
void
vt_fb_blank(struct vt_device *vd, term_color_t color)
{
struct fb_info *info;
uint32_t c;
u_int o;
info = vd->vd_softc;
c = info->fb_cmap[color];
switch (FBTYPE_GET_BYTESPP(info)) {
case 1:
for (o = 0; o < info->fb_stride; o++)
info->wr1(info, o, c);
break;
case 2:
for (o = 0; o < info->fb_stride; o += 2)
info->wr2(info, o, c);
break;
case 3:
/* line 0 */
for (o = 0; o < info->fb_stride; o += 3) {
info->wr1(info, o, (c >> 16) & 0xff);
info->wr1(info, o + 1, (c >> 8) & 0xff);
info->wr1(info, o + 2, c & 0xff);
}
break;
case 4:
for (o = 0; o < info->fb_stride; o += 4)
info->wr4(info, o, c);
break;
default:
/* panic? */
return;
}
/* Copy line0 to all other lines. */
/* XXX will copy with borders. */
for (o = info->fb_stride; o < info->fb_size; o += info->fb_stride) {
info->copy(info, o, 0, info->fb_stride);
}
}
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, m;
const uint8_t *ch;
info = vd->vd_softc;
bpp = FBTYPE_GET_BYTESPP(info);
fgc = info->fb_cmap[fg];
bgc = info->fb_cmap[bg];
b = m = 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;
if (mask != NULL) {
if (c % 8 == 0)
m = *mask++;
else
m <<= 1;
/* Skip pixel write, if mask has no bit set. */
if ((m & 0x80) == 0)
continue;
}
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_postswitch(struct vt_device *vd)
{
struct fb_info *info;
info = vd->vd_softc;
if (info->enter != NULL)
info->enter(info->fb_priv);
}
static int
vt_fb_init_cmap(uint32_t *cmap, int depth)
{
switch (depth) {
case 8:
return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
0x7, 5, 0x7, 2, 0x3, 0));
case 15:
return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
0x1f, 10, 0x1f, 5, 0x1f, 0));
case 16:
return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
0x1f, 11, 0x3f, 5, 0x1f, 0));
case 24:
case 32: /* Ignore alpha. */
return (vt_generate_vga_palette(cmap, COLOR_FORMAT_RGB,
0xff, 0, 0xff, 8, 0xff, 16));
default:
return (1);
}
}
int
vt_fb_init(struct vt_device *vd)
{
struct fb_info *info;
int err;
info = vd->vd_softc;
vd->vd_height = info->fb_height;
vd->vd_width = info->fb_width;
if (info->fb_cmsize <= 0) {
err = vt_fb_init_cmap(info->fb_cmap, FBTYPE_GET_BPP(info));
if (err)
return (CN_DEAD);
info->fb_cmsize = 16;
}
/* Clear the screen. */
vt_fb_blank(vd, TC_BLACK);
/* Wakeup screen. KMS need this. */
vt_fb_postswitch(vd);
return (CN_INTERNAL);
}
int
vt_fb_attach(struct fb_info *info)
{
vt_allocate(&vt_fb_driver, info);
return (0);
}
void
vt_fb_resume(void)
{
vt_resume();
}
void
vt_fb_suspend(void)
{
vt_suspend();
}

47
sys/dev/vt/hw/fb/vt_fb.h Normal file
View File

@ -0,0 +1,47 @@
/*-
* Copyright (c) 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Aleksandr Rybalko under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _DEV_VT_HW_FB_VT_FB_H_
#define _DEV_VT_HW_FB_VT_FB_H_
/* Generic framebuffer interface call vt_fb_attach to init VT(9) */
int vt_fb_attach(struct fb_info *info);
void vt_fb_resume(void);
void vt_fb_suspend(void);
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_postswitch_t vt_fb_postswitch;
#endif /* _DEV_VT_HW_FB_VT_FB_H_ */

348
sys/dev/vt/hw/ofwfb/ofwfb.c Normal file
View File

@ -0,0 +1,348 @@
/*-
* Copyright (c) 2011 Nathan Whitehorn
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c 219888 2011-03-22 21:31:31Z ed $");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
#include <dev/vt/colors/vt_termcolors.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#ifdef __sparc64__
#include <machine/bus_private.h>
#endif
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_pci.h>
struct ofwfb_softc {
phandle_t sc_node;
intptr_t sc_addr;
int sc_depth;
int sc_stride;
bus_space_tag_t sc_memt;
uint32_t sc_colormap[16];
};
static vd_init_t ofwfb_init;
static vd_blank_t ofwfb_blank;
static vd_bitbltchr_t ofwfb_bitbltchr;
static const struct vt_driver vt_ofwfb_driver = {
.vd_init = ofwfb_init,
.vd_blank = ofwfb_blank,
.vd_bitbltchr = ofwfb_bitbltchr,
.vd_priority = VD_PRIORITY_GENERIC+1,
};
static struct ofwfb_softc ofwfb_conssoftc;
VT_CONSDEV_DECLARE(vt_ofwfb_driver, PIXEL_WIDTH(1920), PIXEL_HEIGHT(1200),
&ofwfb_conssoftc);
/* XXX: hardcoded max size */
static void
ofwfb_blank(struct vt_device *vd, term_color_t color)
{
struct ofwfb_softc *sc = vd->vd_softc;
u_int ofs;
uint32_t c;
switch (sc->sc_depth) {
case 8:
for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
*(uint8_t *)(sc->sc_addr + ofs) = color;
break;
case 32:
c = sc->sc_colormap[color];
for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
*(uint32_t *)(sc->sc_addr + 4*ofs) = c;
break;
default:
/* panic? */
break;
}
}
static void
ofwfb_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 ofwfb_softc *sc = vd->vd_softc;
u_long line;
uint32_t fgc, bgc;
int c;
uint8_t b, m;
fgc = sc->sc_colormap[fg];
bgc = sc->sc_colormap[bg];
b = m = 0;
/* Don't try to put off screen pixels */
if (((left + width) > vd->vd_width) || ((top + height) >
vd->vd_height))
return;
line = (sc->sc_stride * top) + left * sc->sc_depth/8;
for (; height > 0; height--) {
for (c = 0; c < width; c++) {
if (c % 8 == 0)
b = *src++;
else
b <<= 1;
if (mask != NULL) {
if (c % 8 == 0)
m = *mask++;
else
m <<= 1;
/* Skip pixel write, if mask has no bit set. */
if ((m & 0x80) == 0)
continue;
}
switch(sc->sc_depth) {
case 8:
*(uint8_t *)(sc->sc_addr + line + c) =
b & 0x80 ? fg : bg;
break;
case 32:
*(uint32_t *)(sc->sc_addr + line + 4*c) =
(b & 0x80) ? fgc : bgc;
break;
default:
/* panic? */
break;
}
}
line += sc->sc_stride;
}
}
static void
ofwfb_initialize(struct vt_device *vd)
{
struct ofwfb_softc *sc = vd->vd_softc;
char name[64];
ihandle_t ih;
int i;
cell_t retval;
uint32_t oldpix;
/* Open display device, thereby initializing it */
memset(name, 0, sizeof(name));
OF_package_to_path(sc->sc_node, name, sizeof(name));
ih = OF_open(name);
/*
* Set up the color map
*/
switch (sc->sc_depth) {
case 8:
vt_generate_vga_palette(sc->sc_colormap, COLOR_FORMAT_RGB, 255,
0, 255, 8, 255, 16);
for (i = 0; i < 16; i++) {
OF_call_method("color!", ih, 4, 1,
(cell_t)((sc->sc_colormap[i] >> 16) & 0xff),
(cell_t)((sc->sc_colormap[i] >> 8) & 0xff),
(cell_t)((sc->sc_colormap[i] >> 0) & 0xff),
(cell_t)i, &retval);
}
break;
case 32:
/*
* We bypass the usual bus_space_() accessors here, mostly
* for performance reasons. In particular, we don't want
* any barrier operations that may be performed and handle
* endianness slightly different. Figure out the host-view
* endianness of the frame buffer.
*/
oldpix = bus_space_read_4(sc->sc_memt, sc->sc_addr, 0);
bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, 0xff000000);
if (*(uint8_t *)(sc->sc_addr) == 0xff)
vt_generate_vga_palette(sc->sc_colormap,
COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
else
vt_generate_vga_palette(sc->sc_colormap,
COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, oldpix);
break;
default:
panic("Unknown color space depth %d", sc->sc_depth);
break;
}
/* Clear the screen. */
ofwfb_blank(vd, TC_BLACK);
}
static int
ofwfb_init(struct vt_device *vd)
{
struct ofwfb_softc *sc = vd->vd_softc;
char type[64];
phandle_t chosen;
ihandle_t stdout;
phandle_t node;
uint32_t depth, height, width;
struct ofw_pci_register pciaddrs[8];
int n_pciaddrs;
uint32_t fb_phys;
int i, len;
#ifdef __sparc64__
static struct bus_space_tag ofwfb_memt[1];
bus_addr_t phys;
int space;
#endif
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)
return (CN_DEAD);
/* Keep track of the OF node */
sc->sc_node = node;
/* Make sure we have needed properties */
if (OF_getproplen(node, "height") != sizeof(height) ||
OF_getproplen(node, "width") != sizeof(width) ||
OF_getproplen(node, "depth") != sizeof(depth) ||
OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
return (CN_DEAD);
/* Only support 8 and 32-bit framebuffers */
OF_getprop(node, "depth", &depth, sizeof(depth));
if (depth != 8 && depth != 32)
return (CN_DEAD);
sc->sc_depth = depth;
OF_getprop(node, "height", &height, sizeof(height));
OF_getprop(node, "width", &width, sizeof(width));
OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
vd->vd_height = height;
vd->vd_width = width;
/*
* Get the PCI addresses of the adapter, if present. The node may be the
* child of the PCI device: in that case, try the parent for
* the assigned-addresses property.
*/
len = OF_getprop(node, "assigned-addresses", pciaddrs,
sizeof(pciaddrs));
if (len == -1) {
len = OF_getprop(OF_parent(node), "assigned-addresses",
pciaddrs, sizeof(pciaddrs));
}
if (len == -1)
len = 0;
n_pciaddrs = len / sizeof(struct ofw_pci_register);
/*
* Grab the physical address of the framebuffer, and then map it
* into our memory space. If the MMU is not yet up, it will be
* remapped for us when relocation turns on.
*/
if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
/* XXX We assume #address-cells is 1 at this point. */
OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
#if defined(__powerpc__)
sc->sc_memt = &bs_be_tag;
bus_space_map(sc->sc_memt, fb_phys, height * sc->sc_stride,
BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
#elif defined(__sparc64__)
OF_decode_addr(node, 0, &space, &phys);
sc->sc_memt = &ofwfb_memt[0];
sc->sc_addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
#else
#error Unsupported platform!
#endif
} else {
/*
* Some IBM systems don't have an address property. Try to
* guess the framebuffer region from the assigned addresses.
* This is ugly, but there doesn't seem to be an alternative.
* Linux does the same thing.
*/
fb_phys = n_pciaddrs;
for (i = 0; i < n_pciaddrs; i++) {
/* If it is too small, not the framebuffer */
if (pciaddrs[i].size_lo < sc->sc_stride*height)
continue;
/* If it is not memory, it isn't either */
if (!(pciaddrs[i].phys_hi &
OFW_PCI_PHYS_HI_SPACE_MEM32))
continue;
/* This could be the framebuffer */
fb_phys = i;
/* If it is prefetchable, it certainly is */
if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
break;
}
if (fb_phys == n_pciaddrs) /* No candidates found */
return (CN_DEAD);
#if defined(__powerpc__)
OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->sc_addr);
#elif defined(__sparc64__)
OF_decode_addr(node, fb_phys, &space, &phys);
sc->sc_memt = &ofwfb_memt[0];
sc->sc_addr = sparc64_fake_bustag(space, phys, sc->sc_memt);
#endif
}
ofwfb_initialize(vd);
return (CN_INTERNAL);
}

604
sys/dev/vt/hw/vga/vga.c Normal file
View File

@ -0,0 +1,604 @@
/*-
* Copyright (c) 2005 Marcel Moolenaar
* All rights reserved.
*
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Ed Schouten
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
#include <dev/vt/hw/vga/vga_reg.h>
#include <machine/bus.h>
#if defined(__amd64__) || defined(__i386__)
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/pmap.h>
#include <machine/vmparam.h>
#endif /* __amd64__ || __i386__ */
struct vga_softc {
bus_space_tag_t vga_fb_tag;
bus_space_handle_t vga_fb_handle;
bus_space_tag_t vga_reg_tag;
bus_space_handle_t vga_reg_handle;
int vga_curcolor;
};
/* Convenience macros. */
#define MEM_READ1(sc, ofs) \
bus_space_read_1(sc->vga_fb_tag, sc->vga_fb_handle, ofs)
#define MEM_WRITE1(sc, ofs, val) \
bus_space_write_1(sc->vga_fb_tag, sc->vga_fb_handle, ofs, val)
#define REG_READ1(sc, reg) \
bus_space_read_1(sc->vga_reg_tag, sc->vga_reg_handle, reg)
#define REG_WRITE1(sc, reg, val) \
bus_space_write_1(sc->vga_reg_tag, sc->vga_reg_handle, reg, val)
#define VT_VGA_WIDTH 640
#define VT_VGA_HEIGHT 480
#define VT_VGA_MEMSIZE (VT_VGA_WIDTH * VT_VGA_HEIGHT / 8)
static vd_init_t vga_init;
static vd_blank_t vga_blank;
static vd_bitbltchr_t vga_bitbltchr;
static vd_putchar_t vga_putchar;
static const struct vt_driver vt_vga_driver = {
.vd_init = vga_init,
.vd_blank = vga_blank,
.vd_bitbltchr = vga_bitbltchr,
.vd_putchar = vga_putchar,
.vd_priority = VD_PRIORITY_GENERIC,
};
/*
* Driver supports both text mode and graphics mode. Make sure the
* buffer is always big enough to support both.
*/
static struct vga_softc vga_conssoftc;
VT_CONSDEV_DECLARE(vt_vga_driver, MAX(80, PIXEL_WIDTH(VT_VGA_WIDTH)),
MAX(25, PIXEL_HEIGHT(VT_VGA_HEIGHT)), &vga_conssoftc);
static inline void
vga_setcolor(struct vt_device *vd, term_color_t color)
{
struct vga_softc *sc = vd->vd_softc;
if (sc->vga_curcolor != color) {
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_SET_RESET);
REG_WRITE1(sc, VGA_GC_DATA, color);
sc->vga_curcolor = color;
}
}
static void
vga_blank(struct vt_device *vd, term_color_t color)
{
struct vga_softc *sc = vd->vd_softc;
u_int ofs;
vga_setcolor(vd, color);
for (ofs = 0; ofs < VT_VGA_MEMSIZE; ofs++)
MEM_WRITE1(sc, ofs, 0xff);
}
static inline void
vga_bitblt_put(struct vt_device *vd, u_long dst, term_color_t color,
uint8_t v)
{
struct vga_softc *sc = vd->vd_softc;
/* Skip empty writes, in order to avoid palette changes. */
if (v != 0x00) {
vga_setcolor(vd, color);
/*
* When this MEM_READ1() gets disabled, all sorts of
* artifacts occur. This is because this read loads the
* set of 8 pixels that are about to be changed. There
* is one scenario where we can avoid the read, namely
* if all pixels are about to be overwritten anyway.
*/
if (v != 0xff)
MEM_READ1(sc, dst);
MEM_WRITE1(sc, dst, v);
}
}
static inline void
vga_bitblt_draw(struct vt_device *vd, const uint8_t *src,
u_long ldst, uint8_t shift, unsigned int width, unsigned int height,
term_color_t color, int negate)
{
u_long dst;
int w;
uint8_t b, r, out;
for (; height > 0; height--) {
dst = ldst;
ldst += VT_VGA_WIDTH / 8;
r = 0;
for (w = width; w > 0; w -= 8) {
b = *src++;
if (negate) {
b = ~b;
/* Don't go too far. */
if (w < 8)
b &= 0xff << (8 - w);
}
/* Reintroduce bits from previous column. */
out = (b >> shift) | r;
r = b << (8 - shift);
vga_bitblt_put(vd, dst++, color, out);
}
/* Print the remainder. */
vga_bitblt_put(vd, dst, color, r);
}
}
static void
vga_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 vga_softc *sc = vd->vd_softc;
u_long dst;
uint8_t shift;
dst = (VT_VGA_WIDTH * top + left) / 8;
shift = left % 8;
/* Don't try to put off screen pixels */
if (((left + width) > VT_VGA_WIDTH) || ((top + height) >
VT_VGA_HEIGHT))
return;
if (sc->vga_curcolor == fg) {
vga_bitblt_draw(vd, src, dst, shift, width, height, fg, 0);
vga_bitblt_draw(vd, src, dst, shift, width, height, bg, 1);
} else {
vga_bitblt_draw(vd, src, dst, shift, width, height, bg, 1);
vga_bitblt_draw(vd, src, dst, shift, width, height, fg, 0);
}
}
/*
* Binary searchable table for Unicode to CP437 conversion.
*/
struct unicp437 {
uint16_t unicode_base;
uint8_t cp437_base;
uint8_t length;
};
static const struct unicp437 cp437table[] = {
{ 0x0020, 0x20, 0x5e }, { 0x00a0, 0x20, 0x00 },
{ 0x00a1, 0xad, 0x00 }, { 0x00a2, 0x9b, 0x00 },
{ 0x00a3, 0x9c, 0x00 }, { 0x00a5, 0x9d, 0x00 },
{ 0x00a7, 0x15, 0x00 }, { 0x00aa, 0xa6, 0x00 },
{ 0x00ab, 0xae, 0x00 }, { 0x00ac, 0xaa, 0x00 },
{ 0x00b0, 0xf8, 0x00 }, { 0x00b1, 0xf1, 0x00 },
{ 0x00b2, 0xfd, 0x00 }, { 0x00b5, 0xe6, 0x00 },
{ 0x00b6, 0x14, 0x00 }, { 0x00b7, 0xfa, 0x00 },
{ 0x00ba, 0xa7, 0x00 }, { 0x00bb, 0xaf, 0x00 },
{ 0x00bc, 0xac, 0x00 }, { 0x00bd, 0xab, 0x00 },
{ 0x00bf, 0xa8, 0x00 }, { 0x00c4, 0x8e, 0x01 },
{ 0x00c6, 0x92, 0x00 }, { 0x00c7, 0x80, 0x00 },
{ 0x00c9, 0x90, 0x00 }, { 0x00d1, 0xa5, 0x00 },
{ 0x00d6, 0x99, 0x00 }, { 0x00dc, 0x9a, 0x00 },
{ 0x00df, 0xe1, 0x00 }, { 0x00e0, 0x85, 0x00 },
{ 0x00e1, 0xa0, 0x00 }, { 0x00e2, 0x83, 0x00 },
{ 0x00e4, 0x84, 0x00 }, { 0x00e5, 0x86, 0x00 },
{ 0x00e6, 0x91, 0x00 }, { 0x00e7, 0x87, 0x00 },
{ 0x00e8, 0x8a, 0x00 }, { 0x00e9, 0x82, 0x00 },
{ 0x00ea, 0x88, 0x01 }, { 0x00ec, 0x8d, 0x00 },
{ 0x00ed, 0xa1, 0x00 }, { 0x00ee, 0x8c, 0x00 },
{ 0x00ef, 0x8b, 0x00 }, { 0x00f0, 0xeb, 0x00 },
{ 0x00f1, 0xa4, 0x00 }, { 0x00f2, 0x95, 0x00 },
{ 0x00f3, 0xa2, 0x00 }, { 0x00f4, 0x93, 0x00 },
{ 0x00f6, 0x94, 0x00 }, { 0x00f7, 0xf6, 0x00 },
{ 0x00f8, 0xed, 0x00 }, { 0x00f9, 0x97, 0x00 },
{ 0x00fa, 0xa3, 0x00 }, { 0x00fb, 0x96, 0x00 },
{ 0x00fc, 0x81, 0x00 }, { 0x00ff, 0x98, 0x00 },
{ 0x0192, 0x9f, 0x00 }, { 0x0393, 0xe2, 0x00 },
{ 0x0398, 0xe9, 0x00 }, { 0x03a3, 0xe4, 0x00 },
{ 0x03a6, 0xe8, 0x00 }, { 0x03a9, 0xea, 0x00 },
{ 0x03b1, 0xe0, 0x01 }, { 0x03b4, 0xeb, 0x00 },
{ 0x03b5, 0xee, 0x00 }, { 0x03bc, 0xe6, 0x00 },
{ 0x03c0, 0xe3, 0x00 }, { 0x03c3, 0xe5, 0x00 },
{ 0x03c4, 0xe7, 0x00 }, { 0x03c6, 0xed, 0x00 },
{ 0x03d5, 0xed, 0x00 }, { 0x2010, 0x2d, 0x00 },
{ 0x2014, 0x2d, 0x00 }, { 0x2018, 0x60, 0x00 },
{ 0x2019, 0x27, 0x00 }, { 0x201c, 0x22, 0x00 },
{ 0x201d, 0x22, 0x00 }, { 0x2022, 0x07, 0x00 },
{ 0x203c, 0x13, 0x00 }, { 0x207f, 0xfc, 0x00 },
{ 0x20a7, 0x9e, 0x00 }, { 0x20ac, 0xee, 0x00 },
{ 0x2126, 0xea, 0x00 }, { 0x2190, 0x1b, 0x00 },
{ 0x2191, 0x18, 0x00 }, { 0x2192, 0x1a, 0x00 },
{ 0x2193, 0x19, 0x00 }, { 0x2194, 0x1d, 0x00 },
{ 0x2195, 0x12, 0x00 }, { 0x21a8, 0x17, 0x00 },
{ 0x2202, 0xeb, 0x00 }, { 0x2208, 0xee, 0x00 },
{ 0x2211, 0xe4, 0x00 }, { 0x2212, 0x2d, 0x00 },
{ 0x2219, 0xf9, 0x00 }, { 0x221a, 0xfb, 0x00 },
{ 0x221e, 0xec, 0x00 }, { 0x221f, 0x1c, 0x00 },
{ 0x2229, 0xef, 0x00 }, { 0x2248, 0xf7, 0x00 },
{ 0x2261, 0xf0, 0x00 }, { 0x2264, 0xf3, 0x00 },
{ 0x2265, 0xf2, 0x00 }, { 0x2302, 0x7f, 0x00 },
{ 0x2310, 0xa9, 0x00 }, { 0x2320, 0xf4, 0x00 },
{ 0x2321, 0xf5, 0x00 }, { 0x2500, 0xc4, 0x00 },
{ 0x2502, 0xb3, 0x00 }, { 0x250c, 0xda, 0x00 },
{ 0x2510, 0xbf, 0x00 }, { 0x2514, 0xc0, 0x00 },
{ 0x2518, 0xd9, 0x00 }, { 0x251c, 0xc3, 0x00 },
{ 0x2524, 0xb4, 0x00 }, { 0x252c, 0xc2, 0x00 },
{ 0x2534, 0xc1, 0x00 }, { 0x253c, 0xc5, 0x00 },
{ 0x2550, 0xcd, 0x00 }, { 0x2551, 0xba, 0x00 },
{ 0x2552, 0xd5, 0x00 }, { 0x2553, 0xd6, 0x00 },
{ 0x2554, 0xc9, 0x00 }, { 0x2555, 0xb8, 0x00 },
{ 0x2556, 0xb7, 0x00 }, { 0x2557, 0xbb, 0x00 },
{ 0x2558, 0xd4, 0x00 }, { 0x2559, 0xd3, 0x00 },
{ 0x255a, 0xc8, 0x00 }, { 0x255b, 0xbe, 0x00 },
{ 0x255c, 0xbd, 0x00 }, { 0x255d, 0xbc, 0x00 },
{ 0x255e, 0xc6, 0x01 }, { 0x2560, 0xcc, 0x00 },
{ 0x2561, 0xb5, 0x00 }, { 0x2562, 0xb6, 0x00 },
{ 0x2563, 0xb9, 0x00 }, { 0x2564, 0xd1, 0x01 },
{ 0x2566, 0xcb, 0x00 }, { 0x2567, 0xcf, 0x00 },
{ 0x2568, 0xd0, 0x00 }, { 0x2569, 0xca, 0x00 },
{ 0x256a, 0xd8, 0x00 }, { 0x256b, 0xd7, 0x00 },
{ 0x256c, 0xce, 0x00 }, { 0x2580, 0xdf, 0x00 },
{ 0x2584, 0xdc, 0x00 }, { 0x2588, 0xdb, 0x00 },
{ 0x258c, 0xdd, 0x00 }, { 0x2590, 0xde, 0x00 },
{ 0x2591, 0xb0, 0x02 }, { 0x25a0, 0xfe, 0x00 },
{ 0x25ac, 0x16, 0x00 }, { 0x25b2, 0x1e, 0x00 },
{ 0x25ba, 0x10, 0x00 }, { 0x25bc, 0x1f, 0x00 },
{ 0x25c4, 0x11, 0x00 }, { 0x25cb, 0x09, 0x00 },
{ 0x25d8, 0x08, 0x00 }, { 0x25d9, 0x0a, 0x00 },
{ 0x263a, 0x01, 0x01 }, { 0x263c, 0x0f, 0x00 },
{ 0x2640, 0x0c, 0x00 }, { 0x2642, 0x0b, 0x00 },
{ 0x2660, 0x06, 0x00 }, { 0x2663, 0x05, 0x00 },
{ 0x2665, 0x03, 0x01 }, { 0x266a, 0x0d, 0x01 },
};
static uint8_t
vga_get_cp437(term_char_t c)
{
int min, mid, max;
min = 0;
max = (sizeof(cp437table) / sizeof(struct unicp437)) - 1;
if (c < cp437table[0].unicode_base ||
c > cp437table[max].unicode_base + cp437table[max].length)
return '?';
while (max >= min) {
mid = (min + max) / 2;
if (c < cp437table[mid].unicode_base)
max = mid - 1;
else if (c > cp437table[mid].unicode_base +
cp437table[mid].length)
min = mid + 1;
else
return (c - cp437table[mid].unicode_base +
cp437table[mid].cp437_base);
}
return '?';
}
static void
vga_putchar(struct vt_device *vd, term_char_t c,
vt_axis_t top, vt_axis_t left, term_color_t fg, term_color_t bg)
{
struct vga_softc *sc = vd->vd_softc;
uint8_t ch, attr;
/*
* Convert character to CP437, which is the character set used
* by the VGA hardware by default.
*/
ch = vga_get_cp437(c);
/*
* Convert colors to VGA attributes.
*/
attr = bg << 4 | fg;
MEM_WRITE1(sc, 0x18000 + (top * 80 + left) * 2 + 0, ch);
MEM_WRITE1(sc, 0x18000 + (top * 80 + left) * 2 + 1, attr);
}
static void
vga_initialize_graphics(struct vt_device *vd)
{
struct vga_softc *sc = vd->vd_softc;
/* Clock select. */
REG_WRITE1(sc, VGA_GEN_MISC_OUTPUT_W, VGA_GEN_MO_VSP | VGA_GEN_MO_HSP |
VGA_GEN_MO_PB | VGA_GEN_MO_ER | VGA_GEN_MO_IOA);
/* Set sequencer clocking and memory mode. */
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_CLOCKING_MODE);
REG_WRITE1(sc, VGA_SEQ_DATA, VGA_SEQ_CM_89);
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_MEMORY_MODE);
REG_WRITE1(sc, VGA_SEQ_DATA, VGA_SEQ_MM_OE | VGA_SEQ_MM_EM);
/* Set the graphics controller in graphics mode. */
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_MISCELLANEOUS);
REG_WRITE1(sc, VGA_GC_DATA, 0x04 + VGA_GC_MISC_GA);
/* Program the CRT controller. */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_HORIZ_TOTAL);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x5f); /* 760 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_HORIZ_DISP_END);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x4f); /* 640 - 8 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_START_HORIZ_BLANK);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x50); /* 640 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_END_HORIZ_BLANK);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_EHB_CR + 2);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_START_HORIZ_RETRACE);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x54); /* 672 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_END_HORIZ_RETRACE);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_EHR_EHB + 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_VERT_TOTAL);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x0b); /* 523 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_OVERFLOW);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_OF_VT9 | VGA_CRTC_OF_LC8 |
VGA_CRTC_OF_VBS8 | VGA_CRTC_OF_VRS8 | VGA_CRTC_OF_VDE8);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_MAX_SCAN_LINE);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_MSL_LC9);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_VERT_RETRACE_START);
REG_WRITE1(sc, VGA_CRTC_DATA, 0xea); /* 480 + 10 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_VERT_RETRACE_END);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x0c);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_VERT_DISPLAY_END);
REG_WRITE1(sc, VGA_CRTC_DATA, 0xdf); /* 480 - 1*/
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_OFFSET);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x28);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_START_VERT_BLANK);
REG_WRITE1(sc, VGA_CRTC_DATA, 0xe7); /* 480 + 7 */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_END_VERT_BLANK);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x04);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_MODE_CONTROL);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_MC_WB | VGA_CRTC_MC_AW |
VGA_CRTC_MC_SRS | VGA_CRTC_MC_CMS);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_LINE_COMPARE);
REG_WRITE1(sc, VGA_CRTC_DATA, 0xff); /* 480 + 31 */
REG_WRITE1(sc, VGA_GEN_FEATURE_CTRL_W, 0);
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_MAP_MASK);
REG_WRITE1(sc, VGA_SEQ_DATA, VGA_SEQ_MM_EM3 | VGA_SEQ_MM_EM2 |
VGA_SEQ_MM_EM1 | VGA_SEQ_MM_EM0);
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_CHAR_MAP_SELECT);
REG_WRITE1(sc, VGA_SEQ_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_SET_RESET);
REG_WRITE1(sc, VGA_GC_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_ENABLE_SET_RESET);
REG_WRITE1(sc, VGA_GC_DATA, 0x0f);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_COLOR_COMPARE);
REG_WRITE1(sc, VGA_GC_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_DATA_ROTATE);
REG_WRITE1(sc, VGA_GC_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_READ_MAP_SELECT);
REG_WRITE1(sc, VGA_GC_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_MODE);
REG_WRITE1(sc, VGA_GC_DATA, 0);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_COLOR_DONT_CARE);
REG_WRITE1(sc, VGA_GC_DATA, 0x0f);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_BIT_MASK);
REG_WRITE1(sc, VGA_GC_DATA, 0xff);
}
static void
vga_initialize(struct vt_device *vd, int textmode)
{
struct vga_softc *sc = vd->vd_softc;
uint8_t x;
/* Make sure the VGA adapter is not in monochrome emulation mode. */
x = REG_READ1(sc, VGA_GEN_MISC_OUTPUT_R);
REG_WRITE1(sc, VGA_GEN_MISC_OUTPUT_W, x | VGA_GEN_MO_IOA);
/* Unprotect CRTC registers 0-7. */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_VERT_RETRACE_END);
x = REG_READ1(sc, VGA_CRTC_DATA);
REG_WRITE1(sc, VGA_CRTC_DATA, x & ~VGA_CRTC_VRE_PR);
/*
* Wait for the vertical retrace.
* NOTE: this code reads the VGA_GEN_INPUT_STAT_1 register, which has
* the side-effect of clearing the internal flip-flip of the attribute
* controller's write register. This means that because this code is
* here, we know for sure that the first write to the attribute
* controller will be a write to the address register. Removing this
* code therefore also removes that guarantee and appropriate measures
* need to be taken.
*/
do {
x = REG_READ1(sc, VGA_GEN_INPUT_STAT_1);
x &= VGA_GEN_IS1_VR | VGA_GEN_IS1_DE;
} while (x != (VGA_GEN_IS1_VR | VGA_GEN_IS1_DE));
/* Now, disable the sync. signals. */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_MODE_CONTROL);
x = REG_READ1(sc, VGA_CRTC_DATA);
REG_WRITE1(sc, VGA_CRTC_DATA, x & ~VGA_CRTC_MC_HR);
/* Asynchronous sequencer reset. */
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_RESET);
REG_WRITE1(sc, VGA_SEQ_DATA, VGA_SEQ_RST_SR);
if (!textmode)
vga_initialize_graphics(vd);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_PRESET_ROW_SCAN);
REG_WRITE1(sc, VGA_CRTC_DATA, 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_CURSOR_START);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_CS_COO);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_CURSOR_END);
REG_WRITE1(sc, VGA_CRTC_DATA, 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_START_ADDR_HIGH);
REG_WRITE1(sc, VGA_CRTC_DATA, 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_START_ADDR_LOW);
REG_WRITE1(sc, VGA_CRTC_DATA, 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_CURSOR_LOC_HIGH);
REG_WRITE1(sc, VGA_CRTC_DATA, 0);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_CURSOR_LOC_LOW);
REG_WRITE1(sc, VGA_CRTC_DATA, 0x59);
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_UNDERLINE_LOC);
REG_WRITE1(sc, VGA_CRTC_DATA, VGA_CRTC_UL_UL);
if (textmode) {
/* Set the attribute controller to blink disable. */
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_MODE_CONTROL);
REG_WRITE1(sc, VGA_AC_WRITE, 0);
} else {
/* Set the attribute controller in graphics mode. */
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_MODE_CONTROL);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_MC_GA);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_HORIZ_PIXEL_PANNING);
REG_WRITE1(sc, VGA_AC_WRITE, 0);
}
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(0));
REG_WRITE1(sc, VGA_AC_WRITE, 0);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(1));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(2));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_G);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(3));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SG | VGA_AC_PAL_R);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(4));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(5));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(6));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_G | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(7));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_R | VGA_AC_PAL_G | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(8));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(9));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_R);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(10));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_G);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(11));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_G);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(12));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(13));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(14));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_G | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PALETTE(15));
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_PAL_SR | VGA_AC_PAL_SG |
VGA_AC_PAL_SB | VGA_AC_PAL_R | VGA_AC_PAL_G | VGA_AC_PAL_B);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_OVERSCAN_COLOR);
REG_WRITE1(sc, VGA_AC_WRITE, 0);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_COLOR_PLANE_ENABLE);
REG_WRITE1(sc, VGA_AC_WRITE, 0x0f);
REG_WRITE1(sc, VGA_AC_WRITE, VGA_AC_COLOR_SELECT);
REG_WRITE1(sc, VGA_AC_WRITE, 0);
if (!textmode) {
u_int ofs;
/*
* Done. Clear the frame buffer. All bit planes are
* enabled, so a single-paged loop should clear all
* planes.
*/
for (ofs = 0; ofs < VT_VGA_MEMSIZE; ofs++) {
MEM_READ1(sc, ofs);
MEM_WRITE1(sc, ofs, 0);
}
}
/* Re-enable the sequencer. */
REG_WRITE1(sc, VGA_SEQ_ADDRESS, VGA_SEQ_RESET);
REG_WRITE1(sc, VGA_SEQ_DATA, VGA_SEQ_RST_SR | VGA_SEQ_RST_NAR);
/* Re-enable the sync signals. */
REG_WRITE1(sc, VGA_CRTC_ADDRESS, VGA_CRTC_MODE_CONTROL);
x = REG_READ1(sc, VGA_CRTC_DATA);
REG_WRITE1(sc, VGA_CRTC_DATA, x | VGA_CRTC_MC_HR);
if (!textmode) {
/* Switch to write mode 3, because we'll mainly do bitblt. */
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_MODE);
REG_WRITE1(sc, VGA_GC_DATA, 3);
REG_WRITE1(sc, VGA_GC_ADDRESS, VGA_GC_ENABLE_SET_RESET);
REG_WRITE1(sc, VGA_GC_DATA, 0x0f);
}
}
static int
vga_init(struct vt_device *vd)
{
struct vga_softc *sc = vd->vd_softc;
int textmode = 0;
#if defined(__amd64__) || defined(__i386__)
sc->vga_fb_tag = X86_BUS_SPACE_MEM;
sc->vga_fb_handle = KERNBASE + VGA_MEM_BASE;
sc->vga_reg_tag = X86_BUS_SPACE_IO;
sc->vga_reg_handle = VGA_REG_BASE;
#elif defined(__ia64__)
sc->vga_fb_tag = IA64_BUS_SPACE_MEM;
sc->vga_fb_handle = IA64_PHYS_TO_RR6(VGA_MEM_BASE);
sc->vga_reg_tag = IA64_BUS_SPACE_IO;
sc->vga_reg_handle = VGA_REG_BASE;
#else
# error "Architecture not yet supported!"
#endif
TUNABLE_INT_FETCH("hw.vga.textmode", &textmode);
if (textmode) {
vd->vd_flags |= VDF_TEXTMODE;
vd->vd_width = 80;
vd->vd_height = 25;
} else {
vd->vd_width = VT_VGA_WIDTH;
vd->vd_height = VT_VGA_HEIGHT;
}
vga_initialize(vd, textmode);
return (CN_INTERNAL);
}

220
sys/dev/vt/hw/vga/vga_reg.h Normal file
View File

@ -0,0 +1,220 @@
/*-
* Copyright (c) 2005 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _DEV_VT_HW_VGA_VGA_REG_H_
#define _DEV_VT_HW_VGA_VGA_REG_H_
/*
* The VGA adapter uses two I/O port blocks. One of these blocks, the CRT
* controller registers, can be located either at 0x3B0 or at 0x3D0 in I/O
* port space. This allows compatibility with the monochrome adapter, which
* has the CRT controller registers at 0x3B0.
*
* It is assumed that compatibility with the monochrome adapter is not of
* interest anymore. As such, the CRT controller can be located at 0x3D0 in
* I/O port space unconditionally. This means that the 2 I/O blocks are
* always adjacent and can therefore be treated as a single logical I/O port
* range. In practical terms: there only has to be a single tag and handle
* to access all registers.
*
* The following definitions are taken from or inspired by:
* Programmer's Guide to the EGA, VGA, and Super VGA Cards -- 3rd ed.,
* Richard F. Ferraro, Addison-Wesley, ISBN 0-201-62490-7
*/
#define VGA_MEM_BASE 0xA0000
#define VGA_MEM_SIZE 0x10000
#define VGA_REG_BASE 0x3c0
#define VGA_REG_SIZE 0x10+0x0c
/* Attribute controller registers. */
#define VGA_AC_WRITE 0x00
#define VGA_AC_READ 0x01
#define VGA_AC_PALETTE(x) (x) /* 0 <= x <= 15 */
#define VGA_AC_PAL_SR 0x20 /* Secondary red */
#define VGA_AC_PAL_SG 0x10 /* Secondary green */
#define VGA_AC_PAL_SB 0x08 /* Secondary blue */
#define VGA_AC_PAL_R 0x04 /* Red */
#define VGA_AC_PAL_G 0x02 /* Green */
#define VGA_AC_PAL_B 0x01 /* Blue */
#define VGA_AC_MODE_CONTROL (32+16)
#define VGA_AC_MC_IPS 0x80 /* Internal palette size */
#define VGA_AC_MC_PCS 0x40 /* Pixel clock select */
#define VGA_AC_MC_PPC 0x20 /* Pixel panning compat. */
#define VGA_AC_MC_BI 0x08 /* Blink/intensity */
#define VGA_AC_MC_ELG 0x04 /* Enable line graphics cc. */
#define VGA_AC_MC_DT 0x02 /* Display type */
#define VGA_AC_MC_GA 0x01 /* Graphics/alphanumeric */
#define VGA_AC_OVERSCAN_COLOR (32+17)
#define VGA_AC_COLOR_PLANE_ENABLE (32+18)
#define VGA_AC_HORIZ_PIXEL_PANNING (32+19)
#define VGA_AC_COLOR_SELECT (32+20)
#define VGA_AC_CS_C67 0x0C /* Color reg. addr. bits 6+7 */
#define VGA_AC_CS_C45 0x03 /* Color reg. addr. bits 4+5 */
/* General registers. */
#define VGA_GEN_MISC_OUTPUT_W 0x02 /* Write only. */
#define VGA_GEN_MISC_OUTPUT_R 0x0c /* Read only. */
#define VGA_GEN_MO_VSP 0x80 /* Vertical sync. polarity */
#define VGA_GEN_MO_HSP 0x40 /* Horiz. sync. polarity */
#define VGA_GEN_MO_PB 0x20 /* Page bit for odd/even */
#define VGA_GEN_MO_CS 0x0C /* Clock select */
#define VGA_GEN_MO_ER 0x02 /* Enable RAM */
#define VGA_GEN_MO_IOA 0x01 /* Input/output address */
#define VGA_GEN_INPUT_STAT_0 0x02 /* Read only. */
#define VGA_GEN_FEATURE_CTRL_W 0x1a /* Write only. */
#define VGA_GEN_FEATURE_CTRL_R 0x0a /* Read only. */
#define VGA_GEN_INPUT_STAT_1 0x1a /* Read only. */
#define VGA_GEN_IS1_VR 0x08 /* Vertical retrace */
#define VGA_GEN_IS1_DE 0x01 /* Display enable not */
/* Sequencer registers. */
#define VGA_SEQ_ADDRESS 0x04
#define VGA_SEQ_RESET 0
#define VGA_SEQ_RST_SR 0x02 /* Synchronous reset */
#define VGA_SEQ_RST_NAR 0x01 /* No async. reset */
#define VGA_SEQ_CLOCKING_MODE 1
#define VGA_SEQ_CM_SO 0x20 /* Screen off */
#define VGA_SEQ_CM_S4 0x10 /* Shift four */
#define VGA_SEQ_CM_DC 0x08 /* Dot clock */
#define VGA_SEQ_CM_SL 0x04 /* Shift load */
#define VGA_SEQ_CM_89 0x01 /* 8/9 Dot clocks */
#define VGA_SEQ_MAP_MASK 2
#define VGA_SEQ_MM_EM3 0x08 /* Enable memory plane 3 */
#define VGA_SEQ_MM_EM2 0x04 /* Enable memory plane 2 */
#define VGA_SEQ_MM_EM1 0x02 /* Enable memory plane 1 */
#define VGA_SEQ_MM_EM0 0x01 /* Enable memory plane 0 */
#define VGA_SEQ_CHAR_MAP_SELECT 3
#define VGA_SEQ_CMS_SAH 0x20 /* Char. A (bit 2) */
#define VGA_SEQ_CMS_SBH 0x10 /* Char. B (bit 2) */
#define VGA_SEQ_CMS_SA 0x0C /* Char. A (bit 0+1) */
#define VGA_SEQ_CMS_SB 0x03 /* Char. B (bit 0+1) */
#define VGA_SEQ_MEMORY_MODE 4
#define VGA_SEQ_MM_C4 0x08 /* Chain four */
#define VGA_SEQ_MM_OE 0x04 /* Odd/even */
#define VGA_SEQ_MM_EM 0x02 /* Extended memory */
#define VGA_SEQ_DATA 0x05
/* Color registers. */
#define VGA_PEL_MASK 0x06
#define VGA_PEL_ADDR_RD_MODE 0x07 /* Write only. */
#define VGA_DAC_STATE 0x07 /* Read only. */
#define VGA_PEL_ADDR_WR_MODE 0x08
#define VGA_PEL_DATA 0x09
/* Graphics controller registers. */
#define VGA_GC_ADDRESS 0x0e
#define VGA_GC_SET_RESET 0
#define VGA_GC_ENABLE_SET_RESET 1
#define VGA_GC_COLOR_COMPARE 2
#define VGA_GC_DATA_ROTATE 3
#define VGA_GC_DR_FS_XOR 0x18 /* Function select - XOR */
#define VGA_GC_DR_FS_OR 0x10 /* Function select - OR */
#define VGA_GC_DR_FS_AND 0x08 /* Function select - AND */
#define VGA_GC_DR_RC 0x07 /* Rotate count */
#define VGA_GC_READ_MAP_SELECT 4
#define VGA_GC_MODE 5
#define VGA_GC_MODE_SR 0x60 /* Shift register */
#define VGA_GC_MODE_OE 0x10 /* Odd/even */
#define VGA_GC_MODE_RM 0x08 /* Read mode */
#define VGA_GC_MODE_WM 0x03 /* Write mode */
#define VGA_GC_MISCELLANEOUS 6
#define VGA_GC_MISC_MM 0x0C /* memory map */
#define VGA_GC_MISC_COE 0x02 /* Chain odd/even */
#define VGA_GC_MISC_GA 0x01 /* Graphics/text mode */
#define VGA_GC_COLOR_DONT_CARE 7
#define VGA_GC_BIT_MASK 8
#define VGA_GC_DATA 0x0f
/* CRT controller registers. */
#define VGA_CRTC_ADDRESS 0x14
#define VGA_CRTC_HORIZ_TOTAL 0
#define VGA_CRTC_HORIZ_DISP_END 1
#define VGA_CRTC_START_HORIZ_BLANK 2
#define VGA_CRTC_END_HORIZ_BLANK 3
#define VGA_CRTC_EHB_CR 0x80 /* Compatible read */
#define VGA_CRTC_EHB_DES 0x60 /* Display enable skew */
#define VGA_CRTC_EHB_EHB 0x1F /* End horizontal blank */
#define VGA_CRTC_START_HORIZ_RETRACE 4
#define VGA_CRTC_END_HORIZ_RETRACE 5
#define VGA_CRTC_EHR_EHB 0x80 /* End horizontal blanking */
#define VGA_CRTC_EHR_HRD 0x60 /* Horizontal retrace delay */
#define VGA_CRTC_EHR_EHR 0x1F /* End horizontal retrace */
#define VGA_CRTC_VERT_TOTAL 6
#define VGA_CRTC_OVERFLOW 7
#define VGA_CRTC_OF_VRS9 0x80 /* Vertical retrace start */
#define VGA_CRTC_OF_VDE9 0x40 /* Vertical disp. enable end */
#define VGA_CRTC_OF_VT9 0x20 /* Vertical total (bit 9) */
#define VGA_CRTC_OF_LC8 0x10 /* Line compare */
#define VGA_CRTC_OF_VBS8 0x08 /* Start vertical blanking */
#define VGA_CRTC_OF_VRS8 0x04 /* Vertical retrace start */
#define VGA_CRTC_OF_VDE8 0x02 /* Vertical disp. enable end */
#define VGA_CRTC_OF_VT8 0x01 /* Vertical total (bit 8) */
#define VGA_CRTC_PRESET_ROW_SCAN 8
#define VGA_CRTC_PRS_BP 0x60 /* Byte panning */
#define VGA_CRTC_PRS_PRS 0x1F /* Preset row scan */
#define VGA_CRTC_MAX_SCAN_LINE 9
#define VGA_CRTC_MSL_2T4 0x80 /* 200-to-400 line conversion */
#define VGA_CRTC_MSL_LC9 0x40 /* Line compare (bit 9) */
#define VGA_CRTC_MSL_VBS9 0x20 /* Start vertical blanking */
#define VGA_CRTC_MSL_MSL 0x1F /* Maximum scan line */
#define VGA_CRTC_CURSOR_START 10
#define VGA_CRTC_CS_COO 0x20 /* Cursor on/off */
#define VGA_CRTC_CS_CS 0x1F /* Cursor start */
#define VGA_CRTC_CURSOR_END 11
#define VGA_CRTC_CE_CSK 0x60 /* Cursor skew */
#define VGA_CRTC_CE_CE 0x1F /* Cursor end */
#define VGA_CRTC_START_ADDR_HIGH 12
#define VGA_CRTC_START_ADDR_LOW 13
#define VGA_CRTC_CURSOR_LOC_HIGH 14
#define VGA_CRTC_CURSOR_LOC_LOW 15
#define VGA_CRTC_VERT_RETRACE_START 16
#define VGA_CRTC_VERT_RETRACE_END 17
#define VGA_CRTC_VRE_PR 0x80 /* Protect register 0-7 */
#define VGA_CRTC_VRE_BW 0x40 /* Bandwidth */
#define VGA_CRTC_VRE_VRE 0x1F /* Vertical retrace end */
#define VGA_CRTC_VERT_DISPLAY_END 18
#define VGA_CRTC_OFFSET 19
#define VGA_CRTC_UNDERLINE_LOC 20
#define VGA_CRTC_UL_DW 0x40 /* Double word mode */
#define VGA_CRTC_UL_CB4 0x20 /* Count by four */
#define VGA_CRTC_UL_UL 0x1F /* Underline location */
#define VGA_CRTC_START_VERT_BLANK 21
#define VGA_CRTC_END_VERT_BLANK 22
#define VGA_CRTC_MODE_CONTROL 23
#define VGA_CRTC_MC_HR 0x80 /* hardware reset */
#define VGA_CRTC_MC_WB 0x40 /* Word/byte mode */
#define VGA_CRTC_MC_AW 0x20 /* Address wrap */
#define VGA_CRTC_MC_CBT 0x08 /* Count by two */
#define VGA_CRTC_MC_HRS 0x04 /* Horizontal retrace select */
#define VGA_CRTC_MC_SRS 0x02 /* Select row scan counter */
#define VGA_CRTC_MC_CMS 0x01 /* Compatibility mode support */
#define VGA_CRTC_LINE_COMPARE 24
#define VGA_CRTC_DATA 0x15
#endif /* !_DEV_VT_HW_VGA_VGA_REG_H_ */

View File

@ -0,0 +1,212 @@
/*-
* Copyright (c) 2005 Rink Springer
* All rights reserved.
*
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were developed by Ed Schouten
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
#include <machine/pmap.h>
#include <machine/vmparam.h>
#include <machine/xbox.h>
struct xbox_softc {
bus_space_tag_t xbox_fb_tag;
bus_space_handle_t xbox_fb_handle;
};
/* Convenience macros. */
#define MEM_WRITE4(sc, ofs, val) \
bus_space_write_4(sc->xbox_fb_tag, sc->xbox_fb_handle, ofs, val)
#define VT_XBOX_WIDTH 640
#define VT_XBOX_HEIGHT 480
static vd_init_t xbox_init;
static vd_blank_t xbox_blank;
static vd_bitbltchr_t xbox_bitbltchr;
static const struct vt_driver vt_xbox_driver = {
.vd_init = xbox_init,
.vd_blank = xbox_blank,
.vd_bitbltchr = xbox_bitbltchr,
.vd_priority = VD_PRIORITY_GENERIC+1,
};
static struct xbox_softc xbox_conssoftc;
VT_CONSDEV_DECLARE(vt_xbox_driver, PIXEL_WIDTH(VT_XBOX_WIDTH),
PIXEL_HEIGHT(VT_XBOX_HEIGHT), &xbox_conssoftc);
static const uint32_t colormap[] = {
0x00000000, /* Black */
0x00ff0000, /* Red */
0x0000ff00, /* Green */
0x00c0c000, /* Brown */
0x000000ff, /* Blue */
0x00c000c0, /* Magenta */
0x0000c0c0, /* Cyan */
0x00c0c0c0, /* Light grey */
0x00808080, /* Dark grey */
0x00ff8080, /* Light red */
0x0080ff80, /* Light green */
0x00ffff80, /* Yellow */
0x008080ff, /* Light blue */
0x00ff80ff, /* Light magenta */
0x0080ffff, /* Light cyan */
0x00ffffff, /* White */
};
static void
xbox_blank(struct vt_device *vd, term_color_t color)
{
struct xbox_softc *sc = vd->vd_softc;
u_int ofs;
uint32_t c;
c = colormap[color];
for (ofs = 0; ofs < (VT_XBOX_WIDTH * VT_XBOX_HEIGHT) * 4; ofs += 4)
MEM_WRITE4(sc, ofs, c);
}
static void
xbox_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 xbox_softc *sc = vd->vd_softc;
u_long line;
uint32_t fgc, bgc;
int c;
uint8_t b, m;
fgc = colormap[fg];
bgc = colormap[bg];
/* Don't try to put off screen pixels */
if (((left + width) > info->fb_width) || ((top + height) >
info->fb_height))
return;
line = (VT_XBOX_WIDTH * top + left) * 4;
for (; height > 0; height--) {
for (c = 0; c < width; c++) {
if (c % 8 == 0)
b = *src++;
else
b <<= 1;
if (mask != NULL) {
if (c % 8 == 0)
m = *mask++;
else
m <<= 1;
/* Skip pixel write, if mask has no bit set. */
if ((m & 0x80) == 0)
continue;
}
MEM_WRITE4(sc, line + c * 4, b & 0x80 ? fgc : bgc);
}
line += VT_XBOX_WIDTH * 4;
}
}
static void
xbox_initialize(struct vt_device *vd)
{
int i;
/*
* We must make a mapping from video framebuffer memory
* to real. This is very crude: we map the entire
* videomemory to PAGE_SIZE! Since our kernel lives at
* it's relocated address range (0xc0xxxxxx), it won't
* care.
*
* We use address PAGE_SIZE and up so we can still trap
* NULL pointers. Once the real init is called, the
* mapping will be done via the OS and stored in a more
* sensible location ... but since we're not fully
* initialized, this is our only way to go :-(
*/
for (i = 0; i < (XBOX_FB_SIZE / PAGE_SIZE); i++) {
pmap_kenter(((i + 1) * PAGE_SIZE),
XBOX_FB_START + (i * PAGE_SIZE));
}
pmap_kenter((i + 1) * PAGE_SIZE,
XBOX_FB_START_PTR - XBOX_FB_START_PTR % PAGE_SIZE);
/* Ensure the framebuffer is where we want it to be. */
*(uint32_t *)((i + 1) * PAGE_SIZE + XBOX_FB_START_PTR % PAGE_SIZE) =
XBOX_FB_START;
/* Clear the screen. */
xbox_blank(vd, TC_BLACK);
}
static int
xbox_init(struct vt_device *vd)
{
struct xbox_softc *sc = vd->vd_softc;
if (!arch_i386_is_xbox)
return (CN_DEAD);
sc->xbox_fb_tag = I386_BUS_SPACE_MEM;
sc->xbox_fb_handle = PAGE_SIZE;
vd->vd_width = VT_XBOX_WIDTH;
vd->vd_height = VT_XBOX_HEIGHT;
xbox_initialize(vd);
return (CN_INTERNAL);
}
static void
xbox_remap(void *unused)
{
if (!arch_i386_is_xbox)
return;
xbox_conssoftc.xbox_fb_handle =
(bus_space_handle_t)pmap_mapdev(XBOX_FB_START, XBOX_FB_SIZE);
}
SYSINIT(xboxfb, SI_SUB_DRIVERS, SI_ORDER_ANY, xbox_remap, NULL);

View File

@ -0,0 +1,641 @@
/*-
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
unsigned int vt_logo_width = 257;
unsigned int vt_logo_height = 219;
unsigned int vt_logo_depth = 1;
unsigned char vt_logo_image[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff,
0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff,
0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xfc, 0x07,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1f, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff,
0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0x81, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0f, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf0, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff,
0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x07, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8,
0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc1,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x83, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff,
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc7, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x7f, 0xff, 0xff, 0xf1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f,
0xff, 0xff, 0xf3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xe3,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xc7, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xc7, 0xff, 0xff, 0xc7, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1,
0xff, 0xff, 0x8f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x0f,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0x07, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x0f, 0xfe, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x01, 0xf8, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x07,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1f,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff,
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00,
0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x07,
0xff, 0xf0, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff,
0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xfe, 0x00,
0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff,
0xe0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x1f,
0xf8, 0x00, 0x7f, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00,
0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x03, 0xfc, 0x00, 0xff,
0xe0, 0xff, 0xc0, 0x1f, 0x80, 0x0f, 0xfc, 0x00, 0x00, 0x3f, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x1f, 0xc0,
0x1f, 0x00, 0x01, 0xff, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3f, 0x00, 0x00, 0x7e, 0x01, 0xfc, 0x00, 0x07, 0x80, 0x3e, 0x00, 0x00,
0x7f, 0x80, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
0x3f, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1f, 0xc0, 0x00,
0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0x03, 0xf0,
0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x7c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x1f, 0x03, 0xe0, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x00, 0x07, 0xf0, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
0x03, 0xf0, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x1f, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0xf8, 0x00,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x03, 0xe0,
0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
0x00, 0x07, 0xfc, 0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f,
0xc0, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x1f, 0x03, 0xe0, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x1f, 0xff,
0x00, 0x00, 0x1f, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00,
0xf8, 0x00, 0x00, 0x1f, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
0x00, 0x7e, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x7f,
0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x3f, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00,
0xfc, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0xf8, 0x00, 0x00, 0x3f, 0x03, 0xf8,
0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xfc, 0x00, 0x00,
0x01, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff,
0xff, 0xc0, 0x00, 0xf8, 0x00, 0x00, 0x7e, 0x01, 0xfc, 0x00, 0x00, 0x00,
0x3e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xfc, 0x00, 0x00, 0x03, 0xfc, 0x07,
0xf8, 0x07, 0xfe, 0x03, 0xff, 0x00, 0x00, 0xff, 0xc0, 0x3f, 0xe0, 0x00,
0xfc, 0x00, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00,
0x00, 0x1f, 0x00, 0xfc, 0x00, 0x00, 0x07, 0xf0, 0x01, 0xf8, 0x0f, 0xf0,
0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x0f, 0xf0, 0x00, 0xfc, 0x00, 0x01,
0xfc, 0x00, 0xff, 0x80, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x1f, 0x00,
0xfc, 0x00, 0x00, 0x07, 0xe0, 0x00, 0xf8, 0x1f, 0xc0, 0x00, 0x3f, 0xc0,
0x03, 0xfc, 0x00, 0x03, 0xf8, 0x00, 0xfe, 0x00, 0x0f, 0xfc, 0x00, 0x7f,
0xe0, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xfe, 0x00, 0x00,
0x0f, 0xc0, 0x00, 0x78, 0x1f, 0x80, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00,
0x01, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x00, 0x00,
0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0xff, 0x00, 0x00, 0x0f, 0x80, 0x00,
0x00, 0x3f, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0xfc, 0x00,
0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x3e, 0x00, 0x00,
0x00, 0x0f, 0x80, 0xff, 0xff, 0xfc, 0x0f, 0x80, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x03, 0xf0, 0x07, 0xe0, 0x00, 0x00, 0x7e, 0x00, 0xff, 0xff, 0xff,
0xff, 0x00, 0x07, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80,
0xff, 0xff, 0xfc, 0x1f, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x03, 0xf0,
0x0f, 0xc0, 0x00, 0x00, 0x7e, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01,
0xff, 0xc0, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0xff, 0xff, 0xfe,
0x1f, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0xf0, 0x0f, 0x80, 0x00,
0x00, 0x3e, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x7f, 0xf0, 0x00,
0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0xff, 0xff, 0xfc, 0x1f, 0x00, 0x00,
0x00, 0xfc, 0x00, 0x00, 0x01, 0xf8, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x1f, 0xfc, 0x00, 0x3e, 0x00, 0x00,
0x00, 0x0f, 0x80, 0xff, 0xff, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x00,
0x00, 0x00, 0xf8, 0x1f, 0x80, 0x00, 0x00, 0x1f, 0x00, 0xfc, 0x00, 0x00,
0x07, 0xf0, 0x00, 0x07, 0xff, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80,
0xfe, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x01, 0xf8,
0x1f, 0x80, 0x00, 0x00, 0x1f, 0x00, 0xf8, 0x00, 0x00, 0x03, 0xf8, 0x00,
0x01, 0xff, 0x80, 0x3e, 0x00, 0x00, 0x00, 0x0f, 0x80, 0xfc, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff,
0xff, 0xff, 0x80, 0xf8, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x7f, 0xc0,
0x3e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80,
0xf8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0xe0, 0x3e, 0x00, 0x00,
0x00, 0x1f, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf8, 0x00, 0x00,
0x00, 0xfc, 0x00, 0x00, 0x0f, 0xf0, 0x3e, 0x00, 0x00, 0x00, 0x1f, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8,
0x1f, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00,
0x00, 0x03, 0xf8, 0x3e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xfc, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff,
0xff, 0xff, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x01, 0xf8,
0x3e, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0x00,
0xf8, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00,
0x00, 0x3e, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xfc, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00, 0x00, 0x7c, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x00,
0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc,
0x3e, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00,
0xf8, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00,
0x01, 0xf8, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00,
0x00, 0x7c, 0x00, 0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00, 0x03, 0xf0, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xfc, 0x00,
0x00, 0x00, 0xfc, 0x3e, 0x00, 0x00, 0x07, 0xe0, 0x00, 0xfc, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00,
0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x01, 0xfc,
0x3e, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x00, 0x1f, 0x80, 0x00, 0x0c, 0x00, 0x03, 0xf0, 0x00, 0x01, 0x80, 0x00,
0xf8, 0x00, 0x00, 0x01, 0xf8, 0x70, 0x00, 0x03, 0xf8, 0x3e, 0x00, 0x00,
0x1f, 0xc0, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0xc0,
0x00, 0x3e, 0x00, 0x03, 0xfc, 0x00, 0x03, 0xc0, 0x00, 0xf8, 0x00, 0x00,
0x03, 0xf8, 0xfc, 0x00, 0x07, 0xf8, 0x3f, 0x00, 0x00, 0x7f, 0x80, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x7e, 0x00,
0x01, 0xfe, 0x00, 0x0f, 0xe0, 0x00, 0xf8, 0x00, 0x00, 0x07, 0xf0, 0xff,
0x80, 0x0f, 0xf0, 0x3f, 0x00, 0x01, 0xff, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x03, 0xfe, 0x00, 0x00, 0xff, 0xc0,
0x3f, 0xc0, 0x00, 0xf8, 0x00, 0x00, 0x3f, 0xe0, 0xff, 0xf8, 0x7f, 0xe0,
0x3f, 0x80, 0x1f, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00,
0x00, 0x03, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xc0, 0x00,
0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff,
0xf8, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x01, 0xff,
0xff, 0xfc, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0xff,
0xff, 0x80, 0x7f, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0xe0, 0x00, 0x00,
0xfc, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf0, 0x00,
0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f,
0xff, 0xff, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x78, 0x00, 0x00,
0x1f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff,
0xf8, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x03, 0xff, 0xfc, 0x00,
0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0e, 0x00, 0x00,
0x00, 0x00, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00,
0x3f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
};

410
sys/dev/vt/vt.h Normal file
View File

@ -0,0 +1,410 @@
/*-
* Copyright (c) 2009, 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Portions of this software were developed by Oleksandr Rybalko
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _DEV_VT_VT_H_
#define _DEV_VT_VT_H_
#include <sys/param.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/callout.h>
#include <sys/condvar.h>
#include <sys/consio.h>
#include <sys/kbio.h>
#include <sys/mouse.h>
#include <sys/terminal.h>
#include <sys/sysctl.h>
#include "opt_syscons.h"
#ifndef VT_MAXWINDOWS
#ifdef MAXCONS
#define VT_MAXWINDOWS MAXCONS
#else
#define VT_MAXWINDOWS 12
#endif
#endif
#ifndef VT_ALT_TO_ESC_HACK
#define VT_ALT_TO_ESC_HACK 1
#endif
#define VT_CONSWINDOW 0
#if defined(SC_TWOBUTTON_MOUSE) || defined(VT_TWOBUTTON_MOUSE)
#define VT_MOUSE_PASTEBUTTON MOUSE_BUTTON3DOWN /* right button */
#define VT_MOUSE_EXTENDBUTTON MOUSE_BUTTON2DOWN /* not really used */
#else
#define VT_MOUSE_PASTEBUTTON MOUSE_BUTTON2DOWN /* middle button */
#define VT_MOUSE_EXTENDBUTTON MOUSE_BUTTON3DOWN /* right button */
#endif /* defined(SC_TWOBUTTON_MOUSE) || defined(VT_TWOBUTTON_MOUSE) */
#define SC_DRIVER_NAME "vt"
#define DPRINTF(_l, ...) if (vt_debug > (_l)) printf( __VA_ARGS__ )
#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG)
#define VT_SYSCTL_INT(_name, _default, _descr) \
static int vt_##_name = _default; \
SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RW, &vt_##_name, _default,\
_descr); \
TUNABLE_INT("kern.vt." #_name, &vt_##_name);
struct vt_driver;
void vt_allocate(struct vt_driver *, void *);
void vt_resume(void);
void vt_suspend(void);
typedef unsigned int vt_axis_t;
/*
* List of locks
* (d) locked by vd_lock
* (b) locked by vb_lock
* (G) locked by Giant
* (u) unlocked, locked by higher levels
* (c) const until freeing
* (?) yet to be determined
*/
/*
* Per-device datastructure.
*/
struct vt_device {
struct vt_window *vd_windows[VT_MAXWINDOWS]; /* (c) Windows. */
struct vt_window *vd_curwindow; /* (d) Current window. */
struct vt_window *vd_savedwindow;/* (?) Saved for suspend. */
struct vt_window *vd_markedwin; /* (?) Copy/paste buf owner. */
const struct vt_driver *vd_driver; /* (c) Graphics driver. */
void *vd_softc; /* (u) Driver data. */
uint16_t vd_mx; /* (?) Mouse X. */
uint16_t vd_my; /* (?) Mouse Y. */
vt_axis_t vd_mdirtyx; /* (?) Screen width. */
vt_axis_t vd_mdirtyy; /* (?) Screen height. */
uint32_t vd_mstate; /* (?) Mouse state. */
term_pos_t vd_offset; /* (?) Pixel offset. */
vt_axis_t vd_width; /* (?) Screen width. */
vt_axis_t vd_height; /* (?) Screen height. */
struct mtx vd_lock; /* Per-device lock. */
struct cv vd_winswitch; /* (d) Window switch notify. */
struct callout vd_timer; /* (d) Display timer. */
int vd_flags; /* (d) Device flags. */
#define VDF_TEXTMODE 0x01 /* Do text mode rendering. */
#define VDF_SPLASH 0x02 /* Splash screen active. */
#define VDF_ASYNC 0x04 /* vt_timer() running. */
#define VDF_INVALID 0x08 /* Entire screen should be re-rendered. */
#define VDF_DEAD 0x10 /* Early probing found nothing. */
#define VDF_INITIALIZED 0x20 /* vtterm_cnprobe already done. */
#define VDF_MOUSECURSOR 0x40 /* Mouse cursor visible. */
int vd_keyboard; /* (G) Keyboard index. */
unsigned int vd_kbstate; /* (?) Device unit. */
unsigned int vd_unit; /* (c) Device unit. */
};
/*
* Per-window terminal screen buffer.
*
* Because redrawing is performed asynchronously, the buffer keeps track
* of a rectangle that needs to be redrawn (vb_dirtyrect). Because this
* approach seemed to cause suboptimal performance (when the top left
* and the bottom right of the screen are modified), it also uses a set
* of bitmasks to keep track of the rows and columns (mod 64) that have
* been modified.
*/
struct vt_bufmask {
uint64_t vbm_row, vbm_col;
#define VBM_DIRTY UINT64_MAX
};
struct vt_buf {
struct mtx vb_lock; /* Buffer lock. */
term_pos_t vb_scr_size; /* (b) Screen dimensions. */
int vb_flags; /* (b) Flags. */
#define VBF_CURSOR 0x1 /* Cursor visible. */
#define VBF_STATIC 0x2 /* Buffer is statically allocated. */
#define VBF_MTX_INIT 0x4 /* Mutex initialized. */
#define VBF_SCROLL 0x8 /* scroll locked mode. */
#define VBF_HISTORY_FULL 0x10 /* All rows filled. */
int vb_history_size;
#define VBF_DEFAULT_HISTORY_SIZE 500
int vb_roffset; /* (b) History rows offset. */
int vb_curroffset; /* (b) Saved rows offset. */
term_pos_t vb_cursor; /* (u) Cursor position. */
term_pos_t vb_mark_start; /* (b) Copy region start. */
term_pos_t vb_mark_end; /* (b) Copy region end. */
int vb_mark_last; /* Last mouse event. */
term_rect_t vb_dirtyrect; /* (b) Dirty rectangle. */
struct vt_bufmask vb_dirtymask; /* (b) Dirty bitmasks. */
term_char_t *vb_buffer; /* (u) Data buffer. */
term_char_t **vb_rows; /* (u) Array of rows */
};
void vtbuf_copy(struct vt_buf *, const term_rect_t *, const term_pos_t *);
void vtbuf_fill_locked(struct vt_buf *, const term_rect_t *, term_char_t);
void vtbuf_init_early(struct vt_buf *);
void vtbuf_init(struct vt_buf *, const term_pos_t *);
void vtbuf_grow(struct vt_buf *, const term_pos_t *, int);
void vtbuf_putchar(struct vt_buf *, const term_pos_t *, term_char_t);
void vtbuf_cursor_position(struct vt_buf *, const term_pos_t *);
void vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row);
void vtbuf_cursor_visibility(struct vt_buf *, int);
void vtbuf_scroll_mode(struct vt_buf *vb, int yes);
void vtbuf_undirty(struct vt_buf *, term_rect_t *, struct vt_bufmask *);
void vtbuf_sethistory_size(struct vt_buf *, int);
int vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row);
int vtbuf_iscursor(struct vt_buf *vb, int row, int col);
int vtbuf_get_marked_len(struct vt_buf *vb);
void vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz);
#define VTB_MARK_NONE 0
#define VTB_MARK_END 1
#define VTB_MARK_START 2
#define VTB_MARK_WORD 3
#define VTB_MARK_ROW 4
#define VTB_MARK_EXTEND 5
#define VTB_MARK_MOVE 6
#define VTBUF_SLCK_ENABLE(vb) vtbuf_scroll_mode((vb), 1)
#define VTBUF_SLCK_DISABLE(vb) vtbuf_scroll_mode((vb), 0)
#define VTBUF_MAX_HEIGHT(vb) \
((vb)->vb_history_size)
#define VTBUF_GET_ROW(vb, r) \
((vb)->vb_rows[((vb)->vb_roffset + (r)) % VTBUF_MAX_HEIGHT(vb)])
#define VTBUF_GET_FIELD(vb, r, c) \
((vb)->vb_rows[((vb)->vb_roffset + (r)) % VTBUF_MAX_HEIGHT(vb)][(c)])
#define VTBUF_FIELD(vb, r, c) \
((vb)->vb_rows[((vb)->vb_curroffset + (r)) % VTBUF_MAX_HEIGHT(vb)][(c)])
#define VTBUF_ISCURSOR(vb, r, c) \
vtbuf_iscursor((vb), (r), (c))
#define VTBUF_DIRTYROW(mask, row) \
((mask)->vbm_row & ((uint64_t)1 << ((row) % 64)))
#define VTBUF_DIRTYCOL(mask, col) \
((mask)->vbm_col & ((uint64_t)1 << ((col) % 64)))
#define VTBUF_SPACE_CHAR (' ' | TC_WHITE << 26 | TC_BLACK << 29)
#define VHS_SET 0
#define VHS_CUR 1
#define VHS_END 2
int vthistory_seek(struct vt_buf *, int offset, int whence);
void vthistory_addlines(struct vt_buf *vb, int offset);
void vthistory_getpos(const struct vt_buf *, unsigned int *offset);
/*
* Per-window datastructure.
*/
struct vt_window {
struct vt_device *vw_device; /* (c) Device. */
struct terminal *vw_terminal; /* (c) Terminal. */
struct vt_buf vw_buf; /* (u) Screen buffer. */
struct vt_font *vw_font; /* (d) Graphical font. */
unsigned int vw_number; /* (c) Window number. */
int vw_kbdmode; /* (?) Keyboard mode. */
char *vw_kbdsq; /* Escape sequence queue*/
unsigned int vw_flags; /* (d) Per-window flags. */
#define VWF_BUSY 0x1 /* Busy reconfiguring device. */
#define VWF_OPENED 0x2 /* TTY in use. */
#define VWF_SCROLL 0x4 /* Keys influence scrollback. */
#define VWF_CONSOLE 0x8 /* Kernel message console window. */
#define VWF_VTYLOCK 0x10 /* Prevent window switch. */
#define VWF_MOUSE_HIDE 0x20 /* Disable mouse events processing. */
#define VWF_SWWAIT_REL 0x10000 /* Program wait for VT acquire is done. */
#define VWF_SWWAIT_ACQ 0x20000 /* Program wait for VT release is done. */
pid_t vw_pid; /* Terminal holding process */
struct proc *vw_proc;
struct vt_mode vw_smode; /* switch mode */
struct callout vw_proc_dead_timer;
struct vt_window *vw_switch_to;
};
#define VT_AUTO 0 /* switching is automatic */
#define VT_PROCESS 1 /* switching controlled by prog */
#define VT_KERNEL 255 /* switching controlled in kernel */
#define IS_VT_PROC_MODE(vw) ((vw)->vw_smode.mode == VT_PROCESS)
/*
* Per-device driver routines.
*
* vd_bitbltchr is used when the driver operates in graphics mode, while
* vd_putchar is used when the driver operates in text mode
* (VDF_TEXTMODE).
*/
typedef int vd_init_t(struct vt_device *vd);
typedef void vd_postswitch_t(struct vt_device *vd);
typedef void vd_blank_t(struct vt_device *vd, term_color_t color);
typedef void vd_bitbltchr_t(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);
typedef void vd_putchar_t(struct vt_device *vd, term_char_t,
vt_axis_t top, vt_axis_t left, term_color_t fg, term_color_t bg);
struct vt_driver {
/* Console attachment. */
vd_init_t *vd_init;
/* Drawing. */
vd_blank_t *vd_blank;
vd_bitbltchr_t *vd_bitbltchr;
/* Text mode operation. */
vd_putchar_t *vd_putchar;
/* Update display setting on vt switch. */
vd_postswitch_t *vd_postswitch;
/* Priority to know which one can override */
int vd_priority;
#define VD_PRIORITY_DUMB 10
#define VD_PRIORITY_GENERIC 100
#define VD_PRIORITY_SPECIFIC 1000
};
/*
* Console device madness.
*
* Utility macro to make early vt(4) instances work.
*/
extern const struct terminal_class vt_termclass;
void vt_upgrade(struct vt_device *vd);
#define PIXEL_WIDTH(w) ((w) / 8)
#define PIXEL_HEIGHT(h) ((h) / 16)
#ifndef VT_FB_DEFAULT_WIDTH
#define VT_FB_DEFAULT_WIDTH 640
#endif
#ifndef VT_FB_DEFAULT_HEIGHT
#define VT_FB_DEFAULT_HEIGHT 480
#endif
#define VT_CONSDEV_DECLARE(driver, width, height, softc) \
static struct terminal driver ## _consterm; \
static struct vt_window driver ## _conswindow; \
static struct vt_device driver ## _consdev = { \
.vd_driver = &driver, \
.vd_softc = (softc), \
.vd_flags = VDF_INVALID, \
.vd_windows = { [VT_CONSWINDOW] = &driver ## _conswindow, }, \
.vd_curwindow = &driver ## _conswindow, \
.vd_markedwin = NULL, \
.vd_kbstate = 0, \
}; \
static term_char_t driver ## _constextbuf[(width) * \
(VBF_DEFAULT_HISTORY_SIZE)]; \
static term_char_t *driver ## _constextbufrows[ \
VBF_DEFAULT_HISTORY_SIZE]; \
static struct vt_window driver ## _conswindow = { \
.vw_number = VT_CONSWINDOW, \
.vw_flags = VWF_CONSOLE, \
.vw_buf = { \
.vb_buffer = driver ## _constextbuf, \
.vb_rows = driver ## _constextbufrows, \
.vb_history_size = VBF_DEFAULT_HISTORY_SIZE, \
.vb_curroffset = 0, \
.vb_roffset = 0, \
.vb_flags = VBF_STATIC, \
.vb_mark_start = { \
.tp_row = 0, \
.tp_col = 0, \
}, \
.vb_mark_end = { \
.tp_row = 0, \
.tp_col = 0, \
}, \
.vb_scr_size = { \
.tp_row = height, \
.tp_col = width, \
}, \
}, \
.vw_device = &driver ## _consdev, \
.vw_terminal = &driver ## _consterm, \
.vw_kbdmode = K_XLATE, \
}; \
TERMINAL_DECLARE_EARLY(driver ## _consterm, vt_termclass, \
&driver ## _conswindow); \
SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, \
vt_upgrade, &driver ## _consdev)
/*
* Fonts.
*
* Remapping tables are used to map Unicode points to glyphs. They need
* to be sorted, because vtfont_lookup() performs a binary search. Each
* font has two remapping tables, for normal and bold. When a character
* is not present in bold, it uses a normal glyph. When no glyph is
* available, it uses glyph 0, which is normally equal to U+FFFD.
*/
struct vt_font_map {
uint32_t vfm_src;
uint16_t vfm_dst;
uint16_t vfm_len;
};
struct vt_font {
struct vt_font_map *vf_bold;
struct vt_font_map *vf_normal;
uint8_t *vf_bytes;
unsigned int vf_height, vf_width,
vf_normal_length, vf_bold_length;
unsigned int vf_refcount;
};
struct mouse_cursor {
uint8_t map[64 * 64 / 8];
uint8_t mask[64 * 64 / 8];
uint8_t w;
uint8_t h;
};
const uint8_t *vtfont_lookup(const struct vt_font *vf, term_char_t c);
struct vt_font *vtfont_ref(struct vt_font *vf);
void vtfont_unref(struct vt_font *vf);
int vtfont_load(vfnt_t *f, struct vt_font **ret);
/* Sysmouse. */
void sysmouse_process_event(mouse_info_t *mi);
void vt_mouse_event(int type, int x, int y, int event, int cnt);
void vt_mouse_state(int show);
#define VT_MOUSE_SHOW 1
#define VT_MOUSE_HIDE 0
#endif /* !_DEV_VT_VT_H_ */

730
sys/dev/vt/vt_buf.c Normal file
View File

@ -0,0 +1,730 @@
/*-
* Copyright (c) 2009, 2013 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Portions of this software were developed by Oleksandr Rybalko
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer");
#define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock)
#define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock)
#define POS_INDEX(c, r) (((r) << 12) + (c))
#define POS_COPY(d, s) do { \
(d).tp_col = (s).tp_col; \
(d).tp_row = (s).tp_row; \
} while (0)
/*
* line4
* line5 <--- curroffset (terminal output to that line)
* line0
* line1 <--- roffset (history display from that point)
* line2
* line3
*/
int
vthistory_seek(struct vt_buf *vb, int offset, int whence)
{
int diff, top, bottom, roffset;
/* No scrolling if not enabled. */
if ((vb->vb_flags & VBF_SCROLL) == 0) {
if (vb->vb_roffset != vb->vb_curroffset) {
vb->vb_roffset = vb->vb_curroffset;
return (0xffff);
}
return (0); /* No changes */
}
top = (vb->vb_flags & VBF_HISTORY_FULL)?
(vb->vb_curroffset + vb->vb_scr_size.tp_row):vb->vb_history_size;
bottom = vb->vb_curroffset + vb->vb_history_size;
/*
* Operate on copy of offset value, since it temporary can be bigger
* than amount of rows in buffer.
*/
roffset = vb->vb_roffset + vb->vb_history_size;
switch (whence) {
case VHS_SET:
roffset = offset + vb->vb_history_size;
break;
case VHS_CUR:
roffset += offset;
break;
case VHS_END:
/* Go to current offset. */
roffset = vb->vb_curroffset + vb->vb_history_size;
break;
}
roffset = (roffset < top)?top:roffset;
roffset = (roffset > bottom)?bottom:roffset;
roffset %= vb->vb_history_size;
if (vb->vb_roffset != roffset) {
diff = vb->vb_roffset - roffset;
vb->vb_roffset = roffset;
/*
* Offset changed, please update Nth lines on sceen.
* +N - Nth lines at top;
* -N - Nth lines at bottom.
*/
return (diff);
}
return (0); /* No changes */
}
void
vthistory_addlines(struct vt_buf *vb, int offset)
{
vb->vb_curroffset += offset;
if (vb->vb_curroffset < 0)
vb->vb_curroffset = 0;
vb->vb_curroffset %= vb->vb_history_size;
if ((vb->vb_flags & VBF_SCROLL) == 0) {
vb->vb_roffset = vb->vb_curroffset;
}
}
void
vthistory_getpos(const struct vt_buf *vb, unsigned int *offset)
{
*offset = vb->vb_roffset;
}
/* Translate current view row number to history row. */
static int
vtbuf_wth(struct vt_buf *vb, int row)
{
return ((vb->vb_roffset + row) % vb->vb_history_size);
}
/* Translate history row to current view row number. */
static int
vtbuf_htw(struct vt_buf *vb, int row)
{
/*
* total 1000 rows.
* History offset roffset winrow
* 205 200 ((205 - 200 + 1000) % 1000) = 5
* 90 990 ((90 - 990 + 1000) % 1000) = 100
*/
return ((row - vb->vb_roffset + vb->vb_history_size) %
vb->vb_history_size);
}
int
vtbuf_iscursor(struct vt_buf *vb, int row, int col)
{
int sc, sr, ec, er, tmp;
if ((vb->vb_flags & (VBF_CURSOR|VBF_SCROLL)) == VBF_CURSOR &&
(vb->vb_cursor.tp_row == row) && (vb->vb_cursor.tp_col == col))
return (1);
/* Mark cut/paste region. */
/*
* Luckily screen view is not like circular buffer, so we will
* calculate in screen coordinates. Translate first.
*/
sc = vb->vb_mark_start.tp_col;
sr = vtbuf_htw(vb, vb->vb_mark_start.tp_row);
ec = vb->vb_mark_end.tp_col;
er = vtbuf_htw(vb, vb->vb_mark_end.tp_row);
/* Swap start and end if start > end. */
if (POS_INDEX(sc, sr) > POS_INDEX(ec, er)) {
tmp = sc; sc = ec; ec = tmp;
tmp = sr; sr = er; er = tmp;
}
if ((POS_INDEX(sc, sr) <= POS_INDEX(col, row)) &&
(POS_INDEX(col, row) < POS_INDEX(ec, er)))
return (1);
return (0);
}
static inline uint64_t
vtbuf_dirty_axis(unsigned int begin, unsigned int end)
{
uint64_t left, right, mask;
/*
* Mark all bits between begin % 64 and end % 64 dirty.
* This code is functionally equivalent to:
*
* for (i = begin; i < end; i++)
* mask |= (uint64_t)1 << (i % 64);
*/
/* Obvious case. Mark everything dirty. */
if (end - begin >= 64)
return (VBM_DIRTY);
/* 1....0; used bits on the left. */
left = VBM_DIRTY << begin % 64;
/* 0....1; used bits on the right. */
right = VBM_DIRTY >> -end % 64;
/*
* Only take the intersection. If the result of that is 0, it
* means that the selection crossed a 64 bit boundary along the
* way, which means we have to take the complement.
*/
mask = left & right;
if (mask == 0)
mask = left | right;
return (mask);
}
static inline void
vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area)
{
VTBUF_LOCK(vb);
if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row)
vb->vb_dirtyrect.tr_begin.tp_row = area->tr_begin.tp_row;
if (vb->vb_dirtyrect.tr_begin.tp_col > area->tr_begin.tp_col)
vb->vb_dirtyrect.tr_begin.tp_col = area->tr_begin.tp_col;
if (vb->vb_dirtyrect.tr_end.tp_row < area->tr_end.tp_row)
vb->vb_dirtyrect.tr_end.tp_row = area->tr_end.tp_row;
if (vb->vb_dirtyrect.tr_end.tp_col < area->tr_end.tp_col)
vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col;
vb->vb_dirtymask.vbm_row |=
vtbuf_dirty_axis(area->tr_begin.tp_row, area->tr_end.tp_row);
vb->vb_dirtymask.vbm_col |=
vtbuf_dirty_axis(area->tr_begin.tp_col, area->tr_end.tp_col);
VTBUF_UNLOCK(vb);
}
static inline void
vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p)
{
term_rect_t area;
area.tr_begin = *p;
area.tr_end.tp_row = p->tp_row + 1;
area.tr_end.tp_col = p->tp_col + 1;
vtbuf_dirty(vb, &area);
}
static void
vtbuf_make_undirty(struct vt_buf *vb)
{
vb->vb_dirtyrect.tr_begin = vb->vb_scr_size;
vb->vb_dirtyrect.tr_end.tp_row = vb->vb_dirtyrect.tr_end.tp_col = 0;
vb->vb_dirtymask.vbm_row = vb->vb_dirtymask.vbm_col = 0;
}
void
vtbuf_undirty(struct vt_buf *vb, term_rect_t *r, struct vt_bufmask *m)
{
VTBUF_LOCK(vb);
*r = vb->vb_dirtyrect;
*m = vb->vb_dirtymask;
vtbuf_make_undirty(vb);
VTBUF_UNLOCK(vb);
}
void
vtbuf_copy(struct vt_buf *vb, const term_rect_t *r, const term_pos_t *p2)
{
const term_pos_t *p1 = &r->tr_begin;
term_rect_t area;
unsigned int rows, cols;
int pr, rdiff;
KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row,
("vtbuf_copy begin.tp_row %d must be less than screen width %d",
r->tr_begin.tp_row, vb->vb_scr_size.tp_row));
KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col,
("vtbuf_copy begin.tp_col %d must be less than screen height %d",
r->tr_begin.tp_col, vb->vb_scr_size.tp_col));
KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row,
("vtbuf_copy end.tp_row %d must be less than screen width %d",
r->tr_end.tp_row, vb->vb_scr_size.tp_row));
KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col,
("vtbuf_copy end.tp_col %d must be less than screen height %d",
r->tr_end.tp_col, vb->vb_scr_size.tp_col));
KASSERT(p2->tp_row < vb->vb_scr_size.tp_row,
("vtbuf_copy tp_row %d must be less than screen width %d",
p2->tp_row, vb->vb_scr_size.tp_row));
KASSERT(p2->tp_col < vb->vb_scr_size.tp_col,
("vtbuf_copy tp_col %d must be less than screen height %d",
p2->tp_col, vb->vb_scr_size.tp_col));
rows = r->tr_end.tp_row - r->tr_begin.tp_row;
rdiff = r->tr_begin.tp_row - p2->tp_row;
cols = r->tr_end.tp_col - r->tr_begin.tp_col;
if (r->tr_begin.tp_row > p2->tp_row && r->tr_begin.tp_col == 0 &&
r->tr_end.tp_col == vb->vb_scr_size.tp_col && /* Full row. */
(rows + rdiff) == vb->vb_scr_size.tp_row && /* Whole screen. */
rdiff > 0) { /* Only forward dirrection. Do not eat history. */
vthistory_addlines(vb, rdiff);
} else if (p2->tp_row < p1->tp_row) {
/* Handle overlapping copies of line segments. */
/* Move data up. */
for (pr = 0; pr < rows; pr++)
memmove(
&VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col),
&VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col),
cols * sizeof(term_char_t));
} else {
/* Move data down. */
for (pr = rows - 1; pr >= 0; pr--)
memmove(
&VTBUF_FIELD(vb, p2->tp_row + pr, p2->tp_col),
&VTBUF_FIELD(vb, p1->tp_row + pr, p1->tp_col),
cols * sizeof(term_char_t));
}
area.tr_begin = *p2;
area.tr_end.tp_row = MIN(p2->tp_row + rows, vb->vb_scr_size.tp_row);
area.tr_end.tp_col = MIN(p2->tp_col + cols, vb->vb_scr_size.tp_col);
vtbuf_dirty(vb, &area);
}
static void
vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
{
unsigned int pr, pc;
term_char_t *row;
for (pr = r->tr_begin.tp_row; pr < r->tr_end.tp_row; pr++) {
row = vb->vb_rows[(vb->vb_curroffset + pr) %
VTBUF_MAX_HEIGHT(vb)];
for (pc = r->tr_begin.tp_col; pc < r->tr_end.tp_col; pc++) {
row[pc] = c;
}
}
}
void
vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c)
{
KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row,
("vtbuf_fill_locked begin.tp_row %d must be < screen width %d",
r->tr_begin.tp_row, vb->vb_scr_size.tp_row));
KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col,
("vtbuf_fill_locked begin.tp_col %d must be < screen height %d",
r->tr_begin.tp_col, vb->vb_scr_size.tp_col));
KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row,
("vtbuf_fill_locked end.tp_row %d must be <= screen width %d",
r->tr_end.tp_row, vb->vb_scr_size.tp_row));
KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col,
("vtbuf_fill_locked end.tp_col %d must be <= screen height %d",
r->tr_end.tp_col, vb->vb_scr_size.tp_col));
VTBUF_LOCK(vb);
vtbuf_fill(vb, r, c);
VTBUF_UNLOCK(vb);
vtbuf_dirty(vb, r);
}
static void
vtbuf_init_rows(struct vt_buf *vb)
{
int r;
vb->vb_history_size = MAX(vb->vb_history_size, vb->vb_scr_size.tp_row);
for (r = 0; r < vb->vb_history_size; r++)
vb->vb_rows[r] = &vb->vb_buffer[r *
vb->vb_scr_size.tp_col];
}
void
vtbuf_init_early(struct vt_buf *vb)
{
vb->vb_flags |= VBF_CURSOR;
vb->vb_roffset = 0;
vb->vb_curroffset = 0;
vb->vb_mark_start.tp_row = 0;
vb->vb_mark_start.tp_col = 0;
vb->vb_mark_end.tp_row = 0;
vb->vb_mark_end.tp_col = 0;
vtbuf_init_rows(vb);
vtbuf_make_undirty(vb);
if ((vb->vb_flags & VBF_MTX_INIT) == 0) {
mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN);
vb->vb_flags |= VBF_MTX_INIT;
}
}
void
vtbuf_init(struct vt_buf *vb, const term_pos_t *p)
{
int sz;
vb->vb_scr_size = *p;
vb->vb_history_size = VBF_DEFAULT_HISTORY_SIZE;
if ((vb->vb_flags & VBF_STATIC) == 0) {
sz = vb->vb_history_size * p->tp_col * sizeof(term_char_t);
vb->vb_buffer = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO);
sz = vb->vb_history_size * sizeof(term_char_t *);
vb->vb_rows = malloc(sz, M_VTBUF, M_WAITOK | M_ZERO);
}
vtbuf_init_early(vb);
}
void
vtbuf_sethistory_size(struct vt_buf *vb, int size)
{
term_pos_t p;
/* With same size */
p.tp_row = vb->vb_scr_size.tp_row;
p.tp_col = vb->vb_scr_size.tp_col;
vtbuf_grow(vb, &p, size);
}
void
vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, int history_size)
{
term_char_t *old, *new, **rows, **oldrows, **copyrows, *row;
int bufsize, rowssize, w, h, c, r;
term_rect_t rect;
history_size = MAX(history_size, p->tp_row);
if (history_size > vb->vb_history_size || p->tp_col >
vb->vb_scr_size.tp_col) {
/* Allocate new buffer. */
bufsize = history_size * p->tp_col * sizeof(term_char_t);
new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO);
rowssize = history_size * sizeof(term_pos_t *);
rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO);
/* Toggle it. */
VTBUF_LOCK(vb);
old = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_buffer;
oldrows = vb->vb_flags & VBF_STATIC ? NULL : vb->vb_rows;
copyrows = vb->vb_rows;
w = vb->vb_scr_size.tp_col;
h = vb->vb_history_size;
vb->vb_history_size = history_size;
vb->vb_buffer = new;
vb->vb_rows = rows;
vb->vb_flags &= ~VBF_STATIC;
vb->vb_scr_size = *p;
vtbuf_init_rows(vb);
/* Copy history and fill extra space. */
for (r = 0; r < history_size; r ++) {
row = rows[r];
if (r < h) { /* Copy. */
memmove(rows[r], copyrows[r],
MIN(p->tp_col, w) * sizeof(term_char_t));
for (c = MIN(p->tp_col, w); c < p->tp_col;
c++) {
row[c] = VTBUF_SPACE_CHAR;
}
} else { /* Just fill. */
rect.tr_begin.tp_col = 0;
rect.tr_begin.tp_row = r;
rect.tr_end.tp_col = p->tp_col;
rect.tr_end.tp_row = p->tp_row;
vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR);
break;
}
}
vtbuf_make_undirty(vb);
VTBUF_UNLOCK(vb);
/* Deallocate old buffer. */
free(old, M_VTBUF);
free(oldrows, M_VTBUF);
}
}
void
vtbuf_putchar(struct vt_buf *vb, const term_pos_t *p, term_char_t c)
{
term_char_t *row;
KASSERT(p->tp_row < vb->vb_scr_size.tp_row,
("vtbuf_putchar tp_row %d must be less than screen width %d",
p->tp_row, vb->vb_scr_size.tp_row));
KASSERT(p->tp_col < vb->vb_scr_size.tp_col,
("vtbuf_putchar tp_col %d must be less than screen height %d",
p->tp_col, vb->vb_scr_size.tp_col));
row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) %
VTBUF_MAX_HEIGHT(vb)];
if (row[p->tp_col] != c) {
VTBUF_LOCK(vb);
row[p->tp_col] = c;
VTBUF_UNLOCK(vb);
vtbuf_dirty_cell(vb, p);
}
}
void
vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p)
{
if (vb->vb_flags & VBF_CURSOR) {
vtbuf_dirty_cell(vb, &vb->vb_cursor);
vb->vb_cursor = *p;
vtbuf_dirty_cell(vb, &vb->vb_cursor);
} else {
vb->vb_cursor = *p;
}
}
void
vtbuf_mouse_cursor_position(struct vt_buf *vb, int col, int row)
{
term_rect_t area;
area.tr_begin.tp_row = MAX(row - 1, 0);
area.tr_begin.tp_col = MAX(col - 1, 0);
area.tr_end.tp_row = MIN(row + 2, vb->vb_scr_size.tp_row);
area.tr_end.tp_col = MIN(col + 2, vb->vb_scr_size.tp_col);
vtbuf_dirty(vb, &area);
}
static void
vtbuf_flush_mark(struct vt_buf *vb)
{
term_rect_t area;
int s, e;
/* Notify renderer to update marked region. */
if (vb->vb_mark_start.tp_col || vb->vb_mark_end.tp_col ||
vb->vb_mark_start.tp_row || vb->vb_mark_end.tp_row) {
s = vtbuf_htw(vb, vb->vb_mark_start.tp_row);
e = vtbuf_htw(vb, vb->vb_mark_end.tp_row);
area.tr_begin.tp_col = 0;
area.tr_begin.tp_row = MIN(s, e);
area.tr_end.tp_col = vb->vb_scr_size.tp_col;
area.tr_end.tp_row = MAX(s, e) + 1;
vtbuf_dirty(vb, &area);
}
}
int
vtbuf_get_marked_len(struct vt_buf *vb)
{
int ei, si, sz;
term_pos_t s, e;
/* Swap according to window coordinates. */
if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row),
vb->vb_mark_start.tp_col) >
POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row),
vb->vb_mark_end.tp_col)) {
POS_COPY(e, vb->vb_mark_start);
POS_COPY(s, vb->vb_mark_end);
} else {
POS_COPY(s, vb->vb_mark_start);
POS_COPY(e, vb->vb_mark_end);
}
si = s.tp_row * vb->vb_scr_size.tp_col + s.tp_col;
ei = e.tp_row * vb->vb_scr_size.tp_col + e.tp_col;
/* Number symbols and number of rows to inject \n */
sz = ei - si + ((e.tp_row - s.tp_row) * 2) + 1;
return (sz * sizeof(term_char_t));
}
void
vtbuf_extract_marked(struct vt_buf *vb, term_char_t *buf, int sz)
{
int i, r, c, cs, ce;
term_pos_t s, e;
/* Swap according to window coordinates. */
if (POS_INDEX(vtbuf_htw(vb, vb->vb_mark_start.tp_row),
vb->vb_mark_start.tp_col) >
POS_INDEX(vtbuf_htw(vb, vb->vb_mark_end.tp_row),
vb->vb_mark_end.tp_col)) {
POS_COPY(e, vb->vb_mark_start);
POS_COPY(s, vb->vb_mark_end);
} else {
POS_COPY(s, vb->vb_mark_start);
POS_COPY(e, vb->vb_mark_end);
}
i = 0;
for (r = s.tp_row; r <= e.tp_row; r ++) {
cs = (r == s.tp_row)?s.tp_col:0;
ce = (r == e.tp_row)?e.tp_col:vb->vb_scr_size.tp_col;
for (c = cs; c < ce; c ++) {
buf[i++] = vb->vb_rows[r][c];
}
/* Add new line for all rows, but not for last one. */
if (r != e.tp_row) {
buf[i++] = '\r';
buf[i++] = '\n';
}
}
}
int
vtbuf_set_mark(struct vt_buf *vb, int type, int col, int row)
{
term_char_t *r;
int i;
switch (type) {
case VTB_MARK_END: /* B1 UP */
if (vb->vb_mark_last != VTB_MARK_MOVE)
return (0);
/* FALLTHROUGH */
case VTB_MARK_MOVE:
case VTB_MARK_EXTEND:
vtbuf_flush_mark(vb); /* Clean old mark. */
vb->vb_mark_end.tp_col = col;
vb->vb_mark_end.tp_row = vtbuf_wth(vb, row);
break;
case VTB_MARK_START:
vtbuf_flush_mark(vb); /* Clean old mark. */
vb->vb_mark_start.tp_col = col;
vb->vb_mark_start.tp_row = vtbuf_wth(vb, row);
/* Start again, so clear end point. */
vb->vb_mark_end.tp_col = col;
vb->vb_mark_end.tp_row = vtbuf_wth(vb, row);
break;
case VTB_MARK_WORD:
vtbuf_flush_mark(vb); /* Clean old mark. */
vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row =
vtbuf_wth(vb, row);
r = vb->vb_rows[vb->vb_mark_start.tp_row];
for (i = col; i >= 0; i --) {
if (TCHAR_CHARACTER(r[i]) == ' ') {
vb->vb_mark_start.tp_col = i + 1;
break;
}
}
for (i = col; i < vb->vb_scr_size.tp_col; i ++) {
if (TCHAR_CHARACTER(r[i]) == ' ') {
vb->vb_mark_end.tp_col = i;
break;
}
}
if (vb->vb_mark_start.tp_col > vb->vb_mark_end.tp_col)
vb->vb_mark_start.tp_col = vb->vb_mark_end.tp_col;
break;
case VTB_MARK_ROW:
vtbuf_flush_mark(vb); /* Clean old mark. */
vb->vb_mark_start.tp_col = 0;
vb->vb_mark_end.tp_col = vb->vb_scr_size.tp_col;
vb->vb_mark_start.tp_row = vb->vb_mark_end.tp_row =
vtbuf_wth(vb, row);
break;
case VTB_MARK_NONE:
vb->vb_mark_last = type;
/* FALLTHROUGH */
default:
/* panic? */
return (0);
}
vb->vb_mark_last = type;
/* Draw new marked region. */
vtbuf_flush_mark(vb);
return (1);
}
void
vtbuf_cursor_visibility(struct vt_buf *vb, int yes)
{
int oflags, nflags;
VTBUF_LOCK(vb);
oflags = vb->vb_flags;
if (yes)
vb->vb_flags |= VBF_CURSOR;
else
vb->vb_flags &= ~VBF_CURSOR;
nflags = vb->vb_flags;
VTBUF_UNLOCK(vb);
if (oflags != nflags)
vtbuf_dirty_cell(vb, &vb->vb_cursor);
}
void
vtbuf_scroll_mode(struct vt_buf *vb, int yes)
{
int oflags, nflags;
VTBUF_LOCK(vb);
oflags = vb->vb_flags;
if (yes)
vb->vb_flags |= VBF_SCROLL;
else
vb->vb_flags &= ~VBF_SCROLL;
nflags = vb->vb_flags;
VTBUF_UNLOCK(vb);
if (oflags != nflags)
vtbuf_dirty_cell(vb, &vb->vb_cursor);
}

View File

@ -0,0 +1,79 @@
/*-
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/consio.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
static d_ioctl_t consolectl_ioctl;
static struct cdevsw consolectl_cdevsw = {
.d_version = D_VERSION,
.d_ioctl = consolectl_ioctl,
.d_name = "consolectl",
};
static int
consolectl_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
{
switch (cmd) {
case CONS_GETVERS:
*(int*)data = 0x200;
return 0;
case CONS_MOUSECTL: {
mouse_info_t *mi = (mouse_info_t*)data;
sysmouse_process_event(mi);
return (0);
}
default:
printf("consolectl: unknown ioctl: %c:%lx\n",
(char)IOCGROUP(cmd), IOCBASECMD(cmd));
return (ENOIOCTL);
}
}
static void
consolectl_drvinit(void *unused)
{
make_dev(&consolectl_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"consolectl");
}
SYSINIT(consolectl, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, consolectl_drvinit, NULL);

1822
sys/dev/vt/vt_core.c Normal file

File diff suppressed because it is too large Load Diff

212
sys/dev/vt/vt_font.c Normal file
View File

@ -0,0 +1,212 @@
/*-
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/refcount.h>
#include <sys/systm.h>
#include <dev/vt/vt.h>
static MALLOC_DEFINE(M_VTFONT, "vtfont", "vt font");
/* Some limits to prevent abnormal fonts from being loaded. */
#define VTFONT_MAXMAPPINGS 1024
#define VTFONT_MAXGLYPHSIZE 262144
#define VTFONT_MAXDIMENSION 128
static uint16_t
vtfont_bisearch(const struct vt_font_map *map, unsigned int len, uint32_t src)
{
int min, mid, max;
min = 0;
max = len - 1;
/* Empty font map. */
if (len == 0)
return (0);
/* Character below minimal entry. */
if (src < map[0].vfm_src)
return (0);
/* Optimization: ASCII characters occur very often. */
if (src <= map[0].vfm_src + map[0].vfm_len)
return (src - map[0].vfm_src + map[0].vfm_dst);
/* Character above maximum entry. */
if (src > map[max].vfm_src + map[max].vfm_len)
return (0);
/* Binary search. */
while (max >= min) {
mid = (min + max) / 2;
if (src < map[mid].vfm_src)
max = mid - 1;
else if (src > map[mid].vfm_src + map[mid].vfm_len)
min = mid + 1;
else
return (src - map[mid].vfm_src + map[mid].vfm_dst);
}
return (0);
}
const uint8_t *
vtfont_lookup(const struct vt_font *vf, term_char_t c)
{
uint32_t src;
uint16_t dst;
size_t stride;
src = TCHAR_CHARACTER(c);
if (TCHAR_FORMAT(c) & TF_BOLD) {
dst = vtfont_bisearch(vf->vf_bold, vf->vf_bold_length, src);
if (dst != 0)
goto found;
}
dst = vtfont_bisearch(vf->vf_normal, vf->vf_normal_length, src);
found:
stride = howmany(vf->vf_width, 8) * vf->vf_height;
return (&vf->vf_bytes[dst * stride]);
}
struct vt_font *
vtfont_ref(struct vt_font *vf)
{
refcount_acquire(&vf->vf_refcount);
return (vf);
}
void
vtfont_unref(struct vt_font *vf)
{
if (refcount_release(&vf->vf_refcount)) {
free(vf->vf_normal, M_VTFONT);
free(vf->vf_bold, M_VTFONT);
free(vf->vf_bytes, M_VTFONT);
free(vf, M_VTFONT);
}
}
static int
vtfont_validate_map(struct vt_font_map *vfm, unsigned int length,
unsigned int nglyphs)
{
unsigned int i, last = 0;
for (i = 0; i < length; i++) {
/* Not ordered. */
if (i > 0 && vfm[i].vfm_src <= last)
return (EINVAL);
/*
* Destination extends amount of glyphs.
*/
if (vfm[i].vfm_dst >= nglyphs ||
vfm[i].vfm_dst + vfm[i].vfm_len >= nglyphs)
return (EINVAL);
last = vfm[i].vfm_src + vfm[i].vfm_len;
}
return (0);
}
int
vtfont_load(vfnt_t *f, struct vt_font **ret)
{
size_t glyphsize;
struct vt_font *vf;
int error;
/* Make sure the dimensions are valid. */
if (f->width < 1 || f->height < 1)
return (EINVAL);
if (f->width > VTFONT_MAXDIMENSION || f->height > VTFONT_MAXDIMENSION)
return (E2BIG);
/* Not too many mappings. */
if (f->nnormal > VTFONT_MAXMAPPINGS || f->nbold > VTFONT_MAXMAPPINGS)
return (E2BIG);
/* Character 0 must always be present. */
if (f->nglyphs < 1)
return (EINVAL);
glyphsize = howmany(f->width, 8) * f->height * f->nglyphs;
if (glyphsize > VTFONT_MAXGLYPHSIZE)
return (E2BIG);
/* Allocate new font structure. */
vf = malloc(sizeof *vf, M_VTFONT, M_WAITOK);
vf->vf_normal = malloc(f->nnormal * sizeof(struct vt_font_map),
M_VTFONT, M_WAITOK);
vf->vf_bold = malloc(f->nbold * sizeof(struct vt_font_map),
M_VTFONT, M_WAITOK);
vf->vf_bytes = malloc(glyphsize, M_VTFONT, M_WAITOK);
vf->vf_height = f->height;
vf->vf_width = f->width;
vf->vf_normal_length = f->nnormal;
vf->vf_bold_length = f->nbold;
vf->vf_refcount = 1;
/* Copy in data. */
error = copyin(f->normal, vf->vf_normal,
vf->vf_normal_length * sizeof(struct vt_font_map));
if (error)
goto bad;
error = copyin(f->bold, vf->vf_bold,
vf->vf_bold_length * sizeof(struct vt_font_map));
if (error)
goto bad;
error = copyin(f->glyphs, vf->vf_bytes, glyphsize);
if (error)
goto bad;
/* Validate mappings. */
error = vtfont_validate_map(vf->vf_normal, vf->vf_normal_length,
f->nglyphs);
if (error)
goto bad;
error = vtfont_validate_map(vf->vf_bold, vf->vf_bold_length,
f->nglyphs);
if (error)
goto bad;
/* Success. */
*ret = vf;
return (0);
bad: vtfont_unref(vf);
return (error);
}

406
sys/dev/vt/vt_sysmouse.c Normal file
View File

@ -0,0 +1,406 @@
/*-
* Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
* All rights reserved.
*
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/condvar.h>
#include <sys/conf.h>
#include <sys/consio.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/poll.h>
#include <sys/random.h>
#include <sys/selinfo.h>
#include <sys/sigio.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <dev/vt/vt.h>
static d_open_t sysmouse_open;
static d_close_t sysmouse_close;
static d_read_t sysmouse_read;
static d_ioctl_t sysmouse_ioctl;
static d_poll_t sysmouse_poll;
static struct cdevsw sysmouse_cdevsw = {
.d_version = D_VERSION,
.d_open = sysmouse_open,
.d_close = sysmouse_close,
.d_read = sysmouse_read,
.d_ioctl = sysmouse_ioctl,
.d_poll = sysmouse_poll,
.d_name = "sysmouse",
};
static struct mtx sysmouse_lock;
static struct cv sysmouse_sleep;
static struct selinfo sysmouse_bufpoll;
static int sysmouse_level;
static mousestatus_t sysmouse_status;
static int sysmouse_flags;
#define SM_ASYNC 0x1
static struct sigio *sysmouse_sigio;
#define SYSMOUSE_MAXFRAMES 250 /* 2 KB */
static MALLOC_DEFINE(M_SYSMOUSE, "sysmouse", "sysmouse device");
static unsigned char *sysmouse_buffer;
static unsigned int sysmouse_start, sysmouse_length;
static int
sysmouse_buf_read(struct uio *uio, unsigned int length)
{
unsigned char buf[MOUSE_SYS_PACKETSIZE];
int error;
if (sysmouse_buffer == NULL)
return (ENXIO);
else if (sysmouse_length == 0)
return (EWOULDBLOCK);
memcpy(buf, sysmouse_buffer +
sysmouse_start * MOUSE_SYS_PACKETSIZE, MOUSE_SYS_PACKETSIZE);
sysmouse_start = (sysmouse_start + 1) % SYSMOUSE_MAXFRAMES;
sysmouse_length--;
mtx_unlock(&sysmouse_lock);
error = uiomove(buf, length, uio);
mtx_lock(&sysmouse_lock);
return (error);
}
static void
sysmouse_buf_store(const unsigned char buf[MOUSE_SYS_PACKETSIZE])
{
unsigned int idx;
if (sysmouse_buffer == NULL || sysmouse_length == SYSMOUSE_MAXFRAMES)
return;
idx = (sysmouse_start + sysmouse_length) % SYSMOUSE_MAXFRAMES;
memcpy(sysmouse_buffer + idx * MOUSE_SYS_PACKETSIZE, buf,
MOUSE_SYS_PACKETSIZE);
sysmouse_length++;
cv_broadcast(&sysmouse_sleep);
selwakeup(&sysmouse_bufpoll);
if (sysmouse_flags & SM_ASYNC && sysmouse_sigio != NULL)
pgsigio(&sysmouse_sigio, SIGIO, 0);
}
void
sysmouse_process_event(mouse_info_t *mi)
{
/* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */
static const int buttonmap[8] = {
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
MOUSE_MSC_BUTTON3UP,
MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
MOUSE_MSC_BUTTON2UP,
MOUSE_MSC_BUTTON1UP,
0,
};
unsigned char buf[MOUSE_SYS_PACKETSIZE];
int x, y, iy, z;
random_harvest(mi, sizeof *mi, 2, RANDOM_MOUSE);
mtx_lock(&sysmouse_lock);
switch (mi->operation) {
case MOUSE_ACTION:
sysmouse_status.button = mi->u.data.buttons;
/* FALLTHROUGH */
case MOUSE_MOTION_EVENT:
x = mi->u.data.x;
y = mi->u.data.y;
z = mi->u.data.z;
break;
case MOUSE_BUTTON_EVENT:
x = y = z = 0;
if (mi->u.event.value > 0)
sysmouse_status.button |= mi->u.event.id;
else
sysmouse_status.button &= ~mi->u.event.id;
break;
default:
goto done;
}
sysmouse_status.dx += x;
sysmouse_status.dy += y;
sysmouse_status.dz += z;
sysmouse_status.flags |= ((x || y || z) ? MOUSE_POSCHANGED : 0) |
(sysmouse_status.obutton ^ sysmouse_status.button);
if (sysmouse_status.flags == 0)
goto done;
/* The first five bytes are compatible with MouseSystems. */
buf[0] = MOUSE_MSC_SYNC |
buttonmap[sysmouse_status.button & MOUSE_STDBUTTONS];
x = imax(imin(x, 255), -256);
buf[1] = x >> 1;
buf[3] = x - buf[1];
iy = -imax(imin(y, 255), -256);
buf[2] = iy >> 1;
buf[4] = iy - buf[2];
/* Extended part. */
z = imax(imin(z, 127), -128);
buf[5] = (z >> 1) & 0x7f;
buf[6] = (z - (z >> 1)) & 0x7f;
/* Buttons 4-10. */
buf[7] = (~sysmouse_status.button >> 3) & 0x7f;
sysmouse_buf_store(buf);
mtx_unlock(&sysmouse_lock);
vt_mouse_event(mi->operation, x, y, mi->u.event.id, mi->u.event.value);
return;
done: mtx_unlock(&sysmouse_lock);
}
static int
sysmouse_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
void *buf;
buf = malloc(MOUSE_SYS_PACKETSIZE * SYSMOUSE_MAXFRAMES,
M_SYSMOUSE, M_WAITOK);
mtx_lock(&sysmouse_lock);
if (sysmouse_buffer == NULL) {
sysmouse_buffer = buf;
sysmouse_start = sysmouse_length = 0;
sysmouse_level = 0;
} else {
free(buf, M_SYSMOUSE);
}
mtx_unlock(&sysmouse_lock);
return (0);
}
static int
sysmouse_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
mtx_lock(&sysmouse_lock);
free(sysmouse_buffer, M_SYSMOUSE);
sysmouse_buffer = NULL;
sysmouse_level = 0;
mtx_unlock(&sysmouse_lock);
return (0);
}
static int
sysmouse_read(struct cdev *dev, struct uio *uio, int ioflag)
{
unsigned int length;
ssize_t oresid;
int error = 0;
oresid = uio->uio_resid;
mtx_lock(&sysmouse_lock);
length = sysmouse_level >= 1 ? MOUSE_SYS_PACKETSIZE :
MOUSE_MSC_PACKETSIZE;
while (uio->uio_resid >= length) {
error = sysmouse_buf_read(uio, length);
if (error == 0) {
/* Process the next frame. */
continue;
} else if (error != EWOULDBLOCK) {
/* Error (e.g. EFAULT). */
break;
} else {
/* Block. */
if (oresid != uio->uio_resid || ioflag & O_NONBLOCK)
break;
error = cv_wait_sig(&sysmouse_sleep, &sysmouse_lock);
if (error != 0)
break;
}
}
mtx_unlock(&sysmouse_lock);
return (error);
}
static int
sysmouse_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
{
switch (cmd) {
case FIOASYNC:
mtx_lock(&sysmouse_lock);
if (*(int *)data)
sysmouse_flags |= SM_ASYNC;
else
sysmouse_flags &= ~SM_ASYNC;
mtx_unlock(&sysmouse_lock);
return (0);
case FIONBIO:
return (0);
case FIOGETOWN:
*(int *)data = fgetown(&sysmouse_sigio);
return (0);
case FIOSETOWN:
return (fsetown(*(int *)data, &sysmouse_sigio));
case MOUSE_GETHWINFO: {
mousehw_t *hw = (mousehw_t *)data;
hw->buttons = 10;
hw->iftype = MOUSE_IF_SYSMOUSE;
hw->type = MOUSE_MOUSE;
hw->model = MOUSE_MODEL_GENERIC;
hw->hwid = 0;
return (0);
}
case MOUSE_GETLEVEL:
*(int *)data = sysmouse_level;
return (0);
case MOUSE_GETMODE: {
mousemode_t *mode = (mousemode_t *)data;
mode->rate = -1;
mode->resolution = -1;
mode->accelfactor = 0;
mode->level = sysmouse_level;
switch (mode->level) {
case 0:
mode->protocol = MOUSE_PROTO_MSC;
mode->packetsize = MOUSE_MSC_PACKETSIZE;
mode->syncmask[0] = MOUSE_MSC_SYNCMASK;
mode->syncmask[1] = MOUSE_MSC_SYNC;
break;
case 1:
mode->protocol = MOUSE_PROTO_SYSMOUSE;
mode->packetsize = MOUSE_SYS_PACKETSIZE;
mode->syncmask[0] = MOUSE_SYS_SYNCMASK;
mode->syncmask[1] = MOUSE_SYS_SYNC;
break;
}
return (0);
}
case MOUSE_GETSTATUS:
mtx_lock(&sysmouse_lock);
*(mousestatus_t *)data = sysmouse_status;
sysmouse_status.flags = 0;
sysmouse_status.obutton = sysmouse_status.button;
sysmouse_status.dx = 0;
sysmouse_status.dy = 0;
sysmouse_status.dz = 0;
mtx_unlock(&sysmouse_lock);
return (0);
case MOUSE_SETLEVEL: {
int level;
level = *(int *)data;
if (level != 0 && level != 1)
return (EINVAL);
sysmouse_level = level;
vt_mouse_state((level == 0)?VT_MOUSE_SHOW:VT_MOUSE_HIDE);
return (0);
}
case MOUSE_SETMODE: {
mousemode_t *mode = (mousemode_t *)data;
switch (mode->level) {
case -1:
/* Do nothing. */
break;
case 0:
case 1:
sysmouse_level = mode->level;
vt_mouse_state((mode->level == 0)?VT_MOUSE_SHOW:
VT_MOUSE_HIDE);
break;
default:
return (EINVAL);
}
return (0);
}
case MOUSE_MOUSECHAR:
return (0);
default:
printf("sysmouse: unknown ioctl: %c:%lx\n",
(char)IOCGROUP(cmd), IOCBASECMD(cmd));
return (ENOIOCTL);
}
}
static int
sysmouse_poll(struct cdev *dev, int events, struct thread *td)
{
int revents = 0;
mtx_lock(&sysmouse_lock);
if (events & (POLLIN|POLLRDNORM)) {
if (sysmouse_length > 0)
revents = events & (POLLIN|POLLRDNORM);
else
selrecord(td, &sysmouse_bufpoll);
}
mtx_unlock(&sysmouse_lock);
return (revents);
}
static void
sysmouse_drvinit(void *unused)
{
mtx_init(&sysmouse_lock, "sysmouse", NULL, MTX_DEF);
cv_init(&sysmouse_sleep, "sysmrd");
make_dev(&sysmouse_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"sysmouse");
}
SYSINIT(sysmouse, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sysmouse_drvinit, NULL);

602
sys/kern/subr_terminal.c Normal file
View File

@ -0,0 +1,602 @@
/*-
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/cons.h>
#include <sys/consio.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/systm.h>
#include <sys/terminal.h>
#include <sys/tty.h>
#include <machine/stdarg.h>
static MALLOC_DEFINE(M_TERMINAL, "terminal", "terminal device");
/*
* Locking.
*
* Normally we don't need to lock down the terminal emulator, because
* the TTY lock is already held when calling teken_input().
* Unfortunately this is not the case when the terminal acts as a
* console device, because cnputc() can be called at the same time.
* This means terminals may need to be locked down using a spin lock.
*/
#define TERMINAL_LOCK(tm) do { \
if ((tm)->tm_flags & TF_CONS) \
mtx_lock_spin(&(tm)->tm_mtx); \
else if ((tm)->tm_tty != NULL) \
tty_lock((tm)->tm_tty); \
} while (0)
#define TERMINAL_UNLOCK(tm) do { \
if ((tm)->tm_flags & TF_CONS) \
mtx_unlock_spin(&(tm)->tm_mtx); \
else if ((tm)->tm_tty != NULL) \
tty_unlock((tm)->tm_tty); \
} while (0)
#define TERMINAL_LOCK_TTY(tm) do { \
if ((tm)->tm_flags & TF_CONS) \
mtx_lock_spin(&(tm)->tm_mtx); \
} while (0)
#define TERMINAL_UNLOCK_TTY(tm) do { \
if ((tm)->tm_flags & TF_CONS) \
mtx_unlock_spin(&(tm)->tm_mtx); \
} while (0)
#define TERMINAL_LOCK_CONS(tm) mtx_lock_spin(&(tm)->tm_mtx)
#define TERMINAL_UNLOCK_CONS(tm) mtx_unlock_spin(&(tm)->tm_mtx)
/*
* TTY routines.
*/
static tsw_open_t termtty_open;
static tsw_close_t termtty_close;
static tsw_outwakeup_t termtty_outwakeup;
static tsw_ioctl_t termtty_ioctl;
static struct ttydevsw terminal_tty_class = {
.tsw_open = termtty_open,
.tsw_close = termtty_close,
.tsw_outwakeup = termtty_outwakeup,
.tsw_ioctl = termtty_ioctl,
};
/*
* Terminal emulator routines.
*/
static tf_bell_t termteken_bell;
static tf_cursor_t termteken_cursor;
static tf_putchar_t termteken_putchar;
static tf_fill_t termteken_fill;
static tf_copy_t termteken_copy;
static tf_param_t termteken_param;
static tf_respond_t termteken_respond;
static teken_funcs_t terminal_drawmethods = {
.tf_bell = termteken_bell,
.tf_cursor = termteken_cursor,
.tf_putchar = termteken_putchar,
.tf_fill = termteken_fill,
.tf_copy = termteken_copy,
.tf_param = termteken_param,
.tf_respond = termteken_respond,
};
/* Kernel message formatting. */
static const teken_attr_t kernel_message = {
.ta_fgcolor = TC_WHITE,
.ta_bgcolor = TC_BLACK,
.ta_format = TF_BOLD,
};
static const teken_attr_t default_message = {
.ta_fgcolor = TC_WHITE,
.ta_bgcolor = TC_BLACK,
};
#define TCHAR_CREATE(c, a) ((c) | \
(a)->ta_format << 22 | \
teken_256to8((a)->ta_fgcolor) << 26 | \
teken_256to8((a)->ta_bgcolor) << 29)
static void
terminal_init(struct terminal *tm)
{
if (tm->tm_flags & TF_CONS)
mtx_init(&tm->tm_mtx, "trmlck", NULL, MTX_SPIN);
teken_init(&tm->tm_emulator, &terminal_drawmethods, tm);
teken_set_defattr(&tm->tm_emulator, &default_message);
}
struct terminal *
terminal_alloc(const struct terminal_class *tc, void *softc)
{
struct terminal *tm;
tm = malloc(sizeof(struct terminal), M_TERMINAL, M_WAITOK|M_ZERO);
terminal_init(tm);
tm->tm_class = tc;
tm->tm_softc = softc;
return (tm);
}
static void
terminal_sync_ttysize(struct terminal *tm)
{
struct tty *tp;
tp = tm->tm_tty;
if (tp == NULL)
return;
tty_lock(tp);
tty_set_winsize(tp, &tm->tm_winsize);
tty_unlock(tp);
}
void
terminal_maketty(struct terminal *tm, const char *fmt, ...)
{
struct tty *tp;
char name[8];
va_list ap;
va_start(ap, fmt);
vsnrprintf(name, sizeof name, 32, fmt, ap);
va_end(ap);
tp = tty_alloc(&terminal_tty_class, tm);
tty_makedev(tp, NULL, "%s", name);
tm->tm_tty = tp;
terminal_sync_ttysize(tm);
}
void
terminal_set_winsize_blank(struct terminal *tm, const struct winsize *size,
int blank)
{
term_rect_t r;
tm->tm_winsize = *size;
r.tr_begin.tp_row = r.tr_begin.tp_col = 0;
r.tr_end.tp_row = size->ws_row;
r.tr_end.tp_col = size->ws_col;
TERMINAL_LOCK(tm);
if (blank == 0)
teken_set_winsize_noreset(&tm->tm_emulator, &r.tr_end);
else
teken_set_winsize(&tm->tm_emulator, &r.tr_end);
TERMINAL_UNLOCK(tm);
if (blank != 0)
tm->tm_class->tc_fill(tm, &r, TCHAR_CREATE((teken_char_t)' ',
&default_message));
terminal_sync_ttysize(tm);
}
void
terminal_set_winsize(struct terminal *tm, const struct winsize *size)
{
terminal_set_winsize_blank(tm, size, 1);
}
/*
* XXX: This function is a kludge. Drivers like vt(4) need to
* temporarily stop input when resizing, etc. This should ideally be
* handled within the driver.
*/
void
terminal_mute(struct terminal *tm, int yes)
{
TERMINAL_LOCK(tm);
if (yes)
tm->tm_flags |= TF_MUTE;
else
tm->tm_flags &= ~TF_MUTE;
TERMINAL_UNLOCK(tm);
}
void
terminal_input_char(struct terminal *tm, term_char_t c)
{
struct tty *tp;
tp = tm->tm_tty;
if (tp == NULL)
return;
/* Strip off any attributes. */
c = TCHAR_CHARACTER(c);
tty_lock(tp);
/*
* Conversion to UTF-8.
*/
if (c < 0x80) {
ttydisc_rint(tp, c, 0);
} else if (c < 0x800) {
char str[2] = {
0xc0 | (c >> 6),
0x80 | (c & 0x3f)
};
ttydisc_rint_simple(tp, str, sizeof str);
} else if (c < 0x10000) {
char str[3] = {
0xe0 | (c >> 12),
0x80 | ((c >> 6) & 0x3f),
0x80 | (c & 0x3f)
};
ttydisc_rint_simple(tp, str, sizeof str);
} else {
char str[4] = {
0xf0 | (c >> 18),
0x80 | ((c >> 12) & 0x3f),
0x80 | ((c >> 6) & 0x3f),
0x80 | (c & 0x3f)
};
ttydisc_rint_simple(tp, str, sizeof str);
}
ttydisc_rint_done(tp);
tty_unlock(tp);
}
void
terminal_input_raw(struct terminal *tm, char c)
{
struct tty *tp;
tp = tm->tm_tty;
if (tp == NULL)
return;
tty_lock(tp);
ttydisc_rint(tp, c, 0);
ttydisc_rint_done(tp);
tty_unlock(tp);
}
void
terminal_input_special(struct terminal *tm, unsigned int k)
{
struct tty *tp;
const char *str;
tp = tm->tm_tty;
if (tp == NULL)
return;
str = teken_get_sequence(&tm->tm_emulator, k);
if (str == NULL)
return;
tty_lock(tp);
ttydisc_rint_simple(tp, str, strlen(str));
ttydisc_rint_done(tp);
tty_unlock(tp);
}
/*
* Binding with the TTY layer.
*/
static int
termtty_open(struct tty *tp)
{
struct terminal *tm = tty_softc(tp);
tm->tm_class->tc_opened(tm, 1);
return (0);
}
static void
termtty_close(struct tty *tp)
{
struct terminal *tm = tty_softc(tp);
tm->tm_class->tc_opened(tm, 0);
}
static void
termtty_outwakeup(struct tty *tp)
{
struct terminal *tm = tty_softc(tp);
char obuf[128];
size_t olen;
unsigned int flags = 0;
while ((olen = ttydisc_getc(tp, obuf, sizeof obuf)) > 0) {
TERMINAL_LOCK_TTY(tm);
if (!(tm->tm_flags & TF_MUTE)) {
tm->tm_flags &= ~TF_BELL;
teken_input(&tm->tm_emulator, obuf, olen);
flags |= tm->tm_flags;
}
TERMINAL_UNLOCK_TTY(tm);
}
tm->tm_class->tc_done(tm);
if (flags & TF_BELL)
tm->tm_class->tc_bell(tm);
}
static int
termtty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
{
struct terminal *tm = tty_softc(tp);
int error;
switch (cmd) {
case CONS_GETINFO: {
vid_info_t *vi = (vid_info_t *)data;
const teken_pos_t *p;
int fg, bg;
if (vi->size != sizeof(vid_info_t))
return (EINVAL);
/* Already help the console driver by filling in some data. */
p = teken_get_cursor(&tm->tm_emulator);
vi->mv_row = p->tp_row;
vi->mv_col = p->tp_col;
p = teken_get_winsize(&tm->tm_emulator);
vi->mv_rsz = p->tp_row;
vi->mv_csz = p->tp_col;
teken_get_defattr_cons25(&tm->tm_emulator, &fg, &bg);
vi->mv_norm.fore = fg;
vi->mv_norm.back = bg;
/* XXX: keep vidcontrol happy; bold backgrounds. */
vi->mv_rev.fore = bg;
vi->mv_rev.back = fg & 0x7;
break;
}
}
/*
* Unlike various other drivers, this driver will never
* deallocate TTYs. This means it's safe to temporarily unlock
* the TTY when handling ioctls.
*/
tty_unlock(tp);
error = tm->tm_class->tc_ioctl(tm, cmd, data, td);
tty_lock(tp);
return (error);
}
/*
* Binding with the kernel and debug console.
*/
static cn_probe_t termcn_cnprobe;
static cn_init_t termcn_cninit;
static cn_term_t termcn_cnterm;
static cn_getc_t termcn_cngetc;
static cn_putc_t termcn_cnputc;
static cn_grab_t termcn_cngrab;
static cn_ungrab_t termcn_cnungrab;
const struct consdev_ops termcn_cnops = {
.cn_probe = termcn_cnprobe,
.cn_init = termcn_cninit,
.cn_term = termcn_cnterm,
.cn_getc = termcn_cngetc,
.cn_putc = termcn_cnputc,
.cn_grab = termcn_cngrab,
.cn_ungrab = termcn_cnungrab,
};
void
termcn_cnregister(struct terminal *tm)
{
struct consdev *cp;
cp = tm->consdev;
if (cp == NULL) {
cp = malloc(sizeof(struct consdev), M_TERMINAL,
M_WAITOK|M_ZERO);
cp->cn_ops = &termcn_cnops;
cp->cn_arg = tm;
cp->cn_pri = CN_INTERNAL;
sprintf(cp->cn_name, "ttyv0");
tm->tm_flags = TF_CONS;
tm->consdev = cp;
terminal_init(tm);
}
/* Attach terminal as console. */
cnadd(cp);
}
static void
termcn_cngrab(struct consdev *cp)
{
}
static void
termcn_cnungrab(struct consdev *cp)
{
}
static void
termcn_cnprobe(struct consdev *cp)
{
struct terminal *tm = cp->cn_arg;
if (tm == NULL) {
cp->cn_pri = CN_DEAD;
return;
}
tm->consdev = cp;
terminal_init(tm);
tm->tm_class->tc_cnprobe(tm, cp);
}
static void
termcn_cninit(struct consdev *cp)
{
}
static void
termcn_cnterm(struct consdev *cp)
{
}
static int
termcn_cngetc(struct consdev *cp)
{
struct terminal *tm = cp->cn_arg;
return (tm->tm_class->tc_cngetc(tm));
}
static void
termcn_cnputc(struct consdev *cp, int c)
{
struct terminal *tm = cp->cn_arg;
teken_attr_t backup;
char cv = c;
TERMINAL_LOCK_CONS(tm);
if (!(tm->tm_flags & TF_MUTE)) {
backup = *teken_get_curattr(&tm->tm_emulator);
teken_set_curattr(&tm->tm_emulator, &kernel_message);
teken_input(&tm->tm_emulator, &cv, 1);
teken_set_curattr(&tm->tm_emulator, &backup);
}
TERMINAL_UNLOCK_CONS(tm);
tm->tm_class->tc_done(tm);
}
/*
* Binding with the terminal emulator.
*/
static void
termteken_bell(void *softc)
{
struct terminal *tm = softc;
tm->tm_flags |= TF_BELL;
}
static void
termteken_cursor(void *softc, const teken_pos_t *p)
{
struct terminal *tm = softc;
tm->tm_class->tc_cursor(tm, p);
}
static void
termteken_putchar(void *softc, const teken_pos_t *p, teken_char_t c,
const teken_attr_t *a)
{
struct terminal *tm = softc;
tm->tm_class->tc_putchar(tm, p, TCHAR_CREATE(c, a));
}
static void
termteken_fill(void *softc, const teken_rect_t *r, teken_char_t c,
const teken_attr_t *a)
{
struct terminal *tm = softc;
tm->tm_class->tc_fill(tm, r, TCHAR_CREATE(c, a));
}
static void
termteken_copy(void *softc, const teken_rect_t *r, const teken_pos_t *p)
{
struct terminal *tm = softc;
tm->tm_class->tc_copy(tm, r, p);
}
static void
termteken_param(void *softc, int cmd, unsigned int arg)
{
struct terminal *tm = softc;
tm->tm_class->tc_param(tm, cmd, arg);
}
static void
termteken_respond(void *softc, const void *buf, size_t len)
{
#if 0
struct terminal *tm = softc;
struct tty *tp;
/*
* Only inject a response into the TTY if the data actually
* originated from the TTY.
*
* XXX: This cannot be done right now. The TTY could pick up
* other locks. It could also in theory cause loops, when the
* TTY performs echoing of a command that generates even more
* input.
*/
tp = tm->tm_tty;
if (tp == NULL)
return;
ttydisc_rint_simple(tp, buf, len);
ttydisc_rint_done(tp);
#endif
}

View File

@ -34,7 +34,7 @@ SRCS = \
SRCS += i915_ioc32.c
.endif
SRCS += device_if.h bus_if.h pci_if.h iicbus_if.h iicbb_if.h opt_drm.h \
opt_compat.h
SRCS += device_if.h fb_if.h bus_if.h pci_if.h iicbus_if.h iicbb_if.h \
opt_drm.h opt_compat.h
.include <bsd.kmod.mk>

View File

@ -96,6 +96,7 @@ SRCS += \
opt_drm.h \
acpi_if.h \
bus_if.h \
fb_if.h \
device_if.h \
iicbb_if.h \
iicbus_if.h \

View File

@ -556,15 +556,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
*/
sun4u_set_traptable(tl0_base);
/*
* Initialize the console.
* NB: the low-level console drivers require a working DELAY() and
* some compiler optimizations may cause the curthread accesses of
* mutex(9) to be factored out even if the latter aren't actually
* called, both requiring PCPU_REG to be set.
*/
cninit();
/*
* Initialize the dynamic per-CPU area for the BSP and the message
* buffer (after setting the trap table).
@ -577,6 +568,12 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
*/
mutex_init();
/*
* Initialize console now that we have a reasonable set of system
* services.
*/
cninit();
/*
* Finish the interrupt initialization now that mutexes work and
* enable them.

View File

@ -209,12 +209,33 @@ struct fnt16 {
};
typedef struct fnt16 fnt16_t;
struct vfnt_map {
uint32_t src;
uint16_t dst;
uint16_t len;
};
typedef struct vfnt_map vfnt_map_t;
struct vfnt {
vfnt_map_t *normal;
vfnt_map_t *bold;
uint8_t *glyphs;
unsigned int nnormal;
unsigned int nbold;
unsigned int nglyphs;
unsigned int width;
unsigned int height;
};
typedef struct vfnt vfnt_t;
#define PIO_FONT8x8 _IOW('c', 64, fnt8_t)
#define GIO_FONT8x8 _IOR('c', 65, fnt8_t)
#define PIO_FONT8x14 _IOW('c', 66, fnt14_t)
#define GIO_FONT8x14 _IOR('c', 67, fnt14_t)
#define PIO_FONT8x16 _IOW('c', 68, fnt16_t)
#define GIO_FONT8x16 _IOR('c', 69, fnt16_t)
#define PIO_VFONT _IOW('c', 70, vfnt_t)
#define GIO_VFONT _IOR('c', 71, vfnt_t)
/* get video mode information */
struct colors {

View File

@ -262,4 +262,12 @@ EVENTHANDLER_DECLARE(kld_load, kld_load_fn);
EVENTHANDLER_DECLARE(kld_unload, kld_unload_fn);
EVENTHANDLER_DECLARE(kld_unload_try, kld_unload_try_fn);
/* Generic graphics framebuffer interface */
struct fb_info;
typedef void (*register_framebuffer_fn)(void *, struct fb_info *);
typedef void (*unregister_framebuffer_fn)(void *, struct fb_info *);
EVENTHANDLER_DECLARE(register_framebuffer, register_framebuffer_fn);
EVENTHANDLER_DECLARE(unregister_framebuffer, unregister_framebuffer_fn);
#endif /* _SYS_EVENTHANDLER_H_ */

View File

@ -40,6 +40,10 @@
#ifndef _KERNEL
#include <sys/types.h>
#else
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/eventhandler.h>
#endif
#include <sys/ioccom.h>
@ -101,6 +105,78 @@ struct fbtype {
};
#define FBIOGTYPE _IOR('F', 0, struct fbtype)
#define FBTYPE_GET_STRIDE(_fb) ((_fb)->fb_size / (_fb)->fb_height)
#define FBTYPE_GET_BPP(_fb) ((_fb)->fb_bpp)
#define FBTYPE_GET_BYTESPP(_fb) ((_fb)->fb_bpp / 8)
#ifdef _KERNEL
struct fb_info;
typedef int fb_enter_t(void *priv);
typedef int fb_leave_t(void *priv);
typedef int fb_write_t(void *priv, int offset, void *data, int size);
typedef int fb_read_t(void *priv, int offset, void *data, int size);
/* XXX: should use priv instead of fb_info too. */
typedef void fb_copy_t(struct fb_info *sc, uint32_t offset_to, uint32_t offset_from,
uint32_t size);
typedef void fb_wr1_t(struct fb_info *sc, uint32_t offset, uint8_t value);
typedef void fb_wr2_t(struct fb_info *sc, uint32_t offset, uint16_t value);
typedef void fb_wr4_t(struct fb_info *sc, uint32_t offset, uint32_t value);
struct fb_info {
/* Raw copy of fbtype. Do not change. */
int fb_type; /* as defined above */
int fb_height; /* in pixels */
int fb_width; /* in pixels */
int fb_depth; /* bits to define color */
int fb_cmsize; /* size of color map (entries) */
int fb_size; /* total size in bytes */
/* Methods. */
fb_write_t *fb_write; /* if NULL, direct mem write. */
fb_read_t *fb_read; /* if NULL, direct mem read. */
fb_wr1_t *wr1;
fb_wr2_t *wr2;
fb_wr4_t *wr4;
fb_copy_t *copy;
fb_enter_t *enter;
fb_leave_t *leave;
intptr_t fb_pbase; /* For FB mmap. */
intptr_t fb_vbase; /* if NULL, use fb_write/fb_read. */
void *fb_priv; /* First argument for read/write. */
const char *fb_name;
uint32_t fb_flags;
int fb_stride;
int fb_bpp; /* bits per pixel */
#define FB_FLAG_NOMMAP 1 /* mmap unsupported. */
uint32_t fb_cmap[16];
};
int fbd_list(void);
int fbd_register(struct fb_info *);
int fbd_unregister(struct fb_info *);
static inline int
register_framebuffer(struct fb_info *info)
{
EVENTHANDLER_INVOKE(register_framebuffer, info);
return (0);
}
static inline int
unregister_framebuffer(struct fb_info *info)
{
EVENTHANDLER_INVOKE(unregister_framebuffer, info);
return (0);
}
#endif
#ifdef notdef
/*
* General purpose structure for passing info in and out of frame buffers

161
sys/sys/terminal.h Normal file
View File

@ -0,0 +1,161 @@
/*-
* Copyright (c) 2009 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Ed Schouten under sponsorship from the
* FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SYS_TERMINAL_H_
#define _SYS_TERMINAL_H_
#include <sys/param.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/cons.h>
#include <sys/linker_set.h>
#include <sys/ttycom.h>
#include <teken/teken.h>
struct terminal;
struct thread;
struct tty;
/*
* The terminal layer is an abstraction on top of the TTY layer and the
* console interface. It can be used by system console drivers to
* easily interact with the kernel console and TTYs.
*
* Terminals contain terminal emulators, which means console drivers
* don't need to implement their own terminal emulator. The terminal
* emulator deals with UTF-8 exclusively. This means that term_char_t,
* the data type used to store input/output characters will always
* contain Unicode codepoints.
*
* To save memory usage, the top bits of term_char_t will contain other
* attributes, like colors. Right now term_char_t is composed as
* follows:
*
* Bits Meaning
* 0-20: Character value
* 21: Unused
* 22-25: Bold, underline, blink, reverse
* 26-28: Foreground color
* 29-31: Background color
*/
typedef uint32_t term_char_t;
#define TCHAR_CHARACTER(c) ((c) & 0x1fffff)
#define TCHAR_FORMAT(c) (((c) >> 22) & 0xf)
#define TCHAR_FGCOLOR(c) (((c) >> 26) & 0x7)
#define TCHAR_BGCOLOR(c) ((c) >> 29)
typedef teken_color_t term_color_t;
#define TCOLOR_LIGHT(c) ((c) | 0x8)
#define TCOLOR_DARK(c) ((c) & ~0x8)
typedef teken_pos_t term_pos_t;
typedef teken_rect_t term_rect_t;
typedef void tc_cursor_t(struct terminal *tm, const term_pos_t *p);
typedef void tc_putchar_t(struct terminal *tm, const term_pos_t *p,
term_char_t c);
typedef void tc_fill_t(struct terminal *tm, const term_rect_t *r,
term_char_t c);
typedef void tc_copy_t(struct terminal *tm, const term_rect_t *r,
const term_pos_t *p);
typedef void tc_param_t(struct terminal *tm, int cmd, unsigned int arg);
typedef void tc_done_t(struct terminal *tm);
typedef void tc_cnprobe_t(struct terminal *tm, struct consdev *cd);
typedef int tc_cngetc_t(struct terminal *tm);
typedef void tc_opened_t(struct terminal *tm, int opened);
typedef int tc_ioctl_t(struct terminal *tm, u_long cmd, caddr_t data,
struct thread *td);
typedef void tc_bell_t(struct terminal *tm);
struct terminal_class {
/* Terminal emulator. */
tc_cursor_t *tc_cursor;
tc_putchar_t *tc_putchar;
tc_fill_t *tc_fill;
tc_copy_t *tc_copy;
tc_param_t *tc_param;
tc_done_t *tc_done;
/* Low-level console interface. */
tc_cnprobe_t *tc_cnprobe;
tc_cngetc_t *tc_cngetc;
/* Misc. */
tc_opened_t *tc_opened;
tc_ioctl_t *tc_ioctl;
tc_bell_t *tc_bell;
};
struct terminal {
const struct terminal_class *tm_class;
void *tm_softc;
struct mtx tm_mtx;
struct tty *tm_tty;
teken_t tm_emulator;
struct winsize tm_winsize;
unsigned int tm_flags;
#define TF_MUTE 0x1 /* Drop incoming data. */
#define TF_BELL 0x2 /* Bell needs to be sent. */
#define TF_CONS 0x4 /* Console device (needs spinlock). */
struct consdev *consdev;
};
#ifdef _KERNEL
struct terminal *terminal_alloc(const struct terminal_class *tc, void *softc);
void terminal_maketty(struct terminal *tm, const char *fmt, ...);
void terminal_set_winsize_blank(struct terminal *tm,
const struct winsize *size, int blank);
void terminal_set_winsize(struct terminal *tm, const struct winsize *size);
void terminal_mute(struct terminal *tm, int yes);
void terminal_input_char(struct terminal *tm, term_char_t c);
void terminal_input_raw(struct terminal *tm, char c);
void terminal_input_special(struct terminal *tm, unsigned int k);
void termcn_cnregister(struct terminal *tm);
/* Kernel console helper interface. */
extern const struct consdev_ops termcn_cnops;
#define TERMINAL_DECLARE_EARLY(name, class, softc) \
static struct terminal name = { \
.tm_class = &class, \
.tm_softc = softc, \
.tm_flags = TF_CONS, \
}; \
CONSOLE_DEVICE(name ## _consdev, termcn_cnops, &name)
#endif /* _KERNEL */
#endif /* !_SYS_TERMINAL_H_ */

View File

@ -166,6 +166,7 @@ void tty_rel_gone(struct tty *tp);
#define tty_lock(tp) mtx_lock((tp)->t_mtx)
#define tty_unlock(tp) mtx_unlock((tp)->t_mtx)
#define tty_lock_owned(tp) mtx_owned((tp)->t_mtx)
#define tty_lock_assert(tp,ma) mtx_assert((tp)->t_mtx, (ma))
#define tty_getlock(tp) ((tp)->t_mtx)

View File

@ -346,6 +346,14 @@ teken_set_winsize(teken_t *t, const teken_pos_t *p)
teken_subr_do_reset(t);
}
void
teken_set_winsize_noreset(teken_t *t, const teken_pos_t *p)
{
t->t_winsize = *p;
teken_subr_do_resize(t);
}
void
teken_set_8bit(teken_t *t)
{

View File

@ -168,6 +168,7 @@ void teken_set_cursor(teken_t *, const teken_pos_t *);
void teken_set_curattr(teken_t *, const teken_attr_t *);
void teken_set_defattr(teken_t *, const teken_attr_t *);
void teken_set_winsize(teken_t *, const teken_pos_t *);
void teken_set_winsize_noreset(teken_t *, const teken_pos_t *);
/* Key input escape sequences. */
#define TKEY_UP 0x00

View File

@ -955,6 +955,15 @@ teken_subr_reset_mode(teken_t *t, unsigned int cmd)
}
}
static void
teken_subr_do_resize(teken_t *t)
{
t->t_scrollreg.ts_begin = 0;
t->t_scrollreg.ts_end = t->t_winsize.tp_row;
t->t_originreg = t->t_scrollreg;
}
static void
teken_subr_do_reset(teken_t *t)
{