1
0
mirror of synced 2026-04-25 03:54:40 +00:00

Replace engine-based Jareth by VexRiscv-based 'Jareth' based on NuBusFPGA's goblin accel; also shorten some Forth name to avoid namespace issues.

This commit is contained in:
Romain Dolbeau
2022-08-15 10:28:39 +02:00
parent cd03241fc6
commit 6767363415
13 changed files with 187 additions and 599 deletions

View File

@@ -111,32 +111,6 @@ struct wsscreen_descr goblin_defaultscreen = {
NULL /* modecookie */
};
struct scrolltest {
int y0;
int y1;
int x0;
int w;
int n;
int pm;
int rop;
};
/* debug only, to remove */
#define GOBLIN_SCROLL _IOW('X', 0, struct scrolltest)
#define GOBLIN_FILL _IOW('X', 1, struct scrolltest)
#define GOBLIN_FILLROP _IOW('X', 2, struct scrolltest)
#define GOBLIN_COPY _IOW('X', 3, struct scrolltest)
#define GOBLIN_COPYREV _IOW('X', 4, struct scrolltest)
#define JARETH_FN_NUM_FILL 0
#define JARETH_FN_NUM_FILLROP 1
#define JARETH_FN_NUM_COPY 2
#define JARETH_FN_NUM_COPYREV 3
struct jareth_fn {
int off;
int len;
};
#define JARETH_FN _IOWR('j', 0, struct jareth_fn)
static int goblin_ioctl(void *, void *, u_long, void *, int, struct lwp *);
static paddr_t goblin_mmap(void *, void *, off_t, int);
@@ -147,34 +121,13 @@ 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 */
enum jareth_verbosity {
jareth_silent,
jareth_silent = 0,
jareth_verbose
};
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 jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n);
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n);
static int jareth_fillrop(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n, int pm, int rop);
static int jareth_copy(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop);
static int jareth_copyrev(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop);
static const uint32_t program_fill[35] = { 0x10000089,0x0f8000c9,0x01bc0014,0x0780000d,0x013c2014,0x001400c0,0x00180000,0x403c0192,0xc03c1033,0x00184185,0x00161146,0xfd800148,0x00226007,0x00208946,0x0020220f,0x00008005,0x00088086,0x01048050,0x07000089,0x001a6087,0x013c6814,0x403c0012,0x00146086,0x01800149,0xe03c1013,0x00165146,0xfe800148,0x0080018e,0xc03c1033,0x000e10c6,0x010000c9,0x00004005,0xfa000809,0x0000000a,0x0000000a };
static const uint32_t program_fillrop[42] = { 0x13800089,0x130000c9,0x01bc0014,0x003c014c,0x0880000d,0x013c2014,0x002000c0,0x00180000,0x403c0192,0x801c0013,0x001c11e2,0xc03c7013,0x00184185,0x00221206,0xfc800208,0x00226007,0x00208946,0x0020220f,0x00008005,0x00088086,0x01048050,0x09000089,0x001a6087,0x013c6814,0x403c0012,0x00206086,0x02800209,0x801c0013,0x001c11c2,0xe03c7013,0x00225206,0xfd800208,0x0180018e,0x801c0013,0x001c11e2,0xc03c7013,0x000e10c6,0x010000c9,0x00004005,0xf8000809,0x0000000a,0x0000000a };
static const uint32_t program_copy[43] = { 0x14000089,0x138000c9,0x01bc0014,0x013c2014,0x00bf0054,0x0900000d,0x002400c0,0x00180000,0x403c0192,0x80a00013,0x403c8033,0x00184185,0x00261246,0xfd000248,0x0026f007,0x00249c06,0x0024224f,0x00240250,0x00009005,0x00089086,0x0a000089,0x013f0814,0x00049045,0x00bf0054,0x001af087,0x403c0012,0x00246086,0xa0a00013,0x02000249,0x603c8033,0x00270246,0x20a08015,0xfe000248,0x0180018d,0x013c6814,0x403c8033,0x013f0814,0x000e10c6,0x010000c9,0x00004005,0xf8000809,0x0000000a,0x0000000a };
static const uint32_t program_copyrev[61] = { 0x1d000089,0x1c8000c9,0x01bc0014,0x00280000,0x002c0040,0x00340080,0x003af007,0x03800389,0x0038ec06,0x0038238f,0x00380390,0x0028e285,0x002ce2c5,0x0034e086,0x11000349,0x013f0814,0x00bf02d4,0x001af347,0x003c6346,0x003c03d0,0x0028f285,0x002cf2c5,0x02000188,0x003c0c00,0x003c03d0,0x0028f286,0x002cf2c6,0x002f02c5,0x003c0c00,0x00bc03d0,0x0028f285,0x003000c0,0x403c0292,0x00246346,0x10a00013,0x0200018d,0x013c6814,0x10a08016,0x503c8033,0x013f0814,0x02000249,0x10a08016,0x503c8033,0x00270246,0xfd800248,0x00321306,0x01000309,0x00284285,0xf7800809,0x04800389,0x013c2014,0x00bf0054,0x002400c0,0x403c0012,0x80a00013,0x403c8033,0x00004005,0x00261246,0xfd000248,0x0000000a,0x0000000a };
static const uint32_t program_scroll128[12] = { 0x407c0012,0x00140080,0x201c0013,0x60fc7013,0x00170146,0xfe000148,0x000e10c6,0x010000c9,
0x00004005,0xfb000809,0x0000000a,0x0000000a };
static const uint32_t* programs[6] = { program_fill, program_fillrop, program_copy, program_copyrev, program_scroll128, NULL };
static const uint32_t program_len[6] = { 35, 42, 43, 61, 12, 0 };
static uint32_t program_offset[6];
static void goblin_set_depth(struct goblin_softc *, int);
@@ -212,17 +165,9 @@ 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 */
/* '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;
@@ -412,58 +357,6 @@ goblinioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
}
break;
case GOBLIN_SCROLL: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_scroll(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n);
}
break;
case GOBLIN_FILL: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_fill(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n);
}
break;
case GOBLIN_FILLROP: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_fillrop(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, st->pm, st->rop);
}
break;
case GOBLIN_COPY: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_copy(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, /* x1 */ st->pm, st->rop);
}
break;
case GOBLIN_COPYREV: {
struct scrolltest *st = (struct scrolltest *)data;
jareth_copyrev(sc, jareth_verbose, st->y0, st->y1, st->x0, st->w, st->n, /* x1 */ st->pm, st->rop);
}
break;
case JARETH_FN: {
struct jareth_fn *fn = (struct jareth_fn *)data;
int pidx = -1;
if (!sc->sc_has_jareth) {
return ENXIO;
}
switch (fn->off) {
case JARETH_FN_NUM_FILL: pidx = 0; break;
case JARETH_FN_NUM_FILLROP: pidx = 1; break;
case JARETH_FN_NUM_COPY: pidx = 2; break;
case JARETH_FN_NUM_COPYREV: pidx = 3; break;
}
if (pidx != -1) {
fn->off = program_offset[pidx];
fn->len = program_len[pidx];
} else {
fn->off = -1;
fn->len = -1;
}
}
break;
default:
return (ENOTTY);
}
@@ -537,15 +430,11 @@ goblinloadcmap(struct goblin_softc *sc, int start, int ncolors)
*/
#define GOBLIN_USER_FBC 0x70000000
#define JARETH_USER_REG 0x70001000
#define JARETH_USER_MICROCODE 0x70002000
#define JARETH_USER_REGFILE 0x70003000
#define GOBLIN_USER_RAM 0x70016000
typedef enum {
goblin_bank_fbc,
goblin_bank_fb,
jareth_bank_reg,
jareth_bank_microcode,
jareth_bank_regfile
} gobo_reg_bank;
struct mmo {
u_long mo_uaddr; /* user (virtual) address */
@@ -563,8 +452,6 @@ goblinmmap(dev_t dev, off_t off, int prot)
{ GOBLIN_USER_RAM, 0, goblin_bank_fb },
{ GOBLIN_USER_FBC, 1, goblin_bank_fbc },
{ JARETH_USER_REG, 1, jareth_bank_reg },
{ JARETH_USER_MICROCODE, 4096, jareth_bank_microcode },
{ JARETH_USER_REGFILE, 1024, jareth_bank_regfile },
};
/* device_printf(sc->sc_dev, "requiesting %llx with %d\n", off, prot); */
@@ -607,14 +494,6 @@ goblinmmap(dev_t dev, off_t off, int prot)
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_reg_paddr, u,
prot, flags));
case jareth_bank_microcode:
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_microcode_paddr, u,
prot, flags));
case jareth_bank_regfile:
return (bus_space_mmap(sc->sc_bustag,
sc->sc_jareth_regfile_paddr, u,
prot, flags));
}
}
}
@@ -791,9 +670,15 @@ goblin_init_screen(void *cookie, struct vcons_screen *scr,
ri->ri_hw = scr;
if (sc->sc_has_jareth) {
device_printf(sc->sc_dev, "Jareth present\n");
ri->ri_ops.copyrows = jareth_copyrows;
ri->ri_ops.eraserows = jareth_eraserows;
device_printf(sc->sc_dev, "Jareth enabled\n");
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_PTR, 0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_PTR, 0);
device_printf(sc->sc_dev, "Jareth console acceleration enabled\n");
/* uint32_t status = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_STATUS); */
/* uint32_t resv0 = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_RESV0); */
/* device_printf(sc->sc_dev, "Jareth sanity check: 0x%08x, 0x%08x\n", status, resv0); */
}
}
@@ -832,210 +717,6 @@ 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, enum jareth_verbosity verbose);
static int wait_job(struct goblin_softc *sc, uint32_t param, enum jareth_verbosity verbose);
static int jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n) {
const uint32_t base = 0;
const int pidx = 4;
/* int i; */
power_on(sc);
if (y0 > y1) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x0));
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));
} else {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0 + (n-1) * sc->sc_stride));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x0 + (n-1) * sc->sc_stride));
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));
}
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); */
/* } */
jareth_mpstart_write(sc, program_offset[pidx]);
jareth_mplen_write(sc, program_len[pidx]);
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 2, verbose);
power_off(sc);
return 0;
}
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n) {
const uint32_t base = 0;
const int pidx = 0; // fill
int i;
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + 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, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_fillrop(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n, int pm, int rop) {
const uint32_t base = 0;
const int pidx = 1; // fillrop
int i;
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + 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));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(5,0), (pm));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(5,1), (rop));
jareth_mpstart_write(sc, program_offset[pidx]);
jareth_mplen_write(sc, program_len[pidx]);
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_copy(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop) {
const uint32_t base = 0;
const int pidx = 2; // copy
/* int i; */
/* device_printf(sc->sc_dev, "%s : %d %d %d %d %d %d\n", __PRETTY_FUNCTION__, y0, y1, x0, w, n, x1); */
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
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]);
#if 0
{
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static int jareth_copyrev(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n, int x1, int rop) {
const uint32_t base = 0;
const int pidx = 3; // copyrev
/* int i; */
/* device_printf(sc->sc_dev, "%s : %d %d %d %d %d %d\n", __PRETTY_FUNCTION__, y0, y1, x0, w, n, x1); */
power_on(sc);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,0), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(0,1), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,0), (sc->sc_internal_adr + y0 * sc->sc_stride + x0));
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(1,1), (sc->sc_internal_adr + y1 * sc->sc_stride + x1));
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]);
#if 0
{
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
(void)start_job(sc, verbose);
delay(1);
(void)wait_job(sc, 1, verbose);
power_off(sc);
return 0;
}
static void
jareth_copyrows(void *cookie, int src, int dst, int n)
{
@@ -1105,158 +786,65 @@ jareth_eraserows(void *cookie, int row, int n, long int attr)
}
}
static int start_job(struct goblin_softc *sc, enum jareth_verbosity verbose) {
uint32_t status = jareth_status_read(sc);
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
if (verbose == jareth_verbose)
aprint_error_dev(sc->sc_dev, "START - Jareth status: 0x%08x, still running?\n", status);
return ENXIO;
static uint32_t wait_for_jareth(struct goblin_softc *sc) {
uint32_t status;
int cnt = 0;
while ((((status = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_STATUS)) & (1<<WORK_IN_PROGRESS_BIT)) != 0) && (cnt < 500)) {
cnt += 2;
delay(cnt);
}
jareth_control_write(sc, 1);
//aprint_normal_dev(sc->sc_dev, "START - Jareth status: 0x%08x\n", jareth_status_read(sc));
return status;
}
static int jareth_scroll(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int y1, int x0, int w, int n) {
uint32_t status;
status = wait_for_jareth(sc);
if ((status & (1<<WORK_IN_PROGRESS_BIT)) == 0) {
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_WIDTH, w);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_HEIGHT, n);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_Y, y0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_Y, y1);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_CMD, (1<<DO_BLIT_BIT));
status = wait_for_jareth(sc);
}
/* if ((status & (1<<WORK_IN_PROGRESS_BIT)) != 0) { */
/* device_printf(sc->sc_dev, "Jareth seems busy/locked (0x%08x)\n", status); */
/* } */
return 0;
}
static int wait_job(struct goblin_softc *sc, uint32_t param, enum jareth_verbosity verbose) {
uint32_t status = jareth_status_read(sc);
int count = 0;
int max_count = 5000;
int del = 1;
const int max_del = 64;
static int max_del_seen = 1;
static int max_cnt_seen = 0;
static int jareth_fill(struct goblin_softc *sc, enum jareth_verbosity verbose, int y0, int pat, int x0, int w, int n) {
uint32_t status;
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;
if (verbose == jareth_verbose)
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;
if (verbose == jareth_verbose)
aprint_normal_dev(sc->sc_dev, "WAIT - new max count %d with %d delay (param was %u)\n", max_cnt_seen, del, param);
}
#if 0
{
const uint32_t base = 0;
uint32_t data[8];
int i, j;
char buf[512];
for (i = 0 ; i < 16 ; i++) {
for (j = 0 ; j < 8 ; j++)
data[j] = bus_space_read_4(sc->sc_bustag, sc->sc_bhregs_regfile,SUBREG_ADDR(i,j));
snprintf(buf, 512, "0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x", data[7-0], data[7-1], data[7-2], data[7-3], data[7-4], data[7-5], data[7-6], data[7-7]);
aprint_normal("reg%d : %s\n", i, buf);
}
}
#endif
status = wait_for_jareth(sc);
//jareth_control_write(sc, 0);
if (status & (1<<CSR_JARETH_STATUS_RUNNING_OFFSET)) {
if (verbose == jareth_verbose)
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)) {
if (verbose == jareth_verbose)
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)) {
if (verbose == jareth_verbose)
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));
if ((status & (1<<WORK_IN_PROGRESS_BIT)) == 0) {
//bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_SRC_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_STRIDE, sc->sc_stride);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_WIDTH, w);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_HEIGHT, n);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_X, x0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_DST_Y, y0);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_FGCOLOR, pat);
bus_space_write_4(sc->sc_bustag, sc->sc_bhregs_jareth, GOBOFB_ACCEL_REG_CMD, (1<<DO_FILL_BIT));
status = wait_for_jareth(sc);
}
#if 1
device_printf(sc->sc_dev, "last run took %d cycle (eng_clk)\n", jareth_cyc_counter_read(sc));
#endif
/* if ((status & (1<<WORK_IN_PROGRESS_BIT)) != 0) { */
/* device_printf(sc->sc_dev, "Jareth seems busy/locked (0x%08x)\n", status); */
/* } */
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

