preliminary goblin
This commit is contained in:
571
NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c
Normal file
571
NetBSD/9.0/usr/src/sys/dev/sbus/goblin.c
Normal file
@@ -0,0 +1,571 @@
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Romain Dolbeau <romain@dolbeau.org>
|
||||
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* color display (goblin) driver.
|
||||
*
|
||||
* Does not use VBL interrupts
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <machine/autoconf.h>
|
||||
|
||||
#include <dev/sun/fbio.h>
|
||||
#include <dev/sun/fbvar.h>
|
||||
|
||||
#include <dev/sun/btreg.h>
|
||||
#include <dev/sun/btvar.h>
|
||||
#include <dev/sbus/goblinreg.h>
|
||||
#include <dev/sbus/goblinvar.h>
|
||||
|
||||
#if NWSDISPLAY > 0
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <dev/wsfont/wsfont.h>
|
||||
#include <dev/rasops/rasops.h>
|
||||
|
||||
#include "opt_wsemul.h"
|
||||
#endif
|
||||
|
||||
#include "ioconf.h"
|
||||
|
||||
static void goblinunblank(device_t);
|
||||
static void goblinloadcmap(struct goblin_softc *, int, int);
|
||||
static void goblin_set_video(struct goblin_softc *, int);
|
||||
static int goblin_get_video(struct goblin_softc *);
|
||||
|
||||
dev_type_open(goblinopen);
|
||||
dev_type_ioctl(goblinioctl);
|
||||
dev_type_mmap(goblinmmap);
|
||||
|
||||
const struct cdevsw goblin_cdevsw = {
|
||||
.d_open = goblinopen,
|
||||
.d_close = nullclose,
|
||||
.d_read = noread,
|
||||
.d_write = nowrite,
|
||||
.d_ioctl = goblinioctl,
|
||||
.d_stop = nostop,
|
||||
.d_tty = notty,
|
||||
.d_poll = nopoll,
|
||||
.d_mmap = goblinmmap,
|
||||
.d_kqfilter = nokqfilter,
|
||||
.d_discard = nodiscard,
|
||||
.d_flag = D_OTHER
|
||||
};
|
||||
|
||||
/* frame buffer generic driver */
|
||||
static struct fbdriver goblinfbdriver = {
|
||||
goblinunblank, goblinopen, nullclose, goblinioctl, nopoll,
|
||||
goblinmmap, nokqfilter
|
||||
};
|
||||
|
||||
static void gobo_setup_palette(struct goblin_softc *);
|
||||
|
||||
struct wsscreen_descr goblin_defaultscreen = {
|
||||
"std",
|
||||
0, 0, /* will be filled in -- XXX shouldn't, it's global */
|
||||
NULL, /* textops */
|
||||
8, 16, /* font width/height */
|
||||
WSSCREEN_WSCOLORS, /* capabilities */
|
||||
NULL /* modecookie */
|
||||
};
|
||||
|
||||
static int goblin_ioctl(void *, void *, u_long, void *, int, struct lwp *);
|
||||
static paddr_t goblin_mmap(void *, void *, off_t, int);
|
||||
static void goblin_init_screen(void *, struct vcons_screen *, int, long *);
|
||||
|
||||
int goblin_putcmap(struct goblin_softc *, struct wsdisplay_cmap *);
|
||||
int goblin_getcmap(struct goblin_softc *, struct wsdisplay_cmap *);
|
||||
|
||||
struct wsdisplay_accessops goblin_accessops = {
|
||||
goblin_ioctl,
|
||||
goblin_mmap,
|
||||
NULL, /* alloc_screen */
|
||||
NULL, /* free_screen */
|
||||
NULL, /* show_screen */
|
||||
NULL, /* load_font */
|
||||
NULL, /* pollc */
|
||||
NULL /* scroll */
|
||||
};
|
||||
|
||||
const struct wsscreen_descr *_goblin_scrlist[] = {
|
||||
&goblin_defaultscreen
|
||||
};
|
||||
|
||||
struct wsscreen_list goblin_screenlist = {
|
||||
sizeof(_goblin_scrlist) / sizeof(struct wsscreen_descr *),
|
||||
_goblin_scrlist
|
||||
};
|
||||
|
||||
|
||||
extern const u_char rasops_cmap[768];
|
||||
|
||||
static struct vcons_screen gobo_console_screen;
|
||||
|
||||
void
|
||||
goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
{
|
||||
struct fbdevice *fb = &sc->sc_fb;
|
||||
struct wsemuldisplaydev_attach_args aa;
|
||||
struct rasops_info *ri = &gobo_console_screen.scr_ri;
|
||||
unsigned long defattr;
|
||||
volatile struct goblin_fbcontrol *fbc = sc->sc_fbc;
|
||||
|
||||
fb->fb_driver = &goblinfbdriver;
|
||||
fb->fb_type.fb_cmsize = 256;
|
||||
fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
|
||||
printf(": %s, %d x %d", name,
|
||||
fb->fb_type.fb_width, fb->fb_type.fb_height);
|
||||
|
||||
/* disable VBL interrupts */
|
||||
fbc->vbl_mask = GOBOFB_VBL_MASK_OFF;
|
||||
|
||||
/* Enable display in a supported mode */
|
||||
fbc->videoctrl = GOBOFB_VIDEOCTRL_OFF;
|
||||
fbc->mode = GOBOFB_MODE_8BIT;
|
||||
fbc->videoctrl = GOBOFB_VIDEOCTRL_ON;
|
||||
|
||||
if (isconsole) {
|
||||
printf(" (console)\n");
|
||||
} else
|
||||
printf("\n");
|
||||
|
||||
fb_attach(fb, isconsole);
|
||||
|
||||
sc->sc_width = fb->fb_type.fb_width;
|
||||
sc->sc_stride = fb->fb_type.fb_width;
|
||||
sc->sc_height = fb->fb_type.fb_height;
|
||||
|
||||
/* setup rasops and so on for wsdisplay */
|
||||
sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
|
||||
|
||||
vcons_init(&sc->vd, sc, &goblin_defaultscreen, &goblin_accessops);
|
||||
sc->vd.init_screen = goblin_init_screen;
|
||||
|
||||
if(isconsole) {
|
||||
/* we mess with gobo_console_screen only once */
|
||||
vcons_init_screen(&sc->vd, &gobo_console_screen, 1,
|
||||
&defattr);
|
||||
memset(sc->sc_fb.fb_pixels, (defattr >> 16) & 0xff,
|
||||
sc->sc_stride * sc->sc_height);
|
||||
gobo_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC;
|
||||
|
||||
goblin_defaultscreen.textops = &ri->ri_ops;
|
||||
goblin_defaultscreen.capabilities = ri->ri_caps;
|
||||
goblin_defaultscreen.nrows = ri->ri_rows;
|
||||
goblin_defaultscreen.ncols = ri->ri_cols;
|
||||
sc->vd.active = &gobo_console_screen;
|
||||
wsdisplay_cnattach(&goblin_defaultscreen, ri, 0, 0, defattr);
|
||||
vcons_replay_msgbuf(&gobo_console_screen);
|
||||
} else {
|
||||
/*
|
||||
* we're not the console so we just clear the screen and don't
|
||||
* set up any sort of text display
|
||||
*/
|
||||
}
|
||||
|
||||
/* Initialize the default color map. */
|
||||
gobo_setup_palette(sc);
|
||||
|
||||
aa.scrdata = &goblin_screenlist;
|
||||
aa.console = isconsole;
|
||||
aa.accessops = &goblin_accessops;
|
||||
aa.accesscookie = &sc->vd;
|
||||
config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
goblinopen(dev_t dev, int flags, int mode, struct lwp *l)
|
||||
{
|
||||
int unit = minor(dev);
|
||||
|
||||
if (device_lookup(&goblin_cd, unit) == NULL)
|
||||
return (ENXIO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
goblinioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
|
||||
{
|
||||
struct goblin_softc *sc = device_lookup_private(&goblin_cd,
|
||||
minor(dev));
|
||||
struct fbgattr *fba;
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case FBIOGTYPE:
|
||||
*(struct fbtype *)data = sc->sc_fb.fb_type;
|
||||
break;
|
||||
|
||||
case FBIOGATTR:
|
||||
fba = (struct fbgattr *)data;
|
||||
fba->real_type = sc->sc_fb.fb_type.fb_type;
|
||||
fba->owner = 0; /* XXX ??? */
|
||||
fba->fbtype = sc->sc_fb.fb_type;
|
||||
fba->sattr.flags = 0;
|
||||
fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
|
||||
fba->sattr.dev_specific[0] = -1;
|
||||
fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
|
||||
fba->emu_types[1] = -1;
|
||||
break;
|
||||
|
||||
case FBIOGETCMAP:
|
||||
#define p ((struct fbcmap *)data)
|
||||
return (bt_getcmap(p, &sc->sc_cmap, 256, 1));
|
||||
|
||||
case FBIOPUTCMAP:
|
||||
/* copy to software map */
|
||||
error = bt_putcmap(p, &sc->sc_cmap, 256, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
/* now blast them into the chip */
|
||||
goblinloadcmap(sc, p->index, p->count);
|
||||
#undef p
|
||||
break;
|
||||
|
||||
case FBIOGVIDEO:
|
||||
*(int *)data = goblin_get_video(sc);
|
||||
break;
|
||||
|
||||
case FBIOSVIDEO:
|
||||
goblin_set_video(sc, *(int *)data);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the effect of an FBIOSVIDEO that turns the video off.
|
||||
*/
|
||||
static void
|
||||
goblinunblank(device_t self)
|
||||
{
|
||||
struct goblin_softc *sc = device_private(self);
|
||||
|
||||
goblin_set_video(sc, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
goblin_set_video(struct goblin_softc *sc, int enable)
|
||||
{
|
||||
|
||||
if (enable)
|
||||
sc->sc_fbc->videoctrl = GOBOFB_VIDEOCTRL_ON;
|
||||
else
|
||||
sc->sc_fbc->videoctrl = GOBOFB_VIDEOCTRL_OFF;
|
||||
}
|
||||
|
||||
static int
|
||||
goblin_get_video(struct goblin_softc *sc)
|
||||
{
|
||||
|
||||
return (sc->sc_fbc->videoctrl == GOBOFB_VIDEOCTRL_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Load a subset of the current (new) colormap into the DAC.
|
||||
* Pretty much the same as the Brooktree DAC in the cg6
|
||||
*/
|
||||
static void
|
||||
goblinloadcmap(struct goblin_softc *sc, int start, int ncolors)
|
||||
{
|
||||
volatile struct goblin_fbcontrol *sc_fbc = sc->sc_fbc;
|
||||
u_int *ip, i;
|
||||
int count;
|
||||
|
||||
ip = &sc->sc_cmap.cm_chip[BT_D4M3(start)]; /* start/4 * 3 */
|
||||
count = BT_D4M3(start + ncolors - 1) - BT_D4M3(start) + 3;
|
||||
sc_fbc->lut_addr = BT_D4M4(start) & 0xFF;
|
||||
while (--count >= 0) {
|
||||
i = *ip++;
|
||||
/* hardware that makes one want to pound boards with hammers */
|
||||
/* ^^^ from the cg6, need to rework this on the HW and SW side ... */
|
||||
sc_fbc->lut = (i >> 24) & 0xff;
|
||||
sc_fbc->lut = (i >> 16) & 0xff;
|
||||
sc_fbc->lut = (i >> 8) & 0xff;
|
||||
sc_fbc->lut = (i ) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the address that would map the given device at the given
|
||||
* offset, allowing for the given protection, or return -1 for error.
|
||||
* 'inspired' by the cg6 code
|
||||
*/
|
||||
#define GOBLIN_USER_FBC 0x70000000
|
||||
#define GOBLIN_USER_RAM 0x70016000
|
||||
typedef enum {
|
||||
goblin_bank_fbc,
|
||||
goblin_bank_fb
|
||||
} gobo_reg_bank;
|
||||
struct mmo {
|
||||
u_long mo_uaddr; /* user (virtual) address */
|
||||
u_long mo_size; /* size, or 0 for video ram size */
|
||||
gobo_reg_bank mo_reg_bank; /* which bank to map */
|
||||
};
|
||||
paddr_t
|
||||
goblinmmap(dev_t dev, off_t off, int prot)
|
||||
{
|
||||
struct goblin_softc *sc = device_lookup_private(&goblin_cd,
|
||||
minor(dev));
|
||||
struct mmo *mo;
|
||||
u_int u, sz, flags;
|
||||
static struct mmo mmo[] = {
|
||||
{ GOBLIN_USER_RAM, 0, goblin_bank_fb },
|
||||
{ GOBLIN_USER_FBC, 1, goblin_bank_fbc },
|
||||
};
|
||||
|
||||
/* device_printf(sc->sc_dev, "requiesting %llx with %d\n", off, prot); */
|
||||
|
||||
#define NMMO (sizeof mmo / sizeof *mmo)
|
||||
if (off & PGOFSET)
|
||||
panic("goblinmmap");
|
||||
if (off < 0)
|
||||
return (-1);
|
||||
/*
|
||||
* Entries with size 0 map video RAM (i.e., the size in fb data).
|
||||
*
|
||||
* Since we work in pages, the fact that the map offset table's
|
||||
* sizes are sometimes bizarre (e.g., 1) is effectively ignored:
|
||||
* one byte is as good as one page.
|
||||
*/
|
||||
for (mo = mmo; mo < &mmo[NMMO]; mo++) {
|
||||
if ((u_long)off < mo->mo_uaddr)
|
||||
continue;
|
||||
u = off - mo->mo_uaddr;
|
||||
if (mo->mo_size == 0) {
|
||||
flags = BUS_SPACE_MAP_LINEAR |
|
||||
BUS_SPACE_MAP_PREFETCHABLE;
|
||||
sz = sc->sc_size;
|
||||
} else {
|
||||
flags = BUS_SPACE_MAP_LINEAR;
|
||||
sz = mo->mo_size;
|
||||
}
|
||||
if (u < sz) {
|
||||
switch (mo->mo_reg_bank) {
|
||||
case goblin_bank_fb:
|
||||
return (bus_space_mmap(sc->sc_bustag,
|
||||
sc->sc_fb_paddr, u,
|
||||
prot, flags));
|
||||
case goblin_bank_fbc:
|
||||
return (bus_space_mmap(sc->sc_bustag,
|
||||
sc->sc_reg_fbc_paddr, u,
|
||||
prot, flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static void
|
||||
gobo_setup_palette(struct goblin_softc *sc)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
sc->sc_cmap.cm_map[i][0] = rasops_cmap[j];
|
||||
j++;
|
||||
sc->sc_cmap.cm_map[i][1] = rasops_cmap[j];
|
||||
j++;
|
||||
sc->sc_cmap.cm_map[i][2] = rasops_cmap[j];
|
||||
j++;
|
||||
}
|
||||
goblinloadcmap(sc, 0, 256);
|
||||
}
|
||||
|
||||
int
|
||||
goblin_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
|
||||
struct lwp *l)
|
||||
{
|
||||
/* we'll probably need to add more stuff here */
|
||||
struct vcons_data *vd = v;
|
||||
struct goblin_softc *sc = vd->cookie;
|
||||
struct wsdisplay_fbinfo *wdf;
|
||||
struct vcons_screen *ms = sc->vd.active;
|
||||
struct rasops_info *ri = &ms->scr_ri;
|
||||
switch (cmd) {
|
||||
case WSDISPLAYIO_GTYPE:
|
||||
*(u_int *)data = WSDISPLAY_TYPE_SUNTCX;
|
||||
return 0;
|
||||
case WSDISPLAYIO_GINFO:
|
||||
wdf = (void *)data;
|
||||
wdf->height = ri->ri_height;
|
||||
wdf->width = ri->ri_width;
|
||||
wdf->depth = 8;
|
||||
wdf->cmsize = 256;
|
||||
return 0;
|
||||
|
||||
case WSDISPLAYIO_GETCMAP:
|
||||
return goblin_getcmap(sc,
|
||||
(struct wsdisplay_cmap *)data);
|
||||
case WSDISPLAYIO_PUTCMAP:
|
||||
return goblin_putcmap(sc,
|
||||
(struct wsdisplay_cmap *)data);
|
||||
|
||||
case WSDISPLAYIO_SMODE:
|
||||
{
|
||||
int new_mode = *(int*)data;
|
||||
if (new_mode != sc->sc_mode)
|
||||
{
|
||||
sc->sc_mode = new_mode;
|
||||
if(new_mode == WSDISPLAYIO_MODE_EMUL)
|
||||
{
|
||||
gobo_setup_palette(sc);
|
||||
vcons_redraw_screen(ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WSDISPLAYIO_GET_FBINFO:
|
||||
{
|
||||
struct wsdisplayio_fbinfo *fbi = data;
|
||||
|
||||
return wsdisplayio_get_fbinfo(&ms->scr_ri, fbi);
|
||||
}
|
||||
}
|
||||
return EPASSTHROUGH;
|
||||
}
|
||||
|
||||
/* for wsdisplay, just map usable memory */
|
||||
paddr_t
|
||||
goblin_mmap(void *v, void *vs, off_t offset, int prot)
|
||||
{
|
||||
struct vcons_data *vd = v;
|
||||
struct goblin_softc *sc = vd->cookie;
|
||||
|
||||
if (offset < 0) return -1;
|
||||
if (offset >= sc->sc_fb.fb_type.fb_size)
|
||||
return -1;
|
||||
|
||||
return bus_space_mmap(sc->sc_bustag,
|
||||
sc->sc_fb_paddr, offset,
|
||||
prot, BUS_SPACE_MAP_LINEAR);
|
||||
}
|
||||
|
||||
int
|
||||
goblin_putcmap(struct goblin_softc *sc, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_int index = cm->index;
|
||||
u_int count = cm->count;
|
||||
int error,i;
|
||||
if (index >= 256 || count > 256 || index + count > 256)
|
||||
return EINVAL;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
error = copyin(&cm->red[i],
|
||||
&sc->sc_cmap.cm_map[index + i][0], 1);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyin(&cm->green[i],
|
||||
&sc->sc_cmap.cm_map[index + i][1],
|
||||
1);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyin(&cm->blue[i],
|
||||
&sc->sc_cmap.cm_map[index + i][2], 1);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
goblinloadcmap(sc, index, count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
goblin_getcmap(struct goblin_softc *sc, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_int index = cm->index;
|
||||
u_int count = cm->count;
|
||||
int error,i;
|
||||
|
||||
if (index >= 256 || count > 256 || index + count > 256)
|
||||
return EINVAL;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
error = copyout(&sc->sc_cmap.cm_map[index + i][0],
|
||||
&cm->red[i], 1);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyout(&sc->sc_cmap.cm_map[index + i][1],
|
||||
&cm->green[i], 1);
|
||||
if (error)
|
||||
return error;
|
||||
error = copyout(&sc->sc_cmap.cm_map[index + i][2],
|
||||
&cm->blue[i], 1);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
goblin_init_screen(void *cookie, struct vcons_screen *scr,
|
||||
int existing, long *defattr)
|
||||
{
|
||||
struct goblin_softc *sc = cookie;
|
||||
struct rasops_info *ri = &scr->scr_ri;
|
||||
|
||||
scr->scr_flags |= VCONS_DONT_READ;
|
||||
|
||||
ri->ri_depth = 8;
|
||||
ri->ri_width = sc->sc_width;
|
||||
ri->ri_height = sc->sc_height;
|
||||
ri->ri_stride = sc->sc_stride;
|
||||
ri->ri_flg = RI_CENTER;
|
||||
|
||||
ri->ri_bits = sc->sc_fb.fb_pixels;
|
||||
|
||||
rasops_init(ri, 0, 0);
|
||||
ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE;
|
||||
rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight,
|
||||
sc->sc_width / ri->ri_font->fontwidth);
|
||||
|
||||
ri->ri_hw = scr;
|
||||
}
|
||||
159
NetBSD/9.0/usr/src/sys/dev/sbus/goblin_sbus.c
Normal file
159
NetBSD/9.0/usr/src/sys/dev/sbus/goblin_sbus.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Romain Dolbeau <romain@dolbeau.org>
|
||||
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* color display (goblin) driver.
|
||||
*
|
||||
* Does not use VBL interrupts
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <sys/bus.h>
|
||||
#include <machine/autoconf.h>
|
||||
|
||||
#include <dev/sun/fbio.h>
|
||||
#include <dev/sun/fbvar.h>
|
||||
|
||||
#include <dev/sun/btreg.h>
|
||||
#include <dev/sun/btvar.h>
|
||||
#include <dev/sbus/goblinreg.h>
|
||||
#include <dev/sbus/goblinvar.h>
|
||||
|
||||
#include <dev/sbus/sbusvar.h>
|
||||
|
||||
|
||||
/* autoconfiguration driver */
|
||||
static int goblinmatch_sbus(device_t, cfdata_t, void *);
|
||||
static void goblinattach_sbus(device_t, device_t, void *);
|
||||
|
||||
CFATTACH_DECL_NEW(goblin_sbus, sizeof(struct goblin_softc),
|
||||
goblinmatch_sbus, goblinattach_sbus, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Match a goblin.
|
||||
*/
|
||||
int
|
||||
goblinmatch_sbus(device_t parent, cfdata_t cf, void *aux)
|
||||
{
|
||||
struct sbus_attach_args *sa = aux;
|
||||
|
||||
if (strcmp(cf->cf_name, sa->sa_name) == 0)
|
||||
return 100; /* beat genfb(4) */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach a display. We need to notice if it is the console, too.
|
||||
*/
|
||||
void
|
||||
goblinattach_sbus(device_t parent, device_t self, void *args)
|
||||
{
|
||||
struct goblin_softc *sc = device_private(self);
|
||||
struct sbus_attach_args *sa = args;
|
||||
struct fbdevice *fb = &sc->sc_fb;
|
||||
int node = sa->sa_node;
|
||||
int isconsole;
|
||||
const char *name;
|
||||
bus_space_handle_t bh;
|
||||
|
||||
sc->sc_dev = self;
|
||||
|
||||
aprint_normal("\n");
|
||||
|
||||
if (sa->sa_nreg < 2) {
|
||||
aprint_error(": Not enough registers spaces\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remember cookies for goblin_mmap() */
|
||||
sc->sc_bustag = sa->sa_bustag;
|
||||
|
||||
fb->fb_device = self;
|
||||
fb->fb_flags = device_cfdata(self)->cf_flags & FB_USERMASK;
|
||||
fb->fb_type.fb_type = FBTYPE_GOBLIN;
|
||||
|
||||
fb->fb_type.fb_depth = 8;
|
||||
/* setsize picks from properties "height" and "width" */
|
||||
fb_setsize_obp(fb, fb->fb_type.fb_depth, 1152, 900, node);
|
||||
|
||||
/* map registers */
|
||||
if (sbus_bus_map(sa->sa_bustag,
|
||||
sa->sa_reg[0].oa_space /* sa_slot */,
|
||||
sa->sa_reg[0].oa_base /* sa_offset */,
|
||||
sa->sa_reg[0].oa_size /* sa_size */,
|
||||
BUS_SPACE_MAP_LINEAR,
|
||||
&bh) != 0) {
|
||||
aprint_error(": cannot map Goblin registers\n");
|
||||
return;
|
||||
} else {
|
||||
sc->sc_reg_fbc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base);
|
||||
aprint_normal_dev(self, "Goblin registers @ %p\n", (void*)bh);
|
||||
}
|
||||
sc->sc_fbc = (struct goblin_fbcontrol *)bus_space_vaddr(sa->sa_bustag, bh);
|
||||
|
||||
isconsole = fb_is_console(node);
|
||||
name = prom_getpropstring(node, "model");
|
||||
if (name == NULL)
|
||||
name = "goblin";
|
||||
|
||||
/* map FB */
|
||||
fb->fb_pixels = NULL;
|
||||
/* if (sa->sa_npromvaddrs != 0) */
|
||||
/* fb->fb_pixels = (void *)(u_long)sa->sa_promvaddrs[0]; */
|
||||
if (fb->fb_pixels == NULL) {
|
||||
if (sbus_bus_map(sa->sa_bustag,
|
||||
sa->sa_reg[1].oa_space /* sa_slot */,
|
||||
sa->sa_reg[1].oa_base /* sa_offset */,
|
||||
sa->sa_reg[1].oa_size /* sa_size */,
|
||||
BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE,
|
||||
&bh) != 0) {
|
||||
aprint_error(": cannot map Goblin framebuffer\n");
|
||||
return;
|
||||
} else {
|
||||
sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base);
|
||||
sc->sc_size = sa->sa_reg[1].oa_size;
|
||||
aprint_normal_dev(self, "Goblin framebuffer @ %p (%d MiB)\n", (void*)bh, sc->sc_size/1048576);
|
||||
}
|
||||
fb->fb_pixels = (char *)bus_space_vaddr(sa->sa_bustag, bh);
|
||||
}
|
||||
|
||||
goblinattach(sc, name, isconsole);
|
||||
}
|
||||
56
NetBSD/9.0/usr/src/sys/dev/sbus/goblinreg.h
Normal file
56
NetBSD/9.0/usr/src/sys/dev/sbus/goblinreg.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Romain Dolbeau <romain@dolbeau.org>
|
||||
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* goblin display registers
|
||||
*/
|
||||
|
||||
/* offsets */
|
||||
#define GOBOFB_REG_BASE 0x200000
|
||||
#define GOBOFB_MEM_BASE 0x800000
|
||||
#define GOBOFB_MODE 0x0
|
||||
#define GOBOFB_VBL_MASK 0x4
|
||||
#define GOBOFB_VIDEOCTRL 0x8
|
||||
#define GOBOFB_INTR_CLEAR 0xc
|
||||
#define GOBOFB_RESET 0x10
|
||||
#define GOBOFB_LUT_ADDR 0x14
|
||||
#define GOBOFB_LUT 0x18
|
||||
|
||||
#define GOBOFB_MODE_1BIT 0x0
|
||||
#define GOBOFB_MODE_2BIT 0x1
|
||||
#define GOBOFB_MODE_4BIT 0x2
|
||||
#define GOBOFB_MODE_8BIT 0x3
|
||||
#define GOBOFB_MODE_24BIT 0x10
|
||||
|
||||
#define GOBOFB_VBL_MASK_OFF 0x0
|
||||
#define GOBOFB_VBL_MASK_ON 0x1
|
||||
|
||||
#define GOBOFB_VIDEOCTRL_OFF 0x0
|
||||
#define GOBOFB_VIDEOCTRL_ON 0x3
|
||||
|
||||
#define GOBOFB_INTR_CLEAR_CLEAR 0x0
|
||||
66
NetBSD/9.0/usr/src/sys/dev/sbus/goblinvar.h
Normal file
66
NetBSD/9.0/usr/src/sys/dev/sbus/goblinvar.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2022 Romain Dolbeau <romain@dolbeau.org>
|
||||
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 "wsdisplay.h"
|
||||
#include <dev/wscons/wsdisplay_vconsvar.h>
|
||||
|
||||
/*
|
||||
* color display (goblin) driver.
|
||||
*/
|
||||
|
||||
struct goblin_fbcontrol {
|
||||
uint32_t mode;
|
||||
uint32_t vbl_mask;
|
||||
uint32_t videoctrl;
|
||||
uint32_t intr_clear;
|
||||
uint32_t reset;
|
||||
uint32_t lut_addr;
|
||||
uint32_t lut;
|
||||
};
|
||||
|
||||
/* per-display variables */
|
||||
struct goblin_softc {
|
||||
device_t sc_dev; /* base device */
|
||||
struct fbdevice sc_fb; /* frame buffer device */
|
||||
bus_space_tag_t sc_bustag;
|
||||
bus_addr_t sc_reg_fbc_paddr; /* phys address for device mmap() */
|
||||
bus_addr_t sc_fb_paddr; /* phys address for device mmap() */
|
||||
uint32_t sc_size; /* full memory size */
|
||||
|
||||
volatile struct goblin_fbcontrol *sc_fbc; /* control registers */
|
||||
#if NWSDISPLAY > 0
|
||||
uint32_t sc_width;
|
||||
uint32_t sc_height; /* display width / height */
|
||||
uint32_t sc_stride;
|
||||
int sc_mode;
|
||||
struct vcons_data vd;
|
||||
#endif
|
||||
union bt_cmap sc_cmap; /* DAC color map */
|
||||
};
|
||||
|
||||
void goblinattach(struct goblin_softc *, const char *, int);
|
||||
@@ -1,7 +1,7 @@
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2020 Romain Dolbeau <romain@dolbeau.org>
|
||||
* Copyright (c) 2022 Romain Dolbeau <romain@dolbeau.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -20,14 +20,10 @@ h# 20 constant /goblin-off-dac
|
||||
h# 800000 constant goblin-off-fb
|
||||
h# SBUSFPGA_CG3_BUFSIZE constant /goblin-off-fb
|
||||
|
||||
: >goblin-reg-spec ( offset size -- encoded-reg )
|
||||
>r 0 my-address d+ my-space encode-phys r> encode-int encode+
|
||||
;
|
||||
|
||||
: goblin-reg
|
||||
\ FIXME: we don't have to do this like the cg3...
|
||||
h# 0 h# 1000000 >goblin-reg-spec
|
||||
" reg" property
|
||||
my-address sbusfpga_regionaddr_goblin_bt + my-space encode-phys /goblin-off-dac encode-int encode+
|
||||
my-address goblin-off-fb + my-space encode-phys encode+ /goblin-off-fb encode-int encode+
|
||||
" reg" property
|
||||
;
|
||||
|
||||
: do-map-in ( offset size -- virt )
|
||||
@@ -52,11 +48,11 @@ h# SBUSFPGA_CG3_BUFSIZE constant /goblin-off-fb
|
||||
external
|
||||
|
||||
: color! ( r g b c# -- )
|
||||
h# 18 << h# 14 dac! ( r g b )
|
||||
h# 14 dac! ( r g b )
|
||||
swap rot ( b g r )
|
||||
h# 18 << h# 18 dac! ( b g )
|
||||
h# 18 << h# 18 dac! ( b )
|
||||
h# 18 << h# 18 dac! ( )
|
||||
h# 18 dac! ( b g )
|
||||
h# 18 dac! ( b )
|
||||
h# 18 dac! ( )
|
||||
;
|
||||
|
||||
headerless
|
||||
@@ -102,8 +98,6 @@ headerless
|
||||
: qemu-goblin-driver-install ( -- )
|
||||
goblin-dac -1 = if
|
||||
map-regs
|
||||
|
||||
0 h# 4 dac! \ disable irq
|
||||
|
||||
fb-map
|
||||
|
||||
@@ -144,13 +138,14 @@ headerless
|
||||
|
||||
h# 39 encode-int 0 encode-int encode+ " intr" property
|
||||
|
||||
\ Monitor sense. Some searching suggests that this is
|
||||
\ 5 for 1024x768 and 7 for 1152x900
|
||||
h# 7 encode-int " monitor-sense" property
|
||||
|
||||
" RDOL" encode-string " manufacturer" property
|
||||
" ISO8859-1" encode-string " character-set" property
|
||||
h# c encode-int " cursorshift" property
|
||||
/goblin-off-fb h# 14 >> encode-int " vmsize" property
|
||||
|
||||
map-regs
|
||||
0 h# 4 dac! \ disable irq
|
||||
unmap-regs
|
||||
|
||||
['] qemu-goblin-driver-install is-install
|
||||
['] qemu-goblin-driver-remove is-remove
|
||||
|
||||
Reference in New Issue
Block a user