[prev in list] [next in list] [prev in thread] [next in thread]
List: bochs-dev
Subject: Re: [Bochs-developers] Enhancing support for PCI
From: "Sebastian Herbszt" <herbszt () gmx ! de>
Date: 2008-10-19 23:01:09
Message-ID: 69B591EF5CB2450FB26E683FE6638719 () FSCPC
[Download RAW message or body]
Mark Marshall wrote:
> My patch has a few parts:
>
> Extend the bx_pci_device_stub_c so that it can contain an EEPROM image.
> This will be needed by any PCI device that has an EEPROM, so this
> seemed like the best place for it.
>
> Extend bx_pcivga_c and bx_svga_cirrus_c so that they expose their option
> ROM's through the EEPROM BAR.
>
> Change rombios32.c so that after we have allocated all of the BARs for
> all PCI devices we then copy the option ROMs into shadow memory in the
> 0xC0000 to 0xE0000 region. The BIOS should check that the VID and PID
> match the option ROM, but I have disabled this test at the moment - it
> will cause big problems with the VGA BIOSes (as they are used with
> different hardware). I don't think this is a problem.
#ifdef sounds reasonable
> Change romios.c so that we only scan for the VGA after we have done the
> rombios32 initialisation. The VGA option ROM will only exist after this
> code has run. I've also added a function that makes the option ROMs
> readonly once the init functions have been called.
>
>
> I'm aware that this is not perfect in places. The main problem that I'm
> having is letting all of the different parts of the system know what is
> going on.
>
> problem 1)
> If we do have an option ROM loaded then I think this will clash with my
> code. I'm not sure how we tell the BIOS that there really is a ROM in
> the address map. I'm guessing that in a real PCI PC there can't be any
> ROM in the first 1Meg. (they are all shadows). I don't know what
> happens if you have both PCI and ISA devices (I think some more reading
> is needed)
I think the pci option rom loading code should scan the option rom space
for existing (valid) roms and then use the spare space:
optromimage1: file=optionalrom.bin, address=0xd0000
does load an option rom for an isa device. New code does detect it and reads
it size and then updates pci_bios_rom_addr.
> problem 2)
> Communicating the option ROM layout to rombios.c. After we have called
> all of the init functions we need to write-protect the shadowed memory.
> We should probably indicate which bits have option rom in them and
> which bits don't. We can then leave unused sections as RAM for use by DOS.
Your current code does only write protect memory associated with PAM1 and
PAM3. I think for now it should be done for PAM2 and PAM4 too.
> problem 3)
> The option ROMs should be called in order, one at a time. The best
> thing would be to have the rombios32 code drop back to 16-bit mode and
> call the option ROM init function. This would allow us to pack the ROM
> images more. The option ROMs should also be called with the PCI bus,
> device and function as a parameter, which is hard to do in the current
> setup.
Or the eeprom loading code could be done in rombios.c instead of rombios32.c.
Any reason you have done it in rombios32.c?
> problem 4)
> I've not written code for configs with BX_PCIBIOS set but without
> BX_ROMBIOS32.
>
> I think the best fix for 1 is do disallow the use of the option-rom
> command when we are using PCI. This will be unpopular, because change
> always is, but it will make things more 'correct'. I'm not sure how
> this firs in with PCs that have both PCI and ISA buses?
I think bochs can be configured with an ISA video card (CL-GD5430) and
a ne2k pci card. We should still allow that configuration.
> Problems 2 & 3 can be fixed by making the rombios32 code drop back to
> 16-bit mode, and then call the init functions itself. We will then need
> to use the rom_scan code in rombios.c to build the IPL table.
>
> Do people care about 4?
>
> I look for to your feedback,
I suggest using the optromimage1-4 syntax for non-pci roms.
i440fxsupport one could be extended for eeprom support, like
i440fxsupport: enabled=1, slot1=pcivga,eeprom=VGABIOS-lgpl-latest
> RCS file: /cvsroot/bochs/bochs/main.cc,v
> retrieving revision 1.383
> diff -u -r1.383 main.cc
> --- main.cc 1 Oct 2008 11:36:04 -0000 1.383
> +++ main.cc 17 Oct 2008 09:14:59 -0000
> @@ -1042,7 +1042,9 @@
> // First load the BIOS and VGABIOS
> BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_ROM_PATH)->getptr(),
> SIM->get_param_num(BXPN_ROM_ADDRESS)->get(), 0);
> +#if !BX_SUPPORT_PCI
> BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr(), 0xc0000, 1);
> +#endif
maybe runtime check here if the vga card is isa or pci instead of the !BX_SUPPORT_PCI
> // Then load the optional ROM images
> if (strcmp(SIM->get_param_string(BXPN_OPTROM1_PATH)->getptr(), "") !=0)
> Index: bios/rombios.c
> ===================================================================
> RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
> retrieving revision 1.214
> diff -u -r1.214 rombios.c
> --- bios/rombios.c 1 Oct 2008 07:41:22 -0000 1.214
> +++ bios/rombios.c 17 Oct 2008 09:15:08 -0000
> @@ -9732,6 +9732,30 @@
> db 0 ;; reserved
> pci_routing_table_structure_end:
>
> +pcibios_protect_roms:
> + wbinvd
> +
> + mov al, #0x09
> + xor bx, bx
> + mov di, #0x5A
> + call pcibios_real
> + and cx, #0xDDDD
> + mov al, #0x0C
> + xor bx, bx
> + mov di, #0x5A
> + call pcibios_real
> +
> + mov al, #0x09
> + xor bx, bx
> + mov di, #0x5C
> + call pcibios_real
> + and cx, #0xDDDD
> + mov al, #0x0C
> + xor bx, bx
> + mov di, #0x5C
> + call pcibios_real
> + ret
> +
maybe check if we're on a 440fx compatible PMC
> #if !BX_ROMBIOS32
> pci_irq_list:
> db 11, 10, 9, 5;
> @@ -10539,12 +10563,6 @@
> #endif
> out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
>
> - mov cx, #0xc000 ;; init vga bios
> - mov ax, #0xc780
> - call rom_scan
> -
> - call _print_bios_banner
> -
> #if BX_ROMBIOS32
> call rombios32_init
> #else
> @@ -10585,10 +10603,16 @@
>
> call _init_boot_vectors
>
> - mov cx, #0xc800 ;; init option roms
> + mov cx, #0xc000 ;; init vga bios & option roms
> mov ax, #0xe000
> call rom_scan
i moved the vga rom scan before rombios32_init so we could use
vga output in rombios32.c. Since it's not used so far we can move it
back
> +#if BX_PCIBIOS
> + call pcibios_protect_roms
> +#endif
> +
> + call _print_bios_banner
> +
> #if BX_ELTORITO_BOOT
> call _interactive_bootkey
> #endif // BX_ELTORITO_BOOT
> Index: bios/rombios32.c
> ===================================================================
> RCS file: /cvsroot/bochs/bochs/bios/rombios32.c,v
> retrieving revision 1.32
> diff -u -r1.32 rombios32.c
> --- bios/rombios32.c 15 Oct 2008 19:04:09 -0000 1.32
> +++ bios/rombios32.c 17 Oct 2008 09:15:09 -0000
> @@ -548,6 +548,7 @@
> static uint32_t pci_bios_io_addr;
> static uint32_t pci_bios_mem_addr;
> static uint32_t pci_bios_bigmem_addr;
> +static uint32_t pci_bios_rom_addr;
> /* host irqs corresponding to PCI irqs A-D */
> static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
> static PCIDevice i440_pcidev;
> @@ -751,7 +752,9 @@
> {
> int class;
> uint32_t *paddr;
> - int i, pin, pic_irq, vendor_id, device_id;
> + int i, pin, pic_irq, vendor_id, device_id, start_slot;
> +
> + start_slot = 0;
>
> class = pci_config_readw(d, PCI_CLASS_DEVICE);
> vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
> @@ -776,10 +779,12 @@
> }
> break;
> case 0x0300:
> - if (vendor_id != 0x1234)
> - goto default_map;
> - /* VGA: map frame buffer to default Bochs VBE address */
> - pci_set_io_region_addr(d, 0, 0xE0000000);
> + if (vendor_id == 0x1234) {
> + /* VGA: map frame buffer to default Bochs VBE address */
> + pci_set_io_region_addr(d, 0, 0xE0000000);
> + start_slot = 1;
> + }
> + goto default_map;
> break;
> case 0x0800:
> /* PIC */
> @@ -801,7 +806,7 @@
> default:
> default_map:
> /* default memory mappings */
> - for(i = 0; i < PCI_NUM_REGIONS; i++) {
> + for(i = start_slot; i < PCI_NUM_REGIONS; i++) {
> int ofs;
> uint32_t val, size ;
>
> @@ -851,6 +856,132 @@
> }
> }
>
> +#define PCI_EEPROM_CHECK_FOR_PCIR
> +#define PCI_EEPROM_ACCEPT_ANY
> +
> +static void pci_bios_init_rom(PCIDevice *d, int class)
> +{
> + uint32_t i, addr, end_addr;
> + uint32_t shadow;
> + uint8_t isa_header[3];
use a structure?
> + uint32_t start_size;
> +#ifdef PCI_EEPROM_CHECK_FOR_PCIR
> + uint8_t pci_ptr[2];
> + uint32_t pci_header_addr;
> + uint8_t pci_header[24];
use a structure?
> + int vendor_id, device_id;
> +#endif
> +
> + addr = pci_config_readl(d, 0x30) & ~0xF;
hide 0x30 behind something like PCI_ROM_ADDRESS
> + if (addr == 0)
> + return;
> +
> + memcpy(isa_header, (void *)addr, 3);
> +
> + BX_INFO("PCI: EEPROM %02x %02x %02x (%x)\n",
> + isa_header[0], isa_header[1], isa_header[2], addr);
> +
> + if (isa_header[0] != 0x55 || isa_header[1] != 0xaa) {
rom_header.signature?
> + BX_INFO("PCI: Bad ISA header\n");
> + goto done;
> + }
> +
> + start_size = isa_header[2] * 512;
rom_header.size?
> +
> +#ifdef PCI_EEPROM_CHECK_FOR_PCIR
> + memcpy(pci_ptr, (void *)(addr + 0x18), 2);
something like PCIR_HEADER_OFFSET?
> + pci_header_addr = addr + readw(pci_ptr);
> +
> + memcpy(pci_header, (void *)pci_header_addr, 24);
sizeof pci_header?
> +
> + if (pci_header[0] != 'P' ||
> + pci_header[1] != 'C' ||
> + pci_header[2] != 'I' ||
> + pci_header[3] != 'R') {
pci_header.signature?
> + BX_INFO("PCI: Bad PCIR header\n");
> +#ifndef PCI_EEPROM_ACCEPT_ANY
> + goto done;
> +#endif
> + } else {
> + vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
> + device_id = pci_config_readw(d, PCI_DEVICE_ID);
> +
> + if (readw(pci_header+4) != vendor_id ||
> + readw(pci_header+6) != device_id ||
> + readw(pci_header+14) != class) {
pci_header.vendor_id, pci_header.device_id and
pci_header.class
> + BX_INFO("PCI: VID, PID & class don't match "
> + "(pci) %04x %04x %04x / (eeprom) %04x %04x %04x\n",
> + vendor_id, device_id, class,
> + readw(pci_header+4), readw(pci_header+6),
> + readw(pci_header+13));
> +#ifndef PCI_EEPROM_ACCEPT_ANY
> + goto done;
> +#endif
> + }
> + }
> +#endif
> +
> + end_addr = pci_bios_rom_addr + ((start_size + 0x3FFF) & ~0x3FFF);
> +
> + /* remap the expansion BIOS to shadow RAM and keep it read/write
> + until after we have run the init function */
> +
> + /* We have to read this as two uint16's because it is unaligned. */
> + shadow = pci_config_readw(&i440_pcidev, 0x5a);
> + shadow |= pci_config_readw(&i440_pcidev, 0x5c) << 16;
> + for (i = pci_bios_rom_addr; i < end_addr; i += 0x4000) {
> + int page = (i - 0xC0000) / 0x4000;
> + shadow |= 0x3 << (page * 4);
> + }
> + pci_config_writew(&i440_pcidev, 0x5a, shadow);
> + pci_config_writew(&i440_pcidev, 0x5c, shadow >> 16);
> +
> + /* copy the image to shadow memory */
> + memcpy((void *)pci_bios_rom_addr, (void *)addr, start_size);
> +
> + BX_INFO("PCI: Shadowed ROM %08x -> %08x (%x)\n",
> + addr, pci_bios_rom_addr, start_size);
> +
> + pci_bios_rom_addr = end_addr;
> +
> +done:
> + /* Disable the EEPROM BAR */
> + pci_config_writel(d, 0x30, 0);
> +
> + /* To be fully accurate we should now call the init function of
> + * the option ROM. We should pass in the Bus,Device,Function in
> + * AX. After the init function has finished we should recheck the
> + * size field, and possibly shrink the amount of shadow memory
> + * used. */
> +}
> +
> +/* We can copy the option ROMs to anywhere in the 0xC0000 - 0xE0000
> + * area, the only restricition is that the VGA ROM must be mapped to
> + * 0xC0000. To make this easy we do two passes. On the first pass we
> + * do the VGA and on the second pass we do everything else.
> + *
> + * If there are two or more VGAs we should only do the first one.
> + */
> +
> +static void pci_bios_init_vga_rom(PCIDevice *d)
> +{
> + int class;
> + /* Check to see if we have done a VGA yet? */
> + if (pci_bios_rom_addr != 0xC0000)
> + return;
> + class = pci_config_readw(d, PCI_CLASS_DEVICE);
> + if (class == 0x0300)
> + pci_bios_init_rom(d, class);
> +}
> +
> +static void pci_bios_init_non_vga_rom(PCIDevice *d)
> +{
> + int class;
> + class = pci_config_readw(d, PCI_CLASS_DEVICE);
> + if (class != 0x0300)
> + pci_bios_init_rom(d, class);
> +}
> +
> void pci_for_each_device(void (*init_func)(PCIDevice *d))
> {
> PCIDevice d1, *d = &d1;
> @@ -875,12 +1006,16 @@
> pci_bios_io_addr = 0xc000;
> pci_bios_mem_addr = 0xf0000000;
> pci_bios_bigmem_addr = ram_size;
> + pci_bios_rom_addr= 0x0C0000;
should be auto-detected for the ISA option-rom case
> if (pci_bios_bigmem_addr < 0x90000000)
> pci_bios_bigmem_addr = 0x90000000;
>
> pci_for_each_device(pci_bios_init_bridges);
>
> pci_for_each_device(pci_bios_init_device);
> +
> + pci_for_each_device(pci_bios_init_vga_rom);
> + pci_for_each_device(pci_bios_init_non_vga_rom);
> }
>
> /****************************************************/
- Sebastian
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
bochs-developers mailing list
bochs-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bochs-developers
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic