128328Ssos/*-
2229784Suqs * Copyright (c) 1991-1997 S��ren Schmidt
328328Ssos * All rights reserved.
428328Ssos *
528328Ssos * Redistribution and use in source and binary forms, with or without
628328Ssos * modification, are permitted provided that the following conditions
728328Ssos * are met:
828328Ssos * 1. Redistributions of source code must retain the above copyright
928328Ssos *    notice, this list of conditions and the following disclaimer
1028328Ssos *    in this position and unchanged.
1128328Ssos * 2. Redistributions in binary form must reproduce the above copyright
1228328Ssos *    notice, this list of conditions and the following disclaimer in the
1328328Ssos *    documentation and/or other materials provided with the distribution.
1428328Ssos * 3. The name of the author may not be used to endorse or promote products
1597748Sschweikh *    derived from this software without specific prior written permission
1628328Ssos *
1728328Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1828328Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1928328Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2028328Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2128328Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2228328Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2328328Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2428328Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2528328Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2628328Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2728328Ssos */
2828328Ssos
2983551Sdillon#include <sys/cdefs.h>
3083551Sdillon__FBSDID("$FreeBSD$");
3183551Sdillon
3228328Ssos#include <stdio.h>
3328328Ssos#include <sys/types.h>
3428328Ssos#include <sys/signal.h>
3528328Ssos#include <sys/file.h>
3628328Ssos#include <sys/ioctl.h>
3728328Ssos#include <sys/mman.h>
3866834Sphk#include <sys/fbio.h>
3966834Sphk#include <sys/kbio.h>
4066834Sphk#include <sys/consio.h>
4128328Ssos#include "vgl.h"
4228328Ssos
4370991Snsouch/* XXX Direct Color 24bits modes unsupported */
4470991Snsouch
4553013Syokota#define min(x, y)	(((x) < (y)) ? (x) : (y))
4653013Syokota#define max(x, y)	(((x) > (y)) ? (x) : (y))
4753013Syokota
4828328SsosVGLBitmap *VGLDisplay;
4953013Syokotavideo_info_t VGLModeInfo;
5053013Syokotavideo_adapter_info_t VGLAdpInfo;
5153013Syokotabyte *VGLBuf;
5228328Ssos
5328328Ssosstatic int VGLMode;
5428328Ssosstatic int VGLOldMode;
5553013Syokotastatic size_t VGLBufSize;
5653013Syokotastatic byte *VGLMem = MAP_FAILED;
5728328Ssosstatic int VGLSwitchPending;
5880270Syokotastatic int VGLAbortPending;
5928328Ssosstatic int VGLOnDisplay;
6053013Syokotastatic unsigned int VGLCurWindow;
6130044Ssosstatic int VGLInitDone = 0;
6276852Ssobomaxstatic vid_info_t VGLOldVInfo;
6328328Ssos
6428328Ssosvoid
6528328SsosVGLEnd()
6628328Ssos{
6728328Ssosstruct vt_mode smode;
6828328Ssos
6930044Ssos  if (!VGLInitDone)
7030044Ssos    return;
7153013Syokota  VGLInitDone = 0;
7280270Syokota  VGLSwitchPending = 0;
7380270Syokota  VGLAbortPending = 0;
7453013Syokota
7553013Syokota  signal(SIGUSR1, SIG_IGN);
7653013Syokota
7753013Syokota  if (VGLMem != MAP_FAILED) {
7853013Syokota    VGLClear(VGLDisplay, 0);
7953013Syokota    munmap(VGLMem, VGLAdpInfo.va_window_size);
8050483Syokota  }
8153013Syokota
8250141Syokota  if (VGLOldMode >= M_VESA_BASE) {
8350141Syokota    /* ugly, but necessary */
8450141Syokota    ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0);
8550141Syokota    if (VGLOldMode == M_VESA_800x600) {
8650141Syokota      int size[3];
8776852Ssobomax      size[0] = VGLOldVInfo.mv_csz;
8876852Ssobomax      size[1] = VGLOldVInfo.mv_rsz;
8950141Syokota      size[2] = 16;
9050141Syokota      ioctl(0, KDRASTER, size);
9150141Syokota    }
9250141Syokota  } else {
9350141Syokota    ioctl(0, _IO('S', VGLOldMode), 0);
9450141Syokota  }
9528328Ssos  ioctl(0, KDDISABIO, 0);
9628328Ssos  ioctl(0, KDSETMODE, KD_TEXT);
9728328Ssos  smode.mode = VT_AUTO;
9828328Ssos  ioctl(0, VT_SETMODE, &smode);
9953013Syokota  if (VGLBuf)
10053013Syokota    free(VGLBuf);
10153013Syokota  VGLBuf = NULL;
10228328Ssos  free(VGLDisplay);
10353013Syokota  VGLDisplay = NULL;
10430044Ssos  VGLKeyboardEnd();
10528328Ssos}
10628328Ssos
10728328Ssosstatic void
108130245SstefanfVGLAbort(int arg __unused)
10928328Ssos{
11080270Syokota  VGLAbortPending = 1;
11180270Syokota  signal(SIGINT, SIG_IGN);
11280270Syokota  signal(SIGTERM, SIG_IGN);
11380270Syokota  signal(SIGSEGV, SIG_IGN);
11480270Syokota  signal(SIGBUS, SIG_IGN);
11580270Syokota  signal(SIGUSR2, SIG_IGN);
11628328Ssos}
11728328Ssos
11828328Ssosstatic void
119130245SstefanfVGLSwitch(int arg __unused)
12028328Ssos{
12128328Ssos  if (!VGLOnDisplay)
12228328Ssos    VGLOnDisplay = 1;
12328328Ssos  else
12428328Ssos    VGLOnDisplay = 0;
12528328Ssos  VGLSwitchPending = 1;
12628328Ssos  signal(SIGUSR1, VGLSwitch);
12728328Ssos}
12828328Ssos
12928328Ssosint
13028328SsosVGLInit(int mode)
13128328Ssos{
13228328Ssos  struct vt_mode smode;
13353013Syokota  int adptype;
13428328Ssos
13553013Syokota  if (VGLInitDone)
13653013Syokota    return -1;
13753013Syokota
13828328Ssos  signal(SIGUSR1, VGLSwitch);
13928328Ssos  signal(SIGINT, VGLAbort);
14050483Syokota  signal(SIGTERM, VGLAbort);
14128328Ssos  signal(SIGSEGV, VGLAbort);
14228328Ssos  signal(SIGBUS, VGLAbort);
14380270Syokota  signal(SIGUSR2, SIG_IGN);
14428328Ssos
14528328Ssos  VGLOnDisplay = 1;
14628328Ssos  VGLSwitchPending = 0;
14780270Syokota  VGLAbortPending = 0;
14828328Ssos
14953013Syokota  if (ioctl(0, CONS_GET, &VGLOldMode) || ioctl(0, CONS_CURRENT, &adptype))
15053013Syokota    return -1;
15153013Syokota  if (IOCGROUP(mode) == 'V')	/* XXX: this is ugly */
15253013Syokota    VGLModeInfo.vi_mode = (mode & 0x0ff) + M_VESA_BASE;
15353013Syokota  else
15453013Syokota    VGLModeInfo.vi_mode = mode & 0x0ff;
15553013Syokota  if (ioctl(0, CONS_MODEINFO, &VGLModeInfo))	/* FBIO_MODEINFO */
15653013Syokota    return -1;
15728328Ssos
15871643Ssobomax  /* If current mode is VESA_800x600 then save its geometry to restore later */
15976852Ssobomax  if ((VGLOldMode >= M_VESA_BASE) && (VGLOldMode == M_VESA_800x600)) {
16076852Ssobomax    VGLOldVInfo.size = sizeof(VGLOldVInfo);
16176852Ssobomax    if (ioctl(0, CONS_GETINFO, &VGLOldVInfo))
16271643Ssobomax      return -1;
16376852Ssobomax  }
16471643Ssobomax
16553013Syokota  VGLDisplay = (VGLBitmap *)malloc(sizeof(VGLBitmap));
16653013Syokota  if (VGLDisplay == NULL)
16753013Syokota    return -2;
16828328Ssos
16953013Syokota  if (ioctl(0, KDENABIO, 0)) {
17053013Syokota    free(VGLDisplay);
17153013Syokota    return -3;
17228328Ssos  }
17328328Ssos
17453013Syokota  VGLInitDone = 1;
17553013Syokota
17653013Syokota  /*
17753013Syokota   * vi_mem_model specifies the memory model of the current video mode
17853013Syokota   * in -CURRENT.
17953013Syokota   */
18053013Syokota  switch (VGLModeInfo.vi_mem_model) {
18153013Syokota  case V_INFO_MM_PLANAR:
18253013Syokota    /* we can handle EGA/VGA planner modes only */
18353013Syokota    if (VGLModeInfo.vi_depth != 4 || VGLModeInfo.vi_planes != 4
18453013Syokota	|| (adptype != KD_EGA && adptype != KD_VGA)) {
18553013Syokota      VGLEnd();
18653013Syokota      return -4;
18753013Syokota    }
18828328Ssos    VGLDisplay->Type = VIDBUF4;
18928328Ssos    break;
19053013Syokota  case V_INFO_MM_PACKED:
19153013Syokota    /* we can do only 256 color packed modes */
19253013Syokota    if (VGLModeInfo.vi_depth != 8) {
19353013Syokota      VGLEnd();
19453013Syokota      return -4;
19553013Syokota    }
19628328Ssos    VGLDisplay->Type = VIDBUF8;
19771623Snsouch    VGLDisplay->PixelBytes = 1;
19828328Ssos    break;
19953013Syokota  case V_INFO_MM_VGAX:
20028328Ssos    VGLDisplay->Type = VIDBUF8X;
20171623Snsouch    VGLDisplay->PixelBytes = 1;
20228328Ssos    break;
20370991Snsouch  case V_INFO_MM_DIRECT:
20470991Snsouch    VGLDisplay->PixelBytes = VGLModeInfo.vi_pixel_size;
20570991Snsouch    switch (VGLDisplay->PixelBytes) {
20670991Snsouch    case 2:
20770991Snsouch      VGLDisplay->Type = VIDBUF16;
20870991Snsouch      break;
20970991Snsouch#if notyet
21070991Snsouch    case 3:
21170991Snsouch      VGLDisplay->Type = VIDBUF24;
21270991Snsouch      break;
21370991Snsouch#endif
21470991Snsouch    case 4:
21570991Snsouch      VGLDisplay->Type = VIDBUF32;
21670991Snsouch      break;
21770991Snsouch    default:
21870991Snsouch      VGLEnd();
21970991Snsouch      return -4;
22070991Snsouch    }
22170991Snsouch    break;
22228328Ssos  default:
22328328Ssos    VGLEnd();
22453013Syokota    return -4;
22528328Ssos  }
22628328Ssos
22728328Ssos  ioctl(0, VT_WAITACTIVE, 0);
22828328Ssos  ioctl(0, KDSETMODE, KD_GRAPHICS);
22953013Syokota  if (ioctl(0, mode, 0)) {
23053013Syokota    VGLEnd();
23153013Syokota    return -5;
23228328Ssos  }
23353013Syokota  if (ioctl(0, CONS_ADPINFO, &VGLAdpInfo)) {	/* FBIO_ADPINFO */
23453013Syokota    VGLEnd();
23553013Syokota    return -6;
23653013Syokota  }
23728328Ssos
23853013Syokota  /*
23953013Syokota   * Calculate the shadow screen buffer size.  In -CURRENT, va_buffer_size
24053013Syokota   * always holds the entire frame buffer size, wheather it's in the linear
24153013Syokota   * mode or windowed mode.
24253013Syokota   *     VGLBufSize = VGLAdpInfo.va_buffer_size;
24353013Syokota   * In -STABLE, va_buffer_size holds the frame buffer size, only if
24453013Syokota   * the linear frame buffer mode is supported. Otherwise the field is zero.
24553013Syokota   * We shall calculate the minimal size in this case:
24653013Syokota   *     VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*VGLModeInfo.vi_planes
24753013Syokota   * or
24853013Syokota   *     VGLAdpInfo.va_window_size*VGLModeInfo.vi_planes;
24953013Syokota   * Use whichever is larger.
25053013Syokota   */
25153013Syokota  if (VGLAdpInfo.va_buffer_size != 0)
25253013Syokota    VGLBufSize = VGLAdpInfo.va_buffer_size;
25353013Syokota  else
25453013Syokota    VGLBufSize = max(VGLAdpInfo.va_line_width*VGLModeInfo.vi_height,
25553013Syokota		     VGLAdpInfo.va_window_size)*VGLModeInfo.vi_planes;
25653013Syokota  VGLBuf = malloc(VGLBufSize);
25753013Syokota  if (VGLBuf == NULL) {
25853013Syokota    VGLEnd();
25953013Syokota    return -7;
26053013Syokota  }
26153013Syokota
26253013Syokota#ifdef LIBVGL_DEBUG
26353013Syokota  fprintf(stderr, "VGLBufSize:0x%x\n", VGLBufSize);
26453013Syokota#endif
26553013Syokota
26653013Syokota  /* see if we are in the windowed buffer mode or in the linear buffer mode */
26753013Syokota  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size) {
26870991Snsouch    switch (VGLDisplay->Type) {
26970991Snsouch    case VIDBUF4:
27053013Syokota      VGLDisplay->Type = VIDBUF4S;
27170991Snsouch      break;
27270991Snsouch    case VIDBUF8:
27353013Syokota      VGLDisplay->Type = VIDBUF8S;
27470991Snsouch      break;
27570991Snsouch    case VIDBUF16:
27670991Snsouch      VGLDisplay->Type = VIDBUF16S;
27770991Snsouch      break;
27870991Snsouch    case VIDBUF24:
27970991Snsouch      VGLDisplay->Type = VIDBUF24S;
28070991Snsouch      break;
28170991Snsouch    case VIDBUF32:
28270991Snsouch      VGLDisplay->Type = VIDBUF32S;
28370991Snsouch      break;
28470991Snsouch    default:
28570991Snsouch      VGLEnd();
28670991Snsouch      return -8;
28770991Snsouch    }
28853013Syokota  }
28953013Syokota
29028328Ssos  VGLMode = mode;
29153013Syokota  VGLCurWindow = 0;
29228328Ssos
29353013Syokota  VGLDisplay->Xsize = VGLModeInfo.vi_width;
29453013Syokota  VGLDisplay->Ysize = VGLModeInfo.vi_height;
29553013Syokota  VGLDisplay->VXsize = VGLAdpInfo.va_line_width
29653013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
29753013Syokota  VGLDisplay->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
29853013Syokota  VGLDisplay->Xorigin = 0;
29953013Syokota  VGLDisplay->Yorigin = 0;
30028328Ssos
30153013Syokota  VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
30253013Syokota		       MAP_FILE, 0, 0);
30353013Syokota  if (VGLMem == MAP_FAILED) {
30428328Ssos    VGLEnd();
30553013Syokota    return -7;
30628328Ssos  }
30753013Syokota  VGLDisplay->Bitmap = VGLMem;
30828328Ssos
30928328Ssos  VGLSavePalette();
31028328Ssos
31153013Syokota#ifdef LIBVGL_DEBUG
31253013Syokota  fprintf(stderr, "va_line_width:%d\n", VGLAdpInfo.va_line_width);
31353013Syokota  fprintf(stderr, "VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
31453013Syokota	  VGLDisplay->Xsize, VGLDisplay->Ysize,
31553013Syokota	  VGLDisplay->VXsize, VGLDisplay->VYsize);
31653013Syokota#endif
31753013Syokota
31828328Ssos  smode.mode = VT_PROCESS;
31928328Ssos  smode.waitv = 0;
32028328Ssos  smode.relsig = SIGUSR1;
32128328Ssos  smode.acqsig = SIGUSR1;
32228328Ssos  smode.frsig  = SIGINT;
32353013Syokota  if (ioctl(0, VT_SETMODE, &smode)) {
32428328Ssos    VGLEnd();
32553013Syokota    return -9;
32628328Ssos  }
32728328Ssos  VGLTextSetFontFile((byte*)0);
32853013Syokota  VGLClear(VGLDisplay, 0);
32928328Ssos  return 0;
33028328Ssos}
33128328Ssos
33228328Ssosvoid
33328328SsosVGLCheckSwitch()
33428328Ssos{
33580270Syokota  if (VGLAbortPending) {
33680270Syokota    VGLEnd();
33780270Syokota    exit(0);
33880270Syokota  }
33950483Syokota  while (VGLSwitchPending) {
34053013Syokota    unsigned int offset;
34153013Syokota    unsigned int len;
34228328Ssos    int i;
34328328Ssos
34428328Ssos    VGLSwitchPending = 0;
34528328Ssos    if (VGLOnDisplay) {
34628328Ssos      ioctl(0, KDENABIO, 0);
34728328Ssos      ioctl(0, KDSETMODE, KD_GRAPHICS);
34828328Ssos      ioctl(0, VGLMode, 0);
34953013Syokota      VGLCurWindow = 0;
35053013Syokota      VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
35153013Syokota			   MAP_FILE, 0, 0);
35253013Syokota
35353013Syokota      /* XXX: what if mmap() has failed! */
35453013Syokota      VGLDisplay->Type = VIDBUF8;	/* XXX */
35553013Syokota      switch (VGLModeInfo.vi_mem_model) {
35653013Syokota      case V_INFO_MM_PLANAR:
35753013Syokota	if (VGLModeInfo.vi_depth == 4 && VGLModeInfo.vi_planes == 4) {
35853013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
35953013Syokota	    VGLDisplay->Type = VIDBUF4S;
36053013Syokota	  else
36153013Syokota	    VGLDisplay->Type = VIDBUF4;
36253013Syokota	} else {
36353013Syokota	  /* shouldn't be happening */
36453013Syokota	}
36528328Ssos        break;
36653013Syokota      case V_INFO_MM_PACKED:
36753013Syokota	if (VGLModeInfo.vi_depth == 8) {
36853013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
36953013Syokota	    VGLDisplay->Type = VIDBUF8S;
37053013Syokota	  else
37153013Syokota	    VGLDisplay->Type = VIDBUF8;
37253013Syokota	}
37328328Ssos        break;
37453013Syokota      case V_INFO_MM_VGAX:
37553013Syokota	VGLDisplay->Type = VIDBUF8X;
37653013Syokota	break;
37770991Snsouch      case V_INFO_MM_DIRECT:
37870991Snsouch	switch (VGLModeInfo.vi_pixel_size) {
37970991Snsouch	  case 2:
38070991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
38170991Snsouch	      VGLDisplay->Type = VIDBUF16S;
38270991Snsouch	    else
38370991Snsouch	      VGLDisplay->Type = VIDBUF16;
38470991Snsouch	    break;
38570991Snsouch	  case 3:
38670991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
38770991Snsouch	      VGLDisplay->Type = VIDBUF24S;
38870991Snsouch	    else
38970991Snsouch	      VGLDisplay->Type = VIDBUF24;
39070991Snsouch	    break;
39170991Snsouch	  case 4:
39270991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
39370991Snsouch	      VGLDisplay->Type = VIDBUF32S;
39470991Snsouch	    else
39570991Snsouch	      VGLDisplay->Type = VIDBUF32;
39670991Snsouch	    break;
39770991Snsouch	  default:
39870991Snsouch	  /* shouldn't be happening */
39970991Snsouch          break;
40070991Snsouch        }
40128328Ssos      default:
40253013Syokota	/* shouldn't be happening */
40328328Ssos        break;
40428328Ssos      }
40553013Syokota
40653013Syokota      VGLDisplay->Bitmap = VGLMem;
40753013Syokota      VGLDisplay->Xsize = VGLModeInfo.vi_width;
40853013Syokota      VGLDisplay->Ysize = VGLModeInfo.vi_height;
40953013Syokota      VGLSetVScreenSize(VGLDisplay, VGLDisplay->VXsize, VGLDisplay->VYsize);
41053013Syokota      VGLPanScreen(VGLDisplay, VGLDisplay->Xorigin, VGLDisplay->Yorigin);
41153013Syokota      switch (VGLDisplay->Type) {
41253013Syokota      case VIDBUF4S:
41353013Syokota	outb(0x3c6, 0xff);
41453013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
41553013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
41653013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
41753013Syokota	     offset += len) {
41853013Syokota	  VGLSetSegment(offset);
41953013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
42053013Syokota		    VGLAdpInfo.va_window_size);
42153013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
42253013Syokota	    outb(0x3c4, 0x02);
42353013Syokota	    outb(0x3c5, 0x01<<i);
42453013Syokota	    bcopy(&VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
42553013Syokota		  VGLMem, len);
42653013Syokota	  }
42753013Syokota	}
42853013Syokota	break;
42953013Syokota      case VIDBUF4:
43053013Syokota      case VIDBUF8X:
43153013Syokota	outb(0x3c6, 0xff);
43253013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
43353013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
43453013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
43553013Syokota	  outb(0x3c4, 0x02);
43653013Syokota	  outb(0x3c5, 0x01<<i);
43753013Syokota	  bcopy(&VGLBuf[i*VGLAdpInfo.va_window_size], VGLMem,
43853013Syokota		VGLAdpInfo.va_window_size);
43953013Syokota	}
44053013Syokota	break;
44153013Syokota      case VIDBUF8:
44253013Syokota      case VIDBUF8S:
44370991Snsouch      case VIDBUF16:
44470991Snsouch      case VIDBUF16S:
44570991Snsouch      case VIDBUF24:
44670991Snsouch      case VIDBUF24S:
44770991Snsouch      case VIDBUF32:
44870991Snsouch      case VIDBUF32S:
44953013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
45053013Syokota	  VGLSetSegment(offset);
45153013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
45253013Syokota          bcopy(&VGLBuf[offset], VGLMem, len);
45353013Syokota	}
45453013Syokota	break;
45553013Syokota      }
45653013Syokota      VGLRestorePalette();
45753013Syokota      ioctl(0, VT_RELDISP, VT_ACKACQ);
45828328Ssos    }
45928328Ssos    else {
46053013Syokota      switch (VGLDisplay->Type) {
46153013Syokota      case VIDBUF4S:
46253013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
46353013Syokota	     offset += len) {
46453013Syokota	  VGLSetSegment(offset);
46553013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
46653013Syokota		    VGLAdpInfo.va_window_size);
46753013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
46853013Syokota	    outb(0x3ce, 0x04);
46953013Syokota	    outb(0x3cf, i);
47053013Syokota	    bcopy(VGLMem, &VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
47153013Syokota		  len);
47253013Syokota	  }
47353013Syokota	}
47453013Syokota	break;
47553013Syokota      case VIDBUF4:
47653013Syokota      case VIDBUF8X:
47753013Syokota	/*
47853013Syokota	 * NOTE: the saved buffer is NOT in the MEMBUF format which
47953013Syokota	 * the ordinary memory bitmap object is stored in. XXX
48053013Syokota	 */
48153013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
48253013Syokota	  outb(0x3ce, 0x04);
48353013Syokota	  outb(0x3cf, i);
48453013Syokota	  bcopy(VGLMem, &VGLBuf[i*VGLAdpInfo.va_window_size],
48553013Syokota		VGLAdpInfo.va_window_size);
48653013Syokota	}
48753013Syokota	break;
48853013Syokota      case VIDBUF8:
48953013Syokota      case VIDBUF8S:
49070991Snsouch      case VIDBUF16:
49170991Snsouch      case VIDBUF16S:
49270991Snsouch      case VIDBUF24:
49370991Snsouch      case VIDBUF24S:
49470991Snsouch      case VIDBUF32:
49570991Snsouch      case VIDBUF32S:
49653013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
49753013Syokota	  VGLSetSegment(offset);
49853013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
49953013Syokota          bcopy(VGLMem, &VGLBuf[offset], len);
50053013Syokota	}
50153013Syokota	break;
50228328Ssos      }
50353013Syokota      VGLMem = MAP_FAILED;
50453013Syokota      munmap(VGLDisplay->Bitmap, VGLAdpInfo.va_window_size);
50528328Ssos      ioctl(0, VGLOldMode, 0);
50628328Ssos      ioctl(0, KDSETMODE, KD_TEXT);
50728328Ssos      ioctl(0, KDDISABIO, 0);
50828328Ssos      ioctl(0, VT_RELDISP, VT_TRUE);
50928328Ssos      VGLDisplay->Bitmap = VGLBuf;
51028328Ssos      VGLDisplay->Type = MEMBUF;
51153013Syokota      VGLDisplay->Xsize = VGLDisplay->VXsize;
51253013Syokota      VGLDisplay->Ysize = VGLDisplay->VYsize;
51350483Syokota      while (!VGLOnDisplay) pause();
51428328Ssos    }
51528328Ssos  }
51628328Ssos}
51753013Syokota
51853013Syokotaint
51953013SyokotaVGLSetSegment(unsigned int offset)
52053013Syokota{
52153013Syokota  if (offset/VGLAdpInfo.va_window_size != VGLCurWindow) {
52253013Syokota    ioctl(0, CONS_SETWINORG, offset);		/* FBIO_SETWINORG */
52353013Syokota    VGLCurWindow = offset/VGLAdpInfo.va_window_size;
52453013Syokota  }
52553013Syokota  return (offset%VGLAdpInfo.va_window_size);
52653013Syokota}
52753013Syokota
52853013Syokotaint
52953013SyokotaVGLSetVScreenSize(VGLBitmap *object, int VXsize, int VYsize)
53053013Syokota{
53153013Syokota  if (VXsize < object->Xsize || VYsize < object->Ysize)
53253013Syokota    return -1;
53353013Syokota  if (object->Type == MEMBUF)
53453013Syokota    return -1;
53553013Syokota  if (ioctl(0, FBIO_SETLINEWIDTH, &VXsize))
53653013Syokota    return -1;
53753013Syokota  ioctl(0, CONS_ADPINFO, &VGLAdpInfo);	/* FBIO_ADPINFO */
53853013Syokota  object->VXsize = VGLAdpInfo.va_line_width
53953013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
54053013Syokota  object->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
54153013Syokota  if (VYsize < object->VYsize)
54253013Syokota    object->VYsize = VYsize;
54353013Syokota
54453013Syokota#ifdef LIBVGL_DEBUG
54553013Syokota  fprintf(stderr, "new size: VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
54653013Syokota	  object->Xsize, object->Ysize, object->VXsize, object->VYsize);
54753013Syokota#endif
54853013Syokota
54953013Syokota  return 0;
55053013Syokota}
55153013Syokota
55253013Syokotaint
55353013SyokotaVGLPanScreen(VGLBitmap *object, int x, int y)
55453013Syokota{
55553013Syokota  video_display_start_t origin;
55653013Syokota
55753013Syokota  if (x < 0 || x + object->Xsize > object->VXsize
55853013Syokota      || y < 0 || y + object->Ysize > object->VYsize)
55953013Syokota    return -1;
56053013Syokota  if (object->Type == MEMBUF)
56153013Syokota    return 0;
56253013Syokota  origin.x = x;
56353013Syokota  origin.y = y;
56453013Syokota  if (ioctl(0, FBIO_SETDISPSTART, &origin))
56553013Syokota    return -1;
56653013Syokota  object->Xorigin = x;
56753013Syokota  object->Yorigin = y;
56853013Syokota
56953013Syokota#ifdef LIBVGL_DEBUG
57053013Syokota  fprintf(stderr, "new origin: (%d, %d)\n", x, y);
57153013Syokota#endif
57253013Syokota
57353013Syokota  return 0;
57453013Syokota}
575