diff --git a/.seabios.metadata b/.seabios.metadata new file mode 100644 index 0000000..0166abd --- /dev/null +++ b/.seabios.metadata @@ -0,0 +1 @@ +4d50b512c589fc7786d398fbc6e3935d4fa66530 SOURCES/seabios-1.7.2.2.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/Add-pvpanic-device-driver.patch b/SOURCES/Add-pvpanic-device-driver.patch new file mode 100644 index 0000000..85b58a2 --- /dev/null +++ b/SOURCES/Add-pvpanic-device-driver.patch @@ -0,0 +1,111 @@ +Add pvpanic device driver + +Message-id: <1370958628-888-1-git-send-email-lersek@redhat.com> +Patchwork-id: 51850 +O-Subject: [RHEL7 seabios PATCH] Add pvpanic device driver +Bugzilla: 967777 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Gerd Hoffmann + +From: Hu Tao + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=967777 +Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=5890930 +Testing: https://bugzilla.redhat.com/show_bug.cgi?id=967777#c3 + +pvpanic device is used to notify host(qemu) when guest panic happens. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Hu Tao +(cherry picked from commit e9725dd76d5d7212cb4a97fd18ff2599538955cf) + +Conflicts: + + src/acpi.c + +RHEL-7 note: + +Gerd already ported this patch to 1.7.2 (which is where RHEL-7 is at +currently). See +and for details. + +I cherry picked his port from , commit +5d01ca924a5c8fcd898ddc5813d88b3c32043882. Unfortunately this seems to +introduce a compile error. I fixed that up. + +Signed-off-by: Laszlo Ersek +--- + src/acpi.c | 4 ++++ + src/ssdt-susp.dsl | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 0 deletions(-) +diff --git a/src/acpi.c b/src/acpi.c +index 6267d7b..9b09118 100644 +--- a/src/acpi.c ++++ b/src/acpi.c +@@ -535,6 +535,10 @@ build_ssdt(void) + 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; ++ ++ int pvpanic_port = romfile_loadint("etc/pvpanic-port", 0x0); ++ *(u16 *)(ssdt_ptr + *ssdt_isa_pest) = pvpanic_port; ++ + ssdt_ptr += sizeof(ssdp_susp_aml); + + // build Scope(_SB_) header +diff --git a/src/ssdt-susp.dsl b/src/ssdt-susp.dsl +index ca9428f..b8e9cf4 100644 +--- a/src/ssdt-susp.dsl ++++ b/src/ssdt-susp.dsl +@@ -35,4 +35,50 @@ DefinitionBlock ("ssdt-susp.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1) + Zero /* reserved */ + }) + } ++ ++ External(\_SB.PCI0, DeviceObj) ++ External(\_SB.PCI0.ISA, DeviceObj) ++ ++ Scope(\_SB.PCI0.ISA) { ++ Device(PEVT) { ++ Name(_HID, "QEMU0001") ++ /* PEST will be patched to be Zero if no such device */ ++ ACPI_EXTRACT_NAME_WORD_CONST ssdt_isa_pest ++ Name(PEST, 0xFFFF) ++ OperationRegion(PEOR, SystemIO, PEST, 0x01) ++ Field(PEOR, ByteAcc, NoLock, Preserve) { ++ PEPT, 8, ++ } ++ ++ Method(_STA, 0, NotSerialized) { ++ Store(PEST, Local0) ++ If (LEqual(Local0, Zero)) { ++ Return (0x00) ++ } Else { ++ Return (0x0F) ++ } ++ } ++ ++ Method(RDPT, 0, NotSerialized) { ++ Store(PEPT, Local0) ++ Return (Local0) ++ } ++ ++ Method(WRPT, 1, NotSerialized) { ++ Store(Arg0, PEPT) ++ } ++ ++ Name(_CRS, ResourceTemplate() { ++ IO(Decode16, 0x00, 0x00, 0x01, 0x01, IO) ++ }) ++ ++ CreateWordField(_CRS, IO._MIN, IOMN) ++ CreateWordField(_CRS, IO._MAX, IOMX) ++ ++ Method(_INI, 0, NotSerialized) { ++ Store(PEST, IOMN) ++ Store(PEST, IOMX) ++ } ++ } ++ } + } diff --git a/SOURCES/config.base b/SOURCES/config.base new file mode 100644 index 0000000..7d8b9dd --- /dev/null +++ b/SOURCES/config.base @@ -0,0 +1,6 @@ +CONFIG_XEN=n +CONFIG_ESP_SCSI=n +CONFIG_LSI_SCSI=n +CONFIG_USB_OHCI=n +CONFIG_BOOTSPLASH=n +CONFIG_MEGASAS=n diff --git a/SOURCES/config.vga.cirrus b/SOURCES/config.vga.cirrus new file mode 100644 index 0000000..c8fe582 --- /dev/null +++ b/SOURCES/config.vga.cirrus @@ -0,0 +1,3 @@ +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_CIRRUS=y +CONFIG_VGA_PCI=y diff --git a/SOURCES/config.vga.isavga b/SOURCES/config.vga.isavga new file mode 100644 index 0000000..e55e294 --- /dev/null +++ b/SOURCES/config.vga.isavga @@ -0,0 +1,3 @@ +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_BOCHS=y +CONFIG_VGA_PCI=n diff --git a/SOURCES/config.vga.qxl b/SOURCES/config.vga.qxl new file mode 100644 index 0000000..d393f0c --- /dev/null +++ b/SOURCES/config.vga.qxl @@ -0,0 +1,6 @@ +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_BOCHS=y +CONFIG_VGA_PCI=y +CONFIG_OVERRIDE_PCI_ID=y +CONFIG_VGA_VID=0x1b36 +CONFIG_VGA_DID=0x0100 diff --git a/SOURCES/config.vga.stdvga b/SOURCES/config.vga.stdvga new file mode 100644 index 0000000..7d063b7 --- /dev/null +++ b/SOURCES/config.vga.stdvga @@ -0,0 +1,3 @@ +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_BOCHS=y +CONFIG_VGA_PCI=y diff --git a/SOURCES/config.vga.vmware b/SOURCES/config.vga.vmware new file mode 100644 index 0000000..eb10427 --- /dev/null +++ b/SOURCES/config.vga.vmware @@ -0,0 +1,6 @@ +CONFIG_BUILD_VGABIOS=y +CONFIG_VGA_BOCHS=y +CONFIG_VGA_PCI=y +CONFIG_OVERRIDE_PCI_ID=y +CONFIG_VGA_VID=0x15ad +CONFIG_VGA_DID=0x0405 diff --git a/SOURCES/seabios-Another-fix-for-hlist_for_each_entry_safe.patch b/SOURCES/seabios-Another-fix-for-hlist_for_each_entry_safe.patch new file mode 100644 index 0000000..9735c36 --- /dev/null +++ b/SOURCES/seabios-Another-fix-for-hlist_for_each_entry_safe.patch @@ -0,0 +1,63 @@ +From 71db0de897afe747d396134334e87a806be0beff Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:15 +0200 +Subject: [PATCH 3/8] Another fix for hlist_for_each_entry_safe. + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-4-git-send-email-kraxel@redhat.com> +Patchwork-id: 54627 +O-Subject: [RHEL-7 seabios PATCH 3/7] Another fix for hlist_for_each_entry_safe. +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +From: Kevin O'Connor + +Although the previous patch does fix hlist_for_each_entry_safe for the +common case, it doesn't work correctly when deleting the current +node. To fix this, introduce two macros - hlist_for_each_entry_safe +for iterating through a list that can be modified, and +hlist_for_each_entry_pprev for those users that only need access to +the "pprev" pointer. + +Signed-off-by: Kevin O'Connor +(cherry picked from commit 030a58a05e595694dccfa958563103d2f0644231) + +[ rhel-6: pick list.h changes only ] + +Conflicts: + src/boot.c + src/pciinit.c + src/pmm.c +--- + src/list.h | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +Signed-off-by: Miroslav Rezanina +--- + src/list.h | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/src/list.h b/src/list.h +index 0f0909b..de656b9 100644 +--- a/src/list.h ++++ b/src/list.h +@@ -66,7 +66,13 @@ hlist_add_after(struct hlist_node *n, struct hlist_node *prev) + ; pos != container_of(NULL, typeof(*pos), member) \ + ; pos = container_of(pos->member.next, typeof(*pos), member)) + +-#define hlist_for_each_entry_safe(pos, pprev, head, member) \ ++#define hlist_for_each_entry_safe(pos, n, head, member) \ ++ for (pos = container_of((head)->first, typeof(*pos), member) \ ++ ; pos != container_of(NULL, typeof(*pos), member) \ ++ && ({ n = pos->member.next; 1; }) \ ++ ; pos = container_of(n, typeof(*pos), member)) ++ ++#define hlist_for_each_entry_pprev(pos, pprev, head, member) \ + for (pprev = &(head)->first \ + ; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \ + ; pprev = &(*pprev)->next) +-- +1.7.1 + diff --git a/SOURCES/seabios-Fix-error-in-hlist_for_each_entry_safe-macro.patch b/SOURCES/seabios-Fix-error-in-hlist_for_each_entry_safe-macro.patch new file mode 100644 index 0000000..3860efb --- /dev/null +++ b/SOURCES/seabios-Fix-error-in-hlist_for_each_entry_safe-macro.patch @@ -0,0 +1,46 @@ +From 8cd6a54fc05d726cc84c6c5b3dc551d208d1ddc1 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:14 +0200 +Subject: [PATCH 2/8] Fix error in hlist_for_each_entry_safe macro. + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-3-git-send-email-kraxel@redhat.com> +Patchwork-id: 54629 +O-Subject: [RHEL-7 seabios PATCH 2/7] Fix error in hlist_for_each_entry_safe macro. +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +From: Kevin O'Connor + +Fix broken macro - it did not work correctly at all. + +Signed-off-by: Kevin O'Connor +(cherry picked from commit 9539e41c4d8701c19434457288c38109da163ffc) +--- + src/list.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/list.h | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +diff --git a/src/list.h b/src/list.h +index db7e962..0f0909b 100644 +--- a/src/list.h ++++ b/src/list.h +@@ -68,8 +68,7 @@ hlist_add_after(struct hlist_node *n, struct hlist_node *prev) + + #define hlist_for_each_entry_safe(pos, pprev, head, member) \ + for (pprev = &(head)->first \ +- ; *pprev \ +- && ({ pos=container_of((*pprev)->next, typeof(*pos), member); 1; }) \ ++ ; *pprev && ({ pos=container_of(*pprev, typeof(*pos), member); 1; }) \ + ; pprev = &(*pprev)->next) + + +-- +1.7.1 + diff --git a/SOURCES/seabios-Introduce-and-convert-pmm-code-to-use-standard-list-.patch b/SOURCES/seabios-Introduce-and-convert-pmm-code-to-use-standard-list-.patch new file mode 100644 index 0000000..f8a8246 --- /dev/null +++ b/SOURCES/seabios-Introduce-and-convert-pmm-code-to-use-standard-list-.patch @@ -0,0 +1,135 @@ +From cd24f3be4bcb388fd6b4ed48fc9a076ef0e1cee9 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:13 +0200 +Subject: [PATCH 1/8] Introduce and convert pmm code to use standard list helpers. + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54628 +O-Subject: [RHEL-7 seabios PATCH 1/7] Introduce and convert pmm code to use standard list helpers. +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +From: Kevin O'Connor + +Signed-off-by: Kevin O'Connor +(cherry picked from commit e097a75ef0de08ad6d8660c41efe10c1133f1865) + +[ rhel6: skip ppm.c changes ] + +Conflicts: + src/pmm.c +--- + src/list.h | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/types.h | 3 +++ + 2 files changed, 79 insertions(+) + create mode 100644 src/list.h + +Signed-off-by: Miroslav Rezanina +--- + src/list.h | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/types.h | 3 ++ + 2 files changed, 79 insertions(+), 0 deletions(-) + create mode 100644 src/list.h + +diff --git a/src/list.h b/src/list.h +new file mode 100644 +index 0000000..db7e962 +--- /dev/null ++++ b/src/list.h +@@ -0,0 +1,76 @@ ++#ifndef __LIST_H ++#define __LIST_H ++ ++#include "types.h" // container_of ++ ++ ++/**************************************************************** ++ * hlist - Double linked lists with a single pointer list head ++ ****************************************************************/ ++ ++struct hlist_node { ++ struct hlist_node *next, **pprev; ++}; ++ ++struct hlist_head { ++ struct hlist_node *first; ++}; ++ ++static inline int ++hlist_empty(const struct hlist_head *h) ++{ ++ return !h->first; ++} ++ ++static inline void ++hlist_del(struct hlist_node *n) ++{ ++ struct hlist_node *next = n->next; ++ struct hlist_node **pprev = n->pprev; ++ *pprev = next; ++ if (next) ++ next->pprev = pprev; ++} ++ ++static inline void ++hlist_add(struct hlist_node *n, struct hlist_node **pprev) ++{ ++ struct hlist_node *next = *pprev; ++ n->pprev = pprev; ++ n->next = next; ++ if (next) ++ next->pprev = &n->next; ++ *pprev = n; ++} ++ ++static inline void ++hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++{ ++ hlist_add(n, &h->first); ++} ++ ++static inline void ++hlist_add_before(struct hlist_node *n, struct hlist_node *next) ++{ ++ hlist_add(n, next->pprev); ++} ++ ++static inline void ++hlist_add_after(struct hlist_node *n, struct hlist_node *prev) ++{ ++ hlist_add(n, &prev->next); ++} ++ ++#define hlist_for_each_entry(pos, head, member) \ ++ for (pos = container_of((head)->first, typeof(*pos), member) \ ++ ; pos != container_of(NULL, typeof(*pos), member) \ ++ ; pos = container_of(pos->member.next, typeof(*pos), member)) ++ ++#define hlist_for_each_entry_safe(pos, pprev, head, member) \ ++ for (pprev = &(head)->first \ ++ ; *pprev \ ++ && ({ pos=container_of((*pprev)->next, typeof(*pos), member); 1; }) \ ++ ; pprev = &(*pprev)->next) ++ ++ ++#endif // list.h +diff --git a/src/types.h b/src/types.h +index 24b078e..e5ab4bf 100644 +--- a/src/types.h ++++ b/src/types.h +@@ -121,6 +121,9 @@ extern void __force_link_error__only_in_16bit(void) __noreturn; + #define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) ++#define container_of_or_null(ptr, type, member) ({ \ ++ const typeof( ((type *)0)->member ) *___mptr = (ptr); \ ++ ___mptr ? container_of(___mptr, type, member) : NULL; }) + + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +-- +1.7.1 + diff --git a/SOURCES/seabios-Place-rpm-version-info-into-version-banner.patch b/SOURCES/seabios-Place-rpm-version-info-into-version-banner.patch new file mode 100644 index 0000000..3eeb0bb --- /dev/null +++ b/SOURCES/seabios-Place-rpm-version-info-into-version-banner.patch @@ -0,0 +1,54 @@ +From 25c134c1c2e5966ed9ba604fb73e4c828131146f Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Thu, 22 Aug 2013 12:06:40 +0200 +Subject: [PATCH 4/5] Place rpm version info into version banner + +RH-Author: Miroslav Rezanina +Message-id: <1377173200-17433-1-git-send-email-mrezanin@redhat.com> +Patchwork-id: 53692 +O-Subject: [RHEL7 seabios PATCH] Place rpm version info into version banner +Bugzilla: 894979 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Michal Novotny + +From: Miroslav Rezanina + +Bugzilla: 894979 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=6199274 + +This patch introduces two changes: + +1) Do not append date and hostname to version string. + +2) Use rpm version insted of git commit as the version string. + +Both changes are trivial so they are not posted in separate patches. + +Signed-off-by: Miroslav Rezanina +--- + redhat/seabios.spec.template | 5 ++--- + tools/buildversion.sh | 1 - + 2 files changed, 2 insertions(+), 4 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + redhat/seabios.spec.template | 5 ++--- + tools/buildversion.sh | 1 - + 2 files changed, 2 insertions(+), 4 deletions(-) + +diff --git a/tools/buildversion.sh b/tools/buildversion.sh +index c8c1725..395e6d6 100755 +--- a/tools/buildversion.sh ++++ b/tools/buildversion.sh +@@ -11,7 +11,6 @@ elif [ -f .version ]; then + else + VERSION="?" + fi +-VERSION="${VERSION}-`date +"%Y%m%d_%H%M%S"`-`hostname`" + echo "Version: ${VERSION}" + + # Build header file +-- +1.7.1 + diff --git a/SOURCES/seabios-ahci-add-missing-check-for-allocation-failure.patch b/SOURCES/seabios-ahci-add-missing-check-for-allocation-failure.patch new file mode 100644 index 0000000..c83356c --- /dev/null +++ b/SOURCES/seabios-ahci-add-missing-check-for-allocation-failure.patch @@ -0,0 +1,87 @@ +From 48c296e7b9851c07ef277d7d37a05e20da3ef76d Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 17 Sep 2013 09:42:30 +0200 +Subject: [PATCH 5/5] ahci: add missing check for allocation failure + +RH-Author: Gerd Hoffmann +Message-id: <1379410950-22494-2-git-send-email-kraxel@redhat.com> +Patchwork-id: 54411 +O-Subject: [RHEL-7 seabios PATCH 1/1] ahci: add missing check for allocation failure +Bugzilla: 1005747 +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Paolo Bonzini + +Triggerable by creating a virtual machine with +*lots* of ahci controllers and disks. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit ce12eaf2044d6aae08795403ecbb888d2b6527ff) +--- + src/ahci.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/ahci.c | 25 ++++++++++++++++--------- + 1 files changed, 16 insertions(+), 9 deletions(-) + +diff --git a/src/ahci.c b/src/ahci.c +index 4a8eafb..056d894 100644 +--- a/src/ahci.c ++++ b/src/ahci.c +@@ -381,12 +381,26 @@ ahci_port_alloc(struct ahci_ctrl_s *ctrl, u32 pnr) + return port; + } + ++static void ahci_port_release(struct ahci_port_s *port) ++{ ++ ahci_port_reset(port->ctrl, port->pnr); ++ free(port->list); ++ free(port->fis); ++ free(port->cmd); ++ free(port); ++} ++ + static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) + { + struct ahci_port_s *tmp; + u32 cmd; + + tmp = malloc_fseg(sizeof(*port)); ++ if (!tmp) { ++ warn_noalloc(); ++ ahci_port_release(port); ++ return NULL; ++ } + *tmp = *port; + free(port); + port = tmp; +@@ -410,15 +424,6 @@ static struct ahci_port_s* ahci_port_realloc(struct ahci_port_s *port) + return port; + } + +-static void ahci_port_release(struct ahci_port_s *port) +-{ +- ahci_port_reset(port->ctrl, port->pnr); +- free(port->list); +- free(port->fis); +- free(port->cmd); +- free(port); +-} +- + #define MAXMODEL 40 + + /* See ahci spec chapter 10.1 "Software Initialization of HBA" */ +@@ -554,6 +559,8 @@ ahci_port_detect(void *data) + ahci_port_release(port); + else { + port = ahci_port_realloc(port); ++ if (port == NULL) ++ return; + dprintf(1, "AHCI/%d: registering: \"%s\"\n", port->pnr, port->desc); + if (!port->atapi) { + // Register with bcv system. +-- +1.7.1 + diff --git a/SOURCES/seabios-allow-1TB-of-RAM.patch b/SOURCES/seabios-allow-1TB-of-RAM.patch new file mode 100644 index 0000000..017b051 --- /dev/null +++ b/SOURCES/seabios-allow-1TB-of-RAM.patch @@ -0,0 +1,67 @@ +From 90414ef38b1f32b5b844e1fc27d30bd6d229f5de Mon Sep 17 00:00:00 2001 +From: Andrea Arcangeli +Date: Tue, 8 Oct 2013 17:07:23 +0200 +Subject: [PATCH 8/8] allow >1TB of RAM + +RH-Author: Andrea Arcangeli +Message-id: <1381252043-13480-2-git-send-email-aarcange@redhat.com> +Patchwork-id: 54785 +O-Subject: [RHEL-7.0 seabios PATCH] allow >1TB of RAM +Bugzilla: 1016974 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gleb Natapov +RH-Acked-by: Laszlo Ersek + +Receive bits 40-48 from qemu to setup e820 maps with more than 1TB of ram. + +Signed-off-by: Andrea Arcangeli +--- + src/cmos.h | 7 ++++--- + src/post.c | 7 ++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/cmos.h | 7 ++++--- + src/post.c | 7 ++++--- + 2 files changed, 8 insertions(+), 6 deletions(-) + +diff --git a/src/cmos.h b/src/cmos.h +index e4b6462..e810534 100644 +--- a/src/cmos.h ++++ b/src/cmos.h +@@ -36,9 +36,10 @@ + #define CMOS_BIOS_BOOTFLAG1 0x38 + #define CMOS_BIOS_DISKTRANSFLAG 0x39 + #define CMOS_BIOS_BOOTFLAG2 0x3d +-#define CMOS_MEM_HIGHMEM_LOW 0x5b +-#define CMOS_MEM_HIGHMEM_MID 0x5c +-#define CMOS_MEM_HIGHMEM_HIGH 0x5d ++#define CMOS_MEM_HIGHMEM_16 0x5b ++#define CMOS_MEM_HIGHMEM_24 0x5c ++#define CMOS_MEM_HIGHMEM_32 0x5d ++#define CMOS_MEM_HIGHMEM_40 0x5e + #define CMOS_BIOS_SMP_COUNT 0x5f + + // CMOS_FLOPPY_DRIVE_TYPE bitdefs +diff --git a/src/post.c b/src/post.c +index f3b56b8..737c16d 100644 +--- a/src/post.c ++++ b/src/post.c +@@ -122,9 +122,10 @@ ram_probe(void) + add_e820(0, rs, E820_RAM); + + // Check for memory over 4Gig +- u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16) +- | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24) +- | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32)); ++ u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_16) << 16) ++ | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_24) << 24) ++ | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_32) << 32) ++ | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_40) << 40)); + RamSizeOver4G = high; + add_e820(0x100000000ull, high, E820_RAM); + +-- +1.7.1 + diff --git a/SOURCES/seabios-floppy-Cleanup-floppy-irq-wait-handling.patch b/SOURCES/seabios-floppy-Cleanup-floppy-irq-wait-handling.patch new file mode 100644 index 0000000..bc4e9c2 --- /dev/null +++ b/SOURCES/seabios-floppy-Cleanup-floppy-irq-wait-handling.patch @@ -0,0 +1,203 @@ +From 46ceee9e43c842627ac0f684e1d9d6244edb2a10 Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 22 Aug 2013 02:15:58 +0200 +Subject: [PATCH 2/5] floppy: Cleanup floppy irq wait handling. + +RH-Author: Fam Zheng +Message-id: <1377137759-16089-3-git-send-email-famz@redhat.com> +Patchwork-id: 53680 +O-Subject: [RHEL-7 seabios PATCH 2/3] floppy: Cleanup floppy irq wait handling. +Bugzilla: 920140 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Markus Armbruster + +From: Kevin O'Connor + +Rename FRS_TIMEOUT to FRS_IRQ - the flag indicates that an irq has +been received - it isn't directly related to timeouts. + +On a timeout event, disable the floppy controller instead of doing a +full reset. Also, perform the disable directly in floppy_wait_irq(). + +Always wait for the floppy irq after enabling the controller and after +a recalibrate command. + +Signed-off-by: Kevin O'Connor +(cherry picked from commit 6e529bdae4922f48c0d7eaa31613b7a9230e8f95) +Signed-off-by: Fam Zheng +--- + src/biosvar.h | 2 +- + src/floppy.c | 88 +++++++++++++++++++++++++++++------------------------------ + 2 files changed, 45 insertions(+), 45 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/biosvar.h | 2 +- + src/floppy.c | 88 ++++++++++++++++++++++++++++---------------------------- + 2 files changed, 45 insertions(+), 45 deletions(-) + +diff --git a/src/biosvar.h b/src/biosvar.h +index f0a0fd2..252d4d1 100644 +--- a/src/biosvar.h ++++ b/src/biosvar.h +@@ -120,7 +120,7 @@ struct bios_data_area_s { + } PACKED; + + // BDA floppy_recalibration_status bitdefs +-#define FRS_TIMEOUT (1<<7) ++#define FRS_IRQ (1<<7) + + // BDA rtc_wait_flag bitdefs + #define RWS_WAIT_PENDING (1<<0) +diff --git a/src/floppy.c b/src/floppy.c +index 458bb7a..429ccb5 100644 +--- a/src/floppy.c ++++ b/src/floppy.c +@@ -164,63 +164,59 @@ find_floppy_type(u32 size) + ****************************************************************/ + + static void +-floppy_reset_controller(void) ++floppy_disable_controller(void) + { +- // Reset controller +- u8 val8 = inb(PORT_FD_DOR); +- outb(val8 & ~0x04, PORT_FD_DOR); +- outb(val8 | 0x04, PORT_FD_DOR); +- +- // Wait for controller to come out of reset +- while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80) +- ; ++ outb(inb(PORT_FD_DOR) & ~0x04, PORT_FD_DOR); + } + + static int +-wait_floppy_irq(void) ++floppy_wait_irq(void) + { +- ASSERT16(); +- u8 frs; ++ u8 frs = GET_BDA(floppy_recalibration_status); ++ SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ); + for (;;) { +- if (!GET_BDA(floppy_motor_counter)) +- return -1; ++ if (!GET_BDA(floppy_motor_counter)) { ++ floppy_disable_controller(); ++ return DISK_RET_ETIMEOUT; ++ } + frs = GET_BDA(floppy_recalibration_status); +- if (frs & FRS_TIMEOUT) ++ if (frs & FRS_IRQ) + break; + // Could use yield_toirq() here, but that causes issues on + // bochs, so use yield() instead. + yield(); + } + +- frs &= ~FRS_TIMEOUT; +- SET_BDA(floppy_recalibration_status, frs); +- return 0; ++ SET_BDA(floppy_recalibration_status, frs & ~FRS_IRQ); ++ return DISK_RET_SUCCESS; + } + +-static void +-floppy_prepare_controller(u8 floppyid) ++static int ++floppy_enable_controller(void) + { +- u8 frs = GET_BDA(floppy_recalibration_status); +- SET_BDA(floppy_recalibration_status, frs & ~FRS_TIMEOUT); +- +- // turn on motor of selected drive, DMA & int enabled, normal operation +- u8 prev_reset = inb(PORT_FD_DOR) & 0x04; +- u8 dor = 0x10; +- if (floppyid) +- dor = 0x20; +- dor |= 0x0c; +- dor |= floppyid; +- outb(dor, PORT_FD_DOR); ++ outb(inb(PORT_FD_DOR) | 0x04, PORT_FD_DOR); ++ return floppy_wait_irq(); ++} + ++static int ++floppy_select_drive(u8 floppyid) ++{ + // reset the disk motor timeout value of INT 08 + SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS); + +- // wait for drive readiness +- while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80) +- ; ++ // Enable controller if it isn't running. ++ u8 dor = inb(PORT_FD_DOR); ++ if (!(dor & 0x04)) { ++ int ret = floppy_enable_controller(); ++ if (ret) ++ return ret; ++ } + +- if (!prev_reset) +- wait_floppy_irq(); ++ // Turn on motor of selected drive, DMA & int enabled, normal operation ++ dor = (floppyid ? 0x20 : 0x10) | 0x0c | floppyid; ++ outb(dor, PORT_FD_DOR); ++ ++ return DISK_RET_SUCCESS; + } + + struct floppy_pio_s { +@@ -233,7 +229,13 @@ struct floppy_pio_s { + static int + floppy_pio(struct floppy_pio_s *pio) + { +- floppy_prepare_controller(pio->data[1] & 1); ++ int ret = floppy_select_drive(pio->data[1] & 1); ++ if (ret) ++ return ret; ++ ++ // wait for drive readiness ++ while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80) ++ ; + + // send command to controller + int i; +@@ -241,11 +243,9 @@ floppy_pio(struct floppy_pio_s *pio) + outb(pio->data[i], PORT_FD_DATA); + + if (pio->waitirq) { +- int ret = wait_floppy_irq(); +- if (ret) { +- floppy_reset_controller(); +- return DISK_RET_ETIMEOUT; +- } ++ int ret = floppy_wait_irq(); ++ if (ret) ++ return ret; + } + + if (!pio->resplen) +@@ -330,7 +330,7 @@ floppy_drive_recal(u8 floppyid) + struct floppy_pio_s pio; + pio.cmdlen = 2; + pio.resplen = 0; +- pio.waitirq = 0; ++ pio.waitirq = 1; + pio.data[0] = 0x07; // 07: Recalibrate + pio.data[1] = floppyid; // 0=drive0, 1=drive1 + floppy_pio(&pio); +@@ -617,7 +617,7 @@ handle_0e(void) + } + // diskette interrupt has occurred + u8 frs = GET_BDA(floppy_recalibration_status); +- SET_BDA(floppy_recalibration_status, frs | FRS_TIMEOUT); ++ SET_BDA(floppy_recalibration_status, frs | FRS_IRQ); + + eoi_pic1(); + } +-- +1.7.1 + diff --git a/SOURCES/seabios-floppy-Implement-media-format-sensing.patch b/SOURCES/seabios-floppy-Implement-media-format-sensing.patch new file mode 100644 index 0000000..a0acc37 --- /dev/null +++ b/SOURCES/seabios-floppy-Implement-media-format-sensing.patch @@ -0,0 +1,199 @@ +From 51d219681f4e073bbaf0a6e540f42447f1a18edf Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 22 Aug 2013 02:15:59 +0200 +Subject: [PATCH 3/5] floppy: Implement media format sensing. + +RH-Author: Fam Zheng +Message-id: <1377137759-16089-4-git-send-email-famz@redhat.com> +Patchwork-id: 53681 +O-Subject: [RHEL-7 seabios PATCH 3/3] floppy: Implement media format sensing. +Bugzilla: 920140 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Markus Armbruster + +From: Kevin O'Connor + +Check for lower capacity media in the floppy drive and set the +corresponding controller data rate for it. + +Signed-off-by: Kevin O'Connor +(cherry picked from commit e7c5a7ef782673f00faf3371721562806e931cdb) +Signed-off-by: Fam Zheng + +Conflicts: + src/floppy.c + Context conflict. Upstream 89a2f96d converted VAR16VISIBLE + to VARFSEG, which we don't have yet. So keep the original + type. + +Signed-off-by: Fam Zheng +--- + src/floppy.c | 123 +++++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 78 insertions(+), 45 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/floppy.c | 123 ++++++++++++++++++++++++++++++++++++--------------------- + 1 files changed, 78 insertions(+), 45 deletions(-) + +diff --git a/src/floppy.c b/src/floppy.c +index 429ccb5..f00349d 100644 +--- a/src/floppy.c ++++ b/src/floppy.c +@@ -51,29 +51,37 @@ struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7); + + struct floppyinfo_s { + struct chs_s chs; +- u8 config_data; +- u8 media_state; ++ u8 floppy_size; ++ u8 data_rate; + }; + ++#define FLOPPY_SIZE_525 0x01 ++#define FLOPPY_SIZE_350 0x02 ++ ++#define FLOPPY_RATE_500K 0x00 ++#define FLOPPY_RATE_300K 0x01 ++#define FLOPPY_RATE_250K 0x02 ++#define FLOPPY_RATE_1M 0x03 ++ + struct floppyinfo_s FloppyInfo[] VAR16VISIBLE = { + // Unknown + { {0, 0, 0}, 0x00, 0x00}, + // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors +- { {2, 40, 9}, 0x00, 0x25}, ++ { {2, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, + // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors +- { {2, 80, 15}, 0x00, 0x25}, ++ { {2, 80, 15}, FLOPPY_SIZE_525, FLOPPY_RATE_500K}, + // 3 - 720KB, 3.5" - 2 heads, 80 tracks, 9 sectors +- { {2, 80, 9}, 0x00, 0x17}, ++ { {2, 80, 9}, FLOPPY_SIZE_350, FLOPPY_RATE_250K}, + // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors +- { {2, 80, 18}, 0x00, 0x17}, ++ { {2, 80, 18}, FLOPPY_SIZE_350, FLOPPY_RATE_500K}, + // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors +- { {2, 80, 36}, 0xCC, 0xD7}, ++ { {2, 80, 36}, FLOPPY_SIZE_350, FLOPPY_RATE_1M}, + // 6 - 160k, 5.25" - 1 heads, 40 tracks, 8 sectors +- { {1, 40, 8}, 0x00, 0x27}, ++ { {1, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, + // 7 - 180k, 5.25" - 1 heads, 40 tracks, 9 sectors +- { {1, 40, 9}, 0x00, 0x27}, ++ { {1, 40, 9}, FLOPPY_SIZE_525, FLOPPY_RATE_300K}, + // 8 - 320k, 5.25" - 2 heads, 40 tracks, 8 sectors +- { {2, 40, 8}, 0x00, 0x27}, ++ { {2, 40, 8}, FLOPPY_SIZE_525, FLOPPY_RATE_250K}, + }; + + struct drive_s * +@@ -341,44 +349,69 @@ floppy_drive_recal(u8 floppyid) + } + + static int ++floppy_drive_readid(u8 floppyid, u8 data_rate, u8 head) ++{ ++ int ret = floppy_select_drive(floppyid); ++ if (ret) ++ return ret; ++ ++ // Set data rate. ++ outb(data_rate, PORT_FD_DIR); ++ ++ // send Read Sector Id command ++ struct floppy_pio_s pio; ++ pio.cmdlen = 2; ++ pio.resplen = 7; ++ pio.waitirq = 1; ++ pio.data[0] = 0x4a; // 0a: Read Sector Id ++ pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2 ++ ret = floppy_pio(&pio); ++ if (ret) ++ return ret; ++ if (pio.data[0] & 0xc0) ++ return -1; ++ return 0; ++} ++ ++static int + floppy_media_sense(struct drive_s *drive_g) + { +- // for now cheat and get drive type from CMOS, +- // assume media is same as drive type +- +- // ** config_data ** +- // Bitfields for diskette media control: +- // Bit(s) Description (Table M0028) +- // 7-6 last data rate set by controller +- // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps +- // 5-4 last diskette drive step rate selected +- // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah +- // 3-2 {data rate at start of operation} +- // 1-0 reserved +- +- // ** media_state ** +- // Bitfields for diskette drive media state: +- // Bit(s) Description (Table M0030) +- // 7-6 data rate +- // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps +- // 5 double stepping required (e.g. 360kB in 1.2MB) +- // 4 media type established +- // 3 drive capable of supporting 4MB media +- // 2-0 on exit from BIOS, contains +- // 000 trying 360kB in 360kB +- // 001 trying 360kB in 1.2MB +- // 010 trying 1.2MB in 1.2MB +- // 011 360kB in 360kB established +- // 100 360kB in 1.2MB established +- // 101 1.2MB in 1.2MB established +- // 110 reserved +- // 111 all other formats/drives +- +- u8 ftype = GET_GLOBAL(drive_g->floppy_type); +- SET_BDA(floppy_last_data_rate, GET_GLOBAL(FloppyInfo[ftype].config_data)); ++ u8 ftype = GET_GLOBAL(drive_g->floppy_type), stype = ftype; + u8 floppyid = GET_GLOBAL(drive_g->cntl_id); +- SET_BDA(floppy_media_state[floppyid] +- , GET_GLOBAL(FloppyInfo[ftype].media_state)); ++ ++ u8 data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate); ++ int ret = floppy_drive_readid(floppyid, data_rate, 0); ++ if (ret) { ++ // Attempt media sense. ++ for (stype=1; ; stype++) { ++ if (stype >= ARRAY_SIZE(FloppyInfo)) ++ return DISK_RET_EMEDIA; ++ if (stype==ftype ++ || (GET_GLOBAL(FloppyInfo[stype].floppy_size) ++ != GET_GLOBAL(FloppyInfo[ftype].floppy_size)) ++ || (GET_GLOBAL(FloppyInfo[stype].chs.heads) ++ > GET_GLOBAL(FloppyInfo[ftype].chs.heads)) ++ || (GET_GLOBAL(FloppyInfo[stype].chs.cylinders) ++ > GET_GLOBAL(FloppyInfo[ftype].chs.cylinders)) ++ || (GET_GLOBAL(FloppyInfo[stype].chs.spt) ++ > GET_GLOBAL(FloppyInfo[ftype].chs.spt))) ++ continue; ++ data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate); ++ ret = floppy_drive_readid(floppyid, data_rate, 0); ++ if (!ret) ++ break; ++ } ++ } ++ ++ u8 old_data_rate = GET_BDA(floppy_media_state[floppyid]) >> 6; ++ SET_BDA(floppy_last_data_rate, (old_data_rate<<2) | (data_rate<<6)); ++ u8 media = (stype == 1 ? 0x04 : (stype == 2 ? 0x05 : 0x07)); ++ u8 fms = (data_rate<<6) | FMS_MEDIA_DRIVE_ESTABLISHED | media; ++ if (GET_GLOBAL(FloppyInfo[stype].chs.cylinders) ++ < GET_GLOBAL(FloppyInfo[ftype].chs.cylinders)) ++ fms |= FMS_DOUBLE_STEPPING; ++ SET_BDA(floppy_media_state[floppyid], fms); ++ + return DISK_RET_SUCCESS; + } + +-- +1.7.1 + diff --git a/SOURCES/seabios-floppy-Introduce-struct-floppy_pio_s-for-floppy-PIO-.patch b/SOURCES/seabios-floppy-Introduce-struct-floppy_pio_s-for-floppy-PIO-.patch new file mode 100644 index 0000000..d3aec63 --- /dev/null +++ b/SOURCES/seabios-floppy-Introduce-struct-floppy_pio_s-for-floppy-PIO-.patch @@ -0,0 +1,265 @@ +From 946dd96997625598fd814500e5fbfd457c6d670d Mon Sep 17 00:00:00 2001 +From: Fam Zheng +Date: Thu, 22 Aug 2013 02:15:57 +0200 +Subject: [PATCH 1/5] floppy: Introduce 'struct floppy_pio_s' for floppy PIO ops. + +RH-Author: Fam Zheng +Message-id: <1377137759-16089-2-git-send-email-famz@redhat.com> +Patchwork-id: 53679 +O-Subject: [RHEL-7 seabios PATCH 1/3] floppy: Introduce 'struct floppy_pio_s' for floppy PIO ops. +Bugzilla: 920140 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Markus Armbruster + +From: Kevin O'Connor + +Populate a struct for the PIO operations and move the PIO manipulation +done in floppy_cmd() to floppy_pio(). + +Signed-off-by: Kevin O'Connor +(cherry picked from commit 9ba374ce1d864b7a50f3657e6b06e7b2d1ec2934) +Signed-off-by: Fam Zheng +--- + src/floppy.c | 158 ++++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 90 insertions(+), 68 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/floppy.c | 158 +++++++++++++++++++++++++++++++++------------------------- + 1 files changed, 90 insertions(+), 68 deletions(-) + +diff --git a/src/floppy.c b/src/floppy.c +index e9f8916..458bb7a 100644 +--- a/src/floppy.c ++++ b/src/floppy.c +@@ -223,27 +223,48 @@ floppy_prepare_controller(u8 floppyid) + wait_floppy_irq(); + } + ++struct floppy_pio_s { ++ u8 cmdlen; ++ u8 resplen; ++ u8 waitirq; ++ u8 data[9]; ++}; ++ + static int +-floppy_pio(u8 *cmd, u8 cmdlen) ++floppy_pio(struct floppy_pio_s *pio) + { +- floppy_prepare_controller(cmd[1] & 1); ++ floppy_prepare_controller(pio->data[1] & 1); + + // send command to controller +- u8 i; +- for (i=0; icmdlen; i++) ++ outb(pio->data[i], PORT_FD_DATA); ++ ++ if (pio->waitirq) { ++ int ret = wait_floppy_irq(); ++ if (ret) { ++ floppy_reset_controller(); ++ return DISK_RET_ETIMEOUT; ++ } + } + +- return 0; ++ if (!pio->resplen) ++ return DISK_RET_SUCCESS; ++ ++ // check port 3f4 for accessibility to status bytes ++ if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) ++ return DISK_RET_ECONTROLLER; ++ ++ // read return status bytes from controller ++ for (i=0; iresplen; i++) ++ pio->data[i] = inb(PORT_FD_DATA); ++ ++ return DISK_RET_SUCCESS; + } + ++// Perform a floppy transfer command (setup DMA and issue PIO). + static int +-floppy_cmd(struct disk_op_s *op, u16 count, u8 *cmd, u8 cmdlen) ++floppy_cmd(struct disk_op_s *op, int count, struct floppy_pio_s *pio) + { + // es:bx = pointer to where to place information from diskette + u32 addr = (u32)op->buf_fl; +@@ -255,7 +276,7 @@ floppy_cmd(struct disk_op_s *op, u16 count, u8 *cmd, u8 cmdlen) + return DISK_RET_EBOUNDARY; + + u8 mode_register = 0x4a; // single mode, increment, autoinit disable, +- if (cmd[0] == 0xe6) ++ if (pio->data[0] == 0xe6) + // read + mode_register = 0x46; + +@@ -277,21 +298,16 @@ floppy_cmd(struct disk_op_s *op, u16 count, u8 *cmd, u8 cmdlen) + + outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2 + +- int ret = floppy_pio(cmd, cmdlen); ++ pio->resplen = 7; ++ pio->waitirq = 1; ++ int ret = floppy_pio(pio); + if (ret) +- return DISK_RET_ETIMEOUT; +- +- // check port 3f4 for accessibility to status bytes +- if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) +- return DISK_RET_ECONTROLLER; ++ return ret; + +- // read 7 return status bytes from controller +- u8 i; +- for (i=0; i<7; i++) { +- u8 v = inb(PORT_FD_DATA); +- cmd[i] = v; +- SET_BDA(floppy_return_status[i], v); +- } ++ // Populate floppy_return_status in BDA ++ int i; ++ for (i=0; i<7; i++) ++ SET_BDA(floppy_return_status[i], pio->data[i]); + + return DISK_RET_SUCCESS; + } +@@ -311,10 +327,13 @@ static void + floppy_drive_recal(u8 floppyid) + { + // send Recalibrate command (2 bytes) to controller +- u8 data[12]; +- data[0] = 0x07; // 07: Recalibrate +- data[1] = floppyid; // 0=drive0, 1=drive1 +- floppy_pio(data, 2); ++ struct floppy_pio_s pio; ++ pio.cmdlen = 2; ++ pio.resplen = 0; ++ pio.waitirq = 0; ++ pio.data[0] = 0x07; // 07: Recalibrate ++ pio.data[1] = floppyid; // 0=drive0, 1=drive1 ++ floppy_pio(&pio); + + u8 frs = GET_BDA(floppy_recalibration_status); + SET_BDA(floppy_recalibration_status, frs | (1<drive_g->cntl_id); +- u8 data[12]; +- data[0] = 0xe6; // e6: read normal data +- data[1] = (head << 2) | floppyid; // HD DR1 DR2 +- data[2] = track; +- data[3] = head; +- data[4] = sector; +- data[5] = FLOPPY_SIZE_CODE; +- data[6] = sector + op->count - 1; // last sector to read on track +- data[7] = FLOPPY_GAPLEN; +- data[8] = FLOPPY_DATALEN; +- +- res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); ++ struct floppy_pio_s pio; ++ pio.cmdlen = 9; ++ pio.data[0] = 0xe6; // e6: read normal data ++ pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2 ++ pio.data[2] = track; ++ pio.data[3] = head; ++ pio.data[4] = sector; ++ pio.data[5] = FLOPPY_SIZE_CODE; ++ pio.data[6] = sector + op->count - 1; // last sector to read on track ++ pio.data[7] = FLOPPY_GAPLEN; ++ pio.data[8] = FLOPPY_DATALEN; ++ ++ res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, &pio); + if (res) + goto fail; + +- if (data[0] & 0xc0) { ++ if (pio.data[0] & 0xc0) { + res = DISK_RET_ECONTROLLER; + goto fail; + } +@@ -464,23 +484,24 @@ floppy_write(struct disk_op_s *op) + + // send write-normal-data command (9 bytes) to controller + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); +- u8 data[12]; +- data[0] = 0xc5; // c5: write normal data +- data[1] = (head << 2) | floppyid; // HD DR1 DR2 +- data[2] = track; +- data[3] = head; +- data[4] = sector; +- data[5] = FLOPPY_SIZE_CODE; +- data[6] = sector + op->count - 1; // last sector to write on track +- data[7] = FLOPPY_GAPLEN; +- data[8] = FLOPPY_DATALEN; +- +- res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); ++ struct floppy_pio_s pio; ++ pio.cmdlen = 9; ++ pio.data[0] = 0xc5; // c5: write normal data ++ pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2 ++ pio.data[2] = track; ++ pio.data[3] = head; ++ pio.data[4] = sector; ++ pio.data[5] = FLOPPY_SIZE_CODE; ++ pio.data[6] = sector + op->count - 1; // last sector to write on track ++ pio.data[7] = FLOPPY_GAPLEN; ++ pio.data[8] = FLOPPY_DATALEN; ++ ++ res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, &pio); + if (res) + goto fail; + +- if (data[0] & 0xc0) { +- if (data[1] & 0x02) ++ if (pio.data[0] & 0xc0) { ++ if (pio.data[1] & 0x02) + res = DISK_RET_EWRITEPROTECT; + else + res = DISK_RET_ECONTROLLER; +@@ -527,20 +548,21 @@ floppy_format(struct disk_op_s *op) + + // send format-track command (6 bytes) to controller + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); +- u8 data[12]; +- data[0] = 0x4d; // 4d: format track +- data[1] = (head << 2) | floppyid; // HD DR1 DR2 +- data[2] = FLOPPY_SIZE_CODE; +- data[3] = op->count; // number of sectors per track +- data[4] = FLOPPY_FORMAT_GAPLEN; +- data[5] = FLOPPY_FILLBYTE; +- +- ret = floppy_cmd(op, op->count * 4, data, 6); ++ struct floppy_pio_s pio; ++ pio.cmdlen = 6; ++ pio.data[0] = 0x4d; // 4d: format track ++ pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2 ++ pio.data[2] = FLOPPY_SIZE_CODE; ++ pio.data[3] = op->count; // number of sectors per track ++ pio.data[4] = FLOPPY_FORMAT_GAPLEN; ++ pio.data[5] = FLOPPY_FILLBYTE; ++ ++ ret = floppy_cmd(op, op->count * 4, &pio); + if (ret) + return ret; + +- if (data[0] & 0xc0) { +- if (data[1] & 0x02) ++ if (pio.data[0] & 0xc0) { ++ if (pio.data[1] & 0x02) + return DISK_RET_EWRITEPROTECT; + return DISK_RET_ECONTROLLER; + } +-- +1.7.1 + diff --git a/SOURCES/seabios-uas-add-temporary-superspeed-stopgap.patch b/SOURCES/seabios-uas-add-temporary-superspeed-stopgap.patch new file mode 100644 index 0000000..91eb4c7 --- /dev/null +++ b/SOURCES/seabios-uas-add-temporary-superspeed-stopgap.patch @@ -0,0 +1,57 @@ +From 50c3f2680f910216492622858884acd5f1eba9d9 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:16 +0200 +Subject: [PATCH 4/8] uas: add (temporary) superspeed stopgap + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-5-git-send-email-kraxel@redhat.com> +Patchwork-id: 54630 +O-Subject: [RHEL-7 seabios PATCH 4/7] uas: add (temporary) superspeed stopgap +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit ee9b84f61c55a67b477a019e937460be13ccbfa1) +--- + src/usb-uas.c | 4 ++++ + src/usb.h | 1 + + 2 files changed, 5 insertions(+) + +Signed-off-by: Miroslav Rezanina +--- + src/usb-uas.c | 4 ++++ + src/usb.h | 1 + + 2 files changed, 5 insertions(+), 0 deletions(-) + +diff --git a/src/usb-uas.c b/src/usb-uas.c +index be153ed..2133c0e 100644 +--- a/src/usb-uas.c ++++ b/src/usb-uas.c +@@ -220,6 +220,10 @@ usb_uas_init(struct usbdevice_s *usbdev) + case USB_DT_ENDPOINT: + ep = (void*)desc; + break; ++ case USB_DT_ENDPOINT_COMPANION: ++ /* No support (yet) for usb3 streams */ ++ dprintf(1, "Superspeed UAS devices not supported (yet)\n"); ++ goto fail; + case 0x24: + switch (desc[2]) { + case UAS_PIPE_ID_COMMAND: +diff --git a/src/usb.h b/src/usb.h +index a43e829..d9eadd7 100644 +--- a/src/usb.h ++++ b/src/usb.h +@@ -130,6 +130,7 @@ struct usb_ctrlrequest { + #define USB_DT_ENDPOINT 0x05 + #define USB_DT_DEVICE_QUALIFIER 0x06 + #define USB_DT_OTHER_SPEED_CONFIG 0x07 ++#define USB_DT_ENDPOINT_COMPANION 0x30 + + struct usb_device_descriptor { + u8 bLength; +-- +1.7.1 + diff --git a/SOURCES/seabios-usb-add-usb_update_pipe.patch b/SOURCES/seabios-usb-add-usb_update_pipe.patch new file mode 100644 index 0000000..86f26da --- /dev/null +++ b/SOURCES/seabios-usb-add-usb_update_pipe.patch @@ -0,0 +1,88 @@ +From 0966143d780d669d8208ab2ac77254fb20f779d2 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:17 +0200 +Subject: [PATCH 5/8] usb: add usb_update_pipe() + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-6-git-send-email-kraxel@redhat.com> +Patchwork-id: 54632 +O-Subject: [RHEL-7 seabios PATCH 5/7] usb: add usb_update_pipe() +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Preparation for better xhci support: allows to notify host controllers +instead of going through a free+alloc cycle. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 63cbab1628dc406ed5d765bd85bae3a1a525a2c0) +--- + src/usb.c | 22 +++++++++++++++++----- + 1 file changed, 17 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/usb.c | 22 +++++++++++++++++----- + 1 files changed, 17 insertions(+), 5 deletions(-) + +diff --git a/src/usb.c b/src/usb.c +index 421d0b8..3efa367 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -40,6 +40,18 @@ usb_alloc_pipe(struct usbdevice_s *usbdev + } + } + ++// Update an pipe (used for control only) ++struct usb_pipe * ++usb_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *pipe ++ , struct usb_endpoint_descriptor *epdesc) ++{ ++ switch (usbdev->hub->cntl->type) { ++ default: ++ free_pipe(pipe); ++ return usb_alloc_pipe(usbdev, epdesc); ++ } ++} ++ + // Send a message on a control pipe using the default control descriptor. + static int + send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize +@@ -258,15 +270,16 @@ usb_set_address(struct usbdevice_s *usbdev) + req.wIndex = 0; + req.wLength = 0; + int ret = send_default_control(usbdev->defpipe, &req, NULL); +- free_pipe(usbdev->defpipe); +- if (ret) ++ if (ret) { ++ free_pipe(usbdev->defpipe); + return -1; ++ } + + msleep(USB_TIME_SETADDR_RECOVERY); + + cntl->maxaddr++; + usbdev->devaddr = cntl->maxaddr; +- usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); ++ usbdev->defpipe = usb_update_pipe(usbdev, usbdev->defpipe, &epdesc); + if (!usbdev->defpipe) + return -1; + return 0; +@@ -290,12 +303,11 @@ configure_usb_device(struct usbdevice_s *usbdev) + , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0); + if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64) + return 0; +- free_pipe(usbdev->defpipe); + struct usb_endpoint_descriptor epdesc = { + .wMaxPacketSize = dinfo.bMaxPacketSize0, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + }; +- usbdev->defpipe = usb_alloc_pipe(usbdev, &epdesc); ++ usbdev->defpipe = usb_update_pipe(usbdev, usbdev->defpipe, &epdesc); + if (!usbdev->defpipe) + return -1; + +-- +1.7.1 + diff --git a/SOURCES/seabios-usb-add-xhci-support.patch b/SOURCES/seabios-usb-add-xhci-support.patch new file mode 100644 index 0000000..d047843 --- /dev/null +++ b/SOURCES/seabios-usb-add-xhci-support.patch @@ -0,0 +1,1472 @@ +From c1d503b5c244efa1daf29fa297314e7cc82175af Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:18 +0200 +Subject: [PATCH 6/8] usb: add xhci support + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-7-git-send-email-kraxel@redhat.com> +Patchwork-id: 54633 +O-Subject: [RHEL-7 seabios PATCH 6/7] usb: add xhci support +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +$subject says all. Support for usb3 streams is not implemented yet, +otherwise it is fully functional. Tested all usb devices supported +by qemu (keyboard, storage, usb hubs), except for usb attached scsi +in usb3 mode (which needs streams). + +Tested on qemu only, tagged with QEMU_HARDWARE because of that. +Testing with physical hardware to be done. + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit e144bb7af49ca8756b7222a75811f3b85b0bc1f5) + +Conflicts: + Makefile + src/usb.c +--- + Makefile | 2 +- + src/Kconfig | 6 + + src/pci_ids.h | 1 + + src/usb-xhci.c | 1124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/usb-xhci.h | 144 ++++++++ + src/usb.c | 13 + + src/usb.h | 16 +- + 7 files changed, 1298 insertions(+), 8 deletions(-) + create mode 100644 src/usb-xhci.c + create mode 100644 src/usb-xhci.h + +Signed-off-by: Miroslav Rezanina +--- + Makefile | 2 +- + src/Kconfig | 6 + + src/pci_ids.h | 1 + + src/usb-xhci.c | 1124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/usb-xhci.h | 144 ++++++++ + src/usb.c | 13 + + src/usb.h | 16 +- + 7 files changed, 1298 insertions(+), 8 deletions(-) + create mode 100644 src/usb-xhci.c + create mode 100644 src/usb-xhci.h + +diff --git a/Makefile b/Makefile +index 20da6d0..409aefa 100644 +--- a/Makefile ++++ b/Makefile +@@ -11,7 +11,7 @@ OUT=out/ + SRCBOTH=misc.c stacks.c pmm.c output.c util.c block.c floppy.c ata.c mouse.c \ + kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.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 \ ++ usb.c usb-uhci.c usb-ohci.c usb-ehci.c usb-xhci.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 esp-scsi.c megasas.c + SRC16=$(SRCBOTH) system.c disk.c font.c +diff --git a/src/Kconfig b/src/Kconfig +index 2c9100d..b059a73 100644 +--- a/src/Kconfig ++++ b/src/Kconfig +@@ -184,6 +184,12 @@ menu "Hardware support" + default y + help + Support USB EHCI controllers. ++ config USB_XHCI ++ depends on USB && QEMU_HARDWARE ++ bool "USB XHCI controllers" ++ default y ++ help ++ Support USB XHCI controllers. + config USB_MSC + depends on USB && DRIVES + bool "USB drives" +diff --git a/src/pci_ids.h b/src/pci_ids.h +index 665e945..322d156 100644 +--- a/src/pci_ids.h ++++ b/src/pci_ids.h +@@ -104,6 +104,7 @@ + #define PCI_CLASS_SERIAL_USB_UHCI 0x0c0300 + #define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310 + #define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320 ++#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330 + #define PCI_CLASS_SERIAL_FIBER 0x0c04 + #define PCI_CLASS_SERIAL_SMBUS 0x0c05 + +diff --git a/src/usb-xhci.c b/src/usb-xhci.c +new file mode 100644 +index 0000000..5be0b25 +--- /dev/null ++++ b/src/usb-xhci.c +@@ -0,0 +1,1124 @@ ++#include "config.h" // CONFIG_* ++#include "util.h" // timer_calc ++#include "pci.h" // pci_bdf_to_bus ++#include "pci_regs.h" // PCI_BASE_ADDRESS_0 ++#include "usb.h" // struct usb_s ++#include "usb-xhci.h" // struct ehci_qh ++#include "biosvar.h" // GET_LOWFLAT ++ ++// -------------------------------------------------------------- ++// configuration ++ ++#define XHCI_RING_ITEMS 16 ++#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb)) ++ ++/* ++ * xhci_ring structs are allocated with XHCI_RING_SIZE alignment, ++ * then we can get it from a trb pointer (provided by evt ring). ++ */ ++#define XHCI_RING(_trb) \ ++ ((struct xhci_ring*)((u32)(_trb) & ~(XHCI_RING_SIZE-1))) ++ ++// -------------------------------------------------------------- ++// bit definitions ++ ++#define XHCI_CMD_RS (1<<0) ++#define XHCI_CMD_HCRST (1<<1) ++#define XHCI_CMD_INTE (1<<2) ++#define XHCI_CMD_HSEE (1<<3) ++#define XHCI_CMD_LHCRST (1<<7) ++#define XHCI_CMD_CSS (1<<8) ++#define XHCI_CMD_CRS (1<<9) ++#define XHCI_CMD_EWE (1<<10) ++#define XHCI_CMD_EU3S (1<<11) ++ ++#define XHCI_STS_HCH (1<<0) ++#define XHCI_STS_HSE (1<<2) ++#define XHCI_STS_EINT (1<<3) ++#define XHCI_STS_PCD (1<<4) ++#define XHCI_STS_SSS (1<<8) ++#define XHCI_STS_RSS (1<<9) ++#define XHCI_STS_SRE (1<<10) ++#define XHCI_STS_CNR (1<<11) ++#define XHCI_STS_HCE (1<<12) ++ ++#define XHCI_PORTSC_CCS (1<<0) ++#define XHCI_PORTSC_PED (1<<1) ++#define XHCI_PORTSC_OCA (1<<3) ++#define XHCI_PORTSC_PR (1<<4) ++#define XHCI_PORTSC_PLS_SHIFT 5 ++#define XHCI_PORTSC_PLS_MASK 0xf ++#define XHCI_PORTSC_PP (1<<9) ++#define XHCI_PORTSC_SPEED_SHIFT 10 ++#define XHCI_PORTSC_SPEED_MASK 0xf ++#define XHCI_PORTSC_SPEED_FULL (1<<10) ++#define XHCI_PORTSC_SPEED_LOW (2<<10) ++#define XHCI_PORTSC_SPEED_HIGH (3<<10) ++#define XHCI_PORTSC_SPEED_SUPER (4<<10) ++#define XHCI_PORTSC_PIC_SHIFT 14 ++#define XHCI_PORTSC_PIC_MASK 0x3 ++#define XHCI_PORTSC_LWS (1<<16) ++#define XHCI_PORTSC_CSC (1<<17) ++#define XHCI_PORTSC_PEC (1<<18) ++#define XHCI_PORTSC_WRC (1<<19) ++#define XHCI_PORTSC_OCC (1<<20) ++#define XHCI_PORTSC_PRC (1<<21) ++#define XHCI_PORTSC_PLC (1<<22) ++#define XHCI_PORTSC_CEC (1<<23) ++#define XHCI_PORTSC_CAS (1<<24) ++#define XHCI_PORTSC_WCE (1<<25) ++#define XHCI_PORTSC_WDE (1<<26) ++#define XHCI_PORTSC_WOE (1<<27) ++#define XHCI_PORTSC_DR (1<<30) ++#define XHCI_PORTSC_WPR (1<<31) ++ ++#define TRB_C (1<<0) ++#define TRB_TYPE_SHIFT 10 ++#define TRB_TYPE_MASK 0x3f ++#define TRB_TYPE(t) (((t) >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) ++ ++#define TRB_EV_ED (1<<2) ++ ++#define TRB_TR_ENT (1<<1) ++#define TRB_TR_ISP (1<<2) ++#define TRB_TR_NS (1<<3) ++#define TRB_TR_CH (1<<4) ++#define TRB_TR_IOC (1<<5) ++#define TRB_TR_IDT (1<<6) ++#define TRB_TR_TBC_SHIFT 7 ++#define TRB_TR_TBC_MASK 0x3 ++#define TRB_TR_BEI (1<<9) ++#define TRB_TR_TLBPC_SHIFT 16 ++#define TRB_TR_TLBPC_MASK 0xf ++#define TRB_TR_FRAMEID_SHIFT 20 ++#define TRB_TR_FRAMEID_MASK 0x7ff ++#define TRB_TR_SIA (1<<31) ++ ++#define TRB_TR_DIR (1<<16) ++ ++#define TRB_CR_SLOTID_SHIFT 24 ++#define TRB_CR_SLOTID_MASK 0xff ++#define TRB_CR_EPID_SHIFT 16 ++#define TRB_CR_EPID_MASK 0x1f ++ ++#define TRB_CR_BSR (1<<9) ++#define TRB_CR_DC (1<<9) ++ ++#define TRB_LK_TC (1<<1) ++ ++#define TRB_INTR_SHIFT 22 ++#define TRB_INTR_MASK 0x3ff ++#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) ++ ++typedef enum TRBType { ++ TRB_RESERVED = 0, ++ TR_NORMAL, ++ TR_SETUP, ++ TR_DATA, ++ TR_STATUS, ++ TR_ISOCH, ++ TR_LINK, ++ TR_EVDATA, ++ TR_NOOP, ++ CR_ENABLE_SLOT, ++ CR_DISABLE_SLOT, ++ CR_ADDRESS_DEVICE, ++ CR_CONFIGURE_ENDPOINT, ++ CR_EVALUATE_CONTEXT, ++ CR_RESET_ENDPOINT, ++ CR_STOP_ENDPOINT, ++ CR_SET_TR_DEQUEUE, ++ CR_RESET_DEVICE, ++ CR_FORCE_EVENT, ++ CR_NEGOTIATE_BW, ++ CR_SET_LATENCY_TOLERANCE, ++ CR_GET_PORT_BANDWIDTH, ++ CR_FORCE_HEADER, ++ CR_NOOP, ++ ER_TRANSFER = 32, ++ ER_COMMAND_COMPLETE, ++ ER_PORT_STATUS_CHANGE, ++ ER_BANDWIDTH_REQUEST, ++ ER_DOORBELL, ++ ER_HOST_CONTROLLER, ++ ER_DEVICE_NOTIFICATION, ++ ER_MFINDEX_WRAP, ++} TRBType; ++ ++typedef enum TRBCCode { ++ CC_INVALID = 0, ++ CC_SUCCESS, ++ CC_DATA_BUFFER_ERROR, ++ CC_BABBLE_DETECTED, ++ CC_USB_TRANSACTION_ERROR, ++ CC_TRB_ERROR, ++ CC_STALL_ERROR, ++ CC_RESOURCE_ERROR, ++ CC_BANDWIDTH_ERROR, ++ CC_NO_SLOTS_ERROR, ++ CC_INVALID_STREAM_TYPE_ERROR, ++ CC_SLOT_NOT_ENABLED_ERROR, ++ CC_EP_NOT_ENABLED_ERROR, ++ CC_SHORT_PACKET, ++ CC_RING_UNDERRUN, ++ CC_RING_OVERRUN, ++ CC_VF_ER_FULL, ++ CC_PARAMETER_ERROR, ++ CC_BANDWIDTH_OVERRUN, ++ CC_CONTEXT_STATE_ERROR, ++ CC_NO_PING_RESPONSE_ERROR, ++ CC_EVENT_RING_FULL_ERROR, ++ CC_INCOMPATIBLE_DEVICE_ERROR, ++ CC_MISSED_SERVICE_ERROR, ++ CC_COMMAND_RING_STOPPED, ++ CC_COMMAND_ABORTED, ++ CC_STOPPED, ++ CC_STOPPED_LENGTH_INVALID, ++ CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, ++ CC_ISOCH_BUFFER_OVERRUN = 31, ++ CC_EVENT_LOST_ERROR, ++ CC_UNDEFINED_ERROR, ++ CC_INVALID_STREAM_ID_ERROR, ++ CC_SECONDARY_BANDWIDTH_ERROR, ++ CC_SPLIT_TRANSACTION_ERROR ++} TRBCCode; ++ ++enum { ++ PLS_U0 = 0, ++ PLS_U1 = 1, ++ PLS_U2 = 2, ++ PLS_U3 = 3, ++ PLS_DISABLED = 4, ++ PLS_RX_DETECT = 5, ++ PLS_INACTIVE = 6, ++ PLS_POLLING = 7, ++ PLS_RECOVERY = 8, ++ PLS_HOT_RESET = 9, ++ PLS_COMPILANCE_MODE = 10, ++ PLS_TEST_MODE = 11, ++ PLS_RESUME = 15, ++}; ++ ++#define xhci_get_field(data, field) \ ++ (((data) >> field##_SHIFT) & field##_MASK) ++ ++// -------------------------------------------------------------- ++// state structs ++ ++struct xhci_ring { ++ struct xhci_trb ring[XHCI_RING_ITEMS]; ++ struct xhci_trb evt; ++ u32 eidx; ++ u32 nidx; ++ u32 cs; ++ struct mutex_s lock; ++}; ++ ++struct usb_xhci_s { ++ struct usb_s usb; ++ struct usbhub_s hub; ++ ++ /* devinfo */ ++ u32 baseaddr; ++ u32 xcap; ++ u32 ports; ++ u32 slots; ++ ++ /* xhci registers */ ++ struct xhci_caps *caps; ++ struct xhci_op *op; ++ struct xhci_pr *pr; ++ struct xhci_ir *ir; ++ struct xhci_db *db; ++ ++ /* xhci data structures */ ++ struct xhci_devlist *devs; ++ struct xhci_ring *cmds; ++ struct xhci_ring *evts; ++ struct xhci_er_seg *eseg; ++ ++ /* usb devices */ ++ struct hlist_head list; ++}; ++ ++struct xhci_device { ++ struct xhci_devctx devctx; ++ struct xhci_inctx inctx; ++ ++ struct usbdevice_s *usbdev; ++ struct usb_xhci_s *xhci; ++ u32 slotid; ++ struct hlist_node next; ++}; ++ ++struct xhci_pipe { ++ struct xhci_ring reqs; ++ ++ struct usb_pipe pipe; ++ struct xhci_device *dev; ++ u32 epid; ++ void *buf; ++ int bufused; ++}; ++ ++// -------------------------------------------------------------- ++// tables ++ ++static const char *speed_name[16] = { ++ [ 0 ] = " - ", ++ [ 1 ] = "Full", ++ [ 2 ] = "Low", ++ [ 3 ] = "High", ++ [ 4 ] = "Super", ++}; ++ ++static const int speed_from_xhci[16] = { ++ [ 0 ... 15 ] = -1, ++ [ 1 ] = USB_FULLSPEED, ++ [ 2 ] = USB_LOWSPEED, ++ [ 3 ] = USB_HIGHSPEED, ++ [ 4 ] = USB_SUPERSPEED, ++}; ++ ++static const int speed_to_xhci[] = { ++ [ USB_FULLSPEED ] = 1, ++ [ USB_LOWSPEED ] = 2, ++ [ USB_HIGHSPEED ] = 3, ++ [ USB_SUPERSPEED ] = 4, ++}; ++ ++static const int speed_to_ctlsize[] = { ++ [ USB_FULLSPEED ] = 8, ++ [ USB_LOWSPEED ] = 8, ++ [ USB_HIGHSPEED ] = 64, ++ [ USB_SUPERSPEED ] = 256, ++}; ++ ++static const int eptype_to_xhci_in[] = { ++ [ USB_ENDPOINT_XFER_CONTROL] = 4, ++ [ USB_ENDPOINT_XFER_ISOC ] = 5, ++ [ USB_ENDPOINT_XFER_BULK ] = 6, ++ [ USB_ENDPOINT_XFER_INT ] = 7, ++}; ++ ++static const int eptype_to_xhci_out[] = { ++ [ USB_ENDPOINT_XFER_CONTROL] = 4, ++ [ USB_ENDPOINT_XFER_ISOC ] = 1, ++ [ USB_ENDPOINT_XFER_BULK ] = 2, ++ [ USB_ENDPOINT_XFER_INT ] = 3, ++}; ++ ++// -------------------------------------------------------------- ++// internal functions, 16bit + 32bit ++ ++static void xhci_doorbell(struct usb_xhci_s *xhci, u32 slotid, u32 value) ++{ ++ struct xhci_db *db = GET_LOWFLAT(xhci->db); ++ u32 addr = (u32)(&db[slotid].doorbell); ++ pci_writel(addr, value); ++} ++ ++static void xhci_process_events(struct usb_xhci_s *xhci) ++{ ++ struct xhci_ring *evts = GET_LOWFLAT(xhci->evts); ++ ++ for (;;) { ++ /* check for event */ ++ u32 nidx = GET_LOWFLAT(evts->nidx); ++ u32 cs = GET_LOWFLAT(evts->cs); ++ struct xhci_trb *etrb = evts->ring + nidx; ++ u32 control = GET_LOWFLAT(etrb->control); ++ if ((control & TRB_C) != (cs ? 1 : 0)) ++ return; ++ ++ /* process event */ ++ u32 evt_type = TRB_TYPE(control); ++ u32 evt_cc = (GET_LOWFLAT(etrb->status) >> 24) & 0xff; ++ switch (evt_type) { ++ case ER_TRANSFER: ++ case ER_COMMAND_COMPLETE: ++ { ++ struct xhci_trb *rtrb = (void*)GET_LOWFLAT(etrb->ptr_low); ++ struct xhci_ring *ring = XHCI_RING(rtrb); ++ struct xhci_trb *evt = &ring->evt; ++ u32 eidx = rtrb - ring->ring + 1; ++ dprintf(5, "%s: ring %p [trb %p, evt %p, type %d, eidx %d, cc %d]\n", ++ __func__, ring, rtrb, evt, evt_type, eidx, evt_cc); ++ memcpy_fl(evt, etrb, sizeof(*etrb)); ++ SET_LOWFLAT(ring->eidx, eidx); ++ break; ++ } ++ case ER_PORT_STATUS_CHANGE: ++ { ++ u32 portid = (GET_LOWFLAT(etrb->ptr_low) >> 24) & 0xff; ++ dprintf(3, "%s: status change port #%d\n", ++ __func__, portid); ++ break; ++ } ++ default: ++ dprintf(1, "%s: unknown event, type %d, cc %d\n", ++ __func__, evt_type, evt_cc); ++ break; ++ } ++ ++ /* move ring index, notify xhci */ ++ nidx++; ++ if (nidx == XHCI_RING_ITEMS) { ++ nidx = 0; ++ cs = cs ? 0 : 1; ++ SET_LOWFLAT(evts->cs, cs); ++ } ++ SET_LOWFLAT(evts->nidx, nidx); ++ struct xhci_ir *ir = GET_LOWFLAT(xhci->ir); ++ u32 addr = (u32)(&ir->erdp_low); ++ u32 erdp = (u32)(evts->ring + nidx); ++ pci_writel(addr, erdp); ++ } ++} ++ ++static int xhci_ring_busy(struct xhci_ring *ring) ++{ ++ u32 eidx = GET_LOWFLAT(ring->eidx); ++ u32 nidx = GET_LOWFLAT(ring->nidx); ++ return (eidx != nidx); ++} ++ ++static int xhci_event_wait(struct usb_xhci_s *xhci, ++ struct xhci_ring *ring, ++ u32 timeout) ++{ ++ u32 end = timer_calc(timeout); ++ ++ for (;;) { ++ xhci_process_events(xhci); ++ if (!xhci_ring_busy(ring)) { ++ u32 status = GET_LOWFLAT(ring->evt.status); ++ return (status >> 24) & 0xff; ++ } ++ if (timer_check(end)) { ++ warn_timeout(); ++ return -1; ++ } ++ yield(); ++ } ++} ++ ++static void xhci_trb_queue(struct xhci_ring *ring, ++ struct xhci_trb *trb) ++{ ++ u32 nidx = GET_LOWFLAT(ring->nidx); ++ u32 cs = GET_LOWFLAT(ring->cs); ++ struct xhci_trb *dst; ++ u32 control; ++ ++ if (nidx == XHCI_RING_ITEMS-1) { ++ dst = ring->ring + nidx; ++ control = (TR_LINK << 10); // trb type ++ control |= TRB_LK_TC; ++ control |= (cs ? TRB_C : 0); ++ SET_LOWFLAT(dst->ptr_low, (u32)&ring[0]); ++ SET_LOWFLAT(dst->ptr_high, 0); ++ SET_LOWFLAT(dst->status, 0); ++ SET_LOWFLAT(dst->control, control); ++ nidx = 0; ++ cs = cs ? 0 : 1; ++ SET_LOWFLAT(ring->nidx, nidx); ++ SET_LOWFLAT(ring->cs, cs); ++ ++ dprintf(5, "%s: ring %p [linked]\n", __func__, ring); ++ } ++ ++ dst = ring->ring + nidx; ++ control = GET_LOWFLAT(trb->control) | (cs ? TRB_C : 0); ++ ++ SET_LOWFLAT(dst->ptr_low, GET_LOWFLAT(trb->ptr_low)); ++ SET_LOWFLAT(dst->ptr_high, GET_LOWFLAT(trb->ptr_high)); ++ SET_LOWFLAT(dst->status, GET_LOWFLAT(trb->status)); ++ SET_LOWFLAT(dst->control, control); ++ nidx++; ++ SET_LOWFLAT(ring->nidx, nidx); ++ ++ dprintf(5, "%s: ring %p [nidx %d, len %d]\n", ++ __func__, ring, nidx, ++ GET_LOWFLAT(trb->status) & 0xffff); ++} ++ ++static void xhci_xfer_queue(struct xhci_pipe *pipe, ++ struct xhci_trb *trb) ++{ ++ xhci_trb_queue(&pipe->reqs, trb); ++} ++ ++static void xhci_xfer_kick(struct xhci_pipe *pipe) ++{ ++ struct xhci_device *dev = GET_LOWFLAT(pipe->dev); ++ struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); ++ u32 slotid = GET_LOWFLAT(dev->slotid); ++ u32 epid = GET_LOWFLAT(pipe->epid); ++ ++ dprintf(5, "%s: ring %p, slotid %d, epid %d\n", ++ __func__, &pipe->reqs, slotid, epid); ++ xhci_doorbell(xhci, slotid, epid); ++} ++ ++static void xhci_xfer_normal(struct xhci_pipe *pipe, ++ void *data, int datalen) ++{ ++ struct xhci_trb trb; ++ ++ memset(&trb, 0, sizeof(trb)); ++ trb.ptr_low = (u32)data; ++ trb.status = datalen; ++ trb.control |= (TR_NORMAL << 10); // trb type ++ trb.control |= TRB_TR_IOC; ++ ++ xhci_xfer_queue(pipe, MAKE_FLATPTR(GET_SEG(SS), &trb)); ++ xhci_xfer_kick(pipe); ++} ++ ++// -------------------------------------------------------------- ++// internal functions, pure 32bit ++ ++static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout) ++{ ++ ASSERT32FLAT(); ++ u32 end = timer_calc(timeout); ++ ++ while ((readl(reg) & mask) != value) { ++ if (timer_check(end)) { ++ warn_timeout(); ++ return -1; ++ } ++ yield(); ++ } ++ return 0; ++} ++ ++static int xhci_cmd_submit(struct usb_xhci_s *xhci, ++ struct xhci_trb *cmd) ++{ ++ ASSERT32FLAT(); ++ int rc; ++ ++ mutex_lock(&xhci->cmds->lock); ++ xhci_trb_queue(xhci->cmds, cmd); ++ xhci_doorbell(xhci, 0, 0); ++ rc = xhci_event_wait(xhci, xhci->cmds, 1000); ++ mutex_unlock(&xhci->cmds->lock); ++ return rc; ++} ++ ++static int xhci_cmd_enable_slot(struct usb_xhci_s *xhci) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb cmd = { ++ .ptr_low = 0, ++ .ptr_high = 0, ++ .status = 0, ++ .control = (CR_ENABLE_SLOT << 10) ++ }; ++ dprintf(3, "%s:\n", __func__); ++ int cc = xhci_cmd_submit(xhci, &cmd); ++ if (cc != CC_SUCCESS) ++ return -1; ++ return (xhci->cmds->evt.control >> 24) & 0xff; ++} ++ ++static int xhci_cmd_disable_slot(struct xhci_device *dev) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb cmd = { ++ .ptr_low = 0, ++ .ptr_high = 0, ++ .status = 0, ++ .control = (dev->slotid << 24) | (CR_DISABLE_SLOT << 10) ++ }; ++ dprintf(3, "%s: slotid %d\n", __func__, dev->slotid); ++ return xhci_cmd_submit(dev->xhci, &cmd); ++} ++ ++static int xhci_cmd_address_device(struct xhci_device *dev) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb cmd = { ++ .ptr_low = (u32)&dev->inctx, ++ .ptr_high = 0, ++ .status = 0, ++ .control = (dev->slotid << 24) | (CR_ADDRESS_DEVICE << 10) ++ }; ++ dprintf(3, "%s: slotid %d\n", __func__, dev->slotid); ++ return xhci_cmd_submit(dev->xhci, &cmd); ++} ++ ++static int xhci_cmd_configure_endpoint(struct xhci_device *dev) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb cmd = { ++ .ptr_low = (u32)&dev->inctx, ++ .ptr_high = 0, ++ .status = 0, ++ .control = (dev->slotid << 24) | (CR_CONFIGURE_ENDPOINT << 10) ++ }; ++ dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__, ++ dev->slotid, dev->inctx.add, dev->inctx.del); ++ return xhci_cmd_submit(dev->xhci, &cmd); ++} ++ ++static int xhci_cmd_evaluate_context(struct xhci_device *dev) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb cmd = { ++ .ptr_low = (u32)&dev->inctx, ++ .ptr_high = 0, ++ .status = 0, ++ .control = (dev->slotid << 24) | (CR_EVALUATE_CONTEXT << 10) ++ }; ++ dprintf(3, "%s: slotid %d, add 0x%x, del 0x%x\n", __func__, ++ dev->slotid, dev->inctx.add, dev->inctx.del); ++ return xhci_cmd_submit(dev->xhci, &cmd); ++} ++ ++static void xhci_xfer_setup(struct xhci_pipe *pipe, ++ const struct usb_ctrlrequest *req, ++ int dir, int datalen) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb trb; ++ ++ memset(&trb, 0, sizeof(trb)); ++ trb.ptr_low |= req->bRequestType; ++ trb.ptr_low |= (req->bRequest) << 8; ++ trb.ptr_low |= (req->wValue) << 16; ++ trb.ptr_high |= req->wIndex; ++ trb.ptr_high |= (req->wLength) << 16; ++ trb.status |= 8; // length ++ trb.control |= (TR_SETUP << 10); // trb type ++ trb.control |= TRB_TR_IDT; ++ if (datalen) ++ trb.control |= (dir ? 3 : 2) << 16; // transfer type ++ xhci_xfer_queue(pipe, &trb); ++} ++ ++static void xhci_xfer_data(struct xhci_pipe *pipe, ++ int dir, void *data, int datalen) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb trb; ++ ++ memset(&trb, 0, sizeof(trb)); ++ trb.ptr_low = (u32)data; ++ trb.status = datalen; ++ trb.control |= (TR_DATA << 10); // trb type ++ if (dir) ++ trb.control |= (1 << 16); ++ xhci_xfer_queue(pipe, &trb); ++} ++ ++static void xhci_xfer_status(struct xhci_pipe *pipe, int dir) ++{ ++ ASSERT32FLAT(); ++ struct xhci_trb trb; ++ ++ memset(&trb, 0, sizeof(trb)); ++ trb.control |= (TR_STATUS << 10); // trb type ++ trb.control |= TRB_TR_IOC; ++ if (dir) ++ trb.control |= (1 << 16); ++ ++ xhci_xfer_queue(pipe, &trb); ++ xhci_xfer_kick(pipe); ++} ++ ++static struct xhci_device *xhci_find_alloc_device(struct usb_xhci_s *xhci, ++ struct usbdevice_s *usbdev) ++{ ++ ASSERT32FLAT(); ++ struct xhci_device *dev; ++ ++ hlist_for_each_entry(dev, &xhci->list, next) { ++ if (dev->usbdev == usbdev) { ++ return dev; ++ } ++ } ++ ++ dev = memalign_low(64, sizeof(*dev)); ++ if (!dev) { ++ warn_noalloc(); ++ return NULL; ++ } ++ memset(dev, 0, sizeof(*dev)); ++ dev->usbdev = usbdev; ++ dev->xhci = xhci; ++ hlist_add_head(&dev->next, &xhci->list); ++ return dev; ++} ++ ++static void ++configure_xhci(void *data) ++{ ++ ASSERT32FLAT(); ++ struct usb_xhci_s *xhci = data; ++ u32 reg; ++ ++ xhci->devs = memalign_high(64, sizeof(*xhci->devs) * (xhci->slots + 1)); ++ xhci->eseg = memalign_high(64, sizeof(*xhci->eseg)); ++ xhci->cmds = memalign_high(XHCI_RING_SIZE, sizeof(*xhci->cmds)); ++ xhci->evts = memalign_low(XHCI_RING_SIZE, sizeof(*xhci->evts)); ++ if (!xhci->devs || !xhci->cmds || !xhci->evts || !xhci->eseg) { ++ warn_noalloc(); ++ goto fail; ++ } ++ memset(xhci->devs, 0, sizeof(*xhci->devs) * (xhci->slots + 1)); ++ memset(xhci->cmds, 0, sizeof(*xhci->cmds)); ++ memset(xhci->evts, 0, sizeof(*xhci->evts)); ++ memset(xhci->eseg, 0, sizeof(*xhci->eseg)); ++ ++ reg = readl(&xhci->op->usbcmd); ++ if (reg & XHCI_CMD_RS) { ++ reg &= ~XHCI_CMD_RS; ++ writel(&xhci->op->usbcmd, reg); ++ if (wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32) != 0) ++ goto fail; ++ } ++ ++ dprintf(3, "%s: resetting\n", __func__); ++ writel(&xhci->op->usbcmd, XHCI_CMD_HCRST); ++ if (wait_bit(&xhci->op->usbcmd, XHCI_CMD_HCRST, 0, 100) != 0) ++ goto fail; ++ if (wait_bit(&xhci->op->usbsts, XHCI_STS_CNR, 0, 100) != 0) ++ goto fail; ++ ++ writel(&xhci->op->config, xhci->slots); ++ writel(&xhci->op->dcbaap_low, (u32)xhci->devs); ++ writel(&xhci->op->dcbaap_high, 0); ++ writel(&xhci->op->crcr_low, (u32)xhci->cmds | 1); ++ writel(&xhci->op->crcr_high, 0); ++ xhci->cmds->cs = 1; ++ ++ xhci->eseg->ptr_low = (u32)xhci->evts; ++ xhci->eseg->ptr_high = 0; ++ xhci->eseg->size = XHCI_RING_ITEMS; ++ writel(&xhci->ir->erstsz, 1); ++ writel(&xhci->ir->erdp_low, (u32)xhci->evts); ++ writel(&xhci->ir->erdp_high, 0); ++ writel(&xhci->ir->erstba_low, (u32)xhci->eseg); ++ writel(&xhci->ir->erstba_high, 0); ++ xhci->evts->cs = 1; ++ ++ reg = readl(&xhci->op->usbcmd); ++ reg |= XHCI_CMD_RS; ++ writel(&xhci->op->usbcmd, reg); ++ ++ // FIXME: try find a more elegant way than a fixed delay ++ mdelay(100); ++ ++ usb_enumerate(&xhci->hub); ++ if (xhci->hub.devcount) ++ return; ++ ++ // No devices found - shutdown and free controller. ++ dprintf(1, "XHCI no devices found\n"); ++ reg = readl(&xhci->op->usbcmd); ++ reg &= ~XHCI_CMD_RS; ++ writel(&xhci->op->usbcmd, reg); ++ wait_bit(&xhci->op->usbsts, XHCI_STS_HCH, XHCI_STS_HCH, 32); ++ ++fail: ++ free(xhci->eseg); ++ free(xhci->evts); ++ free(xhci->cmds); ++ free(xhci->devs); ++ free(xhci); ++} ++ ++// -------------------------------------------------------------- ++// xhci root hub ++ ++// Check if device attached to port ++static void ++xhci_print_port_state(int loglevel, const char *prefix, u32 port, u32 portsc) ++{ ++ ASSERT32FLAT(); ++ u32 pls = xhci_get_field(portsc, XHCI_PORTSC_PLS); ++ u32 speed = xhci_get_field(portsc, XHCI_PORTSC_SPEED); ++ ++ dprintf(loglevel, "%s port #%d: 0x%08x,%s%s pls %d, speed %d [%s]\n", ++ prefix, port + 1, portsc, ++ (portsc & XHCI_PORTSC_PP) ? " powered," : "", ++ (portsc & XHCI_PORTSC_PED) ? " enabled," : "", ++ pls, speed, speed_name[speed]); ++} ++ ++static int ++xhci_hub_detect(struct usbhub_s *hub, u32 port) ++{ ++ ASSERT32FLAT(); ++ struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); ++ u32 portsc = readl(&xhci->pr[port].portsc); ++ ++ xhci_print_port_state(3, __func__, port, portsc); ++ switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) { ++ case PLS_U0: ++ case PLS_POLLING: ++ return 0; ++ default: ++ return -1; ++ } ++} ++ ++// Reset device on port ++static int ++xhci_hub_reset(struct usbhub_s *hub, u32 port) ++{ ++ ASSERT32FLAT(); ++ struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); ++ u32 portsc = readl(&xhci->pr[port].portsc); ++ int rc; ++ ++ switch (xhci_get_field(portsc, XHCI_PORTSC_PLS)) { ++ case PLS_U0: ++ rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)]; ++ break; ++ case PLS_POLLING: ++ xhci_print_port_state(3, __func__, port, portsc); ++ portsc |= XHCI_PORTSC_PR; ++ writel(&xhci->pr[port].portsc, portsc); ++ if (wait_bit(&xhci->pr[port].portsc, XHCI_PORTSC_PED, XHCI_PORTSC_PED, 100) != 0) ++ return -1; ++ portsc = readl(&xhci->pr[port].portsc); ++ rc = speed_from_xhci[xhci_get_field(portsc, XHCI_PORTSC_SPEED)]; ++ break; ++ default: ++ rc = -1; ++ break; ++ } ++ ++ xhci_print_port_state(1, "XHCI", port, portsc); ++ return rc; ++} ++ ++static void ++xhci_hub_disconnect(struct usbhub_s *hub, u32 port) ++{ ++ ASSERT32FLAT(); ++ struct usb_xhci_s *xhci = container_of(hub->cntl, struct usb_xhci_s, usb); ++ struct xhci_device *dev; ++ ++ hlist_for_each_entry(dev, &xhci->list, next) { ++ if (dev->usbdev->hub == hub && ++ dev->usbdev->port == port && ++ dev->slotid != 0) { ++ xhci_cmd_disable_slot(dev); ++ hlist_del(&dev->next); ++ return; ++ } ++ } ++} ++ ++static struct usbhub_op_s xhci_hub_ops = { ++ .detect = xhci_hub_detect, ++ .reset = xhci_hub_reset, ++ .disconnect = xhci_hub_disconnect, ++}; ++ ++// -------------------------------------------------------------- ++// external interface ++ ++struct usb_pipe * ++xhci_alloc_pipe(struct usbdevice_s *usbdev ++ , struct usb_endpoint_descriptor *epdesc) ++{ ++ ASSERT32FLAT(); ++ if (!CONFIG_USB_XHCI) ++ return NULL; ++ u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; ++ struct usb_xhci_s *xhci = container_of( ++ usbdev->hub->cntl, struct usb_xhci_s, usb); ++ struct xhci_pipe *pipe; ++ u32 epid; ++ ++ if (epdesc->bEndpointAddress == 0) { ++ epid = 1; ++ } else { ++ epid = (epdesc->bEndpointAddress & 0x0f) * 2; ++ epid += (epdesc->bEndpointAddress & USB_DIR_IN) ? 1 : 0; ++ } ++ ++ if (eptype == USB_ENDPOINT_XFER_CONTROL) ++ pipe = memalign_high(XHCI_RING_SIZE, sizeof(*pipe)); ++ else ++ pipe = memalign_low(XHCI_RING_SIZE, sizeof(*pipe)); ++ if (!pipe) { ++ warn_noalloc(); ++ return NULL; ++ } ++ memset(pipe, 0, sizeof(*pipe)); ++ ++ usb_desc2pipe(&pipe->pipe, usbdev, epdesc); ++ pipe->dev = xhci_find_alloc_device(xhci, usbdev); ++ if (!pipe->dev) { ++ free(pipe); ++ return NULL; ++ } ++ pipe->epid = epid; ++ pipe->reqs.cs = 1; ++ if (eptype == USB_ENDPOINT_XFER_INT) ++ pipe->buf = malloc_low(pipe->pipe.maxpacket); ++ ++ dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__, ++ usbdev, &pipe->reqs, pipe->dev->slotid, pipe->epid); ++ if (pipe->epid > 1 && pipe->dev->slotid) { ++ struct xhci_inctx *in = &pipe->dev->inctx; ++ in->add = (1 << pipe->epid) | 1; ++ in->del = 0; ++ ++ in->slot.ctx[0] |= (31 << 27); // context entries ++ ++ int e = pipe->epid-1; ++ in->ep[e].ctx[1] |= (eptype << 3); ++ if (epdesc->bEndpointAddress & USB_DIR_IN) ++ in->ep[e].ctx[1] |= (1 << 5); ++ in->ep[e].ctx[1] |= (pipe->pipe.maxpacket << 16); ++ in->ep[e].deq_low = (u32)&pipe->reqs.ring[0]; ++ in->ep[e].deq_low |= 1; // dcs ++ in->ep[e].deq_high = 0; ++ in->ep[e].length = pipe->pipe.maxpacket; ++ ++ int cc = xhci_cmd_configure_endpoint(pipe->dev); ++ if (cc != CC_SUCCESS) { ++ dprintf(1, "%s: configure endpoint: failed (cc %d)\n", __func__, cc); ++ free(pipe); ++ return NULL; ++ } ++ } ++ ++ return &pipe->pipe; ++} ++ ++struct usb_pipe * ++xhci_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *upipe ++ , struct usb_endpoint_descriptor *epdesc) ++{ ++ ASSERT32FLAT(); ++ if (!CONFIG_USB_XHCI) ++ return NULL; ++ u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; ++ struct xhci_pipe *pipe = container_of(upipe, struct xhci_pipe, pipe); ++ dprintf(3, "%s: usbdev %p, ring %p, slotid %d, epid %d\n", __func__, ++ usbdev, &pipe->reqs, pipe->dev->slotid, pipe->epid); ++ if (eptype == USB_ENDPOINT_XFER_CONTROL && ++ pipe->pipe.maxpacket != epdesc->wMaxPacketSize) { ++ dprintf(1, "%s: reconf ctl endpoint pkt size: %d -> %d\n", ++ __func__, pipe->pipe.maxpacket, epdesc->wMaxPacketSize); ++ pipe->pipe.maxpacket = epdesc->wMaxPacketSize; ++ struct xhci_inctx *in = &pipe->dev->inctx; ++ in->add = (1 << 1); ++ in->del = 0; ++ in->ep[0].ctx[1] &= 0xffff; ++ in->ep[0].ctx[1] |= (pipe->pipe.maxpacket << 16); ++ int cc = xhci_cmd_evaluate_context(pipe->dev); ++ if (cc != CC_SUCCESS) { ++ dprintf(1, "%s: reconf ctl endpoint: failed (cc %d)\n", ++ __func__, cc); ++ } ++ } ++ return upipe; ++} ++ ++int ++xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize ++ , void *data, int datalen) ++{ ++ ASSERT32FLAT(); ++ if (!CONFIG_USB_XHCI) ++ return -1; ++ const struct usb_ctrlrequest *req = cmd; ++ struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); ++ struct usb_xhci_s *xhci = pipe->dev->xhci; ++ int cc; ++ ++ if (req->bRequest == USB_REQ_SET_ADDRESS) { ++ int slotid = xhci_cmd_enable_slot(xhci); ++ if (slotid < 0) { ++ dprintf(1, "%s: enable slot: failed\n", __func__); ++ return -1; ++ } ++ dprintf(3, "%s: enable slot: got slotid %d\n", __func__, slotid); ++ pipe->dev->slotid = slotid; ++ xhci->devs[slotid].ptr_low = (u32)&pipe->dev->devctx; ++ xhci->devs[slotid].ptr_high = 0; ++ ++ struct usbdevice_s *usbdev = pipe->dev->usbdev; ++ u32 route = 0; ++ while (usbdev->hub->usbdev) { ++ route <<= 4; ++ route |= (usbdev->port+1) & 0xf; ++ usbdev = usbdev->hub->usbdev; ++ } ++ dprintf(3, "%s: root port %d, route 0x%x\n", ++ __func__, usbdev->port+1, route); ++ ++ struct xhci_inctx *in = &pipe->dev->inctx; ++ in->add = 0x03; ++ in->slot.ctx[0] |= (1 << 27); // context entries ++ in->slot.ctx[0] |= speed_to_xhci[pipe->dev->usbdev->speed] << 20; ++ in->slot.ctx[0] |= route; ++ in->slot.ctx[1] |= (usbdev->port+1) << 16; ++ /* TODO ctx0: hub bit */ ++ /* TODO ctx1: hub ports */ ++ ++ in->ep[0].ctx[0] |= (3 << 16); // interval: 1ms ++ in->ep[0].ctx[1] |= (4 << 3); // control pipe ++ in->ep[0].ctx[1] |= (speed_to_ctlsize[pipe->dev->usbdev->speed] << 16); ++ ++ in->ep[0].deq_low = (u32)&pipe->reqs.ring[0]; ++ in->ep[0].deq_low |= 1; // dcs ++ in->ep[0].deq_high = 0; ++ in->ep[0].length = 8; ++ ++ cc = xhci_cmd_address_device(pipe->dev); ++ if (cc != CC_SUCCESS) { ++ dprintf(1, "%s: address device: failed (cc %d)\n", __func__, cc); ++ return -1; ++ } ++ return 0; ++ } ++ ++ xhci_xfer_setup(pipe, req, dir, datalen); ++ if (datalen) ++ xhci_xfer_data(pipe, dir, data, datalen); ++ xhci_xfer_status(pipe, dir); ++ ++ cc = xhci_event_wait(xhci, &pipe->reqs, 1000); ++ if (cc != CC_SUCCESS) { ++ dprintf(1, "%s: control xfer failed (cc %d)\n", __func__, cc); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ++xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datalen) ++{ ++ if (!CONFIG_USB_XHCI) ++ return -1; ++ ++ struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); ++ struct xhci_device *dev = GET_LOWFLAT(pipe->dev); ++ struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); ++ ++ xhci_xfer_normal(pipe, data, datalen); ++ int cc = xhci_event_wait(xhci, &pipe->reqs, 1000); ++ if (cc != CC_SUCCESS) { ++ dprintf(1, "%s: bulk xfer failed (cc %d)\n", __func__, cc); ++ return -1; ++ } ++ return 0; ++} ++ ++int ++xhci_poll_intr(struct usb_pipe *p, void *data) ++{ ++ if (!CONFIG_USB_XHCI) ++ return -1; ++ ++ struct xhci_pipe *pipe = container_of(p, struct xhci_pipe, pipe); ++ struct xhci_device *dev = GET_LOWFLAT(pipe->dev); ++ struct usb_xhci_s *xhci = GET_LOWFLAT(dev->xhci); ++ u32 len = GET_LOWFLAT(pipe->pipe.maxpacket); ++ void *buf = GET_LOWFLAT(pipe->buf); ++ int bufused = GET_LOWFLAT(pipe->bufused); ++ ++ if (!bufused) { ++ xhci_xfer_normal(pipe, buf, len); ++ bufused = 1; ++ SET_LOWFLAT(pipe->bufused, bufused); ++ return -1; ++ } ++ ++ xhci_process_events(xhci); ++ if (xhci_ring_busy(&pipe->reqs)) ++ return -1; ++ dprintf(5, "%s: st %x ct %x [ %p <= %p / %d ]\n", __func__, ++ GET_LOWFLAT(pipe->reqs.evt.status), ++ GET_LOWFLAT(pipe->reqs.evt.control), ++ MAKE_FLATPTR(GET_SEG(SS), data), buf, len); ++ memcpy_fl(MAKE_FLATPTR(GET_SEG(SS), data), buf, len); ++ xhci_xfer_normal(pipe, buf, len); ++ return 0; ++} ++ ++int ++xhci_setup(struct pci_device *pci, int busid) ++{ ++ ASSERT32FLAT(); ++ if (!CONFIG_USB_XHCI) ++ return -1; ++ ++ struct usb_xhci_s *xhci = malloc_low(sizeof(*xhci)); ++ if (!xhci) { ++ warn_noalloc(); ++ return -1; ++ } ++ memset(xhci, 0, sizeof(*xhci)); ++ ++ xhci->baseaddr = pci_config_readl(pci->bdf, PCI_BASE_ADDRESS_0) ++ & PCI_BASE_ADDRESS_MEM_MASK; ++ xhci->caps = (void*)(xhci->baseaddr); ++ xhci->op = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength)); ++ xhci->pr = (void*)(xhci->baseaddr + readb(&xhci->caps->caplength) + 0x400); ++ xhci->db = (void*)(xhci->baseaddr + readl(&xhci->caps->dboff)); ++ xhci->ir = (void*)(xhci->baseaddr + readl(&xhci->caps->rtsoff) + 0x20); ++ ++ u32 hcs1 = readl(&xhci->caps->hcsparams1); ++ u32 hcc = readl(&xhci->caps->hccparams); ++ xhci->ports = (hcs1 >> 24) & 0xff; ++ xhci->slots = hcs1 & 0xff; ++ xhci->xcap = ((hcc >> 16) & 0xffff) << 2; ++ ++ xhci->usb.busid = busid; ++ xhci->usb.pci = pci; ++ xhci->usb.type = USB_TYPE_XHCI; ++ xhci->hub.cntl = &xhci->usb; ++ xhci->hub.portcount = xhci->ports; ++ xhci->hub.op = &xhci_hub_ops; ++ ++ dprintf(1, "XHCI init on dev %02x:%02x.%x: regs @ %p, %d ports, %d slots\n" ++ , pci_bdf_to_bus(pci->bdf), pci_bdf_to_dev(pci->bdf) ++ , pci_bdf_to_fn(pci->bdf), xhci->caps ++ , xhci->ports, xhci->slots); ++ ++ if (xhci->xcap) { ++ u32 off, addr = xhci->baseaddr + xhci->xcap; ++ do { ++ struct xhci_xcap *xcap = (void*)addr; ++ u32 ports, name, cap = readl(&xcap->cap); ++ switch (cap & 0xff) { ++ case 0x02: ++ name = readl(&xcap->data[0]); ++ ports = readl(&xcap->data[1]); ++ dprintf(1, "XHCI protocol %c%c%c%c %x.%02x, %d ports (offset %d)\n" ++ , (name >> 0) & 0xff ++ , (name >> 8) & 0xff ++ , (name >> 16) & 0xff ++ , (name >> 24) & 0xff ++ , (cap >> 24) & 0xff ++ , (cap >> 16) & 0xff ++ , (ports >> 8) & 0xff ++ , (ports >> 0) & 0xff); ++ break; ++ default: ++ dprintf(1, "XHCI extcap 0x%x @ %x\n", cap & 0xff, addr); ++ break; ++ } ++ off = (cap >> 8) & 0xff; ++ addr += off << 2; ++ } while (off > 0); ++ } ++ ++ pci_config_maskw(pci->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); ++ ++ run_thread(configure_xhci, xhci); ++ return 0; ++} +diff --git a/src/usb-xhci.h b/src/usb-xhci.h +new file mode 100644 +index 0000000..64ee82c +--- /dev/null ++++ b/src/usb-xhci.h +@@ -0,0 +1,144 @@ ++#ifndef __USB_XHCI_H ++#define __USB_XHCI_H ++ ++struct usbdevice_s; ++struct usb_endpoint_descriptor; ++struct usb_pipe; ++ ++// -------------------------------------------------------------- ++ ++// usb-xhci.c ++int xhci_setup(struct pci_device *pci, int busid); ++struct usb_pipe *xhci_alloc_pipe(struct usbdevice_s *usbdev ++ , struct usb_endpoint_descriptor *epdesc); ++struct usb_pipe *xhci_update_pipe(struct usbdevice_s *usbdev ++ , struct usb_pipe *pipe ++ , struct usb_endpoint_descriptor *epdesc); ++int xhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize ++ , void *data, int datasize); ++int xhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); ++int xhci_poll_intr(struct usb_pipe *p, void *data); ++ ++// -------------------------------------------------------------- ++// register interface ++ ++// capabilities ++struct xhci_caps { ++ u8 caplength; ++ u8 reserved_01; ++ u16 hciversion; ++ u32 hcsparams1; ++ u32 hcsparams2; ++ u32 hcsparams3; ++ u32 hccparams; ++ u32 dboff; ++ u32 rtsoff; ++} PACKED; ++ ++// extended capabilities ++struct xhci_xcap { ++ u32 cap; ++ u32 data[]; ++} PACKED; ++ ++// operational registers ++struct xhci_op { ++ u32 usbcmd; ++ u32 usbsts; ++ u32 pagesize; ++ u32 reserved_01[2]; ++ u32 dnctl; ++ u32 crcr_low; ++ u32 crcr_high; ++ u32 reserved_02[4]; ++ u32 dcbaap_low; ++ u32 dcbaap_high; ++ u32 config; ++} PACKED; ++ ++// port registers ++struct xhci_pr { ++ u32 portsc; ++ u32 portpmsc; ++ u32 portli; ++ u32 reserved_01; ++} PACKED; ++ ++// doorbell registers ++struct xhci_db { ++ u32 doorbell; ++} PACKED; ++ ++// runtime registers ++struct xhci_rts { ++ u32 mfindex; ++} PACKED; ++ ++// interrupter registers ++struct xhci_ir { ++ u32 iman; ++ u32 imod; ++ u32 erstsz; ++ u32 reserved_01; ++ u32 erstba_low; ++ u32 erstba_high; ++ u32 erdp_low; ++ u32 erdp_high; ++} PACKED; ++ ++// -------------------------------------------------------------- ++// memory data structs ++ ++// slot context ++struct xhci_slotctx { ++ u32 ctx[4]; ++ u32 reserved_01[4]; ++} PACKED; ++ ++// endpoint context ++struct xhci_epctx { ++ u32 ctx[2]; ++ u32 deq_low; ++ u32 deq_high; ++ u32 length; ++ u32 reserved_01[3]; ++} PACKED; ++ ++// device context ++struct xhci_devctx { ++ struct xhci_slotctx slot; ++ struct xhci_epctx ep[31]; ++} PACKED; ++ ++// device context array element ++struct xhci_devlist { ++ u32 ptr_low; ++ u32 ptr_high; ++} PACKED; ++ ++// input context ++struct xhci_inctx { ++ u32 del; ++ u32 add; ++ u32 reserved_01[6]; ++ struct xhci_slotctx slot; ++ struct xhci_epctx ep[31]; ++} PACKED; ++ ++// transfer block (ring element) ++struct xhci_trb { ++ u32 ptr_low; ++ u32 ptr_high; ++ u32 status; ++ u32 control; ++} PACKED; ++ ++// event ring segment ++struct xhci_er_seg { ++ u32 ptr_low; ++ u32 ptr_high; ++ u32 size; ++ u32 reserved_01; ++} PACKED; ++ ++#endif // usb-xhci.h +diff --git a/src/usb.c b/src/usb.c +index 3efa367..1cdb612 100644 +--- a/src/usb.c ++++ b/src/usb.c +@@ -12,6 +12,7 @@ + #include "usb-uhci.h" // uhci_init + #include "usb-ohci.h" // ohci_init + #include "usb-ehci.h" // ehci_init ++#include "usb-xhci.h" // xhci_setup + #include "usb-hid.h" // usb_keyboard_setup + #include "usb-hub.h" // usb_hub_init + #include "usb-msc.h" // usb_msc_init +@@ -37,6 +38,8 @@ usb_alloc_pipe(struct usbdevice_s *usbdev + return ohci_alloc_pipe(usbdev, epdesc); + case USB_TYPE_EHCI: + return ehci_alloc_pipe(usbdev, epdesc); ++ case USB_TYPE_XHCI: ++ return xhci_alloc_pipe(usbdev, epdesc); + } + } + +@@ -46,6 +49,8 @@ usb_update_pipe(struct usbdevice_s *usbdev, struct usb_pipe *pipe + , struct usb_endpoint_descriptor *epdesc) + { + switch (usbdev->hub->cntl->type) { ++ case USB_TYPE_XHCI: ++ return xhci_update_pipe(usbdev, pipe, epdesc); + default: + free_pipe(pipe); + return usb_alloc_pipe(usbdev, epdesc); +@@ -66,6 +71,8 @@ send_control(struct usb_pipe *pipe, int dir, const void *cmd, int cmdsize + return ohci_control(pipe, dir, cmd, cmdsize, data, datasize); + case USB_TYPE_EHCI: + return ehci_control(pipe, dir, cmd, cmdsize, data, datasize); ++ case USB_TYPE_XHCI: ++ return xhci_control(pipe, dir, cmd, cmdsize, data, datasize); + } + } + +@@ -80,6 +87,8 @@ usb_send_bulk(struct usb_pipe *pipe_fl, int dir, void *data, int datasize) + return ohci_send_bulk(pipe_fl, dir, data, datasize); + case USB_TYPE_EHCI: + return ehci_send_bulk(pipe_fl, dir, data, datasize); ++ case USB_TYPE_XHCI: ++ return xhci_send_bulk(pipe_fl, dir, data, datasize); + } + } + +@@ -94,6 +103,8 @@ usb_poll_intr(struct usb_pipe *pipe_fl, void *data) + return ohci_poll_intr(pipe_fl, data); + case USB_TYPE_EHCI: + return ehci_poll_intr(pipe_fl, data); ++ case USB_TYPE_XHCI: ++ return xhci_poll_intr(pipe_fl, data); + } + } + +@@ -469,5 +480,7 @@ usb_setup(void) + uhci_init(pci, count++); + else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_OHCI) + ohci_init(pci, count++); ++ else if (pci_classprog(pci) == PCI_CLASS_SERIAL_USB_XHCI) ++ xhci_setup(pci, count++); + } + } +diff --git a/src/usb.h b/src/usb.h +index d9eadd7..a034aa6 100644 +--- a/src/usb.h ++++ b/src/usb.h +@@ -60,15 +60,17 @@ struct usbhub_op_s { + void (*disconnect)(struct usbhub_s *hub, u32 port); + }; + +-#define USB_TYPE_UHCI 1 +-#define USB_TYPE_OHCI 2 +-#define USB_TYPE_EHCI 3 ++#define USB_TYPE_UHCI 1 ++#define USB_TYPE_OHCI 2 ++#define USB_TYPE_EHCI 3 ++#define USB_TYPE_XHCI 4 + +-#define USB_FULLSPEED 0 +-#define USB_LOWSPEED 1 +-#define USB_HIGHSPEED 2 ++#define USB_FULLSPEED 0 ++#define USB_LOWSPEED 1 ++#define USB_HIGHSPEED 2 ++#define USB_SUPERSPEED 3 + +-#define USB_MAXADDR 127 ++#define USB_MAXADDR 127 + + + /**************************************************************** +-- +1.7.1 + diff --git a/SOURCES/seabios-xhci-adaptions-for-old-rhel7-seabios-codebase.patch b/SOURCES/seabios-xhci-adaptions-for-old-rhel7-seabios-codebase.patch new file mode 100644 index 0000000..879ee68 --- /dev/null +++ b/SOURCES/seabios-xhci-adaptions-for-old-rhel7-seabios-codebase.patch @@ -0,0 +1,87 @@ +From 9636beca521c90babc3424789dd13317806d36f7 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 2 Oct 2013 07:00:19 +0200 +Subject: [PATCH 7/8] xhci adaptions for old rhel7 seabios codebase + +RH-Author: Gerd Hoffmann +Message-id: <1380697219-1860-8-git-send-email-kraxel@redhat.com> +Patchwork-id: 54631 +O-Subject: [RHEL-7 seabios PATCH 7/7] xhci adaptions for old rhel7 seabios codebase +Bugzilla: 947051 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Bandan Das +RH-Acked-by: Miroslav Rezanina + +Kept as separate commit to make review easier. +rhel-only patch for obvious reasons. + +Signed-off-by: Gerd Hoffmann +--- + src/Kconfig | 2 +- + src/usb-xhci.c | 9 +++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +Signed-off-by: Miroslav Rezanina +--- + src/Kconfig | 2 +- + src/usb-xhci.c | 9 +++++---- + 2 files changed, 6 insertions(+), 5 deletions(-) + +diff --git a/src/Kconfig b/src/Kconfig +index b059a73..d00c66c 100644 +--- a/src/Kconfig ++++ b/src/Kconfig +@@ -185,7 +185,7 @@ menu "Hardware support" + help + Support USB EHCI controllers. + config USB_XHCI +- depends on USB && QEMU_HARDWARE ++ depends on USB && QEMU + bool "USB XHCI controllers" + default y + help +diff --git a/src/usb-xhci.c b/src/usb-xhci.c +index 5be0b25..3a4f3e0 100644 +--- a/src/usb-xhci.c ++++ b/src/usb-xhci.c +@@ -1,5 +1,6 @@ + #include "config.h" // CONFIG_* + #include "util.h" // timer_calc ++#include "list.h" // timer_calc + #include "pci.h" // pci_bdf_to_bus + #include "pci_regs.h" // PCI_BASE_ADDRESS_0 + #include "usb.h" // struct usb_s +@@ -387,7 +388,7 @@ static int xhci_event_wait(struct usb_xhci_s *xhci, + struct xhci_ring *ring, + u32 timeout) + { +- u32 end = timer_calc(timeout); ++ u64 end = calc_future_tsc(timeout); + + for (;;) { + xhci_process_events(xhci); +@@ -395,7 +396,7 @@ static int xhci_event_wait(struct usb_xhci_s *xhci, + u32 status = GET_LOWFLAT(ring->evt.status); + return (status >> 24) & 0xff; + } +- if (timer_check(end)) { ++ if (check_tsc(end)) { + warn_timeout(); + return -1; + } +@@ -482,10 +483,10 @@ static void xhci_xfer_normal(struct xhci_pipe *pipe, + static int wait_bit(u32 *reg, u32 mask, int value, u32 timeout) + { + ASSERT32FLAT(); +- u32 end = timer_calc(timeout); ++ u64 end = calc_future_tsc(timeout); + + while ((readl(reg) & mask) != value) { +- if (timer_check(end)) { ++ if (check_tsc(end)) { + warn_timeout(); + return -1; + } +-- +1.7.1 + diff --git a/SPECS/seabios.spec b/SPECS/seabios.spec new file mode 100644 index 0000000..4e6fdce --- /dev/null +++ b/SPECS/seabios.spec @@ -0,0 +1,276 @@ +Name: seabios +Version: 1.7.2.2 +Release: 4%{?dist} +Summary: Open-source legacy BIOS implementation + +Group: Applications/Emulators +License: LGPLv3 +URL: http://www.coreboot.org/SeaBIOS + + +# No source releases of seabios stable. To generate: +# git clone git://git.seabios.org/seabios.git && cd seabios +# git archive --output seabios-1.7.2.2.tar.gz --prefix seabios-1.7.2.2/ rel-1.7.2.2 +#Source0: http://code.coreboot.org/p/seabios/downloads/get/%{name}-%{version}.tar.gz +Source0: seabios-%{version}.tar.gz + +Source10: config.vga.cirrus +Source11: config.vga.isavga +Source12: config.vga.qxl +Source13: config.vga.stdvga +Source14: config.vga.vmware +Source15: config.base + +# Add pvpanic device driver (rhbz 967777) +Patch1: Add-pvpanic-device-driver.patch +# For bz#920140 - qemu-kvm emulation of 2.88M floppy fails +Patch2: seabios-floppy-Introduce-struct-floppy_pio_s-for-floppy-PIO-.patch +# For bz#920140 - qemu-kvm emulation of 2.88M floppy fails +Patch3: seabios-floppy-Cleanup-floppy-irq-wait-handling.patch +# For bz#920140 - qemu-kvm emulation of 2.88M floppy fails +Patch4: seabios-floppy-Implement-media-format-sensing.patch +# For bz#894979 - place rpm version info into version banner +Patch5: seabios-Place-rpm-version-info-into-version-banner.patch +# For bz#1005747 - fail to boot rhel7 guest with >126(21 ahci controller) ahci disks +Patch6: seabios-ahci-add-missing-check-for-allocation-failure.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch7: seabios-Introduce-and-convert-pmm-code-to-use-standard-list-.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch8: seabios-Fix-error-in-hlist_for_each_entry_safe-macro.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch9: seabios-Another-fix-for-hlist_for_each_entry_safe.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch10: seabios-uas-add-temporary-superspeed-stopgap.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch11: seabios-usb-add-usb_update_pipe.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch12: seabios-usb-add-xhci-support.patch +# For bz#947051 - [RFE] implement xhci support in seabios +Patch13: seabios-xhci-adaptions-for-old-rhel7-seabios-codebase.patch +# For bz#1016974 - [HP 7.0 FEAT]: Increase KVM guest supported memory to 4TiB +Patch14: seabios-allow-1TB-of-RAM.patch + +BuildRequires: python iasl +ExclusiveArch: x86_64 + +Requires: %{name}-bin = %{version}-%{release} +Requires: seavgabios-bin = %{version}-%{release} +Buildarch: x86_64 + +# Seabios is noarch, but required on architectures which cannot build it. +# Disable debuginfo because it is of no use to us. +%global debug_package %{nil} + +# You can build a debugging version of the BIOS by setting this to a +# value > 1. See src/config.h for possible values, but setting it to +# a number like 99 will enable all possible debugging. Note that +# debugging goes to a special qemu port that you have to enable. See +# the SeaBIOS top-level README file for the magic qemu invocation to +# enable this. +%global debug_level 1 + + +%description +SeaBIOS is an open-source legacy BIOS implementation which can be used as +a coreboot payload. It implements the standard BIOS calling interfaces +that a typical x86 proprietary BIOS implements. + + +%package bin +Summary: Seabios for x86 +Buildarch: noarch + + +%description bin +SeaBIOS is an open-source legacy BIOS implementation which can be used as +a coreboot payload. It implements the standard BIOS calling interfaces +that a typical x86 proprietary BIOS implements. + + +%package -n seavgabios-bin +Summary: Seavgabios for x86 +Buildarch: noarch + +Obsoletes: vgabios < vgabios-0.6c-10 +Provides: vgabios = vgabios-0.6c-10 + + +%description -n seavgabios-bin +SeaVGABIOS is an open-source VGABIOS implementation. + + +%prep +%setup -q +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 + +# Store version to be used +echo "%{name}-%{version}-%release" > .version + +%build +cp %{SOURCE15} .config +make oldnoconfig V=1 +sed -i 's,CONFIG_DEBUG_LEVEL=.*,CONFIG_DEBUG_LEVEL=%{debug_level},g' .config + +export CFLAGS="$RPM_OPT_FLAGS" +mkdir binaries + +# seabios +make +cp out/bios.bin binaries + +# seavgabios +for config in %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14}; do + name=${config#*config.vga.} + make clean distclean + cp ${config} .config + echo "CONFIG_DEBUG_LEVEL=%{debug_level}" >> .config + make oldnoconfig + make + cp out/vgabios.bin binaries/vgabios-${name}.bin +done + + +%install +mkdir -p $RPM_BUILD_ROOT%{_datadir}/seabios +mkdir -p $RPM_BUILD_ROOT%{_datadir}/seavgabios +install -m 0644 binaries/bios.bin $RPM_BUILD_ROOT%{_datadir}/seabios +install -m 0644 binaries/vgabios*.bin $RPM_BUILD_ROOT%{_datadir}/seavgabios + + +%files +%doc COPYING COPYING.LESSER README TODO + + +%files bin +%dir %{_datadir}/seabios/ +%{_datadir}/seabios/bios.bin + +%files -n seavgabios-bin +%dir %{_datadir}/seavgabios/ +%{_datadir}/seavgabios/vgabios*.bin + + +%changelog +* Tue Nov 05 2013 Miroslav Rezanina - 1.7.2.2-4.el7 +- seabios-Introduce-and-convert-pmm-code-to-use-standard-list-.patch [bz#947051] +- seabios-Fix-error-in-hlist_for_each_entry_safe-macro.patch [bz#947051] +- seabios-Another-fix-for-hlist_for_each_entry_safe.patch [bz#947051] +- seabios-uas-add-temporary-superspeed-stopgap.patch [bz#947051] +- seabios-usb-add-usb_update_pipe.patch [bz#947051] +- seabios-usb-add-xhci-support.patch [bz#947051] +- seabios-xhci-adaptions-for-old-rhel7-seabios-codebase.patch [bz#947051] +- seabios-allow-1TB-of-RAM.patch [bz#1016974] +- Resolves: bz#1016974 + ([HP 7.0 FEAT]: Increase KVM guest supported memory to 4TiB) +- Resolves: bz#947051 + ([RFE] implement xhci support in seabios) + +* Tue Sep 24 2013 Miroslav Rezanina - seabios-1.7.2.2-3.el7 +- seabios-floppy-Introduce-struct-floppy_pio_s-for-floppy-PIO-.patch [bz#920140] +- seabios-floppy-Cleanup-floppy-irq-wait-handling.patch [bz#920140] +- seabios-floppy-Implement-media-format-sensing.patch [bz#920140] +- seabios-Place-rpm-version-info-into-version-banner.patch [bz#894979] +- seabios-ahci-add-missing-check-for-allocation-failure.patch [bz#1005747] +- Resolves: bz#1005747 + (fail to boot rhel7 guest with >126(21 ahci controller) ahci disks) +- Resolves: bz#894979 + (place rpm version info into version banner) +- Resolves: bz#920140 + (qemu-kvm emulation of 2.88M floppy fails) + +* Wed Jun 26 2013 Miroslav Rezanina - 1.7.2.2-2 +- Disable options not used / not supported by RHEL-7 (rhbz 927582) +- Add pvpanic device driver (rhbz 967777) +- Obsolete vgabios (rhbz 976340) + +* Tue Jun 04 2013 Miroslav Rezanina - 1.7.2.2-1 +- Rebase to 1.7.2.2 + +* Tue Dec 18 2012 Michal Novotny - 1.7.1-5 +- Remove the cross compilation code as we compile it on x86_64 always + +* Thu Dec 6 2012 Peter Robinson 1.7.1-4 +- Root seabios package is noarch too because it only contains docs + +* Fri Oct 19 2012 Cole Robinson - 1.7.1-3 +- Add seavgabios subpackage + +* Wed Oct 17 2012 Paolo Bonzini - 1.7.1-2 +- Build with cross compiler. Resolves: #866664. + +* Wed Sep 05 2012 Cole Robinson - 1.7.1-1 +- Rebased to version 1.7.1 +- Initial support for booting from USB attached scsi (USB UAS) drives +- USB EHCI 64bit controller support +- USB MSC multi-LUN device support +- Support for booting from LSI SCSI controllers on emulators +- Support for booting from AMD PCscsi controllers on emulators + +* Mon Aug 13 2012 Richard W.M. Jones - 1.7.0-4 +- Modernise and tidy up the RPM. +- Allow debug versions of SeaBIOS to be built easily. + +* Mon Aug 06 2012 Cole Robinson - 1.7.0-3 +- Enable S3/S4 support for guests (it's an F18 feature after all) + +* Sat Jul 21 2012 Fedora Release Engineering - 1.7.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon May 28 2012 Cole Robinson - 1.7.0-1 +- Rebased to version 1.7.0 +- Support for virtio-scsi +- Improved USB drive support +- Several USB controller bug fixes and improvements + +* Wed Mar 28 2012 Paolo Bonzini - 1.6.3-2 +- Fix bugs in booting from host (or redirected) USB pen drives + +* Wed Feb 08 2012 Justin M. Forbes - 1.6.3-1 +- Update to 1.6.3 upstream +- Add virtio-scsi + +* Sat Jan 14 2012 Fedora Release Engineering - 0.6.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Oct 05 2011 Justin M. Forbes - 0.6.2-3 +- Stop advertising S3 and S4 in DSDT (bz#741375) +- incdule iasl buildreq + +* Wed Jul 13 2011 Justin M. Forbes - 0.6.2-2 +- Fix QXL bug in 0.6.2 + +* Wed Jul 13 2011 Justin M. forbes - 0.6.2-1 +- Update to 0.6.2 upstream for a number of bugfixes + +* Mon Feb 14 2011 Justin M. forbes - 0.6.1-1 +- Update to 0.6.1 upstream for a number of bugfixes + +* Wed Feb 09 2011 Fedora Release Engineering - 0.6.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Aug 10 2010 Justin M. Forbes 0.6.0-1 +- Update seabios to latest stable so we can drop patches. + +* Tue Apr 20 2010 Justin M. Forbes 0.5.1-2 +- Ugly hacks to make package noarch and available for arch that cannot build it. +- Disable useless debuginfo + +* Wed Mar 03 2010 Justin M. Forbes 0.5.1-1 +- Update to 0.5.1 stable release +- Pick up patches required for current qemu + +* Thu Jan 07 2010 Justin M. Forbes 0.5.1-0.1.20100108git669c991 +- Created initial package