From 83de49c6fff0d04a10d3d2b7626996c1ecf7d54f Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 2 Apr 2024 14:55:53 +0200 Subject: parisc: Build artist / Visualize EG PCI ROM Build a ROM for Visualize EG PCI. Signed-off-by: Helge Deller --- Makefile | 5 +- Makefile.parisc | 19 +++- src/parisc/make-sti-rom.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 3 deletions(-) create mode 100644 src/parisc/make-sti-rom.c diff --git a/Makefile b/Makefile index 3a7e119..a02b50a 100644 --- a/Makefile +++ b/Makefile @@ -112,8 +112,9 @@ endif # Install parisc firmware into qemu pc-bios directory parisc-qemu-install: parisc - hppa-linux-gnu-objcopy -S out/hppa-firmware.img ../../pc-bios/hppa-firmware.img - hppa64-linux-gnu-objcopy -S out-64/hppa-firmware64.img ../../pc-bios/hppa-firmware64.img + cp out/artist-pci.rom ../../pc-bios/ + hppa-linux-gnu-objcopy -S out/hppa-firmware.img ../../pc-bios/ + hppa64-linux-gnu-objcopy -S out-64/hppa-firmware64.img ../../pc-bios/ # Make definitions .PHONY : all clean distclean parisc FORCE diff --git a/Makefile.parisc b/Makefile.parisc index 5c34eb3..cf90258 100644 --- a/Makefile.parisc +++ b/Makefile.parisc @@ -103,6 +103,7 @@ endif target-y := target-$(CONFIG_PARISC) += $(OUT)hppa-firmware$(BIT_SUFFIX).img +target-$(CONFIG_PARISC) += $(OUT)artist-pci.rom all: $(target-y) @@ -169,7 +170,23 @@ $(OUT)hppa-firmware$(BIT_SUFFIX).img: $(OUT)autoconf.h $(OUT)head.o $(OUT)ccode3 @echo " Linking $@" $(Q)$(CPP) $(CPPFLAGS) -Isrc -D__ASSEMBLY__ -DBITS=$(BITS) src/parisc/pafirmware.lds.S -o $(OUT)pafirmware.lds $(Q)$(CC) $(CFLAGS32FLAT) -c src/version.c -o $(OUT)version.o - $(Q)$(LD) -N -T $(OUT)pafirmware.lds $(OUT)head.o $(OUT)version.o -X -o $@ -e startup --as-needed $(OUT)ccode32flat.o $(LIBGCC) + $(Q)$(LD) -N -T $(OUT)pafirmware.lds $(OUT)head.o $(OUT)version.o -X -o $@ \ + -e startup --as-needed $(OUT)ccode32flat.o $(LIBGCC) + +$(OUT)sti-rom.bin: $(OUT)hppa-firmware$(BIT_SUFFIX).img + @echo " Building $@" + $(Q)$(OBJCOPY) -j .sti $< $(OUT)sti-rom.elf + $(Q)$(OBJDUMP) -t $(OUT)sti-rom.elf | grep " sti_" | sort | \ + awk -F ' ' '{print "#define off$(BIT_SUFFIX)_" $$6 "\t0x" $$1}' > $(OUT)sti-rom-offsets.h + $(Q)$(OBJCOPY) $(OUT)sti-rom.elf --output-target binary $@ + +$(OUT)sti-rom-offsets.h: $(OUT)sti-rom.bin + +$(OUT)make-sti-rom$(BIT_SUFFIX): src/parisc/make-sti-rom.c $(OUT)sti-rom-offsets.h + $(HOSTCC) -I. $< -o $@ + +$(OUT)artist-pci.rom: $(OUT)make-sti-rom$(BIT_SUFFIX) $(OUT)sti-rom.bin $(OUT)sti-rom-offsets.h + $(OUT)make-sti-rom$(BIT_SUFFIX) $(OUT)sti-rom.bin $@ ################ Kconfig rules diff --git a/src/parisc/make-sti-rom.c b/src/parisc/make-sti-rom.c new file mode 100644 index 0000000..07f6a3e --- /dev/null +++ b/src/parisc/make-sti-rom.c @@ -0,0 +1,224 @@ +/* + * Build STI ROM for qemu + * + * (C) 2024 Helge Deller + * + * See: + * https://parisc.wiki.kernel.org/images-parisc/e/e3/Sti.pdf + */ + +#include +#include +#include +#include +#include +#include + +#include "out/sti-rom-offsets.h" +#include "src/hw/pci_ids.h" + +#define BUILD_STI_ROM +#include "src/parisc/sticore.h" + +#define ROMSIZE 64 * 1024 +#define BLOCKSIZE 512 +#define STI_ROM_OFFSET sizeof(struct pci_rom_header) /* STI ROM starts after PCI ROM HEADER */ + +#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) + +struct pci_data_structure { + char sig[4]; + uint16_t ven, dev, res1, ds_len; + uint32_t class_and_rev; + uint16_t len, rev; + char code, indicator, res2, res3; +}; + +struct pci_rom_header { + uint32_t sig; + uint32_t rom_type; + uint32_t sti_image_offset; + uint16_t rom_size; /* multiple of 512 */ + uint16_t sti_region_mapper_offset; + uint32_t empty[2]; + uint16_t pci_ds_offset; + struct pci_data_structure ds; + char pci_region_mapper[16]; +}; + +char *rom; +struct pci_rom_header *rh; +char *sti_rom_start; + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + #define host_to_be16(x) __builtin_bswap16(x) + #define host_to_be32(x) __builtin_bswap32(x) + #define host_to_le16(x) (x) + #define host_to_le32(x) (x) +#else + #define host_to_be16(x) (x) + #define host_to_be32(x) (x) + #define host_to_le16(x) __builtin_bswap16(x) + #define host_to_le32(x) __builtin_bswap32(x) +#endif + +int main(int argc, char *argv[]) +{ + int fh; + ssize_t size; + unsigned long addr; + + rom = malloc(ROMSIZE); + assert(rom); + memset(rom, 0, ROMSIZE); + + fh = open(argv[1], O_RDONLY); + assert(fh >= 0); + sti_rom_start = &rom[STI_ROM_OFFSET]; + size = read(fh, sti_rom_start, 2 * ROMSIZE); + assert(size < ROMSIZE); + close(fh); + + rh = (void *)rom; + rh->sig = host_to_le32(0xaa55); + rh->rom_type = host_to_le32(1 << 24); + rh->sti_image_offset = host_to_le32(STI_ROM_OFFSET); + rh->rom_size = host_to_le16(ROMSIZE / BLOCKSIZE); + rh->sti_region_mapper_offset = host_to_le16( + offsetof(struct pci_rom_header, pci_region_mapper)); + rh->pci_region_mapper[0] = 0x10; /* PCI_BASE_ADDRESS_0 */ + rh->pci_region_mapper[1] = 0x10; /* PCI_BASE_ADDRESS_0 */ + rh->pci_region_mapper[2] = 0x10; /* PCI_BASE_ADDRESS_0 */ + rh->pci_region_mapper[3] = 0x10; /* PCI_BASE_ADDRESS_0 */ + rh->pci_ds_offset = host_to_le16(offsetof(struct pci_rom_header, ds)); + + rh->ds.sig[0] = 'P'; + rh->ds.sig[1] = 'C'; + rh->ds.sig[2] = 'I'; + rh->ds.sig[3] = 'R'; + rh->ds.ven = host_to_le16(PCI_VENDOR_ID_HP); + rh->ds.dev = host_to_le16(PCI_DEVICE_ID_HP_VISUALIZE_EG); + rh->ds.ds_len = host_to_le16(sizeof(rh->ds)); + rh->ds.class_and_rev = host_to_le32(PCI_CLASS_DISPLAY_OTHER << 16); + rh->ds.len = host_to_le16(ROMSIZE / BLOCKSIZE); + rh->ds.rev = host_to_le16(0); + rh->ds.code = 0x10; /* Note: NOT 2, as documented in PCI spec! */ + rh->ds.indicator = 1<<7; /* last image */ + + +#define STI_OFFSET(_x) ((off_ ## _x) - off_sti_proc_rom) + + struct sti_rom *sti_proc_rom; + unsigned int sti_rom_size; + + sti_proc_rom = (void *)sti_rom_start; + +#if 0 + region_t *sti_region_list = sti_rom_start + STI_OFFSET(sti_region_list); + + // sti_rom_size = (_sti_rom_end - _sti_rom_start) / 4096; + sti_rom_size = STI_OFFSET(sti_end) / 4096; + if (sti_region_list[0].region_desc.length != sti_rom_size) { + /* The STI ROM size is wrong. Fix it. */ + region_t *rp = (region_t *) &sti_region_list[0]; + rp->region_desc.length = sti_rom_size; + } +#endif + +#if 0 + extern int sti_font; /* in parisc.c, from opt/font fw_cfg option */ + struct font *font_ptr, *font_next, *font_start; + int i; + + /* Swap selected font as first, then chain all. */ + if (sti_font <= 0 || sti_font > ARRAY_SIZE(fontlist)) + sti_font = 1; + + /* Swap selected font in as first font */ + font_next = fontlist[0]; + fontlist[0] = fontlist[sti_font - 1]; + fontlist[sti_font - 1] = font_next; + +#define ENABLE_FONTCOPY +#ifdef ENABLE_FONTCOPY + { + struct font *fontlist_temp[ARRAY_SIZE(fontlist)]; + unsigned long font_size, font_addr; + /* * The trivial swapping above breaks the sti driver on older 64-bit Linux + * kernels which take the "next_font" pointer as unsigned int (instead of + * signed int) and thus calculates a wrong font start address. Avoid the crash + * by sorting the fonts in memory. Maybe HP-UX has problems with that too? + * A Linux kernel patch to avoid that was added in kernel 6.7. + */ + #define FONT_SIZE(f) (sizeof(f->hdr) + f->hdr.bytes_per_char * (unsigned int)(f->hdr.last_char - f->hdr.first_char + 1)) + font_start = fontlist[0]; /* the lowest font ptr */ + for (i = 0; i < ARRAY_SIZE(fontlist); i++) { + font_ptr = fontlist[i]; + if (font_ptr < font_start) /* is font ptr lower? */ + font_start = font_ptr; + font_size = FONT_SIZE(font_ptr); + font_next = malloc_tmplow(font_size); + memcpy(font_next, font_ptr, font_size); + fontlist_temp[i] = font_next; + } + /* font_start is now starting address */ + font_addr = (unsigned long) font_start; + for (i = 0; i < ARRAY_SIZE(fontlist); i++) { + font_ptr = fontlist_temp[i]; + font_size = FONT_SIZE(font_ptr); + memcpy((void *)font_addr, font_ptr, font_size); + malloc_pfree((unsigned long) font_ptr); + fontlist[i] = (struct font *) font_addr; + font_addr += font_size; + font_addr = ALIGN(font_addr, 32); + } + } +#endif + + /* Now chain all fonts */ + font_start = fontlist[0]; + sti_proc_rom.font_start = STI_OFFSET(*font_start); + for (i = 0; i < ARRAY_SIZE(fontlist)-1; i++) { + font_ptr = fontlist[i]; + if (i == ARRAY_SIZE(fontlist)-1) { + /* last entry? */ + font_ptr->hdr.next_font = 0; + continue; + } + font_next = fontlist[i+1]; + font_ptr->hdr.next_font = STI_FONT_OFFSET(font_next, font_start); + } + +#endif + + + addr = STI_OFFSET(sti_end); + addr = (addr + 4096) & ~(4096-1); // align to page boundary + addr -= 1; + sti_proc_rom->last_addr = host_to_be32(addr); + + sti_proc_rom->font_start = host_to_be32(STI_OFFSET(sti_rom_font_10x20)); + + sti_proc_rom->state_mgmt = host_to_be32(STI_OFFSET(sti_state_mgmt)); + sti_proc_rom->inq_conf = host_to_be32(STI_OFFSET(sti_inq_conf)); + sti_proc_rom->init_graph = host_to_be32(STI_OFFSET(sti_init_graph)); + sti_proc_rom->block_move = host_to_be32(STI_OFFSET(sti_bmove)); + sti_proc_rom->region_list = host_to_be32(STI_OFFSET(sti_region_list)); + sti_proc_rom->font_unpmv = host_to_be32(STI_OFFSET(sti_font_unpmv)); + sti_proc_rom->self_test = host_to_be32(STI_OFFSET(sti_self_test)); + sti_proc_rom->mon_tbl_addr = host_to_be32(STI_OFFSET(sti_mon_table)); + sti_proc_rom->user_data_addr = host_to_be32(STI_OFFSET(sti_user_data)); + sti_proc_rom->excep_hdlr = host_to_be32(STI_OFFSET(sti_excep_hdlr)); + sti_proc_rom->set_cm_entry = host_to_be32(STI_OFFSET(sti_set_cm_entry)); + sti_proc_rom->dma_ctrl = host_to_be32(STI_OFFSET(sti_dma_ctrl)); + sti_proc_rom->end = host_to_be32(STI_OFFSET(sti_end)); +// update_crc(&sti_proc_rom); + + + /* finally write ROM image */ + fh = creat(argv[2], 0600); + assert(fh >= 0); + write(fh, rom, ROMSIZE); + close(fh); +} + -- cgit v1.1