> Date: Mon, 20 Jul 2009 01:36:31 +0100
> From: Edd Barrett <[email protected]>
>
> On Sun, Jul 19, 2009 at 10:36:47PM +0200, Mark Kettenis wrote:
> > Oops, I can see where that is going wrong. Here's a new diff.
>
> Now we get a freeze after the kernel reports the firmware version.
>
> Getting there :)
Ugh, it seems that afbinit code does some sneaky word swapping.
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 20 Jul 2009 20:41:48 -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 framebuffer 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,89 @@ 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)
+{
+ int i;
+
+ FBC_WRITE(sc, FFB_FBC_SRAMAR, 0);
+
+ while (size > 0) {
+ creator_ras_fifo_wait(sc, 16);
+ for (i = 0; i < 16; i ++)
+ FBC_WRITE(sc, FFB_FBC_SRAM36 + i, ucode[i ^ 1]);
+ 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 20 Jul 2009 20:41:48 -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