On Mon, Jul 20, 2009 at 10:46:17PM +0200, Mark Kettenis wrote:
> 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
[snip]
> @@ -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);
>  }

I'm sure I'm missing something here; I'm not certain I understand
what you are doing with the for()-loop iterating over 16. So,
take the following comment with a grain of salt: Should there not
be a check to make sure 'fw->fw_size', hence 'size' is a multiple
of 16?

--patrick

Reply via email to