first go at jareth-with-goblin
This commit is contained in:
@@ -71,13 +71,16 @@ 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 *);
|
||||
|
||||
static void jareth_copyrows(void *, int, int, int);
|
||||
|
||||
dev_type_open(goblinopen);
|
||||
dev_type_close(goblinclose);
|
||||
dev_type_ioctl(goblinioctl);
|
||||
dev_type_mmap(goblinmmap);
|
||||
|
||||
const struct cdevsw goblin_cdevsw = {
|
||||
.d_open = goblinopen,
|
||||
.d_close = nullclose,
|
||||
.d_close = goblinclose,
|
||||
.d_read = noread,
|
||||
.d_write = nowrite,
|
||||
.d_ioctl = goblinioctl,
|
||||
@@ -107,12 +110,39 @@ struct wsscreen_descr goblin_defaultscreen = {
|
||||
NULL /* modecookie */
|
||||
};
|
||||
|
||||
struct scrolltest {
|
||||
int y0;
|
||||
int y1;
|
||||
int x0;
|
||||
int w;
|
||||
int n;
|
||||
};
|
||||
#define GOBLIN_SCROLL _IOW('X', 0, struct scrolltest)
|
||||
#define GOBLIN_FILL _IOW('X', 1, struct scrolltest)
|
||||
|
||||
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 *);
|
||||
static int goblin_putcmap(struct goblin_softc *, struct wsdisplay_cmap *);
|
||||
static int goblin_getcmap(struct goblin_softc *, struct wsdisplay_cmap *);
|
||||
static void goblin_init(struct goblin_softc *);
|
||||
static void goblin_reset(struct goblin_softc *);
|
||||
|
||||
/* Jareth stuff */
|
||||
static int init_programs(struct goblin_softc *sc);
|
||||
static int power_on(struct goblin_softc *sc);
|
||||
static int power_off(struct goblin_softc *sc);
|
||||
static int scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n);
|
||||
static int fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n);
|
||||
static const uint32_t program_scroll128[12] = { 0x407c0012,0x00140080,0x201c0013,0x60fc7013,0x00170146,0xfe000148,0x000e10c6,0x010000c9,0x00004005,0xfb000809,0x0000000a,0x0000000a };
|
||||
static const uint32_t program_fill128[12] = { 0x407c0012,0x00140080,0x607c1013,0x00170146,0xfe800148,0x000e10c6,0x010000c9,0x00004005,0xfb800809,0x0000000a,0x0000000a,0x0000000a };
|
||||
|
||||
static const uint32_t* programs[3] = { program_scroll128, program_fill128, NULL };
|
||||
static const uint32_t program_len[3] = { 12, 12, 0 };
|
||||
static uint32_t program_offset[3];
|
||||
|
||||
static void goblin_set_depth(struct goblin_softc *, int);
|
||||
|
||||
struct wsdisplay_accessops goblin_accessops = {
|
||||
goblin_ioctl,
|
||||
@@ -148,9 +178,23 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
unsigned long defattr;
|
||||
volatile struct goblin_fbcontrol *fbc = sc->sc_fbc;
|
||||
|
||||
/* boot Jareth if present */
|
||||
if (sc->sc_has_jareth) {
|
||||
/* first we need to turn the engine power on ... */
|
||||
power_on(sc);
|
||||
if (init_programs(sc)) {
|
||||
if (init_programs(sc)) {
|
||||
aprint_normal_dev(sc->sc_dev, "INIT - FAILED\n");
|
||||
sc->sc_has_jareth = 0;
|
||||
}
|
||||
}
|
||||
power_off(sc);
|
||||
}
|
||||
|
||||
fb->fb_driver = &goblinfbdriver;
|
||||
fb->fb_pfour = NULL;
|
||||
fb->fb_type.fb_cmsize = 256;
|
||||
fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes;
|
||||
fb->fb_type.fb_size = sc->sc_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);
|
||||
|
||||
@@ -158,7 +202,6 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
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;
|
||||
|
||||
@@ -173,25 +216,31 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
sc->sc_stride = fb->fb_type.fb_width;
|
||||
sc->sc_height = fb->fb_type.fb_height;
|
||||
|
||||
wsfont_init();
|
||||
|
||||
/* setup rasops and so on for wsdisplay */
|
||||
sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
|
||||
sc->sc_opens = 0;
|
||||
|
||||
vcons_init(&sc->vd, sc, &goblin_defaultscreen, &goblin_accessops);
|
||||
sc->vd.init_screen = goblin_init_screen;
|
||||
|
||||
vcons_init(&sc->sc_vd, sc, &goblin_defaultscreen, &goblin_accessops);
|
||||
sc->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);
|
||||
goblin_set_depth(sc, 8);
|
||||
vcons_init_screen(&sc->sc_vd, &gobo_console_screen, 1,
|
||||
&defattr);
|
||||
/* clear the screen */
|
||||
memset(sc->sc_fb.fb_pixels, (defattr >> 16) & 0xff,
|
||||
sc->sc_stride * sc->sc_height);
|
||||
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;
|
||||
sc->sc_vd.active = &gobo_console_screen;
|
||||
|
||||
wsdisplay_cnattach(&goblin_defaultscreen, ri, 0, 0, defattr);
|
||||
vcons_replay_msgbuf(&gobo_console_screen);
|
||||
} else {
|
||||
@@ -199,15 +248,17 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
* we're not the console so we just clear the screen and don't
|
||||
* set up any sort of text display
|
||||
*/
|
||||
memset(sc->sc_fb.fb_pixels, (defattr >> 16) & 0xff,
|
||||
sc->sc_stride * sc->sc_height);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the default color map. */
|
||||
gobo_setup_palette(sc);
|
||||
|
||||
aa.scrdata = &goblin_screenlist;
|
||||
aa.console = isconsole;
|
||||
aa.accessops = &goblin_accessops;
|
||||
aa.accesscookie = &sc->vd;
|
||||
aa.accesscookie = &sc->sc_vd;
|
||||
config_found(sc->sc_dev, &aa, wsemuldisplaydevprint);
|
||||
}
|
||||
|
||||
@@ -215,10 +266,38 @@ goblinattach(struct goblin_softc *sc, const char *name, int isconsole)
|
||||
int
|
||||
goblinopen(dev_t dev, int flags, int mode, struct lwp *l)
|
||||
{
|
||||
int unit = minor(dev);
|
||||
|
||||
if (device_lookup(&goblin_cd, unit) == NULL)
|
||||
struct goblin_softc *sc = device_lookup_private(&goblin_cd,
|
||||
minor(dev));
|
||||
int oldopens;
|
||||
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
oldopens = sc->sc_opens++;
|
||||
|
||||
if (oldopens == 0) /* first open only */
|
||||
goblin_init(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
goblinclose(dev_t dev, int flags, int mode, struct lwp *l)
|
||||
{
|
||||
struct goblin_softc *sc = device_lookup_private(&goblin_cd,
|
||||
minor(dev));
|
||||
int opens;
|
||||
|
||||
opens = --sc->sc_opens;
|
||||
if (sc->sc_opens < 0) /* should not happen... */
|
||||
opens = sc->sc_opens = 0;
|
||||
|
||||
/*
|
||||
* Restore video state to make the PROM happy, on last close.
|
||||
*/
|
||||
if (opens == 0) {
|
||||
goblin_reset(sc);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -270,6 +349,28 @@ goblinioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
|
||||
goblin_set_video(sc, *(int *)data);
|
||||
break;
|
||||
|
||||
case GOBLIN_SET_PIXELMODE: {
|
||||
int depth = *(int *)data;
|
||||
|
||||
if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)
|
||||
return EINVAL;
|
||||
|
||||
goblin_set_depth(sc, depth);
|
||||
}
|
||||
break;
|
||||
|
||||
case GOBLIN_SCROLL: {
|
||||
struct scrolltest *st = (struct scrolltest *)data;
|
||||
scroll(sc, st->y0, st->y1, st->x0, st->w, st->n);
|
||||
}
|
||||
break;
|
||||
|
||||
case GOBLIN_FILL: {
|
||||
struct scrolltest *st = (struct scrolltest *)data;
|
||||
fill(sc, st->y0, st->y1, st->x0, st->w, st->n);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (ENOTTY);
|
||||
}
|
||||
@@ -284,6 +385,13 @@ goblinunblank(device_t self)
|
||||
{
|
||||
struct goblin_softc *sc = device_private(self);
|
||||
|
||||
#if NWSDISPLAY > 0
|
||||
if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) {
|
||||
goblin_set_depth(sc, 8);
|
||||
vcons_redraw_screen(sc->sc_vd.active);
|
||||
sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
|
||||
}
|
||||
#endif
|
||||
goblin_set_video(sc, 1);
|
||||
}
|
||||
|
||||
@@ -425,7 +533,7 @@ goblin_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
|
||||
struct vcons_data *vd = v;
|
||||
struct goblin_softc *sc = vd->cookie;
|
||||
struct wsdisplay_fbinfo *wdf;
|
||||
struct vcons_screen *ms = sc->vd.active;
|
||||
struct vcons_screen *ms = sc->sc_vd.active;
|
||||
struct rasops_info *ri = &ms->scr_ri;
|
||||
switch (cmd) {
|
||||
case WSDISPLAYIO_GTYPE:
|
||||
@@ -486,7 +594,7 @@ goblin_mmap(void *v, void *vs, off_t offset, int prot)
|
||||
prot, BUS_SPACE_MAP_LINEAR);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
goblin_putcmap(struct goblin_softc *sc, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_int index = cm->index;
|
||||
@@ -516,7 +624,7 @@ goblin_putcmap(struct goblin_softc *sc, struct wsdisplay_cmap *cm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
goblin_getcmap(struct goblin_softc *sc, struct wsdisplay_cmap *cm)
|
||||
{
|
||||
u_int index = cm->index;
|
||||
@@ -552,7 +660,7 @@ goblin_init_screen(void *cookie, struct vcons_screen *scr,
|
||||
struct goblin_softc *sc = cookie;
|
||||
struct rasops_info *ri = &scr->scr_ri;
|
||||
|
||||
scr->scr_flags |= VCONS_DONT_READ;
|
||||
scr->scr_flags |= VCONS_NO_COPYCOLS;
|
||||
|
||||
ri->ri_depth = 8;
|
||||
ri->ri_width = sc->sc_width;
|
||||
@@ -568,4 +676,310 @@ goblin_init_screen(void *cookie, struct vcons_screen *scr,
|
||||
sc->sc_width / ri->ri_font->fontwidth);
|
||||
|
||||
ri->ri_hw = scr;
|
||||
if (sc->sc_has_jareth) {
|
||||
ri->ri_ops.copyrows = jareth_copyrows;
|
||||
device_printf(sc->sc_dev, "Jareth enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
goblin_set_depth(struct goblin_softc *sc, int depth)
|
||||
{
|
||||
if (sc->sc_depth == depth)
|
||||
return;
|
||||
|
||||
switch (depth) {
|
||||
case 8:
|
||||
sc->sc_fbc->mode = GOBOFB_MODE_8BIT;
|
||||
sc->sc_depth = 8;
|
||||
break;
|
||||
case 32:
|
||||
sc->sc_fbc->mode = GOBOFB_MODE_24BIT;
|
||||
sc->sc_depth = 32;
|
||||
break;
|
||||
default:
|
||||
printf("%s: can't change to depth %d\n",
|
||||
device_xname(sc->sc_dev), depth);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the framebuffer, storing away useful state for later reset */
|
||||
static void
|
||||
goblin_init(struct goblin_softc *sc)
|
||||
{
|
||||
//goblin_set_depth(sc, 32);
|
||||
}
|
||||
|
||||
static void
|
||||
/* Restore the state saved on goblin_init */
|
||||
goblin_reset(struct goblin_softc *sc)
|
||||
{
|
||||
//goblin_set_depth(sc, 8);
|
||||
}
|
||||
|
||||
|
||||
#define CONFIG_CSR_DATA_WIDTH 32
|
||||
#define sbusfpga_jareth_softc goblin_softc
|
||||
#include "dev/sbus/sbusfpga_csr_jareth.h"
|
||||
#undef sbusfpga_jareth_softc
|
||||
|
||||
#define REG_BASE(reg) (base + (reg * 32))
|
||||
#define SUBREG_ADDR(reg, off) (REG_BASE(reg) + (off)*4)
|
||||
|
||||
static int start_job(struct goblin_softc *sc);
|
||||
static int wait_job(struct goblin_softc *sc, uint32_t param);
|
||||
|
||||
static int scroll(struct goblin_softc *sc, int y0, int y1, int x0, int w, int n) {
|
||||
const uint32_t base = 0;
|
||||
const int pidx = 0;
|
||||
int i;
|
||||
|
||||
power_on(sc);
|
||||
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (0x8f800000 + y0 * sc->sc_stride + x0));
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (0x8f800000 + y1 * sc->sc_stride + x0));
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,0), (w));
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,0), (n));
|
||||
for (i = 1 ; i < 8 ; i++) {
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,i), 0);
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,i), 0);
|
||||
}
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,0), (sc->sc_stride));
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,1), (sc->sc_stride));
|
||||
jareth_mpstart_write(sc, program_offset[pidx]);
|
||||
jareth_mplen_write(sc, program_len[pidx]);
|
||||
|
||||
(void)start_job(sc);
|
||||
delay(1);
|
||||
(void)wait_job(sc, 2);
|
||||
|
||||
power_off(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fill(struct goblin_softc *sc, int y0, int pat, int x0, int w, int n) {
|
||||
const uint32_t base = 0;
|
||||
const int pidx = 1;
|
||||
int i;
|
||||
|
||||
power_on(sc);
|
||||
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (0x8f800000 + y0 * sc->sc_stride + x0));
|
||||
for (i = 0 ; i < 8 ; i++) {
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,i), pat);
|
||||
}
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,0), (w));
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,0), (n));
|
||||
for (i = 1 ; i < 8 ; i++) {
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(2,i), 0);
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(3,i), 0);
|
||||
}
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(4,0), (sc->sc_stride));
|
||||
jareth_mpstart_write(sc, program_offset[pidx]);
|
||||
jareth_mplen_write(sc, program_len[pidx]);
|
||||
|
||||
(void)start_job(sc);
|
||||
delay(1);
|
||||
(void)wait_job(sc, 1);
|
||||
|
||||
power_off(sc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
jareth_copyrows(void *cookie, int src, int dst, int n)
|
||||
{
|
||||
struct rasops_info *ri = cookie;
|
||||
struct vcons_screen *scr = ri->ri_hw;
|
||||
struct goblin_softc *sc = scr->scr_cookie;
|
||||
|
||||
if (dst == src)
|
||||
return;
|
||||
if (src < 0) {
|
||||
n += src;
|
||||
src = 0;
|
||||
}
|
||||
if (src+n > ri->ri_rows)
|
||||
n = ri->ri_rows - src;
|
||||
if (dst < 0) {
|
||||
n += dst;
|
||||
dst = 0;
|
||||
}
|
||||
if (dst+n > ri->ri_rows)
|
||||
n = ri->ri_rows - dst;
|
||||
if (n <= 0)
|
||||
return;
|
||||
|
||||
n *= ri->ri_font->fontheight;
|
||||
src *= ri->ri_font->fontheight;
|
||||
dst *= ri->ri_font->fontheight;
|
||||
|
||||
|
||||
int x0 = ri->ri_xorigin;
|
||||
int y0 = ri->ri_yorigin + src;
|
||||
//int x1 = ri->ri_xorigin + ri->ri_emuwidth - 1;
|
||||
/* int y1 = ri->ri_yorigin + src + n - 1; */
|
||||
/* int x2 = ri->ri_xorigin; */
|
||||
int y2 = ri->ri_yorigin + dst;
|
||||
/* int x3 = ri->ri_xorigin + ri->ri_emuwidth - 1; */
|
||||
/* int y3 = ri->ri_yorigin + dst + n - 1; */
|
||||
|
||||
scroll(sc, y0, y2, x0, ri->ri_emuwidth, n);
|
||||
|
||||
#if 0
|
||||
if (y0 > y2) {
|
||||
int x, y;
|
||||
for (y = 0 ; y < n ; y++) {
|
||||
for (x = x0 & ~3 ; x < x1 ; x+= 4) {
|
||||
uint32_t* srcadr = (uint32_t*)(((uint8_t*)sc->sc_fb.fb_pixels) + (y0 + y) * sc->sc_stride + x);
|
||||
uint32_t* dstadr = (uint32_t*)(((uint8_t*)sc->sc_fb.fb_pixels) + (y2 + y) * sc->sc_stride + x);
|
||||
*dstadr = *srcadr;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int x, y;
|
||||
for (y = n-1 ; y >= 0 ; y--) {
|
||||
for (x = x0 & ~3; x < x1 ; x+= 4) {
|
||||
uint32_t* srcadr = (uint32_t*)(((uint8_t*)sc->sc_fb.fb_pixels) + (y0 + y) * sc->sc_stride + x);
|
||||
uint32_t* dstadr = (uint32_t*)(((uint8_t*)sc->sc_fb.fb_pixels) + (y2 + y) * sc->sc_stride + x);
|
||||
*dstadr = *srcadr;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int start_job(struct goblin_softc *sc) {
|
||||
uint32_t status = jareth_status_read(sc);
|
||||
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
|
||||
aprint_error_dev(sc->sc_dev, "START - Jareth status: 0x%08x, still running?\n", status);
|
||||
return ENXIO;
|
||||
}
|
||||
jareth_control_write(sc, 1);
|
||||
//aprint_normal_dev(sc->sc_dev, "START - Jareth status: 0x%08x\n", jareth_status_read(sc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_job(struct goblin_softc *sc, uint32_t param) {
|
||||
uint32_t status = jareth_status_read(sc);
|
||||
int count = 0;
|
||||
int max_count = 2000;
|
||||
int del = 1;
|
||||
const int max_del = 64;
|
||||
static int max_del_seen = 1;
|
||||
static int max_cnt_seen = 0;
|
||||
|
||||
while ((status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) && (count < max_count)) {
|
||||
//uint32_t ls_status = jareth_ls_status_read(sc);
|
||||
//aprint_normal_dev(sc->sc_dev, "WAIT - ongoing, Jareth status: 0x%08x [%d] ls_status: 0x%08x\n", status, count, ls_status);
|
||||
count ++;
|
||||
delay(del * param);
|
||||
del = del < max_del ? 2*del : del;
|
||||
status = jareth_status_read(sc);
|
||||
}
|
||||
if (del > max_del_seen) {
|
||||
max_del_seen = del;
|
||||
aprint_normal_dev(sc->sc_dev, "WAIT - new max delay %d after %d count (param was %u)\n", max_del_seen, count, param);
|
||||
}
|
||||
if (count > max_cnt_seen) {
|
||||
max_cnt_seen = count;
|
||||
aprint_normal_dev(sc->sc_dev, "WAIT - new max count %d with %d delay (param was %u)\n", max_cnt_seen, del, param);
|
||||
|
||||
}
|
||||
|
||||
//jareth_control_write(sc, 0);
|
||||
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
|
||||
aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x (pc 0x%08x), did not finish in time? [inst: 0x%08x ls_status: 0x%08x]\n", status, (status>>1)&0x03ff, jareth_instruction_read(sc), jareth_ls_status_read(sc));
|
||||
return ENXIO;
|
||||
} else if (status & (1<<CSR_JARETH_STATUS_SIGILL_OFFSET)) {
|
||||
aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x, sigill [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc));
|
||||
return ENXIO;
|
||||
} else if (status & (1<<CSR_JARETH_STATUS_ABORT_OFFSET)) {
|
||||
aprint_error_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x, aborted [inst: 0x%08x ls_status: 0x%08x]\n", status, jareth_instruction_read(sc), jareth_ls_status_read(sc));
|
||||
return ENXIO;
|
||||
} else {
|
||||
//aprint_normal_dev(sc->sc_dev, "WAIT - Jareth status: 0x%08x [%d] ls_status: 0x%08x\n", status, count, jareth_ls_status_read(sc));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_programs(struct goblin_softc *sc) {
|
||||
/* the microcode is a the beginning */
|
||||
int err = 0;
|
||||
uint32_t i, j;
|
||||
uint32_t offset = 0;
|
||||
|
||||
for (j = 0 ; programs[j] != NULL; j ++) {
|
||||
program_offset[j] = offset;
|
||||
for (i = 0 ; i < program_len[j] ; i++) {
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_microcode, ((offset+i)*4), programs[j][i]);
|
||||
if ((i%16)==15)
|
||||
delay(1);
|
||||
}
|
||||
offset += program_len[j];
|
||||
}
|
||||
|
||||
jareth_window_write(sc, 0); /* could use window_window to access fields, but it creates a RMW cycle for nothing */
|
||||
jareth_mpstart_write(sc, 0); /* EC25519 */
|
||||
jareth_mplen_write(sc, program_len[0]); /* EC25519 */
|
||||
|
||||
aprint_normal_dev(sc->sc_dev, "INIT - Jareth status: 0x%08x\n", jareth_status_read(sc));
|
||||
|
||||
#if 1
|
||||
/* double check */
|
||||
u_int32_t x;
|
||||
int count = 0;
|
||||
for (i = 0 ; i < program_len[0] && count < 10; i++) {
|
||||
x = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_microcode, (i*4));
|
||||
if (x != programs[0][i]) {
|
||||
aprint_error_dev(sc->sc_dev, "INIT - Jareth program failure: [%d] 0x%08x <> 0x%08x\n", i, x, programs[0][i]);
|
||||
err = 1;
|
||||
count ++;
|
||||
}
|
||||
if ((i%8)==7)
|
||||
delay(1);
|
||||
}
|
||||
if ((x = jareth_window_read(sc)) != 0) {
|
||||
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: window = 0x%08x\n", x);
|
||||
err = 1;
|
||||
}
|
||||
if ((x = jareth_mpstart_read(sc)) != 0) {
|
||||
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: mpstart = 0x%08x\n", x);
|
||||
err = 1;
|
||||
}
|
||||
if ((x = jareth_mplen_read(sc)) != program_len[0]) {
|
||||
aprint_error_dev(sc->sc_dev, "INIT - Jareth register failure: mplen = 0x%08x\n", x);
|
||||
err = 1;
|
||||
}
|
||||
const int test_reg_num = 73;
|
||||
const uint32_t test_reg_value = 0x0C0FFEE0;
|
||||
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile, 4*test_reg_num, test_reg_value);
|
||||
delay(1);
|
||||
if ((x = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile, 4*test_reg_num)) != test_reg_value) {
|
||||
aprint_error_dev(sc->sc_dev, "INIT - Jareth register file failure: 0x%08x != 0x%08x\n", x, test_reg_value);
|
||||
err = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int power_on(struct goblin_softc *sc) {
|
||||
int err = 0;
|
||||
if ((jareth_power_read(sc) & 1) == 0) {
|
||||
jareth_power_write(sc, 1);
|
||||
delay(1);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int power_off(struct goblin_softc *sc) {
|
||||
int err = 0;
|
||||
jareth_power_write(sc, 0);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -155,5 +155,53 @@ goblinattach_sbus(device_t parent, device_t self, void *args)
|
||||
fb->fb_pixels = (char *)bus_space_vaddr(sa->sa_bustag, bh);
|
||||
}
|
||||
|
||||
sc->sc_has_jareth = prom_getpropint(node, "goblin_has_jareth", 0);
|
||||
|
||||
if (sc->sc_has_jareth) {
|
||||
if (sa->sa_nreg < 5) {
|
||||
aprint_error(": Not enough registers spaces for Jareth\n");
|
||||
sc->sc_has_jareth = 0;
|
||||
} else {
|
||||
/* map registers */
|
||||
if (sbus_bus_map(sc->sc_bustag,
|
||||
sa->sa_reg[2].oa_space /* sa_slot */,
|
||||
sa->sa_reg[2].oa_base /* sa_offset */,
|
||||
sa->sa_reg[2].oa_size /* sa_size */,
|
||||
BUS_SPACE_MAP_LINEAR,
|
||||
&sc->sc_bhregs_jareth) != 0) {
|
||||
aprint_error(": cannot map Jareth registers\n");
|
||||
sc->sc_has_jareth = 0;
|
||||
} else {
|
||||
aprint_normal_dev(self, "Jareth registers @ %p\n", (void*)sc->sc_bhregs_jareth);
|
||||
/* map microcode */
|
||||
if (sbus_bus_map(sc->sc_bustag,
|
||||
sa->sa_reg[3].oa_space /* sa_slot */,
|
||||
sa->sa_reg[3].oa_base /* sa_offset */,
|
||||
sa->sa_reg[3].oa_size /* sa_size */,
|
||||
BUS_SPACE_MAP_LINEAR,
|
||||
&sc->sc_bhregs_microcode) != 0) {
|
||||
aprint_error(": cannot map Jareth microcode\n");
|
||||
sc->sc_has_jareth = 0;
|
||||
} else {
|
||||
aprint_normal_dev(self, "Jareth microcode @ %p\n", (void*)sc->sc_bhregs_microcode);
|
||||
/* map register file */
|
||||
if (sbus_bus_map(sc->sc_bustag,
|
||||
sa->sa_reg[4].oa_space /* sa_slot */,
|
||||
sa->sa_reg[4].oa_base /* sa_offset */,
|
||||
sa->sa_reg[4].oa_size /* sa_size */,
|
||||
BUS_SPACE_MAP_LINEAR,
|
||||
&sc->sc_bhregs_regfile) != 0) {
|
||||
aprint_error(": cannot map Jareth regfile\n");
|
||||
sc->sc_has_jareth = 0;
|
||||
} else {
|
||||
aprint_normal_dev(self, "Jareth regfile @ %p\n", (void*)sc->sc_bhregs_regfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
aprint_normal_dev(self, "Jareth not available\n");
|
||||
}
|
||||
|
||||
goblinattach(sc, name, isconsole);
|
||||
}
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
#define GOBOFB_MODE_24BIT 0x10
|
||||
|
||||
#define GOBOFB_VBL_MASK_OFF 0x0
|
||||
#define GOBOFB_VBL_MASK_ON 0x1
|
||||
#define GOBOFB_VBL_MASK_ON 0x1
|
||||
|
||||
#define GOBOFB_VIDEOCTRL_OFF 0x0
|
||||
#define GOBOFB_VIDEOCTRL_ON 0x3
|
||||
#define GOBOFB_VIDEOCTRL_ON 0x1
|
||||
|
||||
#define GOBOFB_INTR_CLEAR_CLEAR 0x0
|
||||
|
||||
@@ -51,6 +51,12 @@ struct goblin_softc {
|
||||
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 */
|
||||
int sc_opens; /* number of open() to track 8/24 bits */
|
||||
int sc_has_jareth; /* whether we have a Jareth vector engine available */
|
||||
|
||||
bus_space_handle_t sc_bhregs_jareth; /* bus handle */
|
||||
bus_space_handle_t sc_bhregs_microcode; /* bus handle */
|
||||
bus_space_handle_t sc_bhregs_regfile; /* bus handle */
|
||||
|
||||
volatile struct goblin_fbcontrol *sc_fbc; /* control registers */
|
||||
#if NWSDISPLAY > 0
|
||||
@@ -58,9 +64,12 @@ struct goblin_softc {
|
||||
uint32_t sc_height; /* display width / height */
|
||||
uint32_t sc_stride;
|
||||
int sc_mode;
|
||||
struct vcons_data vd;
|
||||
struct vcons_data sc_vd;
|
||||
int sc_depth;
|
||||
#endif
|
||||
union bt_cmap sc_cmap; /* DAC color map */
|
||||
};
|
||||
|
||||
#define GOBLIN_SET_PIXELMODE _IOW('M', 3, int)
|
||||
|
||||
void goblinattach(struct goblin_softc *, const char *, int);
|
||||
|
||||
@@ -673,9 +673,26 @@ GOBLINValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
|
||||
static Bool
|
||||
GOBLINSaveScreen(ScreenPtr pScreen, int mode)
|
||||
{
|
||||
/* ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; */
|
||||
/* GoblinPtr pGoblin = GET_GOBLIN_FROM_SCRN(pScrn); */
|
||||
/* xf86Msg(X_INFO, "%s: %s\n", pGoblin->psdp->device, __PRETTY_FUNCTION__); */
|
||||
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
||||
GoblinPtr pGoblin = GET_GOBLIN_FROM_SCRN(pScrn);
|
||||
/* xf86Msg(X_INFO, "%s: %s\n", pGoblin->psdp->device, __PRETTY_FUNCTION__); */
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case SCREEN_SAVER_ON:
|
||||
case SCREEN_SAVER_CYCLE:
|
||||
if (pGoblin->fbc->videoctrl != GOBOFB_VIDEOCTRL_OFF)
|
||||
pGoblin->fbc->videoctrl = GOBOFB_VIDEOCTRL_OFF;
|
||||
break;
|
||||
case SCREEN_SAVER_OFF:
|
||||
case SCREEN_SAVER_FORCER:
|
||||
if (pGoblin->fbc->videoctrl != GOBOFB_VIDEOCTRL_ON)
|
||||
pGoblin->fbc->videoctrl = GOBOFB_VIDEOCTRL_ON;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,10 @@
|
||||
#define GOBOFB_VBL_MASK_ON 0x1
|
||||
|
||||
#define GOBOFB_VIDEOCTRL_OFF 0x0
|
||||
#define GOBOFB_VIDEOCTRL_ON 0x3
|
||||
#define GOBOFB_VIDEOCTRL_ON 0x1
|
||||
|
||||
#define GOBOFB_INTR_CLEAR_CLEAR 0x0
|
||||
|
||||
|
||||
typedef struct goblin_fbc {
|
||||
uint32_t mode;
|
||||
uint32_t vbl_mask;
|
||||
|
||||
@@ -23,7 +23,12 @@ h# SBUSFPGA_CG3_BUFSIZE constant /goblin-off-fb
|
||||
: goblin-reg
|
||||
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
|
||||
h# 1 goblin_has_jareth = if
|
||||
my-address sbusfpga_csraddr_jareth + my-space encode-phys encode+ h# 1000 encode-int encode+
|
||||
my-address sbusfpga_regionaddr_jareth-microcode + my-space encode-phys encode+ h# 1000 encode-int encode+
|
||||
my-address sbusfpga_regionaddr_jareth-regfile + my-space encode-phys encode+ h# 1000 encode-int encode+
|
||||
then
|
||||
" reg" property
|
||||
;
|
||||
|
||||
: do-map-in ( offset size -- virt )
|
||||
@@ -80,11 +85,11 @@ headerless
|
||||
;
|
||||
|
||||
: map-regs
|
||||
dac-map fb-map
|
||||
dac-map
|
||||
;
|
||||
|
||||
: unmap-regs
|
||||
dac-unmap fb-unmap
|
||||
dac-unmap
|
||||
;
|
||||
|
||||
\
|
||||
@@ -95,7 +100,7 @@ headerless
|
||||
" display" device-type
|
||||
" RDOL,sbusfpga" model
|
||||
|
||||
: qemu-goblin-driver-install ( -- )
|
||||
: goblin-driver-install ( -- )
|
||||
goblin-dac -1 = if
|
||||
map-regs
|
||||
|
||||
@@ -104,30 +109,31 @@ headerless
|
||||
\ Initial palette taken from Sun's "Writing FCode Programs"
|
||||
h# ff h# ff h# ff h# 0 color! \ Background white
|
||||
h# 0 h# 0 h# 0 h# ff color! \ Foreground black
|
||||
h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo
|
||||
\ h# 64 h# 41 h# b4 h# 1 color! \ SUN-blue logo
|
||||
h# b4 h# 41 h# 64 h# 1 color! \ SUN-blue logo
|
||||
|
||||
fb-addr to frame-buffer-adr
|
||||
default-font set-font
|
||||
|
||||
frame-buffer-adr encode-int " address" property \ CHECKME
|
||||
|
||||
h# 3 h# 8 dac! \ enable DMA, VTG
|
||||
h# 1 h# 8 dac! \ enable
|
||||
|
||||
openbios-video-width openbios-video-height over char-width / over char-height /
|
||||
fb8-install
|
||||
then
|
||||
;
|
||||
|
||||
: qemu-goblin-driver-remove ( -- )
|
||||
: goblin-driver-remove ( -- )
|
||||
goblin-dac -1 <> if
|
||||
unmap-regs
|
||||
fb-unmap
|
||||
-1 to frame-buffer-adr
|
||||
" address" delete-attribute
|
||||
" address" delete-property
|
||||
then
|
||||
;
|
||||
|
||||
: qemu-goblin-driver-init
|
||||
: goblin-driver-init
|
||||
|
||||
goblin-reg
|
||||
|
||||
@@ -142,13 +148,15 @@ headerless
|
||||
" ISO8859-1" encode-string " character-set" property
|
||||
h# c encode-int " cursorshift" property
|
||||
/goblin-off-fb h# 14 >> encode-int " vmsize" property
|
||||
goblin_has_jareth encode-int " goblin_has_jareth" property
|
||||
|
||||
map-regs
|
||||
0 h# 4 dac! \ disable irq
|
||||
h# 0 h# 4 dac! \ disable irq
|
||||
h# 0 h# 8 dac! \ turn off videoctrl
|
||||
unmap-regs
|
||||
|
||||
['] qemu-goblin-driver-install is-install
|
||||
['] qemu-goblin-driver-remove is-remove
|
||||
['] goblin-driver-install is-install
|
||||
['] goblin-driver-remove is-remove
|
||||
;
|
||||
|
||||
qemu-goblin-driver-init
|
||||
goblin-driver-init
|
||||
|
||||
@@ -17,10 +17,12 @@ opcodes = { # mnemonic : [bit coding, docstring] ; if bit 6 (0x20) is set, shif
|
||||
# 2 MSK
|
||||
"XOR" : [3, "Wd $\gets$ Ra ^ Rb // bitwise XOR"],
|
||||
"NOT" : [4, "Wd $\gets$ ~Ra // binary invert"],
|
||||
"ADD" : [5, "Wd $\gets$ Ra + Rb // 256-bit binary add"],
|
||||
"SUB" : [6, "Wd $\gets$ Ra - Rb // 256-bit binary subtraction"],
|
||||
"ADD32" : [5, "Wd[x..x+32] $\gets$ Ra[x..x+32] + Rb[x..x+32] // vector 32-bit binary add"],
|
||||
"SUB32" : [6, "Wd[x..x+32] $\gets$ Ra[x..x+32] - Rb[x..x+32] // vector 32-bit binary add"],
|
||||
#"ADD" : [5, "Wd $\gets$ Ra + Rb // 256-bit binary add"],
|
||||
#"SUB" : [6, "Wd $\gets$ Ra - Rb // 256-bit binary subtraction"],
|
||||
"AND" : [7, "Wd $\gets$ Ra & Rb // bitwise AND"], # replace MUL
|
||||
"BRNZ" : [8, "If Ra != 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if non-zero"], # relace TRD
|
||||
"BRNZ" : [8, "If Ra != 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if non-zero"], # replace TRD
|
||||
"BRZ" : [9, "If Ra == 0 then mpc[9:0] $\gets$ mpc[9:0] + immediate[9:0] + 1, else mpc $\gets$ mpc + 1 // Branch if zero"],
|
||||
"FIN" : [10, "halt execution and assert interrupt to host CPU that microcode execution is done"],
|
||||
"SHL" : [11, "Wd $\gets$ Ra << 1 // shift Ra left by one and store in Wd"],
|
||||
@@ -231,6 +233,7 @@ class JarethConst(Module, AutoDoc):
|
||||
#3: [3, "three", "The number three"],
|
||||
#4: [4, "four", "The number four"],
|
||||
#5: [5, "five", "The number five"],
|
||||
5: [32, "thirty-two", "The number thirty-two"],
|
||||
#6: [6, "six", "The number six"],
|
||||
#7: [7, "seven", "The number seven"],
|
||||
#8: [8, "eight", "The number eight"],
|
||||
@@ -328,41 +331,8 @@ passthrough.
|
||||
|
||||
class ExecAddSub(ExecUnit, AutoDoc):
|
||||
def __init__(self, width=256):
|
||||
ExecUnit.__init__(self, width, ["ADD", "SUB"])
|
||||
ExecUnit.__init__(self, width, ["ADD32", "SUB32"])
|
||||
self.notes = ModuleDoc(title="Add/Sub ExecUnit Subclass", body=f"""
|
||||
This execution module implements 256-bit binary addition and subtraction.
|
||||
|
||||
Note that to implement operations in $\mathbf{{F}}_p$, where *p* is $2^{{255}}-19$, this must be compounded
|
||||
with other operators as follows:
|
||||
|
||||
Addition of Ra + Rb into Rc in {field_latex}:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
ADD Rc, Ra, Rb // Rc <- Ra + Rb
|
||||
TRD Rd, Rc // Rd <- ReductionValue(Rc)
|
||||
SUB Rc, Rc, Rd // Rc <- Rc - Rd
|
||||
|
||||
Negation of Ra into Rc in {field_latex}:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
SUB Rc, #FIELDPRIME, Ra // Rc <- 2^255-19 - Ra
|
||||
|
||||
Note that **#FIELDPRIME** is one of the 32 available hard-coded constants
|
||||
that can be substituted for any register in any arithmetic operation, please
|
||||
see the section on "Constants" for more details.
|
||||
|
||||
Subtraction of Ra - Rb into Rc in {field_latex}:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
SUB Rb, #FIELDPRIME, Rb // Rb <- 2^255-19 - Rb
|
||||
ADD Rc, Ra, Rb // Rc <- Ra + Rb
|
||||
TRD Rd, Rc // Rd <- ReductionValue(Rc)
|
||||
SUB Rc, Rc, Rd // Rc <- Rc - Rd
|
||||
|
||||
In all the examples above, Ra and Rb must be members of {field_latex}.
|
||||
""")
|
||||
|
||||
self.sync.eng_clk += [
|
||||
@@ -370,10 +340,10 @@ In all the examples above, Ra and Rb must be members of {field_latex}.
|
||||
self.instruction_out.eq(self.instruction_in),
|
||||
]
|
||||
self.comb += [
|
||||
If(self.instruction.opcode == opcodes["ADD"][0],
|
||||
self.q.eq(self.a + self.b),
|
||||
).Elif(self.instruction.opcode == opcodes["SUB"][0],
|
||||
self.q.eq(self.a - self.b),
|
||||
If(self.instruction.opcode == opcodes["ADD32"][0],
|
||||
[ self.q[x*32:(x+1)*32].eq(self.a[x*32:(x+1)*32] + self.b[x*32:(x+1)*32]) for x in range(0, width//32) ],
|
||||
).Elif(self.instruction.opcode == opcodes["SUB32"][0],
|
||||
[ self.q[x*32:(x+1)*32].eq(self.a[x*32:(x+1)*32] - self.b[x*32:(x+1)*32]) for x in range(0, width//32) ],
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ fn main() -> std::io::Result<()> {
|
||||
// slow
|
||||
setmq %31, %1, #16
|
||||
and %5, %2, #15
|
||||
sub %6, %2, %5
|
||||
sub32 %6, %2, %5
|
||||
brz done, %6
|
||||
loop:
|
||||
psa %18, %16
|
||||
@@ -33,7 +33,7 @@ fn main() -> std::io::Result<()> {
|
||||
psa* %17, %16
|
||||
psa %20, %17
|
||||
store128inc %31, %2, %17
|
||||
sub %6, %6, #16
|
||||
sub32 %6, %6, #16
|
||||
brz last, %6
|
||||
loadh128inc %16, %0, %16
|
||||
loadh128inc %17, %1, %17
|
||||
@@ -48,50 +48,125 @@ fn main() -> std::io::Result<()> {
|
||||
fin
|
||||
fin
|
||||
);
|
||||
let _mcode3 = assemble_jareth!(
|
||||
// 0..0 / $DST / $SRC in %0
|
||||
// size in %2
|
||||
// pattern in %3
|
||||
start:
|
||||
resm %31
|
||||
psa %31, #0
|
||||
psa %30, #1
|
||||
sub %30, %31, %30
|
||||
psa %29, #2
|
||||
setmq %31, %29, %2
|
||||
setma %31, %0, %2
|
||||
psa* %30, %3
|
||||
getm %3
|
||||
resm %31
|
||||
psa %2, %30
|
||||
setadr %31 , %0
|
||||
load256 %1, %0
|
||||
load128 %0, %0
|
||||
fin
|
||||
fin
|
||||
|
||||
let mcode_scroll256 = assemble_jareth!(
|
||||
// x..x / $DST / $SRC in %0, aligned on 128 bits ; $DST < $SRC
|
||||
// x..x / X size in %2, multiple of 256 bits (32 bytes)
|
||||
// x..x / Y size in %3, arbitrary
|
||||
// x..x / dst_stride / src_stride in %4 (screen width)
|
||||
// -----
|
||||
// live X count in %5
|
||||
// // live Y count in %3
|
||||
// data in %7
|
||||
// 0/scrap in %31
|
||||
start:
|
||||
// reset masks (probably not necessary with the starred-instruction)
|
||||
// resm %31
|
||||
loop_y:
|
||||
// set source and destination addresses for current Y, X=first
|
||||
setadr %31, %0
|
||||
psa %5, %2
|
||||
loop_x:
|
||||
// load from SRC w/ post-increment
|
||||
load256inc %7, %0
|
||||
// store to DST w/ post-increment
|
||||
store256inc %31, %1, %7
|
||||
// sub 32 (#5 is 32...) from live X count
|
||||
sub32 %5, %5, #5
|
||||
// if X count is not 0, keep looping
|
||||
brnz loop_x, %5
|
||||
|
||||
// decrement Y count
|
||||
sub32 %3, %3, #1
|
||||
// if 0, finished
|
||||
brz done, %3
|
||||
// add strides to initial addresses
|
||||
add32 %0, %0, %4
|
||||
// loop to do next line
|
||||
brz loop_y, #0
|
||||
done:
|
||||
fin
|
||||
fin
|
||||
);
|
||||
let _mcode2 = assemble_jareth!(
|
||||
psa %1, %3
|
||||
setma %31, %0, %2
|
||||
psa %2, %3
|
||||
getm %3
|
||||
|
||||
let mcode_scroll128 = assemble_jareth!(
|
||||
// x..x / $DST / $SRC in %0, aligned on 128 bits ; $DST < $SRC
|
||||
// x..x / X size in %2, multiple of 128 bits (16 bytes)
|
||||
// x..x / Y size in %3, arbitrary
|
||||
// x..x / dst_stride / src_stride in %4 (screen width)
|
||||
// -----
|
||||
// live X count in %5
|
||||
// // live Y count in %3
|
||||
// data in %7
|
||||
// 0/scrap in %31
|
||||
start:
|
||||
// reset masks (probably not necessary with the starred-instruction)
|
||||
// resm %31
|
||||
loop_y:
|
||||
// set source and destination addresses for current Y, X=first
|
||||
setadr %31, %0
|
||||
psa %5, %2
|
||||
loop_x:
|
||||
// load from SRC w/ post-increment
|
||||
load128inc %7, %0
|
||||
// store to DST w/ post-increment
|
||||
store128inc %31, %1, %7
|
||||
// sub 16 (#16 is 16) from live X count
|
||||
sub32 %5, %5, #16
|
||||
// if X count is not 0, keep looping
|
||||
brnz loop_x, %5
|
||||
|
||||
// decrement Y count
|
||||
sub32 %3, %3, #1
|
||||
// if 0, finished
|
||||
brz done, %3
|
||||
// add strides to initial addresses
|
||||
add32 %0, %0, %4
|
||||
// loop to do next line
|
||||
brz loop_y, #0
|
||||
done:
|
||||
fin
|
||||
fin
|
||||
resm %31
|
||||
psa %0, %3
|
||||
setmq %31, %1, %2
|
||||
psa %1, %3
|
||||
);
|
||||
|
||||
let mcode_fill128 = assemble_jareth!(
|
||||
// x..x / $DST in %0, aligned on 128 bits
|
||||
// 128-bits pattern in %1
|
||||
// x..x / X size in %2, multiple of 128 bits (16 bytes)
|
||||
// x..x / Y size in %3, arbitrary
|
||||
// x..x / dst_stride in %4 (screen width)
|
||||
// -----
|
||||
// live X count in %5
|
||||
// // live Y count in %3
|
||||
// data in %7
|
||||
// 0/scrap in %31
|
||||
start:
|
||||
// reset masks (probably not necessary with the starred-instruction)
|
||||
// resm %31
|
||||
loop_y:
|
||||
// set source and destination addresses for current Y, X=first
|
||||
setadr %31, %0
|
||||
psa %5, %2
|
||||
loop_x:
|
||||
// store to DST w/ post-increment
|
||||
store128inc %31, %0, %1
|
||||
// sub 16 (#16 is 16) from live X count
|
||||
sub32 %5, %5, #16
|
||||
// if X count is not 0, keep looping
|
||||
brnz loop_x, %5
|
||||
|
||||
// decrement Y count
|
||||
sub32 %3, %3, #1
|
||||
// if 0, finished
|
||||
brz done, %3
|
||||
// add strides to initial addresses
|
||||
add32 %0, %0, %4
|
||||
// loop to do next line
|
||||
brz loop_y, #0
|
||||
done:
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
setma %31, %0, %2
|
||||
setma %31, %0, %2
|
||||
resm %31
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
fin
|
||||
);
|
||||
);
|
||||
|
||||
let mut pos;
|
||||
|
||||
@@ -104,5 +179,32 @@ fn main() -> std::io::Result<()> {
|
||||
println!("");
|
||||
println!("-> {}", mcode.len());
|
||||
|
||||
pos = 0;
|
||||
println!("scroll256:");
|
||||
while pos < mcode_scroll256.len() {
|
||||
print!("0x{:08x},", mcode_scroll256[pos]);
|
||||
pos = pos + 1;
|
||||
}
|
||||
println!("");
|
||||
println!("-> {}", mcode_scroll256.len());
|
||||
|
||||
pos = 0;
|
||||
println!("scroll128:");
|
||||
while pos < mcode_scroll128.len() {
|
||||
print!("0x{:08x},", mcode_scroll128[pos]);
|
||||
pos = pos + 1;
|
||||
}
|
||||
println!("");
|
||||
println!("-> {}", mcode_scroll128.len());
|
||||
|
||||
pos = 0;
|
||||
println!("fill128:");
|
||||
while pos < mcode_fill128.len() {
|
||||
print!("0x{:08x},", mcode_fill128[pos]);
|
||||
pos = pos + 1;
|
||||
}
|
||||
println!("");
|
||||
println!("-> {}", mcode_fill128.len());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -46,13 +46,16 @@ def get_header_map2_stuff(gname, name1, name2, size1, size2, type1="csr", type2=
|
||||
r += ";\n"
|
||||
return r
|
||||
|
||||
def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1="csr", type2="csr", type3="csr"):
|
||||
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
|
||||
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
|
||||
r += f"my-address sbusfpga_{type3}addr_{name3} + my-space encode-phys encode+ h# {size3:x} encode-int encode+\n"
|
||||
r += "\" reg\" property\n"
|
||||
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
|
||||
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
|
||||
def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1="csr", type2="csr", type3="csr", doreg=True):
|
||||
if (doreg):
|
||||
r = f"my-address sbusfpga_{type1}addr_{name1} + my-space encode-phys h# {size1:x} encode-int encode+\n"
|
||||
r += f"my-address sbusfpga_{type2}addr_{name2} + my-space encode-phys encode+ h# {size2:x} encode-int encode+\n"
|
||||
r += f"my-address sbusfpga_{type3}addr_{name3} + my-space encode-phys encode+ h# {size3:x} encode-int encode+\n"
|
||||
r += "\" reg\" property\n"
|
||||
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
|
||||
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
|
||||
else:
|
||||
r = ""
|
||||
r += "headers\n"
|
||||
r += f"-1 instance value {name1}-virt\n"
|
||||
r += f"-1 instance value {name2}-virt\n"
|
||||
@@ -71,13 +74,16 @@ def get_header_map3_stuff(gname, name1, name2, name3, size1, size2, size3, type1
|
||||
r += ";\n"
|
||||
return r
|
||||
|
||||
def get_header_mapx_stuff(gname, names, sizes, types):
|
||||
r = f"my-address sbusfpga_{types[0]}addr_{names[0]} + my-space encode-phys h# {sizes[0]:x} encode-int encode+\n"
|
||||
for i in range(1, len(names)):
|
||||
r += f"my-address sbusfpga_{types[i]}addr_{names[i]} + my-space encode-phys encode+ h# {sizes[i]:x} encode-int encode+\n"
|
||||
r += "\" reg\" property\n"
|
||||
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
|
||||
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
|
||||
def get_header_mapx_stuff(gname, names, sizes, types, doreg=True):
|
||||
if (doreg):
|
||||
r = f"my-address sbusfpga_{types[0]}addr_{names[0]} + my-space encode-phys h# {sizes[0]:x} encode-int encode+\n"
|
||||
for i in range(1, len(names)):
|
||||
r += f"my-address sbusfpga_{types[i]}addr_{names[i]} + my-space encode-phys encode+ h# {sizes[i]:x} encode-int encode+\n"
|
||||
r += "\" reg\" property\n"
|
||||
r += "h# 7f encode-int \" slave-burst-sizes\" property\n" # fixme: burst-sizes
|
||||
r += "h# 7f encode-int \" burst-sizes\" property\n" # fixme: burst-sizes
|
||||
else:
|
||||
r = ""
|
||||
r += "headers\n"
|
||||
for i in range(0, len(names)):
|
||||
r += f"-1 instance value {names[i]}-virt\n"
|
||||
@@ -122,7 +128,7 @@ def get_prom(soc,
|
||||
r += "\" RDOL,sbusstat\" device-name\n"
|
||||
r += get_header_map_stuff("sbus_bus_stat", "sbus_bus_stat", 256)
|
||||
|
||||
if (trng or usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or jareth):
|
||||
if (trng or usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (trng):
|
||||
@@ -134,7 +140,7 @@ def get_prom(soc,
|
||||
r += " map-out-trng\n"
|
||||
r += ";\n"
|
||||
r += "disabletrng!\n"
|
||||
if (usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or jareth):
|
||||
if (usb or (sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (usb):
|
||||
@@ -154,7 +160,7 @@ def get_prom(soc,
|
||||
r += " map-out-usb_host_ctrl\n"
|
||||
r += ";\n"
|
||||
r += "my-reset!\n"
|
||||
if ((sdram or not sdram) or engine or i2c or framebuffer or sdcard or jareth):
|
||||
if ((sdram or not sdram) or engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (sdram):
|
||||
@@ -179,7 +185,7 @@ def get_prom(soc,
|
||||
r += "\" RDOL,hidden_sdram\" device-name\n"
|
||||
r += get_header_mapx_stuff("mregs", [ "ddrphy", "sdram" ], [ 4096, 4096 ], [ "csr", "csr" ])
|
||||
r += "fload sdram_init.fth\ninit!\n"
|
||||
if (engine or i2c or framebuffer or sdcard or jareth):
|
||||
if (engine or i2c or framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (engine):
|
||||
@@ -187,7 +193,7 @@ def get_prom(soc,
|
||||
r += ": sbusfpga_regionaddr_curve25519engine-microcode sbusfpga_regionaddr_curve25519engine ;\n"
|
||||
r += ": sbusfpga_regionaddr_curve25519engine-regfile sbusfpga_regionaddr_curve25519engine h# 10000 + ;\n"
|
||||
r += get_header_mapx_stuff("curve25519engine", [ "curve25519engine", "curve25519engine-microcode", "curve25519engine-regfile" ], [ 4096, 4096, 65536 ] , ["csr", "region", "region" ] )
|
||||
if (i2c or framebuffer or sdcard or jareth):
|
||||
if (i2c or framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (i2c):
|
||||
@@ -202,7 +208,7 @@ def get_prom(soc,
|
||||
r += " \" lm75\" encode-string \" compatible\" property\n"
|
||||
r += " h# 48 encode-int \" addr\" property\n"
|
||||
r += " finish-device\n"
|
||||
if (framebuffer or sdcard or jareth):
|
||||
if (framebuffer or sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (framebuffer):
|
||||
@@ -210,6 +216,23 @@ def get_prom(soc,
|
||||
vres = int(cg3_res.split("@")[0].split("x")[1])
|
||||
hres_h=(f"{hres:x}").replace("0x", "")
|
||||
vres_h=(f"{vres:x}").replace("0x", "")
|
||||
|
||||
if (goblin):
|
||||
if (jareth):
|
||||
# first add the jareth stuff so we can use it from the goblin init
|
||||
r += ": sbusfpga_regionaddr_jareth-microcode sbusfpga_regionaddr_jareth ;\n"
|
||||
r += ": sbusfpga_regionaddr_jareth-regfile sbusfpga_regionaddr_jareth h# 10000 + ;\n"
|
||||
r += get_header_mapx_stuff("jareth", [ "jareth", "jareth-microcode", "jareth-regfile" ], [ 4096, 4096, 4096 ], ["csr", "region", "region" ], doreg=False )
|
||||
r += "h# 1 constant goblin_has_jareth\n"
|
||||
r += "fload goblin_jareth_define.fth\n"
|
||||
r += "fload goblin_jareth_init.fth\n"
|
||||
else:
|
||||
# use some placeholder so the 'reg' proeperty works
|
||||
r += "h# -1 constant sbusfpga_csraddr_jareth\n"
|
||||
r += "h# -1 constant sbusfpga_regionaddr_jareth-microcode\n"
|
||||
r += "h# -1 constant sbusfpga_regionaddr_jareth-regfile\n"
|
||||
r += "h# 0 constant goblin_has_jareth\n"
|
||||
|
||||
if (bw2):
|
||||
cg3_file = open("bw2.fth")
|
||||
elif (cg3):
|
||||
@@ -242,7 +265,7 @@ def get_prom(soc,
|
||||
r += "fload cg6_init.fth\ncg6_init!\n"
|
||||
elif (goblin):
|
||||
r += "\n"
|
||||
if (sdcard or jareth):
|
||||
if (sdcard or (jareth and not goblin)):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (sdcard):
|
||||
@@ -261,7 +284,7 @@ def get_prom(soc,
|
||||
if (jareth):
|
||||
r += "finish-device\nnew-device\n"
|
||||
|
||||
if (jareth):
|
||||
if (jareth and not goblin): # if there's a goblin, jareth is part of it
|
||||
r += "\" jareth\" device-name\n"
|
||||
r += ": sbusfpga_regionaddr_jareth-microcode sbusfpga_regionaddr_jareth ;\n"
|
||||
r += ": sbusfpga_regionaddr_jareth-regfile sbusfpga_regionaddr_jareth h# 10000 + ;\n"
|
||||
|
||||
@@ -528,6 +528,10 @@ class SBusFPGA(SoCCore):
|
||||
elif (goblin):
|
||||
self.submodules.goblin = goblin_fb.goblin(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga", irq_line=Signal()) # clock_domain for the VGA side, cg6 is running in cd_sys
|
||||
self.bus.add_slave("goblin_bt", self.goblin.bus, SoCRegion(origin=self.mem_map.get("cg6_bt", None), size=0x1000, cached=False))
|
||||
#pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
|
||||
#SBUS_DATA_OE_LED_o = Signal()
|
||||
#self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o)
|
||||
#self.comb += SBUS_DATA_OE_LED_o.eq(self.goblin.video_framebuffer_vtg.enable)
|
||||
|
||||
if (cg6):
|
||||
self.submodules.cg6_accel = cg6_accel.CG6Accel(soc = self, base_fb = base_fb, hres = hres, vres = vres)
|
||||
|
||||
Reference in New Issue
Block a user