Checkpoint of work-in-progress attempt to support the FireGL-UX board. This
authormiod <miod@openbsd.org>
Sat, 17 Aug 2024 08:45:22 +0000 (08:45 +0000)
committermiod <miod@openbsd.org>
Sat, 17 Aug 2024 08:45:22 +0000 (08:45 +0000)
particular sti(4) device relies upon undocumented callbacks from the kernel,
and will default to iodc code otherwise.

The device now initializes correctly, but writes to the frame buffer memory
freeze the system due to bad interaction with the ROM even though it is
disabled at the PCI level - unfortunately I'm currently out of hair to pull
at the moment to make any progress on this.

No functional change intended for other sti(4) devices.

sys/dev/ic/sti.c
sys/dev/ic/stireg.h
sys/dev/ic/stivar.h
sys/dev/pci/sti_pci.c

index 25bcbb1..848658a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sti.c,v 1.83 2022/07/15 19:29:27 deraadt Exp $        */
+/*     $OpenBSD: sti.c,v 1.84 2024/08/17 08:45:22 miod Exp $   */
 
 /*
  * Copyright (c) 2000-2003 Michael Shalayeff
@@ -110,6 +110,7 @@ void        sti_describe_screen(struct sti_softc *, struct sti_screen *);
 void   sti_end_attach_screen(struct sti_softc *, struct sti_screen *, int);
 int    sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, u_int32_t,
            u_int);
+int32_t        sti_gvid(void *, uint32_t, uint32_t *);
 void   sti_region_setup(struct sti_screen *);
 int    sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
            bus_space_handle_t, bus_addr_t *, u_int);
@@ -122,6 +123,10 @@ void       ngle_elk_setupfb(struct sti_screen *);
 void   ngle_timber_setupfb(struct sti_screen *);
 int    ngle_putcmap(struct sti_screen *, u_int, u_int);
 
+/*
+ * Helper macros to control whether the STI ROM is accessible on PCI
+ * devices.
+ */
 #if NSTI_PCI > 0
 #define        STI_ENABLE_ROM(sc) \
 do { \
@@ -301,6 +306,15 @@ sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
            dd->dd_pacode[0xf]);
 #endif
 
+       /*
+        * Take note that it will be necessary to enable the PCI ROM around
+        * some sti function calls if the MMAP (multiple map) bit is set in
+        * the bus support flags, which means the PCI ROM is only available
+        * through the PCI expansion ROM space and never through regular
+        * PCI BARs.
+        */
+       rom->rom_enable = dd->dd_bussup & STI_BUSSUPPORT_ROMMAP;
+
        /*
         * Figure out how much bytes we need for the STI code.
         * Note there could be fewer than STI_END entries pointer
@@ -337,9 +351,8 @@ sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
                u_int32_t addr, eaddr;
 
                for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
-                   addr < eaddr; addr += 4 )
+                   addr < eaddr; addr += 4)
                        *p++ = bus_space_read_4(memt, romh, addr) & 0xff;
-
        } else  /* STI_DEVTYPE4 */
                bus_space_read_raw_region_4(memt, romh,
                    dd->dd_pacode[STI_BEGIN], rom->rom_code, size);
@@ -371,18 +384,10 @@ sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
              (rom->rom_devtype == STI_DEVTYPE1? 4 : 1)))
 
        rom->init       = (sti_init_t)O(STI_INIT_GRAPH);
-       rom->mgmt       = (sti_mgmt_t)O(STI_STATE_MGMT);
        rom->unpmv      = (sti_unpmv_t)O(STI_FONT_UNPMV);
        rom->blkmv      = (sti_blkmv_t)O(STI_BLOCK_MOVE);
-       rom->test       = (sti_test_t)O(STI_SELF_TEST);
-       rom->exhdl      = (sti_exhdl_t)O(STI_EXCEP_HDLR);
        rom->inqconf    = (sti_inqconf_t)O(STI_INQ_CONF);
        rom->scment     = (sti_scment_t)O(STI_SCM_ENT);
