main.c revision 76852
128328Ssos/*-
228328Ssos * 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
1528328Ssos *    derived from this software withough 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 *
2850476Speter * $FreeBSD: head/lib/libvgl/main.c 76852 2001-05-19 17:05:52Z sobomax $
2928328Ssos */
3028328Ssos
3128328Ssos#include <stdio.h>
3228328Ssos#include <sys/types.h>
3328328Ssos#include <sys/signal.h>
3428328Ssos#include <sys/file.h>
3528328Ssos#include <sys/ioctl.h>
3628328Ssos#include <sys/mman.h>
3766834Sphk#include <sys/fbio.h>
3866834Sphk#include <sys/kbio.h>
3966834Sphk#include <sys/consio.h>
4028328Ssos#include "vgl.h"
4128328Ssos
4270991Snsouch/* XXX Direct Color 24bits modes unsupported */
4370991Snsouch
4453013Syokota#define min(x, y)	(((x) < (y)) ? (x) : (y))
4553013Syokota#define max(x, y)	(((x) > (y)) ? (x) : (y))
4653013Syokota
4728328SsosVGLBitmap *VGLDisplay;
4853013Syokotavideo_info_t VGLModeInfo;
4953013Syokotavideo_adapter_info_t VGLAdpInfo;
5053013Syokotabyte *VGLBuf;
5128328Ssos
5228328Ssosstatic int VGLMode;
5328328Ssosstatic int VGLOldMode;
5453013Syokotastatic size_t VGLBufSize;
5553013Syokotastatic byte *VGLMem = MAP_FAILED;
5628328Ssosstatic int VGLSwitchPending;
5728328Ssosstatic int VGLOnDisplay;
5853013Syokotastatic unsigned int VGLCurWindow;
5930044Ssosstatic int VGLInitDone = 0;
6076852Ssobomaxstatic vid_info_t VGLOldVInfo;
6128328Ssos
6228328Ssosvoid
6328328SsosVGLEnd()
6428328Ssos{
6528328Ssosstruct vt_mode smode;
6628328Ssos
6730044Ssos  if (!VGLInitDone)
6830044Ssos    return;
6953013Syokota  VGLInitDone = 0;
7053013Syokota
7153013Syokota  signal(SIGUSR1, SIG_IGN);
7253013Syokota
7353013Syokota  if (VGLMem != MAP_FAILED) {
7453013Syokota    VGLClear(VGLDisplay, 0);
7553013Syokota    munmap(VGLMem, VGLAdpInfo.va_window_size);
7650483Syokota  }
7753013Syokota
7850141Syokota  if (VGLOldMode >= M_VESA_BASE) {
7950141Syokota    /* ugly, but necessary */
8050141Syokota    ioctl(0, _IO('V', VGLOldMode - M_VESA_BASE), 0);
8150141Syokota    if (VGLOldMode == M_VESA_800x600) {
8250141Syokota      int size[3];
8376852Ssobomax      size[0] = VGLOldVInfo.mv_csz;
8476852Ssobomax      size[1] = VGLOldVInfo.mv_rsz;
8550141Syokota      size[2] = 16;
8650141Syokota      ioctl(0, KDRASTER, size);
8750141Syokota    }
8850141Syokota  } else {
8950141Syokota    ioctl(0, _IO('S', VGLOldMode), 0);
9050141Syokota  }
9128328Ssos  ioctl(0, KDDISABIO, 0);
9228328Ssos  ioctl(0, KDSETMODE, KD_TEXT);
9328328Ssos  smode.mode = VT_AUTO;
9428328Ssos  ioctl(0, VT_SETMODE, &smode);
9553013Syokota  if (VGLBuf)
9653013Syokota    free(VGLBuf);
9753013Syokota  VGLBuf = NULL;
9828328Ssos  free(VGLDisplay);
9953013Syokota  VGLDisplay = NULL;
10030044Ssos  VGLKeyboardEnd();
10128328Ssos}
10228328Ssos
10328328Ssosstatic void
10428328SsosVGLAbort()
10528328Ssos{
10628328Ssos  VGLEnd();
10728328Ssos  exit(0);
10828328Ssos}
10928328Ssos
11028328Ssosstatic void
11128328SsosVGLSwitch()
11228328Ssos{
11328328Ssos  if (!VGLOnDisplay)
11428328Ssos    VGLOnDisplay = 1;
11528328Ssos  else
11628328Ssos    VGLOnDisplay = 0;
11728328Ssos  VGLSwitchPending = 1;
11828328Ssos  signal(SIGUSR1, VGLSwitch);
11928328Ssos}
12028328Ssos
12128328Ssosint
12228328SsosVGLInit(int mode)
12328328Ssos{
12428328Ssos  struct vt_mode smode;
12553013Syokota  int adptype;
12628328Ssos
12753013Syokota  if (VGLInitDone)
12853013Syokota    return -1;
12953013Syokota
13028328Ssos  signal(SIGUSR1, VGLSwitch);
13128328Ssos  signal(SIGINT, VGLAbort);
13250483Syokota  signal(SIGTERM, VGLAbort);
13328328Ssos  signal(SIGSEGV, VGLAbort);
13428328Ssos  signal(SIGBUS, VGLAbort);
13528328Ssos
13628328Ssos  VGLOnDisplay = 1;
13728328Ssos  VGLSwitchPending = 0;
13828328Ssos
13953013Syokota  if (ioctl(0, CONS_GET, &VGLOldMode) || ioctl(0, CONS_CURRENT, &adptype))
14053013Syokota    return -1;
14153013Syokota  if (IOCGROUP(mode) == 'V')	/* XXX: this is ugly */
14253013Syokota    VGLModeInfo.vi_mode = (mode & 0x0ff) + M_VESA_BASE;
14353013Syokota  else
14453013Syokota    VGLModeInfo.vi_mode = mode & 0x0ff;
14553013Syokota  if (ioctl(0, CONS_MODEINFO, &VGLModeInfo))	/* FBIO_MODEINFO */
14653013Syokota    return -1;
14728328Ssos
14871643Ssobomax  /* If current mode is VESA_800x600 then save its geometry to restore later */
14976852Ssobomax  if ((VGLOldMode >= M_VESA_BASE) && (VGLOldMode == M_VESA_800x600)) {
15076852Ssobomax    VGLOldVInfo.size = sizeof(VGLOldVInfo);
15176852Ssobomax    if (ioctl(0, CONS_GETINFO, &VGLOldVInfo))
15271643Ssobomax      return -1;
15376852Ssobomax  }
15471643Ssobomax
15553013Syokota  VGLDisplay = (VGLBitmap *)malloc(sizeof(VGLBitmap));
15653013Syokota  if (VGLDisplay == NULL)
15753013Syokota    return -2;
15828328Ssos
15953013Syokota  if (ioctl(0, KDENABIO, 0)) {
16053013Syokota    free(VGLDisplay);
16153013Syokota    return -3;
16228328Ssos  }
16328328Ssos
16453013Syokota  VGLInitDone = 1;
16553013Syokota
16653013Syokota  /*
16753013Syokota   * vi_mem_model specifies the memory model of the current video mode
16853013Syokota   * in -CURRENT.
16953013Syokota   */
17053013Syokota  switch (VGLModeInfo.vi_mem_model) {
17153013Syokota  case V_INFO_MM_PLANAR:
17253013Syokota    /* we can handle EGA/VGA planner modes only */
17353013Syokota    if (VGLModeInfo.vi_depth != 4 || VGLModeInfo.vi_planes != 4
17453013Syokota	|| (adptype != KD_EGA && adptype != KD_VGA)) {
17553013Syokota      VGLEnd();
17653013Syokota      return -4;
17753013Syokota    }
17828328Ssos    VGLDisplay->Type = VIDBUF4;
17928328Ssos    break;
18053013Syokota  case V_INFO_MM_PACKED:
18153013Syokota    /* we can do only 256 color packed modes */
18253013Syokota    if (VGLModeInfo.vi_depth != 8) {
18353013Syokota      VGLEnd();
18453013Syokota      return -4;
18553013Syokota    }
18628328Ssos    VGLDisplay->Type = VIDBUF8;
18771623Snsouch    VGLDisplay->PixelBytes = 1;
18828328Ssos    break;
18953013Syokota  case V_INFO_MM_VGAX:
19028328Ssos    VGLDisplay->Type = VIDBUF8X;
19171623Snsouch    VGLDisplay->PixelBytes = 1;
19228328Ssos    break;
19370991Snsouch  case V_INFO_MM_DIRECT:
19470991Snsouch    VGLDisplay->PixelBytes = VGLModeInfo.vi_pixel_size;
19570991Snsouch    switch (VGLDisplay->PixelBytes) {
19670991Snsouch    case 2:
19770991Snsouch      VGLDisplay->Type = VIDBUF16;
19870991Snsouch      break;
19970991Snsouch#if notyet
20070991Snsouch    case 3:
20170991Snsouch      VGLDisplay->Type = VIDBUF24;
20270991Snsouch      break;
20370991Snsouch#endif
20470991Snsouch    case 4:
20570991Snsouch      VGLDisplay->Type = VIDBUF32;
20670991Snsouch      break;
20770991Snsouch    default:
20870991Snsouch      VGLEnd();
20970991Snsouch      return -4;
21070991Snsouch    }
21170991Snsouch    break;
21228328Ssos  default:
21328328Ssos    VGLEnd();
21453013Syokota    return -4;
21528328Ssos  }
21628328Ssos
21728328Ssos  ioctl(0, VT_WAITACTIVE, 0);
21828328Ssos  ioctl(0, KDSETMODE, KD_GRAPHICS);
21953013Syokota  if (ioctl(0, mode, 0)) {
22053013Syokota    VGLEnd();
22153013Syokota    return -5;
22228328Ssos  }
22353013Syokota  if (ioctl(0, CONS_ADPINFO, &VGLAdpInfo)) {	/* FBIO_ADPINFO */
22453013Syokota    VGLEnd();
22553013Syokota    return -6;
22653013Syokota  }
22728328Ssos
22853013Syokota  /*
22953013Syokota   * Calculate the shadow screen buffer size.  In -CURRENT, va_buffer_size
23053013Syokota   * always holds the entire frame buffer size, wheather it's in the linear
23153013Syokota   * mode or windowed mode.
23253013Syokota   *     VGLBufSize = VGLAdpInfo.va_buffer_size;
23353013Syokota   * In -STABLE, va_buffer_size holds the frame buffer size, only if
23453013Syokota   * the linear frame buffer mode is supported. Otherwise the field is zero.
23553013Syokota   * We shall calculate the minimal size in this case:
23653013Syokota   *     VGLAdpInfo.va_line_width*VGLModeInfo.vi_height*VGLModeInfo.vi_planes
23753013Syokota   * or
23853013Syokota   *     VGLAdpInfo.va_window_size*VGLModeInfo.vi_planes;
23953013Syokota   * Use whichever is larger.
24053013Syokota   */
24153013Syokota  if (VGLAdpInfo.va_buffer_size != 0)
24253013Syokota    VGLBufSize = VGLAdpInfo.va_buffer_size;
24353013Syokota  else
24453013Syokota    VGLBufSize = max(VGLAdpInfo.va_line_width*VGLModeInfo.vi_height,
24553013Syokota		     VGLAdpInfo.va_window_size)*VGLModeInfo.vi_planes;
24653013Syokota  VGLBuf = malloc(VGLBufSize);
24753013Syokota  if (VGLBuf == NULL) {
24853013Syokota    VGLEnd();
24953013Syokota    return -7;
25053013Syokota  }
25153013Syokota
25253013Syokota#ifdef LIBVGL_DEBUG
25353013Syokota  fprintf(stderr, "VGLBufSize:0x%x\n", VGLBufSize);
25453013Syokota#endif
25553013Syokota
25653013Syokota  /* see if we are in the windowed buffer mode or in the linear buffer mode */
25753013Syokota  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size) {
25870991Snsouch    switch (VGLDisplay->Type) {
25970991Snsouch    case VIDBUF4:
26053013Syokota      VGLDisplay->Type = VIDBUF4S;
26170991Snsouch      break;
26270991Snsouch    case VIDBUF8:
26353013Syokota      VGLDisplay->Type = VIDBUF8S;
26470991Snsouch      break;
26570991Snsouch    case VIDBUF16:
26670991Snsouch      VGLDisplay->Type = VIDBUF16S;
26770991Snsouch      break;
26870991Snsouch    case VIDBUF24:
26970991Snsouch      VGLDisplay->Type = VIDBUF24S;
27070991Snsouch      break;
27170991Snsouch    case VIDBUF32:
27270991Snsouch      VGLDisplay->Type = VIDBUF32S;
27370991Snsouch      break;
27470991Snsouch    default:
27570991Snsouch      VGLEnd();
27670991Snsouch      return -8;
27770991Snsouch    }
27853013Syokota  }
27953013Syokota
28028328Ssos  VGLMode = mode;
28153013Syokota  VGLCurWindow = 0;
28228328Ssos
28353013Syokota  VGLDisplay->Xsize = VGLModeInfo.vi_width;
28453013Syokota  VGLDisplay->Ysize = VGLModeInfo.vi_height;
28553013Syokota  VGLDisplay->VXsize = VGLAdpInfo.va_line_width
28653013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
28753013Syokota  VGLDisplay->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
28853013Syokota  VGLDisplay->Xorigin = 0;
28953013Syokota  VGLDisplay->Yorigin = 0;
29028328Ssos
29153013Syokota  VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
29253013Syokota		       MAP_FILE, 0, 0);
29353013Syokota  if (VGLMem == MAP_FAILED) {
29428328Ssos    VGLEnd();
29553013Syokota    return -7;
29628328Ssos  }
29753013Syokota  VGLDisplay->Bitmap = VGLMem;
29828328Ssos
29928328Ssos  VGLSavePalette();
30028328Ssos
30153013Syokota#ifdef LIBVGL_DEBUG
30253013Syokota  fprintf(stderr, "va_line_width:%d\n", VGLAdpInfo.va_line_width);
30353013Syokota  fprintf(stderr, "VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
30453013Syokota	  VGLDisplay->Xsize, VGLDisplay->Ysize,
30553013Syokota	  VGLDisplay->VXsize, VGLDisplay->VYsize);
30653013Syokota#endif
30753013Syokota
30828328Ssos  smode.mode = VT_PROCESS;
30928328Ssos  smode.waitv = 0;
31028328Ssos  smode.relsig = SIGUSR1;
31128328Ssos  smode.acqsig = SIGUSR1;
31228328Ssos  smode.frsig  = SIGINT;
31353013Syokota  if (ioctl(0, VT_SETMODE, &smode)) {
31428328Ssos    VGLEnd();
31553013Syokota    return -9;
31628328Ssos  }
31728328Ssos  VGLTextSetFontFile((byte*)0);
31853013Syokota  VGLClear(VGLDisplay, 0);
31928328Ssos  return 0;
32028328Ssos}
32128328Ssos
32228328Ssosvoid
32328328SsosVGLCheckSwitch()
32428328Ssos{
32550483Syokota  while (VGLSwitchPending) {
32653013Syokota    unsigned int offset;
32753013Syokota    unsigned int len;
32828328Ssos    int i;
32928328Ssos
33028328Ssos    VGLSwitchPending = 0;
33128328Ssos    if (VGLOnDisplay) {
33228328Ssos      ioctl(0, KDENABIO, 0);
33328328Ssos      ioctl(0, KDSETMODE, KD_GRAPHICS);
33428328Ssos      ioctl(0, VGLMode, 0);
33553013Syokota      VGLCurWindow = 0;
33653013Syokota      VGLMem = (byte*)mmap(0, VGLAdpInfo.va_window_size, PROT_READ|PROT_WRITE,
33753013Syokota			   MAP_FILE, 0, 0);
33853013Syokota
33953013Syokota      /* XXX: what if mmap() has failed! */
34053013Syokota      VGLDisplay->Type = VIDBUF8;	/* XXX */
34153013Syokota      switch (VGLModeInfo.vi_mem_model) {
34253013Syokota      case V_INFO_MM_PLANAR:
34353013Syokota	if (VGLModeInfo.vi_depth == 4 && VGLModeInfo.vi_planes == 4) {
34453013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
34553013Syokota	    VGLDisplay->Type = VIDBUF4S;
34653013Syokota	  else
34753013Syokota	    VGLDisplay->Type = VIDBUF4;
34853013Syokota	} else {
34953013Syokota	  /* shouldn't be happening */
35053013Syokota	}
35128328Ssos        break;
35253013Syokota      case V_INFO_MM_PACKED:
35353013Syokota	if (VGLModeInfo.vi_depth == 8) {
35453013Syokota	  if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
35553013Syokota	    VGLDisplay->Type = VIDBUF8S;
35653013Syokota	  else
35753013Syokota	    VGLDisplay->Type = VIDBUF8;
35853013Syokota	}
35928328Ssos        break;
36053013Syokota      case V_INFO_MM_VGAX:
36153013Syokota	VGLDisplay->Type = VIDBUF8X;
36253013Syokota	break;
36370991Snsouch      case V_INFO_MM_DIRECT:
36470991Snsouch	switch (VGLModeInfo.vi_pixel_size) {
36570991Snsouch	  case 2:
36670991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
36770991Snsouch	      VGLDisplay->Type = VIDBUF16S;
36870991Snsouch	    else
36970991Snsouch	      VGLDisplay->Type = VIDBUF16;
37070991Snsouch	    break;
37170991Snsouch	  case 3:
37270991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
37370991Snsouch	      VGLDisplay->Type = VIDBUF24S;
37470991Snsouch	    else
37570991Snsouch	      VGLDisplay->Type = VIDBUF24;
37670991Snsouch	    break;
37770991Snsouch	  case 4:
37870991Snsouch	    if (VGLBufSize/VGLModeInfo.vi_planes > VGLAdpInfo.va_window_size)
37970991Snsouch	      VGLDisplay->Type = VIDBUF32S;
38070991Snsouch	    else
38170991Snsouch	      VGLDisplay->Type = VIDBUF32;
38270991Snsouch	    break;
38370991Snsouch	  default:
38470991Snsouch	  /* shouldn't be happening */
38570991Snsouch          break;
38670991Snsouch        }
38728328Ssos      default:
38853013Syokota	/* shouldn't be happening */
38928328Ssos        break;
39028328Ssos      }
39153013Syokota
39253013Syokota      VGLDisplay->Bitmap = VGLMem;
39353013Syokota      VGLDisplay->Xsize = VGLModeInfo.vi_width;
39453013Syokota      VGLDisplay->Ysize = VGLModeInfo.vi_height;
39553013Syokota      VGLSetVScreenSize(VGLDisplay, VGLDisplay->VXsize, VGLDisplay->VYsize);
39653013Syokota      VGLPanScreen(VGLDisplay, VGLDisplay->Xorigin, VGLDisplay->Yorigin);
39753013Syokota      switch (VGLDisplay->Type) {
39853013Syokota      case VIDBUF4S:
39953013Syokota	outb(0x3c6, 0xff);
40053013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
40153013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
40253013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
40353013Syokota	     offset += len) {
40453013Syokota	  VGLSetSegment(offset);
40553013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
40653013Syokota		    VGLAdpInfo.va_window_size);
40753013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
40853013Syokota	    outb(0x3c4, 0x02);
40953013Syokota	    outb(0x3c5, 0x01<<i);
41053013Syokota	    bcopy(&VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
41153013Syokota		  VGLMem, len);
41253013Syokota	  }
41353013Syokota	}
41453013Syokota	break;
41553013Syokota      case VIDBUF4:
41653013Syokota      case VIDBUF8X:
41753013Syokota	outb(0x3c6, 0xff);
41853013Syokota	outb(0x3ce, 0x01); outb(0x3cf, 0x00);		/* set/reset enable */
41953013Syokota	outb(0x3ce, 0x08); outb(0x3cf, 0xff);		/* bit mask */
42053013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
42153013Syokota	  outb(0x3c4, 0x02);
42253013Syokota	  outb(0x3c5, 0x01<<i);
42353013Syokota	  bcopy(&VGLBuf[i*VGLAdpInfo.va_window_size], VGLMem,
42453013Syokota		VGLAdpInfo.va_window_size);
42553013Syokota	}
42653013Syokota	break;
42753013Syokota      case VIDBUF8:
42853013Syokota      case VIDBUF8S:
42970991Snsouch      case VIDBUF16:
43070991Snsouch      case VIDBUF16S:
43170991Snsouch      case VIDBUF24:
43270991Snsouch      case VIDBUF24S:
43370991Snsouch      case VIDBUF32:
43470991Snsouch      case VIDBUF32S:
43553013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
43653013Syokota	  VGLSetSegment(offset);
43753013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
43853013Syokota          bcopy(&VGLBuf[offset], VGLMem, len);
43953013Syokota	}
44053013Syokota	break;
44153013Syokota      }
44253013Syokota      VGLRestorePalette();
44353013Syokota      ioctl(0, VT_RELDISP, VT_ACKACQ);
44428328Ssos    }
44528328Ssos    else {
44653013Syokota      switch (VGLDisplay->Type) {
44753013Syokota      case VIDBUF4S:
44853013Syokota	for (offset = 0; offset < VGLBufSize/VGLModeInfo.vi_planes;
44953013Syokota	     offset += len) {
45053013Syokota	  VGLSetSegment(offset);
45153013Syokota	  len = min(VGLBufSize/VGLModeInfo.vi_planes - offset,
45253013Syokota		    VGLAdpInfo.va_window_size);
45353013Syokota	  for (i = 0; i < VGLModeInfo.vi_planes; i++) {
45453013Syokota	    outb(0x3ce, 0x04);
45553013Syokota	    outb(0x3cf, i);
45653013Syokota	    bcopy(VGLMem, &VGLBuf[i*VGLBufSize/VGLModeInfo.vi_planes + offset],
45753013Syokota		  len);
45853013Syokota	  }
45953013Syokota	}
46053013Syokota	break;
46153013Syokota      case VIDBUF4:
46253013Syokota      case VIDBUF8X:
46353013Syokota	/*
46453013Syokota	 * NOTE: the saved buffer is NOT in the MEMBUF format which
46553013Syokota	 * the ordinary memory bitmap object is stored in. XXX
46653013Syokota	 */
46753013Syokota	for (i = 0; i < VGLModeInfo.vi_planes; i++) {
46853013Syokota	  outb(0x3ce, 0x04);
46953013Syokota	  outb(0x3cf, i);
47053013Syokota	  bcopy(VGLMem, &VGLBuf[i*VGLAdpInfo.va_window_size],
47153013Syokota		VGLAdpInfo.va_window_size);
47253013Syokota	}
47353013Syokota	break;
47453013Syokota      case VIDBUF8:
47553013Syokota      case VIDBUF8S:
47670991Snsouch      case VIDBUF16:
47770991Snsouch      case VIDBUF16S:
47870991Snsouch      case VIDBUF24:
47970991Snsouch      case VIDBUF24S:
48070991Snsouch      case VIDBUF32:
48170991Snsouch      case VIDBUF32S:
48253013Syokota	for (offset = 0; offset < VGLBufSize; offset += len) {
48353013Syokota	  VGLSetSegment(offset);
48453013Syokota	  len = min(VGLBufSize - offset, VGLAdpInfo.va_window_size);
48553013Syokota          bcopy(VGLMem, &VGLBuf[offset], len);
48653013Syokota	}
48753013Syokota	break;
48828328Ssos      }
48953013Syokota      VGLMem = MAP_FAILED;
49053013Syokota      munmap(VGLDisplay->Bitmap, VGLAdpInfo.va_window_size);
49128328Ssos      ioctl(0, VGLOldMode, 0);
49228328Ssos      ioctl(0, KDSETMODE, KD_TEXT);
49328328Ssos      ioctl(0, KDDISABIO, 0);
49428328Ssos      ioctl(0, VT_RELDISP, VT_TRUE);
49528328Ssos      VGLDisplay->Bitmap = VGLBuf;
49628328Ssos      VGLDisplay->Type = MEMBUF;
49753013Syokota      VGLDisplay->Xsize = VGLDisplay->VXsize;
49853013Syokota      VGLDisplay->Ysize = VGLDisplay->VYsize;
49950483Syokota      while (!VGLOnDisplay) pause();
50028328Ssos    }
50128328Ssos  }
50228328Ssos}
50353013Syokota
50453013Syokotaint
50553013SyokotaVGLSetSegment(unsigned int offset)
50653013Syokota{
50753013Syokota  if (offset/VGLAdpInfo.va_window_size != VGLCurWindow) {
50853013Syokota    ioctl(0, CONS_SETWINORG, offset);		/* FBIO_SETWINORG */
50953013Syokota    VGLCurWindow = offset/VGLAdpInfo.va_window_size;
51053013Syokota  }
51153013Syokota  return (offset%VGLAdpInfo.va_window_size);
51253013Syokota}
51353013Syokota
51453013Syokotaint
51553013SyokotaVGLSetVScreenSize(VGLBitmap *object, int VXsize, int VYsize)
51653013Syokota{
51753013Syokota  if (VXsize < object->Xsize || VYsize < object->Ysize)
51853013Syokota    return -1;
51953013Syokota  if (object->Type == MEMBUF)
52053013Syokota    return -1;
52153013Syokota  if (ioctl(0, FBIO_SETLINEWIDTH, &VXsize))
52253013Syokota    return -1;
52353013Syokota  ioctl(0, CONS_ADPINFO, &VGLAdpInfo);	/* FBIO_ADPINFO */
52453013Syokota  object->VXsize = VGLAdpInfo.va_line_width
52553013Syokota			   *8/(VGLModeInfo.vi_depth/VGLModeInfo.vi_planes);
52653013Syokota  object->VYsize = VGLBufSize/VGLModeInfo.vi_planes/VGLAdpInfo.va_line_width;
52753013Syokota  if (VYsize < object->VYsize)
52853013Syokota    object->VYsize = VYsize;
52953013Syokota
53053013Syokota#ifdef LIBVGL_DEBUG
53153013Syokota  fprintf(stderr, "new size: VGLXsize:%d, Ysize:%d, VXsize:%d, VYsize:%d\n",
53253013Syokota	  object->Xsize, object->Ysize, object->VXsize, object->VYsize);
53353013Syokota#endif
53453013Syokota
53553013Syokota  return 0;
53653013Syokota}
53753013Syokota
53853013Syokotaint
53953013SyokotaVGLPanScreen(VGLBitmap *object, int x, int y)
54053013Syokota{
54153013Syokota  video_display_start_t origin;
54253013Syokota
54353013Syokota  if (x < 0 || x + object->Xsize > object->VXsize
54453013Syokota      || y < 0 || y + object->Ysize > object->VYsize)
54553013Syokota    return -1;
54653013Syokota  if (object->Type == MEMBUF)
54753013Syokota    return 0;
54853013Syokota  origin.x = x;
54953013Syokota  origin.y = y;
55053013Syokota  if (ioctl(0, FBIO_SETDISPSTART, &origin))
55153013Syokota    return -1;
55253013Syokota  object->Xorigin = x;
55353013Syokota  object->Yorigin = y;
55453013Syokota
55553013Syokota#ifdef LIBVGL_DEBUG
55653013Syokota  fprintf(stderr, "new origin: (%d, %d)\n", x, y);
55753013Syokota#endif
55853013Syokota
55953013Syokota  return 0;
56053013Syokota}
561