diff options
author | Anas Nashif <anas.nashif@intel.com> | 2013-01-15 13:31:42 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2013-01-15 13:31:42 -0800 |
commit | 42bf3037d458a330856a0be584200c1e41c3f417 (patch) | |
tree | 25b9be1088727757e52271e25a446e8a852357df /roms | |
parent | 060629c6ef0b7e5c267d84c91600113264d33120 (diff) | |
download | qemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.gz qemu-42bf3037d458a330856a0be584200c1e41c3f417.tar.bz2 qemu-42bf3037d458a330856a0be584200c1e41c3f417.zip |
Imported Upstream version 1.3.0upstream/1.3.0
Diffstat (limited to 'roms')
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); |