-       rom->dmac       = (sti_dmac_t)O(STI_DMA_CTRL);
-       rom->flowc      = (sti_flowc_t)O(STI_FLOW_CTRL);
-       rom->utiming    = (sti_utiming_t)O(STI_UTIMING);
-       rom->pmgr       = (sti_pmgr_t)O(STI_PROC_MGR);
-       rom->util       = (sti_util_t)O(STI_UTIL);
 
 #undef O
 
@@ -502,6 +507,42 @@ sti_region_setup(struct sti_screen *scr)
 #endif
 }
 
+/*
+ * ``gvid'' callback routine.
+ *
+ * The FireGL-UX board is using this interface, and will revert to direct
+ * PDC calls if no gvid callback is set.
+ * Unfortunately, under OpenBSD it is not possible to invoke PDC directly
+ * from its physical address once the MMU is turned on, and no documentation
+ * for the gvid interface (or for the particular PDC_PCI subroutines used
+ * by the FireGL-UX rom) has been found.
+ */
+int32_t
+sti_gvid(void *v, uint32_t cmd, uint32_t *params)
+{
+       struct sti_screen *scr = v;
+       struct sti_rom *rom = scr->scr_rom;
+
+       /* paranoia */
+       if (cmd != 0x000c0003)
+               return -1;
+
+       switch (params[0]) {
+       case 4:
+               /* register read */
+               params[2] =
+                   bus_space_read_4(rom->memt, rom->regh[2], params[1]);
+               return 0;
+       case 5:
+               /* register write */
+               bus_space_write_4(rom->memt, rom->regh[2], params[1],
+                   params[2]);
+               return 0;
+       default:
+               return -1;
+       }
+}
+
 int
 sti_screen_setup(struct sti_screen *scr, int flags)
 {
@@ -510,8 +551,8 @@ sti_screen_setup(struct sti_screen *scr, int flags)
        bus_space_handle_t romh = rom->romh;
        struct sti_dd *dd = &rom->rom_dd;
        struct sti_cfg *cc = &scr->scr_cfg;
-       struct sti_inqconfout cfg;
-       struct sti_einqconfout ecfg;
+       struct sti_inqconfout inq;
+       struct sti_einqconfout einq;
        int error, i;
        int geometry_kluge = 0;
        u_int fontindex = 0;
@@ -522,7 +563,7 @@ sti_screen_setup(struct sti_screen *scr, int flags)
 
        if (dd->dd_stimemreq) {
                scr->scr_ecfg.addr =
-                   malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT);
+                   malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT | M_ZERO);
                if (!scr->scr_ecfg.addr) {
                        printf("cannot allocate %d bytes for STI\n",
                            dd->dd_stimemreq);
@@ -530,6 +571,12 @@ sti_screen_setup(struct sti_screen *scr, int flags)
                }
        }
 
+       if (dd->dd_ebussup & STI_EBUSSUPPORT_GVID) {
+               scr->scr_ecfg.future.g.gvid_cmd_arg = scr;
+               scr->scr_ecfg.future.g.gvid_cmd =
+                   (int32_t (*)(void *, ...))sti_gvid;
+       }
+
        sti_region_setup(scr);
 
        if ((error = sti_init(scr, 0))) {
@@ -537,10 +584,10 @@ sti_screen_setup(struct sti_screen *scr, int flags)
                goto fail;
        }
 
-       bzero(&cfg, sizeof(cfg));
-       bzero(&ecfg, sizeof(ecfg));
-       cfg.ext = &ecfg;
-       if ((error = sti_inqcfg(scr, &cfg))) {
+       bzero(&inq, sizeof(inq));
+       bzero(&einq, sizeof(einq));
+       inq.ext = &einq;
+       if ((error = sti_inqcfg(scr, &inq))) {
                printf(": error %d inquiring config\n", error);
                goto fail;
        }
@@ -550,25 +597,24 @@ sti_screen_setup(struct sti_screen *scr, int flags)
         * similar to the displayable area size, at least in m68k mode.
         * Attempt to detect this and adjust here.
         */
-       if (cfg.owidth == cfg.width &&
-           cfg.oheight == cfg.height)
+       if (inq.owidth == inq.width && inq.oheight == inq.height)
                geometry_kluge = 1;
 
        if (geometry_kluge) {
-               scr->scr_cfg.oscr_width = cfg.owidth =
-                   cfg.fbwidth - cfg.width;
-               scr->scr_cfg.oscr_height = cfg.oheight =
-                   cfg.fbheight - cfg.height;
+               scr->scr_cfg.oscr_width = inq.owidth =
+                   inq.fbwidth - inq.width;
+               scr->scr_cfg.oscr_height = inq.oheight =
+                   inq.fbheight - inq.height;
        }
 
        /*
         * Save a few fields for sti_describe_screen() later
         */
-       scr->fbheight = cfg.fbheight;
-       scr->fbwidth = cfg.fbwidth;
-       scr->oheight = cfg.oheight;
-       scr->owidth = cfg.owidth;
-       bcopy(cfg.name, scr->name, sizeof(scr->name));
+       scr->fbheight = inq.fbheight;
+       scr->fbwidth = inq.fbwidth;
+       scr->oheight = inq.oheight;
+       scr->owidth = inq.owidth;
+       bcopy(inq.name, scr->name, sizeof(scr->name));
 
        if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
                printf(": can not initialize (%d)\n", error);
@@ -576,12 +622,12 @@ sti_screen_setup(struct sti_screen *scr, int flags)
        }
 #ifdef STIDEBUG
        printf("conf: bpp=%d planes=%d attr=%b\n"
-           "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
-           cfg.planes, cfg.attributes, STI_INQCONF_BITS,
-           ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
-           ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]);
+           "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", inq.bpp,
+           inq.planes, inq.attributes, STI_INQCONF_BITS,
+           einq.crt_config[0], einq.crt_config[1], einq.crt_config[2],
+           einq.crt_hw[0], einq.crt_hw[1], einq.crt_hw[2]);
 #endif
-       scr->scr_bpp = cfg.bppu;
+       scr->scr_bpp = inq.bppu;
 
        /*
         * Although scr->scr_ecfg.current_monitor is not filled by
@@ -618,7 +664,7 @@ sti_screen_setup(struct sti_screen *scr, int flags)
 #endif
        }
 
-       if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
+       if ((error = sti_fetchfonts(scr, &inq, dd->dd_fntaddr, fontindex))) {
                printf(": cannot fetch fonts (%d)\n", error);
                goto fail;
        }
@@ -631,8 +677,8 @@ sti_screen_setup(struct sti_screen *scr, int flags)
         */
 
        strlcpy(scr->scr_wsd.name, "std", sizeof(scr->scr_wsd.name));
-       scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
-       scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
+       scr->scr_wsd.ncols = inq.width / scr->scr_curfont.width;
+       scr->scr_wsd.nrows = inq.height / scr->scr_curfont.height;
        scr->scr_wsd.textops = &sti_emulops;
        scr->scr_wsd.fontwidth = scr->scr_curfont.width;
        scr->scr_wsd.fontheight = scr->scr_curfont.height;
@@ -699,9 +745,10 @@ sti_screen_setup(struct sti_screen *scr, int flags)
        case STI_DD_3X2V:
        case STI_DD_DUAL_CRX:
        case STI_DD_HCRX:
-       case STI_DD_LEGO:
        case STI_DD_SUMMIT:
        case STI_DD_PINNACLE:
+       case STI_DD_LEGO:
+       case STI_DD_FIREGL:
        default:
                scr->setupfb = NULL;
                scr->putcmap =
@@ -713,7 +760,11 @@ sti_screen_setup(struct sti_screen *scr, int flags)
        return (0);
 
 fail:
