1
0
mirror of synced 2026-03-03 17:56:30 +00:00

first go at jareth-with-goblin

This commit is contained in:
Romain Dolbeau
2022-03-11 23:02:43 +01:00
parent 9ee9bcd692
commit a87e7eaa6b
11 changed files with 741 additions and 147 deletions

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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) ],
),
]

View File

@@ -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(())
}

View File

@@ -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"

View File

@@ -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)