summaryrefslogtreecommitdiff
path: root/roms
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-01-15 13:31:42 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-01-15 13:31:42 -0800
commit42bf3037d458a330856a0be584200c1e41c3f417 (patch)
tree25b9be1088727757e52271e25a446e8a852357df /roms
parent060629c6ef0b7e5c267d84c91600113264d33120 (diff)
downloadqemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.gz
qemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.bz2
qemu-42bf3037d458a330856a0be584200c1e41c3f417.zip
Imported Upstream version 1.3.0upstream/1.3.0
Diffstat (limited to 'roms')
-rw-r--r--roms/Makefile1
-rw-r--r--roms/seabios/Makefile7
-rw-r--r--roms/seabios/src/Kconfig46
-rw-r--r--roms/seabios/src/acpi-dsdt.dsl50
-rw-r--r--roms/seabios/src/acpi.c221
-rw-r--r--roms/seabios/src/ata.c3
-rw-r--r--roms/seabios/src/block.c2
-rw-r--r--roms/seabios/src/blockcmd.c23
-rw-r--r--roms/seabios/src/bootsplash.c7
-rw-r--r--roms/seabios/src/byteorder.h69
-rw-r--r--roms/seabios/src/clock.c31
-rw-r--r--roms/seabios/src/coreboot.c31
-rw-r--r--roms/seabios/src/disk.c2
-rw-r--r--roms/seabios/src/disk.h2
-rw-r--r--roms/seabios/src/esp-scsi.c233
-rw-r--r--roms/seabios/src/esp-scsi.h8
-rw-r--r--roms/seabios/src/farptr.h4
-rw-r--r--roms/seabios/src/lsi-scsi.c2
-rw-r--r--roms/seabios/src/megasas.c399
-rw-r--r--roms/seabios/src/megasas.h8
-rw-r--r--roms/seabios/src/paravirt.c9
-rw-r--r--roms/seabios/src/pci_ids.h8
-rw-r--r--roms/seabios/src/pciinit.c97
-rw-r--r--roms/seabios/src/post.c5
-rw-r--r--roms/seabios/src/smp.c2
-rw-r--r--roms/seabios/src/ssdt-pcihp.dsl124
-rw-r--r--roms/seabios/src/ssdt-susp.dsl41
-rw-r--r--roms/seabios/src/types.h2
-rw-r--r--roms/seabios/src/util.h31
-rwxr-xr-xroms/seabios/tools/acpi_extract.py30
-rw-r--r--roms/seabios/vgasrc/Kconfig21
-rw-r--r--roms/seabios/vgasrc/bochsvga.c1
-rw-r--r--roms/seabios/vgasrc/geodevga.c298
-rw-r--r--roms/seabios/vgasrc/geodevga.h46
-rw-r--r--roms/seabios/vgasrc/stdvgamodes.c10
-rw-r--r--roms/seabios/vgasrc/vbe.c117
-rw-r--r--roms/seabios/vgasrc/vgafb.c3
37 files changed, 1432 insertions, 562 deletions
diff --git a/roms/Makefile b/roms/Makefile
index feb9c2b14..5e645bc7d 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -12,6 +12,7 @@ bios: config.seabios
sh configure-seabios.sh $<
make -C seabios out/bios.bin
cp seabios/out/bios.bin ../pc-bios/bios.bin
+ cp seabios/out/*dsdt.aml ../pc-bios/
seavgabios: $(patsubst %,seavgabios-%,$(vgabios_variants))
diff --git a/roms/seabios/Makefile b/roms/seabios/Makefile
index 849824d28..b0e203113 100644
--- a/roms/seabios/Makefile
+++ b/roms/seabios/Makefile
@@ -13,7 +13,7 @@ SRCBOTH=misc.c stacks.c pmm.c output.c util.c block.c floppy.c ata.c mouse.c \
pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c blockcmd.c \
usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-hid.c usb-msc.c \
virtio-ring.c virtio-pci.c virtio-blk.c virtio-scsi.c apm.c ahci.c \
- usb-uas.c lsi-scsi.c
+ usb-uas.c lsi-scsi.c esp-scsi.c megasas.c
SRC16=$(SRCBOTH) system.c disk.c font.c
SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
@@ -75,6 +75,7 @@ all: $(target-y)
# Make definitions
.PHONY : all clean distclean FORCE
+.DELETE_ON_ERROR:
vpath %.c src vgasrc
vpath %.S src vgasrc
@@ -221,7 +222,7 @@ $(OUT)vgabios.bin: $(OUT)vgabios.bin.raw tools/buildrom.py
################ DSDT build rules
-iasl-option=$(shell if "$(1)" "$(2)" -h > /dev/null 2>&1 \
+iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
$(OUT)%.hex: src/%.dsl ./tools/acpi_extract_preprocess.py ./tools/acpi_extract.py
@@ -232,7 +233,7 @@ $(OUT)%.hex: src/%.dsl ./tools/acpi_extract_preprocess.py ./tools/acpi_extract.p
$(Q)$(PYTHON) ./tools/acpi_extract.py $(OUT)$*.lst > $(OUT)$*.off
$(Q)cat $(OUT)$*.off > $@
-$(OUT)ccode32flat.o: $(OUT)acpi-dsdt.hex $(OUT)ssdt-proc.hex $(OUT)ssdt-pcihp.hex
+$(OUT)ccode32flat.o: $(OUT)acpi-dsdt.hex $(OUT)ssdt-proc.hex $(OUT)ssdt-pcihp.hex $(OUT)ssdt-susp.hex
################ Kconfig rules
diff --git a/roms/seabios/src/Kconfig b/roms/seabios/src/Kconfig
index bc343ee81..0b112edd8 100644
--- a/roms/seabios/src/Kconfig
+++ b/roms/seabios/src/Kconfig
@@ -4,14 +4,24 @@ mainmenu "SeaBIOS Configuration"
menu "General Features"
+choice
+ prompt "Build Target"
+ default QEMU
+
config COREBOOT
bool "Build for coreboot"
- default n
help
Configure as a coreboot payload.
+ config QEMU
+ bool "Build for QEMU"
+ help
+ Configure as QEMU bios.
+
+endchoice
+
config XEN
- depends on !COREBOOT
+ depends on QEMU
bool "Build for Xen HVM"
default y
help
@@ -108,23 +118,35 @@ menu "Hardware support"
help
Support for AHCI disk code.
config VIRTIO_BLK
- depends on DRIVES && !COREBOOT
+ depends on DRIVES && QEMU
bool "virtio-blk controllers"
default y
help
Support boot from virtio-blk storage.
config VIRTIO_SCSI
- depends on DRIVES && !COREBOOT
+ depends on DRIVES && QEMU
bool "virtio-scsi controllers"
default y
help
Support boot from virtio-scsi storage.
+ config ESP_SCSI
+ depends on DRIVES && QEMU
+ bool "AMD PCscsi controllers"
+ default y
+ help
+ Support boot from AMD PCscsi storage.
config LSI_SCSI
- depends on DRIVES && !COREBOOT
+ depends on DRIVES && QEMU
bool "lsi53c895a scsi controllers"
default y
help
Support boot from qemu-emulated lsi53c895a scsi storage.
+ config MEGASAS
+ depends on DRIVES
+ bool "LSI MegaRAID SAS controllers"
+ default y
+ help
+ Support boot from LSI MegaRAID SAS scsi storage.
config FLOPPY
depends on DRIVES
bool "Floppy controller"
@@ -205,17 +227,23 @@ menu "Hardware support"
Support parallel ports. This also enables int 17 parallel port calls.
config USE_SMM
- depends on !COREBOOT
+ depends on QEMU
bool "System Management Mode (SMM)"
default y
help
Support System Management Mode (on emulators).
config MTRR_INIT
- depends on !COREBOOT
+ depends on QEMU
bool "Initialize MTRRs"
default y
help
Initialize the Memory Type Range Registers (on emulators).
+ config PMTIMER
+ depends on QEMU
+ bool "Use ACPI timer"
+ default y
+ help
+ Use the ACPI timer instead of the TSC for timekeeping (on qemu).
endmenu
menu "BIOS interfaces"
@@ -315,7 +343,7 @@ menu "BIOS interfaces"
endmenu
menu "BIOS Tables"
- depends on !COREBOOT
+ depends on QEMU
config PIRTABLE
bool "PIR table"
default y
@@ -365,7 +393,7 @@ menu "Debugging"
Base port for serial - generally 0x3f8, 0x2f8, 0x3e8, or 0x2e8.
config DEBUG_IO
- depends on !COREBOOT && DEBUG_LEVEL != 0
+ depends on QEMU && DEBUG_LEVEL != 0
bool "Special IO port debugging"
default y
help
diff --git a/roms/seabios/src/acpi-dsdt.dsl b/roms/seabios/src/acpi-dsdt.dsl
index 72dc7d8aa..711302ece 100644
--- a/roms/seabios/src/acpi-dsdt.dsl
+++ b/roms/seabios/src/acpi-dsdt.dsl
@@ -86,7 +86,10 @@ DefinitionBlock (
#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
prt_slot0(0x0000),
/* Device 1 is power mgmt device, and can only use irq 9 */
- prt_slot(0x0001, LNKS, LNKB, LNKC, LNKD),
+ Package() { 0x1ffff, 0, 0, 9 },
+ Package() { 0x1ffff, 1, LNKB, 0 },
+ Package() { 0x1ffff, 2, LNKC, 0 },
+ Package() { 0x1ffff, 3, LNKD, 0 },
prt_slot2(0x0002),
prt_slot3(0x0003),
prt_slot0(0x0004),
@@ -266,15 +269,11 @@ DefinitionBlock (
Return (0x0F)
}
Name(_CRS, ResourceTemplate() {
- DWordMemory(
- ResourceConsumer, PosDecode, MinFixed, MaxFixed,
- NonCacheable, ReadWrite,
- 0x00000000,
- 0xFED00000,
- 0xFED003FF,
- 0x00000000,
- 0x00000400 /* 1K memory: FED00000 - FED003FF */
- )
+ IRQNoFlags () {2, 8}
+ Memory32Fixed (ReadOnly,
+ 0xFED00000, // Address Base
+ 0x00000400, // Address Length
+ )
})
}
}
@@ -556,7 +555,6 @@ DefinitionBlock (
PCNT(Local0, 3)
}
}
- Return(One)
}
}
@@ -651,17 +649,6 @@ DefinitionBlock (
Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ3)) }
Method (_SRS, 1, NotSerialized) { SETIRQ(PRQ3, Arg0) }
}
- Device(LNKS) {
- Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
- Name(_UID, 5)
- Name(_PRS, ResourceTemplate() {
- Interrupt (, Level, ActiveHigh, Shared)
- { 9 }
- })
- Method (_STA, 0, NotSerialized) { Return (IQST(PRQ0)) }
- Method (_DIS, 0, NotSerialized) { DISIRQ(PRQ0) }
- Method (_CRS, 0, NotSerialized) { Return (IQCR(PRQ0)) }
- }
}
/****************************************************************
@@ -737,7 +724,6 @@ DefinitionBlock (
}
Increment(Local0)
}
- Return(One)
}
}
@@ -751,54 +737,40 @@ DefinitionBlock (
Name(_HID, "ACPI0006")
Method(_L00) {
- Return(0x01)
}
Method(_E01) {
// PCI hotplug event
- Return(\_SB.PCI0.PCNF())
+ \_SB.PCI0.PCNF()
}
Method(_E02) {
// CPU hotplug event
- Return(\_SB.PRSC())
+ \_SB.PRSC()
}
Method(_L03) {
- Return(0x01)
}
Method(_L04) {
- Return(0x01)
}
Method(_L05) {
- Return(0x01)
}
Method(_L06) {
- Return(0x01)
}
Method(_L07) {
- Return(0x01)
}
Method(_L08) {
- Return(0x01)
}
Method(_L09) {
- Return(0x01)
}
Method(_L0A) {
- Return(0x01)
}
Method(_L0B) {
- Return(0x01)
}
Method(_L0C) {
- Return(0x01)
}
Method(_L0D) {
- Return(0x01)
}
Method(_L0E) {
- Return(0x01)
}
Method(_L0F) {
- Return(0x01)
}
}
}
diff --git a/roms/seabios/src/acpi.c b/roms/seabios/src/acpi.c
index 39b71720e..6d239fa7f 100644
--- a/roms/seabios/src/acpi.c
+++ b/roms/seabios/src/acpi.c
@@ -7,11 +7,12 @@
#include "acpi.h" // struct rsdp_descriptor
#include "util.h" // memcpy
+#include "byteorder.h" // cpu_to_le16
#include "pci.h" // pci_find_init_device
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
#include "pci_regs.h" // PCI_INTERRUPT_LINE
#include "ioport.h" // inl
-#include "paravirt.h"
+#include "paravirt.h" // qemu_cfg_irq0_override
/****************************************************/
/* ACPI tables init */
@@ -400,34 +401,115 @@ encodeLen(u8 *ssdt_ptr, int length, int bytes)
#include "ssdt-proc.hex"
/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
-#define SD_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
-#define SD_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
-#define SD_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
-#define SD_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
-#define SD_PROC (ssdp_proc_aml + *ssdt_proc_start)
+#define PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
+#define PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
+#define PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
+#define PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
+#define PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
+
+/* 0x5B 0x82 DeviceOp PkgLength NameString */
+#define PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
+#define PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
+#define PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
+#define PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
+#define PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
+#define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
+#define PCI_SLOTS 32
#define SSDT_SIGNATURE 0x54445353 // SSDT
+#define SSDT_HEADER_LENGTH 36
+
+#include "ssdt-susp.hex"
+#include "ssdt-pcihp.hex"
+
+#define PCI_RMV_BASE 0xae0c
+
+static u8*
+build_notify(u8 *ssdt_ptr, const char *name, int skip, int count,
+ const char *target, int ofs)
+{
+ count -= skip;
+
+ *(ssdt_ptr++) = 0x14; // MethodOp
+ ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*count), 2);
+ memcpy(ssdt_ptr, name, 4);
+ ssdt_ptr += 4;
+ *(ssdt_ptr++) = 0x02; // MethodOp
+
+ int i;
+ for (i = skip; count-- > 0; i++) {
+ *(ssdt_ptr++) = 0xA0; // IfOp
+ ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
+ *(ssdt_ptr++) = 0x93; // LEqualOp
+ *(ssdt_ptr++) = 0x68; // Arg0Op
+ *(ssdt_ptr++) = 0x0A; // BytePrefix
+ *(ssdt_ptr++) = i;
+ *(ssdt_ptr++) = 0x86; // NotifyOp
+ memcpy(ssdt_ptr, target, 4);
+ ssdt_ptr[ofs] = getHex(i >> 4);
+ ssdt_ptr[ofs + 1] = getHex(i);
+ ssdt_ptr += 4;
+ *(ssdt_ptr++) = 0x69; // Arg1Op
+ }
+ return ssdt_ptr;
+}
+
+static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject)
+{
+ ssdt_ptr[PCIHP_OFFSET_HEX] = getHex(slot >> 4);
+ ssdt_ptr[PCIHP_OFFSET_HEX+1] = getHex(slot);
+ ssdt_ptr[PCIHP_OFFSET_ID] = slot;
+ ssdt_ptr[PCIHP_OFFSET_ADR + 2] = slot;
+
+ /* Runtime patching of EJ0: to disable hotplug for a slot,
+ * replace the method name: _EJ0 by EJ0_. */
+ /* Sanity check */
+ if (memcmp(ssdt_ptr + PCIHP_OFFSET_EJ0, "_EJ0", 4)) {
+ warn_internalerror();
+ }
+ if (!eject) {
+ memcpy(ssdt_ptr + PCIHP_OFFSET_EJ0, "EJ0_", 4);
+ }
+}
static void*
build_ssdt(void)
{
int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
- // length = ScopeOp + procs + NTYF method + CPON package
- int length = ((1+3+4)
- + (acpi_cpus * SD_SIZEOF)
- + (1+2+5+(12*acpi_cpus))
- + (6+2+1+(1*acpi_cpus))
- + 17);
- u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length);
+ int length = (sizeof(ssdp_susp_aml) // _S3_ / _S4_ / _S5_
+ + (1+3+4) // Scope(_SB_)
+ + (acpi_cpus * PROC_SIZEOF) // procs
+ + (1+2+5+(12*acpi_cpus)) // NTFY
+ + (6+2+1+(1*acpi_cpus)) // CPON
+ + 17 // BDAT
+ + (1+3+4) // Scope(PCI0)
+ + ((PCI_SLOTS - 1) * PCIHP_SIZEOF) // slots
+ + (1+2+5+(12*(PCI_SLOTS - 1)))); // PCNT
+ u8 *ssdt = malloc_high(length);
if (! ssdt) {
warn_noalloc();
return NULL;
}
- u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header);
+ u8 *ssdt_ptr = ssdt;
+
+ // Copy header and encode fwcfg values in the S3_ / S4_ / S5_ packages
+ int sys_state_size;
+ char *sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
+ if (!sys_states || sys_state_size != 6)
+ sys_states = (char[]){128, 0, 0, 129, 128, 128};
+
+ memcpy(ssdt_ptr, ssdp_susp_aml, sizeof(ssdp_susp_aml));
+ if (!(sys_states[3] & 128))
+ ssdt_ptr[acpi_s3_name[0]] = 'X';
+ if (!(sys_states[4] & 128))
+ ssdt_ptr[acpi_s4_name[0]] = 'X';
+ else
+ ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
+ ssdt_ptr += sizeof(ssdp_susp_aml);
// build Scope(_SB_) header
*(ssdt_ptr++) = 0x10; // ScopeOp
- ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3);
+ ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
*(ssdt_ptr++) = '_';
*(ssdt_ptr++) = 'S';
*(ssdt_ptr++) = 'B';
@@ -436,37 +518,17 @@ build_ssdt(void)
// build Processor object for each processor
int i;
for (i=0; i<acpi_cpus; i++) {
- memcpy(ssdt_ptr, SD_PROC, SD_SIZEOF);
- ssdt_ptr[SD_OFFSET_CPUHEX] = getHex(i >> 4);
- ssdt_ptr[SD_OFFSET_CPUHEX+1] = getHex(i);
- ssdt_ptr[SD_OFFSET_CPUID1] = i;
- ssdt_ptr[SD_OFFSET_CPUID2] = i;
- ssdt_ptr += SD_SIZEOF;
+ memcpy(ssdt_ptr, PROC_AML, PROC_SIZEOF);
+ ssdt_ptr[PROC_OFFSET_CPUHEX] = getHex(i >> 4);
+ ssdt_ptr[PROC_OFFSET_CPUHEX+1] = getHex(i);
+ ssdt_ptr[PROC_OFFSET_CPUID1] = i;
+ ssdt_ptr[PROC_OFFSET_CPUID2] = i;
+ ssdt_ptr += PROC_SIZEOF;
}
// build "Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}"
// Arg0 = Processor ID = APIC ID
- *(ssdt_ptr++) = 0x14; // MethodOp
- ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*acpi_cpus), 2);
- *(ssdt_ptr++) = 'N';
- *(ssdt_ptr++) = 'T';
- *(ssdt_ptr++) = 'F';
- *(ssdt_ptr++) = 'Y';
- *(ssdt_ptr++) = 0x02;
- for (i=0; i<acpi_cpus; i++) {
- *(ssdt_ptr++) = 0xA0; // IfOp
- ssdt_ptr = encodeLen(ssdt_ptr, 11, 1);
- *(ssdt_ptr++) = 0x93; // LEqualOp
- *(ssdt_ptr++) = 0x68; // Arg0Op
- *(ssdt_ptr++) = 0x0A; // BytePrefix
- *(ssdt_ptr++) = i;
- *(ssdt_ptr++) = 0x86; // NotifyOp
- *(ssdt_ptr++) = 'C';
- *(ssdt_ptr++) = 'P';
- *(ssdt_ptr++) = getHex(i >> 4);
- *(ssdt_ptr++) = getHex(i);
- *(ssdt_ptr++) = 0x69; // Arg1Op
- }
+ ssdt_ptr = build_notify(ssdt_ptr, "NTFY", 0, acpi_cpus, "CP00", 2);
// build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
*(ssdt_ptr++) = 0x08; // NameOp
@@ -505,66 +567,28 @@ build_ssdt(void)
*(u32*)ssdt_ptr = sizeof(struct bfld);
ssdt_ptr += 4;
- build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
-
- //hexdump(ssdt, ssdt_ptr - ssdt);
-
- return ssdt;
-}
-
-#include "ssdt-pcihp.hex"
-
-#define PCI_RMV_BASE 0xae0c
-
-extern void link_time_assertion(void);
-
-static void* build_pcihp(void)
-{
- char *sys_states;
- int sys_state_size;
- u32 rmvc_pcrm;
- int i;
-
- u8 *ssdt = malloc_high(sizeof ssdp_pcihp_aml);
- if (!ssdt) {
- warn_noalloc();
- return NULL;
+ // build Scope(PCI0) opcode
+ *(ssdt_ptr++) = 0x10; // ScopeOp
+ ssdt_ptr = encodeLen(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
+ *(ssdt_ptr++) = 'P';
+ *(ssdt_ptr++) = 'C';
+ *(ssdt_ptr++) = 'I';
+ *(ssdt_ptr++) = '0';
+
+ // build Device object for each slot
+ u32 rmvc_pcrm = inl(PCI_RMV_BASE);
+ for (i=1; i<PCI_SLOTS; i++) {
+ u32 eject = rmvc_pcrm & (0x1 << i);
+ memcpy(ssdt_ptr, PCIHP_AML, PCIHP_SIZEOF);
+ patch_pcihp(i, ssdt_ptr, eject != 0);
+ ssdt_ptr += PCIHP_SIZEOF;
}
- memcpy(ssdt, ssdp_pcihp_aml, sizeof ssdp_pcihp_aml);
- /* Runtime patching of EJ0: to disable hotplug for a slot,
- * replace the method name: _EJ0 by EJ0_. */
- if (ARRAY_SIZE(aml_ej0_name) != ARRAY_SIZE(aml_adr_dword)) {
- link_time_assertion();
- }
+ ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOTS, "S00_", 1);
- rmvc_pcrm = inl(PCI_RMV_BASE);
- for (i = 0; i < ARRAY_SIZE(aml_ej0_name); ++i) {
- /* Slot is in byte 2 in _ADR */
- u8 slot = ssdp_pcihp_aml[aml_adr_dword[i] + 2] & 0x1F;
- /* Sanity check */
- if (memcmp(ssdp_pcihp_aml + aml_ej0_name[i], "_EJ0", 4)) {
- warn_internalerror();
- free(ssdt);
- return NULL;
- }
- if (!(rmvc_pcrm & (0x1 << slot))) {
- memcpy(ssdt + aml_ej0_name[i], "EJ0_", 4);
- }
- }
-
- sys_states = romfile_loadfile("etc/system-states", &sys_state_size);
- if (!sys_states || sys_state_size != 6)
- sys_states = (char[]){128, 0, 0, 129, 128, 128};
+ build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
- if (!(sys_states[3] & 128))
- ssdt[acpi_s3_name[0]] = 'X';
- if (!(sys_states[4] & 128))
- ssdt[acpi_s4_name[0]] = 'X';
- else
- ssdt[acpi_s4_pkg[0] + 1] = ssdt[acpi_s4_pkg[0] + 3] = sys_states[4] & 127;
- ((struct acpi_table_header*)ssdt)->checksum = 0;
- ((struct acpi_table_header*)ssdt)->checksum -= checksum(ssdt, sizeof(ssdp_pcihp_aml));
+ //hexdump(ssdt, ssdt_ptr - ssdt);
return ssdt;
}
@@ -750,7 +774,6 @@ acpi_bios_init(void)
ACPI_INIT_TABLE(build_madt());
ACPI_INIT_TABLE(build_hpet());
ACPI_INIT_TABLE(build_srat());
- ACPI_INIT_TABLE(build_pcihp());
u16 i, external_tables = qemu_cfg_acpi_additional_tables();
diff --git a/roms/seabios/src/ata.c b/roms/seabios/src/ata.c
index 7ff5f86c5..f604b3726 100644
--- a/roms/seabios/src/ata.c
+++ b/roms/seabios/src/ata.c
@@ -8,6 +8,7 @@
#include "types.h" // u8
#include "ioport.h" // inb
#include "util.h" // dprintf
+#include "byteorder.h" // be16_to_cpu
#include "cmos.h" // inb_cmos
#include "pic.h" // enable_hwirq
#include "biosvar.h" // GET_GLOBAL
@@ -696,7 +697,7 @@ ata_extract_model(char *model, u32 size, u16 *buffer)
// Read model name
int i;
for (i=0; i<size/2; i++)
- *(u16*)&model[i*2] = ntohs(buffer[27+i]);
+ *(u16*)&model[i*2] = be16_to_cpu(buffer[27+i]);
model[size] = 0x00;
nullTrailingSpace(model);
return model;
diff --git a/roms/seabios/src/block.c b/roms/seabios/src/block.c
index 1c200ccaf..cfe5c33c4 100644
--- a/roms/seabios/src/block.c
+++ b/roms/seabios/src/block.c
@@ -335,6 +335,8 @@ process_op(struct disk_op_s *op)
case DTYPE_UAS:
case DTYPE_VIRTIO_SCSI:
case DTYPE_LSI_SCSI:
+ case DTYPE_ESP_SCSI:
+ case DTYPE_MEGASAS:
return process_scsi_op(op);
default:
op->count = 0;
diff --git a/roms/seabios/src/blockcmd.c b/roms/seabios/src/blockcmd.c
index 43656500e..81b191be6 100644
--- a/roms/seabios/src/blockcmd.c
+++ b/roms/seabios/src/blockcmd.c
@@ -6,7 +6,8 @@
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "biosvar.h" // GET_GLOBAL
-#include "util.h" // htonl
+#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
#include "disk.h" // struct disk_op_s
#include "blockcmd.h" // struct cdb_request_sense
#include "ata.h" // atapi_cmd_data
@@ -15,6 +16,8 @@
#include "usb-uas.h" // usb_cmd_data
#include "virtio-scsi.h" // virtio_scsi_cmd_data
#include "lsi-scsi.h" // lsi_scsi_cmd_data
+#include "esp-scsi.h" // esp_scsi_cmd_data
+#include "megasas.h" // megasas_cmd_data
#include "boot.h" // boot_add_hd
// Route command to low-level handler.
@@ -35,6 +38,10 @@ cdb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
return virtio_scsi_cmd_data(op, cdbcmd, blocksize);
case DTYPE_LSI_SCSI:
return lsi_scsi_cmd_data(op, cdbcmd, blocksize);
+ case DTYPE_ESP_SCSI:
+ return esp_scsi_cmd_data(op, cdbcmd, blocksize);
+ case DTYPE_MEGASAS:
+ return megasas_cmd_data(op, cdbcmd, blocksize);
default:
op->count = 0;
return DISK_RET_EPARAM;
@@ -141,12 +148,12 @@ scsi_init_drive(struct drive_s *drive, const char *s, int prio)
// READ CAPACITY returns the address of the last block.
// We do not bother with READ CAPACITY(16) because BIOS does not support
// 64-bit LBA anyway.
- drive->blksize = ntohl(capdata.blksize);
+ drive->blksize = be32_to_cpu(capdata.blksize);
if (drive->blksize != DISK_SECTOR_SIZE) {
dprintf(1, "%s: unsupported block size %d\n", s, drive->blksize);
return -1;
}
- drive->sectors = (u64)ntohl(capdata.sectors) + 1;
+ drive->sectors = (u64)be32_to_cpu(capdata.sectors) + 1;
dprintf(1, "%s blksize=%d sectors=%d\n"
, s, drive->blksize, (unsigned)drive->sectors);
@@ -240,7 +247,7 @@ cdb_mode_sense_geom(struct disk_op_s *op, struct cdbres_mode_sense_geom *data)
cmd.command = CDB_CMD_MODE_SENSE;
cmd.flags = 8; /* DBD */
cmd.page = MODE_PAGE_HD_GEOMETRY;
- cmd.count = htons(sizeof(*data));
+ cmd.count = cpu_to_be16(sizeof(*data));
op->count = 1;
op->buf_fl = data;
return cdb_cmd_data(op, &cmd, sizeof(*data));
@@ -253,8 +260,8 @@ cdb_read(struct disk_op_s *op)
struct cdb_rwdata_10 cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.command = CDB_CMD_READ_10;
- cmd.lba = htonl(op->lba);
- cmd.count = htons(op->count);
+ cmd.lba = cpu_to_be32(op->lba);
+ cmd.count = cpu_to_be16(op->count);
return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
}
@@ -265,7 +272,7 @@ cdb_write(struct disk_op_s *op)
struct cdb_rwdata_10 cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.command = CDB_CMD_WRITE_10;
- cmd.lba = htonl(op->lba);
- cmd.count = htons(op->count);
+ cmd.lba = cpu_to_be32(op->lba);
+ cmd.count = cpu_to_be16(op->count);
return cdb_cmd_data(op, &cmd, GET_GLOBAL(op->drive_g->blksize));
}
diff --git a/roms/seabios/src/bootsplash.c b/roms/seabios/src/bootsplash.c
index a85e2b2ec..78023a594 100644
--- a/roms/seabios/src/bootsplash.c
+++ b/roms/seabios/src/bootsplash.c
@@ -11,7 +11,8 @@
#include "util.h" // dprintf
#include "jpeg.h" // splash
#include "vbe.h" // struct vbe_info
-#include "bmp.h"
+#include "bmp.h" // bmp_alloc
+
/****************************************************************
* Helper functions
@@ -63,7 +64,7 @@ find_videomode(struct vbe_info *vesa_info, struct vbe_mode_info *mode_info
struct bregs br;
memset(&br, 0, sizeof(br));
br.ax = 0x4f01;
- br.cx = (1 << 14) | videomode;
+ br.cx = videomode;
br.di = FLATPTR_TO_OFFSET(mode_info);
br.es = FLATPTR_TO_SEG(mode_info);
call16_int10(&br);
@@ -216,7 +217,7 @@ enable_bootsplash(void)
dprintf(5, "Switching to graphics mode\n");
memset(&br, 0, sizeof(br));
br.ax = 0x4f02;
- br.bx = (1 << 14) | videomode;
+ br.bx = videomode | VBE_MODE_LINEAR_FRAME_BUFFER;
call16_int10(&br);
if (br.ax != 0x4f) {
dprintf(1, "set_mode failed.\n");
diff --git a/roms/seabios/src/byteorder.h b/roms/seabios/src/byteorder.h
new file mode 100644
index 000000000..5a8a64a74
--- /dev/null
+++ b/roms/seabios/src/byteorder.h
@@ -0,0 +1,69 @@
+#ifndef __BYTEORDER_H
+#define __BYTEORDER_H
+
+static inline u16 __swab16_constant(u16 val) {
+ return (val<<8) | (val>>8);
+}
+static inline u32 __swab32_constant(u32 val) {
+ return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24);
+}
+static inline u64 __swab64_constant(u64 val) {
+ return ((u64)__swab32_constant(val) << 32) | __swab32_constant(val>>32);
+}
+static inline u32 __swab32(u32 val) {
+ asm("bswapl %0" : "+r"(val));
+ return val;
+}
+static inline u64 __swab64(u64 val) {
+ union u64_u32_u i, o;
+ i.val = val;
+ o.lo = __swab32(i.hi);
+ o.hi = __swab32(i.lo);
+ return o.val;
+}
+
+#define swab16(x) __swab16_constant(x)
+#define swab32(x) (__builtin_constant_p((u32)(x)) \
+ ? __swab32_constant(x) : __swab32(x))
+#define swab64(x) (__builtin_constant_p((u64)(x)) \
+ ? __swab64_constant(x) : __swab64(x))
+
+static inline u16 cpu_to_le16(u16 x) {
+ return x;
+}
+static inline u32 cpu_to_le32(u32 x) {
+ return x;
+}
+static inline u64 cpu_to_le64(u64 x) {
+ return x;
+}
+static inline u16 le16_to_cpu(u16 x) {
+ return x;
+}
+static inline u32 le32_to_cpu(u32 x) {
+ return x;
+}
+static inline u32 le64_to_cpu(u64 x) {
+ return x;
+}
+
+static inline u16 cpu_to_be16(u16 x) {
+ return swab16(x);
+}
+static inline u32 cpu_to_be32(u32 x) {
+ return swab32(x);
+}
+static inline u64 cpu_to_be64(u64 x) {
+ return swab64(x);
+}
+static inline u16 be16_to_cpu(u16 x) {
+ return swab16(x);
+}
+static inline u32 be32_to_cpu(u32 x) {
+ return swab32(x);
+}
+static inline u32 be64_to_cpu(u64 x) {
+ return swab64(x);
+}
+
+#endif // byteorder.h
diff --git a/roms/seabios/src/clock.c b/roms/seabios/src/clock.c
index 69e9f178b..71b913e59 100644
--- a/roms/seabios/src/clock.c
+++ b/roms/seabios/src/clock.c
@@ -129,11 +129,42 @@ emulate_tsc(void)
return ret;
}
+u16 pmtimer_ioport VAR16VISIBLE;
+u32 pmtimer_wraps VARLOW;
+u32 pmtimer_last VARLOW;
+
+void pmtimer_init(u16 ioport, u32 khz)
+{
+ if (!CONFIG_PMTIMER)
+ return;
+ dprintf(1, "Using pmtimer, ioport 0x%x, freq %d kHz\n", ioport, khz);
+ SET_GLOBAL(pmtimer_ioport, ioport);
+ SET_GLOBAL(cpu_khz, khz);
+}
+
+static u64 pmtimer_get(void)
+{
+ u16 ioport = GET_GLOBAL(pmtimer_ioport);
+ u32 wraps = GET_LOW(pmtimer_wraps);
+ u32 pmtimer = inl(ioport) & 0xffffff;
+
+ if (pmtimer < GET_LOW(pmtimer_last)) {
+ wraps++;
+ SET_LOW(pmtimer_wraps, wraps);
+ }
+ SET_LOW(pmtimer_last, pmtimer);
+
+ dprintf(9, "pmtimer: %u:%u\n", wraps, pmtimer);
+ return (u64)wraps << 24 | pmtimer;
+}
+
static u64
get_tsc(void)
{
if (unlikely(GET_GLOBAL(no_tsc)))
return emulate_tsc();
+ if (CONFIG_PMTIMER && GET_GLOBAL(pmtimer_ioport))
+ return pmtimer_get();
return rdtscll();
}
diff --git a/roms/seabios/src/coreboot.c b/roms/seabios/src/coreboot.c
index 55590cef6..e4767f116 100644
--- a/roms/seabios/src/coreboot.c
+++ b/roms/seabios/src/coreboot.c
@@ -6,6 +6,7 @@
#include "memmap.h" // add_e820
#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
#include "lzmadecode.h" // LzmaDecode
#include "smbios.h" // smbios_init
#include "boot.h" // boot_add_cbfs
@@ -329,17 +330,17 @@ coreboot_cbfs_setup(void)
return;
struct cbfs_header *hdr = *(void **)CBFS_HEADPTR_ADDR;
- if (hdr->magic != htonl(CBFS_HEADER_MAGIC)) {
+ if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) {
dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n"
- , hdr, hdr->magic, htonl(CBFS_HEADER_MAGIC));
+ , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC));
return;
}
dprintf(1, "Found CBFS header at %p\n", hdr);
- struct cbfs_file *cfile = (void *)(0 - ntohl(hdr->romsize)
- + ntohl(hdr->offset));
+ struct cbfs_file *cfile = (void *)(0 - be32_to_cpu(hdr->romsize)
+ + be32_to_cpu(hdr->offset));
for (;;) {
- if (cfile < (struct cbfs_file *)(0xFFFFFFFF - ntohl(hdr->romsize)))
+ if (cfile < (struct cbfs_file *)(0xFFFFFFFF - be32_to_cpu(hdr->romsize)))
break;
u64 magic = cfile->magic;
if (magic != CBFS_FILE_MAGIC)
@@ -352,10 +353,10 @@ coreboot_cbfs_setup(void)
memset(file, 0, sizeof(*file));
strtcpy(file->name, cfile->filename, sizeof(file->name));
dprintf(3, "Found CBFS file: %s\n", file->name);
- file->size = file->rawsize = ntohl(cfile->len);
+ file->size = file->rawsize = be32_to_cpu(cfile->len);
file->id = (u32)cfile;
file->copy = cbfs_copyfile;
- file->data = (void*)cfile + ntohl(cfile->offset);
+ file->data = (void*)cfile + be32_to_cpu(cfile->offset);
int len = strlen(file->name);
if (len > 5 && strcmp(&file->name[len-5], ".lzma") == 0) {
// Using compression.
@@ -365,7 +366,7 @@ coreboot_cbfs_setup(void)
}
romfile_add(file);
- cfile = (void*)ALIGN((u32)file->data + file->size, ntohl(hdr->align));
+ cfile = (void*)ALIGN((u32)file->data + file->size, be32_to_cpu(hdr->align));
}
}
@@ -394,13 +395,13 @@ cbfs_run_payload(struct cbfs_file *file)
if (!CONFIG_COREBOOT || !CONFIG_COREBOOT_FLASH || !file)
return;
dprintf(1, "Run %s\n", file->filename);
- struct cbfs_payload *pay = (void*)file + ntohl(file->offset);
+ struct cbfs_payload *pay = (void*)file + be32_to_cpu(file->offset);
struct cbfs_payload_segment *seg = pay->segments;
for (;;) {
- void *src = (void*)pay + ntohl(seg->offset);
- void *dest = (void*)ntohl((u32)seg->load_addr);
- u32 src_len = ntohl(seg->len);
- u32 dest_len = ntohl(seg->mem_len);
+ void *src = (void*)pay + be32_to_cpu(seg->offset);
+ void *dest = (void*)(u32)be64_to_cpu(seg->load_addr);
+ u32 src_len = be32_to_cpu(seg->len);
+ u32 dest_len = be32_to_cpu(seg->mem_len);
switch (seg->type) {
case PAYLOAD_SEGMENT_BSS:
dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
@@ -415,12 +416,12 @@ cbfs_run_payload(struct cbfs_file *file)
default:
dprintf(3, "Segment %x %d@%p -> %d@%p\n"
, seg->type, src_len, src, dest_len, dest);
- if (seg->compression == htonl(CBFS_COMPRESS_NONE)) {
+ if (seg->compression == cpu_to_be32(CBFS_COMPRESS_NONE)) {
if (src_len > dest_len)
src_len = dest_len;
memcpy(dest, src, src_len);
} else if (CONFIG_LZMA
- && seg->compression == htonl(CBFS_COMPRESS_LZMA)) {
+ && seg->compression == cpu_to_be32(CBFS_COMPRESS_LZMA)) {
int ret = ulzma(dest, dest_len, src, src_len);
if (ret < 0)
return;
diff --git a/roms/seabios/src/disk.c b/roms/seabios/src/disk.c
index 8e1d3ec56..0291fe3e0 100644
--- a/roms/seabios/src/disk.c
+++ b/roms/seabios/src/disk.c
@@ -615,7 +615,7 @@ disk_1348(struct bregs *regs, struct drive_s *drive_g)
u8 sum = checksum_far(SEG_LOW, &DefaultDPTE, 15);
SET_LOW(DefaultDPTE.checksum, -sum);
} else {
- SET_FARVAR(seg, param_far->dpte.segoff, 0);
+ SET_FARVAR(seg, param_far->dpte.segoff, 0xffffffff);
bdf = GET_GLOBAL(drive_g->cntl_id);
}
diff --git a/roms/seabios/src/disk.h b/roms/seabios/src/disk.h
index 2b2511f90..21debec0f 100644
--- a/roms/seabios/src/disk.h
+++ b/roms/seabios/src/disk.h
@@ -234,6 +234,8 @@ struct drive_s {
#define DTYPE_USB 0x0a
#define DTYPE_UAS 0x0b
#define DTYPE_LSI_SCSI 0x0c
+#define DTYPE_ESP_SCSI 0x0d
+#define DTYPE_MEGASAS 0x0e
#define MAXDESCSIZE 80
diff --git a/roms/seabios/src/esp-scsi.c b/roms/seabios/src/esp-scsi.c
new file mode 100644
index 000000000..c43e55b3b
--- /dev/null
+++ b/roms/seabios/src/esp-scsi.c
@@ -0,0 +1,233 @@
+// AMD PCscsi boot support.
+//
+// Copyright (C) 2012 Red Hat Inc.
+//
+// Authors:
+// Paolo Bonzini <pbonzini@redhat.com>
+//
+// based on lsi-scsi.c which is written by:
+// Gerd Hoffman <kraxel@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_init_drive
+#include "disk.h"
+
+#define ESP_TCLO 0x00
+#define ESP_TCMID 0x04
+#define ESP_FIFO 0x08
+#define ESP_CMD 0x0c
+#define ESP_WBUSID 0x10
+#define ESP_TCHI 0x38
+
+#define ESP_RSTAT 0x10
+#define ESP_RINTR 0x14
+#define ESP_RFLAGS 0x1c
+
+#define ESP_DMA_CMD 0x40
+#define ESP_DMA_STC 0x44
+#define ESP_DMA_SPA 0x48
+#define ESP_DMA_WBC 0x4c
+#define ESP_DMA_WAC 0x50
+#define ESP_DMA_STAT 0x54
+#define ESP_DMA_SMDLA 0x58
+#define ESP_DMA_WMAC 0x58c
+
+#define ESP_CMD_DMA 0x80
+#define ESP_CMD_RESET 0x02
+#define ESP_CMD_TI 0x10
+#define ESP_CMD_ICCS 0x11
+#define ESP_CMD_SELATN 0x42
+
+#define ESP_STAT_DI 0x01
+#define ESP_STAT_CD 0x02
+#define ESP_STAT_MSG 0x04
+#define ESP_STAT_TC 0x10
+
+#define ESP_INTR_DC 0x20
+
+struct esp_lun_s {
+ struct drive_s drive;
+ struct pci_device *pci;
+ u32 iobase;
+ u8 target;
+ u8 lun;
+};
+
+static void
+esp_scsi_dma(u32 iobase, u32 buf, u32 len, int read)
+{
+ outb(len & 0xff, iobase + ESP_TCLO);
+ outb((len >> 8) & 0xff, iobase + ESP_TCMID);
+ outb((len >> 16) & 0xff, iobase + ESP_TCHI);
+ outl(buf, iobase + ESP_DMA_SPA);
+ outl(len, iobase + ESP_DMA_STC);
+ outb(read ? 0x83 : 0x03, iobase + ESP_DMA_CMD);
+}
+
+static int
+esp_scsi_cmd(struct esp_lun_s *llun, struct disk_op_s *op,
+ u8 *cdbcmd, u16 target, u16 lun, u16 blocksize)
+{
+ u32 iobase = GET_GLOBAL(llun->iobase);
+ int i, state;
+ u8 status;
+
+ outb(target, iobase + ESP_WBUSID);
+
+ /*
+ * We need to pass the LUN at the beginning of the command, and the FIFO
+ * is only 16 bytes, so we cannot support 16-byte CDBs. The alternative
+ * would be to use DMA for the 17-byte command too, which is quite
+ * overkill.
+ */
+ outb(lun, iobase + ESP_FIFO);
+ cdbcmd[1] &= 0x1f;
+ cdbcmd[1] |= lun << 5;
+ for (i = 0; i < 12; i++)
+ outb(cdbcmd[i], iobase + ESP_FIFO);
+ outb(ESP_CMD_SELATN, iobase + ESP_CMD);
+
+ for (state = 0;;) {
+ u8 stat = inb(iobase + ESP_RSTAT);
+
+ /* Detect disconnected device. */
+ if (state == 0 && (inb(iobase + ESP_RINTR) & ESP_INTR_DC)) {
+ return DISK_RET_ENOTREADY;
+ }
+
+ /* HBA reads command, clears CD, sets TC -> do DMA if needed. */
+ if (state == 0 && (stat & ESP_STAT_TC)) {
+ state++;
+ if (op->count && blocksize) {
+ /* Data phase. */
+ u32 count = (u32)op->count * blocksize;
+ esp_scsi_dma(iobase, (u32)op->buf_fl, count,
+ cdb_is_read(cdbcmd, blocksize));
+ outb(ESP_CMD_TI | ESP_CMD_DMA, iobase + ESP_CMD);
+ continue;
+ }
+ }
+
+ /* At end of DMA TC is set again -> complete command. */
+ if (state == 1 && (stat & ESP_STAT_TC)) {
+ state++;
+ outb(ESP_CMD_ICCS, iobase + ESP_CMD);
+ continue;
+ }
+
+ /* Finally read data from the message in phase. */
+ if (state == 2 && (stat & ESP_STAT_MSG)) {
+ state++;
+ status = inb(iobase + ESP_FIFO);
+ inb(iobase + ESP_FIFO);
+ break;
+ }
+ usleep(5);
+ }
+
+ if (status == 0) {
+ return DISK_RET_SUCCESS;
+ }
+
+ return DISK_RET_EBADTRACK;
+}
+
+int
+esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+ if (!CONFIG_ESP_SCSI)
+ return DISK_RET_EBADTRACK;
+
+ struct esp_lun_s *llun =
+ container_of(op->drive_g, struct esp_lun_s, drive);
+
+ return esp_scsi_cmd(llun, op, cdbcmd,
+ GET_GLOBAL(llun->target), GET_GLOBAL(llun->lun),
+ blocksize);
+}
+
+static int
+esp_scsi_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+{
+ struct esp_lun_s *llun = malloc_fseg(sizeof(*llun));
+ if (!llun) {
+ warn_noalloc();
+ return -1;
+ }
+ memset(llun, 0, sizeof(*llun));
+ llun->drive.type = DTYPE_ESP_SCSI;
+ llun->drive.cntl_id = pci->bdf;
+ llun->pci = pci;
+ llun->target = target;
+ llun->lun = lun;
+ llun->iobase = iobase;
+
+ char *name = znprintf(16, "esp %02x:%02x.%x %d:%d",
+ pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+ pci_bdf_to_fn(pci->bdf), target, lun);
+ int prio = bootprio_find_scsi_device(pci, target, lun);
+ int ret = scsi_init_drive(&llun->drive, name, prio);
+ free(name);
+ if (ret)
+ goto fail;
+ return 0;
+
+fail:
+ free(llun);
+ return -1;
+}
+
+static void
+esp_scsi_scan_target(struct pci_device *pci, u32 iobase, u8 target)
+{
+ esp_scsi_add_lun(pci, iobase, target, 0);
+}
+
+static void
+init_esp_scsi(struct pci_device *pci)
+{
+ u16 bdf = pci->bdf;
+ u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
+ & PCI_BASE_ADDRESS_IO_MASK;
+
+ dprintf(1, "found esp at %02x:%02x.%x, io @ %x\n",
+ pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+ pci_bdf_to_fn(bdf), iobase);
+
+ pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
+ // reset
+ outb(ESP_CMD_RESET, iobase + ESP_CMD);
+
+ int i;
+ for (i = 0; i <= 7; i++)
+ esp_scsi_scan_target(pci, iobase, i);
+
+ return;
+}
+
+void
+esp_scsi_setup(void)
+{
+ ASSERT32FLAT();
+ if (!CONFIG_ESP_SCSI)
+ return;
+
+ dprintf(3, "init esp\n");
+
+ struct pci_device *pci;
+ foreachpci(pci) {
+ if (pci->vendor != PCI_VENDOR_ID_AMD
+ || pci->device != PCI_DEVICE_ID_AMD_SCSI)
+ continue;
+ init_esp_scsi(pci);
+ }
+}
diff --git a/roms/seabios/src/esp-scsi.h b/roms/seabios/src/esp-scsi.h
new file mode 100644
index 000000000..dc555f395
--- /dev/null
+++ b/roms/seabios/src/esp-scsi.h
@@ -0,0 +1,8 @@
+#ifndef __ESP_SCSI_H
+#define __ESP_SCSI_H
+
+struct disk_op_s;
+int esp_scsi_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void esp_scsi_setup(void);
+
+#endif /* __ESP_SCSI_H */
diff --git a/roms/seabios/src/farptr.h b/roms/seabios/src/farptr.h
index 3a85c6b83..5b6c5c109 100644
--- a/roms/seabios/src/farptr.h
+++ b/roms/seabios/src/farptr.h
@@ -26,8 +26,8 @@ extern u16 __segment_FS, __segment_GS;
#define READ64_SEG(prefix, SEG, value, var) do { \
union u64_u32_u __value; \
union u64_u32_u *__r64_ptr = (union u64_u32_u *)&(var); \
- READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi); \
READ32_SEG(prefix, SEG, __value.lo, __r64_ptr->lo); \
+ READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi); \
*(u64*)&(value) = __value.val; \
} while (0)
#define WRITE8_SEG(prefix, SEG, var, value) \
@@ -44,8 +44,8 @@ extern u16 __segment_FS, __segment_GS;
union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \
typeof(var) __value_tmp = (value); \
__value.val = *(u64*)&__value_tmp; \
- WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi); \
WRITE32_SEG(prefix, SEG, __w64_ptr->lo, __value.lo); \
+ WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi); \
} while (0)
// Macros for automatically choosing the appropriate memory size
diff --git a/roms/seabios/src/lsi-scsi.c b/roms/seabios/src/lsi-scsi.c
index b70b3a5a6..f8d715b83 100644
--- a/roms/seabios/src/lsi-scsi.c
+++ b/roms/seabios/src/lsi-scsi.c
@@ -177,6 +177,8 @@ init_lsi_scsi(struct pci_device *pci)
u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0)
& PCI_BASE_ADDRESS_IO_MASK;
+ pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
+
dprintf(1, "found lsi53c895a at %02x:%02x.%x, io @ %x\n",
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
pci_bdf_to_fn(bdf), iobase);
diff --git a/roms/seabios/src/megasas.c b/roms/seabios/src/megasas.c
new file mode 100644
index 000000000..f710cd7a8
--- /dev/null
+++ b/roms/seabios/src/megasas.c
@@ -0,0 +1,399 @@
+// MegaRAID SAS boot support.
+//
+// Copyright (C) 2012 Hannes Reinecke, SUSE Linux Products GmbH
+//
+// Authors:
+// Hannes Reinecke <hare@suse.de>
+//
+// based on virtio-scsi.c which is written by:
+// Paolo Bonzini <pbonzini@redhat.com>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // foreachpci
+#include "config.h" // CONFIG_*
+#include "biosvar.h" // GET_GLOBAL
+#include "pci_ids.h" // PCI_DEVICE_ID_XXX
+#include "pci_regs.h" // PCI_VENDOR_ID
+#include "boot.h" // bootprio_find_scsi_device
+#include "blockcmd.h" // scsi_init_drive
+#include "disk.h"
+
+#define MFI_DB 0x0 // Doorbell
+#define MFI_OMSG0 0x18 // Outbound message 0
+#define MFI_IDB 0x20 // Inbound doorbell
+#define MFI_ODB 0x2c // Outbound doorbell
+#define MFI_IQP 0x40 // Inbound queue port
+#define MFI_OSP0 0xb0 // Outbound scratch pad0
+#define MFI_IQPL 0xc0 // Inbound queue port (low bytes)
+#define MFI_IQPH 0xc4 // Inbound queue port (high bytes)
+
+#define MFI_STATE_MASK 0xf0000000
+#define MFI_STATE_WAIT_HANDSHAKE 0x60000000
+#define MFI_STATE_BOOT_MESSAGE_PENDING 0x90000000
+#define MFI_STATE_READY 0xb0000000
+#define MFI_STATE_OPERATIONAL 0xc0000000
+#define MFI_STATE_FAULT 0xf0000000
+
+/* MFI Commands */
+typedef enum {
+ MFI_CMD_INIT = 0x00,
+ MFI_CMD_LD_READ,
+ MFI_CMD_LD_WRITE,
+ MFI_CMD_LD_SCSI_IO,
+ MFI_CMD_PD_SCSI_IO,
+ MFI_CMD_DCMD,
+ MFI_CMD_ABORT,
+ MFI_CMD_SMP,
+ MFI_CMD_STP
+} mfi_cmd_t;
+
+struct megasas_cmd_frame {
+ u8 cmd; /*00h */
+ u8 sense_len; /*01h */
+ u8 cmd_status; /*02h */
+ u8 scsi_status; /*03h */
+
+ u8 target_id; /*04h */
+ u8 lun; /*05h */
+ u8 cdb_len; /*06h */
+ u8 sge_count; /*07h */
+
+ u32 context; /*08h */
+ u32 context_64; /*0Ch */
+
+ u16 flags; /*10h */
+ u16 timeout; /*12h */
+ u32 data_xfer_len; /*14h */
+
+ union {
+ struct {
+ u32 opcode; /*18h */
+ u8 mbox[12]; /*1Ch */
+ u32 sgl_addr; /*28h */
+ u32 sgl_len; /*32h */
+ u32 pad; /*34h */
+ } dcmd;
+ struct {
+ u32 sense_buf_lo; /*18h */
+ u32 sense_buf_hi; /*1Ch */
+ u8 cdb[16]; /*20h */
+ u32 sgl_addr; /*30h */
+ u32 sgl_len; /*34h */
+ } pthru;
+ struct {
+ u8 pad[22]; /*18h */
+ } gen;
+ };
+} __attribute__ ((packed));
+
+struct mfi_ld_list_s {
+ u32 count;
+ u32 reserved_0;
+ struct {
+ u8 target;
+ u8 lun;
+ u16 seq;
+ u8 state;
+ u8 reserved_1[3];
+ u64 size;
+ } lds[64];
+} __attribute__ ((packed));
+
+#define MEGASAS_POLL_TIMEOUT 60000 // 60 seconds polling timeout
+
+struct megasas_lun_s {
+ struct drive_s drive;
+ struct pci_device *pci;
+ struct megasas_cmd_frame *frame;
+ u32 iobase;
+ u8 target;
+ u8 lun;
+};
+
+static int megasas_fire_cmd(u16 pci_id, u32 ioaddr,
+ struct megasas_cmd_frame *frame)
+{
+ u32 frame_addr = (u32)frame;
+ int frame_count = 1;
+ u8 cmd_state;
+ u64 end;
+
+ dprintf(2, "Frame 0x%x\n", frame_addr);
+ if (pci_id == PCI_DEVICE_ID_LSI_SAS2004 ||
+ pci_id == PCI_DEVICE_ID_LSI_SAS2008) {
+ outl(0, ioaddr + MFI_IQPH);
+ outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQPL);
+ } else if (pci_id == PCI_DEVICE_ID_DELL_PERC5 ||
+ pci_id == PCI_DEVICE_ID_LSI_SAS1064R ||
+ pci_id == PCI_DEVICE_ID_LSI_VERDE_ZCR) {
+ outl(frame_addr >> 3 | frame_count, ioaddr + MFI_IQP);
+ } else {
+ outl(frame_addr | frame_count << 1 | 1, ioaddr + MFI_IQP);
+ }
+
+ end = calc_future_tsc(MEGASAS_POLL_TIMEOUT);
+ do {
+ for (;;) {
+ cmd_state = GET_LOWFLAT(frame->cmd_status);
+ if (cmd_state != 0xff)
+ break;
+ if (check_tsc(end)) {
+ warn_timeout();
+ return -1;
+ }
+ yield();
+ }
+ } while (cmd_state == 0xff);
+
+ if (cmd_state == 0 || cmd_state == 0x2d)
+ return 0;
+ dprintf(1, "ERROR: Frame 0x%x, status 0x%x\n", frame_addr, cmd_state);
+ return -1;
+}
+
+int
+megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize)
+{
+ struct megasas_lun_s *mlun =
+ container_of(op->drive_g, struct megasas_lun_s, drive);
+ u8 *cdb = cdbcmd;
+ struct megasas_cmd_frame *frame = GET_GLOBAL(mlun->frame);
+ u16 pci_id = GET_GLOBAL(mlun->pci->device);
+ int i;
+
+ if (!CONFIG_MEGASAS)
+ return DISK_RET_EBADTRACK;
+
+ memset_fl(frame, 0, sizeof(*frame));
+ SET_LOWFLAT(frame->cmd, MFI_CMD_LD_SCSI_IO);
+ SET_LOWFLAT(frame->cmd_status, 0xFF);
+ SET_LOWFLAT(frame->target_id, GET_GLOBAL(mlun->target));
+ SET_LOWFLAT(frame->lun, GET_GLOBAL(mlun->lun));
+ SET_LOWFLAT(frame->flags, 0x0001);
+ SET_LOWFLAT(frame->data_xfer_len, op->count * blocksize);
+ SET_LOWFLAT(frame->cdb_len, 16);
+
+ for (i = 0; i < 16; i++) {
+ SET_LOWFLAT(frame->pthru.cdb[i], cdb[i]);
+ }
+ dprintf(2, "pthru cmd 0x%x count %d bs %d\n",
+ cdb[0], op->count, blocksize);
+
+ if (op->count) {
+ SET_LOWFLAT(frame->pthru.sgl_addr, (u32)op->buf_fl);
+ SET_LOWFLAT(frame->pthru.sgl_len, op->count * blocksize);
+ SET_LOWFLAT(frame->sge_count, 1);
+ }
+ SET_LOWFLAT(frame->context, (u32)frame);
+
+ if (megasas_fire_cmd(pci_id, GET_GLOBAL(mlun->iobase), frame) == 0)
+ return DISK_RET_SUCCESS;
+
+ dprintf(2, "pthru cmd 0x%x failed\n", cdb[0]);
+ return DISK_RET_EBADTRACK;
+}
+
+static int
+megasas_add_lun(struct pci_device *pci, u32 iobase, u8 target, u8 lun)
+{
+ struct megasas_lun_s *mlun = malloc_fseg(sizeof(*mlun));
+ char *name;
+ int prio, ret = 0;
+
+ if (!mlun) {
+ warn_noalloc();
+ return -1;
+ }
+ memset(mlun, 0, sizeof(*mlun));
+ mlun->drive.type = DTYPE_MEGASAS;
+ mlun->drive.cntl_id = pci->bdf;
+ mlun->pci = pci;
+ mlun->target = target;
+ mlun->lun = lun;
+ mlun->iobase = iobase;
+ mlun->frame = memalign_low(256, sizeof(struct megasas_cmd_frame));
+ if (!mlun->frame) {
+ warn_noalloc();
+ free(mlun);
+ return -1;
+ }
+ name = znprintf(36, "MegaRAID SAS (PCI %02x:%02x.%x) LD %d:%d",
+ pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf),
+ pci_bdf_to_fn(pci->bdf), target, lun);
+ prio = bootprio_find_scsi_device(pci, target, lun);
+ ret = scsi_init_drive(&mlun->drive, name, prio);
+ free(name);
+ if (ret) {
+ free(mlun->frame);
+ free(mlun);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static void megasas_scan_target(struct pci_device *pci, u32 iobase)
+{
+ struct mfi_ld_list_s ld_list;
+ struct megasas_cmd_frame *frame = memalign_tmp(256, sizeof(*frame));
+ int i;
+
+ memset(&ld_list, 0, sizeof(ld_list));
+ memset_fl(frame, 0, sizeof(*frame));
+
+ frame->cmd = MFI_CMD_DCMD;
+ frame->cmd_status = 0xFF;
+ frame->sge_count = 1;
+ frame->flags = 0x0011;
+ frame->data_xfer_len = sizeof(ld_list);
+ frame->dcmd.opcode = 0x03010000;
+ frame->dcmd.sgl_addr = (u32)MAKE_FLATPTR(GET_SEG(SS), &ld_list);
+ frame->dcmd.sgl_len = sizeof(ld_list);
+ frame->context = (u32)frame;
+
+ if (megasas_fire_cmd(pci->device, iobase, frame) == 0) {
+ dprintf(2, "%d LD found\n", ld_list.count);
+ for (i = 0; i < ld_list.count; i++) {
+ dprintf(2, "LD %d:%d state 0x%x\n",
+ ld_list.lds[i].target, ld_list.lds[i].lun,
+ ld_list.lds[i].state);
+ if (ld_list.lds[i].state != 0) {
+ megasas_add_lun(pci, iobase,
+ ld_list.lds[i].target, ld_list.lds[i].lun);
+ }
+ }
+ }
+}
+
+static int megasas_transition_to_ready(struct pci_device *pci, u32 ioaddr)
+{
+ u32 fw_state = 0, new_state, mfi_flags = 0;
+ u64 end;
+
+ if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
+ pci->device == PCI_DEVICE_ID_DELL_PERC5)
+ new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
+ else
+ new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
+
+ while (fw_state != new_state) {
+ switch (new_state) {
+ case MFI_STATE_FAULT:
+ dprintf(1, "ERROR: fw in fault state\n");
+ return -1;
+ break;
+ case MFI_STATE_WAIT_HANDSHAKE:
+ mfi_flags = 0x08;
+ /* fallthrough */
+ case MFI_STATE_BOOT_MESSAGE_PENDING:
+ mfi_flags |= 0x10;
+ if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+ outl(ioaddr + MFI_DB, mfi_flags);
+ } else {
+ outl(ioaddr + MFI_IDB, mfi_flags);
+ }
+ break;
+ case MFI_STATE_OPERATIONAL:
+ mfi_flags = 0x07;
+ if (pci->device == PCI_DEVICE_ID_LSI_SAS2004 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS2008 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+ outl(ioaddr + MFI_DB, mfi_flags);
+ if (pci->device == PCI_DEVICE_ID_LSI_SAS2208 ||
+ pci->device == PCI_DEVICE_ID_LSI_SAS3108) {
+ int j = 0;
+ u32 doorbell;
+
+ while (j < MEGASAS_POLL_TIMEOUT) {
+ doorbell = inl(ioaddr + MFI_DB) & 1;
+ if (!doorbell)
+ break;
+ msleep(20);
+ j++;
+ }
+ }
+ } else {
+ outw(ioaddr + MFI_IDB, mfi_flags);
+ }
+ break;
+ case MFI_STATE_READY:
+ dprintf(2, "MegaRAID SAS fw ready\n");
+ return 0;
+ }
+ // The current state should not last longer than poll timeout
+ end = calc_future_tsc(MEGASAS_POLL_TIMEOUT);
+ for (;;) {
+ if (check_tsc(end)) {
+ break;
+ }
+ yield();
+ fw_state = new_state;
+ if (pci->device == PCI_DEVICE_ID_LSI_SAS1064R ||
+ pci->device == PCI_DEVICE_ID_DELL_PERC5)
+ new_state = inl(ioaddr + MFI_OMSG0) & MFI_STATE_MASK;
+ else
+ new_state = inl(ioaddr + MFI_OSP0) & MFI_STATE_MASK;
+ if (new_state != fw_state) {
+ break;
+ }
+ }
+ }
+ dprintf(1, "ERROR: fw in state %x\n", new_state & MFI_STATE_MASK);
+ return -1;
+}
+
+static void
+init_megasas(struct pci_device *pci)
+{
+ u16 bdf = pci->bdf;
+ u32 iobase = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_2)
+ & PCI_BASE_ADDRESS_IO_MASK;
+
+ dprintf(1, "found MegaRAID SAS at %02x:%02x.%x, io @ %x\n",
+ pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf),
+ pci_bdf_to_fn(bdf), iobase);
+
+ pci_config_maskw(pci->bdf, PCI_COMMAND, 0,
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+ // reset
+ if (megasas_transition_to_ready(pci, iobase) == 0)
+ megasas_scan_target(pci, iobase);
+
+ return;
+}
+
+void
+megasas_setup(void)
+{
+ ASSERT32FLAT();
+ if (!CONFIG_MEGASAS)
+ return;
+
+ dprintf(3, "init megasas\n");
+
+ struct pci_device *pci;
+ foreachpci(pci) {
+ if (pci->vendor != PCI_VENDOR_ID_LSI_LOGIC &&
+ pci->vendor != PCI_VENDOR_ID_DELL)
+ continue;
+ if (pci->device != PCI_DEVICE_ID_LSI_SAS1064R ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS1078 ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS1078DE ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS2108 ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS2108E ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS2004 ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS2008 ||
+ pci->device != PCI_DEVICE_ID_LSI_VERDE_ZCR ||
+ pci->device != PCI_DEVICE_ID_DELL_PERC5 ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS2208 ||
+ pci->device != PCI_DEVICE_ID_LSI_SAS3108)
+ continue;
+ init_megasas(pci);
+ }
+}
diff --git a/roms/seabios/src/megasas.h b/roms/seabios/src/megasas.h
new file mode 100644
index 000000000..124042e1c
--- /dev/null
+++ b/roms/seabios/src/megasas.h
@@ -0,0 +1,8 @@
+#ifndef __MEGASAS_H
+#define __MEGASAS_H
+
+struct disk_op_s;
+int megasas_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize);
+void megasas_setup(void);
+
+#endif /* __MEGASAS_H */
diff --git a/roms/seabios/src/paravirt.c b/roms/seabios/src/paravirt.c
index 2a98d53ed..4b5c4417d 100644
--- a/roms/seabios/src/paravirt.c
+++ b/roms/seabios/src/paravirt.c
@@ -8,7 +8,8 @@
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "config.h" // CONFIG_COREBOOT
-#include "util.h" // ntoh[ls]
+#include "util.h" // dprintf
+#include "byteorder.h" // be32_to_cpu
#include "ioport.h" // outw
#include "paravirt.h" // qemu_cfg_port_probe
#include "smbios.h" // struct smbios_structure_header
@@ -327,7 +328,7 @@ void qemu_cfg_romfile_setup(void)
u32 count;
qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
- count = ntohl(count);
+ count = be32_to_cpu(count);
u32 e;
for (e = 0; e < count; e++) {
struct QemuCfgFile qfile;
@@ -339,8 +340,8 @@ void qemu_cfg_romfile_setup(void)
}
memset(file, 0, sizeof(*file));
strtcpy(file->name, qfile.name, sizeof(file->name));
- file->size = ntohl(qfile.size);
- file->id = ntohs(qfile.select);
+ file->size = be32_to_cpu(qfile.size);
+ file->id = be16_to_cpu(qfile.select);
file->copy = qemu_cfg_read_file;
romfile_add(file);
dprintf(3, "Found fw_cfg file: %s (size=%d)\n", file->name, file->size);
diff --git a/roms/seabios/src/pci_ids.h b/roms/seabios/src/pci_ids.h
index 4b59585bc..665e94553 100644
--- a/roms/seabios/src/pci_ids.h
+++ b/roms/seabios/src/pci_ids.h
@@ -199,6 +199,7 @@
#define PCI_DEVICE_ID_LSI_63C815 0x1000
#define PCI_DEVICE_ID_LSI_SAS1064 0x0050
#define PCI_DEVICE_ID_LSI_SAS1064R 0x0411
+#define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413
#define PCI_DEVICE_ID_LSI_SAS1066 0x005E
#define PCI_DEVICE_ID_LSI_SAS1068 0x0054
#define PCI_DEVICE_ID_LSI_SAS1064A 0x005C
@@ -206,6 +207,13 @@
#define PCI_DEVICE_ID_LSI_SAS1066E 0x005A
#define PCI_DEVICE_ID_LSI_SAS1068E 0x0058
#define PCI_DEVICE_ID_LSI_SAS1078 0x0060
+#define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C
+#define PCI_DEVICE_ID_LSI_SAS2108E 0x0078
+#define PCI_DEVICE_ID_LSI_SAS2108 0x0079
+#define PCI_DEVICE_ID_LSI_SAS2208 0x005B
+#define PCI_DEVICE_ID_LSI_SAS3108 0x005D
+#define PCI_DEVICE_ID_LSI_SAS2004 0x0071
+#define PCI_DEVICE_ID_LSI_SAS2008 0x0073
#define PCI_VENDOR_ID_ATI 0x1002
/* Mach64 */
diff --git a/roms/seabios/src/pciinit.c b/roms/seabios/src/pciinit.c
index 68f302a2f..0e87ab0ba 100644
--- a/roms/seabios/src/pciinit.c
+++ b/roms/seabios/src/pciinit.c
@@ -119,16 +119,6 @@ static void piix_isa_bridge_init(struct pci_device *pci, void *arg)
dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]);
}
-static const struct pci_device_id pci_isa_bridge_tbl[] = {
- /* PIIX3/PIIX4 PCI to ISA bridge */
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
- piix_isa_bridge_init),
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
- piix_isa_bridge_init),
-
- PCI_DEVICE_END
-};
-
static void storage_ide_init(struct pci_device *pci, void *arg)
{
/* IDE: we map it as in ISA mode */
@@ -158,27 +148,8 @@ static void apple_macio_init(struct pci_device *pci, void *arg)
pci_set_io_region_addr(pci, 0, 0x80800000, 0);
}
-static const struct pci_device_id pci_class_tbl[] = {
- /* STORAGE IDE */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
- PCI_CLASS_STORAGE_IDE, piix_ide_init),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
- PCI_CLASS_STORAGE_IDE, piix_ide_init),
- PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
- storage_ide_init),
-
- /* PIC, IBM, MIPC & MPIC2 */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
- pic_ibm_init),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
- pic_ibm_init),
-
- /* 0xff00 */
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init),
- PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init),
-
- PCI_DEVICE_END,
-};
+/* PM Timer ticks per second (HZ) */
+#define PM_TIMER_FREQUENCY 3579545
/* PIIX4 Power Management device (for ACPI) */
static void piix4_pm_init(struct pci_device *pci, void *arg)
@@ -191,13 +162,39 @@ static void piix4_pm_init(struct pci_device *pci, void *arg)
pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
+
+ pmtimer_init(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000);
}
static const struct pci_device_id pci_device_tbl[] = {
+ /* PIIX3/PIIX4 PCI to ISA bridge */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0,
+ piix_isa_bridge_init),
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
+ piix_isa_bridge_init),
+
+ /* STORAGE IDE */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1,
+ PCI_CLASS_STORAGE_IDE, piix_ide_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
+ PCI_CLASS_STORAGE_IDE, piix_ide_init),
+ PCI_DEVICE_CLASS(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE,
+ storage_ide_init),
+
+ /* PIC, IBM, MIPC & MPIC2 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0x0046, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_IBM, 0xFFFF, PCI_CLASS_SYSTEM_PIC,
+ pic_ibm_init),
+
/* PIIX4 Power Management device (for ACPI) */
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
piix4_pm_init),
+ /* 0xff00 */
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0017, 0xff00, apple_macio_init),
+ PCI_DEVICE_CLASS(PCI_VENDOR_ID_APPLE, 0x0022, 0xff00, apple_macio_init),
+
PCI_DEVICE_END,
};
@@ -208,17 +205,15 @@ static void pci_bios_init_device(struct pci_device *pci)
, pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
, pci->vendor, pci->device);
- pci_init_device(pci_class_tbl, pci, NULL);
-
- /* enable memory mappings */
- pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
-
/* map the interrupt */
int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
if (pin != 0)
pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pci_slot_get_irq(pci, pin));
pci_init_device(pci_device_tbl, pci, NULL);
+
+ /* enable memory mappings */
+ pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
}
static void pci_bios_init_devices(void)
@@ -227,9 +222,32 @@ static void pci_bios_init_devices(void)
foreachpci(pci) {
pci_bios_init_device(pci);
}
+}
+
+
+/****************************************************************
+ * Platform device initialization
+ ****************************************************************/
+
+void i440fx_mem_addr_init(struct pci_device *dev, void *arg)
+{
+ if (RamSize <= 0x80000000)
+ pcimem_start = 0x80000000;
+ else if (RamSize <= 0xc0000000)
+ pcimem_start = 0xc0000000;
+}
+static const struct pci_device_id pci_platform_tbl[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441,
+ i440fx_mem_addr_init),
+ PCI_DEVICE_END
+};
+
+static void pci_bios_init_platform(void)
+{
+ struct pci_device *pci;
foreachpci(pci) {
- pci_init_device(pci_isa_bridge_tbl, pci, NULL);
+ pci_init_device(pci_platform_tbl, pci, NULL);
}
}
@@ -592,8 +610,6 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
static void pci_bios_map_devices(struct pci_bus *busses)
{
- pcimem_start = RamSize;
-
if (pci_bios_init_root_regions(busses)) {
struct pci_region r64_mem, r64_pref;
r64_mem.list = NULL;
@@ -656,6 +672,9 @@ pci_setup(void)
dprintf(1, "=== PCI device probing ===\n");
pci_probe_devices();
+ pcimem_start = RamSize;
+ pci_bios_init_platform();
+
dprintf(1, "=== PCI new allocation pass #1 ===\n");
struct pci_bus *busses = malloc_tmp(sizeof(*busses) * (MaxPCIBus + 1));
if (!busses) {
diff --git a/roms/seabios/src/post.c b/roms/seabios/src/post.c
index 0f31b4c35..0133f753e 100644
--- a/roms/seabios/src/post.c
+++ b/roms/seabios/src/post.c
@@ -28,7 +28,8 @@
#include "virtio-blk.h" // virtio_blk_setup
#include "virtio-scsi.h" // virtio_scsi_setup
#include "lsi-scsi.h" // lsi_scsi_setup
-
+#include "esp-scsi.h" // esp_scsi_setup
+#include "megasas.h" // megasas_setup
/****************************************************************
* BIOS init
@@ -196,6 +197,8 @@ init_hw(void)
virtio_blk_setup();
virtio_scsi_setup();
lsi_scsi_setup();
+ esp_scsi_setup();
+ megasas_setup();
}
// Begin the boot process by invoking an int0x19 in 16bit mode.
diff --git a/roms/seabios/src/smp.c b/roms/seabios/src/smp.c
index 3c36f8cf1..4975412f1 100644
--- a/roms/seabios/src/smp.c
+++ b/roms/seabios/src/smp.c
@@ -77,7 +77,7 @@ ASM16(
int apic_id_is_present(u8 apic_id)
{
- return FoundAPICIDs[apic_id/32] & (1 << (apic_id % 32));
+ return !!(FoundAPICIDs[apic_id/32] & (1ul << (apic_id % 32)));
}
// find and initialize the CPUs by launching a SIPI to them
diff --git a/roms/seabios/src/ssdt-pcihp.dsl b/roms/seabios/src/ssdt-pcihp.dsl
index 12555e23e..cd66b831b 100644
--- a/roms/seabios/src/ssdt-pcihp.dsl
+++ b/roms/seabios/src/ssdt-pcihp.dsl
@@ -12,123 +12,23 @@ DefinitionBlock ("ssdt-pcihp.aml", "SSDT", 0x01, "BXPC", "BXSSDTPCIHP", 0x1)
External (\_SB.PCI0.PCEJ, MethodObj)
Scope(\_SB.PCI0) {
+
/* Bulk generated PCI hotplug devices */
+ ACPI_EXTRACT_DEVICE_START ssdt_pcihp_start
+ ACPI_EXTRACT_DEVICE_END ssdt_pcihp_end
+ ACPI_EXTRACT_DEVICE_STRING ssdt_pcihp_name
+
// Method _EJ0 can be patched by BIOS to EJ0_
// at runtime, if the slot is detected to not support hotplug.
// Extract the offset of the address dword and the
// _EJ0 name to allow this patching.
-#define hotplug_slot(slot) \
- Device (S##slot) { \
- ACPI_EXTRACT_NAME_DWORD_CONST aml_adr_dword \
- Name (_ADR, 0x##slot##0000) \
- ACPI_EXTRACT_METHOD_STRING aml_ej0_name \
- Method (_EJ0, 1) { Return(PCEJ(0x##slot)) } \
- Name (_SUN, 0x##slot) \
- }
-
- hotplug_slot(01)
- hotplug_slot(02)
- hotplug_slot(03)
- hotplug_slot(04)
- hotplug_slot(05)
- hotplug_slot(06)
- hotplug_slot(07)
- hotplug_slot(08)
- hotplug_slot(09)
- hotplug_slot(0a)
- hotplug_slot(0b)
- hotplug_slot(0c)
- hotplug_slot(0d)
- hotplug_slot(0e)
- hotplug_slot(0f)
- hotplug_slot(10)
- hotplug_slot(11)
- hotplug_slot(12)
- hotplug_slot(13)
- hotplug_slot(14)
- hotplug_slot(15)
- hotplug_slot(16)
- hotplug_slot(17)
- hotplug_slot(18)
- hotplug_slot(19)
- hotplug_slot(1a)
- hotplug_slot(1b)
- hotplug_slot(1c)
- hotplug_slot(1d)
- hotplug_slot(1e)
- hotplug_slot(1f)
-
-#define gen_pci_hotplug(slot) \
- If (LEqual(Arg0, 0x##slot)) { Notify(S##slot, Arg1) }
-
- Method(PCNT, 2) {
- gen_pci_hotplug(01)
- gen_pci_hotplug(02)
- gen_pci_hotplug(03)
- gen_pci_hotplug(04)
- gen_pci_hotplug(05)
- gen_pci_hotplug(06)
- gen_pci_hotplug(07)
- gen_pci_hotplug(08)
- gen_pci_hotplug(09)
- gen_pci_hotplug(0a)
- gen_pci_hotplug(0b)
- gen_pci_hotplug(0c)
- gen_pci_hotplug(0d)
- gen_pci_hotplug(0e)
- gen_pci_hotplug(0f)
- gen_pci_hotplug(10)
- gen_pci_hotplug(11)
- gen_pci_hotplug(12)
- gen_pci_hotplug(13)
- gen_pci_hotplug(14)
- gen_pci_hotplug(15)
- gen_pci_hotplug(16)
- gen_pci_hotplug(17)
- gen_pci_hotplug(18)
- gen_pci_hotplug(19)
- gen_pci_hotplug(1a)
- gen_pci_hotplug(1b)
- gen_pci_hotplug(1c)
- gen_pci_hotplug(1d)
- gen_pci_hotplug(1e)
- gen_pci_hotplug(1f)
+ Device (SAA) {
+ ACPI_EXTRACT_NAME_BYTE_CONST ssdt_pcihp_id
+ Name (_SUN, 0xAA)
+ ACPI_EXTRACT_NAME_DWORD_CONST ssdt_pcihp_adr
+ Name (_ADR, 0xAA0000)
+ ACPI_EXTRACT_METHOD_STRING ssdt_pcihp_ej0
+ Method (_EJ0, 1) { Return(PCEJ(_SUN)) }
}
}
-
- Scope(\) {
-/****************************************************************
- * Suspend
- ****************************************************************/
-
- /*
- * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
- * must match piix4 emulation.
- */
-
- ACPI_EXTRACT_NAME_STRING acpi_s3_name
- Name (_S3, Package (0x04)
- {
- One, /* PM1a_CNT.SLP_TYP */
- One, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- ACPI_EXTRACT_NAME_STRING acpi_s4_name
- ACPI_EXTRACT_PKG_START acpi_s4_pkg
- Name (_S4, Package (0x04)
- {
- 0x2, /* PM1a_CNT.SLP_TYP */
- 0x2, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- Name (_S5, Package (0x04)
- {
- Zero, /* PM1a_CNT.SLP_TYP */
- Zero, /* PM1b_CNT.SLP_TYP */
- Zero, /* reserved */
- Zero /* reserved */
- })
- }
}
diff --git a/roms/seabios/src/ssdt-susp.dsl b/roms/seabios/src/ssdt-susp.dsl
new file mode 100644
index 000000000..0b3fa082e
--- /dev/null
+++ b/roms/seabios/src/ssdt-susp.dsl
@@ -0,0 +1,41 @@
+ACPI_EXTRACT_ALL_CODE ssdp_susp_aml
+
+DefinitionBlock ("ssdt-susp.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
+{
+
+/****************************************************************
+ * Suspend
+ ****************************************************************/
+
+ Scope(\) {
+ /*
+ * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
+ * must match piix4 emulation.
+ */
+
+ ACPI_EXTRACT_NAME_STRING acpi_s3_name
+ Name (_S3, Package (0x04)
+ {
+ One, /* PM1a_CNT.SLP_TYP */
+ One, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ ACPI_EXTRACT_NAME_STRING acpi_s4_name
+ ACPI_EXTRACT_PKG_START acpi_s4_pkg
+ Name (_S4, Package (0x04)
+ {
+ 0x2, /* PM1a_CNT.SLP_TYP */
+ 0x2, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ Name (_S5, Package (0x04)
+ {
+ Zero, /* PM1a_CNT.SLP_TYP */
+ Zero, /* PM1b_CNT.SLP_TYP */
+ Zero, /* reserved */
+ Zero /* reserved */
+ })
+ }
+}
diff --git a/roms/seabios/src/types.h b/roms/seabios/src/types.h
index b10f3b312..24b078e83 100644
--- a/roms/seabios/src/types.h
+++ b/roms/seabios/src/types.h
@@ -17,7 +17,7 @@ typedef signed long long s64;
typedef u32 size_t;
union u64_u32_u {
- struct { u32 hi, lo; };
+ struct { u32 lo, hi; };
u64 val;
};
diff --git a/roms/seabios/src/util.h b/roms/seabios/src/util.h
index 89e928c5f..7723bb17c 100644
--- a/roms/seabios/src/util.h
+++ b/roms/seabios/src/util.h
@@ -104,36 +104,6 @@ static inline u32 __fls(u32 word)
return word;
}
-static inline u16 __htons_constant(u16 val) {
- return (val<<8) | (val>>8);
-}
-static inline u32 __htonl_constant(u32 val) {
- return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24);
-}
-static inline u32 __htonl(u32 val) {
- asm("bswapl %0" : "+r"(val));
- return val;
-}
-#define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x))
-#define ntohl(x) htonl(x)
-#define htons(x) __htons_constant(x)
-#define ntohs(x) htons(x)
-
-static inline u16 cpu_to_le16(u16 x)
-{
- return x;
-}
-
-static inline u32 cpu_to_le32(u32 x)
-{
- return x;
-}
-
-static inline u32 le32_to_cpu(u32 x)
-{
- return x;
-}
-
static inline u32 getesp(void) {
u32 esp;
asm("movl %%esp, %0" : "=rm"(esp));
@@ -312,6 +282,7 @@ void lpt_setup(void);
// clock.c
#define PIT_TICK_RATE 1193180 // Underlying HZ of PIT
#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
+void pmtimer_init(u16 ioport, u32 khz);
int check_tsc(u64 end);
void timer_setup(void);
void ndelay(u32 count);
diff --git a/roms/seabios/tools/acpi_extract.py b/roms/seabios/tools/acpi_extract.py
index 167a322a3..329567885 100755
--- a/roms/seabios/tools/acpi_extract.py
+++ b/roms/seabios/tools/acpi_extract.py
@@ -93,7 +93,7 @@ def aml_pkglen(offset):
pkglenbytes = aml_pkglen_bytes(offset)
pkglen = aml[offset] & 0x3F
# If multibyte, first nibble only uses bits 0-3
- if ((pkglenbytes > 0) and (pkglen & 0x30)):
+ if ((pkglenbytes > 1) and (pkglen & 0x30)):
die("PkgLen bytes 0x%x but first nibble 0x%x expected 0x0X" %
(pkglen, pkglen))
offset += 1
@@ -164,6 +164,28 @@ def aml_name_word_const(offset):
def aml_name_byte_const(offset):
return aml_data_byte_const(aml_name_string(offset) + 4)
+def aml_device_start(offset):
+ #0x5B 0x82 DeviceOp PkgLength NameString
+ if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x82)):
+ die( "Name offset 0x%x: expected 0x5B 0x82 actual 0x%x 0x%x" %
+ (offset, aml[offset], aml[offset + 1]));
+ return offset
+
+def aml_device_string(offset):
+ #0x5B 0x82 DeviceOp PkgLength NameString
+ start = aml_device_start(offset)
+ offset += 2
+ pkglenbytes = aml_pkglen_bytes(offset)
+ offset += pkglenbytes
+ return offset
+
+def aml_device_end(offset):
+ start = aml_device_start(offset)
+ offset += 2
+ pkglenbytes = aml_pkglen_bytes(offset)
+ pkglen = aml_pkglen(offset)
+ return offset + pkglen
+
def aml_processor_start(offset):
#0x5B 0x83 ProcessorOp PkgLength NameString ProcID
if ((aml[offset] != 0x5B) or (aml[offset + 1] != 0x83)):
@@ -271,6 +293,12 @@ for i in range(len(asl)):
offset = aml_name_string(offset)
elif (directive == "ACPI_EXTRACT_METHOD_STRING"):
offset = aml_method_string(offset)
+ elif (directive == "ACPI_EXTRACT_DEVICE_START"):
+ offset = aml_device_start(offset)
+ elif (directive == "ACPI_EXTRACT_DEVICE_STRING"):
+ offset = aml_device_string(offset)
+ elif (directive == "ACPI_EXTRACT_DEVICE_END"):
+ offset = aml_device_end(offset)
elif (directive == "ACPI_EXTRACT_PROCESSOR_START"):
offset = aml_processor_start(offset)
elif (directive == "ACPI_EXTRACT_PROCESSOR_STRING"):
diff --git a/roms/seabios/vgasrc/Kconfig b/roms/seabios/vgasrc/Kconfig
index 6b22c3928..089a44790 100644
--- a/roms/seabios/vgasrc/Kconfig
+++ b/roms/seabios/vgasrc/Kconfig
@@ -43,6 +43,27 @@ menu "VGA ROM"
Build support for Geode LX vga.
endchoice
+ choice
+ depends on VGA_GEODEGX2 || VGA_GEODELX
+ prompt "Output Mode"
+ default VGA_OUTPUT_CRT
+
+ config VGA_OUTPUT_CRT
+ bool "CRT"
+ help
+ Use CRT for output.
+
+ config VGA_OUTPUT_PANEL
+ bool "Flat Panel"
+ help
+ Use flat panel for output.
+
+ config VGA_OUTPUT_CRT_PANEL
+ bool "CRT and Flat Panel"
+ help
+ Use CRT and flat panel for output.
+ endchoice
+
config BUILD_VGABIOS
bool
default !NO_VGABIOS
diff --git a/roms/seabios/vgasrc/bochsvga.c b/roms/seabios/vgasrc/bochsvga.c
index 2a8aeb186..938dba07c 100644
--- a/roms/seabios/vgasrc/bochsvga.c
+++ b/roms/seabios/vgasrc/bochsvga.c
@@ -364,6 +364,7 @@ bochsvga_init(void)
SET_VGA(VBE_framebuffer, lfb_addr);
u32 totalmem = dispi_read(VBE_DISPI_INDEX_VIDEO_MEMORY_64K) * 64 * 1024;
SET_VGA(VBE_total_memory, totalmem);
+ SET_VGA(VBE_win_granularity, 64);
SET_VGA(VBE_capabilities, VBE_CAPABILITY_8BIT_DAC);
dprintf(1, "VBE DISPI: lfb_addr=%x, size %d MB\n",
diff --git a/roms/seabios/vgasrc/geodevga.c b/roms/seabios/vgasrc/geodevga.c
index 5c6caf045..5b42e00ea 100644
--- a/roms/seabios/vgasrc/geodevga.c
+++ b/roms/seabios/vgasrc/geodevga.c
@@ -20,7 +20,7 @@
* MSR and High Mem access through VSA Virtual Register
****************************************************************/
-static union u64_u32_u geode_msrRead(u32 msrAddr)
+static u64 geode_msr_read(u32 msrAddr)
{
union u64_u32_u val;
asm __volatile__ (
@@ -33,11 +33,14 @@ static union u64_u32_u geode_msrRead(u32 msrAddr)
: "c"(msrAddr)
: "cc"
);
- return val;
+ return val.val;
}
-static void geode_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo)
+static void geode_msr_mask(u32 msrAddr, u64 off, u64 on)
{
+ union u64_u32_u uand, uor;
+ uand.val = ~off;
+ uor.val = on;
asm __volatile__ (
"push %%eax \n"
"movw $0x0AC1C, %%dx \n"
@@ -47,12 +50,12 @@ static void geode_msrWrite(u32 msrAddr,u32 andhi, u32 andlo, u32 orhi, u32 orlo)
"pop %%eax \n"
"outw %%ax, %%dx \n"
:
- : "c"(msrAddr), "S" (andhi), "D" (andlo), "b" (orhi), "a" (orlo)
+ : "c"(msrAddr), "S" (uand.hi), "D" (uand.lo), "b" (uor.hi), "a" (uor.lo)
: "%edx","cc"
);
}
-static u32 geode_memRead(u32 addr)
+static u32 geode_mem_read(u32 addr)
{
u32 val;
asm __volatile__ (
@@ -69,7 +72,7 @@ static u32 geode_memRead(u32 addr)
return val;
}
-static void geode_memWrite(u32 addr, u32 and, u32 or )
+static void geode_mem_mask(u32 addr, u32 off, u32 or)
{
asm __volatile__ (
"movw $0x0AC1C, %%dx \n"
@@ -78,167 +81,159 @@ static void geode_memWrite(u32 addr, u32 and, u32 or )
"addb $2, %%dl \n"
"outw %%ax, %%dx \n"
:
- : "b"(addr), "S" (and), "D" (or)
+ : "b"(addr), "S" (~off), "D" (or)
: "%eax","cc"
);
}
-static int legacyio_check(void)
-{
- int ret=0;
- union u64_u32_u val;
+#define VP_FP_START 0x400
- if (CONFIG_VGA_GEODEGX2)
- val=geode_msrRead(GLIU0_P2D_BM_4);
- else
- val=geode_msrRead(MSR_GLIU0_BASE4);
- if (val.lo != 0x0A0fffe0)
- ret|=1;
-
- val=geode_msrRead(GLIU0_IOD_BM_0);
- if (val.lo != 0x3c0ffff0)
- ret|=2;
+static u32 GeodeFB VAR16;
+static u32 GeodeDC VAR16;
+static u32 GeodeVP VAR16;
- val=geode_msrRead(GLIU0_IOD_BM_1);
- if (val.lo != 0x3d0ffff0)
- ret|=4;
-
- return ret;
+static u32 geode_dc_read(int reg)
+{
+ u32 val = geode_mem_read(GET_GLOBAL(GeodeDC) + reg);
+ dprintf(4, "%s(0x%08x) = 0x%08x\n"
+ , __func__, GET_GLOBAL(GeodeDC) + reg, val);
+ return val;
}
-/****************************************************************
-* Extened CRTC Register functions
-****************************************************************/
-static void crtce_lock(void)
+static void geode_dc_write(int reg, u32 val)
{
- stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
- , CRTCE_LOCK);
+ dprintf(4, "%s(0x%08x, 0x%08x)\n"
+ , __func__, GET_GLOBAL(GeodeDC) + reg, val);
+ geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, ~0, val);
}
-static void crtce_unlock(void)
+static void geode_dc_mask(int reg, u32 off, u32 on)
{
- stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, EXTENDED_REGISTER_LOCK
- , CRTCE_UNLOCK);
+ dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
+ , __func__, GET_GLOBAL(GeodeDC) + reg, off, on);
+ geode_mem_mask(GET_GLOBAL(GeodeDC) + reg, off, on);
}
-static u8 crtce_read(u8 reg)
+static u32 geode_vp_read(int reg)
{
- crtce_unlock();
- u8 val = stdvga_crtc_read(VGAREG_VGA_CRTC_ADDRESS, reg);
- crtce_lock();
+ u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + reg);
+ dprintf(4, "%s(0x%08x) = 0x%08x\n"
+ , __func__, GET_GLOBAL(GeodeVP) + reg, val);
return val;
}
-static void crtce_write(u8 reg, u8 val)
+static void geode_vp_write(int reg, u32 val)
{
- crtce_unlock();
- stdvga_crtc_write(VGAREG_VGA_CRTC_ADDRESS, reg, val);
- crtce_lock();
+ dprintf(4, "%s(0x%08x, 0x%08x)\n"
+ , __func__, GET_GLOBAL(GeodeVP) + reg, val);
+ geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, ~0, val);
}
-/****************************************************************
-* Display Controller Functions
-****************************************************************/
-static u32 dc_read(u16 seg, u32 reg)
+static void geode_vp_mask(int reg, u32 off, u32 on)
{
- u32 val, *dest_far = (void*)reg;
- val = GET_FARVAR(seg,*dest_far);
- return val;
+ dprintf(4, "%s(0x%08x, 0x%08x, 0x%08x)\n"
+ , __func__, GET_GLOBAL(GeodeVP) + reg, off, on);
+ geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, off, on);
}
-static void dc_write(u16 seg, u32 reg, u32 val)
+static u32 geode_fp_read(int reg)
{
- u32 *dest_far = (void*)reg;
- SET_FARVAR(seg,*dest_far,val);
+ u32 val = geode_mem_read(GET_GLOBAL(GeodeVP) + VP_FP_START + reg);
+ dprintf(4, "%s(0x%08x) = 0x%08x\n"
+ , __func__, GET_GLOBAL(GeodeVP) + reg, val);
+ return val;
}
-static void dc_set(u16 seg, u32 reg, u32 and, u32 or)
+static void geode_fp_write(int reg, u32 val)
{
- u32 val = dc_read(seg,reg);
- val &=and;
- val |=or;
- dc_write(seg,reg,val);
+ dprintf(4, "%s(0x%08x, 0x%08x)\n"
+ , __func__, GET_GLOBAL(GeodeVP) + VP_FP_START + reg, val);
+ geode_mem_mask(GET_GLOBAL(GeodeVP) + reg, ~0, val);
}
-static void dc_unlock(u16 seg)
-{
- dc_write(seg,DC_UNLOCK,DC_LOCK_UNLOCK);
-}
+/****************************************************************
+ * Helper functions
+ ****************************************************************/
-static void dc_lock(u16 seg)
+static int legacyio_check(void)
{
- dc_write(seg,DC_UNLOCK,DC_LOCK_LOCK);
-}
+ int ret=0;
+ u64 val;
-static u16 dc_map(u16 seg)
-{
- u8 reg;
-
- reg = crtce_read(EXTENDED_MODE_CONTROL);
- reg &= 0xf9;
- switch (seg) {
- case SEG_GRAPH:
- reg |= 0x02;
- break;
- case SEG_MTEXT:
- reg |= 0x04;
- break;
- case SEG_CTEXT:
- reg |= 0x06;
- break;
- default:
- seg=0;
- break;
- }
+ if (CONFIG_VGA_GEODEGX2)
+ val = geode_msr_read(GLIU0_P2D_BM_4);
+ else
+ val = geode_msr_read(MSR_GLIU0_BASE4);
+ if ((val & 0xffffffff) != 0x0A0fffe0)
+ ret|=1;
- crtce_write(EXTENDED_MODE_CONTROL,reg);
- return seg;
+ val = geode_msr_read(GLIU0_IOD_BM_0);
+ if ((val & 0xffffffff) != 0x3c0ffff0)
+ ret|=2;
+
+ val = geode_msr_read(GLIU0_IOD_BM_1);
+ if ((val & 0xffffffff) != 0x3d0ffff0)
+ ret|=4;
+
+ return ret;
}
-static void dc_unmap(void)
+static u32 framebuffer_size(void)
{
- dc_map(0);
+ /* We use the P2D_R0 msr to read out the number of pages.
+ * One page has a size of 4k
+ *
+ * Bit Name Description
+ * 39:20 PMAX Physical Memory Address Max
+ * 19:0 PMIX Physical Memory Address Min
+ *
+ */
+ u64 msr = geode_msr_read(GLIU0_P2D_RO);
+
+ u32 pmax = (msr >> 20) & 0x000fffff;
+ u32 pmin = msr & 0x000fffff;
+
+ u32 val = pmax - pmin;
+ val += 1;
+
+ /* The page size is 4k */
+ return (val << 12);
}
-
/****************************************************************
* Init Functions
****************************************************************/
/* Set up the dc (display controller) portion of the geodelx
-* The dc provides hardware support for VGA graphics
-* for features not accessible from the VGA registers,
-* the dc's pci bar can be mapped to a vga memory segment
+* The dc provides hardware support for VGA graphics.
*/
-static int dc_setup(void)
+static void dc_setup(void)
{
- u32 fb, dc_fb;
- u16 seg;
-
dprintf(2, "DC_SETUP\n");
- seg = dc_map(SEG_GRAPH);
- dc_unlock(seg);
+ geode_dc_write(DC_UNLOCK, DC_LOCK_UNLOCK);
/* zero memory config */
- dc_write(seg,DC_FB_ST_OFFSET,0x0);
- dc_write(seg,DC_CB_ST_OFFSET,0x0);
- dc_write(seg,DC_CURS_ST_OFFSET,0x0);
+ geode_dc_write(DC_FB_ST_OFFSET, 0x0);
+ geode_dc_write(DC_CB_ST_OFFSET, 0x0);
+ geode_dc_write(DC_CURS_ST_OFFSET, 0x0);
/* read fb-bar from pci, then point dc to the fb base */
- dc_fb = dc_read(seg,DC_GLIU0_MEM_OFFSET);
- fb = pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0);
- if (fb!=dc_fb) {
- dc_write(seg,DC_GLIU0_MEM_OFFSET,fb);
- }
+ u32 fb = GET_GLOBAL(GeodeFB);
+ if (geode_dc_read(DC_GLIU0_MEM_OFFSET) != fb)
+ geode_dc_write(DC_GLIU0_MEM_OFFSET, fb);
- dc_set(seg,DC_DISPLAY_CFG,DC_CFG_MSK,DC_GDEN+DC_TRUP);
- dc_set(seg,DC_GENERAL_CFG,0,DC_VGAE);
+ geode_dc_mask(DC_DISPLAY_CFG, ~DC_CFG_MSK, DC_DISPLAY_CFG_GDEN|DC_DISPLAY_CFG_TRUP);
+ geode_dc_write(DC_GENERAL_CFG, DC_DISPLAY_CFG_VGAE);
- dc_lock(seg);
- dc_unmap();
+ geode_dc_write(DC_UNLOCK, DC_LOCK_LOCK);
- return 0;
+ u32 fb_size = framebuffer_size(); // in byte
+ dprintf(1, "%d KB of video memory at 0x%08x\n", fb_size / 1024, fb);
+
+ /* update VBE variables */
+ SET_VGA(VBE_framebuffer, fb);
+ SET_VGA(VBE_total_memory, fb_size / 1024 / 64); // number of 64K blocks
}
/* Setup the vp (video processor) portion of the geodelx
@@ -247,38 +242,75 @@ static int dc_setup(void)
* The High Mem Access virtual register is used to configure the
* pci mmio bar from 16bit friendly io space.
*/
-int vp_setup(void)
+static void vp_setup(void)
{
- u32 reg,vp;
+ u32 msr_addr;
+ u64 msr;
dprintf(2,"VP_SETUP\n");
+
/* set output to crt and RGB/YUV */
if (CONFIG_VGA_GEODEGX2)
- geode_msrWrite(VP_MSR_CONFIG_GX2, ~0, ~0xf8, 0, 0);
+ msr_addr = VP_MSR_CONFIG_GX2;
else
- geode_msrWrite(VP_MSR_CONFIG_LX, ~0, ~0xf8, 0, 0);
+ msr_addr = VP_MSR_CONFIG_LX;
+
+ /* set output mode (RGB/YUV) */
+ msr = geode_msr_read(msr_addr);
+ msr &= ~VP_MSR_CONFIG_FMT; // mask out FMT (bits 5:3)
+
+ if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
+ msr |= VP_MSR_CONFIG_FMT_FP; // flat panel
+
+ if (CONFIG_VGA_OUTPUT_CRT_PANEL) {
+ msr |= VP_MSR_CONFIG_FPC; // simultaneous Flat Panel and CRT
+ dprintf(1, "output: simultaneous Flat Panel and CRT\n");
+ } else {
+ msr &= ~VP_MSR_CONFIG_FPC; // no simultaneous Flat Panel and CRT
+ dprintf(1, "ouput: flat panel\n");
+ }
+ } else {
+ msr |= VP_MSR_CONFIG_FMT_CRT; // CRT only
+ dprintf(1, "output: CRT\n");
+ }
+ geode_msr_mask(msr_addr, ~msr, msr);
- /* get vp register base from pci */
- vp = pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3);
/* Set mmio registers
* there may be some timing issues here, the reads seem
* to slow things down enough work reliably
*/
- reg = geode_memRead(vp+VP_MISC);
+ u32 reg = geode_vp_read(VP_MISC);
dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
- geode_memWrite(vp+VP_MISC,0,VP_BYP_BOTH);
- reg = geode_memRead(vp+VP_MISC);
+ geode_vp_write(VP_MISC, VP_DCFG_BYP_BOTH);
+ reg = geode_vp_read(VP_MISC);
dprintf(1,"VP_SETUP VP_MISC=0x%08x\n",reg);
- reg = geode_memRead(vp+VP_DCFG);
+ reg = geode_vp_read(VP_DCFG);
dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
- geode_memWrite(vp+VP_DCFG, ~0,VP_CRT_EN+VP_HSYNC_EN+VP_VSYNC_EN+VP_DAC_BL_EN+VP_CRT_SKEW);
- reg = geode_memRead(vp+VP_DCFG);
+ geode_vp_mask(VP_DCFG, 0, VP_DCFG_CRT_EN|VP_DCFG_HSYNC_EN|VP_DCFG_VSYNC_EN|VP_DCFG_DAC_BL_EN|VP_DCFG_CRT_SKEW);
+ reg = geode_vp_read(VP_DCFG);
dprintf(1,"VP_SETUP VP_DCFG=0x%08x\n",reg);
- return 0;
+ /* setup flat panel */
+ if (CONFIG_VGA_OUTPUT_PANEL || CONFIG_VGA_OUTPUT_CRT_PANEL) {
+ dprintf(1, "Setting up flat panel\n");
+ /* write timing register */
+ geode_fp_write(FP_PT1, 0x0);
+ geode_fp_write(FP_PT2, FP_PT2_SCRC);
+
+ /* set pad select for TFT/LVDS */
+ msr = VP_MSR_PADSEL_TFT_SEL_HIGH;
+ msr = msr << 32;
+ msr |= VP_MSR_PADSEL_TFT_SEL_LOW;
+ geode_msr_mask(VP_MSR_PADSEL, ~msr, msr);
+
+ /* turn the panel on (if it isn't already) */
+ reg = geode_fp_read(FP_PM);
+ reg |= FP_PM_P;
+ geode_fp_write(FP_PM, reg);
+ }
}
static u8 geode_crtc_01[] VAR16 = {
@@ -366,8 +398,18 @@ int geodevga_init(void)
if (GET_GLOBAL(VgaBDF) < 0)
// Device should be at 00:01.1
SET_VGA(VgaBDF, pci_to_bdf(0, 1, 1));
- ret |= vp_setup();
- ret |= dc_setup();
- return ret;
+ // setup geode struct which is used for register access
+ SET_VGA(GeodeFB, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_0));
+ SET_VGA(GeodeDC, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_2));
+ SET_VGA(GeodeVP, pci_config_readl(GET_GLOBAL(VgaBDF), PCI_BASE_ADDRESS_3));
+
+ dprintf(1, "fb addr: 0x%08x\n", GET_GLOBAL(GeodeFB));
+ dprintf(1, "dc addr: 0x%08x\n", GET_GLOBAL(GeodeDC));
+ dprintf(1, "vp addr: 0x%08x\n", GET_GLOBAL(GeodeVP));
+
+ vp_setup();
+ dc_setup();
+
+ return 0;
}
diff --git a/roms/seabios/vgasrc/geodevga.h b/roms/seabios/vgasrc/geodevga.h
index fd7ce432a..5993b23b4 100644
--- a/roms/seabios/vgasrc/geodevga.h
+++ b/roms/seabios/vgasrc/geodevga.h
@@ -13,13 +13,6 @@
#define VRC_DATA 0xAC1E // Data register
#define VR_UNLOCK 0xFC53 // Virtual register unlock code
-#define EXTENDED_REGISTER_LOCK 0x30
-#define EXTENDED_MODE_CONTROL 0x43
-#define EXTENDED_START_ADDR 0x44
-
-#define CRTCE_UNLOCK 0x4c
-#define CRTCE_LOCK 0xff
-
// Graphics-specific registers:
#define OEM_BAR0 0x50
#define OEM_BAR1 0x54
@@ -33,11 +26,23 @@
#define MSR_GLIU0 (1 << 28)
#define MSR_GLIU0_BASE4 (MSR_GLIU0 + 0x23) /* LX */
#define GLIU0_P2D_BM_4 (MSR_GLIU0 + 0x24) /* GX2 */
+#define GLIU0_P2D_RO (MSR_GLIU0 + 0x29)
#define GLIU0_IOD_BM_0 (MSR_GLIU0 + 0xE0)
#define GLIU0_IOD_BM_1 (MSR_GLIU0 + 0xE1)
#define DC_SPARE 0x80000011
#define VP_MSR_CONFIG_GX2 0xc0002001 /* GX2 */
#define VP_MSR_CONFIG_LX 0x48002001 /* LX */
+#define VP_MSR_PADSEL 0x48002011
+
+#define VP_MSR_PADSEL_TFT_SEL_LOW 0xDFFFFFFF
+#define VP_MSR_PADSEL_TFT_SEL_HIGH 0x0000003F
+
+/* VP_MSR_CONFIG bits */
+#define VP_MSR_CONFIG_FMT_CRT (0)
+#define VP_MSR_CONFIG_FMT_FP (1 << 3)
+#define VP_MSR_CONFIG_FPC (1 << 15)
+#define VP_MSR_CONFIG_FMT ((1 << 3) | (1 << 4) | (1 << 5))
+
/* DC REG OFFSET */
#define DC_UNLOCK 0x0
@@ -53,19 +58,28 @@
#define VP_DCFG 0x8
#define VP_MISC 0x50
+/* FP REG OFFSET */
+#define FP_PT1 0x00
+#define FP_PT2 0x08
+#define FP_PM 0x10
+
/* DC bits */
-#define DC_VGAE (1 << 7)
-#define DC_GDEN (1 << 3)
-#define DC_TRUP (1 << 6)
+#define DC_DISPLAY_CFG_VGAE (1 << 7)
+#define DC_DISPLAY_CFG_GDEN (1 << 3)
+#define DC_DISPLAY_CFG_TRUP (1 << 6)
/* VP bits */
-#define VP_CRT_EN (1 << 0)
-#define VP_HSYNC_EN (1 << 1)
-#define VP_VSYNC_EN (1 << 2)
-#define VP_DAC_BL_EN (1 << 3)
-#define VP_CRT_SKEW (1 << 16)
-#define VP_BYP_BOTH (1 << 0)
+#define VP_DCFG_CRT_EN (1 << 0)
+#define VP_DCFG_HSYNC_EN (1 << 1)
+#define VP_DCFG_VSYNC_EN (1 << 2)
+#define VP_DCFG_DAC_BL_EN (1 << 3)
+#define VP_DCFG_CRT_SKEW (1 << 16)
+#define VP_DCFG_BYP_BOTH (1 << 0)
+
+/* FP bits */
+#define FP_PM_P (1 << 24) /* panel power ctl */
+#define FP_PT2_SCRC (1 << 27) /* panel shift clock retrace activity ctl */
/* Mask */
#define DC_CFG_MSK 0xf000a6
diff --git a/roms/seabios/vgasrc/stdvgamodes.c b/roms/seabios/vgasrc/stdvgamodes.c
index 5497da8f6..1756adef0 100644
--- a/roms/seabios/vgasrc/stdvgamodes.c
+++ b/roms/seabios/vgasrc/stdvgamodes.c
@@ -334,6 +334,16 @@ stdvga_find_mode(int mode)
void
stdvga_list_modes(u16 seg, u16 *dest, u16 *last)
{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
+ struct stdvga_mode_s *stdmode_g = &vga_modes[i];
+ u16 mode = GET_GLOBAL(stdmode_g->mode);
+ if (mode == 0xffff)
+ continue;
+ SET_FARVAR(seg, *dest, mode);
+ dest++;
+ }
+
SET_FARVAR(seg, *dest, 0xffff);
}
diff --git a/roms/seabios/vgasrc/vbe.c b/roms/seabios/vgasrc/vbe.c
index 227a244a1..d962333bd 100644
--- a/roms/seabios/vgasrc/vbe.c
+++ b/roms/seabios/vgasrc/vbe.c
@@ -17,7 +17,7 @@
u32 VBE_total_memory VAR16 = 256 * 1024;
u32 VBE_capabilities VAR16;
u32 VBE_framebuffer VAR16;
-u16 VBE_win_granularity VAR16 = 64;
+u16 VBE_win_granularity VAR16;
static void
vbe_104f00(struct bregs *regs)
@@ -74,7 +74,7 @@ vbe_104f01(struct bregs *regs)
dprintf(1, "VBE mode info request: %x\n", mode);
- struct vgamode_s *vmode_g = vgahw_find_mode(mode);
+ struct vgamode_s *vmode_g = vgahw_find_mode(mode & ~MF_VBEFLAGS);
if (! vmode_g) {
dprintf(1, "VBE mode %x not found\n", mode);
regs->ax = 0x014f;
@@ -82,27 +82,22 @@ vbe_104f01(struct bregs *regs)
}
memset_far(seg, info, 0, sizeof(*info));
- u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED |
- VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE |
- VBE_MODE_ATTRIBUTE_COLOR_MODE |
- VBE_MODE_ATTRIBUTE_GRAPHICS_MODE |
- VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE;
- u32 framebuffer = GET_GLOBAL(VBE_framebuffer);
- if (framebuffer)
- mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE;
- SET_FARVAR(seg, info->mode_attributes, mode_attr);
+
+ // Basic information about video controller.
+ u32 win_granularity = GET_GLOBAL(VBE_win_granularity);
SET_FARVAR(seg, info->winA_attributes,
- VBE_WINDOW_ATTRIBUTE_RELOCATABLE |
+ (win_granularity ? VBE_WINDOW_ATTRIBUTE_RELOCATABLE : 0) |
VBE_WINDOW_ATTRIBUTE_READABLE |
VBE_WINDOW_ATTRIBUTE_WRITEABLE);
SET_FARVAR(seg, info->winB_attributes, 0);
- SET_FARVAR(seg, info->win_granularity, GET_GLOBAL(VBE_win_granularity));
+ SET_FARVAR(seg, info->win_granularity, win_granularity);
SET_FARVAR(seg, info->win_size, 64); /* Bank size 64K */
SET_FARVAR(seg, info->winA_seg, GET_GLOBAL(vmode_g->sstart));
SET_FARVAR(seg, info->winB_seg, 0x0);
extern void entry_104f05(void);
SET_FARVAR(seg, info->win_func_ptr
, SEGOFF(get_global_seg(), (u32)entry_104f05));
+ // Basic information about mode.
int width = GET_GLOBAL(vmode_g->width);
int height = GET_GLOBAL(vmode_g->height);
int linesize = DIV_ROUND_UP(width * vga_bpp(vmode_g), 8);
@@ -112,18 +107,50 @@ vbe_104f01(struct bregs *regs)
SET_FARVAR(seg, info->xcharsize, GET_GLOBAL(vmode_g->cwidth));
SET_FARVAR(seg, info->ycharsize, GET_GLOBAL(vmode_g->cheight));
int depth = GET_GLOBAL(vmode_g->depth);
- int planes = (depth == 4) ? 4 : 1;
- SET_FARVAR(seg, info->planes, planes);
SET_FARVAR(seg, info->bits_per_pixel, depth);
- SET_FARVAR(seg, info->banks, 1);
- SET_FARVAR(seg, info->mem_model, GET_GLOBAL(vmode_g->memmodel));
- SET_FARVAR(seg, info->bank_size, 0);
- u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024);
- SET_FARVAR(seg, info->pages, (pages / planes) - 1);
+ u8 memmodel = GET_GLOBAL(vmode_g->memmodel);
+ SET_FARVAR(seg, info->mem_model, memmodel);
SET_FARVAR(seg, info->reserved0, 1);
- u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos;
+ // Mode specific info.
+ u16 mode_attr = VBE_MODE_ATTRIBUTE_SUPPORTED |
+ VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE |
+ VBE_MODE_ATTRIBUTE_COLOR_MODE |
+ VBE_MODE_ATTRIBUTE_GRAPHICS_MODE |
+ VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE;
+ u32 framebuffer = 0;
+ int planes = 1, banks = 1;
+ u32 pages = GET_GLOBAL(VBE_total_memory) / ALIGN(height * linesize, 64*1024);
+ switch (memmodel) {
+ case MM_TEXT:
+ mode_attr &= ~VBE_MODE_ATTRIBUTE_GRAPHICS_MODE;
+ mode_attr |= VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT;
+ if (GET_GLOBAL(vmode_g->sstart) == SEG_MTEXT)
+ mode_attr &= ~VBE_MODE_ATTRIBUTE_COLOR_MODE;
+ pages = 1;
+ break;
+ case MM_CGA:
+ pages = 1;
+ banks = 2;
+ SET_FARVAR(seg, info->bank_size, 8);
+ break;
+ case MM_PLANAR:
+ planes = 4;
+ pages /= 4;
+ break;
+ default:
+ framebuffer = GET_GLOBAL(VBE_framebuffer);
+ if (framebuffer)
+ mode_attr |= VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE;
+ break;
+ }
+ SET_FARVAR(seg, info->mode_attributes, mode_attr);
+ SET_FARVAR(seg, info->planes, planes);
+ SET_FARVAR(seg, info->pages, pages - 1);
+ SET_FARVAR(seg, info->banks, banks);
+ // Pixel color breakdown
+ u8 r_size, r_pos, g_size, g_pos, b_size, b_pos, a_size, a_pos;
switch (depth) {
case 15: r_size = 5; r_pos = 10; g_size = 5; g_pos = 5;
b_size = 5; b_pos = 0; a_size = 1; a_pos = 15; break;
@@ -132,11 +159,13 @@ vbe_104f01(struct bregs *regs)
case 24: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
b_size = 8; b_pos = 0; a_size = 0; a_pos = 0; break;
case 32: r_size = 8; r_pos = 16; g_size = 8; g_pos = 8;
- b_size = 8; b_pos = 0; a_size = 8; a_pos = 24; break;
+ b_size = 8; b_pos = 0; a_size = 8; a_pos = 24;
+ SET_FARVAR(seg, info->directcolor_info,
+ VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE);
+ break;
default: r_size = 0; r_pos = 0; g_size = 0; g_pos = 0;
b_size = 0; b_pos = 0; a_size = 0; a_pos = 0; break;
}
-
SET_FARVAR(seg, info->red_size, r_size);
SET_FARVAR(seg, info->red_pos, r_pos);
SET_FARVAR(seg, info->green_size, g_size);
@@ -146,31 +175,23 @@ vbe_104f01(struct bregs *regs)
SET_FARVAR(seg, info->alpha_size, a_size);
SET_FARVAR(seg, info->alpha_pos, a_pos);
- if (depth == 32)
- SET_FARVAR(seg, info->directcolor_info,
- VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE);
- else
- SET_FARVAR(seg, info->directcolor_info, 0);
-
- if (depth > 4)
- SET_FARVAR(seg, info->phys_base, GET_GLOBAL(VBE_framebuffer));
- else
- SET_FARVAR(seg, info->phys_base, 0);
-
- SET_FARVAR(seg, info->reserved1, 0);
- SET_FARVAR(seg, info->reserved2, 0);
- SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize);
- SET_FARVAR(seg, info->bank_pages, 0);
- SET_FARVAR(seg, info->linear_pages, 0);
- SET_FARVAR(seg, info->linear_red_size, r_size);
- SET_FARVAR(seg, info->linear_red_pos, r_pos);
- SET_FARVAR(seg, info->linear_green_size, g_size);
- SET_FARVAR(seg, info->linear_green_pos, g_pos);
- SET_FARVAR(seg, info->linear_blue_size, b_size);
- SET_FARVAR(seg, info->linear_blue_pos, b_pos);
- SET_FARVAR(seg, info->linear_alpha_size, a_size);
- SET_FARVAR(seg, info->linear_alpha_pos, a_pos);
- SET_FARVAR(seg, info->pixclock_max, 0);
+ // Linear framebuffer info.
+ if (framebuffer) {
+ SET_FARVAR(seg, info->phys_base, framebuffer);
+
+ SET_FARVAR(seg, info->reserved1, 0);
+ SET_FARVAR(seg, info->reserved2, 0);
+ SET_FARVAR(seg, info->linear_bytes_per_scanline, linesize);
+ SET_FARVAR(seg, info->linear_pages, 0);
+ SET_FARVAR(seg, info->linear_red_size, r_size);
+ SET_FARVAR(seg, info->linear_red_pos, r_pos);
+ SET_FARVAR(seg, info->linear_green_size, g_size);
+ SET_FARVAR(seg, info->linear_green_pos, g_pos);
+ SET_FARVAR(seg, info->linear_blue_size, b_size);
+ SET_FARVAR(seg, info->linear_blue_pos, b_pos);
+ SET_FARVAR(seg, info->linear_alpha_size, a_size);
+ SET_FARVAR(seg, info->linear_alpha_pos, a_pos);
+ }
regs->ax = 0x004f;
}
diff --git a/roms/seabios/vgasrc/vgafb.c b/roms/seabios/vgasrc/vgafb.c
index 233f3d5fb..3b2f367fb 100644
--- a/roms/seabios/vgasrc/vgafb.c
+++ b/roms/seabios/vgasrc/vgafb.c
@@ -8,6 +8,7 @@
#include "vgabios.h" // vgafb_scroll
#include "biosvar.h" // GET_BDA
#include "util.h" // memset_far
+#include "byteorder.h" // cpu_to_be16
#include "stdvga.h" // stdvga_planar4_plane
@@ -272,7 +273,7 @@ write_gfx_char_cga(struct vgamode_s *vmode_g
for (j = 0; j < 8; j++)
if (fontline & (1<<j))
pixels |= (ca.attr & 0x03) << (j*2);
- pixels = htons(pixels);
+ pixels = cpu_to_be16(pixels);
if (ca.attr & 0x80)
pixels ^= GET_FARVAR(SEG_GRAPH, *(u16*)dest_far);
SET_FARVAR(SEG_CTEXT, *(u16*)dest_far, pixels);