-       /* XXX free resources */
+       /* free resources */
+       if (scr->scr_romfont != NULL) {
+               free(scr->scr_romfont, M_DEVBUF, 0);
+               scr->scr_romfont = NULL;
+       }
        if (scr->scr_ecfg.addr != NULL) {
                free(scr->scr_ecfg.addr, M_DEVBUF, 0);
                scr->scr_ecfg.addr = NULL;
@@ -809,7 +860,7 @@ sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
 }
 
 int
-sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
+sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *inq,
     u_int32_t baseaddr, u_int fontindex)
 {
        struct sti_rom *rom = scr->scr_rom;
@@ -901,16 +952,16 @@ rescan:
         * display all the characters there in order to display them
         * faster with blkmv operations rather than unpmv later on.
         */
-       if (size <= cfg->fbheight *
-           (cfg->fbwidth - cfg->width - cfg->owidth)) {
+       if (size <= inq->fbheight *
+           (inq->fbwidth - inq->width - inq->owidth)) {
                bzero(&a, sizeof(a));
                a.flags.flags = STI_UNPMVF_WAIT;
                a.in.fg_colour = STI_COLOUR_WHITE;
                a.in.bg_colour = STI_COLOUR_BLACK;
                a.in.font_addr = scr->scr_romfont;
 
-               scr->scr_fontmaxcol = cfg->fbheight / fp->height;
-               scr->scr_fontbase = cfg->width + cfg->owidth;
+               scr->scr_fontmaxcol = inq->fbheight / fp->height;
+               scr->scr_fontbase = inq->width + inq->owidth;
                for (uc = fp->first; uc <= fp->last; uc++) {
                        a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
                            fp->width + scr->scr_fontbase;
@@ -969,7 +1020,15 @@ sti_init(struct sti_screen *scr, int mode)
        printf("sti_init,%p(%x, %p, %p, %p)\n",
            rom->init, a.flags.flags, &a.in, &a.out, &scr->scr_cfg);
 #endif
+       /*
+        * Make the ROM visible during initialization, some devices
+        * look for various data into their ROM image.
+        */
+       if (rom->rom_enable)
+               STI_ENABLE_ROM(rom->rom_softc);
        (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
+       if (rom->rom_enable)
+               STI_DISABLE_ROM(rom->rom_softc);
        if (a.out.text_planes != a.in.text_planes)
                return (-1);    /* not colliding with sti errno values */
        return (a.out.errno);
index a0c5bf5..46282c7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: stireg.h,v 1.14 2015/04/05 23:25:57 miod Exp $        */
+/*     $OpenBSD: stireg.h,v 1.15 2024/08/17 08:45:22 miod Exp $        */
 
 /*
  * Copyright (c) 2000 Michael Shalayeff
@@ -29,8 +29,6 @@
 #ifndef _IC_STIREG_H_
 #define _IC_STIREG_H_
 
-/* #define     STIDEBUG */
-
 #define        STI_REGION_MAX  8
 #define        STI_MONITOR_MAX 256
 #define        STI_DEVNAME_LEN 32
@@ -134,6 +132,7 @@ struct      sti_dd {
 #define        STI_DD_SUMMIT           0x2FC1066B      /* Visualize FX2, FX4, FX6 */
 #define        STI_DD_PINNACLE         0x35ACDA16      /* Visualize FXe */
 #define        STI_DD_LEGO             0x35ACDA30      /* Visualize FX5, FX10 */
+#define        STI_DD_FIREGL           0x3BA8F544      /* FireGL-UX */
        u_int32_t       dd_fntaddr;     /* 0x10 font start address */
        u_int32_t       dd_maxst;       /* 0x14 max state storage */
        u_int32_t       dd_romend;      /* 0x18 rom last address */
@@ -157,6 +156,7 @@ struct      sti_dd {
        u_int8_t        dd_ebussup;     /* 0x37 extended bus support */
 #define        STI_EBUSSUPPORT_DMA     0x01    /*      supports dma */
 #define        STI_EBUSSUPPORT_PIOLOCK 0x02    /*      no implicit locking for dma */
+#define        STI_EBUSSUPPORT_GVID    0x04    /*      requires gvid callback */
        u_int8_t        dd_altcodet;    /* 0x38 alternate code type */
 #define        STI_ALTCODE_UNKNOWN     0x00
 #define        STI_ALTCODE_PA64        0x01    /*      alt code is in pa64 */
@@ -228,7 +228,15 @@ typedef struct sti_ecfg {
        u_int16_t       power;          /* power dissipation Watts */
        u_int32_t       freq_ref;
        u_int32_t       *addr;          /* memory block of size dd_stimemreq */
-       void            *future;
+       union {
+               struct {
+                       int32_t         (*gvid_cmd)(void *, ...);
+                       void            *gvid_cmd_arg;
+                       u_int32_t       pci_id;
+                       void            *future;
+               } g;
+               void *future;
+       } future;
 } __packed *sti_ecfg_t;
 
 typedef struct sti_cfg {
index e694d4c..1173831 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: stivar.h,v 1.28 2024/05/29 00:48:15 jsg Exp $ */
+/*     $OpenBSD: stivar.h,v 1.29 2024/08/17 08:45:22 miod Exp $        */
 
 /*
  * Copyright (c) 2000-2003 Michael Shalayeff
@@ -47,22 +47,16 @@ struct sti_rom {
        struct sti_dd            rom_dd;        /* in word format */
        u_int8_t                *rom_code;
 
+       int                      rom_enable;
+
        /*
         * ROM-provided function pointers
         */
        sti_init_t               init;
-       sti_mgmt_t               mgmt;
        sti_unpmv_t              unpmv;
        sti_blkmv_t              blkmv;
-       sti_test_t               test;
-       sti_exhdl_t              exhdl;
        sti_inqconf_t            inqconf;
        sti_scment_t             scment;
-       sti_dmac_t               dmac;
-       sti_flowc_t              flowc;
-       sti_utiming_t            utiming;
-       sti_pmgr_t               pmgr;
-       sti_util_t               util;
 };
 
 /*
index cd51403..10e243b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sti_pci.c,v 1.13 2023/04/13 15:07:43 miod Exp $       */
+/*     $OpenBSD: sti_pci.c,v 1.14 2024/08/17 08:45:22 miod Exp $       */
 
 /*
  * Copyright (c) 2006, 2007, 2023 Miodrag Vallat.
@@ -52,6 +52,9 @@ const struct pci_matchid sti_pci_devices[] = {
        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FX4 },
        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FX6 },
        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FXE },
+#ifdef notyet
+       { PCI_VENDOR_IBM, PCI_PRODUCT_IBM_FIREGL2 }
+#endif
 };
 
 int    sti_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int);
@@ -267,6 +270,15 @@ sti_check_rom(struct sti_pci_softc *spc, struct pci_attach_args *pa)
        bus_space_read_region_1(pa->pa_memt, romh, offs, region_bars,
            STI_REGION_MAX);
        for (i = 0; i < STI_REGION_MAX; i++) {
+               /*
+                * Region 0 is supposed to always be the ROM. FireGL-UX
+                * ROM agrees so well that it will report the expansion
+                * ROM BAR rather than any regular BAR.
+                * We'll address this later after remapping the ROM.
+                */
+               if (i == 0 && region_bars[i] == PCI_ROM_REG)
+                       continue;
+
                rc = sti_readbar(sc, pa, i, region_bars[i]);
                if (rc != 0)
                        goto unmap_disable_return;
@@ -297,6 +309,16 @@ sti_check_rom(struct sti_pci_softc *spc, struct pci_attach_args *pa)
                goto disable_return;
        }
 
+       /*
+        * Now set up region 0 if we had skipped it earlier.
+        */
+
+       if (region_bars[0] == PCI_ROM_REG) {
+               sc->bases[0] =
+                   (bus_addr_t)bus_space_vaddr(pa->pa_memt, spc->sc_romh) -
+                   (offs - ctx.romoffs);
+       }
+
        sti_pci_disable_rom(sc);
        return 0;