19c576acfStsutsui/* $NetBSD: x68kFb.c,v 1.8 2021/03/11 12:08:57 tsutsui Exp $ */
2ba64b02eStsutsui/*-------------------------------------------------------------------------
3ba64b02eStsutsui * Copyright (c) 1996 Yasushi Yamasaki
4ba64b02eStsutsui * All rights reserved.
5ba64b02eStsutsui *
6ba64b02eStsutsui * Redistribution and use in source and binary forms, with or without
7ba64b02eStsutsui * modification, are permitted provided that the following conditions
8ba64b02eStsutsui * are met:
9ba64b02eStsutsui * 1. Redistributions of source code must retain the above copyright
10ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer.
11ba64b02eStsutsui * 2. Redistributions in binary form must reproduce the above copyright
12ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer in the
13ba64b02eStsutsui *    documentation and/or other materials provided with the distribution.
14ba64b02eStsutsui *
15ba64b02eStsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16ba64b02eStsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17ba64b02eStsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18ba64b02eStsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19ba64b02eStsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20ba64b02eStsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21ba64b02eStsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22ba64b02eStsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23ba64b02eStsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24ba64b02eStsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25ba64b02eStsutsui *-----------------------------------------------------------------------*/
26ba64b02eStsutsui
27ba64b02eStsutsui#include "x68k.h"
28ba64b02eStsutsui
29ba64b02eStsutsuistatic void x68kRegSetup(X68kScreenRec *pPriv);
30ba64b02eStsutsui
31ba64b02eStsutsuiDevPrivateKeyRec x68kScreenPrivateKeyRec;
32ba64b02eStsutsui
33d2b73a16Stsutsuistatic int cons_dwidth;
34d2b73a16Stsutsui
35ba64b02eStsutsui/*-------------------------------------------------------------------------
36ba64b02eStsutsui * function "x68kFbCommonOpen"
37ba64b02eStsutsui *
38ba64b02eStsutsui *  purpose:  open and map frame buffer, and obtain some FB-specific
39ba64b02eStsutsui *            infomation. then set controller to approppriate mode as
40ab290810Stsutsui *            configured in X68kConfig.
41ba64b02eStsutsui *  argument: (X68kScreenRec *)pPriv : X68k private screen record
42ba64b02eStsutsui *            (const char *)device   : name of frame buffer device
43ba64b02eStsutsui *  returns:  (Bool): TRUE  if succeeded
44ba64b02eStsutsui *                    FALSE otherwise
45ba64b02eStsutsui *-----------------------------------------------------------------------*/
46ba64b02eStsutsuiBool
47ba64b02eStsutsuix68kFbCommonOpen(X68kScreenRec *pPriv, const char *device)
48ba64b02eStsutsui{
49ba64b02eStsutsui    struct grfinfo gi;
50ab290810Stsutsui
51ba64b02eStsutsui    /* open frame buffer */
52ba64b02eStsutsui    if ( ( pPriv->fd = open(device, O_RDWR, 0)) < 0) {
539c576acfStsutsui        ErrorF( "Can't open frame buffer\n" );
54ba64b02eStsutsui        return FALSE;
55ba64b02eStsutsui    }
56ba64b02eStsutsui    /* get frame buffer infomation */
57ba64b02eStsutsui    if ( ioctl( pPriv->fd, GRFIOCGINFO, &gi ) == -1 ) {
589c576acfStsutsui        ErrorF( "Can't get grfinfo\n" );
59ba64b02eStsutsui        return FALSE;
60ba64b02eStsutsui    }
61ba64b02eStsutsui    pPriv->mapsize = gi.gd_regsize + gi.gd_fbsize;
62ab290810Stsutsui
63ba64b02eStsutsui    /* map control registers and frame buffer */
64ba64b02eStsutsui    pPriv->reg = (FbReg *)mmap(0, pPriv->mapsize, PROT_READ | PROT_WRITE,
65ba64b02eStsutsui                               MAP_FILE | MAP_SHARED, pPriv->fd, 0 );
66ba64b02eStsutsui    if ( pPriv->reg == (FbReg *)-1) {
679c576acfStsutsui        ErrorF( "Can't map frame buffer\n" );
68ba64b02eStsutsui        return FALSE;
69ba64b02eStsutsui    }
70ba64b02eStsutsui    pPriv->fb = (uint8_t *)((uint32_t)pPriv->reg + gi.gd_regsize);
71ba64b02eStsutsui
72ba64b02eStsutsui    x68kRegSetup( pPriv );
73d2b73a16Stsutsui    cons_dwidth = gi.gd_dwidth;
74ba64b02eStsutsui
75ba64b02eStsutsui    return TRUE;
76ba64b02eStsutsui}
77ba64b02eStsutsui
78ba64b02eStsutsui/*-------------------------------------------------------------------------
79ba64b02eStsutsui * function "x68kFbCommonClose"
80ba64b02eStsutsui *
81ba64b02eStsutsui *  purpose:  unmap and close frame buffer, and
82ba64b02eStsutsui *            change video mode to normal ITE mode
83ba64b02eStsutsui *  argument: (X68kScreenRec *)pPriv : X68k private screen record
84ba64b02eStsutsui *  returns:  nothing
85ba64b02eStsutsui *-----------------------------------------------------------------------*/
86ba64b02eStsutsuivoid
87ba64b02eStsutsuix68kFbCommonClose(X68kScreenRec *pPriv)
88ba64b02eStsutsui{
89d2b73a16Stsutsui    static const X68kFbReg graphNone_mode16 = {
90d2b73a16Stsutsui	/* CRT mode 16 (768x512 31.5kHz) */
91ba64b02eStsutsui        { 137,14, 28, 124,
92ba64b02eStsutsui          567, 5, 40, 552,
93ba64b02eStsutsui           27, 0,  0,   0,
94ba64b02eStsutsui            0, 0,  0,   0,
95ba64b02eStsutsui            0, 0,  0,   0,
96ba64b02eStsutsui       0x0416, 0,  0,   0, 0 },
97ba64b02eStsutsui        { 0x0004, 0x21e4, 0x0020 },
98ba64b02eStsutsui        0
99ba64b02eStsutsui    };
100d2b73a16Stsutsui    static const X68kFbReg graphNone_mode19 = {
101d2b73a16Stsutsui	/* CRT mode 19 (640x480 31.5kHz VGA mode) */
102d2b73a16Stsutsui        {  99,11, 13,  93,
103d2b73a16Stsutsui          524, 1, 33, 513,
104d2b73a16Stsutsui           27, 0,  0,   0,
105d2b73a16Stsutsui            0, 0,  0,   0,
106d2b73a16Stsutsui            0, 0,  0,   0,
107d2b73a16Stsutsui       0x0417, 0,  0,   0, 0 },
108d2b73a16Stsutsui        { 0x0004, 0x21e4, 0x0020 },
109d2b73a16Stsutsui        0
110d2b73a16Stsutsui    };
111ba64b02eStsutsui    /* change video mode */
112d2b73a16Stsutsui    pPriv->x68kreg = (cons_dwidth == 640) ? graphNone_mode19 : graphNone_mode16;
113ba64b02eStsutsui    x68kRegSetup(pPriv);
114ab290810Stsutsui
115ba64b02eStsutsui    /* unmap and close frame buffer */
1161fca83cbStsutsui    if ( munmap(pPriv->reg, pPriv->mapsize) == -1 )
1179c576acfStsutsui        ErrorF("Can't unmap frame buffer\n");
118ba64b02eStsutsui    close(pPriv->fd);
119ba64b02eStsutsui}
120ba64b02eStsutsui
121ba64b02eStsutsui/*-------------------------------------------------------------------------
122ba64b02eStsutsui * function "x68kRegSetup"
123ba64b02eStsutsui *
124ba64b02eStsutsui *  purpose:  set up CRT controller and Video controller
125ba64b02eStsutsui *            with register values in pPriv->x68kreg
126ba64b02eStsutsui *  argument: (X68kScreenRec *)pPriv : X68k private screen record
127ba64b02eStsutsui *  returns:  nothing
128ba64b02eStsutsui *-----------------------------------------------------------------------*/
129ba64b02eStsutsui#define CRTCSET(r) pPriv->reg->crtc.r = pPriv->x68kreg.crtc.r
130ba64b02eStsutsui#define VIDEOCSET(r) pPriv->reg->videoc.r = pPriv->x68kreg.videoc.r
131ba64b02eStsutsui
132ba64b02eStsutsuistatic void
133ba64b02eStsutsuix68kRegSetup(X68kScreenRec *pPriv)
134ba64b02eStsutsui{
1359b65525fStsutsui    uint16_t pr20 = pPriv->reg->crtc.r20;
136ba64b02eStsutsui
137ba64b02eStsutsui    /* timing registers */
138ba64b02eStsutsui    if ( (pr20 & 0x0003) < (pPriv->x68kreg.crtc.r20 & 0x0003) ||
139ba64b02eStsutsui         ( (pr20 & 0x0003) == (pPriv->x68kreg.crtc.r20 & 0x0003) &&
140ba64b02eStsutsui           (pr20 & 0x0010) < (pPriv->x68kreg.crtc.r20 & 0x0010) ) ) {
141ab290810Stsutsui
142ba64b02eStsutsui        /* to higher resolution */
143ba64b02eStsutsui        CRTCSET(r00); CRTCSET(r01); CRTCSET(r02);CRTCSET(r03);
144ba64b02eStsutsui        CRTCSET(r04); CRTCSET(r05); CRTCSET(r06);CRTCSET(r07);
145ba64b02eStsutsui        CRTCSET(r20);
146ba64b02eStsutsui    } else {
147ba64b02eStsutsui        /* to lower resolution */
148ba64b02eStsutsui        CRTCSET(r20); CRTCSET(r01); CRTCSET(r02);CRTCSET(r03);
149ba64b02eStsutsui        CRTCSET(r04); CRTCSET(r05); CRTCSET(r06);CRTCSET(r07);
150ba64b02eStsutsui        CRTCSET(r00);
151ba64b02eStsutsui    }
152ba64b02eStsutsui    CRTCSET(r08);
153ba64b02eStsutsui
154ba64b02eStsutsui    /* scroll registers */
155ba64b02eStsutsui    CRTCSET(r12); CRTCSET(r13); CRTCSET(r14);CRTCSET(r15);
156ba64b02eStsutsui    CRTCSET(r16); CRTCSET(r17); CRTCSET(r18);CRTCSET(r19);
157ba64b02eStsutsui
158ba64b02eStsutsui    /* mode controlling registers */
159ba64b02eStsutsui    VIDEOCSET(r0); VIDEOCSET(r1); VIDEOCSET(r2);
160ba64b02eStsutsui
161ba64b02eStsutsui    /* dot clock bit */
162ba64b02eStsutsui    pPriv->reg->sysport.r4 = (pPriv->x68kreg.dotClock)? 0x000e: 0x000c;
163ba64b02eStsutsui}
164ba64b02eStsutsui
165ba64b02eStsutsui/*-------------------------------------------------------------------------
166ba64b02eStsutsui * function "x68kSaveScreen"                      [ screen function ]
167ba64b02eStsutsui *
168ba64b02eStsutsui *  purpose:  activate/deactivate screen saver
169ba64b02eStsutsui *  argument: (ScreenPtr)ipScreen : target screen to save
170ba64b02eStsutsui *            (int)mode          : on/off
171ba64b02eStsutsui *  returns:  nothing
172ba64b02eStsutsui *-----------------------------------------------------------------------*/
173ba64b02eStsutsuiBool
174ba64b02eStsutsuix68kSaveScreen(ScreenPtr pScreen, Bool on)
175ba64b02eStsutsui{
176ba64b02eStsutsui    X68kScreenRec *pPriv = x68kGetScreenPrivate(pScreen);
177ba64b02eStsutsui    static int status = FALSE;
1789b65525fStsutsui    static uint16_t r2;
179ba64b02eStsutsui
180ba64b02eStsutsui    if (on == SCREEN_SAVER_ON || on == SCREEN_SAVER_CYCLE) {
181ba64b02eStsutsui        if (!status) {
182ba64b02eStsutsui            r2 = pPriv->reg->videoc.r2;
183ba64b02eStsutsui            pPriv->reg->videoc.r2 = 0x0000;
184ba64b02eStsutsui            status = TRUE;
185ba64b02eStsutsui        }
186ba64b02eStsutsui    } else {
187ba64b02eStsutsui        if (status) {
188ba64b02eStsutsui            pPriv->reg->videoc.r2 = r2;
189ba64b02eStsutsui            status = FALSE;
190ba64b02eStsutsui        }
191ba64b02eStsutsui    }
192ba64b02eStsutsui    return TRUE;
193ba64b02eStsutsui}
194ba64b02eStsutsui
195ba64b02eStsutsui/* EOF x68kFb.c */
196