#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sti_machdep.c,v 1.7 2025/05/31 03:05:25 tsutsui Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <dev/wscons/wsconsio.h>
#include <hp300/dev/sti_machdep.h>
#define STI_EVRX_REGNO2OFFSET 0x00020000
#define STI_EVRX_FBOFFSET 0x00200000
#define EVRX_BT458_ADDR (STI_EVRX_REGNO2OFFSET + 0x200 + 2)
#define EVRX_BT458_CMAP (STI_EVRX_REGNO2OFFSET + 0x204 + 2)
#define EVRX_BT458_CTRL (STI_EVRX_REGNO2OFFSET + 0x208 + 2)
#define EVRX_BT458_OMAP (STI_EVRX_REGNO2OFFSET + 0x20C + 2)
#define EVRX_BT4xx_ADDR EVRX_BT458_ADDR
#define EVRX_BT4xx_CMAP EVRX_BT458_CMAP
#define EVRX_BT4xx_CTRL EVRX_BT458_CTRL
#define EVRX_MAGIC00 (STI_EVRX_REGNO2OFFSET + 0x600)
#define EVRX_MAGIC04 (STI_EVRX_REGNO2OFFSET + 0x604)
#define EVRX_MAGIC08 (STI_EVRX_REGNO2OFFSET + 0x608)
#define EVRX_MAGIC0C (STI_EVRX_REGNO2OFFSET + 0x60c)
#define EVRX_MAGIC10 (STI_EVRX_REGNO2OFFSET + 0x610)
#define EVRX_MAGIC10_BSY 0x00010000
#define EVRX_MAGIC18 (STI_EVRX_REGNO2OFFSET + 0x618)
#define EVRX_MAGIC1C (STI_EVRX_REGNO2OFFSET + 0x61c)
#define STI_CRX_FBOFFSET 0x01000000
static int sti_evrx_putcmap(struct sti_screen *, u_int, u_int);
static void sti_evrx_resetramdac(struct sti_screen *);
static void sti_evrx_resetcmap(struct sti_screen *);
static void sti_evrx_setupfb(struct sti_screen *);
static paddr_t sti_m68k_mmap(void *, void *, off_t, int);
static struct bus_space_tag sticn_tag;
static struct sti_rom sticn_rom;
static struct sti_screen sticn_scr;
static bus_addr_t sticn_bases[STI_REGION_MAX];
static const struct wsdisplay_accessops sti_m68k_accessops = {
.ioctl = sti_ioctl,
.mmap = sti_m68k_mmap,
.alloc_screen = sti_alloc_screen,
.free_screen = sti_free_screen,
.show_screen = sti_show_screen,
.load_font = sti_load_font
};
void
sti_machdep_attach_console(struct sti_machdep_softc *sc)
{
struct sti_softc *ssc = &sc->sc_sti;
ssc->sc_flags |= STI_CONSOLE | STI_ATTACHED;
ssc->sc_rom = &sticn_rom;
ssc->sc_rom->rom_softc = ssc;
ssc->sc_scr = &sticn_scr;
ssc->sc_scr->scr_rom = ssc->sc_rom;
memcpy(ssc->bases, sticn_bases, sizeof(ssc->bases));
sti_describe(ssc);
}
void
sti_machdep_attach(struct sti_machdep_softc *sc)
{
struct sti_softc *ssc = &sc->sc_sti;
struct sti_screen *scr;
paddr_t base = sc->sc_base;
struct wsemuldisplaydev_attach_args waa;
struct sti_dd *rom_dd;
uint32_t grid0;
rom_dd = &ssc->sc_rom->rom_dd;
grid0 = rom_dd->dd_grid[0];
scr = ssc->sc_scr;
switch (grid0) {
case STI_DD_EVRX:
case STI_DD_382C:
case STI_DD_3X2V:
sc->sc_bitmap = base + STI_EVRX_FBOFFSET;
sti_evrx_resetramdac(scr);
sti_evrx_resetcmap(scr);
scr->setupfb = sti_evrx_setupfb;
scr->putcmap = sti_evrx_putcmap;
break;
case STI_DD_CRX:
sc->sc_bitmap = base + STI_CRX_FBOFFSET;
break;
default:
sti_end_attach(ssc);
return;
}
aprint_normal_dev(ssc->sc_dev, "Enable mmap support\n");
scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
waa.console = ssc->sc_flags & STI_CONSOLE ? 1 : 0;
waa.scrdata = &scr->scr_screenlist;
waa.accessops = &sti_m68k_accessops;
waa.accesscookie = scr;
config_found(ssc->sc_dev, &waa, wsemuldisplaydevprint,
CFARGS_NONE);
}
static int
sti_evrx_putcmap(struct sti_screen *scr, u_int index, u_int count)
{
struct sti_rom *rom = scr->scr_rom;
bus_space_tag_t bst = rom->memt;
bus_space_handle_t bsh = rom->regh[2];
int i;
bus_space_write_4(bst, bsh, EVRX_MAGIC08, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC00, 0x00000001);
for (i = index; i < index + count; i++) {
while ((bus_space_read_4(bst, bsh, EVRX_MAGIC10) &
EVRX_MAGIC10_BSY) != 0)
continue;
bus_space_write_1(bst, bsh, EVRX_BT4xx_ADDR, i);
bus_space_write_1(bst, bsh, EVRX_BT4xx_CMAP, scr->scr_rcmap[i]);
bus_space_write_1(bst, bsh, EVRX_BT4xx_CMAP, scr->scr_gcmap[i]);
bus_space_write_4(bst, bsh, EVRX_MAGIC10, scr->scr_bcmap[i]);
}
return 0;
}
static void
sti_evrx_resetramdac(struct sti_screen *scr)
{
struct sti_rom *rom = scr->scr_rom;
bus_space_tag_t bst = rom->memt;
bus_space_handle_t bsh = rom->regh[2];
#if 0
int i;
#endif
bus_space_write_1(bst, bsh, EVRX_BT4xx_ADDR, 0x04);
bus_space_write_1(bst, bsh, EVRX_BT4xx_CTRL, 0xff);
#if 0
bus_space_write_1(bst, bsh, EVRX_BT458_ADDR, 0x05);
bus_space_write_1(bst, bsh, EVRX_BT458_CTRL, 0x00);
bus_space_write_1(bst, bsh, EVRX_BT458_ADDR, 0x06);
bus_space_write_1(bst, bsh, EVRX_BT458_CTRL, 0x40);
bus_space_write_1(bst, bsh, EVRX_BT458_ADDR, 0x07);
bus_space_write_1(bst, bsh, EVRX_BT458_CTRL, 0x00);
#endif
bus_space_write_4(bst, bsh, EVRX_MAGIC00, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC04, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC08, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC0C, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC18, 0xFFFFFFFF);
bus_space_write_4(bst, bsh, EVRX_MAGIC1C, 0x00000000);
#if 0
bus_space_write_1(bst, bsh, EVRX_BT458_ADDR, 0x00);
for (i = 0; i < 4; i++) {
bus_space_write_1(bst, bsh, EVRX_BT458_OMAP, 0x00);
bus_space_write_1(bst, bsh, EVRX_BT458_OMAP, 0x00);
bus_space_write_1(bst, bsh, EVRX_BT458_OMAP, 0x00);
}
#endif
}
static void
sti_evrx_resetcmap(struct sti_screen *scr)
{
struct sti_rom *rom = scr->scr_rom;
bus_space_tag_t bst = rom->memt;
bus_space_handle_t bsh = rom->regh[2];
int i;
bus_space_write_4(bst, bsh, EVRX_MAGIC08, 0x00000001);
bus_space_write_4(bst, bsh, EVRX_MAGIC00, 0x00000001);
for (i = 0; i < STI_NCMAP; i++) {
while ((bus_space_read_4(bst, bsh, EVRX_MAGIC10) &
EVRX_MAGIC10_BSY) != 0)
continue;
bus_space_write_1(bst, bsh, EVRX_BT458_ADDR, i);
scr->scr_rcmap[i] = bus_space_read_1(bst, bsh, EVRX_BT4xx_CMAP);
scr->scr_gcmap[i] = bus_space_read_1(bst, bsh, EVRX_BT4xx_CMAP);
scr->scr_bcmap[i] = bus_space_read_1(bst, bsh, EVRX_BT4xx_CMAP);
}
}
static void
sti_evrx_setupfb(struct sti_screen *scr)
{
sti_init(scr, 0);
sti_evrx_resetramdac(scr);
}
static paddr_t
sti_m68k_mmap(void *v, void *vs, off_t offset, int prot)
{
struct sti_screen *scr = (struct sti_screen *)v;
struct sti_rom *rom = scr->scr_rom;
struct sti_softc *ssc = rom->rom_softc;
struct sti_machdep_softc *sc = device_private(ssc->sc_dev);
paddr_t cookie = -1;
if ((offset & PAGE_MASK) != 0)
return -1;
switch (scr->scr_wsmode) {
case WSDISPLAYIO_MODE_MAPPED:
break;
case WSDISPLAYIO_MODE_DUMBFB:
if (offset >= 0 && offset < (scr->fbwidth * scr->fbheight))
cookie = m68k_btop(sc->sc_bitmap + offset);
break;
default:
break;
}
return cookie;
}
void
sti_machdep_cnattach(bus_space_tag_t bst, paddr_t base)
{
int i;
sticn_tag = *bst;
for (i = 0; i < STI_REGION_MAX; i++)
sticn_bases[i] = (bus_addr_t)base;
sti_cnattach(&sticn_rom, &sticn_scr, &sticn_tag, sticn_bases,
STI_CODEBASE_M68K);
}