@@ -160,7 +160,7 @@ goblinattach_sbus(device_t parent, device_t self, void *args)
aprint_normal_dev(self, "Goblin framebuffer internally @ %p\n", (void*)sc->sc_internal_adr);
if (sc->sc_has_jareth) {
if (sa->sa_nreg < 5) {
if (sa->sa_nreg < 3) {
aprint_error(": Not enough registers spaces for Jareth\n");
sc->sc_has_jareth = 0;
} else {
@@ -176,35 +176,10 @@ goblinattach_sbus(device_t parent, device_t self, void *args)
} else {
sc->sc_jareth_reg_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base);
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 {
sc->sc_jareth_microcode_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[3].oa_space, sa->sa_reg[3].oa_base);
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 {
sc->sc_jareth_regfile_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_reg[4].oa_space, sa->sa_reg[4].oa_base);
aprint_normal_dev(self, "Jareth regfile @ %p\n", (void*)sc->sc_bhregs_regfile);
}
}
}
}
} else {
}
if (!sc->sc_has_jareth) {
aprint_normal_dev(self, "Jareth not available\n");
}

View File

@@ -59,3 +59,30 @@
#define GOBOFB_VIDEOCTRL_ON 0x1
#define GOBOFB_INTR_CLEAR_CLEAR 0x0
#define GOBOFB_ACCEL_REG_STATUS 0x00
#define GOBOFB_ACCEL_REG_CMD 0x04
#define GOBOFB_ACCEL_REG_R5_CMD 0x08
#define GOBOFB_ACCEL_REG_RESV0 0x0C
#define GOBOFB_ACCEL_REG_WIDTH 0x10
#define GOBOFB_ACCEL_REG_HEIGHT 0x14
#define GOBOFB_ACCEL_REG_FGCOLOR 0x18
#define GOBOFB_ACCEL_REG_RESV2 0x1C
#define GOBOFB_ACCEL_REG_SRC_X 0x20
#define GOBOFB_ACCEL_REG_SRC_Y 0x24
#define GOBOFB_ACCEL_REG_DST_X 0x28
#define GOBOFB_ACCEL_REG_DST_Y 0x2C
#define GOBOFB_ACCEL_REG_SRC_STRIDE 0x30
#define GOBOFB_ACCEL_REG_DST_STRIDE 0x34
#define GOBOFB_ACCEL_REG_SRC_PTR 0x38
#define GOBOFB_ACCEL_REG_DST_PTR 0x3c
// status
#define WORK_IN_PROGRESS_BIT 0
// cmd
#define DO_BLIT_BIT 0 // hardwired in goblin_accel.py
#define DO_FILL_BIT 1 // hardwired in goblin_accel.py
#define DO_PATT_BIT 2 // hardwired in goblin_accel.py
#define DO_TEST_BIT 3 // hardwired in goblin_accel.py

View File

@@ -58,16 +58,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() */
bus_addr_t sc_jareth_reg_paddr; /* phys address for device mmap() */
bus_addr_t sc_jareth_microcode_paddr; /* phys address for device mmap() */
bus_addr_t sc_jareth_regfile_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 */
uint32_t sc_internal_adr;
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