> Date: Sun, 19 Jul 2009 19:04:26 +0100
> From: Edd Barrett <[email protected]>
> 
> Hai,
> 
> On Sun, Jul 19, 2009 at 04:25:20PM +0200, Mark Kettenis wrote:
> > Here is a diff that implements this.  It expects to find the firmware
> > in the file /etc/firmware/afb to be more consistent with the firmwares
> > already there.  Can you test this for me?
> 
> Oh noooo!
> 
> ...
> root on sd0a swap on sd0b dump on sd0b
> creator0: firmware rev 1.3.11
> panic: kernel data fault: pc=14078f4 addr=4000144600

Oops, I can see where that is going wrong.  Here's a new diff.

Index: creator.c
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/creator.c,v
retrieving revision 1.41
diff -u -p -r1.41 creator.c
--- creator.c   16 Jul 2009 21:03:09 -0000      1.41
+++ creator.c   19 Jul 2009 20:34:53 -0000
@@ -32,7 +32,7 @@
 #include <sys/kernel.h>
 #include <sys/device.h>
 #include <sys/conf.h>
-#include <sys/timeout.h>
+#include <sys/malloc.h>
 
 #include <machine/bus.h>
 #include <machine/autoconf.h>
@@ -50,6 +50,7 @@ int   creator_match(struct device *, void 
 void   creator_attach(struct device *, struct device *, void *);
 int    creator_ioctl(void *, u_long, caddr_t, int, struct proc *);
 paddr_t creator_mmap(void *, off_t, int);
+
 void   creator_ras_fifo_wait(struct creator_softc *, int);
 void   creator_ras_wait(struct creator_softc *);
 void   creator_ras_init(struct creator_softc *);
@@ -58,10 +59,14 @@ void        creator_ras_erasecols(void *, int, 
 void   creator_ras_eraserows(void *, int, int, long int);
 void   creator_ras_fill(struct creator_softc *);
 void   creator_ras_setfg(struct creator_softc *, int32_t);
+
 int    creator_setcursor(struct creator_softc *, struct wsdisplay_cursor *);
 int    creator_updatecursor(struct creator_softc *, u_int);
 void   creator_curs_enable(struct creator_softc *, u_int);
 
+void   creator_load_firmware(void *);
+void   creator_load_sram(struct creator_softc *, u_int32_t *, u_int32_t);
+
 struct wsdisplay_accessops creator_accessops = {
        creator_ioctl,
        creator_mmap,
@@ -190,6 +195,15 @@ creator_attach(parent, self, aux)
                sc->sc_sunfb.sf_ro.ri_ops.erasecols = creator_ras_erasecols;
                sc->sc_sunfb.sf_ro.ri_ops.copyrows = creator_ras_copyrows;
                creator_ras_init(sc);
+
+               /*
+                * Elite3D cards need a firmware for accelerated X to
+                * work.  Console fraamebuffer acceleration will work
+                * without it though, so doing this late should be
+                * fine.
+                */
+               if (sc->sc_type == FFB_AFB) 
+                       mountroothook_establish(creator_load_firmware, sc);
        }
 
        if (sc->sc_console)
@@ -711,5 +725,87 @@ creator_ras_setfg(sc, fg)
                return;
        sc->sc_fg_cache = fg;
        FBC_WRITE(sc, FFB_FBC_FG, fg);
+       creator_ras_wait(sc);
+}
+
+struct creator_firmware {
+       char            fw_ident[8];
+       u_int32_t       fw_size;
+       u_int32_t       fw_reserved[2];
+       u_int32_t       fw_ucode[0];
+};
+
+#define CREATOR_FIRMWARE_REV   0x101
+
+void
+creator_load_firmware(void *vsc)
+{
+       struct creator_softc *sc = vsc;
+       struct creator_firmware *fw;
+       u_int32_t ascr;
+       size_t buflen;
+       u_char *buf;
+       int error;
+
+       error = loadfirmware("afb", &buf, &buflen);
+       if (error) {
+               printf("%s: error %d, could not read firmware %s\n",
+                      sc->sc_sunfb.sf_dev.dv_xname, error, "afb");
+               return;
+       }
+
+       fw = (struct creator_firmware *)buf;
+       if (sizeof(*fw) > buflen ||
+           fw->fw_size * sizeof(u_int32_t) > (buflen - sizeof(*fw))) {
+               printf("%s: corrupt firmware\n", sc->sc_sunfb.sf_dev.dv_xname);
+               free(buf, M_DEVBUF);
+               return;
+       }
+
+       printf("%s: firmware rev %d.%d.%d\n", sc->sc_sunfb.sf_dev.dv_xname,
+              (fw->fw_ucode[CREATOR_FIRMWARE_REV] >> 16) & 0xff,
+              (fw->fw_ucode[CREATOR_FIRMWARE_REV] >> 8) & 0xff,
+              fw->fw_ucode[CREATOR_FIRMWARE_REV] & 0xff);
+
+       ascr = FBC_READ(sc, FFB_FBC_ASCR);
+
+       /* Stop all floats. */
+       FBC_WRITE(sc, FFB_FBC_FEM, ascr & 0x3f);
+       FBC_WRITE(sc, FFB_FBC_ASCR, FBC_ASCR_STOP);
+
+       creator_ras_wait(sc);
+
+       /* Load firmware into all secondary floats. */
+       if (ascr & 0x3e) {
+               FBC_WRITE(sc, FFB_FBC_FEM, ascr & 0x3e);
+               creator_load_sram(sc, fw->fw_ucode, fw->fw_size);
+       }
+
+       /* Load firmware into primary float. */
+       FBC_WRITE(sc, FFB_FBC_FEM, ascr & 0x01);
+       creator_load_sram(sc, fw->fw_ucode, fw->fw_size);
+
+       /* Restart all floats. */
+       FBC_WRITE(sc, FFB_FBC_FEM, ascr & 0x3f);
+       FBC_WRITE(sc, FFB_FBC_ASCR, FBC_ASCR_RESTART);
+
+       creator_ras_wait(sc);
+
+       free(buf, M_DEVBUF);
+}
+
+void
+creator_load_sram(struct creator_softc *sc, u_int32_t *ucode, u_int32_t size)
+{
+       FBC_WRITE(sc, FFB_FBC_SRAMAR, 0);
+
+       while (size > 0) {
+               creator_ras_fifo_wait(sc, 16);
+               bus_space_write_region_4(sc->sc_bt, sc->sc_fbc_h,
+                   FFB_FBC_SRAM36, ucode, 16);
+               ucode += 16;
+               size -= 16;
+       }
+
        creator_ras_wait(sc);
 }
Index: creatorreg.h
===================================================================
RCS file: /cvs/src/sys/arch/sparc64/dev/creatorreg.h,v
retrieving revision 1.8
diff -u -p -r1.8 creatorreg.h
--- creatorreg.h        20 Jun 2003 19:54:37 -0000      1.8
+++ creatorreg.h        19 Jul 2009 20:34:53 -0000
@@ -242,6 +242,13 @@
 #define        FFB_FBC_UCSR            0x900   /* User Control & Status */
 #define        FFB_FBC_MER             0x980
 
+#define FFB_FBC_FEM            0x1540
+#define FFB_FBC_SRAMAR         0x1550
+
+#define FFB_FBC_ASCR           0x10800
+#define FFB_FBC_KSCR           0x10900
+#define FFB_FBC_SRAM36         0x114c0
+
 #define        FFB_FBC_WB_A            0x20000000
 #define        FFB_FBC_WM_COMBINED     0x00080000
 #define        FFB_FBC_RB_A            0x00004000
@@ -287,6 +294,9 @@
 #define        FBC_UCSR_RP_BUSY        0x02000000
 #define        FBC_UCSR_READ_ERR       0x40000000
 #define        FBC_UCSR_FIFO_OVFL      0x80000000
+
+#define FBC_ASCR_STOP          0x00020000
+#define FBC_ASCR_RESTART       0x00040000
 
 #define        FBC_DRAWOP_DOT          0x00
 #define        FBC_DRAWOP_AADOT        0x01

Reply via email to