Compare commits

...
171 Commits
Author SHA1 Message Date
(no author) 8f1a4fd795 This commit was manufactured by cvs2svn to create tag
'release_0_8_2'.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_8_2@2069 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-22 17:06:45 +00:00
bellard 47dbd1f32d error display fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2068 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-22 17:06:44 +00:00
pbrook d07edbfa00 Fix Arm cp15 c13 (Process ID) register writes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2067 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-21 22:39:57 +00:00
bellard 059809e451 usb destroy API change (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2066 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-19 18:06:15 +00:00
bellard 3b2ccc57c7 Linux compilation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2065 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-19 17:54:57 +00:00
bellard 74ccb34e6b Sparc64 host support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2064 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-18 21:23:34 +00:00
bellard 5ef54116ea Sparc64 user emulator fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2063 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-18 21:14:09 +00:00
bellard 725cb90bf7 sparc64 fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2062 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-18 21:12:17 +00:00
bellard a3c259974e audio capture fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2061 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-18 21:09:59 +00:00
pbrook 69db0ac75a Fix comment typo.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2060 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-17 18:45:34 +00:00
bellard ec36b695b0 audio capture to wab files (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2059 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-16 18:57:03 +00:00
bellard 6330126439 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2058 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-16 18:56:50 +00:00
pbrook 634fce96eb Defer timer initialization until after commandline processing.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2057 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-15 17:40:09 +00:00
bellard 13224a87fb added mouse event generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2056 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 22:03:35 +00:00
bellard 7ba1260ac1 generate CRLF instead of LF
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2055 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 20:26:42 +00:00
bellard bd468840d4 fixed LF interpretation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2054 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 20:24:31 +00:00
bellard 3c656346c9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2053 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 13:13:51 +00:00
bellard 29b9a3456f win32 compilation fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2052 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 09:40:02 +00:00
bellard a8e5ac33d2 win32 compilation - force process affinity on win32 as a workaround for SMP issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2051 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-14 09:36:13 +00:00
bellard ec607da7c2 avoid recursive tx
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2050 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-13 23:25:11 +00:00
bellard 1dce7c3c22 new clock logic: cpu ticks and virtual clocks are no longer proportional - added timestamps on the stdio console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2049 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-13 23:20:22 +00:00
bellard effedbc915 export cpu_get_real_ticks()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2048 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-13 23:00:40 +00:00
bellard 9f909fefd5 use posix timers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2047 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-13 23:00:26 +00:00
bellard 718da2b9b0 fixed for TCP segmentation offloading - removed dependency on slirp.h (Igor Kovalenko)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2046 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-10 21:38:17 +00:00
bellard 0de6bb73fd monitor/mwait workaround
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2045 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-10 19:53:43 +00:00
bellard 3d7374c5da monitor/mwait support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2044 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-10 19:53:04 +00:00
pbrook 4f2092904d Don't include audio.h when building tools.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2043 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-05 14:39:57 +00:00
bellard d929eba5d4 audio endianness API changes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2042 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 21:47:22 +00:00
bellard 219fb12503 avoid unneeded dependencies
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2041 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 21:42:10 +00:00
bellard 8ead62cfc2 audio fixes + initial audio capture support (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2040 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 16:51:32 +00:00
bellard feea13e186 sb16 fixes (WfW 3 appears to work with shipped drivers) (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2039 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 16:49:00 +00:00
bellard 6c270db741 rate converter fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2038 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 16:47:58 +00:00
bellard 47378eb1ca update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2037 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 16:33:33 +00:00
bellard e3c2613f91 pcnet nic support (Antony T Curtis)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2036 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 11:33:00 +00:00
bellard 6cadb320c7 rtl8139 fixes (Igor Kovalenko)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2035 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 10:08:36 +00:00
bellard 856074ec70 fix for IO_MEM_ROMD support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2034 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 09:47:34 +00:00
bellard 99ba31b4fe flash device fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2033 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-04 09:46:31 +00:00
bellard 0510224e89 disable unimplemented C+ mode (aka windows xp 64 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2032 c046a42c-6fe2-441c-8c8c-71466251a162
2006-07-01 21:41:18 +00:00
bellard 106ec87921 initial MIPS signal handling (initial patch by Raphael Rigo)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2031 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-27 21:08:10 +00:00
bellard 951f13516a telnet protocol and more consistent syntax (Jason Wessel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2030 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-27 21:02:43 +00:00
bellard 1f6e24e73c display device identifier string for user with info usb (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2029 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 21:00:51 +00:00
bellard 3e382bc84c consistent update of ERL and EXL
(Dirk Behme)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2028 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 20:29:47 +00:00
bellard beac80cd43 Windows sparse file support (Frediano Ziglio)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2027 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 20:08:57 +00:00
bellard 3587d7e69c fix crash when closing windows (Frediano Ziglio)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2026 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 20:03:44 +00:00
bellard d796321b6b lwu support - generate exception if unaligned pc (Marius Groeger)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2025 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 20:02:45 +00:00
bellard 567d4107a6 qsub fix (Wolfgang Schildbach)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2024 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 19:55:19 +00:00
bellard a80dde0837 SPARC FPU optimization (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2023 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-26 19:53:29 +00:00
bellard 29133e9a0f AMD NOR flash device support (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2022 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 22:28:15 +00:00
bellard 9d42037b1d support for dynamic address space changes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2021 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 22:25:22 +00:00
bellard 2a4188a38f low level support for memory mapped flash devices (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2020 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 21:54:59 +00:00
bellard 4f4fbf77ad 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2019 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 18:28:12 +00:00
bellard 26a76461f2 C99 64 bit printf
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2018 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 18:15:32 +00:00
bellard 3b42c9794c sse2 comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2017 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 18:02:38 +00:00
bellard 755d13753b removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2016 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 18:02:02 +00:00
bellard 26489844dc avoid name conflicts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2015 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 17:37:36 +00:00
bellard 87ac54273f disable user targets by default for cross compile with mingw32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2014 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 17:35:56 +00:00
bellard a18e524af0 multiple wait object support for win32 (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2013 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 17:18:27 +00:00
bellard e15d737181 send correctly long key sequences on slow terminals - fixes backspace handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2012 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 16:26:29 +00:00
bellard be995c2764 removed unused code - init timers earlier
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2011 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 16:25:21 +00:00
bellard 6b1575b746 cpu_get_phys_page_debug fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2010 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 15:33:53 +00:00
bellard 9d9754a31d sparc fpu fix - allow 64 bit addresses (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2009 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 15:32:37 +00:00
bellard 1579bde84d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2008 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 14:50:00 +00:00
bellard 0bab00f30f UDP char device (initial patch by Jason Wessel) - TCP char device
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2007 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-25 14:49:44 +00:00
bellard 3532fa7402 mips socket calls (initial patch by Raphael Rigo)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2006 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-24 15:06:03 +00:00
bellard 480c1cdb39 fix for movq2dq, movdq2q and cvttps2dq (thanx to Julian Seward and malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2005 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-24 14:03:10 +00:00
bellard 80e7d52103 added movdq2q and movq2dq
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2004 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-24 14:01:32 +00:00
bellard 13846e700f Sparc64 BPr branch target fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2003 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-23 21:01:56 +00:00
bellard 3cb0853ad7 more info about -std-vga
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2002 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-21 21:19:50 +00:00
bellard 1bdb68ea13 fixed sparc64 cpu fp save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2001 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-21 18:48:01 +00:00
bellard 65ce8c2fb4 soft floats for SPARC (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2000 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-21 18:37:05 +00:00
bellard ee6c0b51e9 sparc branch fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1999 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-21 18:26:15 +00:00
bellard 48dc41eb8b sparc user fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1998 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-21 18:15:50 +00:00
bellard a891c7a194 fxam fix (Julian Seward)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1997 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-19 22:43:38 +00:00
bellard b2a8e59224 fxam test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1996 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-19 22:42:57 +00:00
bellard 447c2cefcb switch_tss eflags restore fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1995 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-19 22:06:13 +00:00
pbrook 75956cf032 Sun4u vga+bios tweaks (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1994 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-18 19:41:28 +00:00
pbrook ded3ab80dd Sparc64 insn fixes (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1993 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-18 19:36:58 +00:00
pbrook 908f52b05c Add big-endian SH4-user target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1992 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-18 19:16:53 +00:00
pbrook 9c2a9ea1b1 SH bugfixes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1991 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-18 19:12:54 +00:00
pbrook 397e923f7f Remove debug output.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1990 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-17 20:04:26 +00:00
pbrook 4dbed8972b Enable SH bFLT loader.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1989 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-17 20:01:14 +00:00
pbrook 355fb23d83 SH usermode fault handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1988 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-17 19:58:25 +00:00
pbrook 9854bc4662 SH4 rts fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1987 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-17 18:48:31 +00:00
pbrook 978efd6aac Respond to qOffsets gdb packet (for debugging bFLT binaries).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1986 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-17 18:30:42 +00:00
pbrook e6de1bad46 Arm h/w doc updates.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1985 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-16 21:48:48 +00:00
bellard 30a604f363 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1984 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 18:35:18 +00:00
bellard 856860f5e3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1983 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 18:18:38 +00:00
bellard ce05c32384 allow ACPI table build
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1982 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 18:17:46 +00:00
bellard 1ce549abf9 more ACPI definition to keep Solaris Happy (Juergen Kiel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1981 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 18:17:04 +00:00
bellard a08beb33cd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1980 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 17:32:56 +00:00
bellard fdbb46910a Solaris/SPARC host port (Ben Taylor)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1979 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 17:32:25 +00:00
bellard 43057ab127 use constants for TLB handling (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1978 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 17:15:19 +00:00
bellard c5d6edc3fc mips config fixes (initial patch by Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1977 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 16:49:24 +00:00
bellard 52ca8d6af0 -no-fd-bootchk option (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1976 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 16:03:05 +00:00
bellard 5cbfcd00b0 cocoa monitor fix regarding the handling of dead keys (Joachim Henke)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1975 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 15:53:24 +00:00
bellard ec3757de32 use C99 64 bit printf format to ease win32 porting
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1974 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 15:50:07 +00:00
bellard e8445331b6 show real allocated disk image size on Windows (Frediano Ziglio)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1973 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 15:32:10 +00:00
bellard 8f447cc753 gdb stub for win32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1972 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 15:21:14 +00:00
bellard eda9b09b1d sh4 fmov et al instructions (amatus)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1971 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 15:02:05 +00:00
pbrook 191f9a93f4 ARM postincrememnt addressing fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1970 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 14:36:07 +00:00
bellard d1e42c5c1e x86_64 mmx/sse fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1969 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 14:29:34 +00:00
bellard 4bb3973f61 typo in get_reloc_expr()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1968 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 13:41:08 +00:00
bellard bc1ad2decd MIPS FPU support in linux user emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1967 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 13:37:55 +00:00
bellard 83fcb51548 use glibc syscall (David Woodhouse)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1966 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 13:37:16 +00:00
bellard 5b9053a5ea remove proll
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1965 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:57:01 +00:00
bellard 6ea83fedc8 MIPS FPU support (Marius Goeger)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1964 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:56:19 +00:00
bellard 180b700dc7 clock year fix for sparc (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1963 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:41:34 +00:00
bellard 55e4f6644e FPU fix (Joerg Platte)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1962 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:37:58 +00:00
bellard d8e3326c8e MMU no fault fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1961 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:37:30 +00:00
bellard 0986ac3be2 use OpenBIOS instead of Proll on sparc (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1960 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 12:36:32 +00:00
bellard 9d0869b630 fixed VBE protected mode calls - added VGA and VBE save restore support (not fully tested) - automatic generation of VBE mode table
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1959 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-14 00:58:54 +00:00
bellard 8fa00e0fec more high resolution VESA modes in -std-vga case - changed video memory size to 8 MB
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1958 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 16:54:27 +00:00
bellard 8454df8b1e support for Bochs VBE GETCAPS call so that -std-vga works again with new VGA BIOSes - added support for modes up to 1600x1200x32 in -std-vga case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1957 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 16:37:40 +00:00
bellard 99589bdcd1 support for higher resolutions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1956 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 16:35:24 +00:00
bellard 74a14f22b8 increase video memory to 8MB
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1955 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 15:57:21 +00:00
bellard c66b0d4cf4 avoid stopping QEMU when switching desktops with Ctrl-Alt-x
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1954 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 12:03:53 +00:00
bellard 8785a8ddcc 'invisible wall' patch (Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1953 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-13 10:49:12 +00:00
pbrook 79737e4a7d Document new arm-user features.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1952 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-11 16:28:41 +00:00
pbrook e5fe0c5230 bFLT loader (for uClinux binaries).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1951 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-11 13:32:59 +00:00
pbrook ac62f715c6 Win32 build fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1950 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-08 21:51:27 +00:00
pbrook 7a6cba611d Disk cache flush support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1949 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-04 11:39:07 +00:00
pbrook 17acfe326c More SCSI commands (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1948 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-03 14:23:34 +00:00
pbrook 9f149aa9c1 SATN fixes (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1947 c046a42c-6fe2-441c-8c8c-71466251a162
2006-06-03 14:19:19 +00:00
pbrook 7d8406be69 PCI SCSI HBA emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1946 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-30 01:48:12 +00:00
pbrook 0fc5c15a4f SCSI lun probing fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1945 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-26 21:53:41 +00:00
pbrook cac782d496 Small read fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1944 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-26 18:08:11 +00:00
pbrook 4be9a500e7 Fix partial transfer bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1943 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-26 17:15:13 +00:00
pbrook 7c22dd5216 Fix scsi sector size confusion (Blue Swirl).
Fix short TOC read.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1942 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-26 16:46:55 +00:00
pbrook 0aff66b5c8 Update USB documentation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1941 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-26 00:49:52 +00:00
pbrook 2e5d83bbef Rearrange SCSI disk emulation code.
Add USB mass storage device emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1940 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-25 23:58:51 +00:00
pbrook e6f3e5e016 OHCI large packet fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1939 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-25 23:37:07 +00:00
bellard 159f366388 ARM undefined instruction execution (Jason Wessel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1938 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 23:06:04 +00:00
bellard ba9a74dae0 fix wrong bitmasks for CP0_Context and CP0_EntryHi (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1937 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 22:14:43 +00:00
bellard 3d9fb9fefe cosmetics (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1936 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 22:13:29 +00:00
bellard 42fe404458 dump all mips insn (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1935 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 22:05:04 +00:00
bellard 9d05095e5f mips cleanup (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1934 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 22:03:52 +00:00
bellard ea4e754f5a PPC Breakpoints for gdb-stub (Jason Wessel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1933 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 21:50:20 +00:00
bellard cae41b10a4 fix missing type declarations (Joachim Henke)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1932 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 21:25:04 +00:00
pbrook 6106487019 Fix USB root hub hotplugging.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1931 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 17:17:06 +00:00
pbrook 6cb7ee859a Only use /dev/shm hack when kqemu is enabled.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1930 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-22 14:10:48 +00:00
pbrook e4d165c24b Don't clear DMA status register when loading address.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1929 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-21 22:20:03 +00:00
pbrook 0d92ed3022 OHCI USB host emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1928 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-21 16:30:15 +00:00
pbrook 6650ee6d33 Use lookup table for PCI class descriptions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1927 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-21 13:45:09 +00:00
pbrook db59203d10 ESP DMA fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1926 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-21 12:46:31 +00:00
bellard 1c46d7139a clear screen when changing graphic mode in Cirrus VGA BIOS (aka win2k mode change bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1925 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 21:03:52 +00:00
bellard f815fa45da ne2000 buffer fulness fix (Han Zhu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1924 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 18:41:52 +00:00
bellard 3512779a88 support for all VNC pixel formats
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1923 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 18:11:49 +00:00
pbrook 5c3ff3a7be Avoid compiler warning.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1922 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 13:44:07 +00:00
pbrook 0cb3fb1e30 Add doc, html, dvi and .PHONY Makefile targets.
Add resulting files to .cvsignore.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1921 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 12:07:53 +00:00
pbrook c59372208a Teach usermode emulation how to lie about uname -r.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1920 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-14 11:30:38 +00:00
pbrook 00a9bf191b Update ARM board documentation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1919 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-13 16:55:46 +00:00
pbrook b9dea4fbc6 Move all: target first.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1918 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-13 16:54:03 +00:00
pbrook 214feb514b Add dependency on config.h and config-host.h.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1917 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-13 16:30:17 +00:00
pbrook 502a53952d Rearrange PCI host emulation code.
Add ARM PCI emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1916 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-13 16:11:23 +00:00
pbrook 4aa4253115 Allow parallel make.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1915 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-13 13:55:08 +00:00
bellard 5627148a19 BGR_FORMAT fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1914 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-11 21:54:44 +00:00
bellard 1fc2244d87 mips bios loading fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1913 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-11 21:15:08 +00:00
bellard d3079cd241 bgr32 pixel format support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1912 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-10 22:17:36 +00:00
bellard 38f3e7c2f5 suppressed unaligned accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1911 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-10 19:21:58 +00:00
bellard 73540ca962 alignment fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1910 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-08 13:38:46 +00:00
pbrook 064aae138b Test if compiler works instead of checking if binary exists.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1909 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-08 00:51:44 +00:00
bellard 699e4642a9 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1908 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-07 18:06:27 +00:00
bellard 64866c3d5c more keycodes - hexa keycodes - keycode completion
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1907 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-07 18:03:31 +00:00
bellard 294e863721 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1906 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-06 14:23:06 +00:00
bellard 67f3656039 patch in bLength for hub descriptor (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1905 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-05 20:05:35 +00:00
bellard 7ef4da1c3a typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1904 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-05 20:03:45 +00:00
bellard 6583391f0d PCI irq mapping fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1903 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 23:13:13 +00:00
bellard 6515b20370 ACPI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1902 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 22:02:44 +00:00
bellard 107654552c more correct e820 ranges for ACPI compatibility
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1901 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 21:24:55 +00:00
bellard ceb5caaf18 removed ssize_t for win32 compatibility
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1900 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 21:18:59 +00:00
bellard c904d61f78 UDP broadcast translation error (Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1899 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 20:53:46 +00:00
164 changed files with 19648 additions and 9497 deletions

No files matched your search

+13
View File
@@ -11,6 +11,8 @@ ppc64-softmmu
ppc-user
qemu-doc.html
qemu-tech.html
qemu-doc.info
qemu-tech.info
qemu.1
qemu.pod
qemu-img.1
@@ -25,5 +27,16 @@ mips-softmmu
mipsel-softmmu
mips-user
mipsel-user
.gdbinit
sh4-user
sh4-softmmu
*.aux
*.cp
*.dvi
*.fn
*.ky
*.log
*.pg
*.toc
*.tp
*.vr
+19
View File
@@ -1,3 +1,22 @@
version 0.8.2:
- ACPI support
- PC VGA BIOS fixes
- switch to OpenBios for SPARC targets (Blue Swirl)
- VNC server fixes
- MIPS FPU support (Marius Groeger)
- Solaris/SPARC host support (Ben Taylor)
- PPC breakpoints and single stepping (Jason Wessel)
- USB updates (Paul Brook)
- UDP/TCP/telnet character devices (Jason Wessel)
- Windows sparse file support (Frediano Ziglio)
- RTL8139 NIC TCP segmentation offloading (Igor Kovalenko)
- PCNET NIC support (Antony T Curtis)
- Support for variable frequency host CPUs
- Workaround for win32 SMP hosts
- Support for AMD Flash memories (Jocelyn Mayer)
- Audio capture to WAV files support (malc)
version 0.8.1:
- USB tablet support (Brad Campbell, Anthony Liguori)
+23 -6
View File
@@ -1,9 +1,17 @@
# Makefile for QEMU.
include config-host.mak
.PHONY: all clean distclean dvi info install install-doc tar tarbin \
speed test test2 html dvi info
CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I.
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
endif
ifeq ($(ARCH),sparc)
CFLAGS+=-mcpu=ultrasparc
endif
LDFLAGS=-g
LIBS=
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
@@ -17,11 +25,13 @@ else
DOCS=
endif
all: dyngen$(EXESUF) $(TOOLS) $(DOCS)
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
all: $(TOOLS) $(DOCS) recurse-all
subdir-%: dyngen$(EXESUF)
$(MAKE) -C $(subst subdir-,,$@) all
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
@@ -39,6 +49,7 @@ clean:
distclean: clean
rm -f config-host.mak config-host.h $(DOCS)
rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
@@ -60,7 +71,7 @@ install: all $(if $(BUILD_DOCS),install-doc)
$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
mkdir -p "$(DESTDIR)$(datadir)"
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
video.x proll.elf linux_boot.bin; do \
video.x openbios-sparc32 linux_boot.bin; do \
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
done
ifndef CONFIG_WIN32
@@ -103,6 +114,12 @@ qemu-img.1: qemu-img.texi
$(SRC_PATH)/texi2pod.pl $< qemu-img.pod
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
info: qemu-doc.info qemu-tech.info
dvi: qemu-doc.dvi qemu-tech.dvi
html: qemu-doc.html qemu-tech.html
FILE=qemu-$(shell cat VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
@@ -135,7 +152,7 @@ tarbin:
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/video.x \
$(datadir)/proll.elf \
$(datadir)/openbios-sparc32 \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
+46 -8
View File
@@ -30,6 +30,11 @@ ifeq ($(TARGET_ARCH),arm)
TARGET_ARCH2=armeb
endif
endif
ifeq ($(TARGET_ARCH),sh4)
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=sh4eb
endif
endif
ifeq ($(TARGET_ARCH),mips)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mipsel
@@ -102,17 +107,24 @@ LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
endif
ifeq ($(ARCH),sparc)
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
ifeq ($(CONFIG_SOLARIS),yes)
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
else
CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
# -static is used to avoid g1/g3 usage by the dynamic linker
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
endif
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
LDFLAGS+=-m64
LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
endif
@@ -171,7 +183,12 @@ LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
elfload.o linuxload.o
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
endif
@@ -305,24 +322,30 @@ endif
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
endif
AUDIODRV+= wavcapture.o
# SCSI layer
VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
# USB layer
VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o
VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
# PCI network cards
VL_OBJS+= ne2000.o rtl8139.o
VL_OBJS+= ne2000.o rtl8139.o pcnet.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o
VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
VL_OBJS+= usb-uhci.o
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
@@ -331,7 +354,7 @@ VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
VL_OBJS+= cirrus_vga.o parallel.o
else
@@ -342,6 +365,7 @@ endif
ifeq ($(TARGET_BASE_ARCH), arm)
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
VL_OBJS+= versatile_pci.o
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
@@ -379,7 +403,7 @@ endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
ifndef CONFIG_SOLARIS
VL_LIBS=-lutil
VL_LIBS=-lutil -lrt
endif
endif
endif
@@ -392,6 +416,11 @@ ifeq ($(ARCH),ia64)
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
endif
ifeq ($(ARCH),sparc64)
VL_LDFLAGS+=-m64
VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
endif
ifdef CONFIG_WIN32
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
@@ -471,6 +500,13 @@ endif
loader.o: loader.c elf_ops.h
acpi.o: acpi.c acpi-dsdt.hex
ifdef BUILD_ACPI_TABLES
$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
iasl -tc -p $@ $<
endif
ifeq ($(TARGET_ARCH), sh4)
op.o: op.c op_mem.c cpu.h
op_helper.o: op_helper.c exec.h cpu.h
@@ -481,6 +517,8 @@ sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
tc58128.o: tc58128.c
endif
$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+2 -8
View File
@@ -1,24 +1,20 @@
short term:
----------
- support variable tsc freq
- cycle counter for all archs
- cpu_interrupt() win32/SMP fix
- support variable tsc freq
- USB host async
- IDE async
- debug option in 'configure' script + disable -fomit-frame-pointer
- Precise VGA timings for old games/demos (malc patch)
- merge PIC spurious interrupt patch
- merge Solaris patch
- warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?)
- config file (at least for windows/Mac OS X)
- commit message if execution of code in IO memory
- update doc: PCI infos.
- VNC patch + Synaptic patch.
- basic VGA optimizations
- physical memory cache (reduce qemu-fast address space size to about 32 MB)
- better code fetch (different exception handling + CS.limit support)
- do not resize vga if invalid size.
- avoid looping if only exceptions
- cycle counter for all archs
- TLB code protection support for PPC
- see openMosix Doc
- disable SMC handling for ARM/SPARC/PPC (not finished)
@@ -31,12 +27,10 @@ short term:
- fix CCOP optimisation
- fix all remaining thread lock issues (must put TBs in a specific invalid
state, find a solution for tb_flush()).
- fix arm fpu rounding (at least for float->integer conversions)
ppc specific:
------------
- TLB invalidate not needed if msr_pr changes
- SPR_ENCODE() not useful
- enable shift optimizations ?
linux-user specific:
+1 -1
View File
@@ -1 +1 @@
0.8.1
0.8.2
+6 -13
View File
@@ -61,8 +61,8 @@ static struct {
.size_in_usec_in = 1,
.size_in_usec_out = 1,
#endif
.pcm_name_out = "hw:0,0",
.pcm_name_in = "hw:0,0",
.pcm_name_out = "default",
.pcm_name_in = "default",
#ifdef HIGH_LATENCY
.buffer_size_in = 400000,
.period_size_in = 400000 / 4,
@@ -606,7 +606,6 @@ static int alsa_run_out (HWVoiceOut *hw)
}
}
mixeng_clear (src, written);
rpos = (rpos + written) % hw->samples;
samples -= written;
len -= written;
@@ -663,12 +662,9 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = obt.samples;
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
@@ -752,12 +748,9 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = obt.samples;
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+417 -27
View File
@@ -29,6 +29,7 @@
/* #define DEBUG_PLIVE */
/* #define DEBUG_LIVE */
/* #define DEBUG_OUT */
/* #define DEBUG_CAPTURE */
#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
@@ -137,7 +138,7 @@ int audio_bug (const char *funcname, int cond)
if (cond) {
static int shown;
AUD_log (NULL, "Error a bug that was just triggered in %s\n", funcname);
AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
if (!shown) {
shown = 1;
AUD_log (NULL, "Save all your work and restart without audio\n");
@@ -509,14 +510,28 @@ static void audio_print_settings (audsettings_t *as)
AUD_log (NULL, "invalid(%d)", as->fmt);
break;
}
AUD_log (NULL, " endianness=");
switch (as->endianness) {
case 0:
AUD_log (NULL, "little");
break;
case 1:
AUD_log (NULL, "big");
break;
default:
AUD_log (NULL, "invalid");
break;
}
AUD_log (NULL, "\n");
}
static int audio_validate_settigs (audsettings_t *as)
static int audio_validate_settings (audsettings_t *as)
{
int invalid;
invalid = as->nchannels != 1 && as->nchannels != 2;
invalid |= as->endianness != 0 && as->endianness != 1;
switch (as->fmt) {
case AUD_FMT_S8:
@@ -530,11 +545,7 @@ static int audio_validate_settigs (audsettings_t *as)
}
invalid |= as->freq <= 0;
if (invalid) {
return -1;
}
return 0;
return invalid ? -1 : 0;
}
static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
@@ -556,14 +567,11 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
return info->freq == as->freq
&& info->nchannels == as->nchannels
&& info->sign == sign
&& info->bits == bits;
&& info->bits == bits
&& info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
}
void audio_pcm_init_info (
struct audio_pcm_info *info,
audsettings_t *as,
int swap_endian
)
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
{
int bits = 8, sign = 0;
@@ -587,7 +595,7 @@ void audio_pcm_init_info (
info->shift = (as->nchannels == 2) + (bits == 16);
info->align = (1 << info->shift) - 1;
info->bytes_per_second = info->freq << info->shift;
info->swap_endian = swap_endian;
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
}
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
@@ -609,7 +617,7 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
int shift = info->nchannels - 1;
short s = INT16_MAX;
if (info->swap_endian) {
if (info->swap_endianness) {
s = bswap16 (s);
}
@@ -620,6 +628,143 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
}
}
/*
* Capture
*/
static void noop_conv (st_sample_t *dst, const void *src,
int samples, volume_t *vol)
{
(void) src;
(void) dst;
(void) samples;
(void) vol;
}
static CaptureVoiceOut *audio_pcm_capture_find_specific (
AudioState *s,
audsettings_t *as
)
{
CaptureVoiceOut *cap;
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
if (audio_pcm_info_eq (&cap->hw.info, as)) {
return cap;
}
}
return NULL;
}
static void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
{
struct capture_callback *cb;
#ifdef DEBUG_CAPTURE
dolog ("notification %d sent\n", cmd);
#endif
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
cb->ops.notify (cb->opaque, cmd);
}
}
static void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled)
{
if (cap->hw.enabled != enabled) {
audcnotification_e cmd;
cap->hw.enabled = enabled;
cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
audio_notify_capture (cap, cmd);
}
}
static void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
{
HWVoiceOut *hw = &cap->hw;
SWVoiceOut *sw;
int enabled = 0;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (sw->active) {
enabled = 1;
break;
}
}
audio_capture_maybe_changed (cap, enabled);
}
static void audio_detach_capture (HWVoiceOut *hw)
{
SWVoiceCap *sc = hw->cap_head.lh_first;
while (sc) {
SWVoiceCap *sc1 = sc->entries.le_next;
SWVoiceOut *sw = &sc->sw;
CaptureVoiceOut *cap = sc->cap;
int was_active = sw->active;
if (sw->rate) {
st_rate_stop (sw->rate);
sw->rate = NULL;
}
LIST_REMOVE (sw, entries);
LIST_REMOVE (sc, entries);
qemu_free (sc);
if (was_active) {
/* We have removed soft voice from the capture:
this might have changed the overall status of the capture
since this might have been the only active voice */
audio_recalc_and_notify_capture (cap);
}
sc = sc1;
}
}
static int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
{
CaptureVoiceOut *cap;
audio_detach_capture (hw);
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
SWVoiceCap *sc;
SWVoiceOut *sw;
HWVoiceOut *hw_cap = &cap->hw;
sc = audio_calloc (AUDIO_FUNC, 1, sizeof (*sc));
if (!sc) {
dolog ("Could not allocate soft capture voice (%zu bytes)\n",
sizeof (*sc));
return -1;
}
sc->cap = cap;
sw = &sc->sw;
sw->hw = hw_cap;
sw->info = hw->info;
sw->empty = 1;
sw->active = hw->enabled;
sw->conv = noop_conv;
sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
if (!sw->rate) {
dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
qemu_free (sw);
return -1;
}
LIST_INSERT_HEAD (&hw_cap->sw_head, sw, entries);
LIST_INSERT_HEAD (&hw->cap_head, sc, entries);
#ifdef DEBUG_CAPTURE
asprintf (&sw->name, "for %p %d,%d,%d",
hw, sw->info.freq, sw->info.bits, sw->info.nchannels);
dolog ("Added %s active = %d\n", sw->name, sw->active);
#endif
if (sw->active) {
audio_capture_maybe_changed (cap, 1);
}
}
return 0;
}
/*
* Hard voice (capture)
*/
@@ -796,6 +941,9 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
}
if (live == hwsamples) {
#ifdef DEBUG_OUT
dolog ("%s is full %d\n", sw->name, live);
#endif
return 0;
}
@@ -914,19 +1062,14 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw = sw->hw;
if (sw->active != on) {
SWVoiceOut *temp_sw;
SWVoiceCap *sc;
if (on) {
int total;
hw->pending_disable = 0;
if (!hw->enabled) {
hw->enabled = 1;
hw->pcm_ops->ctl_out (hw, VOICE_ENABLE);
}
if (sw->empty) {
total = 0;
}
}
else {
if (hw->enabled) {
@@ -940,6 +1083,13 @@ void AUD_set_active_out (SWVoiceOut *sw, int on)
hw->pending_disable = nb_active == 1;
}
}
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
sc->sw.active = hw->enabled;
if (hw->enabled) {
audio_capture_maybe_changed (sc->cap, 1);
}
}
sw->active = on;
}
}
@@ -997,7 +1147,7 @@ static int audio_get_avail (SWVoiceIn *sw)
}
ldebug (
"%s: get_avail live %d ret %lld\n",
"%s: get_avail live %d ret %" PRId64 "\n",
SW_NAME (sw),
live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
);
@@ -1023,7 +1173,7 @@ static int audio_get_free (SWVoiceOut *sw)
dead = sw->hw->samples - live;
#ifdef DEBUG_OUT
dolog ("%s: get_free live %d dead %d ret %lld\n",
dolog ("%s: get_free live %d dead %d ret %" PRId64 "\n",
SW_NAME (sw),
live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
#endif
@@ -1031,6 +1181,43 @@ static int audio_get_free (SWVoiceOut *sw)
return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
}
static void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples)
{
int n;
if (hw->enabled) {
SWVoiceCap *sc;
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
SWVoiceOut *sw = &sc->sw;
int rpos2 = rpos;
n = samples;
while (n) {
int till_end_of_hw = hw->samples - rpos2;
int to_write = audio_MIN (till_end_of_hw, n);
int bytes = to_write << hw->info.shift;
int written;
sw->buf = hw->mix_buf + rpos2;
written = audio_pcm_sw_write (sw, NULL, bytes);
if (written - bytes) {
dolog ("Could not mix %d bytes into a capture "
"buffer, mixed %d\n",
bytes, written);
break;
}
n -= to_write;
rpos2 = (rpos2 + to_write) % hw->samples;
}
}
}
n = audio_MIN (samples, hw->samples - rpos);
mixeng_clear (hw->mix_buf + rpos, n);
mixeng_clear (hw->mix_buf, samples - n);
}
static void audio_run_out (AudioState *s)
{
HWVoiceOut *hw = NULL;
@@ -1038,7 +1225,7 @@ static void audio_run_out (AudioState *s)
while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
int played;
int live, free, nb_live, cleanup_required;
int live, free, nb_live, cleanup_required, prev_rpos;
live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
if (!nb_live) {
@@ -1051,12 +1238,17 @@ static void audio_run_out (AudioState *s)
}
if (hw->pending_disable && !nb_live) {
SWVoiceCap *sc;
#ifdef DEBUG_OUT
dolog ("Disabling voice\n");
#endif
hw->enabled = 0;
hw->pending_disable = 0;
hw->pcm_ops->ctl_out (hw, VOICE_DISABLE);
for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
sc->sw.active = 0;
audio_recalc_and_notify_capture (sc->cap);
}
continue;
}
@@ -1072,6 +1264,7 @@ static void audio_run_out (AudioState *s)
continue;
}
prev_rpos = hw->rpos;
played = hw->pcm_ops->run_out (hw);
if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
dolog ("hw->rpos=%d hw->samples=%d played=%d\n",
@@ -1085,6 +1278,7 @@ static void audio_run_out (AudioState *s)
if (played) {
hw->ts_helper += played;
audio_capture_mix_and_clear (hw, prev_rpos, played);
}
cleanup_required = 0;
@@ -1115,15 +1309,18 @@ static void audio_run_out (AudioState *s)
}
if (cleanup_required) {
restart:
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
SWVoiceOut *sw1;
sw = hw->sw_head.lh_first;
while (sw) {
sw1 = sw->entries.le_next;
if (!sw->active && !sw->callback.fn) {
#ifdef DEBUG_PLIVE
dolog ("Finishing with old voice\n");
#endif
audio_close_out (s, sw);
goto restart; /* play it safe */
}
sw = sw1;
}
}
}
@@ -1158,12 +1355,60 @@ static void audio_run_in (AudioState *s)
}
}
static void audio_run_capture (AudioState *s)
{
CaptureVoiceOut *cap;
for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
int live, rpos, captured;
HWVoiceOut *hw = &cap->hw;
SWVoiceOut *sw;
captured = live = audio_pcm_hw_get_live_out (hw);
rpos = hw->rpos;
while (live) {
int left = hw->samples - rpos;
int to_capture = audio_MIN (live, left);
st_sample_t *src;
struct capture_callback *cb;
src = hw->mix_buf + rpos;
hw->clip (cap->buf, src, to_capture);
mixeng_clear (src, to_capture);
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
cb->ops.capture (cb->opaque, cap->buf,
to_capture << hw->info.shift);
}
rpos = (rpos + to_capture) % hw->samples;
live -= to_capture;
}
hw->rpos = rpos;
for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
if (!sw->active && sw->empty) {
continue;
}
if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) {
dolog ("captured=%d sw->total_hw_samples_mixed=%d\n",
captured, sw->total_hw_samples_mixed);
captured = sw->total_hw_samples_mixed;
}
sw->total_hw_samples_mixed -= captured;
sw->empty = sw->total_hw_samples_mixed == 0;
}
}
}
static void audio_timer (void *opaque)
{
AudioState *s = opaque;
audio_run_out (s);
audio_run_in (s);
audio_run_capture (s);
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
}
@@ -1327,8 +1572,19 @@ static void audio_atexit (void)
HWVoiceIn *hwi = NULL;
while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
SWVoiceCap *sc;
hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
hwo->pcm_ops->fini_out (hwo);
for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
CaptureVoiceOut *cap = sc->cap;
struct capture_callback *cb;
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
cb->ops.destroy (cb->opaque);
}
}
}
while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
@@ -1383,6 +1639,7 @@ AudioState *AUD_init (void)
LIST_INIT (&s->hw_head_out);
LIST_INIT (&s->hw_head_in);
LIST_INIT (&s->cap_head);
atexit (audio_atexit);
s->ts = qemu_new_timer (vm_clock, audio_timer, s);
@@ -1479,3 +1736,136 @@ AudioState *AUD_init (void)
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
return s;
}
CaptureVoiceOut *AUD_add_capture (
AudioState *s,
audsettings_t *as,
struct audio_capture_ops *ops,
void *cb_opaque
)
{
CaptureVoiceOut *cap;
struct capture_callback *cb;
if (!s) {
/* XXX suppress */
s = &glob_audio_state;
}
if (audio_validate_settings (as)) {
dolog ("Invalid settings were passed when trying to add capture\n");
audio_print_settings (as);
goto err0;
}
cb = audio_calloc (AUDIO_FUNC, 1, sizeof (*cb));
if (!cb) {
dolog ("Could not allocate capture callback information, size %zu\n",
sizeof (*cb));
goto err0;
}
cb->ops = *ops;
cb->opaque = cb_opaque;
cap = audio_pcm_capture_find_specific (s, as);
if (cap) {
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
return cap;
}
else {
HWVoiceOut *hw;
CaptureVoiceOut *cap;
cap = audio_calloc (AUDIO_FUNC, 1, sizeof (*cap));
if (!cap) {
dolog ("Could not allocate capture voice, size %zu\n",
sizeof (*cap));
goto err1;
}
hw = &cap->hw;
LIST_INIT (&hw->sw_head);
LIST_INIT (&cap->cb_head);
/* XXX find a more elegant way */
hw->samples = 4096 * 4;
hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples,
sizeof (st_sample_t));
if (!hw->mix_buf) {
dolog ("Could not allocate capture mix buffer (%d samples)\n",
hw->samples);
goto err2;
}
audio_pcm_init_info (&hw->info, as);
cap->buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
if (!cap->buf) {
dolog ("Could not allocate capture buffer "
"(%d samples, each %d bytes)\n",
hw->samples, 1 << hw->info.shift);
goto err3;
}
hw->clip = mixeng_clip
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endianness]
[hw->info.bits == 16];
LIST_INSERT_HEAD (&s->cap_head, cap, entries);
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
hw = NULL;
while ((hw = audio_pcm_hw_find_any_out (s, hw))) {
audio_attach_capture (s, hw);
}
return cap;
err3:
qemu_free (cap->hw.mix_buf);
err2:
qemu_free (cap);
err1:
qemu_free (cb);
err0:
return NULL;
}
}
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque)
{
struct capture_callback *cb;
for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
if (cb->opaque == cb_opaque) {
cb->ops.destroy (cb_opaque);
LIST_REMOVE (cb, entries);
qemu_free (cb);
if (!cap->cb_head.lh_first) {
SWVoiceOut *sw = cap->hw.sw_head.lh_first, *sw1;
while (sw) {
SWVoiceCap *sc = (SWVoiceCap *) sw;
#ifdef DEBUG_CAPTURE
dolog ("freeing %s\n", sw->name);
#endif
sw1 = sw->entries.le_next;
if (sw->rate) {
st_rate_stop (sw->rate);
sw->rate = NULL;
}
LIST_REMOVE (sw, entries);
LIST_REMOVE (sc, entries);
qemu_free (sc);
sw = sw1;
}
LIST_REMOVE (cap, entries);
qemu_free (cap);
}
return;
}
}
}
+41 -5
View File
@@ -24,6 +24,7 @@
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "config.h"
#include "sys-queue.h"
typedef void (*audio_callback_fn_t) (void *opaque, int avail);
@@ -35,14 +36,44 @@ typedef enum {
AUD_FMT_S16
} audfmt_e;
#ifdef WORDS_BIGENDIAN
#define AUDIO_HOST_ENDIANNESS 1
#else
#define AUDIO_HOST_ENDIANNESS 0
#endif
typedef struct {
int freq;
int nchannels;
audfmt_e fmt;
int endianness;
} audsettings_t;
typedef enum {
AUD_CNOTIFY_ENABLE,
AUD_CNOTIFY_DISABLE
} audcnotification_e;
struct audio_capture_ops {
void (*notify) (void *opaque, audcnotification_e cmd);
void (*capture) (void *opaque, void *buf, int size);
void (*destroy) (void *opaque);
};
struct capture_ops {
void (*info) (void *opaque);
void (*destroy) (void *opaque);
};
typedef struct CaptureState {
void *opaque;
struct capture_ops ops;
LIST_ENTRY (CaptureState) entries;
} CaptureState;
typedef struct AudioState AudioState;
typedef struct SWVoiceOut SWVoiceOut;
typedef struct CaptureVoiceOut CaptureVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
typedef struct QEMUSoundCard {
@@ -66,6 +97,13 @@ AudioState *AUD_init (void);
void AUD_help (void);
void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card);
void AUD_remove_card (QEMUSoundCard *card);
CaptureVoiceOut *AUD_add_capture (
AudioState *s,
audsettings_t *as,
struct audio_capture_ops *ops,
void *opaque
);
void AUD_del_capture (CaptureVoiceOut *cap, void *cb_opaque);
SWVoiceOut *AUD_open_out (
QEMUSoundCard *card,
@@ -73,8 +111,7 @@ SWVoiceOut *AUD_open_out (
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
audsettings_t *settings,
int sw_endian
audsettings_t *settings
);
void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
@@ -92,8 +129,7 @@ SWVoiceIn *AUD_open_in (
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
audsettings_t *settings,
int sw_endian
audsettings_t *settings
);
void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
@@ -111,7 +147,7 @@ static inline void *advance (void *p, int incr)
}
uint32_t popcount (uint32_t u);
inline uint32_t lsbindex (uint32_t u);
uint32_t lsbindex (uint32_t u);
#ifdef __GNUC__
#define audio_MIN(a, b) ( __extension__ ({ \
+26 -14
View File
@@ -61,13 +61,14 @@ struct audio_pcm_info {
int align;
int shift;
int bytes_per_second;
int swap_endian;
int swap_endianness;
};
typedef struct SWVoiceCap SWVoiceCap;
typedef struct HWVoiceOut {
int enabled;
int pending_disable;
int valid;
struct audio_pcm_info info;
f_sample *clip;
@@ -79,6 +80,7 @@ typedef struct HWVoiceOut {
int samples;
LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
struct audio_pcm_ops *pcm_ops;
LIST_ENTRY (HWVoiceOut) entries;
} HWVoiceOut;
@@ -160,14 +162,34 @@ struct audio_pcm_ops {
int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
};
struct capture_callback {
struct audio_capture_ops ops;
void *opaque;
LIST_ENTRY (capture_callback) entries;
};
struct CaptureVoiceOut {
HWVoiceOut hw;
void *buf;
LIST_HEAD (cb_listhead, capture_callback) cb_head;
LIST_ENTRY (CaptureVoiceOut) entries;
};
struct SWVoiceCap {
SWVoiceOut sw;
CaptureVoiceOut *cap;
LIST_ENTRY (SWVoiceCap) entries;
};
struct AudioState {
struct audio_driver *drv;
void *drv_opaque;
QEMUTimer *ts;
LIST_HEAD (card_head, QEMUSoundCard) card_head;
LIST_HEAD (card_listhead, QEMUSoundCard) card_head;
LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
LIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head;
int nb_hw_voices_out;
int nb_hw_voices_in;
};
@@ -182,8 +204,7 @@ extern struct audio_driver coreaudio_audio_driver;
extern struct audio_driver dsound_audio_driver;
extern volume_t nominal_volume;
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as,
int swap_endian);
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
@@ -204,15 +225,6 @@ static inline int audio_ring_dist (int dst, int src, int len)
return (dst >= src) ? (dst - src) : (len - src + dst);
}
static inline int audio_need_to_swap_endian (int endianness)
{
#ifdef WORDS_BIGENDIAN
return endianness != 1;
#else
return endianness != 0;
#endif
}
#if defined __GNUC__
#define GCC_ATTR __attribute__ ((__unused__, __format__ (__printf__, 1, 2)))
#define INIT_FIELD(f) . f
+19 -14
View File
@@ -140,13 +140,12 @@ static int glue (audio_pcm_sw_init_, TYPE) (
SW *sw,
HW *hw,
const char *name,
audsettings_t *as,
int endian
audsettings_t *as
)
{
int err;
audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian));
audio_pcm_init_info (&sw->info, as);
sw->hw = hw;
sw->active = 0;
#ifdef DAC
@@ -164,7 +163,7 @@ static int glue (audio_pcm_sw_init_, TYPE) (
#endif
[sw->info.nchannels == 2]
[sw->info.sign]
[sw->info.swap_endian]
[sw->info.swap_endianness]
[sw->info.bits == 16];
sw->name = qemu_strdup (name);
@@ -200,6 +199,9 @@ static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp)
HW *hw = *hwp;
if (!hw->sw_head.lh_first) {
#ifdef DAC
audio_detach_capture (hw);
#endif
LIST_REMOVE (hw, entries);
glue (s->nb_hw_voices_, TYPE) += 1;
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
@@ -266,7 +268,9 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
hw->pcm_ops = drv->pcm_ops;
LIST_INIT (&hw->sw_head);
#ifdef DAC
LIST_INIT (&hw->cap_head);
#endif
if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
goto err0;
}
@@ -283,7 +287,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
#endif
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endian]
[hw->info.swap_endianness]
[hw->info.bits == 16];
if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
@@ -292,6 +296,9 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
glue (s->nb_hw_voices_, TYPE) -= 1;
#ifdef DAC
audio_attach_capture (s, hw);
#endif
return hw;
err1:
@@ -328,8 +335,7 @@ static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as)
static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
AudioState *s,
const char *sw_name,
audsettings_t *as,
int sw_endian
audsettings_t *as
)
{
SW *sw;
@@ -357,7 +363,7 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) {
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
goto err3;
}
@@ -399,8 +405,7 @@ SW *glue (AUD_open_, TYPE) (
const char *name,
void *callback_opaque ,
audio_callback_fn_t callback_fn,
audsettings_t *as,
int sw_endian
audsettings_t *as
)
{
AudioState *s;
@@ -421,7 +426,7 @@ SW *glue (AUD_open_, TYPE) (
s = card->audio;
if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) {
if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
audio_print_settings (as);
goto fail;
}
@@ -473,12 +478,12 @@ SW *glue (AUD_open_, TYPE) (
}
glue (audio_pcm_sw_fini_, TYPE) (sw);
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) {
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
goto fail;
}
}
else {
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian);
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as);
if (!sw) {
dolog ("Failed to create voice `%s'\n", name);
return NULL;
+1 -11
View File
@@ -275,8 +275,6 @@ static OSStatus audioDeviceIOProc(
#endif
}
/* cleanup */
mixeng_clear (src, frameCount);
rpos = (rpos + frameCount) % hw->samples;
core->decr += frameCount;
core->rpos = rpos;
@@ -297,7 +295,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
UInt32 propertySize;
int err;
int bits = 8;
int endianess = 0;
const char *typ = "playback";
AudioValueRange frameRange;
@@ -310,16 +307,9 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
bits = 16;
endianess = 1;
}
audio_pcm_init_info (
&hw->info,
as,
/* Following is irrelevant actually since we do not use
mixengs clipping routines */
audio_need_to_swap_endian (endianess)
);
audio_pcm_init_info (&hw->info, as);
/* open default output device */
propertySize = sizeof(core->outputDeviceID);
+9 -9
View File
@@ -70,7 +70,13 @@ static int glue (dsound_lock_, TYPE) (
int i;
LPVOID p1 = NULL, p2 = NULL;
DWORD blen1 = 0, blen2 = 0;
DWORD flag;
#ifdef DSBTYPE_IN
flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
#else
flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
#endif
for (i = 0; i < conf.lock_retries; ++i) {
hr = glue (IFACE, _Lock) (
buf,
@@ -80,13 +86,7 @@ static int glue (dsound_lock_, TYPE) (
&blen1,
&p2,
&blen2,
(entire
#ifdef DSBTYPE_IN
? DSCBLOCK_ENTIREBUFFER
#else
? DSBLOCK_ENTIREBUFFER
#endif
: 0)
flag
);
if (FAILED (hr)) {
@@ -250,8 +250,8 @@ static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
}
ds->first_time = 1;
audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0));
obt_as.endianness = 0;
audio_pcm_init_info (&hw->info, &obt_as);
if (bc.dwBufferBytes & hw->info.align) {
dolog (
+6 -2
View File
@@ -453,13 +453,11 @@ static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
if (src_len1) {
hw->clip (dst, src1, src_len1);
mixeng_clear (src1, src_len1);
}
if (src_len2) {
dst = advance (dst, src_len1 << hw->info.shift);
hw->clip (dst, src2, src_len2);
mixeng_clear (src2, src_len2);
}
hw->rpos = pos % hw->samples;
@@ -987,6 +985,12 @@ static void *dsound_audio_init (void)
hr = IDirectSound_Initialize (s->dsound, NULL);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not initialize DirectSound\n");
hr = IDirectSound_Release (s->dsound);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not release DirectSound\n");
}
s->dsound = NULL;
return NULL;
}
+6 -4
View File
@@ -153,13 +153,11 @@ static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
if (src_len1) {
hw->clip (dst, src1, src_len1);
mixeng_clear (src1, src_len1);
}
if (src_len2) {
dst = advance (dst, src_len1 << hw->info.shift);
hw->clip (dst, src2, src_len2);
mixeng_clear (src2, src_len2);
}
hw->rpos = pos % hw->samples;
@@ -360,6 +358,7 @@ static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
{
int bits16, mode, channel;
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
audsettings_t obt_as = *as;
mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
fmd->fmod_sample = FSOUND_Sample_Alloc (
@@ -386,7 +385,8 @@ static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
fmd->channel = channel;
/* FMOD always operates on little endian frames? */
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
obt_as.endianness = 0;
audio_pcm_init_info (&hw->info, &obt_as);
bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
@@ -420,6 +420,7 @@ static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
{
int bits16, mode;
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
audsettings_t obt_as = *as;
if (conf.broken_adc) {
return -1;
@@ -442,7 +443,8 @@ static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
}
/* FMOD always operates on little endian frames? */
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
obt_as.endianness = 0;
audio_pcm_init_info (&hw->info, &obt_as);
bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
+21 -19
View File
@@ -40,22 +40,21 @@ static int no_run_out (HWVoiceOut *hw)
{
NoVoiceOut *no = (NoVoiceOut *) hw;
int live, decr, samples;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - no->old_ticks;
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
if (bytes > INT_MAX) {
samples = INT_MAX >> hw->info.shift;
}
else {
samples = bytes >> hw->info.shift;
}
int64_t now;
int64_t ticks;
int64_t bytes;
live = audio_pcm_hw_get_live_out (&no->hw);
if (!live) {
return 0;
}
now = qemu_get_clock (vm_clock);
ticks = now - no->old_ticks;
bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
bytes = audio_MIN (bytes, INT_MAX);
samples = bytes >> hw->info.shift;
no->old_ticks = now;
decr = audio_MIN (live, samples);
hw->rpos = (hw->rpos + decr) % hw->samples;
@@ -69,7 +68,7 @@ static int no_write (SWVoiceOut *sw, void *buf, int len)
static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
{
audio_pcm_init_info (&hw->info, as, 0);
audio_pcm_init_info (&hw->info, as);
hw->samples = 1024;
return 0;
}
@@ -88,7 +87,7 @@ static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
{
audio_pcm_init_info (&hw->info, as, 0);
audio_pcm_init_info (&hw->info, as);
hw->samples = 1024;
return 0;
}
@@ -101,17 +100,20 @@ static void no_fini_in (HWVoiceIn *hw)
static int no_run_in (HWVoiceIn *hw)
{
NoVoiceIn *no = (NoVoiceIn *) hw;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - no->old_ticks;
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
int live = audio_pcm_hw_get_live_in (hw);
int dead = hw->samples - live;
int samples;
int samples = 0;
bytes = audio_MIN (bytes, INT_MAX);
samples = bytes >> hw->info.shift;
samples = audio_MIN (samples, dead);
if (dead) {
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - no->old_ticks;
int64_t bytes = (ticks * hw->info.bytes_per_second) / ticks_per_sec;
no->old_ticks = now;
bytes = audio_MIN (bytes, INT_MAX);
samples = bytes >> hw->info.shift;
samples = audio_MIN (samples, dead);
}
return samples;
}
+23 -17
View File
@@ -55,12 +55,14 @@ static struct {
int fragsize;
const char *devpath_out;
const char *devpath_in;
int debug;
} conf = {
.try_mmap = 0,
.nfrags = 4,
.fragsize = 4096,
.devpath_out = "/dev/dsp",
.devpath_in = "/dev/dsp"
.devpath_in = "/dev/dsp",
.debug = 0
};
struct oss_params {
@@ -324,9 +326,20 @@ static int oss_run_out (HWVoiceOut *hw)
return 0;
}
if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
abinfo.bytes, bufsize);
if (abinfo.bytes > bufsize) {
if (conf.debug) {
dolog ("warning: Invalid available size, size=%d bufsize=%d\n"
"please report your OS/audio hw to malc@pulsesoft.com\n",
abinfo.bytes, bufsize);
}
abinfo.bytes = bufsize;
}
if (abinfo.bytes < 0) {
if (conf.debug) {
dolog ("warning: Invalid available size, size=%d bufsize=%d\n",
abinfo.bytes, bufsize);
}
return 0;
}
@@ -369,15 +382,12 @@ static int oss_run_out (HWVoiceOut *hw)
"alignment %d\n",
wbytes, written, hw->info.align + 1);
}
mixeng_clear (src, wsamples);
decr -= wsamples;
rpos = (rpos + wsamples) % hw->samples;
break;
}
}
mixeng_clear (src, convert_samples);
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
}
@@ -443,12 +453,9 @@ static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
audio_pcm_init_info (&hw->info, &obt_as);
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
@@ -587,12 +594,9 @@ static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianness;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
audio_pcm_init_info (&hw->info, &obt_as);
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
@@ -730,6 +734,8 @@ static struct audio_option oss_options[] = {
"Path to DAC device", NULL, 0},
{"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
"Path to ADC device", NULL, 0},
{"DEBUG", AUD_OPT_BOOL, &conf.debug,
"Turn on some debugging messages", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
+1 -1
View File
@@ -51,7 +51,7 @@ void NAME (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
if (rate->opos_inc == (1ULL + UINT_MAX)) {
int i, n = *isamp > *osamp ? *osamp : *isamp;
for (i = 0; i < n; i++) {
OP (obuf[i].l, ibuf[i].r);
OP (obuf[i].l, ibuf[i].l);
OP (obuf[i].r, ibuf[i].r);
}
*isamp = n;
+2 -6
View File
@@ -240,7 +240,6 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
/* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
hw->clip (buf, src, chunk);
mixeng_clear (src, chunk);
sdl->rpos = (sdl->rpos + chunk) % hw->samples;
to_mix -= chunk;
buf += chunk << hw->info.shift;
@@ -336,12 +335,9 @@ static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as)
obt_as.freq = obt.freq;
obt_as.nchannels = obt.channels;
obt_as.fmt = effective_fmt;
obt_as.endianness = endianess;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianess)
);
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = obt.samples;
s->initialized = 1;
+2 -2
View File
@@ -81,7 +81,6 @@ static int wav_run_out (HWVoiceOut *hw)
hw->clip (dst, src, convert_samples);
qemu_put_buffer (wav->f, dst, convert_samples << hw->info.shift);
mixeng_clear (src, convert_samples);
rpos = (rpos + convert_samples) % hw->samples;
samples -= convert_samples;
@@ -136,7 +135,8 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
hdr[34] = bits16 ? 0x10 : 0x08;
audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0));
wav_as.endianness = 0;
audio_pcm_init_info (&hw->info, &wav_as);
hw->samples = 1024;
wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
+164
View File
@@ -0,0 +1,164 @@
#include "vl.h"
typedef struct {
QEMUFile *f;
int bytes;
char *path;
int freq;
int bits;
int nchannels;
CaptureVoiceOut *cap;
} WAVState;
/* VICE code: Store number as little endian. */
static void le_store (uint8_t *buf, uint32_t val, int len)
{
int i;
for (i = 0; i < len; i++) {
buf[i] = (uint8_t) (val & 0xff);
val >>= 8;
}
}
static void wav_notify (void *opaque, audcnotification_e cmd)
{
(void) opaque;
(void) cmd;
}
static void wav_destroy (void *opaque)
{
WAVState *wav = opaque;
uint8_t rlen[4];
uint8_t dlen[4];
uint32_t datalen = wav->bytes;
uint32_t rifflen = datalen + 36;
if (!wav->f) {
return;
}
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
qemu_fseek (wav->f, 4, SEEK_SET);
qemu_put_buffer (wav->f, rlen, 4);
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
fclose (wav->f);
if (wav->path) {
qemu_free (wav->path);
}
}
static void wav_capture (void *opaque, void *buf, int size)
{
WAVState *wav = opaque;
qemu_put_buffer (wav->f, buf, size);
wav->bytes += size;
}
static void wav_capture_destroy (void *opaque)
{
WAVState *wav = opaque;
AUD_del_capture (wav->cap, wav);
}
static void wav_capture_info (void *opaque)
{
WAVState *wav = opaque;
char *path = wav->path;
term_printf ("Capturing audio(%d,%d,%d) to %s: %d bytes\n",
wav->freq, wav->bits, wav->nchannels,
path ? path : "<not available>", wav->bytes);
}
static struct capture_ops wav_capture_ops = {
.destroy = wav_capture_destroy,
.info = wav_capture_info
};
int wav_start_capture (CaptureState *s, const char *path, int freq,
int bits, int nchannels)
{
WAVState *wav;
uint8_t hdr[] = {
0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56,
0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00,
0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04,
0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00
};
audsettings_t as;
struct audio_capture_ops ops;
int stereo, bits16, shift;
CaptureVoiceOut *cap;
if (bits != 8 && bits != 16) {
term_printf ("incorrect bit count %d, must be 8 or 16\n", bits);
return -1;
}
if (nchannels != 1 && nchannels != 2) {
term_printf ("incorrect channel count %d, must be 1 or 2\n",
nchannels);
return -1;
}
stereo = nchannels == 2;
bits16 = bits == 16;
as.freq = freq;
as.nchannels = 1 << stereo;
as.fmt = bits16 ? AUD_FMT_S16 : AUD_FMT_U8;
as.endianness = 0;
ops.notify = wav_notify;
ops.capture = wav_capture;
ops.destroy = wav_destroy;
wav = qemu_mallocz (sizeof (*wav));
if (!wav) {
term_printf ("Could not allocate memory for wav capture (%zu bytes)",
sizeof (*wav));
return -1;
}
shift = bits16 + stereo;
hdr[34] = bits16 ? 0x10 : 0x08;
le_store (hdr + 22, as.nchannels, 2);
le_store (hdr + 24, freq, 4);
le_store (hdr + 28, freq << shift, 4);
le_store (hdr + 32, 1 << shift, 2);
wav->f = fopen (path, "wb");
if (!wav->f) {
term_printf ("Failed to open wave file `%s'\nReason: %s\n",
path, strerror (errno));
qemu_free (wav);
return -1;
}
wav->path = qemu_strdup (path);
wav->bits = bits;
wav->nchannels = nchannels;
wav->freq = freq;
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
cap = AUD_add_capture (NULL, &as, &ops, wav);
if (!cap) {
term_printf ("Failed to add audio capture\n");
qemu_free (wav);
return -1;
}
wav->cap = cap;
s->opaque = wav;
s->ops = wav_capture_ops;
return 0;
}
+7
View File
@@ -250,6 +250,12 @@ static int cow_create(const char *filename, int64_t image_sectors,
return 0;
}
static void cow_flush(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
fsync(s->fd);
}
BlockDriver bdrv_cow = {
"cow",
sizeof(BDRVCowState),
@@ -259,6 +265,7 @@ BlockDriver bdrv_cow = {
cow_write,
cow_close,
cow_create,
cow_flush,
cow_is_allocated,
};
#endif
+7
View File
@@ -693,6 +693,12 @@ int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
return 0;
}
static void qcow_flush(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
fsync(s->fd);
}
BlockDriver bdrv_qcow = {
"qcow",
sizeof(BDRVQcowState),
@@ -702,6 +708,7 @@ BlockDriver bdrv_qcow = {
qcow_write,
qcow_close,
qcow_create,
qcow_flush,
qcow_is_allocated,
qcow_set_key,
qcow_make_empty
+7
View File
@@ -426,6 +426,12 @@ static void vmdk_close(BlockDriverState *bs)
close(s->fd);
}
static void vmdk_flush(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
fsync(s->fd);
}
BlockDriver bdrv_vmdk = {
"vmdk",
sizeof(BDRVVmdkState),
@@ -435,5 +441,6 @@ BlockDriver bdrv_vmdk = {
vmdk_write,
vmdk_close,
vmdk_create,
vmdk_flush,
vmdk_is_allocated,
};
+1 -1
View File
@@ -163,7 +163,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
bitmap_offset = 512 * s->pagetable[pagetable_index];
block_offset = bitmap_offset + 512 + (512 * pageentry_index);
// printf("sector: %llx, index: %x, offset: %x, bioff: %llx, bloff: %llx\n",
// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
// sector_num, pagetable_index, pageentry_index,
// bitmap_offset, block_offset);
+1
View File
@@ -2772,6 +2772,7 @@ BlockDriver bdrv_vvfat = {
vvfat_read,
vvfat_write,
vvfat_close,
NULL, /* ??? Not sure if we can do any meaningful flushing. */
NULL,
vvfat_is_allocated
};
+61
View File
@@ -615,6 +615,14 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
return bs->device_name;
}
void bdrv_flush(BlockDriverState *bs)
{
if (bs->drv->bdrv_flush)
bs->drv->bdrv_flush(bs);
if (bs->backing_hd)
bdrv_flush(bs->backing_hd);
}
void bdrv_info(void)
{
BlockDriverState *bs;
@@ -753,6 +761,51 @@ static void raw_close(BlockDriverState *bs)
close(s->fd);
}
#ifdef _WIN32
#include <windows.h>
#include <winioctl.h>
int qemu_ftruncate64(int fd, int64_t length)
{
LARGE_INTEGER li;
LONG high;
HANDLE h;
BOOL res;
if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
return -1;
h = (HANDLE)_get_osfhandle(fd);
/* get current position, ftruncate do not change position */
li.HighPart = 0;
li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
return -1;
high = length >> 32;
if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
return -1;
res = SetEndOfFile(h);
/* back to old position */
SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
return res ? 0 : -1;
}
static int set_sparse(int fd)
{
DWORD returned;
return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
NULL, 0, NULL, 0, &returned, NULL);
}
#else
static inline int set_sparse(int fd)
{
return 1;
}
#endif
static int raw_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
@@ -765,11 +818,18 @@ static int raw_create(const char *filename, int64_t total_size,
0644);
if (fd < 0)
return -EIO;
set_sparse(fd);
ftruncate(fd, total_size * 512);
close(fd);
return 0;
}
static void raw_flush(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
fsync(s->fd);
}
BlockDriver bdrv_raw = {
"raw",
sizeof(BDRVRawState),
@@ -779,6 +839,7 @@ BlockDriver bdrv_raw = {
raw_write,
raw_close,
raw_create,
raw_flush,
};
void bdrv_init(void)
+1
View File
@@ -36,6 +36,7 @@ struct BlockDriver {
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
+36 -20
View File
@@ -439,23 +439,40 @@ static void cocoa_refresh(DisplayState *ds)
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
/* handle monitor key events */
} else {
int keysym = 0;
switch([event keyCode]) {
case 123:
kbd_put_keysym(QEMU_KEY_LEFT);
break;
case 124:
kbd_put_keysym(QEMU_KEY_RIGHT);
break;
case 125:
kbd_put_keysym(QEMU_KEY_DOWN);
break;
case 126:
kbd_put_keysym(QEMU_KEY_UP);
break;
default:
kbd_put_keysym([[event characters] characterAtIndex:0]);
break;
case 115:
keysym = QEMU_KEY_HOME;
break;
case 117:
keysym = QEMU_KEY_DELETE;
break;
case 119:
keysym = QEMU_KEY_END;
break;
case 123:
keysym = QEMU_KEY_LEFT;
break;
case 124:
keysym = QEMU_KEY_RIGHT;
break;
case 125:
keysym = QEMU_KEY_DOWN;
break;
case 126:
keysym = QEMU_KEY_UP;
break;
default:
{
NSString *ks = [event characters];
if ([ks length] > 0)
keysym = [ks characterAtIndex:0];
}
}
if (keysym)
kbd_put_keysym(keysym);
}
}
}
@@ -867,10 +884,9 @@ static void setupWindowMenu(void)
/* Finally give up our references to the objects */
[windowMenu release];
[windowMenuItem release];
}
static void CustomApplicationMain (argc, argv)
static void CustomApplicationMain(void)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QemuCocoaGUIController *gui_controller;
@@ -904,8 +920,8 @@ int main(int argc, char **argv)
{
gArgc = argc;
gArgv = argv;
CustomApplicationMain (argc, argv);
CustomApplicationMain();
return 0;
}
Vendored
+38 -7
View File
@@ -95,6 +95,8 @@ check_gcc="yes"
softmmu="yes"
user="no"
build_docs="no"
build_acpi_tables="no"
uname_release=""
# OS specific
targetos=`uname -s`
@@ -211,7 +213,7 @@ for opt do
;;
--fmod-inc=*) fmod_inc="$optarg"
;;
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
;;
--disable-slirp) slirp="no"
;;
@@ -237,6 +239,10 @@ for opt do
;;
--enable-user) user="yes"
;;
--enable-uname-release=*) uname_release="$optarg"
;;
--enable-iasl) build_acpi_tables="yes"
;;
esac
done
@@ -284,6 +290,8 @@ echo " --enable-user enable all linux usermode emulation targets"
echo " --disable-user disable all linux usermode emulation targets"
echo " --fmod-lib path to FMOD library"
echo " --fmod-inc path to FMOD includes"
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
echo " --enable-iasl compilation of ACPI tables with the IASL compiler"
echo ""
echo "NOTE: The object files are build at the place where configure is launched"
exit 1
@@ -293,15 +301,21 @@ cc="${cross_prefix}${cc}"
ar="${cross_prefix}${ar}"
strip="${cross_prefix}${strip}"
if [ ! -x "`which $cc`" ] ; then
echo "Compiler $cc could not be found"
exit
# check that the C compiler works.
cat > $TMPC <<EOF
int main(void) {}
EOF
if $cc -c -o $TMPO $TMPC 2>/dev/null ; then
: C compiler works ok
else
echo "ERROR: \"$cc\" either does not exist or does not work"
exit 1
fi
if test "$mingw32" = "yes" ; then
linux="no"
EXESUF=".exe"
gdbstub="no"
oss="no"
if [ "$cpu" = "i386" ] ; then
kqemu="yes"
@@ -546,6 +560,8 @@ fi
echo "FMOD support $fmod $fmod_support"
echo "kqemu support $kqemu"
echo "Documentation $build_docs"
[ ! -z "$uname_release" ] && \
echo "uname -r $uname_release"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -696,6 +712,9 @@ echo "TARGET_DIRS=$target_list" >> $config_mak
if [ "$build_docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_mak
fi
if [ "$build_acpi_tables" = "yes" ] ; then
echo "BUILD_ACPI_TABLES=yes" >> $config_mak
fi
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
@@ -704,6 +723,8 @@ if [ "$bsd" = "yes" ] ; then
echo "#define _BSD 1" >> $config_h
fi
echo "#define CONFIG_UNAME_RELEASE \"$uname_release\"" >> $config_h
for target in $target_list; do
target_dir="$target"
config_mak=$target_dir/config.mak
@@ -716,6 +737,7 @@ target_bigendian="no"
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
[ "$target_cpu" = "mips" ] && target_bigendian=yes
[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
target_softmmu="no"
if expr $target : '.*-softmmu' > /dev/null ; then
target_softmmu="yes"
@@ -758,6 +780,7 @@ echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "include ../config-host.mak" >> $config_mak
echo "#include \"../config-host.h\"" >> $config_h
bflt="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
@@ -772,6 +795,7 @@ elif test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
echo "TARGET_ARCH=arm" >> $config_mak
echo "#define TARGET_ARCH \"arm\"" >> $config_h
echo "#define TARGET_ARM 1" >> $config_h
bflt="yes"
elif test "$target_cpu" = "sparc" ; then
echo "TARGET_ARCH=sparc" >> $config_mak
echo "#define TARGET_ARCH \"sparc\"" >> $config_h
@@ -802,10 +826,13 @@ elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then
echo "TARGET_ARCH=mips" >> $config_mak
echo "#define TARGET_ARCH \"mips\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
elif test "$target_cpu" = "sh4" ; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
echo "TARGET_ARCH=sh4" >> $config_mak
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
echo "#define TARGET_SH4 1" >> $config_h
bflt="yes"
else
echo "Unsupported target CPU"
exit 1
@@ -823,10 +850,14 @@ if test "$target_user_only" = "yes" ; then
echo "#define CONFIG_USER_ONLY 1" >> $config_h
fi
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
fi
if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=yes" >> $config_mak
echo "#define TARGET_HAS_BFLT 1" >> $config_h
fi
# sdl defines
if test "$target_user_only" = "no"; then
+126 -44
View File
@@ -27,8 +27,8 @@
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RGB(r, g, b) RGBA(r, g, b, 0xff)
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
typedef struct TextAttributes {
uint8_t fgcol:4;
@@ -53,6 +53,57 @@ enum TTYState {
TTY_STATE_CSI,
};
typedef struct QEMUFIFO {
uint8_t *buf;
int buf_size;
int count, wptr, rptr;
} QEMUFIFO;
int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
{
int l, len;
l = f->buf_size - f->count;
if (len1 > l)
len1 = l;
len = len1;
while (len > 0) {
l = f->buf_size - f->wptr;
if (l > len)
l = len;
memcpy(f->buf + f->wptr, buf, l);
f->wptr += l;
if (f->wptr >= f->buf_size)
f->wptr = 0;
buf += l;
len -= l;
}
f->count += len1;
return len1;
}
int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
{
int l, len;
if (len1 > f->count)
len1 = f->count;
len = len1;
while (len > 0) {
l = f->buf_size - f->rptr;
if (l > len)
l = len;
memcpy(buf, f->buf + f->rptr, l);
f->rptr += l;
if (f->rptr >= f->buf_size)
f->rptr = 0;
buf += l;
len -= l;
}
f->count -= len1;
return len1;
}
/* ??? This is mis-named.
It is used for both text and graphical consoles. */
struct TextConsole {
@@ -81,8 +132,13 @@ struct TextConsole {
int nb_esc_params;
/* kbd read handler */
IOCanRWHandler *fd_can_read;
IOReadHandler *fd_read;
void *fd_opaque;
/* fifo for key pressed */
QEMUFIFO out_fifo;
uint8_t out_fifo_buf[16];
QEMUTimer *kbd_timer;
};
static TextConsole *active_console;
@@ -274,24 +330,24 @@ enum color_names {
static const uint32_t color_table_rgb[2][8] = {
{ /* dark */
RGB(0x00, 0x00, 0x00), /* black */
RGB(0xaa, 0x00, 0x00), /* red */
RGB(0x00, 0xaa, 0x00), /* green */
RGB(0xaa, 0xaa, 0x00), /* yellow */
RGB(0x00, 0x00, 0xaa), /* blue */
RGB(0xaa, 0x00, 0xaa), /* magenta */
RGB(0x00, 0xaa, 0xaa), /* cyan */
RGB(0xaa, 0xaa, 0xaa), /* white */
QEMU_RGB(0x00, 0x00, 0x00), /* black */
QEMU_RGB(0xaa, 0x00, 0x00), /* red */
QEMU_RGB(0x00, 0xaa, 0x00), /* green */
QEMU_RGB(0xaa, 0xaa, 0x00), /* yellow */
QEMU_RGB(0x00, 0x00, 0xaa), /* blue */
QEMU_RGB(0xaa, 0x00, 0xaa), /* magenta */
QEMU_RGB(0x00, 0xaa, 0xaa), /* cyan */
QEMU_RGB(0xaa, 0xaa, 0xaa), /* white */
},
{ /* bright */
RGB(0x00, 0x00, 0x00), /* black */
RGB(0xff, 0x00, 0x00), /* red */
RGB(0x00, 0xff, 0x00), /* green */
RGB(0xff, 0xff, 0x00), /* yellow */
RGB(0x00, 0x00, 0xff), /* blue */
RGB(0xff, 0x00, 0xff), /* magenta */
RGB(0x00, 0xff, 0xff), /* cyan */
RGB(0xff, 0xff, 0xff), /* white */
QEMU_RGB(0x00, 0x00, 0x00), /* black */
QEMU_RGB(0xff, 0x00, 0x00), /* red */
QEMU_RGB(0x00, 0xff, 0x00), /* green */
QEMU_RGB(0xff, 0xff, 0x00), /* yellow */
QEMU_RGB(0x00, 0x00, 0xff), /* blue */
QEMU_RGB(0xff, 0x00, 0xff), /* magenta */
QEMU_RGB(0x00, 0xff, 0xff), /* cyan */
QEMU_RGB(0xff, 0xff, 0xff), /* white */
}
};
@@ -563,7 +619,6 @@ static void console_put_lf(TextConsole *s)
TextCell *c;
int x, y1;
s->x = 0;
s->y++;
if (s->y >= s->height) {
s->y = s->height - 1;
@@ -712,15 +767,12 @@ static void console_putchar(TextConsole *s, int ch)
console_put_lf(s);
break;
case '\b': /* backspace */
if(s->x > 0) s->x--;
y1 = (s->y_base + s->y) % s->total_height;
c = &s->cells[y1 * s->width + s->x];
c->ch = ' ';
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
if (s->x > 0)
s->x--;
break;
case '\t': /* tabspace */
if (s->x + (8 - (s->x % 8)) > s->width) {
s->x = 0;
console_put_lf(s);
} else {
s->x = s->x + (8 - (s->x % 8));
@@ -739,8 +791,10 @@ static void console_putchar(TextConsole *s, int ch)
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
s->x++;
if (s->x >= s->width)
if (s->x >= s->width) {
s->x = 0;
console_put_lf(s);
}
break;
}
break;
@@ -835,6 +889,7 @@ static void console_chr_add_read_handler(CharDriverState *chr,
IOReadHandler *fd_read, void *opaque)
{
TextConsole *s = chr->opaque;
s->fd_can_read = fd_can_read;
s->fd_read = fd_read;
s->fd_opaque = opaque;
}
@@ -854,6 +909,28 @@ static void console_send_event(CharDriverState *chr, int event)
}
}
static void kbd_send_chars(void *opaque)
{
TextConsole *s = opaque;
int len;
uint8_t buf[16];
len = s->fd_can_read(s->fd_opaque);
if (len > s->out_fifo.count)
len = s->out_fifo.count;
if (len > 0) {
if (len > sizeof(buf))
len = sizeof(buf);
qemu_fifo_read(&s->out_fifo, buf, len);
s->fd_read(s->fd_opaque, buf, len);
}
/* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
if (s->out_fifo.count > 0) {
qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
}
}
/* called when an ascii key is pressed */
void kbd_put_keysym(int keysym)
{
@@ -879,25 +956,26 @@ void kbd_put_keysym(int keysym)
console_scroll(10);
break;
default:
if (s->fd_read) {
/* convert the QEMU keysym to VT100 key string */
q = buf;
if (keysym >= 0xe100 && keysym <= 0xe11f) {
*q++ = '\033';
*q++ = '[';
c = keysym - 0xe100;
if (c >= 10)
*q++ = '0' + (c / 10);
*q++ = '0' + (c % 10);
*q++ = '~';
} else if (keysym >= 0xe120 && keysym <= 0xe17f) {
*q++ = '\033';
*q++ = '[';
*q++ = keysym & 0xff;
} else {
/* convert the QEMU keysym to VT100 key string */
q = buf;
if (keysym >= 0xe100 && keysym <= 0xe11f) {
*q++ = '\033';
*q++ = '[';
c = keysym - 0xe100;
if (c >= 10)
*q++ = '0' + (c / 10);
*q++ = '0' + (c % 10);
*q++ = '~';
} else if (keysym >= 0xe120 && keysym <= 0xe17f) {
*q++ = '\033';
*q++ = '[';
*q++ = keysym & 0xff;
} else {
*q++ = keysym;
}
s->fd_read(s->fd_opaque, buf, q - buf);
}
if (s->fd_read) {
qemu_fifo_write(&s->out_fifo, buf, q - buf);
kbd_send_chars(s);
}
break;
}
@@ -974,6 +1052,10 @@ CharDriverState *text_console_init(DisplayState *ds)
chr->chr_add_read_handler = console_chr_add_read_handler;
chr->chr_send_event = console_send_event;
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
if (!color_inited) {
color_inited = 1;
for(j = 0; j < 2; j++) {
+99 -3
View File
@@ -828,6 +828,10 @@ extern uint8_t *phys_ram_dirty;
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */
/* acts like a ROM when read and like a device when written. As an
exception, the write memory callback gets the ram offset instead of
the physical address */
#define IO_MEM_ROMD (1)
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
@@ -896,15 +900,107 @@ void cpu_tlb_update_dirty(CPUState *env);
void dump_exec_info(FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
/* profiling */
#ifdef CONFIG_PROFILER
static inline int64_t profile_getclock(void)
/*******************************************/
/* host CPU ticks (if available) */
#if defined(__powerpc__)
static inline uint32_t get_tbl(void)
{
uint32_t tbl;
asm volatile("mftb %0" : "=r" (tbl));
return tbl;
}
static inline uint32_t get_tbu(void)
{
uint32_t tbl;
asm volatile("mftbu %0" : "=r" (tbl));
return tbl;
}
static inline int64_t cpu_get_real_ticks(void)
{
uint32_t l, h, h1;
/* NOTE: we test if wrapping has occurred */
do {
h = get_tbu();
l = get_tbl();
h1 = get_tbu();
} while (h != h1);
return ((int64_t)h << 32) | l;
}
#elif defined(__i386__)
static inline int64_t cpu_get_real_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
return val;
}
#elif defined(__x86_64__)
static inline int64_t cpu_get_real_ticks(void)
{
uint32_t low,high;
int64_t val;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
val = high;
val <<= 32;
val |= low;
return val;
}
#elif defined(__ia64)
static inline int64_t cpu_get_real_ticks(void)
{
int64_t val;
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
return val;
}
#elif defined(__s390__)
static inline int64_t cpu_get_real_ticks(void)
{
int64_t val;
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
return val;
}
#elif defined(__sparc_v9__)
static inline int64_t cpu_get_real_ticks (void)
{
#if defined(_LP64)
uint64_t rval;
asm volatile("rd %%tick,%0" : "=r"(rval));
return rval;
#else
union {
uint64_t i64;
struct {
uint32_t high;
uint32_t low;
} i32;
} rval;
asm volatile("rd %%tick,%1; srlx %1,32,%0"
: "=r"(rval.i32.high), "=r"(rval.i32.low));
return rval.i64;
#endif
}
#endif
/* profiling */
#ifdef CONFIG_PROFILER
static inline int64_t profile_getclock(void)
{
return cpu_get_real_ticks();
}
extern int64_t kqemu_time, kqemu_time_start;
extern int64_t qemu_time, qemu_time_start;
extern int64_t tlb_flush_time;
+1 -1
View File
@@ -47,7 +47,7 @@ typedef uint32_t target_ulong;
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#define TARGET_FMT_lx "%016llx"
#define TARGET_FMT_lx "%016" PRIx64
#else
#error TARGET_LONG_SIZE undefined
#endif
+25 -22
View File
@@ -47,7 +47,7 @@ void cpu_loop_exit(void)
longjmp(env->jmp_env, 1);
}
#endif
#ifndef TARGET_SPARC
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
#define reg_T2
#endif
@@ -175,9 +175,13 @@ static inline TranslationBlock *tb_find_fast(void)
pc = env->regs[15];
#elif defined(TARGET_SPARC)
#ifdef TARGET_SPARC64
flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
// Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
| (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
#else
flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
// FPU enable . MMU enabled . MMU no-fault . Supervisor
flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
| env->psrs;
#endif
cs_base = env->npc;
pc = env->pc;
@@ -253,7 +257,7 @@ int cpu_exec(CPUState *env1)
uint32_t *saved_regwptr;
#endif
#endif
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
int saved_i7, tmp_T0;
#endif
int ret, interrupt_request;
@@ -323,7 +327,7 @@ int cpu_exec(CPUState *env1)
#if defined(reg_T2)
saved_T2 = T2;
#endif
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
/* we also save i7 because longjmp may not restore it */
asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
#endif
@@ -447,7 +451,7 @@ int cpu_exec(CPUState *env1)
T0 = 0; /* force lookup of first TB */
for(;;) {
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
/* g1 can be modified by some libc? functions */
tmp_T0 = T0;
#endif
@@ -467,7 +471,7 @@ int cpu_exec(CPUState *env1)
do_interrupt(intno, 0, 0, 0, 1);
/* ensure that no TB jump will be modified as
the program flow was changed */
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -486,7 +490,7 @@ int cpu_exec(CPUState *env1)
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -497,7 +501,7 @@ int cpu_exec(CPUState *env1)
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -516,7 +520,7 @@ int cpu_exec(CPUState *env1)
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -534,7 +538,7 @@ int cpu_exec(CPUState *env1)
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
do_interrupt(env->interrupt_index);
env->interrupt_index = 0;
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -561,11 +565,13 @@ int cpu_exec(CPUState *env1)
#elif defined(TARGET_SH4)
/* XXXXX */
#endif
/* Don't use the cached interupt_request value,
do_interrupt may have updated the EXITTB flag. */
if (env->interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
/* ensure that no TB jump will be modified as
the program flow was changed */
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
T0 = 0;
@@ -633,7 +639,7 @@ int cpu_exec(CPUState *env1)
lookup_symbol(tb->pc));
}
#endif
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
T0 = tmp_T0;
#endif
/* see if we can patch the calling TB. When the TB
@@ -669,7 +675,9 @@ int cpu_exec(CPUState *env1)
"mov %%o7,%%i0"
: /* no outputs */
: "r" (gen_func)
: "i0", "i1", "i2", "i3", "i4", "i5");
: "i0", "i1", "i2", "i3", "i4", "i5",
"l0", "l1", "l2", "l3", "l4", "l5",
"l6", "l7");
#elif defined(__arm__)
asm volatile ("mov pc, %0\n\t"
".global exec_loop\n\t"
@@ -834,7 +842,7 @@ int cpu_exec(CPUState *env1)
#else
#error unsupported target CPU
#endif
#ifdef __sparc__
#if defined(__sparc__) && !defined(HOST_SOLARIS)
asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
#endif
T0 = saved_T0;
@@ -1168,19 +1176,14 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
a virtual CPU fault */
cpu_restore_state(tb, env, pc, puc);
}
if (ret == 1) {
#if 0
printf("PF exception: NIP=0x%08x error=0x%x %p\n",
env->nip, env->error_code, tb);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
// do_raise_exception_err(env->exception_index, env->error_code);
} else {
/* activate soft MMU for this block */
cpu_resume_from_signal(env, puc);
}
sigprocmask(SIG_SETMASK, old_set, NULL);
cpu_loop_exit();
/* never comes here */
return 1;
}
+2 -2
View File
@@ -58,7 +58,7 @@ perror_memory (status, memaddr, info)
/* Actually, address between memaddr and memaddr + len was
out of bounds. */
(*info->fprintf_func) (info->stream,
"Address 0x%llx is out of bounds.\n", memaddr);
"Address 0x%" PRIx64 " is out of bounds.\n", memaddr);
}
/* This could be in a separate file, to save miniscule amounts of space
@@ -73,7 +73,7 @@ generic_print_address (addr, info)
bfd_vma addr;
struct disassemble_info *info;
{
(*info->fprintf_func) (info->stream, "0x%llx", addr);
(*info->fprintf_func) (info->stream, "0x%" PRIx64, addr);
}
/* Just return the given address. */
+23 -4
View File
@@ -35,12 +35,15 @@
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
// Linux/Sparc64 defines uint64_t
#if !(defined (__sparc_v9__) && defined(__linux__))
/* XXX may be done for all 64 bits targets ? */
#if defined (__x86_64__) || defined(__ia64)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
#endif
/* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd
prior to this and will cause an error in compliation, conflicting
@@ -50,11 +53,14 @@ typedef signed char int8_t;
#endif
typedef signed short int16_t;
typedef signed int int32_t;
// Linux/Sparc64 defines int64_t
#if !(defined (__sparc_v9__) && defined(__linux__))
#if defined (__x86_64__) || defined(__ia64)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#endif
#endif
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
@@ -121,6 +127,19 @@ extern int printf(const char *, ...);
#define AREG3 "s2"
#endif
#ifdef __sparc__
#ifdef HOST_SOLARIS
#define AREG0 "g2"
#define AREG1 "g3"
#define AREG2 "g4"
#define AREG3 "g5"
#define AREG4 "g6"
#else
#ifdef __sparc_v9__
#define AREG0 "g1"
#define AREG1 "g4"
#define AREG2 "g5"
#define AREG3 "g7"
#else
#define AREG0 "g6"
#define AREG1 "g1"
#define AREG2 "g2"
@@ -133,6 +152,8 @@ extern int printf(const char *, ...);
#define AREG9 "l5"
#define AREG10 "l6"
#define AREG11 "l7"
#endif
#endif
#define USE_FP_CONVERT
#endif
#ifdef __s390__
@@ -241,10 +262,8 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __sparc__
#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0\n" \
"nop")
#define GOTO_LABEL_PARAM(n) asm volatile ( \
"set " ASM_NAME(__op_gen_label) #n ", %g1; jmp %g1; nop")
#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop")
#define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop")
#endif
#ifdef __arm__
#define EXIT_TB() asm volatile ("b exec_loop")
+80 -12
View File
@@ -1196,7 +1196,7 @@ void get_reloc_expr(char *name, int name_size, const char *sym_name)
} else {
#ifdef HOST_SPARC
if (sym_name[0] == '.')
snprintf(name, sizeof(name),
snprintf(name, name_size,
"(long)(&__dot_%s)",
sym_name + 1);
else
@@ -1440,6 +1440,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_SPARC)
{
#define INSN_SAVE 0x9de3a000
#define INSN_RET 0x81c7e008
#define INSN_RETL 0x81c3e008
#define INSN_RESTORE 0x81e80000
#define INSN_RETURN 0x81cfe008
#define INSN_NOP 0x01000000
#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
uint32_t start_insn, end_insn1, end_insn2;
uint8_t *p;
p = (void *)(p_end - 8);
@@ -1448,13 +1457,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
start_insn = get32((uint32_t *)(p_start + 0x0));
end_insn1 = get32((uint32_t *)(p + 0x0));
end_insn2 = get32((uint32_t *)(p + 0x4));
if ((start_insn & ~0x1fff) == 0x9de3a000) {
if (((start_insn & ~0x1fff) == INSN_SAVE) ||
(start_insn & ~0x1fff) == INSN_ADD_SP) {
p_start += 0x4;
start_offset += 0x4;
if ((int)(start_insn | ~0x1fff) < -128)
error("Found bogus save at the start of %s", name);
if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
/* SPARC v7: ret; restore; */ ;
else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
/* SPARC v9: return; nop; */ ;
else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
/* SPARC v7: retl; sub %sp, nn, %sp; */ ;
else
error("ret; restore; not found at end of %s", name);
} else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
;
} else {
error("No save at the beginning of %s", name);
}
@@ -1462,7 +1479,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
/* Skip a preceeding nop, if present. */
if (p > p_start) {
skip_insn = get32((uint32_t *)(p - 0x4));
if (skip_insn == 0x01000000)
if (skip_insn == INSN_NOP)
p -= 4;
}
#endif
@@ -1470,21 +1487,41 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_SPARC64)
{
#define INSN_SAVE 0x9de3a000
#define INSN_RET 0x81c7e008
#define INSN_RETL 0x81c3e008
#define INSN_RESTORE 0x81e80000
#define INSN_RETURN 0x81cfe008
#define INSN_NOP 0x01000000
#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp
#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp
uint32_t start_insn, end_insn1, end_insn2, skip_insn;
uint8_t *p;
p = (void *)(p_end - 8);
#if 0
/* XXX: check why it occurs */
if (p <= p_start)
error("empty code for %s", name);
#endif
start_insn = get32((uint32_t *)(p_start + 0x0));
end_insn1 = get32((uint32_t *)(p + 0x0));
end_insn2 = get32((uint32_t *)(p + 0x4));
if ((start_insn & ~0x1fff) == 0x9de3a000) {
if (((start_insn & ~0x1fff) == INSN_SAVE) ||
(start_insn & ~0x1fff) == INSN_ADD_SP) {
p_start += 0x4;
start_offset += 0x4;
if ((int)(start_insn | ~0x1fff) < -256)
error("Found bogus save at the start of %s", name);
if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE)
/* SPARC v7: ret; restore; */ ;
else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP)
/* SPARC v9: return; nop; */ ;
else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP)
/* SPARC v7: retl; sub %sp, nn, %sp; */ ;
else
error("ret; restore; not found at end of %s", name);
} else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) {
;
} else {
error("No save at the beginning of %s", name);
}
@@ -2151,6 +2188,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
reloc_offset, reloc_offset, name, addend,
reloc_offset);
break;
case R_SPARC_WDISP22:
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) "
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffff);\n",
rel->r_offset - start_offset,
rel->r_offset - start_offset,
name, addend,
rel->r_offset - start_offset);
break;
default:
error("unsupported sparc relocation (%d)", type);
}
@@ -2168,7 +2217,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
get_reloc_expr(name, sizeof(name), sym_name);
type = ELF64_R_TYPE(rel->r_info);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
@@ -2192,6 +2241,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" | ((%s + %d) & 0x3ff);\n",
reloc_offset, reloc_offset, name, addend);
break;
case R_SPARC_OLO10:
addend += ELF64_R_TYPE_DATA (rel->r_info);
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n",
reloc_offset, reloc_offset, name, addend);
break;
case R_SPARC_WDISP30:
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = "
@@ -2202,8 +2260,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
reloc_offset, reloc_offset, name, addend,
reloc_offset);
break;
case R_SPARC_WDISP22:
fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) "
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffff);\n",
reloc_offset, reloc_offset, name, addend,
reloc_offset);
break;
default:
error("unsupported sparc64 relocation (%d)", type);
error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
}
}
}
+7 -1
View File
@@ -19,7 +19,13 @@
*/
int __op_param1, __op_param2, __op_param3;
int __op_gen_label1, __op_gen_label2, __op_gen_label3;
#ifdef __sparc__
void __op_gen_label1(){}
void __op_gen_label2(){}
void __op_gen_label3(){}
#else
int __op_gen_label1, __op_gen_label2, __op_gen_label3;
#endif
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
+2
View File
@@ -227,6 +227,7 @@ typedef struct {
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
#define ELF64_R_TYPE_DATA(i) (((ELF64_R_TYPE(i) >> 8) ^ 0x00800000) - 0x00800000)
#define R_386_NONE 0
#define R_386_32 1
@@ -326,6 +327,7 @@ typedef struct {
#define R_SPARC_10 30
#define R_SPARC_11 31
#define R_SPARC_64 32
#define R_SPARC_OLO10 33
#define R_SPARC_WDISP16 40
#define R_SPARC_WDISP19 41
#define R_SPARC_7 43
+1 -1
View File
@@ -570,7 +570,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
ldub_code(addr);
}
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM) {
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
}
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
+24 -9
View File
@@ -1488,7 +1488,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
if (is_softmmu)
#endif
{
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
/* IO memory case */
address = vaddr | pd;
addend = paddr;
@@ -1513,9 +1513,11 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
te->addr_code = -1;
}
if (prot & PAGE_WRITE) {
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM) {
/* ROM: access is ignored (same as unassigned) */
te->addr_write = vaddr | IO_MEM_ROM;
if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_ROM ||
(pd & IO_MEM_ROMD)) {
/* write access calls the I/O callback */
te->addr_write = vaddr |
(pd & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
} else if ((pd & ~TARGET_PAGE_MASK) == IO_MEM_RAM &&
!cpu_physical_memory_is_dirty(pd)) {
te->addr_write = vaddr | IO_MEM_NOTDIRTY;
@@ -1779,15 +1781,24 @@ void cpu_register_physical_memory(target_phys_addr_t start_addr,
{
target_phys_addr_t addr, end_addr;
PhysPageDesc *p;
CPUState *env;
size = (size + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
end_addr = start_addr + size;
for(addr = start_addr; addr != end_addr; addr += TARGET_PAGE_SIZE) {
p = phys_page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
p->phys_offset = phys_offset;
if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM)
if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM ||
(phys_offset & IO_MEM_ROMD))
phys_offset += TARGET_PAGE_SIZE;
}
/* since each CPU stores ram addresses in its TLB cache, we must
reset the modified entries */
/* XXX: slow ! */
for(env = first_cpu; env != NULL; env = env->next_cpu) {
tlb_flush(env, 1);
}
}
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -2048,7 +2059,8 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
}
}
} else {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
if (l >= 4 && ((addr & 3) == 0)) {
@@ -2103,7 +2115,8 @@ void cpu_physical_memory_write_rom(target_phys_addr_t addr,
}
if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM &&
(pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM) {
(pd & ~TARGET_PAGE_MASK) != IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
/* do nothing */
} else {
unsigned long addr1;
@@ -2135,7 +2148,8 @@ uint32_t ldl_phys(target_phys_addr_t addr)
pd = p->phys_offset;
}
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
@@ -2164,7 +2178,8 @@ uint64_t ldq_phys(target_phys_addr_t addr)
pd = p->phys_offset;
}
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM &&
!(pd & IO_MEM_ROMD)) {
/* I/O case */
io_index = (pd >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
#ifdef TARGET_WORDS_BIGENDIAN
+9 -4
View File
@@ -6,7 +6,7 @@
void set_float_rounding_mode(int val STATUS_PARAM)
{
STATUS(float_rounding_mode) = val;
#if defined(_BSD) && !defined(__APPLE__)
#if defined(_BSD) && !defined(__APPLE__) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
fpsetround(val);
#elif defined(__arm__)
/* nothing to do */
@@ -22,9 +22,14 @@ void set_floatx80_rounding_precision(int val STATUS_PARAM)
}
#endif
#if defined(_BSD)
#define lrint(d) ((long)rint(d))
#define llrint(d) ((long long)rint(d))
#if defined(_BSD) || (defined(HOST_SOLARIS) && HOST_SOLARIS < 10)
#define lrint(d) ((int32_t)rint(d))
#define llrint(d) ((int64_t)rint(d))
#define lrintf(f) ((int32_t)rint(f))
#define llrintf(f) ((int64_t)rint(f))
#define sqrtf(f) ((float)sqrt(f))
#define remainderf(fa, fb) ((float)remainder(fa, fb))
#define rintf(f) ((float)rint(f))
#endif
#if defined(__powerpc__)
+81 -44
View File
@@ -17,6 +17,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef CONFIG_USER_ONLY
#include <stdlib.h>
#include <stdio.h>
@@ -24,16 +25,25 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "qemu.h"
#else
#include "vl.h"
#endif
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include "qemu_socket.h"
#ifdef _WIN32
/* XXX: these constants may be independent of the host ones even for Unix */
#ifndef SIGTRAP
#define SIGTRAP 5
#endif
#ifndef SIGINT
#define SIGINT 2
#endif
#else
#include <signal.h>
#endif
//#define DEBUG_GDB
@@ -69,7 +79,7 @@ static int get_char(GDBState *s)
int ret;
for(;;) {
ret = read(s->fd, &ch, 1);
ret = recv(s->fd, &ch, 1, 0);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return -1;
@@ -87,7 +97,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
int ret;
while (len > 0) {
ret = write(s->fd, buf, len);
ret = send(s->fd, buf, len, 0);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return;
@@ -305,11 +315,11 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
for(i = 0; i < 24; i++) {
registers[i + 8] = tswapl(env->regwptr[i]);
}
#ifndef TARGET_SPARC64
/* fill in fprs */
for (i = 0; i < 32; i++) {
registers[i + 32] = tswapl(*((uint32_t *)&env->fpr[i]));
}
#ifndef TARGET_SPARC64
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
registers[64] = tswapl(env->y);
{
@@ -327,16 +337,21 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
registers[72] = 0;
return 73 * sizeof(target_ulong);
#else
for (i = 0; i < 32; i += 2) {
registers[i/2 + 64] = tswapl(*((uint64_t *)&env->fpr[i]));
/* fill in fprs */
for (i = 0; i < 64; i += 2) {
uint64_t tmp;
tmp = (uint64_t)tswap32(*((uint32_t *)&env->fpr[i])) << 32;
tmp |= tswap32(*((uint32_t *)&env->fpr[i + 1]));
registers[i/2 + 32] = tmp;
}
registers[81] = tswapl(env->pc);
registers[82] = tswapl(env->npc);
registers[83] = tswapl(env->tstate[env->tl]);
registers[84] = tswapl(env->fsr);
registers[85] = tswapl(env->fprs);
registers[86] = tswapl(env->y);
return 87 * sizeof(target_ulong);
registers[64] = tswapl(env->pc);
registers[65] = tswapl(env->npc);
registers[66] = tswapl(env->tstate[env->tl]);
registers[67] = tswapl(env->fsr);
registers[68] = tswapl(env->fprs);
registers[69] = tswapl(env->y);
return 70 * sizeof(target_ulong);
#endif
}
@@ -353,11 +368,11 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
for(i = 0; i < 24; i++) {
env->regwptr[i] = tswapl(registers[i + 8]);
}
#ifndef TARGET_SPARC64
/* fill in fprs */
for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = tswapl(registers[i + 32]);
}
#ifndef TARGET_SPARC64
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
env->y = tswapl(registers[64]);
PUT_PSR(env, tswapl(registers[65]));
@@ -367,18 +382,16 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
env->npc = tswapl(registers[69]);
env->fsr = tswapl(registers[70]);
#else
for (i = 0; i < 32; i += 2) {
uint64_t tmp;
tmp = tswapl(registers[i/2 + 64]) << 32;
tmp |= tswapl(registers[i/2 + 64 + 1]);
*((uint64_t *)&env->fpr[i]) = tmp;
for (i = 0; i < 64; i += 2) {
*((uint32_t *)&env->fpr[i]) = tswap32(registers[i/2 + 32] >> 32);
*((uint32_t *)&env->fpr[i + 1]) = tswap32(registers[i/2 + 32] & 0xffffffff);
}
env->pc = tswapl(registers[81]);
env->npc = tswapl(registers[82]);
env->tstate[env->tl] = tswapl(registers[83]);
env->fsr = tswapl(registers[84]);
env->fprs = tswapl(registers[85]);
env->y = tswapl(registers[86]);
env->pc = tswapl(registers[64]);
env->npc = tswapl(registers[65]);
env->tstate[env->tl] = tswapl(registers[66]);
env->fsr = tswapl(registers[67]);
env->fprs = tswapl(registers[68]);
env->y = tswapl(registers[69]);
#endif
}
#elif defined (TARGET_ARM)
@@ -494,7 +507,12 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
int i;
#define SAVE(x) *ptr++=tswapl(x)
for (i = 0; i < 16; i++) SAVE(env->gregs[i]);
if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
for (i = 0; i < 8; i++) SAVE(env->gregs[i + 16]);
} else {
for (i = 0; i < 8; i++) SAVE(env->gregs[i]);
}
for (i = 8; i < 16; i++) SAVE(env->gregs[i]);
SAVE (env->pc);
SAVE (env->pr);
SAVE (env->gbr);
@@ -517,7 +535,12 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
int i;
#define LOAD(x) (x)=*ptr++;
for (i = 0; i < 16; i++) LOAD(env->gregs[i]);
if ((env->sr & (SR_MD | SR_RB)) == (SR_MD | SR_RB)) {
for (i = 0; i < 8; i++) LOAD(env->gregs[i + 16]);
} else {
for (i = 0; i < 8; i++) LOAD(env->gregs[i]);
}
for (i = 8; i < 16; i++) LOAD(env->gregs[i]);
LOAD (env->pc);
LOAD (env->pr);
LOAD (env->gbr);
@@ -545,7 +568,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
char buf[4096];
uint8_t mem_buf[2000];
uint32_t *registers;
uint32_t addr, len;
target_ulong addr, len;
#ifdef DEBUG_GDB
printf("command='%s'\n", line_buf);
@@ -560,7 +583,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
break;
case 'c':
if (*p != '\0') {
addr = strtoul(p, (char **)&p, 16);
addr = strtoull(p, (char **)&p, 16);
#if defined(TARGET_I386)
env->eip = addr;
#elif defined (TARGET_PPC)
@@ -616,10 +639,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
put_packet(s, "OK");
break;
case 'm':
addr = strtoul(p, (char **)&p, 16);
addr = strtoull(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, NULL, 16);
len = strtoull(p, NULL, 16);
if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0) {
put_packet (s, "E14");
} else {
@@ -628,10 +651,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
}
break;
case 'M':
addr = strtoul(p, (char **)&p, 16);
addr = strtoull(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
len = strtoull(p, (char **)&p, 16);
if (*p == ':')
p++;
hextomem(mem_buf, p, len);
@@ -644,10 +667,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
addr = strtoull(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
len = strtoull(p, (char **)&p, 16);
if (type == 0 || type == 1) {
if (cpu_breakpoint_insert(env, addr) < 0)
goto breakpoint_error;
@@ -661,10 +684,10 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
addr = strtoull(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
len = strtoull(p, (char **)&p, 16);
if (type == 0 || type == 1) {
cpu_breakpoint_remove(env, addr);
put_packet(s, "OK");
@@ -672,6 +695,18 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
goto breakpoint_error;
}
break;
#ifdef CONFIG_USER_ONLY
case 'q':
if (strncmp(p, "Offsets", 7) == 0) {
TaskState *ts = env->opaque;
sprintf(buf, "Text=%x;Data=%x;Bss=%x", ts->info->code_offset,
ts->info->data_offset, ts->info->data_offset);
put_packet(s, buf);
break;
}
/* Fall through. */
#endif
default:
// unknown_command:
/* put empty packet */
@@ -829,7 +864,7 @@ static void gdb_read(void *opaque)
int i, size;
uint8_t buf[4096];
size = read(s->fd, buf, sizeof(buf));
size = recv(s->fd, buf, sizeof(buf), 0);
if (size < 0)
return;
if (size == 0) {
@@ -866,7 +901,7 @@ static void gdb_accept(void *opaque)
/* set short latency */
val = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
#ifdef CONFIG_USER_ONLY
s = &gdbserver_state;
@@ -881,9 +916,11 @@ static void gdb_accept(void *opaque)
s->env = first_cpu; /* XXX: allow to change CPU */
s->fd = fd;
#ifdef CONFIG_USER_ONLY
fcntl(fd, F_SETFL, O_NONBLOCK);
#else
socket_set_nonblock(fd);
#ifndef CONFIG_USER_ONLY
/* stop the VM */
vm_stop(EXCP_INTERRUPT);
@@ -907,7 +944,7 @@ static int gdbserver_open(int port)
/* allow fast reuse */
val = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
@@ -923,7 +960,7 @@ static int gdbserver_open(int port)
return -1;
}
#ifndef CONFIG_USER_ONLY
fcntl(fd, F_SETFL, O_NONBLOCK);
socket_set_nonblock(fd);
#endif
return fd;
}
+559
View File
@@ -0,0 +1,559 @@
/*
* QEMU ACPI DSDT ASL definition
*
* Copyright (c) 2006 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
DefinitionBlock (
"acpi-dsdt.aml", // Output Filename
"DSDT", // Signature
0x01, // DSDT Compliance Revision
"QEMU", // OEMID
"QEMUDSDT", // TABLE ID
0x1 // OEM Revision
)
{
Scope (\)
{
/* CMOS memory access */
OperationRegion (CMS, SystemIO, 0x70, 0x02)
Field (CMS, ByteAcc, NoLock, Preserve)
{
CMSI, 8,
CMSD, 8
}
Method (CMRD, 1, NotSerialized)
{
Store (Arg0, CMSI)
Store (CMSD, Local0)
Return (Local0)
}
/* Debug Output */
OperationRegion (DBG, SystemIO, 0xb044, 0x04)
Field (DBG, DWordAcc, NoLock, Preserve)
{
DBGL, 32,
}
}
/* PCI Bus definition */
Scope(\_SB) {
Device(PCI0) {
Name (_HID, EisaId ("PNP0A03"))
Name (_ADR, 0x00)
Name (_UID, 1)
Name(_PRT, Package() {
/* PCI IRQ routing table, example from ACPI 2.0a specification,
section 6.2.8.1 */
/* Note: we provide the same info as the PCI routing
table of the Bochs BIOS */
// PCI Slot 0
Package() {0x0000ffff, 0, LNKD, 0},
Package() {0x0000ffff, 1, LNKA, 0},
Package() {0x0000ffff, 2, LNKB, 0},
Package() {0x0000ffff, 3, LNKC, 0},
// PCI Slot 1
Package() {0x0001ffff, 0, LNKA, 0},
Package() {0x0001ffff, 1, LNKB, 0},
Package() {0x0001ffff, 2, LNKC, 0},
Package() {0x0001ffff, 3, LNKD, 0},
// PCI Slot 2
Package() {0x0002ffff, 0, LNKB, 0},
Package() {0x0002ffff, 1, LNKC, 0},
Package() {0x0002ffff, 2, LNKD, 0},
Package() {0x0002ffff, 3, LNKA, 0},
// PCI Slot 3
Package() {0x0003ffff, 0, LNKC, 0},
Package() {0x0003ffff, 1, LNKD, 0},
Package() {0x0003ffff, 2, LNKA, 0},
Package() {0x0003ffff, 3, LNKB, 0},
// PCI Slot 4
Package() {0x0004ffff, 0, LNKD, 0},
Package() {0x0004ffff, 1, LNKA, 0},
Package() {0x0004ffff, 2, LNKB, 0},
Package() {0x0004ffff, 3, LNKC, 0},
// PCI Slot 5
Package() {0x0005ffff, 0, LNKA, 0},
Package() {0x0005ffff, 1, LNKB, 0},
Package() {0x0005ffff, 2, LNKC, 0},
Package() {0x0005ffff, 3, LNKD, 0},
})
Method (_CRS, 0, NotSerialized)
{
Name (MEMP, ResourceTemplate ()
{
WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x00FF, // Address Range Maximum
0x0000, // Address Translation Offset
0x0100, // Address Length
,, )
IO (Decode16,
0x0CF8, // Address Range Minimum
0x0CF8, // Address Range Maximum
0x01, // Address Alignment
0x08, // Address Length
)
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0000, // Address Range Minimum
0x0CF7, // Address Range Maximum
0x0000, // Address Translation Offset
0x0CF8, // Address Length
,, , TypeStatic)
WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
0x0000, // Address Space Granularity
0x0D00, // Address Range Minimum
0xFFFF, // Address Range Maximum
0x0000, // Address Translation Offset
0xF300, // Address Length
,, , TypeStatic)
DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x000A0000, // Address Range Minimum
0x000BFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00020000, // Address Length
,, , AddressRangeMemory, TypeStatic)
DWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, NonCacheable, ReadWrite,
0x00000000, // Address Space Granularity
0x00000000, // Address Range Minimum
0xFEBFFFFF, // Address Range Maximum
0x00000000, // Address Translation Offset
0x00000000, // Address Length
,, MEMF, AddressRangeMemory, TypeStatic)
})
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MIN, PMIN)
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._MAX, PMAX)
CreateDWordField (MEMP, \_SB.PCI0._CRS.MEMF._LEN, PLEN)
/* compute available RAM */
Add(CMRD(0x34), ShiftLeft(CMRD(0x35), 8), Local0)
ShiftLeft(Local0, 16, Local0)
Add(Local0, 0x1000000, Local0)
/* update field of last region */
Store(Local0, PMIN)
Subtract (PMAX, PMIN, PLEN)
Increment (PLEN)
Return (MEMP)
}
}
}
Scope(\_SB.PCI0) {
/* PIIX3 ISA bridge */
Device (ISA) {
Name (_ADR, 0x00010000)
/* PIIX PCI to ISA irq remapping */
OperationRegion (P40C, PCI_Config, 0x60, 0x04)
/* Keyboard seems to be important for WinXP install */
Device (KBD)
{
Name (_HID, EisaId ("PNP0303"))
Method (_STA, 0, NotSerialized)
{
Return (0x0f)
}
Method (_CRS, 0, NotSerialized)
{
Name (TMP, ResourceTemplate ()
{
IO (Decode16,
0x0060, // Address Range Minimum
0x0060, // Address Range Maximum
0x01, // Address Alignment
0x01, // Address Length
)
IO (Decode16,
0x0064, // Address Range Minimum
0x0064, // Address Range Maximum
0x01, // Address Alignment
0x01, // Address Length
)
IRQNoFlags ()
{1}
})
Return (TMP)
}
}
/* PS/2 mouse */
Device (MOU)
{
Name (_HID, EisaId ("PNP0F13"))
Method (_STA, 0, NotSerialized)
{
Return (0x0f)
}
Method (_CRS, 0, NotSerialized)
{
Name (TMP, ResourceTemplate ()
{
IRQNoFlags () {12}
})
Return (TMP)
}
}
/* PS/2 floppy controller */
Device (FDC0)
{
Name (_HID, EisaId ("PNP0700"))
Method (_STA, 0, NotSerialized)
{
Return (0x0F)
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
IRQNoFlags () {6}
DMA (Compatibility, NotBusMaster, Transfer8) {2}
})
Return (BUF0)
}
}
/* Parallel port */
Device (LPT)
{
Name (_HID, EisaId ("PNP0400"))
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSA, Local0)
And (Local0, 0x80000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
IRQNoFlags () {7}
})
Return (BUF0)
}
}
/* Serial Ports */
Device (COM1)
{
Name (_HID, EisaId ("PNP0501"))
Name (_UID, 0x01)
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSC, Local0)
And (Local0, 0x08000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
IRQNoFlags () {4}
})
Return (BUF0)
}
}
Device (COM2)
{
Name (_HID, EisaId ("PNP0501"))
Name (_UID, 0x02)
Method (_STA, 0, NotSerialized)
{
Store (\_SB.PCI0.PX13.DRSC, Local0)
And (Local0, 0x80000000, Local0)
If (LEqual (Local0, 0))
{
Return (0x00)
}
Else
{
Return (0x0F)
}
}
Method (_CRS, 0, NotSerialized)
{
Name (BUF0, ResourceTemplate ()
{
IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
IRQNoFlags () {3}
})
Return (BUF0)
}
}
}
/* PIIX4 PM */
Device (PX13) {
Name (_ADR, 0x00010003)
OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
Field (P13C, DWordAcc, NoLock, Preserve)
{
DRSA, 32,
DRSB, 32,
DRSC, 32,
DRSE, 32,
DRSF, 32,
DRSG, 32,
DRSH, 32,
DRSI, 32,
DRSJ, 32
}
}
}
/* PCI IRQs */
Scope(\_SB) {
Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
{
PRQ0, 8,
PRQ1, 8,
PRQ2, 8,
PRQ3, 8
}
Device(LNKA){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 1)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ0, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ0, 0x80, PRQ0)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ0, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ0)
}
}
Device(LNKB){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 2)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ1, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ1, 0x80, PRQ1)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ1, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ1)
}
}
Device(LNKC){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 3)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ2, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ2, 0x80, PRQ2)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ2, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ2)
}
}
Device(LNKD){
Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link
Name(_UID, 4)
Name(_PRS, ResourceTemplate(){
IRQ (Level, ActiveLow, Shared)
{3,4,5,6,7,9,10,11,12}
})
Method (_STA, 0, NotSerialized)
{
Store (0x0B, Local0)
If (And (0x80, PRQ3, Local1))
{
Store (0x09, Local0)
}
Return (Local0)
}
Method (_DIS, 0, NotSerialized)
{
Or (PRQ3, 0x80, PRQ3)
}
Method (_CRS, 0, NotSerialized)
{
Name (PRR0, ResourceTemplate ()
{
IRQ (Level, ActiveLow, Shared)
{1}
})
CreateWordField (PRR0, 0x01, TMP)
Store (PRQ3, Local0)
If (LLess (Local0, 0x80))
{
ShiftLeft (One, Local0, TMP)
}
Else
{
Store (Zero, TMP)
}
Return (PRR0)
}
Method (_SRS, 1, NotSerialized)
{
CreateWordField (Arg0, 0x01, TMP)
FindSetRightBit (TMP, Local0)
Decrement (Local0)
Store (Local0, PRQ3)
}
}
}
/* S5 = power off state */
Name (_S5, Package (4) {
0x00, // PM1a_CNT.SLP_TYP
0x00, // PM2a_CNT.SLP_TYP
0x00, // reserved
0x00, // reserved
})
}
+278
View File
@@ -0,0 +1,278 @@
/*
*
* Intel ACPI Component Architecture
* ASL Optimizing Compiler version 20060421 [Apr 29 2006]
* Copyright (C) 2000 - 2006 Intel Corporation
* Supports ACPI Specification Revision 3.0a
*
* Compilation of "/usr/local/home/bellard/qemu-current/hw/acpi-dsdt.dsl" - Wed Jun 14 20:09:53 2006
*
* C source code output
*
*/
unsigned char AmlCode[] =
{
0x44,0x53,0x44,0x54,0x32,0x08,0x00,0x00, /* 00000000 "DSDT2..." */
0x01,0x5B,0x51,0x45,0x4D,0x55,0x00,0x00, /* 00000008 ".[QEMU.." */
0x51,0x45,0x4D,0x55,0x44,0x53,0x44,0x54, /* 00000010 "QEMUDSDT" */
0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
0x21,0x04,0x06,0x20,0x10,0x4F,0x04,0x5C, /* 00000020 "!.. .O.\" */
0x00,0x5B,0x80,0x43,0x4D,0x53,0x5F,0x01, /* 00000028 ".[.CMS_." */
0x0A,0x70,0x0A,0x02,0x5B,0x81,0x10,0x43, /* 00000030 ".p..[..C" */
0x4D,0x53,0x5F,0x01,0x43,0x4D,0x53,0x49, /* 00000038 "MS_.CMSI" */
0x08,0x43,0x4D,0x53,0x44,0x08,0x14,0x14, /* 00000040 ".CMSD..." */
0x43,0x4D,0x52,0x44,0x01,0x70,0x68,0x43, /* 00000048 "CMRD.phC" */
0x4D,0x53,0x49,0x70,0x43,0x4D,0x53,0x44, /* 00000050 "MSIpCMSD" */
0x60,0xA4,0x60,0x5B,0x80,0x44,0x42,0x47, /* 00000058 "`.`[.DBG" */
0x5F,0x01,0x0B,0x44,0xB0,0x0A,0x04,0x5B, /* 00000060 "_..D...[" */
0x81,0x0B,0x44,0x42,0x47,0x5F,0x03,0x44, /* 00000068 "..DBG_.D" */
0x42,0x47,0x4C,0x20,0x10,0x4E,0x25,0x5F, /* 00000070 "BGL .N%_" */
0x53,0x42,0x5F,0x5B,0x82,0x46,0x25,0x50, /* 00000078 "SB_[.F%P" */
0x43,0x49,0x30,0x08,0x5F,0x48,0x49,0x44, /* 00000080 "CI0._HID" */
0x0C,0x41,0xD0,0x0A,0x03,0x08,0x5F,0x41, /* 00000088 ".A...._A" */
0x44,0x52,0x00,0x08,0x5F,0x55,0x49,0x44, /* 00000090 "DR.._UID" */
0x01,0x08,0x5F,0x50,0x52,0x54,0x12,0x47, /* 00000098 ".._PRT.G" */
0x15,0x18,0x12,0x0B,0x04,0x0B,0xFF,0xFF, /* 000000A0 "........" */
0x00,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0B, /* 000000A8 ".LNKD..." */
0x04,0x0B,0xFF,0xFF,0x01,0x4C,0x4E,0x4B, /* 000000B0 ".....LNK" */
0x41,0x00,0x12,0x0C,0x04,0x0B,0xFF,0xFF, /* 000000B8 "A......." */
0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000000C0 "..LNKB.." */
0x0C,0x04,0x0B,0xFF,0xFF,0x0A,0x03,0x4C, /* 000000C8 ".......L" */
0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000000D0 "NKC....." */
0xFF,0xFF,0x01,0x00,0x00,0x4C,0x4E,0x4B, /* 000000D8 ".....LNK" */
0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000000E0 "A......." */
0x01,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000000E8 "...LNKB." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000000F0 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000000F8 "..LNKC.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A, /* 00000100 "........" */
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0D, /* 00000108 ".LNKD..." */
0x04,0x0C,0xFF,0xFF,0x02,0x00,0x00,0x4C, /* 00000110 ".......L" */
0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04,0x0C, /* 00000118 "NKB....." */
0xFF,0xFF,0x02,0x00,0x01,0x4C,0x4E,0x4B, /* 00000120 ".....LNK" */
0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000128 "C......." */
0x02,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x44, /* 00000130 "....LNKD" */
0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02, /* 00000138 "........" */
0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x41,0x00, /* 00000140 "...LNKA." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000148 "........" */
0x00,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0D, /* 00000150 ".LNKC..." */
0x04,0x0C,0xFF,0xFF,0x03,0x00,0x01,0x4C, /* 00000158 ".......L" */
0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000160 "NKD....." */
0xFF,0xFF,0x03,0x00,0x0A,0x02,0x4C,0x4E, /* 00000168 "......LN" */
0x4B,0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000170 "KA......" */
0xFF,0x03,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000178 ".....LNK" */
0x42,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000180 "B......." */
0x04,0x00,0x00,0x4C,0x4E,0x4B,0x44,0x00, /* 00000188 "...LNKD." */
0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000190 "........" */
0x01,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000198 ".LNKA..." */
0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000001A0 "........" */
0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04, /* 000001A8 "LNKB...." */
0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x03,0x4C, /* 000001B0 ".......L" */
0x4E,0x4B,0x43,0x00,0x12,0x0D,0x04,0x0C, /* 000001B8 "NKC....." */
0xFF,0xFF,0x05,0x00,0x00,0x4C,0x4E,0x4B, /* 000001C0 ".....LNK" */
0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000001C8 "A......." */
0x05,0x00,0x01,0x4C,0x4E,0x4B,0x42,0x00, /* 000001D0 "...LNKB." */
0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 000001D8 "........" */
0x0A,0x02,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 000001E0 "..LNKC.." */
0x0E,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A, /* 000001E8 "........" */
0x03,0x4C,0x4E,0x4B,0x44,0x00,0x14,0x4C, /* 000001F0 ".LNKD..L" */
0x0D,0x5F,0x43,0x52,0x53,0x00,0x08,0x4D, /* 000001F8 "._CRS..M" */
0x45,0x4D,0x50,0x11,0x42,0x07,0x0A,0x6E, /* 00000200 "EMP.B..n" */
0x88,0x0D,0x00,0x02,0x0C,0x00,0x00,0x00, /* 00000208 "........" */
0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x01, /* 00000210 "........" */
0x47,0x01,0xF8,0x0C,0xF8,0x0C,0x01,0x08, /* 00000218 "G......." */
0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000220 "........" */
0x00,0x00,0xF7,0x0C,0x00,0x00,0xF8,0x0C, /* 00000228 "........" */
0x88,0x0D,0x00,0x01,0x0C,0x03,0x00,0x00, /* 00000230 "........" */
0x00,0x0D,0xFF,0xFF,0x00,0x00,0x00,0xF3, /* 00000238 "........" */
0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00, /* 00000240 "........" */
0x00,0x00,0x00,0x00,0x0A,0x00,0xFF,0xFF, /* 00000248 "........" */
0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000250 "........" */
0x02,0x00,0x87,0x17,0x00,0x00,0x08,0x01, /* 00000258 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000260 "........" */
0xFF,0xFF,0xBF,0xFE,0x00,0x00,0x00,0x00, /* 00000268 "........" */
0x00,0x00,0x00,0x00,0x79,0x00,0x8A,0x4D, /* 00000270 "....y..M" */
0x45,0x4D,0x50,0x0A,0x5C,0x50,0x4D,0x49, /* 00000278 "EMP.\PMI" */
0x4E,0x8A,0x4D,0x45,0x4D,0x50,0x0A,0x60, /* 00000280 "N.MEMP.`" */
0x50,0x4D,0x41,0x58,0x8A,0x4D,0x45,0x4D, /* 00000288 "PMAX.MEM" */
0x50,0x0A,0x68,0x50,0x4C,0x45,0x4E,0x72, /* 00000290 "P.hPLENr" */
0x43,0x4D,0x52,0x44,0x0A,0x34,0x79,0x43, /* 00000298 "CMRD.4yC" */
0x4D,0x52,0x44,0x0A,0x35,0x0A,0x08,0x00, /* 000002A0 "MRD.5..." */
0x60,0x79,0x60,0x0A,0x10,0x60,0x72,0x60, /* 000002A8 "`y`..`r`" */
0x0C,0x00,0x00,0x00,0x01,0x60,0x70,0x60, /* 000002B0 ".....`p`" */
0x50,0x4D,0x49,0x4E,0x74,0x50,0x4D,0x41, /* 000002B8 "PMINtPMA" */
0x58,0x50,0x4D,0x49,0x4E,0x50,0x4C,0x45, /* 000002C0 "XPMINPLE" */
0x4E,0x75,0x50,0x4C,0x45,0x4E,0xA4,0x4D, /* 000002C8 "NuPLEN.M" */
0x45,0x4D,0x50,0x10,0x42,0x26,0x2E,0x5F, /* 000002D0 "EMP.B&._" */
0x53,0x42,0x5F,0x50,0x43,0x49,0x30,0x5B, /* 000002D8 "SB_PCI0[" */
0x82,0x43,0x20,0x49,0x53,0x41,0x5F,0x08, /* 000002E0 ".C ISA_." */
0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01, /* 000002E8 "_ADR...." */
0x00,0x5B,0x80,0x50,0x34,0x30,0x43,0x02, /* 000002F0 ".[.P40C." */
0x0A,0x60,0x0A,0x04,0x5B,0x82,0x44,0x04, /* 000002F8 ".`..[.D." */
0x4B,0x42,0x44,0x5F,0x08,0x5F,0x48,0x49, /* 00000300 "KBD_._HI" */
0x44,0x0C,0x41,0xD0,0x03,0x03,0x14,0x09, /* 00000308 "D.A....." */
0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000310 "_STA...." */
0x14,0x29,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000318 ".)_CRS.." */
0x54,0x4D,0x50,0x5F,0x11,0x18,0x0A,0x15, /* 00000320 "TMP_...." */
0x47,0x01,0x60,0x00,0x60,0x00,0x01,0x01, /* 00000328 "G.`.`..." */
0x47,0x01,0x64,0x00,0x64,0x00,0x01,0x01, /* 00000330 "G.d.d..." */
0x22,0x02,0x00,0x79,0x00,0xA4,0x54,0x4D, /* 00000338 ""..y..TM" */
0x50,0x5F,0x5B,0x82,0x33,0x4D,0x4F,0x55, /* 00000340 "P_[.3MOU" */
0x5F,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000348 "_._HID.A" */
0xD0,0x0F,0x13,0x14,0x09,0x5F,0x53,0x54, /* 00000350 "....._ST" */
0x41,0x00,0xA4,0x0A,0x0F,0x14,0x19,0x5F, /* 00000358 "A......_" */
0x43,0x52,0x53,0x00,0x08,0x54,0x4D,0x50, /* 00000360 "CRS..TMP" */
0x5F,0x11,0x08,0x0A,0x05,0x22,0x00,0x10, /* 00000368 "_....".." */
0x79,0x00,0xA4,0x54,0x4D,0x50,0x5F,0x5B, /* 00000370 "y..TMP_[" */
0x82,0x47,0x04,0x46,0x44,0x43,0x30,0x08, /* 00000378 ".G.FDC0." */
0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x07, /* 00000380 "_HID.A.." */
0x00,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000388 "..._STA." */
0xA4,0x0A,0x0F,0x14,0x2C,0x5F,0x43,0x52, /* 00000390 "....,_CR" */
0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000398 "S..BUF0." */
0x1B,0x0A,0x18,0x47,0x01,0xF2,0x03,0xF2, /* 000003A0 "...G...." */
0x03,0x00,0x04,0x47,0x01,0xF7,0x03,0xF7, /* 000003A8 "...G...." */
0x03,0x00,0x01,0x22,0x40,0x00,0x2A,0x04, /* 000003B0 "..."@.*." */
0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 000003B8 ".y..BUF0" */
0x5B,0x82,0x4B,0x05,0x4C,0x50,0x54,0x5F, /* 000003C0 "[.K.LPT_" */
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000003C8 "._HID.A." */
0x04,0x00,0x14,0x28,0x5F,0x53,0x54,0x41, /* 000003D0 "...(_STA" */
0x00,0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58, /* 000003D8 ".p^^^.PX" */
0x31,0x33,0x44,0x52,0x53,0x41,0x60,0x7B, /* 000003E0 "13DRSA`{" */
0x60,0x0C,0x00,0x00,0x00,0x80,0x60,0xA0, /* 000003E8 "`.....`." */
0x06,0x93,0x60,0x00,0xA4,0x00,0xA1,0x04, /* 000003F0 "..`....." */
0xA4,0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52, /* 000003F8 "....!_CR" */
0x53,0x00,0x08,0x42,0x55,0x46,0x30,0x11, /* 00000400 "S..BUF0." */
0x10,0x0A,0x0D,0x47,0x01,0x78,0x03,0x78, /* 00000408 "...G.x.x" */
0x03,0x08,0x08,0x22,0x80,0x00,0x79,0x00, /* 00000410 "..."..y." */
0xA4,0x42,0x55,0x46,0x30,0x5B,0x82,0x41, /* 00000418 ".BUF0[.A" */
0x06,0x43,0x4F,0x4D,0x31,0x08,0x5F,0x48, /* 00000420 ".COM1._H" */
0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000428 "ID.A...." */
0x5F,0x55,0x49,0x44,0x01,0x14,0x28,0x5F, /* 00000430 "_UID..(_" */
0x53,0x54,0x41,0x00,0x70,0x5E,0x5E,0x5E, /* 00000438 "STA.p^^^" */
0x2E,0x50,0x58,0x31,0x33,0x44,0x52,0x53, /* 00000440 ".PX13DRS" */
0x43,0x60,0x7B,0x60,0x0C,0x00,0x00,0x00, /* 00000448 "C`{`...." */
0x08,0x60,0xA0,0x06,0x93,0x60,0x00,0xA4, /* 00000450 ".`...`.." */
0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x14,0x21, /* 00000458 ".......!" */
0x5F,0x43,0x52,0x53,0x00,0x08,0x42,0x55, /* 00000460 "_CRS..BU" */
0x46,0x30,0x11,0x10,0x0A,0x0D,0x47,0x01, /* 00000468 "F0....G." */
0xF8,0x03,0xF8,0x03,0x00,0x08,0x22,0x10, /* 00000470 "......"." */
0x00,0x79,0x00,0xA4,0x42,0x55,0x46,0x30, /* 00000478 ".y..BUF0" */
0x5B,0x82,0x42,0x06,0x43,0x4F,0x4D,0x32, /* 00000480 "[.B.COM2" */
0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000488 "._HID.A." */
0x05,0x01,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000490 "..._UID." */
0x02,0x14,0x28,0x5F,0x53,0x54,0x41,0x00, /* 00000498 "..(_STA." */
0x70,0x5E,0x5E,0x5E,0x2E,0x50,0x58,0x31, /* 000004A0 "p^^^.PX1" */
0x33,0x44,0x52,0x53,0x43,0x60,0x7B,0x60, /* 000004A8 "3DRSC`{`" */
0x0C,0x00,0x00,0x00,0x80,0x60,0xA0,0x06, /* 000004B0 ".....`.." */
0x93,0x60,0x00,0xA4,0x00,0xA1,0x04,0xA4, /* 000004B8 ".`......" */
0x0A,0x0F,0x14,0x21,0x5F,0x43,0x52,0x53, /* 000004C0 "...!_CRS" */
0x00,0x08,0x42,0x55,0x46,0x30,0x11,0x10, /* 000004C8 "..BUF0.." */
0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02, /* 000004D0 "..G....." */
0x00,0x08,0x22,0x08,0x00,0x79,0x00,0xA4, /* 000004D8 ".."..y.." */
0x42,0x55,0x46,0x30,0x5B,0x82,0x40,0x05, /* 000004E0 "BUF0[.@." */
0x50,0x58,0x31,0x33,0x08,0x5F,0x41,0x44, /* 000004E8 "PX13._AD" */
0x52,0x0C,0x03,0x00,0x01,0x00,0x5B,0x80, /* 000004F0 "R.....[." */
0x50,0x31,0x33,0x43,0x02,0x0A,0x5C,0x0A, /* 000004F8 "P13C..\." */
0x24,0x5B,0x81,0x33,0x50,0x31,0x33,0x43, /* 00000500 "$[.3P13C" */
0x03,0x44,0x52,0x53,0x41,0x20,0x44,0x52, /* 00000508 ".DRSA DR" */
0x53,0x42,0x20,0x44,0x52,0x53,0x43,0x20, /* 00000510 "SB DRSC " */
0x44,0x52,0x53,0x45,0x20,0x44,0x52,0x53, /* 00000518 "DRSE DRS" */
0x46,0x20,0x44,0x52,0x53,0x47,0x20,0x44, /* 00000520 "F DRSG D" */
0x52,0x53,0x48,0x20,0x44,0x52,0x53,0x49, /* 00000528 "RSH DRSI" */
0x20,0x44,0x52,0x53,0x4A,0x20,0x10,0x4F, /* 00000530 " DRSJ .O" */
0x2E,0x5F,0x53,0x42,0x5F,0x5B,0x81,0x24, /* 00000538 "._SB_[.$" */
0x2F,0x03,0x50,0x43,0x49,0x30,0x49,0x53, /* 00000540 "/.PCI0IS" */
0x41,0x5F,0x50,0x34,0x30,0x43,0x01,0x50, /* 00000548 "A_P40C.P" */
0x52,0x51,0x30,0x08,0x50,0x52,0x51,0x31, /* 00000550 "RQ0.PRQ1" */
0x08,0x50,0x52,0x51,0x32,0x08,0x50,0x52, /* 00000558 ".PRQ2.PR" */
0x51,0x33,0x08,0x5B,0x82,0x4E,0x0A,0x4C, /* 00000560 "Q3.[.N.L" */
0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44, /* 00000568 "NKA._HID" */
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000570 ".A...._U" */
0x49,0x44,0x01,0x08,0x5F,0x50,0x52,0x53, /* 00000578 "ID.._PRS" */
0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E,0x18, /* 00000580 "....#..." */
0x79,0x00,0x14,0x1A,0x5F,0x53,0x54,0x41, /* 00000588 "y..._STA" */
0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D,0x7B, /* 00000590 ".p..`..{" */
0x0A,0x80,0x50,0x52,0x51,0x30,0x61,0x70, /* 00000598 "..PRQ0ap" */
0x0A,0x09,0x60,0xA4,0x60,0x14,0x11,0x5F, /* 000005A0 "..`.`.._" */
0x44,0x49,0x53,0x00,0x7D,0x50,0x52,0x51, /* 000005A8 "DIS.}PRQ" */
0x30,0x0A,0x80,0x50,0x52,0x51,0x30,0x14, /* 000005B0 "0..PRQ0." */
0x3F,0x5F,0x43,0x52,0x53,0x00,0x08,0x50, /* 000005B8 "?_CRS..P" */
0x52,0x52,0x30,0x11,0x09,0x0A,0x06,0x23, /* 000005C0 "RR0....#" */
0x02,0x00,0x18,0x79,0x00,0x8B,0x50,0x52, /* 000005C8 "...y..PR" */
0x52,0x30,0x01,0x54,0x4D,0x50,0x5F,0x70, /* 000005D0 "R0.TMP_p" */
0x50,0x52,0x51,0x30,0x60,0xA0,0x0C,0x95, /* 000005D8 "PRQ0`..." */
0x60,0x0A,0x80,0x79,0x01,0x60,0x54,0x4D, /* 000005E0 "`..y.`TM" */
0x50,0x5F,0xA1,0x07,0x70,0x00,0x54,0x4D, /* 000005E8 "P_..p.TM" */
0x50,0x5F,0xA4,0x50,0x52,0x52,0x30,0x14, /* 000005F0 "P_.PRR0." */
0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 000005F8 "._SRS..h" */
0x01,0x54,0x4D,0x50,0x5F,0x82,0x54,0x4D, /* 00000600 ".TMP_.TM" */
0x50,0x5F,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000608 "P_`v`p`P" */
0x52,0x51,0x30,0x5B,0x82,0x4F,0x0A,0x4C, /* 00000610 "RQ0[.O.L" */
0x4E,0x4B,0x42,0x08,0x5F,0x48,0x49,0x44, /* 00000618 "NKB._HID" */
0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000620 ".A...._U" */
0x49,0x44,0x0A,0x02,0x08,0x5F,0x50,0x52, /* 00000628 "ID..._PR" */
0x53,0x11,0x09,0x0A,0x06,0x23,0xF8,0x1E, /* 00000630 "S....#.." */
0x18,0x79,0x00,0x14,0x1A,0x5F,0x53,0x54, /* 00000638 ".y..._ST" */
0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0,0x0D, /* 00000640 "A.p..`.." */
0x7B,0x0A,0x80,0x50,0x52,0x51,0x31,0x61, /* 00000648 "{..PRQ1a" */
0x70,0x0A,0x09,0x60,0xA4,0x60,0x14,0x11, /* 00000650 "p..`.`.." */
0x5F,0x44,0x49,0x53,0x00,0x7D,0x50,0x52, /* 00000658 "_DIS.}PR" */
0x51,0x31,0x0A,0x80,0x50,0x52,0x51,0x31, /* 00000660 "Q1..PRQ1" */
0x14,0x3F,0x5F,0x43,0x52,0x53,0x00,0x08, /* 00000668 ".?_CRS.." */
0x50,0x52,0x52,0x30,0x11,0x09,0x0A,0x06, /* 00000670 "PRR0...." */
0x23,0x02,0x00,0x18,0x79,0x00,0x8B,0x50, /* 00000678 "#...y..P" */
0x52,0x52,0x30,0x01,0x54,0x4D,0x50,0x5F, /* 00000680 "RR0.TMP_" */
0x70,0x50,0x52,0x51,0x31,0x60,0xA0,0x0C, /* 00000688 "pPRQ1`.." */
0x95,0x60,0x0A,0x80,0x79,0x01,0x60,0x54, /* 00000690 ".`..y.`T" */
0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00,0x54, /* 00000698 "MP_..p.T" */
0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52,0x30, /* 000006A0 "MP_.PRR0" */
0x14,0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B, /* 000006A8 ".._SRS.." */
0x68,0x01,0x54,0x4D,0x50,0x5F,0x82,0x54, /* 000006B0 "h.TMP_.T" */
0x4D,0x50,0x5F,0x60,0x76,0x60,0x70,0x60, /* 000006B8 "MP_`v`p`" */
0x50,0x52,0x51,0x31,0x5B,0x82,0x4F,0x0A, /* 000006C0 "PRQ1[.O." */
0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48,0x49, /* 000006C8 "LNKC._HI" */
0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F, /* 000006D0 "D.A...._" */
0x55,0x49,0x44,0x0A,0x03,0x08,0x5F,0x50, /* 000006D8 "UID..._P" */
0x52,0x53,0x11,0x09,0x0A,0x06,0x23,0xF8, /* 000006E0 "RS....#." */
0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F,0x53, /* 000006E8 "..y..._S" */
0x54,0x41,0x00,0x70,0x0A,0x0B,0x60,0xA0, /* 000006F0 "TA.p..`." */
0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51,0x32, /* 000006F8 ".{..PRQ2" */
0x61,0x70,0x0A,0x09,0x60,0xA4,0x60,0x14, /* 00000700 "ap..`.`." */
0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000708 "._DIS.}P" */
0x52,0x51,0x32,0x0A,0x80,0x50,0x52,0x51, /* 00000710 "RQ2..PRQ" */
0x32,0x14,0x3F,0x5F,0x43,0x52,0x53,0x00, /* 00000718 "2.?_CRS." */
0x08,0x50,0x52,0x52,0x30,0x11,0x09,0x0A, /* 00000720 ".PRR0..." */
0x06,0x23,0x02,0x00,0x18,0x79,0x00,0x8B, /* 00000728 ".#...y.." */
0x50,0x52,0x52,0x30,0x01,0x54,0x4D,0x50, /* 00000730 "PRR0.TMP" */
0x5F,0x70,0x50,0x52,0x51,0x32,0x60,0xA0, /* 00000738 "_pPRQ2`." */
0x0C,0x95,0x60,0x0A,0x80,0x79,0x01,0x60, /* 00000740 "..`..y.`" */
0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70,0x00, /* 00000748 "TMP_..p." */
0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52,0x52, /* 00000750 "TMP_.PRR" */
0x30,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000758 "0.._SRS." */
0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F,0x82, /* 00000760 ".h.TMP_." */
0x54,0x4D,0x50,0x5F,0x60,0x76,0x60,0x70, /* 00000768 "TMP_`v`p" */
0x60,0x50,0x52,0x51,0x32,0x5B,0x82,0x4F, /* 00000770 "`PRQ2[.O" */
0x0A,0x4C,0x4E,0x4B,0x44,0x08,0x5F,0x48, /* 00000778 ".LNKD._H" */
0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000780 "ID.A...." */
0x5F,0x55,0x49,0x44,0x0A,0x04,0x08,0x5F, /* 00000788 "_UID..._" */
0x50,0x52,0x53,0x11,0x09,0x0A,0x06,0x23, /* 00000790 "PRS....#" */
0xF8,0x1E,0x18,0x79,0x00,0x14,0x1A,0x5F, /* 00000798 "...y..._" */
0x53,0x54,0x41,0x00,0x70,0x0A,0x0B,0x60, /* 000007A0 "STA.p..`" */
0xA0,0x0D,0x7B,0x0A,0x80,0x50,0x52,0x51, /* 000007A8 "..{..PRQ" */
0x33,0x61,0x70,0x0A,0x09,0x60,0xA4,0x60, /* 000007B0 "3ap..`.`" */
0x14,0x11,0x5F,0x44,0x49,0x53,0x00,0x7D, /* 000007B8 ".._DIS.}" */
0x50,0x52,0x51,0x33,0x0A,0x80,0x50,0x52, /* 000007C0 "PRQ3..PR" */
0x51,0x33,0x14,0x3F,0x5F,0x43,0x52,0x53, /* 000007C8 "Q3.?_CRS" */
0x00,0x08,0x50,0x52,0x52,0x30,0x11,0x09, /* 000007D0 "..PRR0.." */
0x0A,0x06,0x23,0x02,0x00,0x18,0x79,0x00, /* 000007D8 "..#...y." */
0x8B,0x50,0x52,0x52,0x30,0x01,0x54,0x4D, /* 000007E0 ".PRR0.TM" */
0x50,0x5F,0x70,0x50,0x52,0x51,0x33,0x60, /* 000007E8 "P_pPRQ3`" */
0xA0,0x0C,0x95,0x60,0x0A,0x80,0x79,0x01, /* 000007F0 "...`..y." */
0x60,0x54,0x4D,0x50,0x5F,0xA1,0x07,0x70, /* 000007F8 "`TMP_..p" */
0x00,0x54,0x4D,0x50,0x5F,0xA4,0x50,0x52, /* 00000800 ".TMP_.PR" */
0x52,0x30,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000808 "R0.._SRS" */
0x01,0x8B,0x68,0x01,0x54,0x4D,0x50,0x5F, /* 00000810 "..h.TMP_" */
0x82,0x54,0x4D,0x50,0x5F,0x60,0x76,0x60, /* 00000818 ".TMP_`v`" */
0x70,0x60,0x50,0x52,0x51,0x33,0x08,0x5F, /* 00000820 "p`PRQ3._" */
0x53,0x35,0x5F,0x12,0x06,0x04,0x00,0x00, /* 00000828 "S5_....." */
0x00,0x00,
};
+615
View File
@@ -0,0 +1,615 @@
/*
* ACPI implementation
*
* Copyright (c) 2006 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "vl.h"
//#define DEBUG
/* i82731AB (PIIX4) compatible power management function */
#define PM_FREQ 3579545
/* XXX: make them variable */
#define PM_IO_BASE 0xb000
#define SMI_CMD_IO_ADDR 0xb040
#define ACPI_DBG_IO_ADDR 0xb044
typedef struct PIIX4PMState {
PCIDevice dev;
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
QEMUTimer *tmr_timer;
int64_t tmr_overflow_time;
} PIIX4PMState;
#define RTC_EN (1 << 10)
#define PWRBTN_EN (1 << 8)
#define GBL_EN (1 << 5)
#define TMROF_EN (1 << 0)
#define SCI_EN (1 << 0)
#define SUS_EN (1 << 13)
/* Note: only used for ACPI bios init. Could be deleted when ACPI init
is integrated in Bochs BIOS */
static PIIX4PMState *piix4_pm_state;
static uint32_t get_pmtmr(PIIX4PMState *s)
{
uint32_t d;
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
return d & 0xffffff;
}
static int get_pmsts(PIIX4PMState *s)
{
int64_t d;
int pmsts;
pmsts = s->pmsts;
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
if (d >= s->tmr_overflow_time)
s->pmsts |= TMROF_EN;
return pmsts;
}
static void pm_update_sci(PIIX4PMState *s)
{
int sci_level, pmsts;
int64_t expire_time;
pmsts = get_pmsts(s);
sci_level = (((pmsts & s->pmen) &
(RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0);
pci_set_irq(&s->dev, 0, sci_level);
/* schedule a timer interruption if needed */
if ((s->pmen & TMROF_EN) && !(pmsts & TMROF_EN)) {
expire_time = muldiv64(s->tmr_overflow_time, ticks_per_sec, PM_FREQ);
qemu_mod_timer(s->tmr_timer, expire_time);
} else {
qemu_del_timer(s->tmr_timer);
}
}
static void pm_tmr_timer(void *opaque)
{
PIIX4PMState *s = opaque;
pm_update_sci(s);
}
static void pm_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
{
PIIX4PMState *s = opaque;
addr &= 0x3f;
switch(addr) {
case 0x00:
{
int64_t d;
int pmsts;
pmsts = get_pmsts(s);
if (pmsts & val & TMROF_EN) {
/* if TMRSTS is reset, then compute the new overflow time */
d = muldiv64(qemu_get_clock(vm_clock), PM_FREQ, ticks_per_sec);
s->tmr_overflow_time = (d + 0x800000LL) & ~0x7fffffLL;
}
s->pmsts &= ~val;
pm_update_sci(s);
}
break;
case 0x02:
s->pmen = val;
pm_update_sci(s);
break;
case 0x04:
{
int sus_typ;
s->pmcntrl = val & ~(SUS_EN);
if (val & SUS_EN) {
/* change suspend type */
sus_typ = (val >> 10) & 3;
switch(sus_typ) {
case 0: /* soft power off */
qemu_system_shutdown_request();
break;
default:
break;
}
}
}
break;
default:
break;
}
#ifdef DEBUG
printf("PM writew port=0x%04x val=0x%04x\n", addr, val);
#endif
}
static uint32_t pm_ioport_readw(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
uint32_t val;
addr &= 0x3f;
switch(addr) {
case 0x00:
val = get_pmsts(s);
break;
case 0x02:
val = s->pmen;
break;
case 0x04:
val = s->pmcntrl;
break;
default:
val = 0;
break;
}
#ifdef DEBUG
printf("PM readw port=0x%04x val=0x%04x\n", addr, val);
#endif
return val;
}
static void pm_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
// PIIX4PMState *s = opaque;
addr &= 0x3f;
#ifdef DEBUG
printf("PM writel port=0x%04x val=0x%08x\n", addr, val);
#endif
}
static uint32_t pm_ioport_readl(void *opaque, uint32_t addr)
{
PIIX4PMState *s = opaque;
uint32_t val;
addr &= 0x3f;
switch(addr) {
case 0x08:
val = get_pmtmr(s);
break;
default:
val = 0;
break;
}
#ifdef DEBUG
printf("PM readl port=0x%04x val=0x%08x\n", addr, val);
#endif
return val;
}
static void smi_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
{
PIIX4PMState *s = opaque;
#ifdef DEBUG
printf("SMI cmd val=0x%02x\n", val);
#endif
switch(val) {
case 0xf0: /* ACPI disable */
s->pmcntrl &= ~SCI_EN;
break;
case 0xf1: /* ACPI enable */
s->pmcntrl |= SCI_EN;
break;
}
}
static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val)
{
#if defined(DEBUG)
printf("ACPI: DBG: 0x%08x\n", val);
#endif
}
/* XXX: we still add it to the PIIX3 and we count on the fact that
OSes are smart enough to accept this strange configuration */
void piix4_pm_init(PCIBus *bus, int devfn)
{
PIIX4PMState *s;
uint8_t *pci_conf;
uint32_t pm_io_base;
s = (PIIX4PMState *)pci_register_device(bus,
"PM", sizeof(PIIX4PMState),
devfn, NULL, NULL);
pci_conf = s->dev.config;
pci_conf[0x00] = 0x86;
pci_conf[0x01] = 0x80;
pci_conf[0x02] = 0x13;
pci_conf[0x03] = 0x71;
pci_conf[0x08] = 0x00; // revision number
pci_conf[0x09] = 0x00;
pci_conf[0x0a] = 0x80; // other bridge device
pci_conf[0x0b] = 0x06; // bridge device
pci_conf[0x0e] = 0x00; // header_type
pci_conf[0x3d] = 0x01; // interrupt pin 1
pm_io_base = PM_IO_BASE;
pci_conf[0x40] = pm_io_base | 1;
pci_conf[0x41] = pm_io_base >> 8;
register_ioport_write(pm_io_base, 64, 2, pm_ioport_writew, s);
register_ioport_read(pm_io_base, 64, 2, pm_ioport_readw, s);
register_ioport_write(pm_io_base, 64, 4, pm_ioport_writel, s);
register_ioport_read(pm_io_base, 64, 4, pm_ioport_readl, s);
register_ioport_write(SMI_CMD_IO_ADDR, 1, 1, smi_cmd_writeb, s);
register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s);
/* XXX: which specification is used ? The i82731AB has different
mappings */
pci_conf[0x5f] = (parallel_hds[0] != NULL ? 0x80 : 0) | 0x10;
pci_conf[0x63] = 0x60;
pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
(serial_hds[1] != NULL ? 0x90 : 0);
s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
piix4_pm_state = s;
}
/* ACPI tables */
/* XXX: move them in the Bochs BIOS ? */
/*************************************************/
/* Table structure from Linux kernel (the ACPI tables are under the
BSD license) */
#define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \
uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\
uint32_t length; /* Length of table, in bytes, including header */\
uint8_t revision; /* ACPI Specification minor version # */\
uint8_t checksum; /* To make sum of entire table == 0 */\
uint8_t oem_id [6]; /* OEM identification */\
uint8_t oem_table_id [8]; /* OEM table identification */\
uint32_t oem_revision; /* OEM revision number */\
uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\
uint32_t asl_compiler_revision; /* ASL compiler revision number */
struct acpi_table_header /* ACPI common table header */
{
ACPI_TABLE_HEADER_DEF
};
struct rsdp_descriptor /* Root System Descriptor Pointer */
{
uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */
uint8_t checksum; /* To make sum of struct == 0 */
uint8_t oem_id [6]; /* OEM identification */
uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */
uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */
uint32_t length; /* XSDT Length in bytes including hdr */
uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */
uint8_t extended_checksum; /* Checksum of entire table */
uint8_t reserved [3]; /* Reserved field must be 0 */
};
/*
* ACPI 1.0 Root System Description Table (RSDT)
*/
struct rsdt_descriptor_rev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t table_offset_entry [2]; /* Array of pointers to other */
/* ACPI tables */
};
/*
* ACPI 1.0 Firmware ACPI Control Structure (FACS)
*/
struct facs_descriptor_rev1
{
uint8_t signature[4]; /* ACPI Signature */
uint32_t length; /* Length of structure, in bytes */
uint32_t hardware_signature; /* Hardware configuration signature */
uint32_t firmware_waking_vector; /* ACPI OS waking vector */
uint32_t global_lock; /* Global Lock */
uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */
uint32_t reserved1 : 31; /* Must be 0 */
uint8_t resverved3 [40]; /* Reserved - must be zero */
};
/*
* ACPI 1.0 Fixed ACPI Description Table (FADT)
*/
struct fadt_descriptor_rev1
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t firmware_ctrl; /* Physical address of FACS */
uint32_t dsdt; /* Physical address of DSDT */
uint8_t model; /* System Interrupt Model */
uint8_t reserved1; /* Reserved */
uint16_t sci_int; /* System vector of SCI interrupt */
uint32_t smi_cmd; /* Port address of SMI command port */
uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */
uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */
uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */
uint8_t reserved2; /* Reserved - must be zero */
uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */
uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */
uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */
uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */
uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */
uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */
uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */
uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */
uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */
uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */
uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */
uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */
uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */
uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */
uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */
uint8_t reserved3; /* Reserved */
uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */
uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */
uint16_t flush_size; /* Size of area read to flush caches */
uint16_t flush_stride; /* Stride used in flushing caches */
uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */
uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */
uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */
uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */
uint8_t century; /* Index to century in RTC CMOS RAM */
uint8_t reserved4; /* Reserved */
uint8_t reserved4a; /* Reserved */
uint8_t reserved4b; /* Reserved */
#if 0
uint32_t wb_invd : 1; /* The wbinvd instruction works properly */
uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */
uint32_t proc_c1 : 1; /* All processors support C1 state */
uint32_t plvl2_up : 1; /* C2 state works on MP system */
uint32_t pwr_button : 1; /* Power button is handled as a generic feature */
uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */
uint32_t reserved5 : 23; /* Reserved - must be zero */
#else
uint32_t flags;
#endif
};
/*
* MADT values and structures
*/
/* Values for MADT PCATCompat */
#define DUAL_PIC 0
#define MULTIPLE_APIC 1
/* Master MADT */
struct multiple_apic_table
{
ACPI_TABLE_HEADER_DEF /* ACPI common table header */
uint32_t local_apic_address; /* Physical address of local APIC */
#if 0
uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */
uint32_t reserved1 : 31;
#else
uint32_t flags;
#endif
};
/* Values for Type in APIC_HEADER_DEF */
#define APIC_PROCESSOR 0
#define APIC_IO 1
#define APIC_XRUPT_OVERRIDE 2
#define APIC_NMI 3
#define APIC_LOCAL_NMI 4
#define APIC_ADDRESS_OVERRIDE 5
#define APIC_IO_SAPIC 6
#define APIC_LOCAL_SAPIC 7
#define APIC_XRUPT_SOURCE 8
#define APIC_RESERVED 9 /* 9 and greater are reserved */
/*
* MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
*/
#define APIC_HEADER_DEF /* Common APIC sub-structure header */\
uint8_t type; \
uint8_t length;
/* Sub-structures for MADT */
struct madt_processor_apic
{
APIC_HEADER_DEF
uint8_t processor_id; /* ACPI processor id */
uint8_t local_apic_id; /* Processor's local APIC id */
#if 0
uint32_t processor_enabled: 1; /* Processor is usable if set */
uint32_t reserved2 : 31; /* Reserved, must be zero */
#else
uint32_t flags;
#endif
};
struct madt_io_apic
{
APIC_HEADER_DEF
uint8_t io_apic_id; /* I/O APIC ID */
uint8_t reserved; /* Reserved - must be zero */
uint32_t address; /* APIC physical address */
uint32_t interrupt; /* Global system interrupt where INTI
* lines start */
};
#include "acpi-dsdt.hex"
static int acpi_checksum(const uint8_t *data, int len)
{
int sum, i;
sum = 0;
for(i = 0; i < len; i++)
sum += data[i];
return (-sum) & 0xff;
}
static void acpi_build_table_header(struct acpi_table_header *h,
char *sig, int len)
{
memcpy(h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = 0;
memcpy(h->oem_id, "QEMU ", 6);
memcpy(h->oem_table_id, "QEMU", 4);
memcpy(h->oem_table_id + 4, sig, 4);
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, "QEMU", 4);
h->asl_compiler_revision = cpu_to_le32(1);
h->checksum = acpi_checksum((void *)h, len);
}
#define ACPI_TABLES_BASE 0x000e8000
/* base_addr must be a multiple of 4KB */
void acpi_bios_init(void)
{
struct rsdp_descriptor *rsdp;
struct rsdt_descriptor_rev1 *rsdt;
struct fadt_descriptor_rev1 *fadt;
struct facs_descriptor_rev1 *facs;
struct multiple_apic_table *madt;
uint8_t *dsdt;
uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr;
uint32_t pm_io_base, acpi_tables_size, madt_addr, madt_size;
int i;
/* compute PCI I/O addresses */
pm_io_base = (piix4_pm_state->dev.config[0x40] |
(piix4_pm_state->dev.config[0x41] << 8)) & ~0x3f;
base_addr = ACPI_TABLES_BASE;
/* reserve memory space for tables */
addr = base_addr;
rsdp = (void *)(phys_ram_base + addr);
addr += sizeof(*rsdp);
rsdt_addr = addr;
rsdt = (void *)(phys_ram_base + addr);
addr += sizeof(*rsdt);
fadt_addr = addr;
fadt = (void *)(phys_ram_base + addr);
addr += sizeof(*fadt);
/* XXX: FACS should be in RAM */
addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */
facs_addr = addr;
facs = (void *)(phys_ram_base + addr);
addr += sizeof(*facs);
dsdt_addr = addr;
dsdt = (void *)(phys_ram_base + addr);
addr += sizeof(AmlCode);
addr = (addr + 7) & ~7;
madt_addr = addr;
madt_size = sizeof(*madt) +
sizeof(struct madt_processor_apic) * smp_cpus +
sizeof(struct madt_io_apic);
madt = (void *)(phys_ram_base + addr);
addr += madt_size;
acpi_tables_size = addr - base_addr;
cpu_register_physical_memory(base_addr, acpi_tables_size,
base_addr | IO_MEM_ROM);
/* RSDP */
memset(rsdp, 0, sizeof(*rsdp));
memcpy(rsdp->signature, "RSD PTR ", 8);
memcpy(rsdp->oem_id, "QEMU ", 6);
rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr);
rsdp->checksum = acpi_checksum((void *)rsdp, 20);
/* RSDT */
rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
acpi_build_table_header((struct acpi_table_header *)rsdt,
"RSDT", sizeof(*rsdt));
/* FADT */
memset(fadt, 0, sizeof(*fadt));
fadt->firmware_ctrl = cpu_to_le32(facs_addr);
fadt->dsdt = cpu_to_le32(dsdt_addr);
fadt->model = 1;
fadt->reserved1 = 0;
fadt->sci_int = cpu_to_le16(piix4_pm_state->dev.config[0x3c]);
fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR);
fadt->acpi_enable = 0xf1;
fadt->acpi_disable = 0xf0;
fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base);
fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04);
fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08);
fadt->pm1_evt_len = 4;
fadt->pm1_cnt_len = 2;
fadt->pm_tmr_len = 4;
fadt->plvl2_lat = cpu_to_le16(50);
fadt->plvl3_lat = cpu_to_le16(50);
fadt->plvl3_lat = cpu_to_le16(50);
/* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */
fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6));
acpi_build_table_header((struct acpi_table_header *)fadt, "FACP",
sizeof(*fadt));
/* FACS */
memset(facs, 0, sizeof(*facs));
memcpy(facs->signature, "FACS", 4);
facs->length = cpu_to_le32(sizeof(*facs));
/* DSDT */
memcpy(dsdt, AmlCode, sizeof(AmlCode));
/* MADT */
{
struct madt_processor_apic *apic;
struct madt_io_apic *io_apic;
memset(madt, 0, madt_size);
madt->local_apic_address = cpu_to_le32(0xfee00000);
madt->flags = cpu_to_le32(1);
apic = (void *)(madt + 1);
for(i=0;i<smp_cpus;i++) {
apic->type = APIC_PROCESSOR;
apic->length = sizeof(*apic);
apic->processor_id = i;
apic->local_apic_id = i;
apic->flags = cpu_to_le32(1);
apic++;
}
io_apic = (void *)apic;
io_apic->type = APIC_IO;
io_apic->length = sizeof(*io_apic);
io_apic->io_apic_id = smp_cpus;
io_apic->address = cpu_to_le32(0xfec00000);
io_apic->interrupt = cpu_to_le32(0);
acpi_build_table_header((struct acpi_table_header *)madt,
"APIC", madt_size);
}
}
+2 -2
View File
@@ -301,6 +301,7 @@ int Adlib_init (AudioState *audio)
as.freq = conf.freq;
as.nchannels = SHIFT;
as.fmt = AUD_FMT_S16;
as.endianness = AUDIO_HOST_ENDIANNESS;
AUD_register_card (audio, "adlib", &s->card);
@@ -310,8 +311,7 @@ int Adlib_init (AudioState *audio)
"adlib",
s,
adlib_callback,
&as,
0 /* XXX: little endian? */
&as
);
if (!s->voice) {
Adlib_fini (s);
+232
View File
@@ -0,0 +1,232 @@
/*
* QEMU Ultrasparc APB PCI host
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
typedef PCIHostState APBState;
static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
APBState *s = opaque;
int i;
for (i = 11; i < 32; i++) {
if ((val & (1 << i)) != 0)
break;
}
s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
}
static uint32_t pci_apb_config_readl (void *opaque,
target_phys_addr_t addr)
{
APBState *s = opaque;
uint32_t val;
int devfn;
devfn = (s->config_reg >> 8) & 0xFF;
val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
return val;
}
static CPUWriteMemoryFunc *pci_apb_config_write[] = {
&pci_apb_config_writel,
&pci_apb_config_writel,
&pci_apb_config_writel,
};
static CPUReadMemoryFunc *pci_apb_config_read[] = {
&pci_apb_config_readl,
&pci_apb_config_readl,
&pci_apb_config_readl,
};
static void apb_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
//PCIBus *s = opaque;
switch (addr & 0x3f) {
case 0x00: // Control/Status
case 0x10: // AFSR
case 0x18: // AFAR
case 0x20: // Diagnostic
case 0x28: // Target address space
// XXX
default:
break;
}
}
static uint32_t apb_config_readl (void *opaque,
target_phys_addr_t addr)
{
//PCIBus *s = opaque;
uint32_t val;
switch (addr & 0x3f) {
case 0x00: // Control/Status
case 0x10: // AFSR
case 0x18: // AFAR
case 0x20: // Diagnostic
case 0x28: // Target address space
// XXX
default:
val = 0;
break;
}
return val;
}
static CPUWriteMemoryFunc *apb_config_write[] = {
&apb_config_writel,
&apb_config_writel,
&apb_config_writel,
};
static CPUReadMemoryFunc *apb_config_read[] = {
&apb_config_readl,
&apb_config_readl,
&apb_config_readl,
};
static CPUWriteMemoryFunc *pci_apb_write[] = {
&pci_host_data_writeb,
&pci_host_data_writew,
&pci_host_data_writel,
};
static CPUReadMemoryFunc *pci_apb_read[] = {
&pci_host_data_readb,
&pci_host_data_readw,
&pci_host_data_readl,
};
static void pci_apb_iowriteb (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
cpu_outb(NULL, addr & 0xffff, val);
}
static void pci_apb_iowritew (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
cpu_outw(NULL, addr & 0xffff, val);
}
static void pci_apb_iowritel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
cpu_outl(NULL, addr & 0xffff, val);
}
static uint32_t pci_apb_ioreadb (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inb(NULL, addr & 0xffff);
return val;
}
static uint32_t pci_apb_ioreadw (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inw(NULL, addr & 0xffff);
return val;
}
static uint32_t pci_apb_ioreadl (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = cpu_inl(NULL, addr & 0xffff);
return val;
}
static CPUWriteMemoryFunc *pci_apb_iowrite[] = {
&pci_apb_iowriteb,
&pci_apb_iowritew,
&pci_apb_iowritel,
};
static CPUReadMemoryFunc *pci_apb_ioread[] = {
&pci_apb_ioreadb,
&pci_apb_ioreadw,
&pci_apb_ioreadl,
};
/* ??? This is probably wrong. */
static void pci_apb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
{
pic_set_irq_new(pic, d->config[PCI_INTERRUPT_LINE], level);
}
PCIBus *pci_apb_init(target_ulong special_base, target_ulong mem_base,
void *pic)
{
APBState *s;
PCIDevice *d;
int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
s = qemu_mallocz(sizeof(APBState));
/* Ultrasparc APB main bus */
s->bus = pci_register_bus(pci_apb_set_irq, pic, 0);
pci_mem_config = cpu_register_io_memory(0, pci_apb_config_read,
pci_apb_config_write, s);
apb_config = cpu_register_io_memory(0, apb_config_read,
apb_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_apb_read,
pci_apb_write, s);
pci_ioport = cpu_register_io_memory(0, pci_apb_ioread,
pci_apb_iowrite, s);
cpu_register_physical_memory(special_base + 0x2000ULL, 0x40, apb_config);
cpu_register_physical_memory(special_base + 0x1000000ULL, 0x10, pci_mem_config);
cpu_register_physical_memory(special_base + 0x2000000ULL, 0x10000, pci_ioport);
cpu_register_physical_memory(mem_base, 0x10000000, pci_mem_data); // XXX size should be 4G-prom
d = pci_register_device(s->bus, "Advanced PCI Bus", sizeof(PCIDevice),
-1, NULL, NULL);
d->config[0x00] = 0x8e; // vendor_id : Sun
d->config[0x01] = 0x10;
d->config[0x02] = 0x00; // device_id
d->config[0x03] = 0xa0;
d->config[0x04] = 0x06; // command = bus master, pci mem
d->config[0x05] = 0x00;
d->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
d->config[0x07] = 0x03; // status = medium devsel
d->config[0x08] = 0x00; // revision
d->config[0x09] = 0x00; // programming i/f
d->config[0x0A] = 0x00; // class_sub = pci host
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
return s->bus;
}
+2 -2
View File
@@ -239,7 +239,7 @@ void cpu_set_apic_base(CPUState *env, uint64_t val)
{
APICState *s = env->apic_state;
#ifdef DEBUG_APIC
printf("cpu_set_apic_base: %016llx\n", val);
printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
#endif
s->apicbase = (val & 0xfffff000) |
(s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
@@ -255,7 +255,7 @@ uint64_t cpu_get_apic_base(CPUState *env)
{
APICState *s = env->apic_state;
#ifdef DEBUG_APIC
printf("cpu_get_apic_base: %016llx\n", (uint64_t)s->apicbase);
printf("cpu_get_apic_base: %016" PRIx64 "\n", (uint64_t)s->apicbase);
#endif
return s->apicbase;
}
+156
View File
@@ -0,0 +1,156 @@
/*
* QEMU ATAPI CD-ROM Emulator
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* ??? Most of the ATAPI emulation is still in ide.c. It should be moved
here. */
#include <vl.h>
static void lba_to_msf(uint8_t *buf, int lba)
{
lba += 150;
buf[0] = (lba / 75) / 60;
buf[1] = (lba / 75) % 60;
buf[2] = lba % 75;
}
/* same toc as bochs. Return -1 if error or the toc length */
/* XXX: check this */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
{
uint8_t *q;
int len;
if (start_track > 1 && start_track != 0xaa)
return -1;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
if (start_track <= 1) {
*q++ = 0; /* reserved */
*q++ = 0x14; /* ADR, control */
*q++ = 1; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
} else {
/* sector 0 */
cpu_to_be32wu((uint32_t *)q, 0);
q += 4;
}
}
/* lead out track */
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_be32wu((uint32_t *)q, nb_sectors);
q += 4;
}
len = q - buf;
cpu_to_be16wu((uint16_t *)buf, len - 2);
return len;
}
/* mostly same info as PearPc */
int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num)
{
uint8_t *q;
int len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_be32wu((uint32_t *)q, nb_sectors);
q += 4;
}
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
if (msf) {
*q++ = 0;
lba_to_msf(q, 0);
q += 3;
} else {
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
}
len = q - buf;
cpu_to_be16wu((uint16_t *)buf, len - 2);
return len;
}
+1 -1
View File
@@ -209,7 +209,7 @@ static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
}
#if 0
#ifdef DEBUG_CUDA
printf("latch=%d counter=%lld delta_next=%lld\n",
printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
s->latch, d, next_time - d);
#endif
#endif
+5 -5
View File
@@ -423,6 +423,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
as.freq = new_freq;
as.nchannels = 1 << (new_fmt & 1);
as.fmt = (new_fmt & 2) ? AUD_FMT_S16 : AUD_FMT_U8;
as.endianness = 0;
if (i == ADC_CHANNEL) {
s->adc_voice =
@@ -432,8 +433,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
"es1370.adc",
s,
es1370_adc_callback,
&as,
0 /* little endian */
&as
);
}
else {
@@ -444,8 +444,7 @@ static void es1370_update_voices (ES1370State *s, uint32_t ctl, uint32_t sctl)
i ? "es1370.dac2" : "es1370.dac1",
s,
i ? es1370_dac2_callback : es1370_dac1_callback,
&as,
0 /* litle endian */
&as
);
}
}
@@ -479,9 +478,10 @@ static inline uint32_t es1370_fixup (ES1370State *s, uint32_t addr)
IO_WRITE_PROTO (es1370_writeb)
{
ES1370State *s = opaque;
addr = es1370_fixup (s, addr);
uint32_t shift, mask;
addr = es1370_fixup (s, addr);
switch (addr) {
case ES1370_REG_CONTROL:
case ES1370_REG_CONTROL + 1:
+170 -346
View File
@@ -38,17 +38,14 @@ do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level)
#define ESPDMA_REGS 4
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
#define ESP_MAXREG 0x3f
#define TI_BUFSZ 1024*1024 // XXX
#define TI_BUFSZ 32
#define DMA_VER 0xa0000000
#define DMA_INTR 1
#define DMA_INTREN 0x10
#define DMA_WRITE_MEM 0x100
#define DMA_LOADED 0x04000000
typedef struct ESPState ESPState;
typedef int ESPDMAFunc(ESPState *s,
target_phys_addr_t phys_addr,
int transfer_size1);
struct ESPState {
BlockDriverState **bd;
uint8_t rregs[ESP_MAXREG];
@@ -57,12 +54,14 @@ struct ESPState {
uint32_t espdmaregs[ESPDMA_REGS];
uint32_t ti_size;
uint32_t ti_rptr, ti_wptr;
int ti_dir;
uint8_t ti_buf[TI_BUFSZ];
int sense;
int dma;
ESPDMAFunc *dma_cb;
int64_t offset, len;
int target;
SCSIDevice *scsi_dev[MAX_DISKS];
SCSIDevice *current_dev;
uint8_t cmdbuf[TI_BUFSZ];
int cmdlen;
int do_cmd;
};
#define STAT_DO 0x00
@@ -83,394 +82,200 @@ struct ESPState {
#define SEQ_0 0x0
#define SEQ_CD 0x4
/* XXX: stolen from ide.c, move to common ATAPI/SCSI library */
static void lba_to_msf(uint8_t *buf, int lba)
static int get_cmd(ESPState *s, uint8_t *buf)
{
lba += 150;
buf[0] = (lba / 75) / 60;
buf[1] = (lba / 75) % 60;
buf[2] = lba % 75;
}
static inline void cpu_to_ube16(uint8_t *buf, int val)
{
buf[0] = val >> 8;
buf[1] = val;
}
static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
{
buf[0] = val >> 24;
buf[1] = val >> 16;
buf[2] = val >> 8;
buf[3] = val;
}
/* same toc as bochs. Return -1 if error or the toc length */
/* XXX: check this */
static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
{
uint8_t *q;
int len;
if (start_track > 1 && start_track != 0xaa)
return -1;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
if (start_track <= 1) {
*q++ = 0; /* reserved */
*q++ = 0x14; /* ADR, control */
*q++ = 1; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
} else {
/* sector 0 */
cpu_to_ube32(q, 0);
q += 4;
}
}
/* lead out track */
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_ube32(q, nb_sectors);
q += 4;
}
len = q - buf;
cpu_to_ube16(buf, len - 2);
return len;
}
/* mostly same info as PearPc */
static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf,
int session_num)
{
uint8_t *q;
int len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_ube32(q, nb_sectors);
q += 4;
}
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
if (msf) {
*q++ = 0;
lba_to_msf(q, 0);
q += 3;
} else {
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
}
len = q - buf;
cpu_to_ube16(buf, len - 2);
return len;
}
static int esp_write_dma_cb(ESPState *s,
target_phys_addr_t phys_addr,
int transfer_size1)
{
DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
s->offset, s->len, s->ti_size, transfer_size1);
bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
s->offset = 0;
s->len = 0;
s->target = 0;
return 0;
}
static void handle_satn(ESPState *s)
{
uint8_t buf[32];
uint32_t dmaptr, dmalen;
unsigned int i;
int64_t nb_sectors;
int target;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
target = s->wregs[4] & 7;
DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
cpu_physical_memory_read(dmaptr, buf, dmalen);
} else {
buf[0] = 0;
memcpy(&buf[1], s->ti_buf, dmalen);
dmalen++;
}
for (i = 0; i < dmalen; i++) {
DPRINTF("Command %2.2x\n", buf[i]);
}
s->ti_dir = 0;
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
if (target >= 4 || !s->bd[target]) { // No such drive
if (target >= 4 || !s->scsi_dev[target]) {
// No such drive
s->rregs[4] = STAT_IN;
s->rregs[5] = INTR_DC;
s->rregs[6] = SEQ_0;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
return;
return 0;
}
switch (buf[1]) {
case 0x0:
DPRINTF("Test Unit Ready (len %d)\n", buf[5]);
break;
case 0x12:
DPRINTF("Inquiry (len %d)\n", buf[5]);
memset(s->ti_buf, 0, 36);
if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
s->ti_buf[0] = 5;
memcpy(&s->ti_buf[16], "QEMU CDROM ", 16);
} else {
s->ti_buf[0] = 0;
memcpy(&s->ti_buf[16], "QEMU HARDDISK ", 16);
}
memcpy(&s->ti_buf[8], "QEMU ", 8);
s->ti_buf[2] = 1;
s->ti_buf[3] = 2;
s->ti_buf[4] = 32;
s->ti_dir = 1;
s->ti_size = 36;
break;
case 0x1a:
DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);
break;
case 0x25:
DPRINTF("Read Capacity (len %d)\n", buf[5]);
memset(s->ti_buf, 0, 8);
bdrv_get_geometry(s->bd[target], &nb_sectors);
s->ti_buf[0] = (nb_sectors >> 24) & 0xff;
s->ti_buf[1] = (nb_sectors >> 16) & 0xff;
s->ti_buf[2] = (nb_sectors >> 8) & 0xff;
s->ti_buf[3] = nb_sectors & 0xff;
s->ti_buf[4] = 0;
s->ti_buf[5] = 0;
if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
s->ti_buf[6] = 8; // sector size 2048
else
s->ti_buf[6] = 2; // sector size 512
s->ti_buf[7] = 0;
s->ti_dir = 1;
s->ti_size = 8;
break;
case 0x28:
{
int64_t offset, len;
s->current_dev = s->scsi_dev[target];
return dmalen;
}
if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
len = ((buf[8] << 8) | buf[9]) * 4;
s->ti_size = len * 2048;
} else {
offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
len = (buf[8] << 8) | buf[9];
s->ti_size = len * 512;
}
DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
if (s->ti_size > TI_BUFSZ) {
DPRINTF("size too large %d\n", s->ti_size);
}
bdrv_read(s->bd[target], offset, s->ti_buf, len);
// XXX error handling
s->ti_dir = 1;
break;
}
case 0x2a:
{
int64_t offset, len;
static void do_cmd(ESPState *s, uint8_t *buf)
{
int32_t datalen;
int lun;
if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
len = ((buf[8] << 8) | buf[9]) * 4;
s->ti_size = len * 2048;
} else {
offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
len = (buf[8] << 8) | buf[9];
s->ti_size = len * 512;
}
DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
if (s->ti_size > TI_BUFSZ) {
DPRINTF("size too large %d\n", s->ti_size);
}
s->dma_cb = esp_write_dma_cb;
s->offset = offset;
s->len = len;
s->target = target;
// XXX error handling
s->ti_dir = 0;
break;
}
case 0x43:
{
int start_track, format, msf, len;
msf = buf[2] & 2;
format = buf[3] & 0xf;
start_track = buf[7];
bdrv_get_geometry(s->bd[target], &nb_sectors);
DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
switch(format) {
case 0:
len = cdrom_read_toc(nb_sectors, buf, msf, start_track);
if (len < 0)
goto error_cmd;
s->ti_size = len;
break;
case 1:
/* multi session : only a single session defined */
memset(buf, 0, 12);
buf[1] = 0x0a;
buf[2] = 0x01;
buf[3] = 0x01;
s->ti_size = 12;
break;
case 2:
len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);
if (len < 0)
goto error_cmd;
s->ti_size = len;
break;
default:
error_cmd:
DPRINTF("Read TOC error\n");
// XXX error handling
break;
}
s->ti_dir = 1;
break;
DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
lun = buf[0] & 7;
datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
if (datalen == 0) {
s->ti_size = 0;
} else {
s->rregs[4] = STAT_IN | STAT_TC;
if (datalen > 0) {
s->rregs[4] |= STAT_DI;
s->ti_size = datalen;
} else {
s->rregs[4] |= STAT_DO;
s->ti_size = -datalen;
}
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
break;
}
s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
}
static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
static void handle_satn(ESPState *s)
{
uint32_t dmaptr, dmalen;
uint8_t buf[32];
int len;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
DPRINTF("Transfer status len %d\n", dmalen);
len = get_cmd(s, buf);
if (len)
do_cmd(s, buf);
}
static void handle_satn_stop(ESPState *s)
{
s->cmdlen = get_cmd(s, s->cmdbuf);
if (s->cmdlen) {
DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
s->do_cmd = 1;
s->espdmaregs[1] += s->cmdlen;
s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
}
}
static void write_response(ESPState *s)
{
uint32_t dmaptr;
DPRINTF("Transfer status (sense=%d)\n", s->sense);
s->ti_buf[0] = s->sense;
s->ti_buf[1] = 0;
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
cpu_physical_memory_write(dmaptr, buf, len);
DPRINTF("DMA Direction: %c\n",
s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->rregs[5] = INTR_BS | INTR_FC;
s->rregs[6] = SEQ_CD;
} else {
memcpy(s->ti_buf, buf, len);
s->ti_size = dmalen;
s->ti_size = 2;
s->ti_rptr = 0;
s->ti_wptr = 0;
s->rregs[7] = dmalen;
s->rregs[7] = 2;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
}
static const uint8_t okbuf[] = {0, 0};
static void esp_command_complete(void *opaque, uint32_t tag, int sense)
{
ESPState *s = (ESPState *)opaque;
DPRINTF("SCSI Command complete\n");
if (s->ti_size != 0)
DPRINTF("SCSI command completed unexpectedly\n");
s->ti_size = 0;
if (sense)
DPRINTF("Command failed\n");
s->sense = sense;
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
}
static void handle_ti(ESPState *s)
{
uint32_t dmaptr, dmalen;
uint32_t dmaptr, dmalen, minlen, len, from, to;
unsigned int i;
int to_device;
uint8_t buf[TARGET_PAGE_SIZE];
dmalen = s->wregs[0] | (s->wregs[1] << 8);
DPRINTF("Transfer Information len %d\n", dmalen);
if (dmalen==0) {
dmalen=0x10000;
}
if (s->do_cmd)
minlen = (dmalen < 32) ? dmalen : 32;
else
minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
DPRINTF("Transfer Information len %d\n", minlen);
if (s->dma) {
dmaptr = iommu_translate(s->espdmaregs[1]);
DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
for (i = 0; i < s->ti_size; i++) {
/* Check if the transfer writes to to reads from the device. */
to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
to_device ? 'r': 'w', dmaptr, s->ti_size);
from = s->espdmaregs[1];
to = from + minlen;
for (i = 0; i < minlen; i += len, from += len) {
dmaptr = iommu_translate(s->espdmaregs[1] + i);
if (s->ti_dir)
cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
else
cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
}
if (s->dma_cb) {
s->dma_cb(s, s->espdmaregs[1], dmalen);
s->dma_cb = NULL;
if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
} else {
len = to - from;
}
DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
s->ti_size -= len;
if (s->do_cmd) {
DPRINTF("command len %d + %d\n", s->cmdlen, len);
cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
s->ti_size = 0;
s->cmdlen = 0;
s->do_cmd = 0;
do_cmd(s, s->cmdbuf);
return;
} else {
if (to_device) {
cpu_physical_memory_read(dmaptr, buf, len);
scsi_write_data(s->current_dev, buf, len);
} else {
scsi_read_data(s->current_dev, buf, len);
cpu_physical_memory_write(dmaptr, buf, len);
}
}
}
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->rregs[5] = INTR_BS;
if (s->ti_size) {
s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
}
s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
s->rregs[7] = 0;
s->espdmaregs[0] |= DMA_INTR;
} else {
s->ti_size = dmalen;
s->ti_rptr = 0;
s->ti_wptr = 0;
s->rregs[7] = dmalen;
}
} else if (s->do_cmd) {
DPRINTF("command len %d\n", s->cmdlen);
s->ti_size = 0;
s->cmdlen = 0;
s->do_cmd = 0;
do_cmd(s, s->cmdbuf);
return;
}
pic_set_irq(s->irq, 1);
}
@@ -484,9 +289,8 @@ static void esp_reset(void *opaque)
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
s->ti_dir = 0;
s->dma = 0;
s->dma_cb = NULL;
s->do_cmd = 0;
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -501,7 +305,12 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
// FIFO
if (s->ti_size > 0) {
s->ti_size--;
s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
if ((s->rregs[4] & 6) == 0) {
/* Data in/out. */
scsi_read_data(s->current_dev, &s->rregs[2], 0);
} else {
s->rregs[2] = s->ti_buf[s->ti_rptr++];
}
pic_set_irq(s->irq, 1);
}
if (s->ti_size == 0) {
@@ -536,8 +345,17 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
break;
case 2:
// FIFO
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
if (s->do_cmd) {
s->cmdbuf[s->cmdlen++] = val & 0xff;
} else if ((s->rregs[4] & 6) == 0) {
uint8_t buf;
buf = val & 0xff;
s->ti_size--;
scsi_write_data(s->current_dev, &buf, 0);
} else {
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
}
break;
case 3:
s->rregs[saddr] = val;
@@ -574,11 +392,11 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
break;
case 0x11:
DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
dma_write(s, okbuf, 2);
write_response(s);
break;
case 0x12:
DPRINTF("Message Accepted (%2.2x)\n", val);
dma_write(s, okbuf, 2);
write_response(s);
s->rregs[5] = INTR_DC;
s->rregs[6] = 0;
break;
@@ -586,11 +404,12 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
DPRINTF("Set ATN (%2.2x)\n", val);
break;
case 0x42:
DPRINTF("Set ATN (%2.2x)\n", val);
handle_satn(s);
break;
case 0x43:
DPRINTF("Set ATN & stop (%2.2x)\n", val);
handle_satn(s);
handle_satn_stop(s);
break;
default:
DPRINTF("Unhandled ESP command (%2.2x)\n", val);
@@ -660,7 +479,7 @@ static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
val |= DMA_VER;
break;
case 1:
s->espdmaregs[0] = DMA_LOADED;
s->espdmaregs[0] |= DMA_LOADED;
break;
default:
break;
@@ -693,7 +512,6 @@ static void esp_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, &s->ti_size);
qemu_put_be32s(f, &s->ti_rptr);
qemu_put_be32s(f, &s->ti_wptr);
qemu_put_be32s(f, &s->ti_dir);
qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
qemu_put_be32s(f, &s->dma);
}
@@ -714,7 +532,6 @@ static int esp_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &s->ti_size);
qemu_get_be32s(f, &s->ti_rptr);
qemu_get_be32s(f, &s->ti_wptr);
qemu_get_be32s(f, &s->ti_dir);
qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
qemu_get_be32s(f, &s->dma);
@@ -725,6 +542,7 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd
{
ESPState *s;
int esp_io_memory, espdma_io_memory;
int i;
s = qemu_mallocz(sizeof(ESPState));
if (!s)
@@ -743,5 +561,11 @@ void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdadd
register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
qemu_register_reset(esp_reset, s);
for (i = 0; i < MAX_DISKS; i++) {
if (bs_table[i]) {
s->scsi_dev[i] =
scsi_disk_init(bs_table[i], esp_command_complete, s);
}
}
}
+156
View File
@@ -0,0 +1,156 @@
/*
* QEMU Grackle (heathrow PPC) PCI host
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
typedef PCIHostState GrackleState;
static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
GrackleState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
s->config_reg = val;
}
static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
{
GrackleState *s = opaque;
uint32_t val;
val = s->config_reg;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_grackle_config_write[] = {
&pci_grackle_config_writel,
&pci_grackle_config_writel,
&pci_grackle_config_writel,
};
static CPUReadMemoryFunc *pci_grackle_config_read[] = {
&pci_grackle_config_readl,
&pci_grackle_config_readl,
&pci_grackle_config_readl,
};
static CPUWriteMemoryFunc *pci_grackle_write[] = {
&pci_host_data_writeb,
&pci_host_data_writew,
&pci_host_data_writel,
};
static CPUReadMemoryFunc *pci_grackle_read[] = {
&pci_host_data_readb,
&pci_host_data_readw,
&pci_host_data_readl,
};
/* XXX: we do not simulate the hardware - we rely on the BIOS to
set correctly for irq line field */
static void pci_grackle_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
{
heathrow_pic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
}
PCIBus *pci_grackle_init(uint32_t base, void *pic)
{
GrackleState *s;
PCIDevice *d;
int pci_mem_config, pci_mem_data;
s = qemu_mallocz(sizeof(GrackleState));
s->bus = pci_register_bus(pci_grackle_set_irq, pic, 0);
pci_mem_config = cpu_register_io_memory(0, pci_grackle_config_read,
pci_grackle_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_grackle_read,
pci_grackle_write, s);
cpu_register_physical_memory(base, 0x1000, pci_mem_config);
cpu_register_physical_memory(base + 0x00200000, 0x1000, pci_mem_data);
d = pci_register_device(s->bus, "Grackle host bridge", sizeof(PCIDevice),
0, NULL, NULL);
d->config[0x00] = 0x57; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x02; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x00; // revision
d->config[0x09] = 0x01;
d->config[0x0a] = 0x00; // class_sub = host
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x00; // header_type
d->config[0x18] = 0x00; // primary_bus
d->config[0x19] = 0x01; // secondary_bus
d->config[0x1a] = 0x00; // subordinate_bus
d->config[0x1c] = 0x00;
d->config[0x1d] = 0x00;
d->config[0x20] = 0x00; // memory_base
d->config[0x21] = 0x00;
d->config[0x22] = 0x01; // memory_limit
d->config[0x23] = 0x00;
d->config[0x24] = 0x00; // prefetchable_memory_base
d->config[0x25] = 0x00;
d->config[0x26] = 0x00; // prefetchable_memory_limit
d->config[0x27] = 0x00;
#if 0
/* PCI2PCI bridge same values as PearPC - check this */
d->config[0x00] = 0x11; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x26; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x02; // revision
d->config[0x0a] = 0x04; // class_sub = pci2pci
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x01; // header_type
d->config[0x18] = 0x0; // primary_bus
d->config[0x19] = 0x1; // secondary_bus
d->config[0x1a] = 0x1; // subordinate_bus
d->config[0x1c] = 0x10; // io_base
d->config[0x1d] = 0x20; // io_limit
d->config[0x20] = 0x80; // memory_base
d->config[0x21] = 0x80;
d->config[0x22] = 0x90; // memory_limit
d->config[0x23] = 0x80;
d->config[0x24] = 0x00; // prefetchable_memory_base
d->config[0x25] = 0x84;
d->config[0x26] = 0x00; // prefetchable_memory_limit
d->config[0x27] = 0x85;
#endif
return s->bus;
}
+1 -1
View File
@@ -531,7 +531,7 @@ void irq_info(void)
for (i = 0; i < 16; i++) {
count = irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
term_printf("%2d: %" PRId64 "\n", i, count);
}
#endif
}
+9 -125
View File
@@ -1082,127 +1082,6 @@ static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
}
}
/* same toc as bochs. Return -1 if error or the toc length */
/* XXX: check this */
static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)
{
uint8_t *q;
int nb_sectors, len;
if (start_track > 1 && start_track != 0xaa)
return -1;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
if (start_track <= 1) {
*q++ = 0; /* reserved */
*q++ = 0x14; /* ADR, control */
*q++ = 1; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
} else {
/* sector 0 */
cpu_to_ube32(q, 0);
q += 4;
}
}
/* lead out track */
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
nb_sectors = s->nb_sectors >> 2;
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_ube32(q, nb_sectors);
q += 4;
}
len = q - buf;
cpu_to_ube16(buf, len - 2);
return len;
}
/* mostly same info as PearPc */
static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf,
int session_num)
{
uint8_t *q;
int nb_sectors, len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
nb_sectors = s->nb_sectors >> 2;
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, nb_sectors);
q += 3;
} else {
cpu_to_ube32(q, nb_sectors);
q += 4;
}
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
if (msf) {
*q++ = 0;
lba_to_msf(q, 0);
q += 3;
} else {
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
}
len = q - buf;
cpu_to_ube16(buf, len - 2);
return len;
}
static void ide_atapi_cmd(IDEState *s)
{
const uint8_t *packet;
@@ -1449,7 +1328,7 @@ static void ide_atapi_cmd(IDEState *s)
start_track = packet[6];
switch(format) {
case 0:
len = cdrom_read_toc(s, buf, msf, start_track);
len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, start_track);
if (len < 0)
goto error_cmd;
ide_atapi_cmd_reply(s, len, max_len);
@@ -1463,7 +1342,7 @@ static void ide_atapi_cmd(IDEState *s)
ide_atapi_cmd_reply(s, 12, max_len);
break;
case 2:
len = cdrom_read_toc_raw(s, buf, msf, start_track);
len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, start_track);
if (len < 0)
goto error_cmd;
ide_atapi_cmd_reply(s, len, max_len);
@@ -1777,6 +1656,11 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
break;
case WIN_FLUSH_CACHE:
case WIN_FLUSH_CACHE_EXT:
if (s->bs)
bdrv_flush(s->bs);
s->status = READY_STAT;
ide_set_irq(s);
break;
case WIN_STANDBYNOW1:
case WIN_IDLEIMMEDIATE:
s->status = READY_STAT;
@@ -2490,7 +2374,7 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
/* hd_table must contain 4 block drivers */
/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
{
PCIIDEState *d;
uint8_t *pci_conf;
@@ -2498,7 +2382,7 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
/* register a function 1 of PIIX3 */
d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
sizeof(PCIIDEState),
((PCIDevice *)piix3_state)->devfn + 1,
devfn,
NULL, NULL);
d->type = IDE_TYPE_PIIX3;
+1571
View File
File diff suppressed because it is too large. Load diff
+8 -2
View File
@@ -332,7 +332,10 @@ void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
if (NVRAM->type == 8)
tm.tm_year = fromBCD(val) + 68; // Base year is 1968
else
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
@@ -421,7 +424,10 @@ uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
if (NVRAM->type == 8)
retval = toBCD(tm.tm_year - 68); // Base year is 1968
else
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
+1 -5
View File
@@ -60,7 +60,7 @@ static void cpu_mips_update_count (CPUState *env, uint32_t count,
next++;
#if 0
if (logfile) {
fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
fprintf(logfile, "%s: 0x%08" PRIx64 " %08x %08x => 0x%08" PRIx64 "\n",
__func__, now, count, compare, next - now);
}
#endif
@@ -214,14 +214,10 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
run. */
bios_offset = ram_size + vga_ram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
printf("%s: load BIOS '%s' size %d\n", __func__, buf, BIOS_SIZE);
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret == BIOS_SIZE) {
cpu_register_physical_memory((uint32_t)(0x1fc00000),
BIOS_SIZE, bios_offset | IO_MEM_ROM);
env->PC = 0xBFC00000;
if (!kernel_filename)
return;
} else {
/* not fatal */
fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
+1 -1
View File
@@ -206,7 +206,7 @@ static int ne2000_buffer_full(NE2000State *s)
index = s->curpag << 8;
boundary = s->boundary << 8;
if (index < boundary)
if (index <= boundary)
avail = boundary - index;
else
avail = (s->stop - s->start) - (index - boundary);
+40 -11
View File
@@ -40,7 +40,6 @@ static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
static IOAPICState *ioapic;
static USBPort *usb_root_ports[2];
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
@@ -59,10 +58,19 @@ static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
}
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return qemu_get_clock(vm_clock);
/* Note: when using kqemu, it is more logical to return the host TSC
because kqemu does not trap the RDTSC instruction for
performance reasons */
#if USE_KQEMU
if (env->kqemu_enabled) {
return cpu_get_real_ticks();
} else
#endif
{
return cpu_get_ticks();
}
}
/* IRQ handling */
@@ -194,6 +202,8 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
case 'a':
case 'b':
rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
if (!fd_bootchk)
rtc_set_memory(s, 0x38, 0x01); /* disable signature check */
break;
default:
case 'c':
@@ -265,10 +275,6 @@ static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table
}
}
rtc_set_memory(s, 0x39, val);
/* Disable check of 0x55AA signature on the last two bytes of
first sector of disk. XXX: make it the default ? */
// rtc_set_memory(s, 0x38, 1);
}
void ioport_set_a20(int enable)
@@ -611,6 +617,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
unsigned long bios_offset, vga_bios_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
int piix3_devfn = -1;
CPUState *env;
NICInfo *nd;
@@ -741,7 +748,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
if (pci_enabled) {
pci_bus = i440fx_init();
piix3_init(pci_bus);
piix3_devfn = piix3_init(pci_bus);
} else {
pci_bus = NULL;
}
@@ -813,7 +820,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
}
if (pci_enabled) {
pci_piix3_ide_init(pci_bus, bs_table);
pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1);
} else {
for(i = 0; i < 2; i++) {
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
@@ -832,14 +839,36 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
cmos_init(ram_size, boot_device, bs_table);
if (pci_enabled && usb_enabled) {
usb_uhci_init(pci_bus, usb_root_ports);
usb_attach(usb_root_ports[0], vm_usb_hub);
usb_uhci_init(pci_bus, piix3_devfn + 2);
}
if (pci_enabled && acpi_enabled) {
piix4_pm_init(pci_bus, piix3_devfn + 3);
}
#if 0
/* ??? Need to figure out some way for the user to
specify SCSI devices. */
if (pci_enabled) {
void *scsi;
BlockDriverState *bdrv;
scsi = lsi_scsi_init(pci_bus, -1);
bdrv = bdrv_new("scsidisk");
bdrv_open(bdrv, "scsi_disk.img", 0);
lsi_scsi_attach(scsi, bdrv, -1);
bdrv = bdrv_new("scsicd");
bdrv_open(bdrv, "scsi_cd.iso", 0);
bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM);
lsi_scsi_attach(scsi, bdrv, -1);
}
#endif
/* must be done after all PCI devices are instanciated */
/* XXX: should be done in the Bochs BIOS */
if (pci_enabled) {
pci_bios_init();
if (acpi_enabled)
acpi_bios_init();
}
}
+54 -1406
View File
File diff suppressed because it is too large. Load diff
+93
View File
@@ -0,0 +1,93 @@
/*
* QEMU Common PCI Host bridge configuration data space access routines.
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* Worker routines for a PCI host controller that uses an {address,data}
register pair to access PCI configuration space. */
typedef struct {
uint32_t config_reg;
PCIBus *bus;
} PCIHostState;
static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
{
PCIHostState *s = opaque;
if (s->config_reg & (1u << 31))
pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
}
static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
{
PCIHostState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
if (s->config_reg & (1u << 31))
pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
}
static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
{
PCIHostState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
if (s->config_reg & (1u << 31))
pci_data_write(s->bus, s->config_reg, val, 4);
}
static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
{
PCIHostState *s = opaque;
if (!(s->config_reg & (1 << 31)))
return 0xff;
return pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
}
static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
{
PCIHostState *s = opaque;
uint32_t val;
if (!(s->config_reg & (1 << 31)))
return 0xffff;
val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
{
PCIHostState *s = opaque;
uint32_t val;
if (!(s->config_reg & (1 << 31)))
return 0xffffffff;
val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
+1789
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -95,7 +95,7 @@ static void pcspk_callback(void *opaque, int free)
int pcspk_audio_init(AudioState *audio)
{
PCSpkState *s = &pcspk_state;
audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8};
audsettings_t as = {PCSPK_SAMPLE_RATE, 1, AUD_FMT_U8, 0};
if (!audio) {
AUD_log(s_spk, "No audio state\n");
@@ -103,7 +103,7 @@ int pcspk_audio_init(AudioState *audio)
}
AUD_register_card(audio, s_spk, &s->card);
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as, 0);
s->voice = AUD_open_out(&s->card, s->voice, s_spk, s, pcspk_callback, &as);
if (!s->voice) {
AUD_log(s_spk, "Could not open voice\n");
return -1;
+624
View File
@@ -0,0 +1,624 @@
/*
* CFI parallel flash with AMD command set emulation
*
* Copyright (c) 2005 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* For now, this code can emulate flashes of 1, 2 or 4 bytes width.
* Supported commands/modes are:
* - flash read
* - flash write
* - flash ID read
* - sector erase
* - chip erase
* - unlock bypass command
* - CFI queries
*
* It does not support flash interleaving.
* It does not implement boot blocs with reduced size
* It does not implement software data protection as found in many real chips
* It does not implement erase suspend/resume commands
* It does not implement multiple sectors erase
*/
#include "vl.h"
//#define PFLASH_DEBUG
#ifdef PFLASH_DEBUG
#define DPRINTF(fmt, args...) \
do { \
printf("PFLASH: " fmt , ##args); \
} while (0)
#else
#define DPRINTF(fmt, args...) do { } while (0)
#endif
struct pflash_t {
BlockDriverState *bs;
target_ulong base;
target_ulong sector_len;
target_ulong total_len;
int width;
int wcycle; /* if 0, the flash is read normally */
int bypass;
int ro;
uint8_t cmd;
uint8_t status;
uint16_t ident[4];
uint8_t cfi_len;
uint8_t cfi_table[0x52];
QEMUTimer *timer;
ram_addr_t off;
int fl_mem;
void *storage;
};
static void pflash_timer (void *opaque)
{
pflash_t *pfl = opaque;
DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
/* Reset flash */
pfl->status ^= 0x80;
if (pfl->bypass) {
pfl->wcycle = 2;
} else {
cpu_register_physical_memory(pfl->base, pfl->total_len,
pfl->off | IO_MEM_ROMD | pfl->fl_mem);
pfl->wcycle = 0;
}
pfl->cmd = 0;
}
static uint32_t pflash_read (pflash_t *pfl, target_ulong offset, int width)
{
target_ulong boff;
uint32_t ret;
uint8_t *p;
DPRINTF("%s: offset %08x\n", __func__, offset);
ret = -1;
offset -= pfl->base;
boff = offset & 0xFF;
if (pfl->width == 2)
boff = boff >> 1;
else if (pfl->width == 4)
boff = boff >> 2;
switch (pfl->cmd) {
default:
/* This should never happen : reset state & treat it as a read*/
DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
pfl->wcycle = 0;
pfl->cmd = 0;
case 0x80:
/* We accept reads during second unlock sequence... */
case 0x00:
flash_read:
/* Flash area read */
p = pfl->storage;
switch (width) {
case 1:
ret = p[offset];
// DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret);
break;
case 2:
#if defined(TARGET_WORDS_BIGENDIAN)
ret = p[offset] << 8;
ret |= p[offset + 1];
#else
ret = p[offset];
ret |= p[offset + 1] << 8;
#endif
// DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret);
break;
case 4:
#if defined(TARGET_WORDS_BIGENDIAN)
ret = p[offset] << 24;
ret |= p[offset + 1] << 16;
ret |= p[offset + 2] << 8;
ret |= p[offset + 3];
#else
ret = p[offset];
ret |= p[offset + 1] << 8;
ret |= p[offset + 1] << 8;
ret |= p[offset + 2] << 16;
ret |= p[offset + 3] << 24;
#endif
// DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret);
break;
}
break;
case 0x90:
/* flash ID read */
switch (boff) {
case 0x00:
case 0x01:
ret = pfl->ident[boff & 0x01];
break;
case 0x02:
ret = 0x00; /* Pretend all sectors are unprotected */
break;
case 0x0E:
case 0x0F:
if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
goto flash_read;
ret = pfl->ident[2 + (boff & 0x01)];
break;
default:
goto flash_read;
}
DPRINTF("%s: ID %d %x\n", __func__, boff, ret);
break;
case 0xA0:
case 0x10:
case 0x30:
/* Status register read */
ret = pfl->status;
DPRINTF("%s: status %x\n", __func__, ret);
/* Toggle bit 6 */
pfl->status ^= 0x40;
break;
case 0x98:
/* CFI query mode */
if (boff > pfl->cfi_len)
ret = 0;
else
ret = pfl->cfi_table[boff];
break;
}
return ret;
}
/* update flash content on disk */
static void pflash_update(pflash_t *pfl, int offset,
int size)
{
int offset_end;
if (pfl->bs) {
offset_end = offset + size;
/* round to sectors */
offset = offset >> 9;
offset_end = (offset_end + 511) >> 9;
bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
offset_end - offset);
}
}
static void pflash_write (pflash_t *pfl, target_ulong offset, uint32_t value,
int width)
{
target_ulong boff;
uint8_t *p;
uint8_t cmd;
/* WARNING: when the memory area is in ROMD mode, the offset is a
ram offset, not a physical address */
if (pfl->wcycle == 0)
offset -= (target_ulong)(long)pfl->storage;
else
offset -= pfl->base;
cmd = value;
DPRINTF("%s: offset %08x %08x %d\n", __func__, offset, value, width);
if (pfl->cmd != 0xA0 && cmd == 0xF0) {
DPRINTF("%s: flash reset asked (%02x %02x)\n",
__func__, pfl->cmd, cmd);
goto reset_flash;
}
/* Set the device in I/O access mode */
cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
boff = offset & (pfl->sector_len - 1);
if (pfl->width == 2)
boff = boff >> 1;
else if (pfl->width == 4)
boff = boff >> 2;
switch (pfl->wcycle) {
case 0:
/* We're in read mode */
check_unlock0:
if (boff == 0x55 && cmd == 0x98) {
enter_CFI_mode:
/* Enter CFI query mode */
pfl->wcycle = 7;
pfl->cmd = 0x98;
return;
}
if (boff != 0x555 || cmd != 0xAA) {
DPRINTF("%s: unlock0 failed %04x %02x %04x\n",
__func__, boff, cmd, 0x555);
goto reset_flash;
}
DPRINTF("%s: unlock sequence started\n", __func__);
break;
case 1:
/* We started an unlock sequence */
check_unlock1:
if (boff != 0x2AA || cmd != 0x55) {
DPRINTF("%s: unlock1 failed %04x %02x\n", __func__, boff, cmd);
goto reset_flash;
}
DPRINTF("%s: unlock sequence done\n", __func__);
break;
case 2:
/* We finished an unlock sequence */
if (!pfl->bypass && boff != 0x555) {
DPRINTF("%s: command failed %04x %02x\n", __func__, boff, cmd);
goto reset_flash;
}
switch (cmd) {
case 0x20:
pfl->bypass = 1;
goto do_bypass;
case 0x80:
case 0x90:
case 0xA0:
pfl->cmd = cmd;
DPRINTF("%s: starting command %02x\n", __func__, cmd);
break;
default:
DPRINTF("%s: unknown command %02x\n", __func__, cmd);
goto reset_flash;
}
break;
case 3:
switch (pfl->cmd) {
case 0x80:
/* We need another unlock sequence */
goto check_unlock0;
case 0xA0:
DPRINTF("%s: write data offset %08x %08x %d\n",
__func__, offset, value, width);
p = pfl->storage;
switch (width) {
case 1:
p[offset] &= value;
pflash_update(pfl, offset, 1);
break;
case 2:
#if defined(TARGET_WORDS_BIGENDIAN)
p[offset] &= value >> 8;
p[offset + 1] &= value;
#else
p[offset] &= value;
p[offset + 1] &= value >> 8;
#endif
pflash_update(pfl, offset, 2);
break;
case 4:
#if defined(TARGET_WORDS_BIGENDIAN)
p[offset] &= value >> 24;
p[offset + 1] &= value >> 16;
p[offset + 2] &= value >> 8;
p[offset + 3] &= value;
#else
p[offset] &= value;
p[offset + 1] &= value >> 8;
p[offset + 2] &= value >> 16;
p[offset + 3] &= value >> 24;
#endif
pflash_update(pfl, offset, 4);
break;
}
pfl->status = 0x00 | ~(value & 0x80);
/* Let's pretend write is immediate */
if (pfl->bypass)
goto do_bypass;
goto reset_flash;
case 0x90:
if (pfl->bypass && cmd == 0x00) {
/* Unlock bypass reset */
goto reset_flash;
}
/* We can enter CFI query mode from autoselect mode */
if (boff == 0x55 && cmd == 0x98)
goto enter_CFI_mode;
/* No break here */
default:
DPRINTF("%s: invalid write for command %02x\n",
__func__, pfl->cmd);
goto reset_flash;
}
case 4:
switch (pfl->cmd) {
case 0xA0:
/* Ignore writes while flash data write is occuring */
/* As we suppose write is immediate, this should never happen */
return;
case 0x80:
goto check_unlock1;
default:
/* Should never happen */
DPRINTF("%s: invalid command state %02x (wc 4)\n",
__func__, pfl->cmd);
goto reset_flash;
}
break;
case 5:
switch (cmd) {
case 0x10:
if (boff != 0x555) {
DPRINTF("%s: chip erase: invalid address %04x\n",
__func__, offset);
goto reset_flash;
}
/* Chip erase */
DPRINTF("%s: start chip erase\n", __func__);
memset(pfl->storage, 0xFF, pfl->total_len);
pfl->status = 0x00;
pflash_update(pfl, 0, pfl->total_len);
/* Let's wait 5 seconds before chip erase is done */
qemu_mod_timer(pfl->timer,
qemu_get_clock(vm_clock) + (ticks_per_sec * 5));
break;
case 0x30:
/* Sector erase */
p = pfl->storage;
offset &= ~(pfl->sector_len - 1);
DPRINTF("%s: start sector erase at %08x\n", __func__, offset);
memset(p + offset, 0xFF, pfl->sector_len);
pflash_update(pfl, offset, pfl->sector_len);
pfl->status = 0x00;
/* Let's wait 1/2 second before sector erase is done */
qemu_mod_timer(pfl->timer,
qemu_get_clock(vm_clock) + (ticks_per_sec / 2));
break;
default:
DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
goto reset_flash;
}
pfl->cmd = cmd;
break;
case 6:
switch (pfl->cmd) {
case 0x10:
/* Ignore writes during chip erase */
return;
case 0x30:
/* Ignore writes during sector erase */
return;
default:
/* Should never happen */
DPRINTF("%s: invalid command state %02x (wc 6)\n",
__func__, pfl->cmd);
goto reset_flash;
}
break;
case 7: /* Special value for CFI queries */
DPRINTF("%s: invalid write in CFI query mode\n", __func__);
goto reset_flash;
default:
/* Should never happen */
DPRINTF("%s: invalid write state (wc 7)\n", __func__);
goto reset_flash;
}
pfl->wcycle++;
return;
/* Reset flash */
reset_flash:
if (pfl->wcycle != 0) {
cpu_register_physical_memory(pfl->base, pfl->total_len,
pfl->off | IO_MEM_ROMD | pfl->fl_mem);
}
pfl->bypass = 0;
pfl->wcycle = 0;
pfl->cmd = 0;
return;
do_bypass:
pfl->wcycle = 2;
pfl->cmd = 0;
return;
}
static uint32_t pflash_readb (void *opaque, target_phys_addr_t addr)
{
return pflash_read(opaque, addr, 1);
}
static uint32_t pflash_readw (void *opaque, target_phys_addr_t addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 2);
}
static uint32_t pflash_readl (void *opaque, target_phys_addr_t addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4);
}
static void pflash_writeb (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1);
}
static void pflash_writew (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2);
}
static void pflash_writel (void *opaque, target_phys_addr_t addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4);
}
static CPUWriteMemoryFunc *pflash_write_ops[] = {
&pflash_writeb,
&pflash_writew,
&pflash_writel,
};
static CPUReadMemoryFunc *pflash_read_ops[] = {
&pflash_readb,
&pflash_readw,
&pflash_readl,
};
/* Count trailing zeroes of a 32 bits quantity */
static int ctz32 (uint32_t n)
{
int ret;
ret = 0;
if (!(n & 0xFFFF)) {
ret += 16;
n = n >> 16;
}
if (!(n & 0xFF)) {
ret += 8;
n = n >> 8;
}
if (!(n & 0xF)) {
ret += 4;
n = n >> 4;
}
if (!(n & 0x3)) {
ret += 2;
n = n >> 2;
}
if (!(n & 0x1)) {
ret++;
n = n >> 1;
}
#if 0 /* This is not necessary as n is never 0 */
if (!n)
ret++;
#endif
return ret;
}
pflash_t *pflash_register (target_ulong base, ram_addr_t off,
BlockDriverState *bs,
target_ulong sector_len, int nb_blocs, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3)
{
pflash_t *pfl;
target_long total_len;
total_len = sector_len * nb_blocs;
/* XXX: to be fixed */
if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
return NULL;
pfl = qemu_mallocz(sizeof(pflash_t));
if (pfl == NULL)
return NULL;
pfl->storage = phys_ram_base + off;
pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, pfl);
pfl->off = off;
cpu_register_physical_memory(base, total_len,
off | pfl->fl_mem | IO_MEM_ROMD);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
}
#if 0 /* XXX: there should be a bit to set up read-only,
* the same way the hardware does (with WP pin).
*/
pfl->ro = 1;
#else
pfl->ro = 0;
#endif
pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
pfl->base = base;
pfl->sector_len = sector_len;
pfl->total_len = total_len;
pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
pfl->status = 0;
pfl->ident[0] = id0;
pfl->ident[1] = id1;
pfl->ident[2] = id2;
pfl->ident[3] = id3;
/* Hardcoded CFI table (mostly from SG29 Spansion flash) */
pfl->cfi_len = 0x52;
/* Standard "QRY" string */
pfl->cfi_table[0x10] = 'Q';
pfl->cfi_table[0x11] = 'R';
pfl->cfi_table[0x12] = 'Y';
/* Command set (AMD/Fujitsu) */
pfl->cfi_table[0x13] = 0x02;
pfl->cfi_table[0x14] = 0x00;
/* Primary extended table address (none) */
pfl->cfi_table[0x15] = 0x00;
pfl->cfi_table[0x16] = 0x00;
/* Alternate command set (none) */
pfl->cfi_table[0x17] = 0x00;
pfl->cfi_table[0x18] = 0x00;
/* Alternate extended table (none) */
pfl->cfi_table[0x19] = 0x00;
pfl->cfi_table[0x1A] = 0x00;
/* Vcc min */
pfl->cfi_table[0x1B] = 0x27;
/* Vcc max */
pfl->cfi_table[0x1C] = 0x36;
/* Vpp min (no Vpp pin) */
pfl->cfi_table[0x1D] = 0x00;
/* Vpp max (no Vpp pin) */
pfl->cfi_table[0x1E] = 0x00;
/* Reserved */
pfl->cfi_table[0x1F] = 0x07;
/* Timeout for min size buffer write (16 µs) */
pfl->cfi_table[0x20] = 0x04;
/* Typical timeout for block erase (512 ms) */
pfl->cfi_table[0x21] = 0x09;
/* Typical timeout for full chip erase (4096 ms) */
pfl->cfi_table[0x22] = 0x0C;
/* Reserved */
pfl->cfi_table[0x23] = 0x01;
/* Max timeout for buffer write */
pfl->cfi_table[0x24] = 0x04;
/* Max timeout for block erase */
pfl->cfi_table[0x25] = 0x0A;
/* Max timeout for chip erase */
pfl->cfi_table[0x26] = 0x0D;
/* Device size */
pfl->cfi_table[0x27] = ctz32(total_len) + 1;
/* Flash device interface (8 & 16 bits) */
pfl->cfi_table[0x28] = 0x02;
pfl->cfi_table[0x29] = 0x00;
/* Max number of bytes in multi-bytes write */
pfl->cfi_table[0x2A] = 0x05;
pfl->cfi_table[0x2B] = 0x00;
/* Number of erase block regions (uniform) */
pfl->cfi_table[0x2C] = 0x01;
/* Erase block region 1 */
pfl->cfi_table[0x2D] = nb_blocs - 1;
pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
pfl->cfi_table[0x2F] = sector_len >> 8;
pfl->cfi_table[0x30] = sector_len >> 16;
return pfl;
}
+419
View File
@@ -0,0 +1,419 @@
/*
* QEMU i440FX/PIIX3 PCI Bridge Emulation
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef uint32_t pci_addr_t;
#include "pci_host.h"
typedef PCIHostState I440FXState;
static void i440fx_addr_writel(void* opaque, uint32_t addr, uint32_t val)
{
I440FXState *s = opaque;
s->config_reg = val;
}
static uint32_t i440fx_addr_readl(void* opaque, uint32_t addr)
{
I440FXState *s = opaque;
return s->config_reg;
}
static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level);
PCIBus *i440fx_init(void)
{
PCIBus *b;
PCIDevice *d;
I440FXState *s;
s = qemu_mallocz(sizeof(I440FXState));
b = pci_register_bus(piix3_set_irq, NULL, 0);
s->bus = b;
register_ioport_write(0xcf8, 4, 4, i440fx_addr_writel, s);
register_ioport_read(0xcf8, 4, 4, i440fx_addr_readl, s);
register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
d = pci_register_device(b, "i440FX", sizeof(PCIDevice), 0,
NULL, NULL);
d->config[0x00] = 0x86; // vendor_id
d->config[0x01] = 0x80;
d->config[0x02] = 0x37; // device_id
d->config[0x03] = 0x12;
d->config[0x08] = 0x02; // revision
d->config[0x0a] = 0x00; // class_sub = host2pci
d->config[0x0b] = 0x06; // class_base = PCI_bridge
d->config[0x0e] = 0x00; // header_type
return b;
}
/* PIIX3 PCI to ISA bridge */
static PCIDevice *piix3_dev;
/* just used for simpler irq handling. */
#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
/* return the global irq number corresponding to a given device irq
pin. We could also use the bus number to have a more precise
mapping. */
static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
{
int slot_addend;
slot_addend = (pci_dev->devfn >> 3) - 1;
return (irq_num + slot_addend) & 3;
}
static inline int get_pci_irq_level(int irq_num)
{
int pic_level;
#if (PCI_IRQ_WORDS == 2)
pic_level = ((pci_irq_levels[irq_num][0] |
pci_irq_levels[irq_num][1]) != 0);
#else
{
int i;
pic_level = 0;
for(i = 0; i < PCI_IRQ_WORDS; i++) {
if (pci_irq_levels[irq_num][i]) {
pic_level = 1;
break;
}
}
}
#endif
return pic_level;
}
static void piix3_set_irq(PCIDevice *pci_dev, void *pic, int irq_num, int level)
{
int irq_index, shift, pic_irq, pic_level;
uint32_t *p;
irq_num = pci_slot_get_pirq(pci_dev, irq_num);
irq_index = pci_dev->irq_index;
p = &pci_irq_levels[irq_num][irq_index >> 5];
shift = (irq_index & 0x1f);
*p = (*p & ~(1 << shift)) | (level << shift);
/* now we change the pic irq level according to the piix irq mappings */
/* XXX: optimize */
pic_irq = piix3_dev->config[0x60 + irq_num];
if (pic_irq < 16) {
/* the pic level is the logical OR of all the PCI irqs mapped
to it */
pic_level = 0;
if (pic_irq == piix3_dev->config[0x60])
pic_level |= get_pci_irq_level(0);
if (pic_irq == piix3_dev->config[0x61])
pic_level |= get_pci_irq_level(1);
if (pic_irq == piix3_dev->config[0x62])
pic_level |= get_pci_irq_level(2);
if (pic_irq == piix3_dev->config[0x63])
pic_level |= get_pci_irq_level(3);
pic_set_irq(pic_irq, pic_level);
}
}
static void piix3_reset(PCIDevice *d)
{
uint8_t *pci_conf = d->config;
pci_conf[0x04] = 0x07; // master, memory and I/O
pci_conf[0x05] = 0x00;
pci_conf[0x06] = 0x00;
pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
pci_conf[0x4c] = 0x4d;
pci_conf[0x4e] = 0x03;
pci_conf[0x4f] = 0x00;
pci_conf[0x60] = 0x80;
pci_conf[0x69] = 0x02;
pci_conf[0x70] = 0x80;
pci_conf[0x76] = 0x0c;
pci_conf[0x77] = 0x0c;
pci_conf[0x78] = 0x02;
pci_conf[0x79] = 0x00;
pci_conf[0x80] = 0x00;
pci_conf[0x82] = 0x00;
pci_conf[0xa0] = 0x08;
pci_conf[0xa0] = 0x08;
pci_conf[0xa2] = 0x00;
pci_conf[0xa3] = 0x00;
pci_conf[0xa4] = 0x00;
pci_conf[0xa5] = 0x00;
pci_conf[0xa6] = 0x00;
pci_conf[0xa7] = 0x00;
pci_conf[0xa8] = 0x0f;
pci_conf[0xaa] = 0x00;
pci_conf[0xab] = 0x00;
pci_conf[0xac] = 0x00;
pci_conf[0xae] = 0x00;
}
int piix3_init(PCIBus *bus)
{
PCIDevice *d;
uint8_t *pci_conf;
d = pci_register_device(bus, "PIIX3", sizeof(PCIDevice),
-1, NULL, NULL);
register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
piix3_dev = d;
pci_conf = d->config;
pci_conf[0x00] = 0x86; // Intel
pci_conf[0x01] = 0x80;
pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
pci_conf[0x03] = 0x70;
pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
piix3_reset(d);
return d->devfn;
}
/***********************************************************/
/* XXX: the following should be moved to the PC BIOS */
static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
{
return cpu_inb(NULL, addr);
}
static void isa_outb(uint32_t val, uint32_t addr)
{
cpu_outb(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
{
return cpu_inw(NULL, addr);
}
static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
{
cpu_outw(NULL, addr, val);
}
static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
{
return cpu_inl(NULL, addr);
}
static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
{
cpu_outl(NULL, addr, val);
}
static uint32_t pci_bios_io_addr;
static uint32_t pci_bios_mem_addr;
/* host irqs corresponding to PCI irqs A-D */
static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 4);
}
static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 2);
}
static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
pci_data_write(s, addr, val, 1);
}
static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 4);
}
static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 2);
}
static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
{
PCIBus *s = d->bus;
addr |= (pci_bus_num(s) << 16) | (d->devfn << 8);
return pci_data_read(s, addr, 1);
}
static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
{
PCIIORegion *r;
uint16_t cmd;
uint32_t ofs;
if ( region_num == PCI_ROM_SLOT ) {
ofs = 0x30;
}else{
ofs = 0x10 + region_num * 4;
}
pci_config_writel(d, ofs, addr);
r = &d->io_regions[region_num];
/* enable memory mappings */
cmd = pci_config_readw(d, PCI_COMMAND);
if ( region_num == PCI_ROM_SLOT )
cmd |= 2;
else if (r->type & PCI_ADDRESS_SPACE_IO)
cmd |= 1;
else
cmd |= 2;
pci_config_writew(d, PCI_COMMAND, cmd);
}
static void pci_bios_init_device(PCIDevice *d)
{
int class;
PCIIORegion *r;
uint32_t *paddr;
int i, pin, pic_irq, vendor_id, device_id;
class = pci_config_readw(d, PCI_CLASS_DEVICE);
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
switch(class) {
case 0x0101:
if (vendor_id == 0x8086 && device_id == 0x7010) {
/* PIIX3 IDE */
pci_config_writew(d, 0x40, 0x8000); // enable IDE0
pci_config_writew(d, 0x42, 0x8000); // enable IDE1
goto default_map;
} else {
/* IDE: we map it as in ISA mode */
pci_set_io_region_addr(d, 0, 0x1f0);
pci_set_io_region_addr(d, 1, 0x3f4);
pci_set_io_region_addr(d, 2, 0x170);
pci_set_io_region_addr(d, 3, 0x374);
}
break;
case 0x0300:
if (vendor_id != 0x1234)
goto default_map;
/* VGA: map frame buffer to default Bochs VBE address */
pci_set_io_region_addr(d, 0, 0xE0000000);
break;
case 0x0800:
/* PIC */
vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
device_id = pci_config_readw(d, PCI_DEVICE_ID);
if (vendor_id == 0x1014) {
/* IBM */
if (device_id == 0x0046 || device_id == 0xFFFF) {
/* MPIC & MPIC2 */
pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
}
}
break;
case 0xff00:
if (vendor_id == 0x0106b &&
(device_id == 0x0017 || device_id == 0x0022)) {
/* macio bridge */
pci_set_io_region_addr(d, 0, 0x80800000);
}
break;
default:
default_map:
/* default memory mappings */
for(i = 0; i < PCI_NUM_REGIONS; i++) {
r = &d->io_regions[i];
if (r->size) {
if (r->type & PCI_ADDRESS_SPACE_IO)
paddr = &pci_bios_io_addr;
else
paddr = &pci_bios_mem_addr;
*paddr = (*paddr + r->size - 1) & ~(r->size - 1);
pci_set_io_region_addr(d, i, *paddr);
*paddr += r->size;
}
}
break;
}
/* map the interrupt */
pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
if (pin != 0) {
pin = pci_slot_get_pirq(d, pin - 1);
pic_irq = pci_irqs[pin];
pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
}
}
/*
* This function initializes the PCI devices as a normal PCI BIOS
* would do. It is provided just in case the BIOS has no support for
* PCI.
*/
void pci_bios_init(void)
{
int i, irq;
uint8_t elcr[2];
pci_bios_io_addr = 0xc000;
pci_bios_mem_addr = 0xf0000000;
/* activate IRQ mappings */
elcr[0] = 0x00;
elcr[1] = 0x00;
for(i = 0; i < 4; i++) {
irq = pci_irqs[i];
/* set to trigger level */
elcr[irq >> 3] |= (1 << (irq & 7));
/* activate irq remapping in PIIX */
pci_config_writeb(piix3_dev, 0x60 + i, irq);
}
isa_outb(elcr[0], 0x4d0);
isa_outb(elcr[1], 0x4d1);
pci_for_each_device(pci_bios_init_device);
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*
* Arm PrimeCell PL050 Kyeboard / Mouse Interface
* Arm PrimeCell PL050 Keyboard / Mouse Interface
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
+11 -9
View File
@@ -415,19 +415,18 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
if (is_heathrow) {
isa_mem_base = 0x80000000;
pci_bus = pci_grackle_init(0xfec00000);
/* Register 2 MB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0xfe000000, 0x00200000, PPC_io_memory);
/* init basic PC hardware */
pic = heathrow_pic_init(&heathrow_pic_mem_index);
set_irq = heathrow_pic_set_irq;
pci_bus = pci_grackle_init(0xfec00000, pic);
vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
pic = heathrow_pic_init(&heathrow_pic_mem_index);
set_irq = heathrow_pic_set_irq;
pci_set_pic(pci_bus, set_irq, pic);
/* XXX: suppress that */
isa_pic = pic_init(pic_irq_request, NULL);
@@ -462,7 +461,6 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
arch_name = "HEATHROW";
} else {
isa_mem_base = 0x80000000;
pci_bus = pci_pmac_init();
/* Register 8 MB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
@@ -472,13 +470,13 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);
pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
set_irq = openpic_set_irq;
pci_bus = pci_pmac_init(pic);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size,
ram_size, vga_ram_size,
vga_bios_offset, vga_bios_size);
pic = openpic_init(NULL, &openpic_mem_index, 1, &env);
set_irq = openpic_set_irq;
pci_set_pic(pci_bus, set_irq, pic);
/* XXX: suppress that */
isa_pic = pic_init(pic_irq_request, NULL);
@@ -508,7 +506,11 @@ static void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
arch_name = "MAC99";
}
if (usb_enabled) {
usb_ohci_init(pci_bus, 3, -1);
}
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
graphic_depth = 15;
+4
View File
@@ -665,6 +665,10 @@ static void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
#endif
if (usb_enabled) {
usb_ohci_init(pci_bus, 3, -1);
}
nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE, 59);
if (nvram == NULL)
return;
+167
View File
@@ -0,0 +1,167 @@
/*
* QEMU PREP PCI host
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef uint32_t pci_addr_t;
#include "pci_host.h"
typedef PCIHostState PREPPCIState;
static void pci_prep_addr_writel(void* opaque, uint32_t addr, uint32_t val)
{
PREPPCIState *s = opaque;
s->config_reg = val;
}
static uint32_t pci_prep_addr_readl(void* opaque, uint32_t addr)
{
PREPPCIState *s = opaque;
return s->config_reg;
}
static inline uint32_t PPC_PCIIO_config(target_phys_addr_t addr)
{
int i;
for(i = 0; i < 11; i++) {
if ((addr & (1 << (11 + i))) != 0)
break;
}
return (addr & 0x7ff) | (i << 11);
}
static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
{
PREPPCIState *s = opaque;
pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 1);
}
static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
{
PREPPCIState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 2);
}
static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
{
PREPPCIState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
pci_data_write(s->bus, PPC_PCIIO_config(addr), val, 4);
}
static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr)
{
PREPPCIState *s = opaque;
uint32_t val;
val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 1);
return val;
}
static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr)
{
PREPPCIState *s = opaque;
uint32_t val;
val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 2);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
{
PREPPCIState *s = opaque;
uint32_t val;
val = pci_data_read(s->bus, PPC_PCIIO_config(addr), 4);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *PPC_PCIIO_write[] = {
&PPC_PCIIO_writeb,
&PPC_PCIIO_writew,
&PPC_PCIIO_writel,
};
static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
&PPC_PCIIO_readb,
&PPC_PCIIO_readw,
&PPC_PCIIO_readl,
};
static void prep_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
{
/* XXX: we do not simulate the hardware - we rely on the BIOS to
set correctly for irq line field */
pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
}
PCIBus *pci_prep_init(void)
{
PREPPCIState *s;
PCIDevice *d;
int PPC_io_memory;
s = qemu_mallocz(sizeof(PREPPCIState));
s->bus = pci_register_bus(prep_set_irq, NULL, 0);
register_ioport_write(0xcf8, 4, 4, pci_prep_addr_writel, s);
register_ioport_read(0xcf8, 4, 4, pci_prep_addr_readl, s);
register_ioport_write(0xcfc, 4, 1, pci_host_data_writeb, s);
register_ioport_write(0xcfc, 4, 2, pci_host_data_writew, s);
register_ioport_write(0xcfc, 4, 4, pci_host_data_writel, s);
register_ioport_read(0xcfc, 4, 1, pci_host_data_readb, s);
register_ioport_read(0xcfc, 4, 2, pci_host_data_readw, s);
register_ioport_read(0xcfc, 4, 4, pci_host_data_readl, s);
PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read,
PPC_PCIIO_write, s);
cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
/* PCI host bridge */
d = pci_register_device(s->bus, "PREP Host Bridge - Motorola Raven",
sizeof(PCIDevice), 0, NULL, NULL);
d->config[0x00] = 0x57; // vendor_id : Motorola
d->config[0x01] = 0x10;
d->config[0x02] = 0x01; // device_id : Raven
d->config[0x03] = 0x48;
d->config[0x08] = 0x00; // revision
d->config[0x0A] = 0x00; // class_sub = pci host
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
return s->bus;
}
+1039 -443
View File
File diff suppressed because it is too large. Load diff
+65 -29
View File
@@ -193,6 +193,31 @@ static void aux_timer (void *opaque)
#define DMA8_AUTO 1
#define DMA8_HIGH 2
static void continue_dma8 (SB16State *s)
{
if (s->freq > 0) {
audsettings_t as;
s->audio_free = 0;
as.freq = s->freq;
as.nchannels = 1 << s->fmt_stereo;
as.fmt = s->fmt;
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->voice,
"sb16",
s,
SB_audio_callback,
&as
);
}
control (s, 1);
}
static void dma_cmd8 (SB16State *s, int mask, int dma_len)
{
s->fmt = AUD_FMT_U8;
@@ -201,7 +226,8 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
s->fmt_signed = 0;
s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
if (-1 == s->time_const) {
s->freq = 11025;
if (s->freq <= 0)
s->freq = 11025;
}
else {
int tmp = (256 - s->time_const);
@@ -239,27 +265,7 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
s->block_size, s->dma_auto, s->fifo, s->highspeed);
if (s->freq) {
audsettings_t as;
s->audio_free = 0;
as.freq = s->freq;
as.nchannels = 1 << s->fmt_stereo;
as.fmt = s->fmt;
s->voice = AUD_open_out (
&s->card,
s->voice,
"sb16",
s,
SB_audio_callback,
&as,
0 /* little endian */
);
}
control (s, 1);
continue_dma8 (s);
speaker (s, 1);
}
@@ -342,6 +348,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
as.freq = s->freq;
as.nchannels = 1 << s->fmt_stereo;
as.fmt = s->fmt;
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
@@ -349,8 +356,7 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
"sb16",
s,
SB_audio_callback,
&as,
0 /* little endian */
&as
);
}
@@ -437,7 +443,7 @@ static void command (SB16State *s, uint8_t cmd)
break;
case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
control (s, 1);
dma_cmd8 (s, DMA8_AUTO, -1);
break;
case 0x20: /* Direct ADC, Juice/PL */
@@ -531,7 +537,9 @@ static void command (SB16State *s, uint8_t cmd)
break;
case 0xd4: /* continue DMA operation. 8bit */
control (s, 1);
/* KQ6 (or maybe Sierras audblst.drv in general) resets
the frequency between halt/continue */
continue_dma8 (s);
break;
case 0xd5: /* halt DMA operation. 16bit */
@@ -765,7 +773,7 @@ static void complete (SB16State *s)
);
}
}
ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
ldebug ("mix silence %d %d %" PRId64 "\n", samples, bytes, ticks);
}
break;
@@ -818,6 +826,33 @@ static void complete (SB16State *s)
return;
}
static void legacy_reset (SB16State *s)
{
audsettings_t as;
s->freq = 11025;
s->fmt_signed = 0;
s->fmt_bits = 8;
s->fmt_stereo = 0;
as.freq = s->freq;
as.nchannels = 1;
as.fmt = AUD_FMT_U8;
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
s->voice,
"sb16",
s,
SB_audio_callback,
&as
);
/* Not sure about that... */
/* AUD_set_active_out (s->voice, 1); */
}
static void reset (SB16State *s)
{
pic_set_irq (s->irq, 0);
@@ -841,6 +876,7 @@ static void reset (SB16State *s)
dsp_out_data(s, 0xaa);
speaker (s, 0);
control (s, 0);
legacy_reset (s);
}
static IO_WRITE_PROTO (dsp_write)
@@ -1335,6 +1371,7 @@ static int SB_load (QEMUFile *f, void *opaque, int version_id)
as.freq = s->freq;
as.nchannels = 1 << s->fmt_stereo;
as.fmt = s->fmt;
as.endianness = 0;
s->voice = AUD_open_out (
&s->card,
@@ -1342,8 +1379,7 @@ static int SB_load (QEMUFile *f, void *opaque, int version_id)
"sb16",
s,
SB_audio_callback,
&as,
0 /* little endian */
&as
);
}
+478
View File
@@ -0,0 +1,478 @@
/*
* SCSI Device emulation
*
* Copyright (c) 2006 CodeSourcery.
* Based on code by Fabrice Bellard
*
* Written by Paul Brook
*
* This code is licenced under the LGPL.
*/
//#define DEBUG_SCSI
#ifdef DEBUG_SCSI
#define DPRINTF(fmt, args...) \
do { printf("scsi-disk: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#endif
#define BADF(fmt, args...) \
do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
#include "vl.h"
#define SENSE_NO_SENSE 0
#define SENSE_ILLEGAL_REQUEST 5
struct SCSIDevice
{
int command;
uint32_t tag;
BlockDriverState *bdrv;
/* The qemu block layer uses a fixed 512 byte sector size.
This is the number of 512 byte blocks in a single scsi sector. */
int cluster_size;
/* When transfering data buf_pos and buf_len contain a partially
transferred block of data (or response to a command), and
sector/sector_count identify any remaining sectors.
Both sector and sector_count are in terms of qemu 512 byte blocks. */
/* ??? We should probably keep track of whether the data trasfer is
a read or a write. Currently we rely on the host getting it right. */
int sector;
int sector_count;
int buf_pos;
int buf_len;
int sense;
char buf[512];
scsi_completionfn completion;
void *opaque;
};
static void scsi_command_complete(SCSIDevice *s, int sense)
{
s->sense = sense;
s->completion(s->opaque, s->tag, sense);
}
/* Read data from a scsi device. Returns nonzero on failure. */
int scsi_read_data(SCSIDevice *s, uint8_t *data, uint32_t len)
{
uint32_t n;
DPRINTF("Read %d (%d/%d)\n", len, s->buf_len, s->sector_count);
if (s->buf_len == 0 && s->sector_count == 0)
return 1;
if (s->buf_len) {
n = s->buf_len;
if (n > len)
n = len;
memcpy(data, s->buf + s->buf_pos, n);
s->buf_pos += n;
s->buf_len -= n;
data += n;
len -= n;
if (s->buf_len == 0)
s->buf_pos = 0;
}
n = len / 512;
if (n > s->sector_count)
n = s->sector_count;
if (n != 0) {
bdrv_read(s->bdrv, s->sector, data, n);
data += n * 512;
len -= n * 512;
s->sector += n;
s->sector_count -= n;
}
if (len && s->sector_count) {
bdrv_read(s->bdrv, s->sector, s->buf, 1);
s->sector++;
s->sector_count--;
s->buf_pos = 0;
s->buf_len = 512;
/* Recurse to complete the partial read. */
return scsi_read_data(s, data, len);
}
if (len != 0)
return 1;
if (s->buf_len == 0 && s->sector_count == 0)
scsi_command_complete(s, SENSE_NO_SENSE);
return 0;
}
/* Read data to a scsi device. Returns nonzero on failure. */
int scsi_write_data(SCSIDevice *s, uint8_t *data, uint32_t len)
{
uint32_t n;
DPRINTF("Write %d (%d/%d)\n", len, s->buf_len, s->sector_count);
if (s->buf_pos != 0) {
BADF("Bad state on write\n");
return 1;
}
if (s->sector_count == 0)
return 1;
if (s->buf_len != 0 || len < 512) {
n = 512 - s->buf_len;
if (n > len)
n = len;
memcpy(s->buf + s->buf_len, data, n);
data += n;
s->buf_len += n;
len -= n;
if (s->buf_len == 512) {
/* A full sector has been accumulated. Write it to disk. */
bdrv_write(s->bdrv, s->sector, s->buf, 1);
s->buf_len = 0;
s->sector++;
s->sector_count--;
}
}
n = len / 512;
if (n > s->sector_count)
n = s->sector_count;
if (n != 0) {
bdrv_write(s->bdrv, s->sector, data, n);
data += n * 512;
len -= n * 512;
s->sector += n;
s->sector_count -= n;
}
if (len >= 512)
return 1;
if (len && s->sector_count) {
/* Recurse to complete the partial write. */
return scsi_write_data(s, data, len);
}
if (len != 0)
return 1;
if (s->sector_count == 0)
scsi_command_complete(s, SENSE_NO_SENSE);
return 0;
}
/* Execute a scsi command. Returns the length of the data expected by the
command. This will be Positive for data transfers from the device
(eg. disk reads), negative for transfers to the device (eg. disk writes),
and zero if the command does not transfer any data. */
int32_t scsi_send_command(SCSIDevice *s, uint32_t tag, uint8_t *buf, int lun)
{
int64_t nb_sectors;
uint32_t lba;
uint32_t len;
int cmdlen;
int is_write;
s->command = buf[0];
s->tag = tag;
s->sector_count = 0;
s->buf_pos = 0;
s->buf_len = 0;
is_write = 0;
DPRINTF("Command: 0x%02x", buf[0]);
switch (s->command >> 5) {
case 0:
lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16);
len = buf[4];
cmdlen = 6;
break;
case 1:
case 2:
lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
len = buf[8] | (buf[7] << 8);
cmdlen = 10;
break;
case 4:
lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24);
cmdlen = 16;
break;
case 5:
lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24);
len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24);
cmdlen = 12;
break;
default:
BADF("Unsupported command length, command %x\n", s->command);
goto fail;
}
#ifdef DEBUG_SCSI
{
int i;
for (i = 1; i < cmdlen; i++) {
printf(" 0x%02x", buf[i]);
}
printf("\n");
}
#endif
if (lun || buf[1] >> 5) {
/* Only LUN 0 supported. */
DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5);
goto fail;
}
switch (s->command) {
case 0x0:
DPRINTF("Test Unit Ready\n");
break;
case 0x03:
DPRINTF("Request Sense (len %d)\n", len);
if (len < 4)
goto fail;
memset(buf, 0, 4);
s->buf[0] = 0xf0;
s->buf[1] = 0;
s->buf[2] = s->sense;
s->buf_len = 4;
break;
case 0x12:
DPRINTF("Inquiry (len %d)\n", len);
if (len < 36) {
BADF("Inquiry buffer too small (%d)\n", len);
}
memset(s->buf, 0, 36);
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
s->buf[0] = 5;
s->buf[1] = 0x80;
memcpy(&s->buf[16], "QEMU CD-ROM ", 16);
} else {
s->buf[0] = 0;
memcpy(&s->buf[16], "QEMU HARDDISK ", 16);
}
memcpy(&s->buf[8], "QEMU ", 8);
memcpy(&s->buf[32], QEMU_VERSION, 4);
/* Identify device as SCSI-3 rev 1.
Some later commands are also implemented. */
s->buf[2] = 3;
s->buf[3] = 2; /* Format 2 */
s->buf[4] = 32;
s->buf_len = 36;
break;
case 0x16:
DPRINTF("Reserve(6)\n");
if (buf[1] & 1)
goto fail;
break;
case 0x17:
DPRINTF("Release(6)\n");
if (buf[1] & 1)
goto fail;
break;
case 0x1a:
case 0x5a:
{
char *p;
int page;
page = buf[2] & 0x3f;
DPRINTF("Mode Sense (page %d, len %d)\n", page, len);
p = s->buf;
memset(p, 0, 4);
s->buf[1] = 0; /* Default media type. */
s->buf[3] = 0; /* Block descriptor length. */
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
s->buf[2] = 0x80; /* Readonly. */
}
p += 4;
if ((page == 8 || page == 0x3f)) {
/* Caching page. */
p[0] = 8;
p[1] = 0x12;
p[2] = 4; /* WCE */
p += 19;
}
if ((page == 0x3f || page == 0x2a)
&& (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) {
/* CD Capabilities and Mechanical Status page. */
p[0] = 0x2a;
p[1] = 0x14;
p[2] = 3; // CD-R & CD-RW read
p[3] = 0; // Writing not supported
p[4] = 0x7f; /* Audio, composite, digital out,
mode 2 form 1&2, multi session */
p[5] = 0xff; /* CD DA, DA accurate, RW supported,
RW corrected, C2 errors, ISRC,
UPC, Bar code */
p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0);
/* Locking supported, jumper present, eject, tray */
p[7] = 0; /* no volume & mute control, no
changer */
p[8] = (50 * 176) >> 8; // 50x read speed
p[9] = (50 * 176) & 0xff;
p[10] = 0 >> 8; // No volume
p[11] = 0 & 0xff;
p[12] = 2048 >> 8; // 2M buffer
p[13] = 2048 & 0xff;
p[14] = (16 * 176) >> 8; // 16x read speed current
p[15] = (16 * 176) & 0xff;
p[18] = (16 * 176) >> 8; // 16x write speed
p[19] = (16 * 176) & 0xff;
p[20] = (16 * 176) >> 8; // 16x write speed current
p[21] = (16 * 176) & 0xff;
p += 21;
}
s->buf_len = p - s->buf;
s->buf[0] = s->buf_len - 4;
if (s->buf_len > len)
s->buf_len = len;
}
break;
case 0x1b:
DPRINTF("Start Stop Unit\n");
break;
case 0x1e:
DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3);
bdrv_set_locked(s->bdrv, buf[4] & 1);
break;
case 0x25:
DPRINTF("Read Capacity\n");
/* The normal LEN field for this command is zero. */
memset(s->buf, 0, 8);
bdrv_get_geometry(s->bdrv, &nb_sectors);
s->buf[0] = (nb_sectors >> 24) & 0xff;
s->buf[1] = (nb_sectors >> 16) & 0xff;
s->buf[2] = (nb_sectors >> 8) & 0xff;
s->buf[3] = nb_sectors & 0xff;
s->buf[4] = 0;
s->buf[5] = 0;
s->buf[6] = s->cluster_size * 2;
s->buf[7] = 0;
s->buf_len = 8;
break;
case 0x08:
case 0x28:
DPRINTF("Read (sector %d, count %d)\n", lba, len);
s->sector = lba * s->cluster_size;
s->sector_count = len * s->cluster_size;
break;
case 0x0a:
case 0x2a:
DPRINTF("Write (sector %d, count %d)\n", lba, len);
s->sector = lba * s->cluster_size;
s->sector_count = len * s->cluster_size;
is_write = 1;
break;
case 0x35:
DPRINTF("Syncronise cache (sector %d, count %d)\n", lba, len);
bdrv_flush(s->bdrv);
break;
case 0x43:
{
int start_track, format, msf, toclen;
msf = buf[1] & 2;
format = buf[2] & 0xf;
start_track = buf[6];
bdrv_get_geometry(s->bdrv, &nb_sectors);
DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
switch(format) {
case 0:
toclen = cdrom_read_toc(nb_sectors, s->buf, msf, start_track);
break;
case 1:
/* multi session : only a single session defined */
toclen = 12;
memset(s->buf, 0, 12);
s->buf[1] = 0x0a;
s->buf[2] = 0x01;
s->buf[3] = 0x01;
break;
case 2:
toclen = cdrom_read_toc_raw(nb_sectors, s->buf, msf, start_track);
break;
default:
goto error_cmd;
}
if (toclen > 0) {
if (len > toclen)
len = toclen;
s->buf_len = len;
break;
}
error_cmd:
DPRINTF("Read TOC error\n");
goto fail;
}
case 0x46:
DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len);
memset(s->buf, 0, 8);
/* ??? This shoud probably return much more information. For now
just return the basic header indicating the CD-ROM profile. */
s->buf[7] = 8; // CD-ROM
s->buf_len = 8;
break;
case 0x56:
DPRINTF("Reserve(10)\n");
if (buf[1] & 3)
goto fail;
break;
case 0x57:
DPRINTF("Release(10)\n");
if (buf[1] & 3)
goto fail;
break;
case 0xa0:
DPRINTF("Report LUNs (len %d)\n", len);
if (len < 16)
goto fail;
memset(s->buf, 0, 16);
s->buf[3] = 8;
s->buf_len = 16;
break;
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
fail:
scsi_command_complete(s, SENSE_ILLEGAL_REQUEST);
return 0;
}
if (s->sector_count == 0 && s->buf_len == 0) {
scsi_command_complete(s, SENSE_NO_SENSE);
}
len = s->sector_count * 512 + s->buf_len;
return is_write ? -len : len;
}
void scsi_disk_destroy(SCSIDevice *s)
{
bdrv_close(s->bdrv);
qemu_free(s);
}
SCSIDevice *scsi_disk_init(BlockDriverState *bdrv,
scsi_completionfn completion,
void *opaque)
{
SCSIDevice *s;
s = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
s->bdrv = bdrv;
s->completion = completion;
s->opaque = opaque;
if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) {
s->cluster_size = 4;
} else {
s->cluster_size = 1;
}
return s;
}
+1 -1
View File
@@ -124,7 +124,7 @@ static void start_timer0(SH7750State * s)
s->periph_freq);
if (next == now)
next = now + 1;
fprintf(stderr, "now=%016llx, next=%016llx\n", now, next);
fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
fprintf(stderr, "timer will underflow in %f seconds\n",
(float) (next - now) / (float) ticks_per_sec);
+1 -1
View File
@@ -203,7 +203,7 @@ void slavio_irq_info(void *opaque)
for (i = 0; i < 32; i++) {
count = s->irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
term_printf("%2d: %" PRId64 "\n", i, count);
}
#endif
}
+1 -1
View File
@@ -100,7 +100,7 @@ static void slavio_timer_get_out(SLAVIO_TIMERState *s)
// Convert remaining counter ticks to CPU ticks
s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
DPRINTF("irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
DPRINTF("irq %d limit %d reached %d d %" PRId64 " count %d s->c %x diff %" PRId64 " stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
if (s->mode != 1)
pic_set_irq_cpu(s->irq, out, s->cpu);
+7 -7
View File
@@ -28,8 +28,7 @@
#define INITRD_LOAD_ADDR 0x00800000
#define PROM_SIZE_MAX (256 * 1024)
#define PROM_ADDR 0xffd00000
#define PROM_FILENAMEB "proll.bin"
#define PROM_FILENAMEE "proll.elf"
#define PROM_FILENAME "openbios-sparc32"
#define PHYS_JJ_EEPROM 0x71200000 /* m48t08 */
#define PHYS_JJ_IDPROM_OFF 0x1FD8
#define PHYS_JJ_EEPROM_SIZE 0x2000
@@ -183,6 +182,11 @@ void pic_set_irq(int irq, int level)
slavio_pic_set_irq(slavio_intctl, irq, level);
}
void pic_set_irq_new(void *opaque, int irq, int level)
{
pic_set_irq(irq, level);
}
void pic_set_irq_cpu(int irq, int level, unsigned int cpu)
{
slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
@@ -268,12 +272,8 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
(PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
ret = load_elf(buf, 0, NULL);
if (ret < 0) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_image(buf, phys_ram_base + prom_offset);
}
if (ret < 0) {
fprintf(stderr, "qemu: could not load prom '%s'\n",
buf);
+5 -13
View File
@@ -27,13 +27,12 @@
#define KERNEL_LOAD_ADDR 0x00404000
#define CMDLINE_ADDR 0x003ff000
#define INITRD_LOAD_ADDR 0x00300000
#define PROM_SIZE_MAX (256 * 1024)
#define PROM_SIZE_MAX (512 * 1024)
#define PROM_ADDR 0x1fff0000000ULL
#define APB_SPECIAL_BASE 0x1fe00000000ULL
#define APB_MEM_BASE 0x1ff00000000ULL
#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
#define PROM_FILENAMEB "proll-sparc64.bin"
#define PROM_FILENAMEE "proll-sparc64.elf"
#define PROM_FILENAME "openbios-sparc64"
#define NVRAM_SIZE 0x2000
/* TSC handling */
@@ -282,12 +281,8 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
(PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
ret = load_elf(buf, 0, NULL);
if (ret < 0) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_image(buf, phys_ram_base + prom_offset);
}
if (ret < 0) {
fprintf(stderr, "qemu: could not load prom '%s'\n",
buf);
@@ -329,12 +324,9 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
}
}
}
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE);
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
isa_mem_base = VGA_BASE;
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size);
//pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size);
pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
+261
View File
@@ -0,0 +1,261 @@
/*
* QEMU Uninorth PCI host (for all Mac99 and newer machines)
*
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
typedef target_phys_addr_t pci_addr_t;
#include "pci_host.h"
typedef PCIHostState UNINState;
static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
UNINState *s = opaque;
int i;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
for (i = 11; i < 32; i++) {
if ((val & (1 << i)) != 0)
break;
}
#if 0
s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
#else
s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11);
#endif
}
static uint32_t pci_unin_main_config_readl (void *opaque,
target_phys_addr_t addr)
{
UNINState *s = opaque;
uint32_t val;
int devfn;
devfn = (s->config_reg >> 8) & 0xFF;
val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
&pci_unin_main_config_writel,
&pci_unin_main_config_writel,
&pci_unin_main_config_writel,
};
static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
&pci_unin_main_config_readl,
&pci_unin_main_config_readl,
&pci_unin_main_config_readl,
};
static CPUWriteMemoryFunc *pci_unin_main_write[] = {
&pci_host_data_writeb,
&pci_host_data_writew,
&pci_host_data_writel,
};
static CPUReadMemoryFunc *pci_unin_main_read[] = {
&pci_host_data_readb,
&pci_host_data_readw,
&pci_host_data_readl,
};
#if 0
static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
UNINState *s = opaque;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
s->config_reg = 0x80000000 | (val & ~0x00000001);
}
static uint32_t pci_unin_config_readl (void *opaque,
target_phys_addr_t addr)
{
UNINState *s = opaque;
uint32_t val;
val = (s->config_reg | 0x00000001) & ~0x80000000;
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_unin_config_write[] = {
&pci_unin_config_writel,
&pci_unin_config_writel,
&pci_unin_config_writel,
};
static CPUReadMemoryFunc *pci_unin_config_read[] = {
&pci_unin_config_readl,
&pci_unin_config_readl,
&pci_unin_config_readl,
};
static CPUWriteMemoryFunc *pci_unin_write[] = {
&pci_host_pci_writeb,
&pci_host_pci_writew,
&pci_host_pci_writel,
};
static CPUReadMemoryFunc *pci_unin_read[] = {
&pci_host_pci_readb,
&pci_host_pci_readw,
&pci_host_pci_readl,
};
#endif
static void pci_unin_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
{
openpic_set_irq(pic, d->config[PCI_INTERRUPT_LINE], level);
}
PCIBus *pci_pmac_init(void *pic)
{
UNINState *s;
PCIDevice *d;
int pci_mem_config, pci_mem_data;
/* Use values found on a real PowerMac */
/* Uninorth main bus */
s = qemu_mallocz(sizeof(UNINState));
s->bus = pci_register_bus(pci_unin_set_irq, NULL, 11 << 3);
pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read,
pci_unin_main_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
pci_unin_main_write, s);
cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
d = pci_register_device(s->bus, "Uni-north main", sizeof(PCIDevice),
11 << 3, NULL, NULL);
d->config[0x00] = 0x6b; // vendor_id : Apple
d->config[0x01] = 0x10;
d->config[0x02] = 0x1F; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x00; // revision
d->config[0x0A] = 0x00; // class_sub = pci host
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
/* pci-to-pci bridge */
d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
NULL, NULL);
d->config[0x00] = 0x11; // vendor_id : TI
d->config[0x01] = 0x10;
d->config[0x02] = 0x26; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x05; // revision
d->config[0x0A] = 0x04; // class_sub = pci2pci
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x20; // latency_timer
d->config[0x0E] = 0x01; // header_type
d->config[0x18] = 0x01; // primary_bus
d->config[0x19] = 0x02; // secondary_bus
d->config[0x1A] = 0x02; // subordinate_bus
d->config[0x1B] = 0x20; // secondary_latency_timer
d->config[0x1C] = 0x11; // io_base
d->config[0x1D] = 0x01; // io_limit
d->config[0x20] = 0x00; // memory_base
d->config[0x21] = 0x80;
d->config[0x22] = 0x00; // memory_limit
d->config[0x23] = 0x80;
d->config[0x24] = 0x01; // prefetchable_memory_base
d->config[0x25] = 0x80;
d->config[0x26] = 0xF1; // prefectchable_memory_limit
d->config[0x27] = 0x7F;
// d->config[0x34] = 0xdc // capabilities_pointer
#endif
#if 0 // XXX: not needed for now
/* Uninorth AGP bus */
s = &pci_bridge[1];
pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
pci_unin_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
pci_unin_write, s);
cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
NULL, NULL);
d->config[0x00] = 0x6b; // vendor_id : Apple
d->config[0x01] = 0x10;
d->config[0x02] = 0x20; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x00; // revision
d->config[0x0A] = 0x00; // class_sub = pci host
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
// d->config[0x34] = 0x80; // capabilities_pointer
#endif
#if 0 // XXX: not needed for now
/* Uninorth internal bus */
s = &pci_bridge[2];
pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
pci_unin_config_write, s);
pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
pci_unin_write, s);
cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);
d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
3, 11 << 3, NULL, NULL);
d->config[0x00] = 0x6b; // vendor_id : Apple
d->config[0x01] = 0x10;
d->config[0x02] = 0x1E; // device_id
d->config[0x03] = 0x00;
d->config[0x08] = 0x00; // revision
d->config[0x0A] = 0x00; // class_sub = pci host
d->config[0x0B] = 0x06; // class_base = PCI_bridge
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
d->config[0x0E] = 0x00; // header_type
d->config[0x34] = 0x00; // capabilities_pointer
#endif
return s->bus;
}
+14
View File
@@ -500,6 +500,14 @@ static int usb_mouse_handle_data(USBDevice *dev, int pid,
return ret;
}
static void usb_mouse_handle_destroy(USBDevice *dev)
{
USBMouseState *s = (USBMouseState *)dev;
qemu_add_mouse_event_handler(NULL, NULL, 0);
qemu_free(s);
}
USBDevice *usb_tablet_init(void)
{
USBMouseState *s;
@@ -513,8 +521,11 @@ USBDevice *usb_tablet_init(void)
s->dev.handle_reset = usb_mouse_handle_reset;
s->dev.handle_control = usb_mouse_handle_control;
s->dev.handle_data = usb_mouse_handle_data;
s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_TABLET;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
return (USBDevice *)s;
}
@@ -531,7 +542,10 @@ USBDevice *usb_mouse_init(void)
s->dev.handle_reset = usb_mouse_handle_reset;
s->dev.handle_control = usb_mouse_handle_control;
s->dev.handle_data = usb_mouse_handle_data;
s->dev.handle_destroy = usb_mouse_handle_destroy;
s->kind = USB_MOUSE;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
return (USBDevice *)s;
}
+20 -6
View File
@@ -152,7 +152,7 @@ static const uint8_t qemu_hub_config_descriptor[] = {
static const uint8_t qemu_hub_hub_descriptor[] =
{
0x09, /* u8 bLength; */
0x00, /* u8 bLength; patched in later */
0x29, /* u8 bDescriptorType; Hub-descriptor */
0x00, /* u8 bNbrPorts; (patched later) */
0x0a, /* u16 wHubCharacteristics; */
@@ -179,6 +179,9 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
else
port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
port->port.dev = dev;
/* send the attach message */
dev->handle_packet(dev,
USB_MSG_ATTACH, 0, 0, NULL, 0);
} else {
dev = port->port.dev;
if (dev) {
@@ -188,6 +191,9 @@ static void usb_hub_attach(USBPort *port1, USBDevice *dev)
port->wPortStatus &= ~PORT_STAT_ENABLE;
port->wPortChange |= PORT_STAT_C_ENABLE;
}
/* send the detach message */
dev->handle_packet(dev,
USB_MSG_DETACH, 0, 0, NULL, 0);
port->port.dev = NULL;
}
}
@@ -417,6 +423,7 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
}
ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
data[0] = ret;
break;
}
default:
@@ -516,7 +523,14 @@ static int usb_hub_handle_packet(USBDevice *dev, int pid,
return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
}
USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports)
static void usb_hub_handle_destroy(USBDevice *dev)
{
USBHubState *s = (USBHubState *)dev;
qemu_free(s);
}
USBDevice *usb_hub_init(int nb_ports)
{
USBHubState *s;
USBHubPort *port;
@@ -534,16 +548,16 @@ USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports)
s->dev.handle_reset = usb_hub_handle_reset;
s->dev.handle_control = usb_hub_handle_control;
s->dev.handle_data = usb_hub_handle_data;
s->dev.handle_destroy = usb_hub_handle_destroy;
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub");
s->nb_ports = nb_ports;
for(i = 0; i < s->nb_ports; i++) {
port = &s->ports[i];
qemu_register_usb_port(&port->port, s, i, usb_hub_attach);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
port->port.attach = usb_hub_attach;
port->port.opaque = s;
port->port.index = i;
usb_ports[i] = &port->port;
}
return (USBDevice *)s;
}
+402
View File
@@ -0,0 +1,402 @@
/*
* USB Mass Storage Device emulation
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the LGPL.
*/
#include "vl.h"
//#define DEBUG_MSD
#ifdef DEBUG_MSD
#define DPRINTF(fmt, args...) \
do { printf("usb-msd: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while(0)
#endif
/* USB requests. */
#define MassStorageReset 0xff
#define GetMaxLun 0xfe
enum USBMSDMode {
USB_MSDM_CBW, /* Command Block. */
USB_MSDM_DATAOUT, /* Tranfer data to device. */
USB_MSDM_DATAIN, /* Transfer data from device. */
USB_MSDM_CSW /* Command Status. */
};
typedef struct {
USBDevice dev;
enum USBMSDMode mode;
uint32_t data_len;
uint32_t tag;
SCSIDevice *scsi_dev;
int result;
} MSDState;
static const uint8_t qemu_msd_dev_descriptor[] = {
0x12, /* u8 bLength; */
0x01, /* u8 bDescriptorType; Device */
0x10, 0x00, /* u16 bcdUSB; v1.0 */
0x00, /* u8 bDeviceClass; */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
/* Vendor and product id are arbitrary. */
0x00, 0x00, /* u16 idVendor; */
0x00, 0x00, /* u16 idProduct; */
0x00, 0x00, /* u16 bcdDevice */
0x01, /* u8 iManufacturer; */
0x02, /* u8 iProduct; */
0x03, /* u8 iSerialNumber; */
0x01 /* u8 bNumConfigurations; */
};
static const uint8_t qemu_msd_config_descriptor[] = {
/* one configuration */
0x09, /* u8 bLength; */
0x02, /* u8 bDescriptorType; Configuration */
0x20, 0x00, /* u16 wTotalLength; */
0x01, /* u8 bNumInterfaces; (1) */
0x01, /* u8 bConfigurationValue; */
0x00, /* u8 iConfiguration; */
0xc0, /* u8 bmAttributes;
Bit 7: must be set,
6: Self-powered,
5: Remote wakeup,
4..0: resvd */
0x00, /* u8 MaxPower; */
/* one interface */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x00, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x02, /* u8 if_bNumEndpoints; */
0x08, /* u8 if_bInterfaceClass; MASS STORAGE */
0x06, /* u8 if_bInterfaceSubClass; SCSI */
0x50, /* u8 if_bInterfaceProtocol; Bulk Only */
0x00, /* u8 if_iInterface; */
/* Bulk-In endpoint */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
0x02, /* u8 ep_bmAttributes; Bulk */
0x40, 0x00, /* u16 ep_wMaxPacketSize; */
0x00, /* u8 ep_bInterval; */
/* Bulk-Out endpoint */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
0x02, /* u8 ep_bmAttributes; Bulk */
0x40, 0x00, /* u16 ep_wMaxPacketSize; */
0x00 /* u8 ep_bInterval; */
};
static void usb_msd_command_complete(void *opaque, uint32_t tag, int fail)
{
MSDState *s = (MSDState *)opaque;
DPRINTF("Command complete\n");
s->result = fail;
s->mode = USB_MSDM_CSW;
}
static void usb_msd_handle_reset(USBDevice *dev)
{
MSDState *s = (MSDState *)dev;
DPRINTF("Reset\n");
s->mode = USB_MSDM_CBW;
}
static int usb_msd_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
MSDState *s = (MSDState *)dev;
int ret = 0;
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
(dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
data[1] = 0x00;
ret = 2;
break;
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP) {
dev->remote_wakeup = 0;
} else {
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_FEATURE:
if (value == USB_DEVICE_REMOTE_WAKEUP) {
dev->remote_wakeup = 1;
} else {
goto fail;
}
ret = 0;
break;
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
dev->addr = value;
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
switch(value >> 8) {
case USB_DT_DEVICE:
memcpy(data, qemu_msd_dev_descriptor,
sizeof(qemu_msd_dev_descriptor));
ret = sizeof(qemu_msd_dev_descriptor);
break;
case USB_DT_CONFIG:
memcpy(data, qemu_msd_config_descriptor,
sizeof(qemu_msd_config_descriptor));
ret = sizeof(qemu_msd_config_descriptor);
break;
case USB_DT_STRING:
switch(value & 0xff) {
case 0:
/* language ids */
data[0] = 4;
data[1] = 3;
data[2] = 0x09;
data[3] = 0x04;
ret = 4;
break;
case 1:
/* vendor description */
ret = set_usb_string(data, "QEMU " QEMU_VERSION);
break;
case 2:
/* product description */
ret = set_usb_string(data, "QEMU USB HARDDRIVE");
break;
case 3:
/* serial number */
ret = set_usb_string(data, "1");
break;
default:
goto fail;
}
break;
default:
goto fail;
}
break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
break;
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
ret = 0;
break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == 0 && index != 0x81) { /* clear ep halt */
goto fail;
}
ret = 0;
break;
/* Class specific requests. */
case MassStorageReset:
/* Reset state ready for the next CBW. */
s->mode = USB_MSDM_CBW;
ret = 0;
break;
case GetMaxLun:
data[0] = 0;
ret = 1;
break;
default:
fail:
ret = USB_RET_STALL;
break;
}
return ret;
}
struct usb_msd_cbw {
uint32_t sig;
uint32_t tag;
uint32_t data_len;
uint8_t flags;
uint8_t lun;
uint8_t cmd_len;
uint8_t cmd[16];
};
struct usb_msd_csw {
uint32_t sig;
uint32_t tag;
uint32_t residue;
uint8_t status;
};
static int usb_msd_handle_data(USBDevice *dev, int pid, uint8_t devep,
uint8_t *data, int len)
{
MSDState *s = (MSDState *)dev;
int ret = 0;
struct usb_msd_cbw cbw;
struct usb_msd_csw csw;
switch (pid) {
case USB_TOKEN_OUT:
if (devep != 2)
goto fail;
switch (s->mode) {
case USB_MSDM_CBW:
if (len != 31) {
fprintf(stderr, "usb-msd: Bad CBW size");
goto fail;
}
memcpy(&cbw, data, 31);
if (le32_to_cpu(cbw.sig) != 0x43425355) {
fprintf(stderr, "usb-msd: Bad signature %08x\n",
le32_to_cpu(cbw.sig));
goto fail;
}
DPRINTF("Command on LUN %d\n", cbw.lun);
if (cbw.lun != 0) {
fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
goto fail;
}
s->tag = le32_to_cpu(cbw.tag);
s->data_len = le32_to_cpu(cbw.data_len);
if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
} else if (cbw.flags & 0x80) {
s->mode = USB_MSDM_DATAIN;
} else {
s->mode = USB_MSDM_DATAOUT;
}
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
s->tag, cbw.flags, cbw.cmd_len, s->data_len);
scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0);
ret = len;
break;
case USB_MSDM_DATAOUT:
DPRINTF("Data out %d/%d\n", len, s->data_len);
if (len > s->data_len)
goto fail;
if (scsi_write_data(s->scsi_dev, data, len))
goto fail;
s->data_len -= len;
if (s->data_len == 0)
s->mode = USB_MSDM_CSW;
ret = len;
break;
default:
DPRINTF("Unexpected write (len %d)\n", len);
goto fail;
}
break;
case USB_TOKEN_IN:
if (devep != 1)
goto fail;
switch (s->mode) {
case USB_MSDM_CSW:
DPRINTF("Command status %d tag 0x%x, len %d\n",
s->result, s->tag, len);
if (len < 13)
goto fail;
csw.sig = cpu_to_le32(0x53425355);
csw.tag = cpu_to_le32(s->tag);
csw.residue = 0;
csw.status = s->result;
memcpy(data, &csw, 13);
ret = 13;
s->mode = USB_MSDM_CBW;
break;
case USB_MSDM_DATAIN:
DPRINTF("Data in %d/%d\n", len, s->data_len);
if (len > s->data_len)
len = s->data_len;
if (scsi_read_data(s->scsi_dev, data, len))
goto fail;
s->data_len -= len;
if (s->data_len == 0)
s->mode = USB_MSDM_CSW;
ret = len;
break;
default:
DPRINTF("Unexpected read (len %d)\n", len);
goto fail;
}
break;
default:
DPRINTF("Bad token\n");
fail:
ret = USB_RET_STALL;
break;
}
return ret;
}
static void usb_msd_handle_destroy(USBDevice *dev)
{
MSDState *s = (MSDState *)dev;
scsi_disk_destroy(s->scsi_dev);
qemu_free(s);
}
USBDevice *usb_msd_init(const char *filename)
{
MSDState *s;
BlockDriverState *bdrv;
s = qemu_mallocz(sizeof(MSDState));
if (!s)
return NULL;
bdrv = bdrv_new("usb");
bdrv_open(bdrv, filename, 0);
s->dev.speed = USB_SPEED_FULL;
s->dev.handle_packet = usb_generic_handle_packet;
s->dev.handle_reset = usb_msd_handle_reset;
s->dev.handle_control = usb_msd_handle_control;
s->dev.handle_data = usb_msd_handle_data;
s->dev.handle_destroy = usb_msd_handle_destroy;
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",
filename);
s->scsi_dev = scsi_disk_init(bdrv, usb_msd_command_complete, s);
usb_msd_handle_reset((USBDevice *)s);
return (USBDevice *)s;
}
+1190
View File
File diff suppressed because it is too large. Load diff
+8 -14
View File
@@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
usb_attach(port1, NULL);
}
/* set connect status */
if (!(port->ctrl & UHCI_PORT_CCS)) {
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
}
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
/* update speed */
if (dev->speed == USB_SPEED_LOW)
port->ctrl |= UHCI_PORT_LSDA;
@@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
USB_MSG_ATTACH, 0, 0, NULL, 0);
} else {
/* set connect status */
if (!(port->ctrl & UHCI_PORT_CCS)) {
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
if (port->ctrl & UHCI_PORT_CCS) {
port->ctrl &= ~UHCI_PORT_CCS;
port->ctrl |= UHCI_PORT_CSC;
}
/* disable port */
if (port->ctrl & UHCI_PORT_EN) {
@@ -638,17 +638,15 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
}
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports)
void usb_uhci_init(PCIBus *bus, int devfn)
{
UHCIState *s;
uint8_t *pci_conf;
UHCIPort *port;
int i;
s = (UHCIState *)pci_register_device(bus,
"USB-UHCI", sizeof(UHCIState),
((PCIDevice *)piix3_state)->devfn + 2,
NULL, NULL);
devfn, NULL, NULL);
pci_conf = s->dev.config;
pci_conf[0x00] = 0x86;
pci_conf[0x01] = 0x80;
@@ -663,11 +661,7 @@ void usb_uhci_init(PCIBus *bus, USBPort **usb_ports)
pci_conf[0x60] = 0x10; // release number
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
port->port.opaque = s;
port->port.index = i;
port->port.attach = uhci_attach;
usb_ports[i] = &port->port;
qemu_register_usb_port(&s->ports[i].port, s, i, uhci_attach);
}
s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
+15 -3
View File
@@ -116,6 +116,8 @@ struct USBDevice {
int (*handle_packet)(USBDevice *dev, int pid,
uint8_t devaddr, uint8_t devep,
uint8_t *data, int len);
void (*handle_destroy)(USBDevice *dev);
int speed;
/* The following fields are used by the generic USB device
@@ -127,6 +129,7 @@ struct USBDevice {
int (*handle_data)(USBDevice *dev, int pid, uint8_t devep,
uint8_t *data, int len);
uint8_t addr;
char devname[32];
int state;
uint8_t setup_buf[8];
@@ -137,12 +140,15 @@ struct USBDevice {
int setup_index;
};
typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
/* USB port on which a device can be connected */
struct USBPort {
USBDevice *dev;
void (*attach)(USBPort *port, USBDevice *dev);
usb_attachfn attach;
void *opaque;
int index; /* internal port index, may be used with the opaque */
struct USBPort *next; /* Used internally by qemu. */
};
void usb_attach(USBPort *port, USBDevice *dev);
@@ -152,10 +158,13 @@ int usb_generic_handle_packet(USBDevice *s, int pid,
int set_usb_string(uint8_t *buf, const char *str);
/* usb hub */
USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports);
USBDevice *usb_hub_init(int nb_ports);
/* usb-uhci.c */
void usb_uhci_init(PCIBus *bus, USBPort **usb_ports);
void usb_uhci_init(PCIBus *bus, int devfn);
/* usb-ohci.c */
void usb_ohci_init(struct PCIBus *bus, int num_ports, int devfn);
/* usb-linux.c */
USBDevice *usb_host_device_open(const char *devname);
@@ -164,3 +173,6 @@ void usb_host_info(void);
/* usb-hid.c */
USBDevice *usb_mouse_init(void);
USBDevice *usb_tablet_init(void);
/* usb-msd.c */
USBDevice *usb_msd_init(const char *filename);
+119
View File
@@ -0,0 +1,119 @@
/*
* ARM Versatile/PB PCI host controller
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the LGPL.
*/
#include "vl.h"
static inline uint32_t vpb_pci_config_addr(target_phys_addr_t addr)
{
return addr & 0xf8ff;
}
static void pci_vpb_config_writeb (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 1);
}
static void pci_vpb_config_writew (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 2);
}
static void pci_vpb_config_writel (void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
pci_data_write(opaque, vpb_pci_config_addr (addr), val, 4);
}
static uint32_t pci_vpb_config_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 1);
return val;
}
static uint32_t pci_vpb_config_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 2);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap16(val);
#endif
return val;
}
static uint32_t pci_vpb_config_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t val;
val = pci_data_read(opaque, vpb_pci_config_addr (addr), 4);
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
return val;
}
static CPUWriteMemoryFunc *pci_vpb_config_write[] = {
&pci_vpb_config_writeb,
&pci_vpb_config_writew,
&pci_vpb_config_writel,
};
static CPUReadMemoryFunc *pci_vpb_config_read[] = {
&pci_vpb_config_readb,
&pci_vpb_config_readw,
&pci_vpb_config_readl,
};
static void pci_vpb_set_irq(PCIDevice *d, void *pic, int irq_num, int level)
{
pic_set_irq_new(pic, 27 + irq_num, level);
}
PCIBus *pci_vpb_init(void *pic)
{
PCIBus *s;
PCIDevice *d;
int mem_config;
s = pci_register_bus(pci_vpb_set_irq, pic, 11 << 3);
/* ??? Register memory space. */
mem_config = cpu_register_io_memory(0, pci_vpb_config_read,
pci_vpb_config_write, s);
/* Selfconfig area. */
cpu_register_physical_memory(0x41000000, 0x10000, mem_config);
/* Normal config area. */
cpu_register_physical_memory(0x42000000, 0x10000, mem_config);
d = pci_register_device(s, "Versatile/PB PCI Controller",
sizeof(PCIDevice), -1, NULL, NULL);
d->config[0x00] = 0xee; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x00; // device_id
d->config[0x03] = 0x03;
d->config[0x04] = 0x00;
d->config[0x05] = 0x00;
d->config[0x06] = 0x20;
d->config[0x07] = 0x02;
d->config[0x08] = 0x00; // revision
d->config[0x09] = 0x00; // programming i/f
d->config[0x0A] = 0x40; // class_sub = pci host
d->config[0x0B] = 0x0b; // class_base = PCI_bridge
d->config[0x0D] = 0x10; // latency_timer
return s;
}
+209 -7
View File
@@ -10,6 +10,8 @@
#include "vl.h"
#include "arm_pic.h"
#define LOCK_VALUE 0xa05f
/* Primary interrupt controller. */
typedef struct vpb_sic_state
@@ -145,6 +147,188 @@ static vpb_sic_state *vpb_sic_init(uint32_t base, void *parent, int irq)
return s;
}
/* System controller. */
typedef struct {
uint32_t base;
uint32_t leds;
uint16_t lockval;
uint32_t cfgdata1;
uint32_t cfgdata2;
uint32_t flags;
uint32_t nvflags;
uint32_t resetlevel;
} vpb_sys_state;
static uint32_t vpb_sys_read(void *opaque, target_phys_addr_t offset)
{
vpb_sys_state *s = (vpb_sys_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x00: /* ID */
return 0x41007004;
case 0x04: /* SW */
/* General purpose hardware switches.
We don't have a useful way of exposing these to the user. */
return 0;
case 0x08: /* LED */
return s->leds;
case 0x20: /* LOCK */
return s->lockval;
case 0x0c: /* OSC0 */
case 0x10: /* OSC1 */
case 0x14: /* OSC2 */
case 0x18: /* OSC3 */
case 0x1c: /* OSC4 */
case 0x24: /* 100HZ */
/* ??? Implement these. */
return 0;
case 0x28: /* CFGDATA1 */
return s->cfgdata1;
case 0x2c: /* CFGDATA2 */
return s->cfgdata2;
case 0x30: /* FLAGS */
return s->flags;
case 0x38: /* NVFLAGS */
return s->nvflags;
case 0x40: /* RESETCTL */
return s->resetlevel;
case 0x44: /* PCICTL */
return 1;
case 0x48: /* MCI */
return 0;
case 0x4c: /* FLASH */
return 0;
case 0x50: /* CLCD */
return 0x1000;
case 0x54: /* CLCDSER */
return 0;
case 0x58: /* BOOTCS */
return 0;
case 0x5c: /* 24MHz */
/* ??? not implemented. */
return 0;
case 0x60: /* MISC */
return 0;
case 0x64: /* DMAPSR0 */
case 0x68: /* DMAPSR1 */
case 0x6c: /* DMAPSR2 */
case 0x8c: /* OSCRESET0 */
case 0x90: /* OSCRESET1 */
case 0x94: /* OSCRESET2 */
case 0x98: /* OSCRESET3 */
case 0x9c: /* OSCRESET4 */
case 0xc0: /* SYS_TEST_OSC0 */
case 0xc4: /* SYS_TEST_OSC1 */
case 0xc8: /* SYS_TEST_OSC2 */
case 0xcc: /* SYS_TEST_OSC3 */
case 0xd0: /* SYS_TEST_OSC4 */
return 0;
default:
printf ("vpb_sys_read: Bad register offset 0x%x\n", offset);
return 0;
}
}
static void vpb_sys_write(void *opaque, target_phys_addr_t offset,
uint32_t val)
{
vpb_sys_state *s = (vpb_sys_state *)opaque;
offset -= s->base;
switch (offset) {
case 0x08: /* LED */
s->leds = val;
case 0x0c: /* OSC0 */
case 0x10: /* OSC1 */
case 0x14: /* OSC2 */
case 0x18: /* OSC3 */
case 0x1c: /* OSC4 */
/* ??? */
break;
case 0x20: /* LOCK */
if (val == LOCK_VALUE)
s->lockval = val;
else
s->lockval = val & 0x7fff;
break;
case 0x28: /* CFGDATA1 */
/* ??? Need to implement this. */
s->cfgdata1 = val;
break;
case 0x2c: /* CFGDATA2 */
/* ??? Need to implement this. */
s->cfgdata2 = val;
break;
case 0x30: /* FLAGSSET */
s->flags |= val;
break;
case 0x34: /* FLAGSCLR */
s->flags &= ~val;
break;
case 0x38: /* NVFLAGSSET */
s->nvflags |= val;
break;
case 0x3c: /* NVFLAGSCLR */
s->nvflags &= ~val;
break;
case 0x40: /* RESETCTL */
if (s->lockval == LOCK_VALUE) {
s->resetlevel = val;
if (val & 0x100)
cpu_abort(cpu_single_env, "Board reset\n");
}
break;
case 0x44: /* PCICTL */
/* nothing to do. */
break;
case 0x4c: /* FLASH */
case 0x50: /* CLCD */
case 0x54: /* CLCDSER */
case 0x64: /* DMAPSR0 */
case 0x68: /* DMAPSR1 */
case 0x6c: /* DMAPSR2 */
case 0x8c: /* OSCRESET0 */
case 0x90: /* OSCRESET1 */
case 0x94: /* OSCRESET2 */
case 0x98: /* OSCRESET3 */
case 0x9c: /* OSCRESET4 */
break;
default:
printf ("vpb_sys_write: Bad register offset 0x%x\n", offset);
return;
}
}
static CPUReadMemoryFunc *vpb_sys_readfn[] = {
vpb_sys_read,
vpb_sys_read,
vpb_sys_read
};
static CPUWriteMemoryFunc *vpb_sys_writefn[] = {
vpb_sys_write,
vpb_sys_write,
vpb_sys_write
};
static vpb_sys_state *vpb_sys_init(uint32_t base)
{
vpb_sys_state *s;
int iomemtype;
s = (vpb_sys_state *)qemu_mallocz(sizeof(vpb_sys_state));
if (!s)
return NULL;
s->base = base;
iomemtype = cpu_register_io_memory(0, vpb_sys_readfn,
vpb_sys_writefn, s);
cpu_register_physical_memory(base, 0x00000fff, iomemtype);
/* ??? Save/restore. */
return s;
}
/* Board init. */
/* The AB and PB boards both use the same core, just with different
@@ -159,6 +343,11 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
CPUState *env;
void *pic;
void *sic;
void *scsi_hba;
PCIBus *pci_bus;
NICInfo *nd;
int n;
int done_smc = 0;
env = cpu_init();
cpu_arm_set_model(env, ARM_CPUID_ARM926);
@@ -166,20 +355,33 @@ static void versatile_init(int ram_size, int vga_ram_size, int boot_device,
/* SDRAM at address zero. */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
vpb_sys_init(0x10000000);
pic = arm_pic_init_cpu(env);
pic = pl190_init(0x10140000, pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
sic = vpb_sic_init(0x10003000, pic, 31);
pl050_init(0x10006000, sic, 3, 0);
pl050_init(0x10007000, sic, 4, 1);
/* TODO: Init PCI NICs. */
if (nd_table[0].vlan) {
if (nd_table[0].model == NULL
|| strcmp(nd_table[0].model, "smc91c111") == 0) {
smc91c111_init(&nd_table[0], 0x10010000, sic, 25);
pci_bus = pci_vpb_init(sic);
/* The Versatile PCI bridge does not provide access to PCI IO space,
so many of the qemu PCI devices are not useable. */
for(n = 0; n < nb_nics; n++) {
nd = &nd_table[n];
if (!nd->model)
nd->model = done_smc ? "rtl8139" : "smc91c111";
if (strcmp(nd->model, "smc91c111") == 0) {
smc91c111_init(nd, 0x10010000, sic, 25);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
exit (1);
pci_nic_init(pci_bus, nd);
}
}
if (usb_enabled) {
usb_ohci_init(pci_bus, 3, -1);
}
scsi_hba = lsi_scsi_init(pci_bus, -1);
for (n = 0; n < MAX_DISKS; n++) {
if (bs_table[n]) {
lsi_scsi_attach(scsi_hba, bs_table[n], n);
}
}
+94 -35
View File
@@ -378,10 +378,29 @@ static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
VGAState *s = opaque;
uint32_t val;
if (s->vbe_index <= VBE_DISPI_INDEX_NB)
val = s->vbe_regs[s->vbe_index];
else
if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
switch(s->vbe_index) {
/* XXX: do not hardcode ? */
case VBE_DISPI_INDEX_XRES:
val = VBE_DISPI_MAX_XRES;
break;
case VBE_DISPI_INDEX_YRES:
val = VBE_DISPI_MAX_YRES;
break;
case VBE_DISPI_INDEX_BPP:
val = VBE_DISPI_MAX_BPP;
break;
default:
val = s->vbe_regs[s->vbe_index];
break;
}
} else {
val = s->vbe_regs[s->vbe_index];
}
} else {
val = 0;
}
#ifdef DEBUG_BOCHS_VBE
printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
#endif
@@ -434,7 +453,8 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
s->bank_offset = (val << 16);
break;
case VBE_DISPI_INDEX_ENABLE:
if (val & VBE_DISPI_ENABLED) {
if ((val & VBE_DISPI_ENABLED) &&
!(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
int h, shift_control;
s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
@@ -450,7 +470,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
s->vbe_start_addr = 0;
/* clear the screen (should be done in BIOS) */
if (!(val & VBE_DISPI_NOCLEARMEM)) {
memset(s->vram_ptr, 0,
@@ -464,7 +484,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
s->cr[0x13] = s->vbe_line_offset >> 3;
/* width */
s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
/* height */
/* height (only meaningful if < 1024) */
h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
s->cr[0x12] = h;
s->cr[0x07] = (s->cr[0x07] & ~0x42) |
@@ -808,6 +828,11 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign
return (r << 16) | (g << 8) | b;
}
static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
{
return (b << 16) | (g << 8) | r;
}
#define DEPTH 8
#include "vga_template.h"
@@ -820,6 +845,10 @@ static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsign
#define DEPTH 32
#include "vga_template.h"
#define BGR_FORMAT
#define DEPTH 32
#include "vga_template.h"
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
{
unsigned int col;
@@ -852,6 +881,13 @@ static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned
return col;
}
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
{
unsigned int col;
col = rgb_to_pixel32bgr(r, g, b);
return col;
}
/* return true if the palette was modified */
static int update_palette16(VGAState *s)
{
@@ -948,9 +984,11 @@ static int update_basic_params(VGAState *s)
return full_update;
}
static inline int get_depth_index(int depth)
#define NB_DEPTHS 5
static inline int get_depth_index(DisplayState *s)
{
switch(depth) {
switch(s->depth) {
default:
case 8:
return 0;
@@ -959,29 +997,35 @@ static inline int get_depth_index(int depth)
case 16:
return 2;
case 32:
return 3;
if (s->bgr)
return 4;
else
return 3;
}
}
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
vga_draw_glyph8_8,
vga_draw_glyph8_16,
vga_draw_glyph8_16,
vga_draw_glyph8_32,
vga_draw_glyph8_32,
};
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
vga_draw_glyph16_8,
vga_draw_glyph16_16,
vga_draw_glyph16_16,
vga_draw_glyph16_32,
vga_draw_glyph16_32,
};
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
vga_draw_glyph9_8,
vga_draw_glyph9_16,
vga_draw_glyph9_16,
vga_draw_glyph9_32,
vga_draw_glyph9_32,
};
static const uint8_t cursor_glyph[32 * 4] = {
@@ -1103,7 +1147,7 @@ static void vga_draw_text(VGAState *s, int full_update)
}
cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
depth_index = get_depth_index(s->ds->depth);
depth_index = get_depth_index(s->ds);
if (cw == 16)
vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
else
@@ -1196,56 +1240,76 @@ enum {
VGA_DRAW_LINE_NB,
};
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
vga_draw_line2_8,
vga_draw_line2_16,
vga_draw_line2_16,
vga_draw_line2_32,
vga_draw_line2_32,
vga_draw_line2d2_8,
vga_draw_line2d2_16,
vga_draw_line2d2_16,
vga_draw_line2d2_32,
vga_draw_line2d2_32,
vga_draw_line4_8,
vga_draw_line4_16,
vga_draw_line4_16,
vga_draw_line4_32,
vga_draw_line4_32,
vga_draw_line4d2_8,
vga_draw_line4d2_16,
vga_draw_line4d2_16,
vga_draw_line4d2_32,
vga_draw_line4d2_32,
vga_draw_line8d2_8,
vga_draw_line8d2_16,
vga_draw_line8d2_16,
vga_draw_line8d2_32,
vga_draw_line8d2_32,
vga_draw_line8_8,
vga_draw_line8_16,
vga_draw_line8_16,
vga_draw_line8_32,
vga_draw_line8_32,
vga_draw_line15_8,
vga_draw_line15_15,
vga_draw_line15_16,
vga_draw_line15_32,
vga_draw_line15_32bgr,
vga_draw_line16_8,
vga_draw_line16_15,
vga_draw_line16_16,
vga_draw_line16_32,
vga_draw_line16_32bgr,
vga_draw_line24_8,
vga_draw_line24_15,
vga_draw_line24_16,
vga_draw_line24_32,
vga_draw_line24_32bgr,
vga_draw_line32_8,
vga_draw_line32_15,
vga_draw_line32_16,
vga_draw_line32_32,
vga_draw_line32_32bgr,
};
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
rgb_to_pixel8_dup,
rgb_to_pixel15_dup,
rgb_to_pixel16_dup,
rgb_to_pixel32_dup,
rgb_to_pixel32bgr_dup,
};
static int vga_get_bpp(VGAState *s)
@@ -1266,11 +1330,19 @@ static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
{
int width, height;
width = (s->cr[0x01] + 1) * 8;
height = s->cr[0x12] |
((s->cr[0x07] & 0x02) << 7) |
((s->cr[0x07] & 0x40) << 3);
height = (height + 1);
#ifdef CONFIG_BOCHS_VBE
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
} else
#endif
{
width = (s->cr[0x01] + 1) * 8;
height = s->cr[0x12] |
((s->cr[0x07] & 0x02) << 7) |
((s->cr[0x07] & 0x40) << 3);
height = (height + 1);
}
*pwidth = width;
*pheight = height;
}
@@ -1362,7 +1434,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
break;
}
}
vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
if (disp_width != s->last_width ||
height != s->last_height) {
@@ -1492,21 +1564,8 @@ static void vga_update_display(void *opaque)
if (s->ds->depth == 0) {
/* nothing to do */
} else {
switch(s->ds->depth) {
case 8:
s->rgb_to_pixel = rgb_to_pixel8_dup;
break;
case 15:
s->rgb_to_pixel = rgb_to_pixel15_dup;
break;
default:
case 16:
s->rgb_to_pixel = rgb_to_pixel16_dup;
break;
case 32:
s->rgb_to_pixel = rgb_to_pixel32_dup;
break;
}
s->rgb_to_pixel =
rgb_to_pixel_dup_table[get_depth_index(s->ds)];
full_update = 0;
if (!(s->ar_index & 0x20)) {
+6 -3
View File
@@ -30,8 +30,9 @@
/* bochs VBE support */
#define CONFIG_BOCHS_VBE
#define VBE_DISPI_MAX_XRES 1024
#define VBE_DISPI_MAX_YRES 768
#define VBE_DISPI_MAX_XRES 1600
#define VBE_DISPI_MAX_YRES 1200
#define VBE_DISPI_MAX_BPP 32
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
@@ -51,6 +52,8 @@
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_GETCAPS 0x02
#define VBE_DISPI_8BIT_DAC 0x20
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
@@ -72,7 +75,7 @@
#endif /* !CONFIG_BOCHS_VBE */
#define CH_ATTR_SIZE (160 * 100)
#define VGA_MAX_HEIGHT 1024
#define VGA_MAX_HEIGHT 2048
#define VGA_STATE_COMMON \
uint8_t *vram_ptr; \
+119 -113
View File
@@ -35,7 +35,13 @@
#error unsupport depth
#endif
#if DEPTH != 15
#ifdef BGR_FORMAT
#define PIXEL_NAME glue(DEPTH, bgr)
#else
#define PIXEL_NAME DEPTH
#endif /* BGR_FORMAT */
#if DEPTH != 15 && !defined(BGR_FORMAT)
static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
uint32_t font_data,
@@ -334,118 +340,6 @@ static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d,
}
}
#endif /* DEPTH != 15 */
/* XXX: optimize */
/*
* 15 bit color
*/
static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 7) & 0xf8;
g = (v >> 2) & 0xf8;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 16 bit color
*/
static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 24 bit color
*/
static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[0];
g = s[1];
b = s[2];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 3;
d += BPP;
} while (--w != 0);
}
/*
* 32 bit color
*/
static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 4);
#else
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[1];
g = s[2];
b = s[3];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 4;
d += BPP;
} while (--w != 0);
#endif
}
#if DEPTH != 15
void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
const uint8_t *src1,
int poffset, int w,
@@ -511,9 +405,121 @@ void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
d += BPP;
}
}
#endif /* DEPTH != 15 */
/* XXX: optimize */
/*
* 15 bit color
*/
static void glue(vga_draw_line15_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 7) & 0xf8;
g = (v >> 2) & 0xf8;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 16 bit color
*/
static void glue(vga_draw_line16_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 24 bit color
*/
static void glue(vga_draw_line24_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[0];
g = s[1];
b = s[2];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
s += 3;
d += BPP;
} while (--w != 0);
}
/*
* 32 bit color
*/
static void glue(vga_draw_line32_, PIXEL_NAME)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) && !defined(BGR_FORMAT)
memcpy(d, s, width * 4);
#else
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[1];
g = s[2];
b = s[3];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, PIXEL_NAME)(r, g, b);
s += 4;
d += BPP;
} while (--w != 0);
#endif
}
#undef PUT_PIXEL2
#undef DEPTH
#undef BPP
#undef PIXEL_TYPE
#undef PIXEL_NAME
#undef BGR_FORMAT
+8 -3
View File
@@ -119,7 +119,7 @@ static int is_cpuid_supported(void)
static void kqemu_update_cpuid(CPUState *env)
{
int critical_features_mask, features;
int critical_features_mask, features, ext_features, ext_features_mask;
uint32_t eax, ebx, ecx, edx;
/* the following features are kept identical on the host and
@@ -130,11 +130,14 @@ static void kqemu_update_cpuid(CPUState *env)
CPUID_CMOV | CPUID_CX8 |
CPUID_FXSR | CPUID_MMX | CPUID_SSE |
CPUID_SSE2 | CPUID_SEP;
ext_features_mask = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR;
if (!is_cpuid_supported()) {
features = 0;
ext_features = 0;
} else {
cpuid(1, eax, ebx, ecx, edx);
features = edx;
ext_features = ecx;
}
#ifdef __x86_64__
/* NOTE: on x86_64 CPUs, SYSENTER is not supported in
@@ -144,6 +147,8 @@ static void kqemu_update_cpuid(CPUState *env)
#endif
env->cpuid_features = (env->cpuid_features & ~critical_features_mask) |
(features & critical_features_mask);
env->cpuid_ext_features = (env->cpuid_ext_features & ~ext_features_mask) |
(ext_features & ext_features_mask);
/* XXX: we could update more of the target CPUID state so that the
non accelerated code sees exactly the same CPU features as the
accelerated code */
@@ -598,12 +603,12 @@ void kqemu_record_dump(void)
perror("/tmp/kqemu.stats");
exit(1);
}
fprintf(f, "total: %lld\n", total);
fprintf(f, "total: %" PRId64 "\n", total);
sum = 0;
for(i = 0; i < nb_pc_records; i++) {
r = pr[i];
sum += r->count;
fprintf(f, "%08lx: %lld %0.2f%% %0.2f%%\n",
fprintf(f, "%08lx: %" PRId64 " %0.2f%% %0.2f%%\n",
r->pc,
r->count,
(double)r->count / (double)total * 100.0,
+49 -267
View File
@@ -3,7 +3,6 @@
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
@@ -59,19 +58,19 @@ static uint32_t get_elf_hwcap(void)
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_386
/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
starts %edx contains a pointer to a function which might be
registered using `atexit'. This provides a mean for the
dynamic linker to call DT_FINI functions for shared libraries
that have been loaded before the code runs.
A value of 0 tells we have no such handler. */
#define ELF_PLAT_INIT(_r) _r->edx = 0
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->esp = infop->start_stack;
regs->eip = infop->entry;
/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
starts %edx contains a pointer to a function which might be
registered using `atexit'. This provides a mean for the
dynamic linker to call DT_FINI functions for shared libraries
that have been loaded before the code runs.
A value of 0 tells we have no such handler. */
regs->edx = 0;
}
#define USE_ELF_CORE_DUMP
@@ -93,8 +92,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#endif
#define ELF_ARCH EM_ARM
#define ELF_PLAT_INIT(_r) _r->ARM_r0 = 0
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
target_long stack = infop->start_stack;
@@ -107,7 +104,9 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
regs->ARM_r2 = tgetl(stack + 8); /* envp */
regs->ARM_r1 = tgetl(stack + 4); /* envp */
/* XXX: it seems that r0 is zeroed after ! */
// regs->ARM_r0 = tgetl(stack); /* argc */
regs->ARM_r0 = 0;
/* For uClinux PIC binaries. */
regs->ARM_r10 = infop->start_data;
}
#define USE_ELF_CORE_DUMP
@@ -136,14 +135,13 @@ enum
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ( (x) == EM_SPARC )
#define elf_check_arch(x) ( (x) == EM_SPARCV9 )
#define ELF_CLASS ELFCLASS64
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARC
#define ELF_ARCH EM_SPARCV9
/*XXX*/
#define ELF_PLAT_INIT(_r)
#define STACK_BIAS 2047
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
@@ -151,7 +149,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
regs->pc = infop->entry;
regs->npc = regs->pc + 4;
regs->y = 0;
regs->u_regs[14] = infop->start_stack - 16 * 4;
regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
}
#else
@@ -163,9 +161,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARC
/*XXX*/
#define ELF_PLAT_INIT(_r)
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->psr = 0;
@@ -192,20 +187,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#endif
#define ELF_ARCH EM_PPC
/* Note that isn't exactly what regular kernel does
* but this is what the ABI wants and is needed to allow
* execution of PPC BSD programs.
*/
#define ELF_PLAT_INIT(_r) \
do { \
target_ulong *pos = (target_ulong *)bprm->p, tmp = 1; \
_r->gpr[3] = bprm->argc; \
_r->gpr[4] = (unsigned long)++pos; \
for (; tmp != 0; pos++) \
tmp = ldl(pos); \
_r->gpr[5] = (unsigned long)pos; \
} while (0)
/*
* We need to put in some extra aux table entries to tell glibc what
* the cache block size is, so it can use the dcbz instruction safely.
@@ -239,9 +220,22 @@ do { \
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
{
target_ulong pos = infop->start_stack;
target_ulong tmp;
_regs->msr = 1 << MSR_PR; /* Set user mode */
_regs->gpr[1] = infop->start_stack;
_regs->nip = infop->entry;
/* Note that isn't exactly what regular kernel does
* but this is what the ABI wants and is needed to allow
* execution of PPC BSD programs.
*/
_regs->gpr[3] = tgetl(pos);
pos += sizeof(target_ulong);
_regs->gpr[4] = pos;
for (tmp = 1; tmp != 0; pos += sizeof(target_ulong))
tmp = ldl(pos);
_regs->gpr[5] = pos;
}
#define USE_ELF_CORE_DUMP
@@ -263,8 +257,6 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info *
#endif
#define ELF_ARCH EM_MIPS
#define ELF_PLAT_INIT(_r)
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->cp0_status = CP0St_UM;
@@ -284,8 +276,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_SH
#define ELF_PLAT_INIT(_r) /* XXXXX */
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
/* Check other registers XXXXX */
@@ -308,30 +298,6 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#include "elf.h"
/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB w/4KB pages!
*/
#define MAX_ARG_PAGES 32
/*
* This structure is used to hold the arguments that are
* used when loading binaries.
*/
struct linux_binprm {
char buf[128];
void *page[MAX_ARG_PAGES];
unsigned long p;
int sh_bang;
int fd;
int e_uid, e_gid;
int argc, envc;
char * filename; /* Name of binary */
unsigned long loader, exec;
int dont_iput; /* binfmt handler has put inode */
};
struct exec
{
unsigned int a_info; /* Use macros N_MAGIC, etc for access */
@@ -377,8 +343,6 @@ struct exec
#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
/* Necessary parameters */
#define NGROUPS 32
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
@@ -452,13 +416,13 @@ static void bswap_sym(Elf32_Sym *sym)
#endif
/*
* 'copy_string()' copies argument/envelope strings from user
* 'copy_elf_strings()' copies argument/envelope strings from user
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*
*/
static unsigned long copy_strings(int argc,char ** argv, void **page,
unsigned long p)
static unsigned long copy_elf_strings(int argc,char ** argv, void **page,
unsigned long p)
{
char *tmp, *tmp1, *pag = NULL;
int len, offset = 0;
@@ -506,101 +470,6 @@ static unsigned long copy_strings(int argc,char ** argv, void **page,
return p;
}
static int in_group_p(gid_t g)
{
/* return TRUE if we're in the specified group, FALSE otherwise */
int ngroup;
int i;
gid_t grouplist[NGROUPS];
ngroup = getgroups(NGROUPS, grouplist);
for(i = 0; i < ngroup; i++) {
if(grouplist[i] == g) {
return 1;
}
}
return 0;
}
static int count(char ** vec)
{
int i;
for(i = 0; *vec; i++) {
vec++;
}
return(i);
}
static int prepare_binprm(struct linux_binprm *bprm)
{
struct stat st;
int mode;
int retval, id_change;
if(fstat(bprm->fd, &st) < 0) {
return(-errno);
}
mode = st.st_mode;
if(!S_ISREG(mode)) { /* Must be regular file */
return(-EACCES);
}
if(!(mode & 0111)) { /* Must have at least one execute bit set */
return(-EACCES);
}
bprm->e_uid = geteuid();
bprm->e_gid = getegid();
id_change = 0;
/* Set-uid? */
if(mode & S_ISUID) {
bprm->e_uid = st.st_uid;
if(bprm->e_uid != geteuid()) {
id_change = 1;
}
}
/* Set-gid? */
/*
* If setgid is set but no group execute bit then this
* is a candidate for mandatory locking, not a setgid
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->e_gid = st.st_gid;
if (!in_group_p(bprm->e_gid)) {
id_change = 1;
}
}
memset(bprm->buf, 0, sizeof(bprm->buf));
retval = lseek(bprm->fd, 0L, SEEK_SET);
if(retval >= 0) {
retval = read(bprm->fd, bprm->buf, 128);
}
if(retval < 0) {
perror("prepare_binprm");
exit(-1);
/* return(-errno); */
}
else {
return(retval);
}
}
static inline void memcpy_to_target(target_ulong dest, const void *src,
unsigned long len)
{
void *host_ptr;
host_ptr = lock_user(dest, len, 0);
memcpy(host_ptr, src, len);
unlock_user(host_ptr, dest, 1);
}
unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
struct image_info * info)
{
@@ -628,11 +497,6 @@ unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
p += stack_base;
if (bprm->loader) {
bprm->loader += stack_base;
}
bprm->exec += stack_base;
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
if (bprm->page[i]) {
info->rss++;
@@ -703,7 +567,6 @@ static unsigned long create_elf_tables(target_ulong p, int argc, int envc,
unsigned long interp_load_addr, int ibcs,
struct image_info *info)
{
target_ulong argv, envp;
target_ulong sp;
int size;
target_ulong u_platform;
@@ -765,28 +628,7 @@ static unsigned long create_elf_tables(target_ulong p, int argc, int envc,
#endif
#undef NEW_AUX_ENT
sp -= (envc + 1) * n;
envp = sp;
sp -= (argc + 1) * n;
argv = sp;
if (!ibcs) {
sp -= n; tputl(sp, envp);
sp -= n; tputl(sp, argv);
}
sp -= n; tputl(sp, argc);
info->arg_start = p;
while (argc-->0) {
tputl(argv, p); argv += n;
p += target_strlen(p) + 1;
}
tputl(argv, 0);
info->arg_end = info->env_start = p;
while (envc-->0) {
tputl(envp, p); envp += n;
p += target_strlen(p) + 1;
}
tputl(envp, 0);
info->env_end = p;
sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
return sp;
}
@@ -1001,8 +843,8 @@ static void load_symbols(struct elfhdr *hdr, int fd)
syminfos = s;
}
static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info)
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info)
{
struct elfhdr elf_ex;
struct elfhdr interp_elf_ex;
@@ -1034,17 +876,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
bswap_ehdr(&elf_ex);
#endif
if (elf_ex.e_ident[0] != 0x7f ||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
return -ENOEXEC;
}
/* First of all, some simple consistency checks */
if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
(! elf_check_arch(elf_ex.e_machine))) {
return -ENOEXEC;
}
bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
if (!bprm->p) {
retval = -E2BIG;
}
/* Now read in all of the header information */
elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
if (elf_phdata == NULL) {
@@ -1188,7 +1032,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
/* OK, we are done with that, now set up the arg stuff,
and then start this sucker up */
if (!bprm->sh_bang) {
{
char * passed_p;
if (interpreter_type == INTERPRETER_AOUT) {
@@ -1196,7 +1040,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
passed_p = passed_fileno;
if (elf_interpreter) {
bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
bprm->argc++;
}
}
@@ -1347,11 +1191,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
interp_load_addr,
(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
info);
if (interpreter_type == INTERPRETER_AOUT)
info->arg_start += strlen(passed_fileno) + 1;
info->start_brk = info->brk = elf_brk;
info->end_code = end_code;
info->start_code = start_code;
info->start_data = end_code;
info->end_data = end_data;
info->start_stack = bprm->p;
@@ -1380,79 +1223,18 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
MAP_FIXED | MAP_PRIVATE, -1, 0);
}
#ifdef ELF_PLAT_INIT
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
* example. This macro performs whatever initialization to
* the regs structure is required.
*/
ELF_PLAT_INIT(regs);
#endif
info->entry = elf_entry;
return 0;
}
int elf_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop)
{
struct linux_binprm bprm;
int retval;
int i;
bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = 0;
retval = open(filename, O_RDONLY);
if (retval < 0)
return retval;
bprm.fd = retval;
bprm.filename = (char *)filename;
bprm.sh_bang = 0;
bprm.loader = 0;
bprm.exec = 0;
bprm.dont_iput = 0;
bprm.argc = count(argv);
bprm.envc = count(envp);
retval = prepare_binprm(&bprm);
if(retval>=0) {
bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
bprm.exec = bprm.p;
bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
if (!bprm.p) {
retval = -E2BIG;
}
}
if(retval>=0) {
retval = load_elf_binary(&bprm,regs,infop);
}
if(retval>=0) {
/* success. Initialize important registers */
init_thread(regs, infop);
return retval;
}
/* Something went wrong, return the inode and free the argument pages*/
for (i=0 ; i<MAX_ARG_PAGES ; i++) {
free(bprm.page[i]);
}
return(retval);
}
static int load_aout_interp(void * exptr, int interp_fd)
{
printf("a.out interpreter not yet supported\n");
return(0);
}
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
init_thread(regs, infop);
}
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2002-2003 David McCullough <davidm@snapgear.com>
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* The Silver Hammer Group, Ltd.
*
* This file provides the definitions and structures needed to
* support uClinux flat-format executables.
*/
#define FLAT_VERSION 0x00000004L
#ifdef CONFIG_BINFMT_SHARED_FLAT
#define MAX_SHARED_LIBS (4)
#else
#define MAX_SHARED_LIBS (1)
#endif
/*
* To make everything easier to port and manage cross platform
* development, all fields are in network byte order.
*/
struct flat_hdr {
char magic[4];
unsigned long rev; /* version (as above) */
unsigned long entry; /* Offset of first executable instruction
with text segment from beginning of file */
unsigned long data_start; /* Offset of data segment from beginning of
file */
unsigned long data_end; /* Offset of end of data segment
from beginning of file */
unsigned long bss_end; /* Offset of end of bss segment from beginning
of file */
/* (It is assumed that data_end through bss_end forms the bss segment.) */
unsigned long stack_size; /* Size of stack, in bytes */
unsigned long reloc_start; /* Offset of relocation records from
beginning of file */
unsigned long reloc_count; /* Number of relocation records */
unsigned long flags;
unsigned long build_date; /* When the program/library was built */
unsigned long filler[5]; /* Reservered, set to zero */
};
#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */
#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
#define FLAT_FLAG_GZIP 0x0004 /* all but the header is compressed */
#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
/*
* While it would be nice to keep this header clean, users of older
* tools still need this support in the kernel. So this section is
* purely for compatibility with old tool chains.
*
* DO NOT make changes or enhancements to the old format please, just work
* with the format above, except to fix bugs with old format support.
*/
#define OLD_FLAT_VERSION 0x00000002L
#define OLD_FLAT_RELOC_TYPE_TEXT 0
#define OLD_FLAT_RELOC_TYPE_DATA 1
#define OLD_FLAT_RELOC_TYPE_BSS 2
# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */
+793
View File
@@ -0,0 +1,793 @@
/****************************************************************************/
/*
* QEMU bFLT binary loader. Based on linux/fs/binfmt_flat.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Copyright (C) 2006 CodeSourcery.
* Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com>
* Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
* Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com>
* Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com>
* based heavily on:
*
* linux/fs/binfmt_aout.c:
* Copyright (C) 1991, 1992, 1996 Linus Torvalds
* linux/fs/binfmt_flat.c for 2.0 kernel
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* JAN/99 -- coded full program relocation (gerg@snapgear.com)
*/
/* ??? ZFLAT and shared library support is currently disabled. */
/****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include "qemu.h"
#include "flat.h"
//#define DEBUG
#ifdef DEBUG
#define DBG_FLT(a...) printf(a)
#else
#define DBG_FLT(a...)
#endif
#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
#define flat_old_ram_flag(flag) (flag)
#ifdef TARGET_WORDS_BIGENDIAN
#define flat_get_relocate_addr(relval) (relval)
#else
#define flat_get_relocate_addr(relval) bswap32(relval)
#endif
#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
struct lib_info {
target_ulong start_code; /* Start of text segment */
target_ulong start_data; /* Start of data segment */
target_ulong end_data; /* Start of bss section */
target_ulong start_brk; /* End of data segment */
target_ulong text_len; /* Length of text segment */
target_ulong entry; /* Start address for this module */
target_ulong build_date; /* When this one was compiled */
short loaded; /* Has this library been loaded? */
};
#ifdef CONFIG_BINFMT_SHARED_FLAT
static int load_flat_shared_library(int id, struct lib_info *p);
#endif
struct linux_binprm;
#define ntohl(x) be32_to_cpu(x)
/****************************************************************************/
/*
* create_flat_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
/* Push a block of strings onto the guest stack. */
static target_ulong copy_strings(target_ulong p, int n, char **s)
{
int len;
while (n-- > 0) {
len = strlen(s[n]) + 1;
p -= len;
memcpy_to_target(p, s[n], len);
}
return p;
}
int target_pread(int fd, target_ulong ptr, target_ulong len,
target_ulong offset)
{
void *buf;
int ret;
buf = lock_user(ptr, len, 0);
ret = pread(fd, buf, len, offset);
unlock_user(buf, ptr, len);
return ret;
}
/****************************************************************************/
#ifdef CONFIG_BINFMT_ZFLAT
#include <linux/zlib.h>
#define LBUFSIZE 4000
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
#define RESERVED 0xC0 /* bit 6,7: reserved */
static int decompress_exec(
struct linux_binprm *bprm,
unsigned long offset,
char *dst,
long len,
int fd)
{
unsigned char *buf;
z_stream strm;
loff_t fpos;
int ret, retval;
DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
memset(&strm, 0, sizeof(strm));
strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
if (strm.workspace == NULL) {
DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
return -ENOMEM;
}
buf = kmalloc(LBUFSIZE, GFP_KERNEL);
if (buf == NULL) {
DBG_FLT("binfmt_flat: no memory for read buffer\n");
retval = -ENOMEM;
goto out_free;
}
/* Read in first chunk of data and parse gzip header. */
fpos = offset;
ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
strm.next_in = buf;
strm.avail_in = ret;
strm.total_in = 0;
retval = -ENOEXEC;
/* Check minimum size -- gzip header */
if (ret < 10) {
DBG_FLT("binfmt_flat: file too small?\n");
goto out_free_buf;
}
/* Check gzip magic number */
if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
DBG_FLT("binfmt_flat: unknown compression magic?\n");
goto out_free_buf;
}
/* Check gzip method */
if (buf[2] != 8) {
DBG_FLT("binfmt_flat: unknown compression method?\n");
goto out_free_buf;
}
/* Check gzip flags */
if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
(buf[3] & RESERVED)) {
DBG_FLT("binfmt_flat: unknown flags?\n");
goto out_free_buf;
}
ret = 10;
if (buf[3] & EXTRA_FIELD) {
ret += 2 + buf[10] + (buf[11] << 8);
if (unlikely(LBUFSIZE == ret)) {
DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
goto out_free_buf;
}
}
if (buf[3] & ORIG_NAME) {
for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
;
if (unlikely(LBUFSIZE == ret)) {
DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
goto out_free_buf;
}
}
if (buf[3] & COMMENT) {
for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
;
if (unlikely(LBUFSIZE == ret)) {
DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
goto out_free_buf;
}
}
strm.next_in += ret;
strm.avail_in -= ret;
strm.next_out = dst;
strm.avail_out = len;
strm.total_out = 0;
if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
DBG_FLT("binfmt_flat: zlib init failed?\n");
goto out_free_buf;
}
while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
if (ret <= 0)
break;
if (ret >= (unsigned long) -4096)
break;
len -= ret;
strm.next_in = buf;
strm.avail_in = ret;
strm.total_in = 0;
}
if (ret < 0) {
DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
ret, strm.msg);
goto out_zlib;
}
retval = 0;
out_zlib:
zlib_inflateEnd(&strm);
out_free_buf:
kfree(buf);
out_free:
kfree(strm.workspace);
out:
return retval;
}
#endif /* CONFIG_BINFMT_ZFLAT */
/****************************************************************************/
static target_ulong
calc_reloc(target_ulong r, struct lib_info *p, int curid, int internalp)
{
target_ulong addr;
int id;
target_ulong start_brk;
target_ulong start_data;
target_ulong text_len;
target_ulong start_code;
#ifdef CONFIG_BINFMT_SHARED_FLAT
#error needs checking
if (r == 0)
id = curid; /* Relocs of 0 are always self referring */
else {
id = (r >> 24) & 0xff; /* Find ID for this reloc */
r &= 0x00ffffff; /* Trim ID off here */
}
if (id >= MAX_SHARED_LIBS) {
fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n",
(unsigned) r, id);
goto failed;
}
if (curid != id) {
if (internalp) {
fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not "
"in same module (%d != %d)\n",
(unsigned) r, curid, id);
goto failed;
} else if ( ! p[id].loaded &&
load_flat_shared_library(id, p) > (unsigned long) -4096) {
fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id);
goto failed;
}
/* Check versioning information (i.e. time stamps) */
if (p[id].build_date && p[curid].build_date
&& p[curid].build_date < p[id].build_date) {
fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n",
id, curid);
goto failed;
}
}
#else
id = 0;
#endif
start_brk = p[id].start_brk;
start_data = p[id].start_data;
start_code = p[id].start_code;
text_len = p[id].text_len;
if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
fprintf(stderr, "BINFMT_FLAT: reloc outside program 0x%x "
"(0 - 0x%x/0x%x)\n",
(int) r,(int)(start_brk-start_code),(int)text_len);
goto failed;
}
if (r < text_len) /* In text segment */
addr = r + start_code;
else /* In data segment */
addr = r - text_len + start_data;
/* Range checked already above so doing the range tests is redundant...*/
return(addr);
failed:
abort();
return RELOC_FAILED;
}
/****************************************************************************/
/* ??? This does not handle endianness correctly. */
void old_reloc(struct lib_info *libinfo, uint32_t rl)
{
#ifdef DEBUG
char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
#endif
uint32_t *ptr;
uint32_t offset;
int reloc_type;
offset = rl & 0x3fffffff;
reloc_type = rl >> 30;
/* ??? How to handle this? */
#if defined(CONFIG_COLDFIRE)
ptr = (uint32_t *) (libinfo->start_code + offset);
#else
ptr = (uint32_t *) (libinfo->start_data + offset);
#endif
#ifdef DEBUG
fprintf(stderr, "Relocation of variable at DATASEG+%x "
"(address %p, currently %x) into segment %s\n",
offset, ptr, (int)*ptr, segment[reloc_type]);
#endif
switch (reloc_type) {
case OLD_FLAT_RELOC_TYPE_TEXT:
*ptr += libinfo->start_code;
break;
case OLD_FLAT_RELOC_TYPE_DATA:
*ptr += libinfo->start_data;
break;
case OLD_FLAT_RELOC_TYPE_BSS:
*ptr += libinfo->end_data;
break;
default:
fprintf(stderr, "BINFMT_FLAT: Unknown relocation type=%x\n",
reloc_type);
break;
}
DBG_FLT("Relocation became %x\n", (int)*ptr);
}
/****************************************************************************/
static int load_flat_file(struct linux_binprm * bprm,
struct lib_info *libinfo, int id, target_ulong *extra_stack)
{
struct flat_hdr * hdr;
target_ulong textpos = 0, datapos = 0, result;
target_ulong realdatastart = 0;
target_ulong text_len, data_len, bss_len, stack_len, flags;
target_ulong memp = 0; /* for finding the brk area */
target_ulong extra;
target_ulong reloc = 0, rp;
int i, rev, relocs = 0;
target_ulong fpos;
target_ulong start_code, end_code;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
text_len = ntohl(hdr->data_start);
data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
stack_len = ntohl(hdr->stack_size);
if (extra_stack) {
stack_len += *extra_stack;
*extra_stack = stack_len;
}
relocs = ntohl(hdr->reloc_count);
flags = ntohl(hdr->flags);
rev = ntohl(hdr->rev);
DBG_FLT("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
fprintf(stderr, "BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
rev, (int) FLAT_VERSION);
return -ENOEXEC;
}
/* Don't allow old format executables to use shared libraries */
if (rev == OLD_FLAT_VERSION && id != 0) {
fprintf(stderr, "BINFMT_FLAT: shared libraries are not available\n");
return -ENOEXEC;
}
/*
* fix up the flags for the older format, there were all kinds
* of endian hacks, this only works for the simple cases
*/
if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
flags = FLAT_FLAG_RAM;
#ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
fprintf(stderr, "Support for ZFLAT executables is not enabled\n");
return -ENOEXEC;
}
#endif
/*
* calculate the extra space we need to map in
*/
extra = relocs * sizeof(target_ulong);
if (extra < bss_len + stack_len)
extra = bss_len + stack_len;
/*
* there are a couple of cases here, the separate code/data
* case, and then the fully copied to RAM case which lumps
* it all together.
*/
if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
/*
* this should give us a ROM ptr, but if it doesn't we don't
* really care
*/
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC,
MAP_PRIVATE, bprm->fd, 0);
if (textpos == -1) {
fprintf(stderr, "Unable to mmap process text\n");
return -1;
}
realdatastart = target_mmap(0, data_len + extra +
MAX_SHARED_LIBS * sizeof(target_ulong),
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (realdatastart == -1) {
fprintf(stderr, "Unable to allocate RAM for process data\n");
return realdatastart;
}
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong);
DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
(int)(data_len + bss_len + stack_len), (int)datapos);
fpos = ntohl(hdr->data_start);
#ifdef CONFIG_BINFMT_ZFLAT
if (flags & FLAT_FLAG_GZDATA) {
result = decompress_exec(bprm, fpos, (char *) datapos,
data_len + (relocs * sizeof(target_ulong)))
} else
#endif
{
result = target_pread(bprm->fd, datapos,
data_len + (relocs * sizeof(target_ulong)),
fpos);
}
if (result < 0) {
fprintf(stderr, "Unable to read data+bss\n");
return result;
}
reloc = datapos + (ntohl(hdr->reloc_start) - text_len);
memp = realdatastart;
} else {
textpos = target_mmap(0, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(target_ulong),
PROT_READ | PROT_EXEC | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (textpos == -1 ) {
fprintf(stderr, "Unable to allocate RAM for process text/data\n");
return -1;
}
realdatastart = textpos + ntohl(hdr->data_start);
datapos = realdatastart + MAX_SHARED_LIBS * sizeof(target_ulong);
reloc = (textpos + ntohl(hdr->reloc_start) +
MAX_SHARED_LIBS * sizeof(target_ulong));
memp = textpos;
#ifdef CONFIG_BINFMT_ZFLAT
#error code needs checking
/*
* load it all in and treat it like a RAM load from now on
*/
if (flags & FLAT_FLAG_GZIP) {
result = decompress_exec(bprm, sizeof (struct flat_hdr),
(((char *) textpos) + sizeof (struct flat_hdr)),
(text_len + data_len + (relocs * sizeof(unsigned long))
- sizeof (struct flat_hdr)),
0);
memmove((void *) datapos, (void *) realdatastart,
data_len + (relocs * sizeof(unsigned long)));
} else if (flags & FLAT_FLAG_GZDATA) {
fpos = 0;
result = bprm->file->f_op->read(bprm->file,
(char *) textpos, text_len, &fpos);
if (result < (unsigned long) -4096)
result = decompress_exec(bprm, text_len, (char *) datapos,
data_len + (relocs * sizeof(unsigned long)), 0);
}
else
#endif
{
result = target_pread(bprm->fd, textpos,
text_len, 0);
if (result >= 0) {
result = target_pread(bprm->fd, datapos,
data_len + (relocs * sizeof(target_ulong)),
ntohl(hdr->data_start));
}
}
if (result < 0) {
fprintf(stderr, "Unable to read code+data+bss\n");
return result;
}
}
DBG_FLT("Mapping is 0x%x, Entry point is 0x%x, data_start is 0x%x\n",
(int)textpos, 0x00ffffff&ntohl(hdr->entry),
ntohl(hdr->data_start));
/* The main program needs a little extra setup in the task structure */
start_code = textpos + sizeof (struct flat_hdr);
end_code = textpos + text_len;
DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
id ? "Lib" : "Load", bprm->filename,
(int) start_code, (int) end_code,
(int) datapos,
(int) (datapos + data_len),
(int) (datapos + data_len),
(int) (((datapos + data_len + bss_len) + 3) & ~3));
text_len -= sizeof(struct flat_hdr); /* the real code len */
/* Store the current module values into the global library structure */
libinfo[id].start_code = start_code;
libinfo[id].start_data = datapos;
libinfo[id].end_data = datapos + data_len;
libinfo[id].start_brk = datapos + data_len + bss_len;
libinfo[id].text_len = text_len;
libinfo[id].loaded = 1;
libinfo[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
libinfo[id].build_date = ntohl(hdr->build_date);
/*
* We just load the allocations into some temporary memory to
* help simplify all this mumbo jumbo
*
* We've got two different sections of relocation entries.
* The first is the GOT which resides at the begining of the data segment
* and is terminated with a -1. This one can be relocated in place.
* The second is the extra relocation entries tacked after the image's
* data segment. These require a little more processing as the entry is
* really an offset into the image which contains an offset into the
* image.
*/
if (flags & FLAT_FLAG_GOTPIC) {
rp = datapos;
while (1) {
target_ulong addr;
addr = tgetl(rp);
if (addr == -1)
break;
if (addr) {
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED)
return -ENOEXEC;
tputl(rp, addr);
}
rp += sizeof(target_ulong);
}
}
/*
* Now run through the relocation entries.
* We've got to be careful here as C++ produces relocatable zero
* entries in the constructor and destructor tables which are then
* tested for being not zero (which will always occur unless we're
* based from address zero). This causes an endless loop as __start
* is at zero. The solution used is to not relocate zero addresses.
* This has the negative side effect of not allowing a global data
* reference to be statically initialised to _stext (I've moved
* __start to address 4 so that is okay).
*/
if (rev > OLD_FLAT_VERSION) {
for (i = 0; i < relocs; i++) {
target_ulong addr, relval;
/* Get the address of the pointer to be
relocated (of course, the address has to be
relocated first). */
relval = tgetl(reloc + i * sizeof (target_ulong));
addr = flat_get_relocate_addr(relval);
rp = calc_reloc(addr, libinfo, id, 1);
if (rp == RELOC_FAILED)
return -ENOEXEC;
/* Get the pointer's value. */
addr = tgetl(rp);
if (addr != 0) {
/*
* Do the relocation. PIC relocs in the data section are
* already in target order
*/
#ifndef TARGET_WORDS_BIGENDIAN
if ((flags & FLAT_FLAG_GOTPIC) == 0)
addr = bswap32(addr);
#endif
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED)
return -ENOEXEC;
/* Write back the relocated pointer. */
tputl(rp, addr);
}
}
} else {
for (i = 0; i < relocs; i++) {
target_ulong relval;
relval = tgetl(reloc + i * sizeof (target_ulong));
old_reloc(&libinfo[0], relval);
}
}
/* zero the BSS. */
memset((void*)(datapos + data_len), 0, bss_len);
return 0;
}
/****************************************************************************/
#ifdef CONFIG_BINFMT_SHARED_FLAT
/*
* Load a shared library into memory. The library gets its own data
* segment (including bss) but not argv/argc/environ.
*/
static int load_flat_shared_library(int id, struct lib_info *libs)
{
struct linux_binprm bprm;
int res;
char buf[16];
/* Create the file name */
sprintf(buf, "/lib/lib%d.so", id);
/* Open the file up */
bprm.filename = buf;
bprm.file = open_exec(bprm.filename);
res = PTR_ERR(bprm.file);
if (IS_ERR(bprm.file))
return res;
res = prepare_binprm(&bprm);
if (res <= (unsigned long)-4096)
res = load_flat_file(&bprm, libs, id, NULL);
if (bprm.file) {
allow_write_access(bprm.file);
fput(bprm.file);
bprm.file = NULL;
}
return(res);
}
#endif /* CONFIG_BINFMT_SHARED_FLAT */
int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info)
{
struct lib_info libinfo[MAX_SHARED_LIBS];
target_ulong p = bprm->p;
target_ulong stack_len;
target_ulong start_addr;
target_ulong sp;
int res;
int i, j;
memset(libinfo, 0, sizeof(libinfo));
/*
* We have to add the size of our arguments to our stack size
* otherwise it's too easy for users to create stack overflows
* by passing in a huge argument list. And yes, we have to be
* pedantic and include space for the argv/envp array as it may have
* a lot of entries.
*/
#define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
stack_len += (bprm->argc + 1) * 4; /* the argv array */
stack_len += (bprm->envc + 1) * 4; /* the envp array */
res = load_flat_file(bprm, libinfo, 0, &stack_len);
if (res > (unsigned long)-4096)
return res;
/* Update data segment pointers for all libraries */
for (i=0; i<MAX_SHARED_LIBS; i++) {
if (libinfo[i].loaded) {
target_ulong p;
p = libinfo[i].start_data;
for (j=0; j<MAX_SHARED_LIBS; j++) {
p -= 4;
tput32(p, libinfo[j].loaded
? libinfo[j].start_data
: UNLOADED_LIB);
}
}
}
p = ((libinfo[0].start_brk + stack_len + 3) & ~3) - 4;
DBG_FLT("p=%x\n", (int)p);
/* Copy argv/envp. */
p = copy_strings(p, bprm->argc, bprm->argv);
p = copy_strings(p, bprm->envc, bprm->envp);
/* Align stack. */
sp = p & ~(target_ulong)(sizeof(target_ulong) - 1);
sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
/* Fake some return addresses to ensure the call chain will
* initialise library in order for us. We are required to call
* lib 1 first, then 2, ... and finally the main program (id 0).
*/
start_addr = libinfo[0].entry;
#ifdef CONFIG_BINFMT_SHARED_FLAT
#error here
for (i = MAX_SHARED_LIBS-1; i>0; i--) {
if (libinfo[i].loaded) {
/* Push previos first to call address */
--sp; put_user(start_addr, sp);
start_addr = libinfo[i].entry;
}
}
#endif
/* Stash our initial stack pointer into the mm structure */
info->start_code = libinfo[0].start_code;
info->end_code = libinfo[0].start_code = libinfo[0].text_len;
info->start_data = libinfo[0].start_data;
info->end_data = libinfo[0].end_data;
info->start_brk = libinfo[0].start_brk;
info->start_stack = sp;
info->entry = start_addr;
info->code_offset = info->start_code;
info->data_offset = info->start_data - libinfo[0].text_len;
DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n",
(int)info->entry, (int)info->start_stack);
return 0;
}
+195
View File
@@ -0,0 +1,195 @@
/* Code for loading Linux executables. Mostly linux kenrel code. */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "qemu.h"
#define NGROUPS 32
/* ??? This should really be somewhere else. */
void memcpy_to_target(target_ulong dest, const void *src,
unsigned long len)
{
void *host_ptr;
host_ptr = lock_user(dest, len, 0);
memcpy(host_ptr, src, len);
unlock_user(host_ptr, dest, 1);
}
static int in_group_p(gid_t g)
{
/* return TRUE if we're in the specified group, FALSE otherwise */
int ngroup;
int i;
gid_t grouplist[NGROUPS];
ngroup = getgroups(NGROUPS, grouplist);
for(i = 0; i < ngroup; i++) {
if(grouplist[i] == g) {
return 1;
}
}
return 0;
}
static int count(char ** vec)
{
int i;
for(i = 0; *vec; i++) {
vec++;
}
return(i);
}
static int prepare_binprm(struct linux_binprm *bprm)
{
struct stat st;
int mode;
int retval, id_change;
if(fstat(bprm->fd, &st) < 0) {
return(-errno);
}
mode = st.st_mode;
if(!S_ISREG(mode)) { /* Must be regular file */
return(-EACCES);
}
if(!(mode & 0111)) { /* Must have at least one execute bit set */
return(-EACCES);
}
bprm->e_uid = geteuid();
bprm->e_gid = getegid();
id_change = 0;
/* Set-uid? */
if(mode & S_ISUID) {
bprm->e_uid = st.st_uid;
if(bprm->e_uid != geteuid()) {
id_change = 1;
}
}
/* Set-gid? */
/*
* If setgid is set but no group execute bit then this
* is a candidate for mandatory locking, not a setgid
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->e_gid = st.st_gid;
if (!in_group_p(bprm->e_gid)) {
id_change = 1;
}
}
memset(bprm->buf, 0, sizeof(bprm->buf));
retval = lseek(bprm->fd, 0L, SEEK_SET);
if(retval >= 0) {
retval = read(bprm->fd, bprm->buf, 128);
}
if(retval < 0) {
perror("prepare_binprm");
exit(-1);
/* return(-errno); */
}
else {
return(retval);
}
}
/* Construct the envp and argv tables on the target stack. */
target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
target_ulong stringp, int push_ptr)
{
int n = sizeof(target_ulong);
target_ulong envp;
target_ulong argv;
sp -= (envc + 1) * n;
envp = sp;
sp -= (argc + 1) * n;
argv = sp;
if (push_ptr) {
sp -= n; tputl(sp, envp);
sp -= n; tputl(sp, argv);
}
sp -= n; tputl(sp, argc);
while (argc-- > 0) {
tputl(argv, stringp); argv += n;
stringp += target_strlen(stringp) + 1;
}
tputl(argv, 0);
while (envc-- > 0) {
tputl(envp, stringp); envp += n;
stringp += target_strlen(stringp) + 1;
}
tputl(envp, 0);
return sp;
}
int loader_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop)
{
struct linux_binprm bprm;
int retval;
int i;
bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = 0;
retval = open(filename, O_RDONLY);
if (retval < 0)
return retval;
bprm.fd = retval;
bprm.filename = (char *)filename;
bprm.argc = count(argv);
bprm.argv = argv;
bprm.envc = count(envp);
bprm.envp = envp;
retval = prepare_binprm(&bprm);
if(retval>=0) {
if (bprm.buf[0] == 0x7f
&& bprm.buf[1] == 'E'
&& bprm.buf[2] == 'L'
&& bprm.buf[3] == 'F') {
retval = load_elf_binary(&bprm,regs,infop);
#if defined(TARGET_HAS_BFLT)
} else if (bprm.buf[0] == 'b'
&& bprm.buf[1] == 'F'
&& bprm.buf[2] == 'L'
&& bprm.buf[3] == 'T') {
retval = load_flt_binary(&bprm,regs,infop);
#endif
} else {
fprintf(stderr, "Unknown binary format\n");
return -1;
}
}
if(retval>=0) {
/* success. Initialize important registers */
do_init_thread(regs, infop);
return retval;
}
/* Something went wrong, return the inode and free the argument pages*/
for (i=0 ; i<MAX_ARG_PAGES ; i++) {
free(bprm.page[i]);
}
return(retval);
}
+65 -69
View File
@@ -34,6 +34,7 @@
#endif
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
#if defined(__i386__) && !defined(CONFIG_STATIC)
/* Force usage of an ELF interpreter even if it is an ELF shared
@@ -106,29 +107,7 @@ int cpu_get_pic_interrupt(CPUState *env)
/* timers for rdtsc */
#if defined(__i386__)
int64_t cpu_get_real_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
return val;
}
#elif defined(__x86_64__)
int64_t cpu_get_real_ticks(void)
{
uint32_t low,high;
int64_t val;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
val = high;
val <<= 32;
val |= low;
return val;
}
#else
#if 0
static uint64_t emu_time;
@@ -494,11 +473,17 @@ static inline void save_window_offset(CPUSPARCState *env, int cwp1)
static void save_window(CPUSPARCState *env)
{
#ifndef TARGET_SPARC64
unsigned int new_wim;
new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
((1LL << NWINDOWS) - 1);
save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
env->wim = new_wim;
#else
save_window_offset(env, (env->cwp - 2) & (NWINDOWS - 1));
env->cansave++;
env->canrestore--;
#endif
}
static void restore_window(CPUSPARCState *env)
@@ -521,6 +506,12 @@ static void restore_window(CPUSPARCState *env)
sp_ptr += sizeof(target_ulong);
}
env->wim = new_wim;
#ifdef TARGET_SPARC64
env->canrestore++;
if (env->cleanwin < NWINDOWS - 1)
env->cleanwin++;
env->cansave--;
#endif
}
static void flush_windows(CPUSPARCState *env)
@@ -553,8 +544,12 @@ void cpu_loop (CPUSPARCState *env)
trapnr = cpu_sparc_exec (env);
switch (trapnr) {
#ifndef TARGET_SPARC64
case 0x88:
case 0x90:
#else
case 0x16d:
#endif
ret = do_syscall (env, env->gregs[1],
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
@@ -595,10 +590,17 @@ void cpu_loop (CPUSPARCState *env)
}
break;
#else
case TT_SPILL: /* window overflow */
save_window(env);
break;
case TT_FILL: /* window underflow */
restore_window(env);
break;
// XXX
#endif
case 0x100: // XXX, why do we get these?
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
case EXCP_DEBUG:
{
int sig;
@@ -1300,6 +1302,7 @@ void cpu_loop(CPUMIPSState *env)
case EXCP_SYSCALL:
{
syscall_num = env->gpr[2] - 4000;
env->PC += 4;
if (syscall_num >= sizeof(mips_syscall_args)) {
ret = -ENOSYS;
} else {
@@ -1326,8 +1329,6 @@ void cpu_loop(CPUMIPSState *env)
arg5,
arg6);
}
fail:
env->PC += 4;
if ((unsigned int)ret >= (unsigned int)(-1133)) {
env->gpr[7] = 1; /* error flag */
ret = -ret;
@@ -1341,39 +1342,13 @@ void cpu_loop(CPUMIPSState *env)
break;
case EXCP_CpU:
case EXCP_RI:
{
uint32_t insn, op;
insn = tget32(env->PC);
op = insn >> 26;
// printf("insn=%08x op=%02x\n", insn, op);
/* XXX: totally dummy FP ops just to be able to launch
a few executables */
switch(op) {
case 0x31: /* LWC1 */
env->PC += 4;
break;
case 0x39: /* SWC1 */
env->PC += 4;
break;
case 0x11:
switch((insn >> 21) & 0x1f) {
case 0x02: /* CFC1 */
env->PC += 4;
break;
default:
goto sigill;
}
break;
default:
sigill:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = 0;
queue_signal(info.si_signo, &info);
break;
}
}
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = 0;
queue_signal(info.si_signo, &info);
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
default:
// error:
@@ -1391,7 +1366,7 @@ void cpu_loop(CPUMIPSState *env)
void cpu_loop (CPUState *env)
{
int trapnr, ret;
// target_siginfo_t info;
target_siginfo_t info;
while (1) {
trapnr = cpu_sh4_exec (env);
@@ -1399,16 +1374,30 @@ void cpu_loop (CPUState *env)
switch (trapnr) {
case 0x160:
ret = do_syscall(env,
env->gregs[0x13],
env->gregs[0x14],
env->gregs[0x15],
env->gregs[0x16],
env->gregs[0x17],
env->gregs[0x10],
env->gregs[3],
env->gregs[4],
env->gregs[5],
env->gregs[6],
env->gregs[7],
env->gregs[0],
0);
env->gregs[0x10] = ret;
env->gregs[0] = ret;
env->pc += 2;
break;
case EXCP_DEBUG:
{
int sig;
sig = gdb_handlesig (env, TARGET_SIGTRAP);
if (sig)
{
info.si_signo = sig;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
queue_signal(info.si_signo, &info);
}
}
break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_dump_state(env, stderr, fprintf, 0);
@@ -1514,6 +1503,8 @@ int main(int argc, char **argv)
}
} else if (!strcmp(r, "g")) {
gdbstub_port = atoi(argv[optind++]);
} else if (!strcmp(r, "r")) {
qemu_uname_release = argv[optind++];
} else
#ifdef USE_CODE_COPY
if (!strcmp(r, "no-code-copy")) {
@@ -1542,7 +1533,7 @@ int main(int argc, char **argv)
env = cpu_init();
global_env = env;
if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
if (loader_exec(filename, argv+optind, environ, regs, info) != 0) {
printf("Error loading %s\n", filename);
_exit(1);
}
@@ -1553,6 +1544,7 @@ int main(int argc, char **argv)
fprintf(logfile, "start_brk 0x%08lx\n" , info->start_brk);
fprintf(logfile, "end_code 0x%08lx\n" , info->end_code);
fprintf(logfile, "start_code 0x%08lx\n" , info->start_code);
fprintf(logfile, "start_data 0x%08lx\n" , info->start_data);
fprintf(logfile, "end_data 0x%08lx\n" , info->end_data);
fprintf(logfile, "start_stack 0x%08lx\n" , info->start_stack);
fprintf(logfile, "brk 0x%08lx\n" , info->brk);
@@ -1567,6 +1559,7 @@ int main(int argc, char **argv)
memset(ts, 0, sizeof(TaskState));
env->opaque = ts;
ts->used = 1;
ts->info = info;
env->user_mode_only = 1;
#if defined(TARGET_I386)
@@ -1696,6 +1689,9 @@ int main(int argc, char **argv)
env->gpr[i] = regs->regs[i];
}
env->PC = regs->cp0_epc;
#ifdef MIPS_USES_FPU
env->CP0_Status |= (1 << CP0St_CU1);
#endif
}
#elif defined(TARGET_SH4)
{
+40 -5
View File
@@ -18,6 +18,7 @@
struct image_info {
unsigned long start_code;
unsigned long end_code;
unsigned long start_data;
unsigned long end_data;
unsigned long start_brk;
unsigned long brk;
@@ -25,11 +26,9 @@ struct image_info {
unsigned long mmap;
unsigned long rss;
unsigned long start_stack;
unsigned long arg_start;
unsigned long arg_end;
unsigned long env_start;
unsigned long env_end;
unsigned long entry;
target_ulong code_offset;
target_ulong data_offset;
int personality;
};
@@ -76,14 +75,50 @@ typedef struct TaskState {
uint32_t v86mask;
#endif
int used; /* non zero if used */
struct image_info *info;
uint8_t stack[0];
} __attribute__((aligned(16))) TaskState;
extern TaskState *first_task_state;
extern const char *qemu_uname_release;
int elf_exec(const char * filename, char ** argv, char ** envp,
/* ??? See if we can avoid exposing so much of the loader internals. */
/*
* MAX_ARG_PAGES defines the number of pages allocated for arguments
* and envelope for the new program. 32 should suffice, this gives
* a maximum env+arg of 128kB w/4KB pages!
*/
#define MAX_ARG_PAGES 32
/*
* This structure is used to hold the arguments that are
* used when loading binaries.
*/
struct linux_binprm {
char buf[128];
void *page[MAX_ARG_PAGES];
unsigned long p;
int fd;
int e_uid, e_gid;
int argc, envc;
char **argv;
char **envp;
char * filename; /* Name of binary */
};
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop);
target_ulong loader_build_argptr(int envc, int argc, target_ulong sp,
target_ulong stringp, int push_ptr);
int loader_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop);
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info);
int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info);
void memcpy_to_target(target_ulong dest, const void *src,
unsigned long len);
void target_set_brk(target_ulong new_brk);
long do_brk(target_ulong new_brk);
void syscall_init(void);
+340 -8
View File
@@ -432,13 +432,17 @@ int do_sigaction(int sig, const struct target_sigaction *act,
if (oact) {
oact->_sa_handler = tswapl(k->sa._sa_handler);
oact->sa_flags = tswapl(k->sa.sa_flags);
oact->sa_restorer = tswapl(k->sa.sa_restorer);
#if !defined(TARGET_MIPS)
oact->sa_restorer = tswapl(k->sa.sa_restorer);
#endif
oact->sa_mask = k->sa.sa_mask;
}
if (act) {
k->sa._sa_handler = tswapl(act->_sa_handler);
k->sa.sa_flags = tswapl(act->sa_flags);
k->sa.sa_restorer = tswapl(act->sa_restorer);
#if !defined(TARGET_MIPS)
k->sa.sa_restorer = tswapl(act->sa_restorer);
#endif
k->sa.sa_mask = act->sa_mask;
/* we update the host linux signal state */
@@ -1330,28 +1334,28 @@ typedef struct {
unsigned long *insn_addr;
unsigned long insn;
} si_fpqueue [16];
} __siginfo_fpu_t;
} qemu_siginfo_fpu_t;
struct target_signal_frame {
struct sparc_stackf ss;
__siginfo_t info;
__siginfo_fpu_t *fpu_save;
qemu_siginfo_fpu_t *fpu_save;
target_ulong insns[2] __attribute__ ((aligned (8)));
target_ulong extramask[TARGET_NSIG_WORDS - 1];
target_ulong extra_size; /* Should be 0 */
__siginfo_fpu_t fpu_state;
qemu_siginfo_fpu_t fpu_state;
};
struct target_rt_signal_frame {
struct sparc_stackf ss;
siginfo_t info;
target_ulong regs[20];
sigset_t mask;
__siginfo_fpu_t *fpu_save;
qemu_siginfo_fpu_t *fpu_save;
unsigned int insns[2];
stack_t stack;
unsigned int extra_size; /* Should be 0 */
__siginfo_fpu_t fpu_state;
qemu_siginfo_fpu_t fpu_state;
};
#define UREG_O0 16
@@ -1496,7 +1500,7 @@ sigsegv:
force_sig(TARGET_SIGSEGV);
}
static inline int
restore_fpu_state(CPUState *env, __siginfo_fpu_t *fpu)
restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu)
{
int err;
#if 0
@@ -1618,6 +1622,334 @@ long do_rt_sigreturn(CPUState *env)
return -ENOSYS;
}
#elif defined(TARGET_MIPS)
struct target_sigcontext {
uint32_t sc_regmask; /* Unused */
uint32_t sc_status;
uint64_t sc_pc;
uint64_t sc_regs[32];
uint64_t sc_fpregs[32];
uint32_t sc_ownedfp; /* Unused */
uint32_t sc_fpc_csr;
uint32_t sc_fpc_eir; /* Unused */
uint32_t sc_used_math;
uint32_t sc_dsp; /* dsp status, was sc_ssflags */
uint64_t sc_mdhi;
uint64_t sc_mdlo;
target_ulong sc_hi1; /* Was sc_cause */
target_ulong sc_lo1; /* Was sc_badvaddr */
target_ulong sc_hi2; /* Was sc_sigset[4] */
target_ulong sc_lo2;
target_ulong sc_hi3;
target_ulong sc_lo3;
};
struct sigframe {
uint32_t sf_ass[4]; /* argument save space for o32 */
uint32_t sf_code[2]; /* signal trampoline */
struct target_sigcontext sf_sc;
target_sigset_t sf_mask;
};
/* Install trampoline to jump back from signal handler */
static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
{
int err;
/*
* Set up the return code ...
*
* li v0, __NR__foo_sigreturn
* syscall
*/
err = __put_user(0x24020000 + syscall, tramp + 0);
err |= __put_user(0x0000000c , tramp + 1);
/* flush_cache_sigtramp((unsigned long) tramp); */
return err;
}
static inline int
setup_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{
int err = 0;
err |= __put_user(regs->PC, &sc->sc_pc);
#define save_gp_reg(i) do { \
err |= __put_user(regs->gpr[i], &sc->sc_regs[i]); \
} while(0)
__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
save_gp_reg(31);
#undef save_gp_reg
err |= __put_user(regs->HI, &sc->sc_mdhi);
err |= __put_user(regs->LO, &sc->sc_mdlo);
/* Not used yet, but might be useful if we ever have DSP suppport */
#if 0
if (cpu_has_dsp) {
err |= __put_user(mfhi1(), &sc->sc_hi1);
err |= __put_user(mflo1(), &sc->sc_lo1);
err |= __put_user(mfhi2(), &sc->sc_hi2);
err |= __put_user(mflo2(), &sc->sc_lo2);
err |= __put_user(mfhi3(), &sc->sc_hi3);
err |= __put_user(mflo3(), &sc->sc_lo3);
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
}
/* same with 64 bit */
#ifdef CONFIG_64BIT
err |= __put_user(regs->hi, &sc->sc_hi[0]);
err |= __put_user(regs->lo, &sc->sc_lo[0]);
if (cpu_has_dsp) {
err |= __put_user(mfhi1(), &sc->sc_hi[1]);
err |= __put_user(mflo1(), &sc->sc_lo[1]);
err |= __put_user(mfhi2(), &sc->sc_hi[2]);
err |= __put_user(mflo2(), &sc->sc_lo[2]);
err |= __put_user(mfhi3(), &sc->sc_hi[3]);
err |= __put_user(mflo3(), &sc->sc_lo[3]);
err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
}
#endif
#endif
#if 0
err |= __put_user(!!used_math(), &sc->sc_used_math);
if (!used_math())
goto out;
/*
* Save FPU state to signal context. Signal handler will "inherit"
* current FPU state.
*/
preempt_disable();
if (!is_fpu_owner()) {
own_fpu();
restore_fp(current);
}
err |= save_fp_context(sc);
preempt_enable();
out:
#endif
return err;
}
static inline int
restore_sigcontext(CPUState *regs, struct target_sigcontext *sc)
{
int err = 0;
err |= __get_user(regs->CP0_EPC, &sc->sc_pc);
err |= __get_user(regs->HI, &sc->sc_mdhi);
err |= __get_user(regs->LO, &sc->sc_mdlo);
#define restore_gp_reg(i) do { \
err |= __get_user(regs->gpr[i], &sc->sc_regs[i]); \
} while(0)
restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
restore_gp_reg(31);
#undef restore_gp_reg
#if 0
if (cpu_has_dsp) {
err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
}
#ifdef CONFIG_64BIT
err |= __get_user(regs->hi, &sc->sc_hi[0]);
err |= __get_user(regs->lo, &sc->sc_lo[0]);
if (cpu_has_dsp) {
err |= __get_user(treg, &sc->sc_hi[1]); mthi1(treg);
err |= __get_user(treg, &sc->sc_lo[1]); mthi1(treg);
err |= __get_user(treg, &sc->sc_hi[2]); mthi2(treg);
err |= __get_user(treg, &sc->sc_lo[2]); mthi2(treg);
err |= __get_user(treg, &sc->sc_hi[3]); mthi3(treg);
err |= __get_user(treg, &sc->sc_lo[3]); mthi3(treg);
err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
}
#endif
err |= __get_user(used_math, &sc->sc_used_math);
conditional_used_math(used_math);
preempt_disable();
if (used_math()) {
/* restore fpu context if we have used it before */
own_fpu();
err |= restore_fp_context(sc);
} else {
/* signal handler may have used FPU. Give it up. */
lose_fpu();
}
preempt_enable();
#endif
return err;
}
/*
* Determine which stack to use..
*/
static inline void *
get_sigframe(struct emulated_sigaction *ka, CPUState *regs, size_t frame_size)
{
unsigned long sp;
/* Default to using normal stack */
sp = regs->gpr[29];
/*
* FPU emulator may have it's own trampoline active just
* above the user stack, 16-bytes before the next lowest
* 16 byte boundary. Try to avoid trashing it.
*/
sp -= 32;
#if 0
/* This is the X/Open sanctioned signal stack switching. */
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
#endif
return g2h((sp - frame_size) & ~7);
}
static void setup_frame(int sig, struct emulated_sigaction * ka,
target_sigset_t *set, CPUState *regs)
{
struct sigframe *frame;
int i;
frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv;
install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
if(setup_sigcontext(regs, &frame->sf_sc))
goto give_sigsegv;
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if(__put_user(set->sig[i], &frame->sf_mask.sig[i]))
goto give_sigsegv;
}
/*
* Arguments to signal handler:
*
* a0 = signal number
* a1 = 0 (should be cause)
* a2 = pointer to struct sigcontext
*
* $25 and PC point to the signal handler, $29 points to the
* struct sigframe.
*/
regs->gpr[ 4] = sig;
regs->gpr[ 5] = 0;
regs->gpr[ 6] = h2g(&frame->sf_sc);
regs->gpr[29] = h2g(frame);
regs->gpr[31] = h2g(frame->sf_code);
/* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
regs->PC = regs->gpr[25] = ka->sa._sa_handler;
return;
give_sigsegv:
force_sig(TARGET_SIGSEGV/*, current*/);
return;
}
long do_sigreturn(CPUState *regs)
{
struct sigframe *frame;
sigset_t blocked;
target_sigset_t target_set;
int i;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "do_sigreturn\n");
#endif
frame = (struct sigframe *) regs->gpr[29];
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if(__get_user(target_set.sig[i], &frame->sf_mask.sig[i]))
goto badframe;
}
target_to_host_sigset_internal(&blocked, &target_set);
sigprocmask(SIG_SETMASK, &blocked, NULL);
if (restore_sigcontext(regs, &frame->sf_sc))
goto badframe;
#if 0
/*
* Don't let your children do this ...
*/
__asm__ __volatile__(
"move\t$29, %0\n\t"
"j\tsyscall_exit"
:/* no outputs */
:"r" (&regs));
/* Unreached */
#endif
regs->PC = regs->CP0_EPC;
/* I am not sure this is right, but it seems to work
* maybe a problem with nested signals ? */
regs->CP0_EPC = 0;
return 0;
badframe:
force_sig(TARGET_SIGSEGV/*, current*/);
return 0;
}
static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
target_siginfo_t *info,
target_sigset_t *set, CPUState *env)
{
fprintf(stderr, "setup_rt_frame: not implemented\n");
}
long do_rt_sigreturn(CPUState *env)
{
fprintf(stderr, "do_rt_sigreturn: not implemented\n");
return -ENOSYS;
}
#else
+138
View File
@@ -0,0 +1,138 @@
#if defined(TARGET_MIPS)
// MIPS special values for constants
/*
* For setsockopt(2)
*
* This defines are ABI conformant as far as Linux supports these ...
*/
#define TARGET_SOL_SOCKET 0xffff
#define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */
#define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */
#define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send
SIGPIPE when they die. */
#define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */
#define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of
broadcast messages. */
#define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable
socket to transmit pending data. */
#define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */
#if 0
To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
#endif
#define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */
#define TARGET_SO_STYLE SO_TYPE /* Synonym */
#define TARGET_SO_ERROR 0x1007 /* get error status and clear */
#define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */
#define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */
#define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */
#define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */
#define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */
#define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */
#define TARGET_SO_ACCEPTCONN 0x1009
/* linux-specific, might as well be the same as on i386 */
#define TARGET_SO_NO_CHECK 11
#define TARGET_SO_PRIORITY 12
#define TARGET_SO_BSDCOMPAT 14
#define TARGET_SO_PASSCRED 17
#define TARGET_SO_PEERCRED 18
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define TARGET_SO_SECURITY_AUTHENTICATION 22
#define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
#define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
#define TARGET_SO_BINDTODEVICE 25
/* Socket filtering */
#define TARGET_SO_ATTACH_FILTER 26
#define TARGET_SO_DETACH_FILTER 27
#define TARGET_SO_PEERNAME 28
#define TARGET_SO_TIMESTAMP 29
#define SCM_TIMESTAMP SO_TIMESTAMP
#define TARGET_SO_PEERSEC 30
#define TARGET_SO_SNDBUFFORCE 31
#define TARGET_SO_RCVBUFFORCE 33
/** sock_type - Socket types
*
* Please notice that for binary compat reasons MIPS has to
* override the enum sock_type in include/linux/net.h, so
* we define ARCH_HAS_SOCKET_TYPES here.
*
* @SOCK_DGRAM - datagram (conn.less) socket
* @SOCK_STREAM - stream (connection) socket
* @SOCK_RAW - raw socket
* @SOCK_RDM - reliably-delivered message
* @SOCK_SEQPACKET - sequential packet socket
* @SOCK_PACKET - linux specific way of getting packets at the dev level.
* For writing rarp and other similar things on the user level.
*/
enum sock_type {
TARGET_SOCK_DGRAM = 1,
TARGET_SOCK_STREAM = 2,
TARGET_SOCK_RAW = 3,
TARGET_SOCK_RDM = 4,
TARGET_SOCK_SEQPACKET = 5,
TARGET_SOCK_DCCP = 6,
TARGET_SOCK_PACKET = 10,
};
#define TARGET_SOCK_MAX (SOCK_PACKET + 1)
#else
/* For setsockopt(2) */
#define TARGET_SOL_SOCKET 1
#define TARGET_SO_DEBUG 1
#define TARGET_SO_REUSEADDR 2
#define TARGET_SO_TYPE 3
#define TARGET_SO_ERROR 4
#define TARGET_SO_DONTROUTE 5
#define TARGET_SO_BROADCAST 6
#define TARGET_SO_SNDBUF 7
#define TARGET_SO_RCVBUF 8
#define TARGET_SO_SNDBUFFORCE 32
#define TARGET_SO_RCVBUFFORCE 33
#define TARGET_SO_KEEPALIVE 9
#define TARGET_SO_OOBINLINE 10
#define TARGET_SO_NO_CHECK 11
#define TARGET_SO_PRIORITY 12
#define TARGET_SO_LINGER 13
#define TARGET_SO_BSDCOMPAT 14
/* To add :#define TARGET_SO_REUSEPORT 15 */
#define TARGET_SO_PASSCRED 16
#define TARGET_SO_PEERCRED 17
#define TARGET_SO_RCVLOWAT 18
#define TARGET_SO_SNDLOWAT 19
#define TARGET_SO_RCVTIMEO 20
#define TARGET_SO_SNDTIMEO 21
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define TARGET_SO_SECURITY_AUTHENTICATION 22
#define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23
#define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24
#define TARGET_SO_BINDTODEVICE 25
/* Socket filtering */
#define TARGET_SO_ATTACH_FILTER 26
#define TARGET_SO_DETACH_FILTER 27
#define TARGET_SO_PEERNAME 28
#define TARGET_SO_TIMESTAMP 29
#define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP
#define TARGET_SO_ACCEPTCONN 30
#define TARGET_SO_PEERSEC 31
#endif
Loaded 100 of 164 files, more files were not shown because too many files have changed in this diff. Show more