Compare commits

..

1392 Commits

Author SHA1 Message Date
(no author)
bebe39c387 This commit was manufactured by cvs2svn to create tag
'release_0_8_1'.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_8_1@1898 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 20:18:44 +00:00
bellard
215cf0bed8 removed sh4 user build (not usable yet)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1897 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 20:18:43 +00:00
bellard
691fce48a3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1896 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 20:15:47 +00:00
bellard
8dbca8dd8a separate alias_addr (10.0.2.2) from our_addr (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1895 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 19:58:17 +00:00
bellard
68cae3d8c1 bswapq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1894 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-03 19:17:26 +00:00
bellard
c91fde65f4 correct qemu-system-mipsel naming
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1893 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-02 22:52:36 +00:00
bellard
f5d2a381d1 performance boost (on P4 hosts at least, rdtsc is a _very_ bad random generator)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1892 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-02 22:18:28 +00:00
bellard
e553272d75 > 32 KB packet handling (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1891 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-02 21:09:02 +00:00
bellard
3aee288bc8 fixed memory leak
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1890 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-02 20:54:12 +00:00
bellard
bdbd7676fd uppercase fix (Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1889 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 21:44:22 +00:00
bellard
38cfa06cbd Solaris port (Ben Taylor)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1888 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 13:58:07 +00:00
bellard
e035649ea3 use a single select for slirp and qemu sockets
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1887 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 13:33:02 +00:00
bellard
29e3055c37 workaround: force /dev/rtc usage on Linux
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1886 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 13:28:36 +00:00
bellard
06d9f2f7d4 better win32 timers - use win32 event to wake up cpu in idle mode (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1885 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 13:23:04 +00:00
bellard
eade0f192e fix for hosts resuming from software suspend (initial patch by John Coiner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1884 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 12:43:29 +00:00
bellard
07de1eaa9d increase max kernel size with initrd
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1883 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 12:31:24 +00:00
bellard
4f552e3b9a do not delay TCP acks (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1882 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 11:18:01 +00:00
bellard
773f2cdd3c set TCP_MSS to 1460 (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1881 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 11:17:27 +00:00
bellard
fedc54adaa fixed IP packet rassembly logic (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1880 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 11:02:11 +00:00
bellard
4b6ccfdec9 fixed realloc logic (Ed Swierk)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1879 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 10:59:02 +00:00
bellard
7d510b8c0c copyright
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1878 c046a42c-6fe2-441c-8c8c-71466251a162
2006-05-01 10:38:19 +00:00
pbrook
38954dca9f Add install-doc rule. Use it when building docs.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1877 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 23:54:18 +00:00
bellard
6ca957f08f win32 socket fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1876 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 22:53:25 +00:00
bellard
f354832878 info and dvi doc targets
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1875 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 22:51:54 +00:00
bellard
45a8f3ca06 typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1874 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 22:20:58 +00:00
bellard
debc70650a Enhanced Documentation (Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1873 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 21:58:41 +00:00
bellard
985d1742db fixes for more than 8 ports - return NAK if no change - FreeBSD workaround (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1872 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 21:53:59 +00:00
bellard
3f423c9c8f removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1871 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 21:34:15 +00:00
bellard
7f881e5674 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1870 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 21:33:34 +00:00
bellard
24236869fb VNC server (Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1869 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-30 21:28:36 +00:00
pbrook
a46e4035e2 Fix non-portable use of expr.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1868 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-29 23:05:22 +00:00
bellard
4dbe19e181 ELCR is not reset by PIC reset (bug report by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1867 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-29 15:52:14 +00:00
bellard
a1e7547389 APM CPU idle fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1866 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-28 22:47:21 +00:00
pbrook
7918bf476b Fix typo in BSD FP rounding mode names.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1865 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-28 15:26:51 +00:00
pbrook
1640695026 Add nominal ARM Versatil/AB board emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1864 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-27 23:15:07 +00:00
pbrook
008a8818d9 Fix build failure.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1863 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-27 22:32:36 +00:00
bellard
27c7ca7e77 SHIX board emulation (Samuel Tardieu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1862 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-27 21:32:09 +00:00
bellard
fdf9b3e831 sh4 target (Samuel Tardieu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1861 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-27 21:07:38 +00:00
bellard
66a93e0f47 ELF loader (Thiemo Seufer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1860 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-26 22:06:55 +00:00
bellard
9ee3c02942 added entry parameter to ELF loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1859 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-26 22:05:26 +00:00
pbrook
94ac515889 Solaris configure hacks.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1858 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-26 16:07:35 +00:00
pbrook
3598ecb620 Remove missing include.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1857 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-26 15:55:55 +00:00
bellard
a8ca632cc0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1856 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-25 22:36:31 +00:00
bellard
ec530c81ef Solaris port (Ben Taylor)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1855 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-25 22:36:06 +00:00
bellard
96b74a0221 enable APIC by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1854 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-25 21:27:42 +00:00
bellard
c2ff060fd4 LBA48 support (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1853 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-25 21:24:22 +00:00
bellard
467d409f7e fix for HCHALTED status bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1852 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-25 21:01:19 +00:00
bellard
fd06c37550 PC speaker emulation (Joachim Henke)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1851 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 21:58:30 +00:00
bellard
52328140e2 HCHALTED status bit handling (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1850 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 21:38:50 +00:00
bellard
135e73c5f7 do not set PORT_STAT_C_ENABLE when doing port reset (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1849 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 21:25:26 +00:00
bellard
72899afc5d separate file for usb hub device
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1848 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 21:18:20 +00:00
bellard
56bebe70bd usb setup state machine fix when driver reads or writes too many bytes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1847 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 21:10:52 +00:00
bellard
fd4a43e4e2 ia64 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1846 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 20:32:17 +00:00
bellard
ad1a5b7853 rol/ror cc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1845 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 20:19:07 +00:00
bellard
6c3ee14ff3 better shift tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1844 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 20:18:26 +00:00
bellard
ba6526df38 movddup fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1843 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-24 20:14:56 +00:00
bellard
1b2b0af50d 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1842 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 22:59:41 +00:00
bellard
e774a278d8 -win2k-hack performance+DMA support (Leonardo E. Reiter)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1841 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 22:21:30 +00:00
bellard
fa7cf687ac warning fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1840 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 21:57:03 +00:00
bellard
465e983875 SSE3 support (Joachim Henke)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1839 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 21:54:01 +00:00
bellard
b854608e0c sparc condition code computation fix (Even Rouault)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1838 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 21:33:48 +00:00
pbrook
f4e15b4b4b Fix slirp redirection on systems without a useful host IP address.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1837 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 19:41:17 +00:00
bellard
bbeb7b5cbd SIGINT generation (Jason Wessel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1836 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 18:42:15 +00:00
bellard
f9ebe432db removed unnecessary header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1835 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 18:18:10 +00:00
pbrook
cc8ae6de58 Autodetect tools neccessary for building documentation.
Make distclean remove generated documentation files.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1834 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 17:57:59 +00:00
bellard
d0ecd2aaf9 added cpu_physical_memory_write_rom()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1833 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 17:14:48 +00:00
bellard
b37837317f use generic ELF loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1832 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 17:14:05 +00:00
bellard
5fe141fd30 generic ELF loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1831 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 17:12:42 +00:00
bellard
ce2f4b3cb9 MIPS single stepping fix (Dirk Behme)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1830 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 15:23:48 +00:00
bellard
cd7dd10f09 MIPS CP0 not usable in kernel mode (Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1829 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 15:21:24 +00:00
bellard
76e050c2e6 Fix overflow conditions for MIPS add / subtract (Stefan Weil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1828 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 15:18:58 +00:00
bellard
da2414e933 moved misplaced declaration
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1827 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 14:36:41 +00:00
bellard
a7350fa109 check if specified compiler exists
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1826 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-23 14:35:23 +00:00
pbrook
132ea32fae Fix display resize bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1825 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-18 19:02:59 +00:00
pbrook
d7ce493a38 Initialize PCI BAR config data.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1824 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-18 16:55:22 +00:00
pbrook
6a8826434f Allow user to specify "install" utility.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1823 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-17 13:57:12 +00:00
pbrook
a03a60532a Fix typo.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1822 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 18:46:12 +00:00
pbrook
9c03850684 Typo in error message.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1821 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 15:19:15 +00:00
pbrook
99773bd4b4 Fix DEBUG_TB_CHECK build failure (balrog).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1820 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 15:14:59 +00:00
pbrook
2483668940 Implement acct and pretend to implement madvise.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1819 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 14:14:53 +00:00
pbrook
d4b8f0396a Add quotes missing from previous patch.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1818 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 13:49:23 +00:00
pbrook
8606e5b450 Remove stray "}".
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1817 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 13:34:44 +00:00
pbrook
b1a550a0da Remove non-portable code from configure.
Allow newline at end of VERSION file.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1816 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 13:28:56 +00:00
pbrook
0f8134bfd6 Downgrade DNS failure to a warning.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1815 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 13:02:00 +00:00
pbrook
ad06484063 Fix out of tree builds.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1814 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 12:41:07 +00:00
pbrook
115defd163 Set slirp client hostname.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1813 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-16 11:06:58 +00:00
bellard
ffcdb539de mouse API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1812 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 21:59:55 +00:00
bellard
210fe0be2a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1811 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 21:09:31 +00:00
bellard
09b26c5ec0 USB tablet support (Brad Campbell, Anthony Liguori)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1810 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 21:09:08 +00:00
bellard
6a15fd12ca 64 bit disassembly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1809 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 21:07:07 +00:00
bellard
3e749fe1f7 simulate a null modem cable
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1808 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 20:42:42 +00:00
bellard
f331110f35 win32 serial port support (initial patch by kazu
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1807 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-12 20:21:17 +00:00
pbrook
1236cab73d DESTDIR makefile support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1806 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-09 20:47:35 +00:00
pbrook
358bf29e80 Thumb prefetch abort fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1805 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-09 14:38:57 +00:00
pbrook
cdbdb648b7 ARM Versatile Platform Baseboard emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1804 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-09 01:32:52 +00:00
pbrook
95219897ff Allow multiple graphics devices.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1803 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-09 01:06:34 +00:00
pbrook
07435f7462 Fix incorrect return type.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1802 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 23:32:52 +00:00
pbrook
e3f4e2a4b0 Initialize physical memory space to IO_MEM_UNASSIGNED.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1801 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 20:02:06 +00:00
pbrook
706cd4b547 Fix typo in previous patch.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1800 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 17:36:21 +00:00
pbrook
c2f07f81a2 Fix breakpoint TLB invalidation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1799 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 17:14:56 +00:00
pbrook
af5db58e8b Move configure --help output before gcc checks.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1798 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 14:26:41 +00:00
pbrook
7783e9f002 Keyboard savevm fix (malc).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1797 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-08 14:12:31 +00:00
bellard
33698e5ffc btx decode fix on x86_64
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1796 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-02 19:13:41 +00:00
bellard
894244f6ca do not test reserved config bits
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1795 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-02 19:11:31 +00:00
bellard
1298fe6316 CDROM detection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1794 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-02 19:10:47 +00:00
bellard
307b0c24de update to latest Bochs bios - added PCI BIOS real mode 'get irq routing options' function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1793 c046a42c-6fe2-441c-8c8c-71466251a162
2006-04-02 19:10:24 +00:00
bellard
61b9415691 update links
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1792 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-31 21:17:44 +00:00
pbrook
89ba1a738e Use 3-argument open call when creating file.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1791 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-28 20:20:38 +00:00
pbrook
53a5960aad Avoid accessing guest memory directly in usermode emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1790 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-25 19:31:22 +00:00
bellard
26f69dc09f upgrade to latest vgabios version - added Video Parameter Table support - added 1600x1200x8 Cirrus mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1789 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-25 01:25:02 +00:00
pbrook
cad25d69ad Rename --*able-softmmu --*able-system.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1788 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-19 16:31:11 +00:00
pbrook
0a8e90f401 Configure options to enable/disable all softmmu/user targets.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1787 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-19 14:54:16 +00:00
pbrook
8637c67fc5 Fix FIQ bank switching.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1786 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-14 14:20:32 +00:00
pbrook
d80cfb3f70 Add missing break statement.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1785 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 21:46:12 +00:00
pbrook
19b045dec9 Fix FPA condition codes (Ulrich Hecht).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1784 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 21:03:16 +00:00
pbrook
b55669bf57 Set SO_REUSEADDR before calling bind().
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1783 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 20:48:36 +00:00
pbrook
f5ba07d399 Fix typo in ppc icache flush.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1782 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 20:43:48 +00:00
pbrook
ce5c37c2a4 Fix off by one length calciulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1781 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 20:37:58 +00:00
pbrook
5b31187812 Make sure gui_key_modifier_pressed is cleared correctly.
Use correct event fields for SDL_ACTIVEEVENT.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1780 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 20:07:45 +00:00
pbrook
38ca0f6dee Tweak UHCI device settings. Ignore host root hubs.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1779 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 18:03:38 +00:00
pbrook
09c56b842e Avoid flushing of global TLB entries for differing ASIDs (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1778 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 16:39:23 +00:00
pbrook
ecd78a0ac7 Clear MIPS_HFLAG_BMASK for ErrorEPC (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1777 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 16:35:30 +00:00
pbrook
4e9aec746e Sparcf ESP dma fixes (Blue Swirl).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1776 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 16:29:14 +00:00
pbrook
56b194039e Rename MIPS_HFLAG(S)_TMASK (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1775 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 16:23:39 +00:00
pbrook
98c1b82b6c e bitfields in mips TLB structures (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1774 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 16:20:36 +00:00
pbrook
6d6f7c288d Improved terminal emulation (Piotr Esden-Tempski).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1773 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 15:35:30 +00:00
pbrook
d2ec1774eb Add missing function prototype.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1772 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 15:00:08 +00:00
pbrook
38260998a2 mipsel configure support (Thiemo Seufer).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1771 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 14:51:13 +00:00
pbrook
647c593038 Add missing FORCE_RET()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1770 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-11 14:46:59 +00:00
bellard
9540a78b90 x86_64 stack alignment fixes - x86_64 32 bit syscall fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1769 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-03 01:54:40 +00:00
pbrook
e10c2bfb73 Add missing return statement.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1768 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-02 23:58:13 +00:00
bellard
023e9351d0 suppressed invalid test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1767 c046a42c-6fe2-441c-8c8c-71466251a162
2006-03-02 21:52:18 +00:00
pbrook
ed96ca3571 Update Arm docs.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1766 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-20 00:35:00 +00:00
pbrook
40f137e1ea Add Arm926 core support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1765 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-20 00:33:36 +00:00
pbrook
4081fccf14 WIn32 compile fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1764 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-19 12:40:00 +00:00
pbrook
be9d365723 PL110 byteswapping fix.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1763 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-19 12:31:32 +00:00
pbrook
242011157f Fix Arm big-endian host bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1762 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-13 14:16:52 +00:00
pbrook
2ae23e7504 Fix Arm msr spsr bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1761 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-11 16:20:39 +00:00
pbrook
3b7f5d479c Avoid crash if -redir or -smb used without -net user.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1760 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-10 17:34:02 +00:00
bellard
1247c5f7be always compile 'int' traces
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1759 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-09 21:54:36 +00:00
bellard
e0b3073f53 BIOS workarounds for kqemu
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1758 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-09 21:51:02 +00:00
pbrook
29517134c6 Record configure commandline.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1757 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-09 17:58:47 +00:00
pbrook
ce4defa062 Arm Linux EABI syscall support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1756 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-09 16:49:55 +00:00
bellard
b88a38324b kqemu.h include path fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1755 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:59:35 +00:00
bellard
89bfc105d0 added last_io_time field - '-kernel-kqemu' experimental option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1754 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:46:31 +00:00
bellard
f32fc64851 optional support for kernel code virtualization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1753 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:43:39 +00:00
bellard
f1c85677fc added last_io_time field
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1752 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:41:53 +00:00
bellard
5f1ce9487c support for builtin profiler
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1751 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:40:15 +00:00
bellard
05c2a3e731 kqemu/qvm86 must now be compiled outside QEMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1750 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 22:39:17 +00:00
pbrook
f94f5d717c Add support for raw AT keyboard scancodes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1749 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-08 04:42:17 +00:00
pbrook
3aa22b4b53 Fix Thumb variable shift condition code bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1748 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-07 03:34:35 +00:00
pbrook
af2f67333f Fix -nographic on Arm.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1747 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-06 16:05:19 +00:00
pbrook
bdd5003ae5 Arm display emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1746 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-06 04:11:15 +00:00
pbrook
a41b2ff2dd Allow selection of emulated network card.
rtl8139 emulation.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1745 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-05 04:14:41 +00:00
pbrook
d861b05ea3 Avoid buffer overflow when sending slirp packets.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1744 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 22:15:28 +00:00
pbrook
191abaa2f0 Fix Arm interrupted ldm bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1743 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 21:50:36 +00:00
pbrook
3442e8964e 64-bit host/cross fixes.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1742 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 20:47:57 +00:00
pbrook
e89f07d384 Make target_mmap always return -1 on failure.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1741 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 20:46:24 +00:00
pbrook
06c949e62a Implement Arm BKPT instruction.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1740 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 19:35:26 +00:00
pbrook
0240ded8bb Correctly initialize Arm CPU for Thumb entry points.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1739 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 19:30:51 +00:00
bellard
0fd14b72ac fxsave/fxrstor fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1738 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-04 17:40:20 +00:00
bellard
7fb843f8cc tap win32 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1737 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 23:06:55 +00:00
bellard
9445880298 correct DMA and transfer mode reporting (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1736 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 22:20:12 +00:00
bellard
8147cfca56 added --enable-cocoa in help (Pavel Janík)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1735 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 21:45:16 +00:00
bellard
28a5c9c8b2 use uint8_t instead of char
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1734 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 21:43:52 +00:00
bellard
acff9df6a8 rxcr save/restore (initial patch by Jürgen Pfennig
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1733 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 21:40:18 +00:00
bellard
039af320d9 clearer -net doc (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1732 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 21:30:55 +00:00
bellard
fd1dff4b41 win32 socket support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1731 c046a42c-6fe2-441c-8c8c-71466251a162
2006-02-01 21:29:26 +00:00
bellard
ff3fbb307d kqemu and SMP are currently not compatible
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1730 c046a42c-6fe2-441c-8c8c-71466251a162
2006-01-08 10:53:14 +00:00
bellard
90dc3b395f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1729 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-19 22:28:04 +00:00
bellard
85b2c68832 vvfat note
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1728 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-19 22:12:34 +00:00
bellard
48c2f068e4 win32 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1727 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-19 22:11:49 +00:00
bellard
1538800276 workaround for gcc bug on PowerPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1726 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-19 01:42:32 +00:00
bellard
6a36d84e10 suppressed -enable-audio and simplified -soundhw option handling (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1725 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 20:34:32 +00:00
bellard
3f9f3aa1ca MIPS, ARM and SMP updates
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1724 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 20:11:37 +00:00
bellard
31febb71f4 log typos
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1723 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 20:03:27 +00:00
bellard
2d7a3b9d7b qruncom compile fixes (initial patch by Even Rouault)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1722 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 19:28:08 +00:00
bellard
7c206a754a (Joachim Henke)
- suppress unwanted kernel logs
- avoids passing modifier keys to the guest OS when typing in the Monitor
- fixes the bug that the mouse cursor grab is released with _any_ modifier key
  (should be only ctrl+alt)
- removes some code redundancies


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1721 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 19:18:45 +00:00
bellard
2efc32658e better help option support (Bernhard Fischer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1720 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 19:14:49 +00:00
bellard
91fc211974 avoid echo on pty devices (David Decotigny) - fixes in the command line help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1719 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 19:09:37 +00:00
bellard
2c6cadd49e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1718 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 18:31:45 +00:00
bellard
a046433a16 Major overhaul of the virtual FAT driver for read/write support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1717 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 18:29:50 +00:00
bellard
95389c8681 qcow_make_empty() support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1716 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 18:28:15 +00:00
bellard
1658b44bf5 use IPPROTO_IP instead of SOL_IP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1715 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 18:02:24 +00:00
bellard
183b4a3806 do not init ne2000 if no network enabled
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1714 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 17:51:01 +00:00
bellard
5198cfd927 smc91c111 fixes (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1713 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 17:39:52 +00:00
bellard
68998c5de3 cpu_reset() fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1712 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 16:55:25 +00:00
bellard
6d7e63262c switching to Arm mode in do_interrupt() (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1711 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 16:54:08 +00:00
bellard
3d830459b1 '-net socket,mcast=' option support (initial patch by Juan Jose Ciarlante)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1710 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-18 16:36:49 +00:00
bellard
87022ff52b moved mp config table to a safer place
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1709 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 14:02:29 +00:00
bellard
cd072e01d8 fixed null segment validation (aka x86_64 regression bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1708 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 02:59:58 +00:00
bellard
d3e9db933f initial support for up to 255 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1707 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 01:27:28 +00:00
bellard
01dbbdf1e5 disable debug mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1706 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 01:11:12 +00:00
bellard
76b3030c56 mipsel disas fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1705 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 01:10:04 +00:00
bellard
265d349776 switch_tss fix (aka spoon OS bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1704 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-17 01:05:42 +00:00
bellard
dbf2c23a60 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1703 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:48:41 +00:00
bellard
56902eee82 more targets
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1702 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:44:55 +00:00
bellard
9f25f11fe5 fix for mipsel (will need change for softmmu case)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1701 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:44:28 +00:00
bellard
909a8762ee mips and mipsel support - fixed e_type mask
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1700 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:43:35 +00:00
bellard
c20eb47362 mipsel-user target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1699 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:42:55 +00:00
bellard
01f5e596ed mipsel target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1698 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:42:17 +00:00
bellard
ea31eb5b0c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1697 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-06 21:42:03 +00:00
bellard
cc4adeef98 added MIPS user in automatic tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1696 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 21:04:50 +00:00
bellard
6900e84b20 handle coprocessor exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1695 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 21:04:24 +00:00
bellard
ba3c64fb47 Initial SPARC SMP support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1694 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 20:31:52 +00:00
bellard
b9788fc4c4 cdrom_read_toc support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1693 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 20:30:36 +00:00
bellard
227671c93b PAGE_EXEC support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1692 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 20:29:47 +00:00
bellard
f881a0d4f6 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1691 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 20:00:00 +00:00
bellard
4ad40f366f MIPS fixes (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1690 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:59:36 +00:00
bellard
6810e15490 MIPS halt support - MIPS static state fix (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1689 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:59:05 +00:00
bellard
a64d4718f1 MIPS unaligned accesses exceptions (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1688 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:57:57 +00:00
bellard
2d7272a588 kernel command line support (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1687 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:56:38 +00:00
bellard
30d6cb8479 correct MIPS state restoring (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1686 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:56:07 +00:00
bellard
6f970bd90e MIPS support and memory access error reporting (Daniel Jacobowitz)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1685 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-05 19:55:19 +00:00
bellard
89984cd2e5 segment validation fix in lret/iret
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1684 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-04 22:17:10 +00:00
bellard
ee0971849e Arm mulxy insn fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1683 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-04 18:56:28 +00:00
bellard
80337b66a8 NIC emulation for qemu arm-softmmu (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1682 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-04 18:54:21 +00:00
bellard
54ca9095f0 generate GPF if non canonical addresses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1681 c046a42c-6fe2-441c-8c8c-71466251a162
2005-12-04 18:46:06 +00:00
bellard
56c8f68f1d statfs fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1680 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 22:28:41 +00:00
bellard
c960bde13c correct ioctls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1679 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 22:28:16 +00:00
bellard
148f50581b uid32 syscalls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1678 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 22:28:07 +00:00
bellard
4b4f782c78 NX support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1677 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 21:19:42 +00:00
bellard
84b7b8e778 PAGE_EXEC support in TLBs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1676 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 21:19:04 +00:00
bellard
5cf3839607 nx defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1675 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 21:02:43 +00:00
bellard
5732fd2779 x86_64 ldl fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1674 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 21:02:17 +00:00
bellard
649ea05a2c x86_64 lcall fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1673 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-28 21:01:52 +00:00
bellard
7664728bdf win32 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1672 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-27 19:10:42 +00:00
bellard
50443c98e4 specialize the power save code for 7x0 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1671 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 20:15:14 +00:00
bellard
6f5a9f7e56 fixed async signal support for tb_phys_invalidate()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1670 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 20:12:28 +00:00
bellard
4a38940da0 using _exit in fork() (Kamo Hiroyasu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1669 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 20:10:07 +00:00
bellard
048f6b4df7 mips user emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1668 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 18:47:20 +00:00
bellard
eeef26cd42 fixed BLTZAL and BLTZALL insns - fixed regressions from jmp opts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1667 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 18:47:06 +00:00
bellard
cc9442b9fc fixed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1666 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 18:43:28 +00:00
bellard
15338fd765 added AT_PLATFORM and AT_HWCAP for x86 (initial patch by Gwenole Beauchesne)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1665 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 11:41:16 +00:00
bellard
79639d423f update boot sector when using -kernel (Magnus Damm)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1664 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:58:41 +00:00
bellard
9332f9dafa ARM CPU suspend/halt (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1663 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:46:39 +00:00
bellard
e8ebb8a8d7 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1662 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:39:51 +00:00
bellard
b5ff1b3127 ARM system emulation (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1661 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:38:39 +00:00
bellard
0e43e99c04 PS2 mouse and keyboard separation (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1660 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:36:25 +00:00
bellard
98699967b8 use TARGET_PAGE_SIZE (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1659 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:29:22 +00:00
bellard
daa579632d PS2 mouse and keyboard separation (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1658 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-26 10:14:03 +00:00
bellard
e80e1cc4b1 halt state support for ppc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1657 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 22:05:28 +00:00
bellard
f24e5695e5 avoid generating useless exceptions (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1656 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:36:30 +00:00
bellard
7668a27f1d openpic SMP support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1655 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:13:45 +00:00
bellard
e5d13e2f64 more generic serial port (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1654 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:11:49 +00:00
bellard
2023a2c836 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1653 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:03:04 +00:00
bellard
5a1e3cfcb0 better halted state support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1652 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:02:53 +00:00
bellard
d2ac63e03e added HF_HALTED bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1651 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:02:10 +00:00
bellard
ad49ff9de3 use HF_HALTED bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1650 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:01:33 +00:00
bellard
15a7644956 better SMP scheduling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1649 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 21:01:03 +00:00
bellard
8dd69b8f2c fummy DM_LOWPRI handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1648 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-23 20:59:44 +00:00
bellard
089af99118 RTL8029 IDs support (Warner Losh)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1647 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-22 20:16:13 +00:00
bellard
3476562d36 monitor_disas() prototype change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1646 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:35:10 +00:00
bellard
59b8ad81c4 SMP support - cpu_single_env usage fix - a20 helpers - dynamic Multi Processor BIOS table generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1645 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:34:32 +00:00
bellard
c68ea7043f cpu_single_env usage fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1644 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:33:12 +00:00
bellard
173d6cfe51 cpu_exec_init() change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1643 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:32:20 +00:00
bellard
0e1fd3694e target_disas() little endian change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1642 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:32:10 +00:00
bellard
e0fd87812f APIC fixes - SIPI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1641 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:26:26 +00:00
bellard
6a00d60127 SMP support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1640 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:25:50 +00:00
bellard
f0aca8227f fixed big endian host support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1639 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-21 23:22:06 +00:00
bellard
e59c11393b make the number of buffers settable (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1638 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 18:53:42 +00:00
bellard
32d448c470 added LF missing in logs (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1637 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 18:53:05 +00:00
bellard
571ec3d68d audio merge (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1636 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 16:24:34 +00:00
bellard
5e941d4b51 workaround for atexit - buffer size API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1635 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 16:24:09 +00:00
bellard
509035303d wav finalization fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1634 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 16:22:16 +00:00
bellard
546754dc1d pcm endianness is now explicit (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1633 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 16:20:39 +00:00
bellard
8a40a180d3 make the TB cache independent of MMU mappings (faster MMU context switches and needed for SMP support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1632 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 10:35:40 +00:00
bellard
313adae905 removed unneeded code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1631 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 10:33:00 +00:00
bellard
a316d3353c added CPU_COMMON and CPUState.tb_jmp_cache[]
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1630 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 10:32:34 +00:00
bellard
6e256c935c use direct jump only for jumps in the same page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1629 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 10:32:05 +00:00
bellard
c1942362bc use direct jump only for jumps in the same page - stop translation after mtsr[in]
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1628 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-20 10:31:08 +00:00
bellard
0b7a4a9711 DOS 6.22 fix (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1627 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-19 18:17:16 +00:00
bellard
2df3b95dbb target independent memory access functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1626 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-19 17:47:39 +00:00
bellard
5e9ab4c493 USB reset typo (Lonnie Mendez)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1625 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-19 17:43:37 +00:00
bellard
7e89463d4a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1624 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-19 17:42:52 +00:00
bellard
41d03949e1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1623 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-15 23:02:53 +00:00
bellard
7c9d8e07e1 new network emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1622 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-15 22:16:05 +00:00
bellard
868bfe2b2b correct use of USBDEVFS_DISCONNECT
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1621 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-13 21:53:15 +00:00
bellard
9e61bde56a sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1620 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:24:58 +00:00
bellard
4787c71d17 debug fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1619 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:06:10 +00:00
bellard
541e084426 VM state change support (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1618 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:04:19 +00:00
bellard
e7cad33853 size_t fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1617 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:03:36 +00:00
bellard
575b5dc4dc compile fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1616 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:03:20 +00:00
bellard
b41cffbeb4 debug msg (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1615 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:02:25 +00:00
bellard
0bd4885002 API for changes in VM state (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1614 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:00:47 +00:00
bellard
946fc94733 ES1370 word sized read fix (aka Win9x bug) (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1613 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-11 00:00:09 +00:00
bellard
a0d01ed9ea spelling fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1612 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-10 23:59:38 +00:00
bellard
e57a8c0eef low level host parallel port access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1611 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-10 23:58:52 +00:00
bellard
2122c51a9c char dev ioctls
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1610 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-10 23:58:33 +00:00
bellard
f8d179e33d use host serial port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1609 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-08 22:30:36 +00:00
bellard
3f87bf6959 use softfloat types in softmmu_header.h (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1608 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 19:56:23 +00:00
bellard
2531fc7bc0 thumb BLX insn fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1607 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 19:36:29 +00:00
bellard
3dbbdc2555 suppressed unneeded options - added isapc machine
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1606 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 18:20:37 +00:00
bellard
48024e4a48 m68k disassembler (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1605 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 16:52:11 +00:00
bellard
b389dbfb58 USB help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1604 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 16:49:55 +00:00
bellard
a594cfbf3e USB user interface
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1603 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 16:13:29 +00:00
bellard
8738a8d079 serial load/save VM support (Vincent Pelletier)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1602 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-06 15:48:04 +00:00
bellard
c0fe3827ea audio merge (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1601 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-05 18:55:28 +00:00
bellard
f04308e452 same PCI parameters as PIIX3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1600 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-05 17:22:48 +00:00
bellard
59ae540c3d added virtual USB mouse support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1599 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-05 16:57:08 +00:00
bellard
92414fdca0 cosmetics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1598 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-05 16:55:48 +00:00
bellard
bb36d4708b initial USB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1597 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-05 14:22:28 +00:00
bellard
1aff381f59 gcc4 warning (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1596 c046a42c-6fe2-441c-8c8c-71466251a162
2005-11-02 22:30:45 +00:00
bellard
9903da21e3 SDL full screen patch for Windows (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1595 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 23:19:10 +00:00
bellard
c53be33474 suppressed JUMP_TB (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1594 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 21:39:19 +00:00
bellard
d5d11eac6c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1593 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 21:38:50 +00:00
bellard
24741ef3de avoid using physical accesses in user emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1592 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 21:23:39 +00:00
bellard
74c33bed31 User-mode gdbserver port number (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1591 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 21:01:05 +00:00
bellard
afce2927aa Arm AT_HWCAP AUXV entry (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1590 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 20:58:30 +00:00
bellard
bd6ea3c8f3 vmdk endianness fix (Benoit Poulot-Cazajous)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1589 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 20:53:51 +00:00
bellard
02aab46a36 endianness fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1588 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 20:49:44 +00:00
bellard
aab3309407 more physical memory access functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1587 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 20:48:42 +00:00
bellard
05f3fb8de3 endianness fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1586 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 19:34:15 +00:00
bellard
6f5f11a5bc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1585 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 19:12:29 +00:00
bellard
1d14ffa97e merged 15a_aqemu.patch audio patch (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1584 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 18:58:22 +00:00
bellard
3b0d4f61c9 OS X: support for the built in CD-ROM drive (Mike Kronenberg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1583 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 18:30:10 +00:00
bellard
87f48e6a1a fixed/full keyboard input - full mouse support - support for qemu console (Mike Kronenberg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1582 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 18:24:49 +00:00
bellard
b3ecf620de Thumb symbol lookup (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1581 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 18:21:23 +00:00
bellard
a9049a07bb moved common softmmu code to common header (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1580 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 18:16:26 +00:00
bellard
bb3911a609 Sparc64 add/sub flag bugs fixed (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1579 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:28:50 +00:00
bellard
4e3b1ea1b8 sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1578 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:24:19 +00:00
bellard
4f6200f03b ESP PIO mode, 2k CDROM sector size (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1577 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:24:05 +00:00
bellard
aea3ce4c8d restore regwptr (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1576 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:06:11 +00:00
bellard
f69a86955e slavio_serial fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1575 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:05:44 +00:00
bellard
7b936c0c42 sparc64 fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1574 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 17:05:13 +00:00
bellard
819385c58b suppressed m48t08 RTC - simplified m48t59 RTC api
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1573 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 16:58:32 +00:00
bellard
48b2c19353 sparc fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1572 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 16:08:23 +00:00
bellard
1983a3956c ASI printing (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1571 c046a42c-6fe2-441c-8c8c-71466251a162
2005-10-30 15:45:19 +00:00
bellard
c0b24a1dd6 div64 fix (aka ssh bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1570 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-08 19:26:14 +00:00
bellard
de75815006 disabled LDT test (kqemu 0.7.2 no longer needs it)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1569 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-04 16:54:47 +00:00
bellard
7fa98e2a7a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1568 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-04 16:35:31 +00:00
bellard
8289336c98 kqemu_enabled test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1567 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 21:33:43 +00:00
bellard
a332e112b7 kqemu_cpu_interrupt support for win32 (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1566 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 17:55:47 +00:00
bellard
ca0d1734b4 SYSENTER fix for x86_64 CPUs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1565 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 16:25:14 +00:00
bellard
aa0bc6b68c avoid losing chars in serial console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1564 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 15:28:58 +00:00
bellard
1c213d1976 comments
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1563 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 10:49:04 +00:00
bellard
a7c15abbb1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1562 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 10:45:39 +00:00
bellard
df5f895699 improved user net performances
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1561 c046a42c-6fe2-441c-8c8c-71466251a162
2005-09-03 10:45:09 +00:00
bellard
fc8dc06020 kqemu_set_notdirty() opt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1560 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 19:15:23 +00:00
bellard
f23db1692b dirty ram page handling fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1559 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 19:12:28 +00:00
bellard
3f20e1ddf2 TSS error code push fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1558 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 17:30:26 +00:00
bellard
75913b727e compilation fix for gcc3.4 on win32 (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1557 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 15:19:36 +00:00
bellard
ecada8a2dd CR4.TSD flag support (Matt Schulkind)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1556 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 10:28:44 +00:00
bellard
1e8a7cfd11 Show thumb state in cpu dump (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1555 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 10:14:28 +00:00
bellard
0bccf03d6f fix AUX vector entries (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1554 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 10:12:28 +00:00
bellard
89353a790b Byte swapping bug in arm semihosting (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1553 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:50:09 +00:00
bellard
7ebab69910 Fix interrupt masking (Ralf Baechle
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1552 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:43:38 +00:00
bellard
697584ab24 Add i8259 PIT to MIPS (Ralf Baechle
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1551 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:41:56 +00:00
bellard
c96a29cdef Fix MIPS counter / compare interrupt (Ralf Baechle
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1550 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:40:49 +00:00
bellard
4b7df22f91 added kqemu_set_notdirty()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1549 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:37:35 +00:00
bellard
2c8e030185 RSP update fix for x86_64 in iret
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1548 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:32:43 +00:00
bellard
81eea5ebb6 comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1547 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:30:54 +00:00
bellard
5e6ad6f90e kqemu profiling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1546 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:30:40 +00:00
bellard
aa06297340 kqemu fixes - new API support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1545 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:30:12 +00:00
bellard
3a7d929e62 merge self modifying code handling in dirty ram page mecanism
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1544 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:26:42 +00:00
bellard
04c504cc4f use ram_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1543 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:24:50 +00:00
bellard
ff7b8f5b0f ram_addr_t type for ram offsets
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1542 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:24:05 +00:00
bellard
6688bc6d04 cscope rule
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1541 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-21 09:23:39 +00:00
bellard
bc3fc8dac0 16/32 stack operations fix on x86_64 (aka win2000 startup bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1540 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-15 16:33:56 +00:00
bellard
1f3358c87d CLFLUSH cpuid fix (aka Linux 2.6 hang on x86_64)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1539 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-15 16:33:12 +00:00
bellard
92510b8cf5 ide PCI ident fix, aka FreeBSD/amd64 bug fix (Jung-uk Kim)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1538 c046a42c-6fe2-441c-8c8c-71466251a162
2005-08-06 09:14:32 +00:00
bellard
6cc721cf42 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1537 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-28 22:27:28 +00:00
bellard
e99f906055 FreeBSD fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1536 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-28 21:45:38 +00:00
bellard
f5a8510c7c copyright
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1534 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 18:44:56 +00:00
bellard
93856aac7b update tarbin target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1533 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 18:44:35 +00:00
bellard
5cedb46460 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1532 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 18:14:03 +00:00
bellard
0f4c64157f kqemu info
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1531 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 18:10:56 +00:00
bellard
90cb949352 s390 bits
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1530 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 15:11:38 +00:00
bellard
db6e6ed77e do not export fls_bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1529 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 14:56:40 +00:00
bellard
57e4c06ed7 fscale fix (bug noticed by Kuwanger, fix by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1528 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 14:33:17 +00:00
bellard
09d459a1db temporary work around for 16 bit code in kqemu
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1527 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 14:14:53 +00:00
bellard
108c49b8a2 allow more than 32 bit of physical memory
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1526 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 12:55:09 +00:00
bellard
90f18422d9 64 bit virtual addressing fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1525 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 10:17:31 +00:00
bellard
9529397248 open OSS audio device as write only (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1524 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-24 09:05:18 +00:00
bellard
a2458627f9 ppc64 target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1523 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 22:39:53 +00:00
bellard
b1fc0348b1 EXTINT delivery mode support for I/O APIC (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1522 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 21:43:15 +00:00
bellard
45bbbb466c added overflow exceptions in divisions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1521 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 20:21:38 +00:00
bellard
d592d3033d IOAPIC support (initial patch by Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1520 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 19:05:37 +00:00
bellard
1ff5c1a68e prevent window resizing
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1519 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 17:54:50 +00:00
bellard
e5d80f94c5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1518 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 17:43:14 +00:00
bellard
8f091a5960 x86_64 fixes (initial patch by Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1517 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 17:41:26 +00:00
bellard
2efbe911d3 more set/getsockopt values
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1516 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 15:10:20 +00:00
bellard
667f38b167 [f]truncate64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1515 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 14:46:27 +00:00
bellard
8346901560 sparc64 fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1514 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 14:27:54 +00:00
bellard
b7c7b18129 fixed VIA irq register access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1513 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-23 14:01:47 +00:00
bellard
9835236910 specific mac-io PCI device_id for paddington/heathrow - fixed atapi requests - reset IDE drives in quiesce - added heathrow nvram OF description
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1512 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 22:38:00 +00:00
bellard
e573335624 heathrow nvram support - use different device ids for different macios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1511 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 21:47:27 +00:00
bellard
4e588a4d0e negative decr fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1510 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 21:46:29 +00:00
bellard
a368741bf2 suppressed ppc ide hack - fixed read toc for Darwin/PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1509 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 21:46:09 +00:00
bellard
61271e5c2d more precise cuda timers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1508 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 21:45:18 +00:00
bellard
aefce9af41 compilation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1507 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-07 19:07:52 +00:00
bellard
ee5bbe38b1 correct split between helper.c and op_helper.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1506 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-04 22:18:23 +00:00
bellard
e37e863f5e correct split between helper.c and op_helper.c - cosmetics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1505 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-04 22:17:33 +00:00
bellard
fdabc366bd correct split between helper.c and op_helper.c - moved some uops to op_helper.c (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1504 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-04 22:17:05 +00:00
bellard
2157fa0682 better fpu state dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1503 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 21:29:17 +00:00
bellard
d24b15a8d8 no need to dump CCOP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1502 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 21:28:00 +00:00
bellard
9d0a8e6f8f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1501 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 17:34:05 +00:00
bellard
51a36cb2cb win32 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1500 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 17:08:43 +00:00
bellard
33d084399c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1499 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 16:45:42 +00:00
bellard
e0727e17f3 removed bogus include
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1498 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 16:44:10 +00:00
bellard
97067eb5bc temporary version with better Darwin/Mac OS X support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1497 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 16:25:26 +00:00
bellard
4157a66212 allow variable bios size
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1496 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 16:00:49 +00:00
bellard
0289b2c1df changed machine names
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1495 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 16:00:32 +00:00
bellard
d5295253b0 VGA bios support for PowerPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1494 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 14:00:51 +00:00
bellard
fb3444b86c endian register support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1493 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-03 13:57:11 +00:00
bellard
2be0071f22 simplified PowerPC exception handling (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1492 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 22:09:27 +00:00
bellard
f68c781c2d simplified
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1491 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 22:07:19 +00:00
bellard
fa296b0fb4 PIC fix - changed back TB frequency to 100 MHz
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1490 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 22:04:06 +00:00
bellard
3fc6c082e3 preliminary patch to support more PowerPC CPUs (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1489 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 20:59:34 +00:00
bellard
2f636b458f Cirrus fix (Magnus Damm)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1488 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 20:12:37 +00:00
bellard
3de388f676 more generic i8259 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1487 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 18:11:44 +00:00
bellard
73133662c6 i8259 PIC support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1486 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 18:11:03 +00:00
bellard
bf82d81801 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1485 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 18:07:26 +00:00
bellard
b195775fef update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1484 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:39:14 +00:00
bellard
1b351e5291 moved CALL_FROM_TBx definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1483 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:39:04 +00:00
bellard
d325856010 MIPS support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1482 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:37:12 +00:00
bellard
0d8aca8c67 TLB reload exception vector (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1481 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:35:03 +00:00
bellard
8549850891 fixed c0_context in tlb exception (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1480 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:34:05 +00:00
bellard
7a962d3087 use MIPS_TLB_NB constant (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1479 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:31:15 +00:00
bellard
e1d9a50836 use mask in C0_status (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1478 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:29:46 +00:00
bellard
568b600d85 report C0 status correctly (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1477 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:28:16 +00:00
bellard
bc2c390907 fixed priviledgees for CP0 use (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1476 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:27:11 +00:00
bellard
9827e95c78 added NE2000 (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1475 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:26:04 +00:00
bellard
51e11d9e6c fixed eret insn (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1474 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:23:21 +00:00
bellard
90b37806ba fixed C0 status codes (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1473 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:22:34 +00:00
bellard
0699b54839 init cleanup (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1472 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:20:29 +00:00
bellard
9d1d106a3d unaligned load fix (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1471 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:20:06 +00:00
bellard
ae022501f2 soft irq are just irqs (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1470 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:16:15 +00:00
bellard
899abcf513 fixed random register (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1469 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:13:42 +00:00
bellard
dfae6487c0 remove nonsense exception code (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1468 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:12:18 +00:00
bellard
de12d6369b kernel load fix (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1467 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:11:25 +00:00
bellard
bc9ed47b12 fixed jump mask (Ralf Baechle)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1466 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:10:44 +00:00
bellard
9fb63ac281 MIPS_USES_R4K_TLB typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1465 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 15:07:44 +00:00
bellard
6af0bf9c7c MIPS target (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1464 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 14:58:51 +00:00
bellard
6643d27ea0 MIPS disas support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1463 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 14:45:34 +00:00
bellard
3475187dd8 sparc64 marge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1462 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 14:31:34 +00:00
bellard
8979b2277d VMDK disk image creation (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1461 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 14:02:54 +00:00
bellard
97ccc689e6 Configure check for graphical output (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1460 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 13:32:17 +00:00
bellard
c98baaac2f correct __builtin_expect definition - increased code gen buffer size for x86
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1459 c046a42c-6fe2-441c-8c8c-71466251a162
2005-07-02 13:31:24 +00:00
bellard
101c593562 64 bit fixes (initial patch by Gwenole Beauchesne)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1458 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 17:11:42 +00:00
bellard
b685369795 added HOST_LONG_BITS in configure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1457 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 17:10:39 +00:00
bellard
3f1a88f450 added help on -nics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1456 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 16:48:41 +00:00
bellard
a84eaf0c9b add missing definitions in the ppc linker script (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1455 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:57:04 +00:00
bellard
6e20a45f53 comma separated list of targets in --target-list (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1454 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:56:02 +00:00
bellard
cadae95f33 IER behavior change - better IRQ handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1453 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:24:23 +00:00
bellard
e68b9b2b10 added Heathrow PIC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1452 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:21:57 +00:00
bellard
c0e564d53b use new machine API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1451 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:17:28 +00:00
bellard
384d887691 correct PCI ID for PREP PCI host bridge - added Grackle PCI host bridge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1450 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:16:50 +00:00
bellard
5457c8ceeb added CMD646 PCI IDE controller support - better IRQ handling - added IDE flush cache command - added work around for Darwin/PPC to select IDE drive
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1449 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:15:26 +00:00
bellard
0aa6a4a250 added Heathrow PowerMAC machine - added UniN memory fake controller for Mac99 - added temporary frame buffer OSI calls to keep Mac OS X happy
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1448 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 15:11:17 +00:00
bellard
938828a263 use new machine API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1447 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:54:40 +00:00
bellard
b5ff2d6e2d PC machine support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1446 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:51:11 +00:00
bellard
54fa5af546 more generic IRQ support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1445 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:50:39 +00:00
bellard
cc1daa40f1 added -M machine option - permit to put CDROM on hdb on PPC to handle the case where a single IDE controller is present
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1444 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:49:17 +00:00
bellard
2d61879305 simplified end of page handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1443 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:39:02 +00:00
bellard
7c48011b45 added back loglevel test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1442 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-05 14:38:00 +00:00
bellard
8dd4983c4e fixed lsw[ix] / stsw[ix] potential exception bug - mtcrf workaround for Mac OS X 10.4 - use direct jump at page boundary
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1441 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:22:27 +00:00
bellard
71be0fc3eb removed dynamic test of traces
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1440 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:19:46 +00:00
bellard
30aec8768f xec_bc mask fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1439 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:19:19 +00:00
bellard
8993433789 bctr and blr must ignore the two lsb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1438 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:19:02 +00:00
bellard
d094807b9b MMU fix - temporary osi_call support - xec_bc mask fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1437 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:17:59 +00:00
bellard
6d506e6dc2 added temporary osi_call callback
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1436 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 22:16:41 +00:00
bellard
43ef9eb267 use fprintf_func callback to print code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1435 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 20:34:16 +00:00
bellard
e4cf1adc80 added sum command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1434 c046a42c-6fe2-441c-8c8c-71466251a162
2005-06-04 20:15:57 +00:00
bellard
72cc6cfeef handle the case where several PCI irqs share the same PIC irq
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1433 c046a42c-6fe2-441c-8c8c-71466251a162
2005-05-13 23:08:13 +00:00
bellard
bc380d1719 ARM VFP dump fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1432 c046a42c-6fe2-441c-8c8c-71466251a162
2005-05-13 22:50:47 +00:00
bellard
ff8263a951 ARM saturating arithmetic fixes (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1431 c046a42c-6fe2-441c-8c8c-71466251a162
2005-05-13 22:45:23 +00:00
bellard
04d81be884 open fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1430 c046a42c-6fe2-441c-8c8c-71466251a162
2005-05-13 22:42:37 +00:00
bellard
2d5262f991 dcbz fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1429 c046a42c-6fe2-441c-8c8c-71466251a162
2005-05-12 18:46:11 +00:00
bellard
a09db21f71 Windows 2000 install disk full hack (original idea from Vladimir N. Oleynik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1428 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-30 16:10:35 +00:00
bellard
b671f9ed2d typos
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1427 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-30 15:08:33 +00:00
bellard
de167e416f Virtual VFAT support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1426 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 21:15:08 +00:00
bellard
712e78744e probing fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1425 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 21:09:32 +00:00
bellard
7c35359cbf raw dmg support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1424 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 20:49:23 +00:00
bellard
d37282add1 added --enable-adlib in help
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1423 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 20:41:53 +00:00
bellard
a343df1659 ne2000 reset fix - start/stop registers read access (aka OS/2 Warp V4 fix) (lukewarm)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1422 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 19:45:10 +00:00
bellard
98ff7d30f2 BMDMA interrupt fix (aka Solaris x86 IDE bug fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1421 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-28 19:26:35 +00:00
bellard
43095f3198 tarbin fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1419 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 20:49:23 +00:00
bellard
5899f386ba ARM thumb fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1418 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 20:25:20 +00:00
bellard
6a0f9e82c5 Virtual PC read-only disk image support (Alex Beregszaszi)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1417 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 20:17:58 +00:00
bellard
c2d551ff5a ARM thumb disassembly (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1416 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 20:15:00 +00:00
bellard
192c7bd927 ARM Thumb syscalls (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1415 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 20:11:21 +00:00
bellard
b48a8bb6b1 win32 fix (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1414 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 19:55:58 +00:00
bellard
e5484d3391 BSD fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1413 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-27 19:55:01 +00:00
bellard
7674e7bf08 BSD cdrom device access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1412 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:59:26 +00:00
bellard
c747cd1fa2 raw CDROM access for windows (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1411 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:47:02 +00:00
bellard
11650e3638 clean target update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1410 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:39:25 +00:00
bellard
a8753c3466 Bochs disk image support (Alex Beregszaszi)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1409 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:34:00 +00:00
bellard
c99280bc29 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1408 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:25:15 +00:00
bellard
905f20b151 fixed gdb error reporting (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1407 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:09:55 +00:00
bellard
ff1afc72f2 VMDK4 write support - fixed packing of VMDK4Header (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1406 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:08:00 +00:00
bellard
6d82d04a49 proll update: IDE HDD/CD support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1405 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 21:02:48 +00:00
bellard
ad81218e40 depth=24 write mask fix (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1404 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:49:17 +00:00
bellard
e4afee9716 cosmetics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1403 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:46:24 +00:00
bellard
d0b3e73525 SYS_SEEK fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1402 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:44:10 +00:00
bellard
e90096763d report user mode gdb exit codes (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1401 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:42:36 +00:00
bellard
43fb823b5f removed switches in op.c (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1400 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:38:17 +00:00
bellard
e50e6a2019 better arm conditionnal execution implementation (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1399 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:36:11 +00:00
bellard
430116a1d8 debug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1398 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:35:05 +00:00
bellard
1026f1336b win32 conf fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1397 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:34:45 +00:00
bellard
e362b55a32 fixed clean target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1396 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 20:34:26 +00:00
bellard
fc9f715de8 i386-user compile fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1395 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-26 19:33:35 +00:00
bellard
b359d4e7e4 fixed zero ss selector case in x86_64 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1394 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 18:04:33 +00:00
bellard
c45b3c0e1b efer is present even in legacy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1393 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 18:03:37 +00:00
bellard
e04f40b5aa compatibility fix with kqemu-x86_64
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1392 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 18:02:38 +00:00
bellard
dff293e751 qemu code is not ready to handle these registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1391 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 18:01:56 +00:00
bellard
b3180cdc01 MMU fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1390 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 10:08:19 +00:00
bellard
4162503368 removed RS_CONTINUE 'state'
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1389 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-24 10:07:11 +00:00
bellard
6bae7ed8b9 informative message about low memory on /dev/shm
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1388 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 20:44:25 +00:00
bellard
74c161bd17 Fix dumping of arm registers (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1387 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:46:03 +00:00
bellard
08e489025b removed obsolete S3 VGA code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1386 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:43:45 +00:00
bellard
c326e0afec cygwin host support (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1385 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:30:28 +00:00
bellard
8aaca4c0b4 ARM singlestep support (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1384 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:27:52 +00:00
bellard
a4f81979e8 ARM "Angel" semihosting syscalls (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1383 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:25:41 +00:00
bellard
89344d5ad7 arm vfp fcmp and fcmpe instructions fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1382 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:21:13 +00:00
bellard
da9b266bb8 PREP machines have two IO mappings.
This patch adds support for non-contiguous IO map, which is used by
OS/2.
It also adds the missing legacy IO ports for the PREP PCI bridge and
changes CPU PVR from 74x/75x to 604 to make OS/2 happy.
(Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1381 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:18:54 +00:00
bellard
dccfafc4e1 This patch fixes two bugs in cuda emulation:
- the CUDA timer is always triggered twice, with current code
- SET_TIME command is supposed to send back a 7 bytes packet
(Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1380 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:16:54 +00:00
bellard
111bfab3b5 This patch adds little-endian mode support to PPC emulation.
This is needed by OS/2 and Windows NT and some programs like VirtualPC.
This patch has been tested using OS/2 bootloader (thanks to Tero
Kaarlela).
(Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1379 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:16:07 +00:00
bellard
c7d344af8f - remove the ugly "stop" pseudo-opcode.
- fix fsqrt instruction (there's no fsqrt.).
- floating point load and store are not integer instructions.
- wrong opcode for dcba instructions.
(Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1378 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:05:46 +00:00
bellard
e1a2849c90 ARM syscall fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1377 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 18:01:57 +00:00
bellard
e06e5259c3 lretq, lcall and ljmp tests in 64 bit mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1376 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:54:59 +00:00
bellard
aba9d61e34 lcall and ljmp fixes in 64 bit mode - sysret fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1375 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:53:12 +00:00
bellard
a6f379881e return model id in cpuid for x86_64
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1374 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:50:32 +00:00
bellard
f419b32104 sysret fix - better cpuid support - lcall support for x86_64 - efer access in i386 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1373 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:48:47 +00:00
bellard
8d9bfc2b48 enable EFER usage in i386 emulation - more cpuid bits
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1372 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:46:55 +00:00
bellard
c28e951fc7 x86_64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1371 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:45:43 +00:00
bellard
07f4ddbf7e kqemu build fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1370 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-23 17:44:28 +00:00
bellard
5516d670f6 make lsl, lar verr and verw exception safe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1369 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 19:50:21 +00:00
bellard
cc6f538bf6 verr and verw eflags opt fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1368 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 19:49:02 +00:00
bellard
1fddef4b1b gdb support for user mode (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1367 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 19:16:13 +00:00
bellard
6e4255f6a6 windows support for kqemu (Filip Navara)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1366 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 18:33:47 +00:00
bellard
74ffc7729e removed unused stuff
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1365 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 18:32:14 +00:00
bellard
e3a4e4b643 destination write mask support, fixed banked memory access, read-only access for bus type in SR 0x17 (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1364 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-17 17:56:18 +00:00
bellard
40545f84cf packet fix for for netware 3.11 (initial patch by Mark Jonckheere) - security bug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1363 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-10 14:51:41 +00:00
bellard
d39c0b990a fixed MMU bug on code page boundary
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1362 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-10 14:40:58 +00:00
bellard
2b03a7a5bc renamed set_bit to cow_set_bit (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1361 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-10 14:39:05 +00:00
bellard
b8076a748d ia64 host support (David Mosberger)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1360 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 22:20:31 +00:00
bellard
7a674b1363 accept more disk image extensions (David Still)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1359 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 20:36:50 +00:00
bellard
5a246934eb open the dialog box if an image was not selected from command-line (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1358 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 20:35:06 +00:00
bellard
b7e2c11dbd helper_lret_protected fix for kqemu (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1357 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 20:33:08 +00:00
bellard
9d60cac01f ARM double ordering fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1356 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 19:55:52 +00:00
bellard
8e96005d86 VFP register ordering (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1355 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-07 19:42:46 +00:00
bellard
85d8be6bf2 Open Hack'Ware version 0.4.1
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1354 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 23:06:54 +00:00
bellard
c194feda5f IDE irq fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1353 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 23:03:38 +00:00
bellard
7e6c3f34bf new bochs BIOS - 16 bit APM support (initial patch by Struan Bartlett)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1352 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 23:01:24 +00:00
bellard
39d2243955 PCI irq in sync with new Bochs BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1351 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 23:00:25 +00:00
bellard
66321a11a4 sparc update (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1350 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:47:48 +00:00
bellard
c44644bb96 update (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1349 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:45:26 +00:00
bellard
ed91024191 defaut case (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1348 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:44:48 +00:00
bellard
b81b3b10aa swap serial ports (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1347 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:43:37 +00:00
bellard
8be1f5c889 keyboard support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1346 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:42:35 +00:00
bellard
d827220bbf use standard TCX display size for sparc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1345 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:32:23 +00:00
bellard
2f275b8f9f SCSI support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1344 c046a42c-6fe2-441c-8c8c-71466251a162
2005-04-06 20:31:50 +00:00
bellard
c3278b7bf0 sparc exception fix (we go up to the shell prompt)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1343 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-20 12:43:29 +00:00
bellard
86bd2ca58a NaN tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1342 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-20 10:40:15 +00:00
bellard
8422b11337 NaN support in FPU comparisons
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1341 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-20 10:39:24 +00:00
bellard
b7a100da9c removed extern inline (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1340 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-20 10:34:22 +00:00
bellard
b109f9f867 more native FPU comparison functions - native FPU remainder
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1339 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-20 10:33:58 +00:00
bellard
1d6bda3561 added abs, chs and compare functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1338 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 18:52:29 +00:00
bellard
53cd663792 soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1337 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 18:50:23 +00:00
bellard
7a0e1f41ce soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1336 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 17:01:47 +00:00
bellard
4ecc31906d fpu fixes (Jocelyn Mayer) - soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1335 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 17:01:22 +00:00
bellard
4c2e770f37 fpu init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1334 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 16:56:51 +00:00
bellard
2049521883 use the generic soft float code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1333 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 16:55:58 +00:00
bellard
158142c2c2 soft float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1332 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 16:54:06 +00:00
bellard
4f716dc681 avoid redefinition problems
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1331 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 16:53:06 +00:00
bellard
539827ecf5 fpu init fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1330 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 16:51:00 +00:00
bellard
6eea2b1b81 add missing FORCE_RET (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1329 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 09:55:49 +00:00
bellard
ae200d1062 GOTO_LABEL_PARAM for ARM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1328 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 09:53:38 +00:00
bellard
ba68055eab ARM host configure tweaks (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1327 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 09:49:52 +00:00
bellard
6f7e9aec5e sparc fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1326 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 09:43:36 +00:00
bellard
b756921ad1 sparc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1325 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-13 09:43:05 +00:00
bellard
313132138a x86_64 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1324 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-03 01:14:55 +00:00
bellard
d057099aa8 cmov fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1323 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-03 01:13:19 +00:00
bellard
da4dbf742d cocoa tiny fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1322 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-02 22:22:43 +00:00
bellard
776f2227f6 x86_64 test program
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1321 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-02 22:19:12 +00:00
bellard
d785e6be4d x86_64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1320 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 22:33:42 +00:00
bellard
5e83e8e3e7 SUSE fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1319 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 22:32:06 +00:00
bellard
24b55b9650 disabled obsolete static SDL warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1318 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 22:30:41 +00:00
bellard
232ba5ab2e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1317 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 22:30:05 +00:00
bellard
b6f479d355 -append support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1316 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:51:04 +00:00
bellard
1289f43ab1 Windows keys support with keymaps
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1315 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:43:42 +00:00
bellard
76472292e4 escape support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1314 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:40:00 +00:00
bellard
5b0753e0d8 initial Cocoa support (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1313 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:37:28 +00:00
bellard
157777ef3e Samba 3 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1312 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:28:45 +00:00
bellard
f94daedd27 more explicit message
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1311 c046a42c-6fe2-441c-8c8c-71466251a162
2005-03-01 21:28:22 +00:00
bellard
6df700c206 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1310 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-22 19:43:42 +00:00
bellard
b7bcbe9524 ARM VFP support (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1309 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-22 19:27:29 +00:00
bellard
55754d9ef2 MMU fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1308 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-22 19:14:33 +00:00
bellard
afc7df1148 PSR.PS fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1307 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-22 19:08:57 +00:00
bellard
713c45faf8 initrd support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1306 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-22 19:08:41 +00:00
bellard
0b9dc5e4c3 loop insn fix for non x86 hosts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1305 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-21 20:23:59 +00:00
bellard
194884dd6f win32 + Mac OS X compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1304 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-21 20:10:36 +00:00
bellard
91aa5d4975 Mac OS X fix (Jonas Maebe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1303 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-21 19:53:34 +00:00
bellard
6f2f2b2489 removed all references to KQEMU to comply with the Savannah rules
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1302 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-20 19:09:44 +00:00
bellard
1d6e34fd37 sparc Linux works better with NWINDOWS = 8
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1301 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-19 17:26:37 +00:00
bellard
2623cbaf1a fixed handling of sparc register window exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1300 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-19 17:25:31 +00:00
bellard
a20b552469 suppressed sparc64 targets as they are far from being usable
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1299 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-19 17:24:28 +00:00
bellard
f512c6fb6e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1298 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 23:06:39 +00:00
bellard
3cc6237083 ppc fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1297 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 23:06:19 +00:00
bellard
c4decf377c ppc fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1296 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 22:59:52 +00:00
bellard
3988e8977b ADB reset support (Joceylin Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1295 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 22:58:51 +00:00
bellard
7483750d7d sparc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1294 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 22:55:43 +00:00
bellard
61ff6f58e9 sparc sigsegv support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1293 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-15 22:54:53 +00:00
bellard
0bee699e1d fixed jmpl, rett and call
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1292 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-13 20:11:30 +00:00
bellard
878d3096d2 sparc fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1291 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-13 19:02:42 +00:00
bellard
1a0c3292b5 sparc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1290 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-13 19:02:07 +00:00
bellard
824d560f09 fixed kqemu config
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1289 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-12 18:58:00 +00:00
bellard
580a5e27c6 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1288 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-12 15:16:03 +00:00
bellard
0443eaf6ae update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1287 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-12 15:02:03 +00:00
bellard
9117a4ab91 disable USE_KQEMU if no source
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1286 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-12 14:50:42 +00:00
bellard
441c72ba15 kqemu is an external project
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1285 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-12 14:45:23 +00:00
bellard
bf079a1e70 enabled MMX, PAE and SEP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1284 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 22:06:29 +00:00
bellard
9df217a317 kqemu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1283 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 22:05:51 +00:00
bellard
92a31b1fff 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1282 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 22:00:52 +00:00
bellard
0a962c0276 dirty flag changes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1281 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 22:00:27 +00:00
bellard
d993e0260b -no-kqemu option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1280 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 22:00:06 +00:00
bellard
49b470eb96 shared pages memory allocation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1279 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 21:59:25 +00:00
bellard
c9ec1fe474 kqemu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1278 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 21:55:30 +00:00
bellard
e3086fbf8f kqemu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1277 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 21:48:51 +00:00
bellard
7c3fc84d86 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1276 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-10 21:46:47 +00:00
bellard
d7ce296f57 power down support + date fix (Thayne Harbaugh)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1275 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-09 00:07:08 +00:00
bellard
f8407028b4 spelling fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1274 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-09 00:01:34 +00:00
bellard
18fba28c95 ppc fixes - gcc 3.4 compile fix (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1273 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-08 21:24:36 +00:00
bellard
68016c627b SIGSEGV signals for ARM and SPARC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1272 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 23:12:27 +00:00
bellard
9d89330183 clean up - comments
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1271 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 23:10:53 +00:00
bellard
b8a9e8f133 initial user mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1270 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 23:10:07 +00:00
bellard
4955a2cd16 test and set fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1269 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 14:09:05 +00:00
bellard
a8d3431ae9 endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1268 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 12:43:57 +00:00
bellard
7ff4d2180b CF generator for constant operands
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1267 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 12:42:35 +00:00
bellard
e88de09993 ARM FPA get_user/put_user fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1266 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 12:35:39 +00:00
bellard
832ed0fa34 ARM FPU endianness fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1265 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-07 12:35:16 +00:00
bellard
78573df6b2 SBCS fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1264 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-02 20:43:01 +00:00
bellard
9f0777ed88 ARM SMC workaround
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1263 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-02 20:42:01 +00:00
bellard
6bae70713c sparc fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1262 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-02 20:40:17 +00:00
bellard
90f11f95fe pusha, popa and enter fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1261 c046a42c-6fe2-441c-8c8c-71466251a162
2005-02-01 20:25:03 +00:00
bellard
fa15e030bf 64 bit disas fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1260 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-31 23:32:31 +00:00
bellard
1ef3868708 x86_64 call Ev fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1259 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-31 23:31:02 +00:00
bellard
99c475abf1 armv5te support (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1258 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-31 20:45:13 +00:00
bellard
dfe86665b8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1257 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 23:04:39 +00:00
bellard
a315a14547 initial sparc64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1256 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:59:18 +00:00
bellard
4fa5d7722d fixed sparc cpu load/save
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1255 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:57:54 +00:00
bellard
64b3ab2439 sparc64 support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1254 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:43:42 +00:00
bellard
c1135f6152 removed debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1253 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:41:54 +00:00
bellard
3a5c313852 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1252 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:39:56 +00:00
bellard
af7bf89b1f initial sparc64 support - sparc fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1251 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-30 22:39:04 +00:00
bellard
49be803015 endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1250 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-28 22:40:22 +00:00
bellard
8df1cd076c physical memory access functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1249 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-28 22:37:22 +00:00
bellard
bb05683b12 flush TLBs at cpu reset
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1248 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-28 00:01:00 +00:00
bellard
662f3c86ec ram dirty flag handling fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1247 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-28 00:00:27 +00:00
bellard
5416376efe ram dirty flag update fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1246 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-27 23:58:13 +00:00
bellard
f34c9d6f10 mouse reset fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1245 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-27 22:32:51 +00:00
bellard
e3db7226b4 JIT statistics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1244 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-26 22:00:47 +00:00
bellard
d79284e07a i386 linux 2.6 timer fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1243 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-26 21:56:26 +00:00
bellard
9191d4d19f Mac OS X fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1242 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-26 21:30:57 +00:00
bellard
0b74ed78ef mode 4 and 5 write fix (Magnus Damn)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1241 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-26 19:50:16 +00:00
bellard
f51589dad5 Support resolving addresses in PAE mode in cpu_get_phys_page_debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1240 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-25 22:35:05 +00:00
bellard
82e41634cd avoid empty op
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1239 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:55:36 +00:00
bellard
bd3fae3df6 removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1238 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:48:05 +00:00
bellard
9230e66e5c CR8 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1237 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:46:56 +00:00
bellard
0523c6b7c5 FORCE_RET() fixes - fpu fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1236 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:46:31 +00:00
bellard
39c61f49f4 CR8 support - FORCE_RET() fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1235 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:46:09 +00:00
bellard
4d6b6c0aec more fpu functions - x86_64 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1234 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:45:23 +00:00
bellard
79f91c27ba more fpu functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1233 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:44:55 +00:00
bellard
dc9543dc22 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1232 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:42:59 +00:00
bellard
bef79c34a2 support for dyngen labels on more hosts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1231 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:42:06 +00:00
bellard
83b34f8b57 more consistent type for size (still a bug in wrapping)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1230 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-23 20:26:30 +00:00
bellard
18a6d284ad enabled wheel mouse support (initial patch by Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1229 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-17 22:32:23 +00:00
bellard
ada89ce61b enabled wheel mouse support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1228 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-17 22:31:41 +00:00
bellard
b328f873ab gdb M packet parsing fix (Thomas Petazzoni)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1227 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-17 22:03:16 +00:00
bellard
ca954f6d90 x86_64 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1226 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-16 23:35:43 +00:00
bellard
97ed14aead fix shufps/shufpd tests - added maskmov tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1225 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-16 01:09:01 +00:00
bellard
d52cf7a64a sse fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1224 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-16 01:07:28 +00:00
bellard
bb2d531499 -nographic fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1223 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-15 21:50:11 +00:00
bellard
c82913f742 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1222 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-15 12:03:28 +00:00
bellard
6508fe59e0 PC parallel port support (Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1221 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-15 12:02:56 +00:00
bellard
e5843bc816 enable MMX for x86_64 too
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1220 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-12 22:46:19 +00:00
bellard
d3c617219b fxsr fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1219 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-12 22:41:17 +00:00
bellard
735a8fd38e fixed performance regression
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1218 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-12 22:36:43 +00:00
bellard
1bde465e06 sse fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1217 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-12 22:34:47 +00:00
bellard
a4682cc20a fxsr test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1216 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-12 22:33:30 +00:00
bellard
839fa98885 moved ASM_NAME
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1215 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:23:48 +00:00
bellard
7c2e623559 removed debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1214 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:20:21 +00:00
bellard
977d5710e6 DATA_MASK fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1213 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:20:04 +00:00
bellard
34444131ad windows header fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1212 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:19:34 +00:00
bellard
8adbc566c9 typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1211 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:19:18 +00:00
bellard
5327cf489f better target_list logic
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1210 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-10 23:18:50 +00:00
bellard
e995898b06 removed trace
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1209 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-09 00:42:09 +00:00
bellard
9df8aa4abb win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1208 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-09 00:39:12 +00:00
bellard
ae063a68dc generalized use of GOTO_TB() macro
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1207 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-09 00:07:04 +00:00
bellard
8636b5d873 compilation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1206 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-09 00:03:14 +00:00
bellard
664e0f195a MMX/SSE support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1205 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-08 18:58:29 +00:00
bellard
085339a12b MMX/SSE test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1204 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-08 18:54:41 +00:00
bellard
abd2c7dc9c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1203 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-06 20:50:00 +00:00
bellard
a8ede8ba8b div64 fix - raise_interrupt() fix - SSE fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1202 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-06 20:46:58 +00:00
bellard
826461bb40 big endian SSE fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1201 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-06 20:44:11 +00:00
bellard
02536f8b1f x86_64 save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1200 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-06 20:43:38 +00:00
bellard
06c2f5066e syscall insn fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1199 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-04 01:06:58 +00:00
bellard
bdfaf503dc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1198 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:51:01 +00:00
bellard
14ce26e755 x86_64 target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1197 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:50:08 +00:00
bellard
c46878786a labels support in dyngen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1196 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:44:44 +00:00
bellard
0fa85d43d4 64 bit target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1195 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:43:32 +00:00
bellard
b4ff598727 removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1194 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:43:09 +00:00
bellard
526ff7de82 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1193 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:41:14 +00:00
bellard
995179f1cc gcc 2.x fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1192 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:39:08 +00:00
bellard
0b0babc623 x86_64 target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1191 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:38:40 +00:00
bellard
20f3228237 initial x86_64 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1190 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:36:21 +00:00
bellard
c27004ec78 64 bit target support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1189 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:35:10 +00:00
bellard
612458f544 removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1188 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:34:06 +00:00
bellard
80a9d03503 64 bit target fixes - removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1187 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:31:27 +00:00
bellard
75598f6131 APIC support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1186 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:30:09 +00:00
bellard
4f7631cfb5 initial APIC support (only for x86_64 target now)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1185 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:28:51 +00:00
bellard
62a46c6168 suppressed warnings in 64 bit case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1184 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:28:27 +00:00
bellard
574bbf7b0d initial APIC support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1183 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:27:31 +00:00
bellard
acae4681ae fixed imul im test - added TEST_VM86 define for x86_64 tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1182 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 23:25:56 +00:00
bellard
42ad6ae973 'syscall' syscall
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1181 c046a42c-6fe2-441c-8c8c-71466251a162
2005-01-03 22:48:11 +00:00
bellard
808c4954bf big endian ARM support (Lennert Buytenhek)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1180 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-19 23:33:47 +00:00
bellard
e80cfcfc88 SPARC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1179 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-19 23:18:01 +00:00
bellard
9772c73bbc fixed ins in case of page fault
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1178 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-19 23:03:29 +00:00
bellard
de06c511ff win32 qcow fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1177 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-19 20:57:26 +00:00
bellard
bc7712a4ac update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1176 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-13 19:38:08 +00:00
bellard
4ca0074c8c no need to use -k for Windows
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1175 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-12 22:20:04 +00:00
bellard
fed4a9adc0 keymap install fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1174 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-12 22:18:34 +00:00
bellard
3d11d0eb33 keymaps support (initial patch by Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1173 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-12 16:56:30 +00:00
bellard
7b91a17212 slirp fix for -smb command (Initial patch by Juergen Keil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1172 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-12 11:45:10 +00:00
bellard
585d0ed98b .dmg disk image format support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1171 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-12 11:24:44 +00:00
bellard
a483b654b5 updated guest kernel patch for qemu-fast (Martin Koniczek)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1170 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-08 23:48:11 +00:00
bellard
6a78ece5c5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1169 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-08 23:47:30 +00:00
bellard
1e8d4eec48 more complete ARM shift fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1168 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-08 23:40:14 +00:00
bellard
88920f344d ARM shift fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1167 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-08 22:28:39 +00:00
bellard
f7cce89882 -pidfile option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1166 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-08 22:21:25 +00:00
bellard
fe2cece60e audio fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1165 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-06 23:14:48 +00:00
bellard
978a66ff73 utimes() support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1164 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-06 22:58:05 +00:00
bellard
f7806f9467 uname() fix (James Pellow)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1163 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-06 22:40:57 +00:00
bellard
45aea85cef FRSP fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1162 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-02 23:33:11 +00:00
bellard
c451ee717a added WIN_IDLEIMMEDIATE and WIN_DIAGNOSE commands
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1161 c046a42c-6fe2-441c-8c8c-71466251a162
2004-12-02 20:20:21 +00:00
bellard
a07167d3d4 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1160 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-30 23:41:30 +00:00
bellard
02cfb0b4f3 update to current vga bios version - Cirrus VGA: support for 1280x1024x[8,15,16] modes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1159 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-30 23:41:04 +00:00
bellard
3bc2175dcc socket send fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1158 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-24 20:39:26 +00:00
bellard
bed5cd8048 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1157 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-24 19:31:52 +00:00
bellard
c169c906a3 added undocumented FPU ops support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1156 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-24 19:28:52 +00:00
bellard
17444c9c84 fixed invalid received length
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1155 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-21 20:02:08 +00:00
bellard
bf1b938fce disable automatic BIOS translation if the logical disk geometry implies it
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1154 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-17 22:35:32 +00:00
bellard
46d4767d93 better BIOS ATA translation support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1153 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-16 01:45:27 +00:00
bellard
e35c55fe38 windows install fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1152 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-16 01:44:03 +00:00
bellard
acd935ef62 doc update - added qemu-img manual page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1151 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-15 22:57:26 +00:00
bellard
c9c0eae84e bitblt fix (aka Solaris display fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1150 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-15 21:43:57 +00:00
bellard
c72a345f5b do not remove docs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1148 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 20:52:54 +00:00
bellard
102a52e471 FMOD configure options (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1147 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:57:29 +00:00
bellard
c76338c34f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1146 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:52:18 +00:00
bellard
bf2b84e4a7 better ctrl-alt handling, at least for SDL/X11
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1145 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 19:46:35 +00:00
bellard
9f059eca52 win32/SDL build fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1144 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:59:52 +00:00
bellard
53360e00e2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1143 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:58:40 +00:00
bellard
ef6ff6b71e removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1142 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 18:58:04 +00:00
bellard
546fa6abd1 vga font change detection
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1141 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 17:52:01 +00:00
bellard
e875c40a15 indent fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1140 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 17:30:35 +00:00
bellard
a98d49b136 Mac OS compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1139 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:22:05 +00:00
bellard
44a095a77c mmap audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1138 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:02:51 +00:00
bellard
15b6147000 audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1137 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 16:02:09 +00:00
bellard
9e89a4be8e boot device 'b' is not supported
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1136 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 15:42:27 +00:00
bellard
61a8c4ec3a enter insn fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1135 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-14 15:39:16 +00:00
bellard
9746b15b4e 'info mem' monitor command fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1134 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-11 18:30:24 +00:00
bellard
7372f88dc1 audio fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1133 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-11 16:55:09 +00:00
bellard
d7382233d8 audio clean up (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1132 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-10 00:16:34 +00:00
bellard
fb065187e4 audio clean up (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1131 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 23:09:44 +00:00
bellard
bf71c9d9b6 disabled again register usage for ppc because my previous patch seems still buggy
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1130 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:12:08 +00:00
bellard
7a987127f4 bit mask conversion fix (Harald Welte
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1129 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:08:48 +00:00
bellard
e0fe67aa72 enabled DMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1128 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-09 22:04:05 +00:00
bellard
f6c958c865 CRTC register write protection fix - line_compare, multi_scan and double_scan fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1127 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 22:57:20 +00:00
bellard
9bb34eac8b CRTC register write protection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1126 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 22:54:14 +00:00
bellard
85571bc741 audio merge (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1125 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 18:04:02 +00:00
bellard
8f46820d92 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1124 c046a42c-6fe2-441c-8c8c-71466251a162
2004-11-07 17:44:42 +00:00
bellard
dbb2c92142 SDL config fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1123 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-24 22:17:47 +00:00
bellard
0d1a29f9fc correct handling of saved host registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 22:01:28 +00:00
bellard
b8b5ac6376 do not assume signed char
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1121 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 21:52:40 +00:00
bellard
40b6ecc6bc no need to use LARGE translation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1120 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-12 21:50:05 +00:00
bellard
f3ff649d3b openpty fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1119 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 18:00:00 +00:00
bellard
953569d21b fdc fix (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1118 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 17:51:13 +00:00
bellard
a0c4cb4a70 sparc fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1117 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 17:46:24 +00:00
bellard
188d857911 limited 8 bit support - removed unaligned memory accesses in VGA (initial patch by Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1116 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:44:19 +00:00
bellard
9bc9d1c75a info version command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1115 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:15:51 +00:00
bellard
8926b517e9 faster Cirrus VGA VRAM access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1114 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-10 15:14:20 +00:00
bellard
6d46bf8ae3 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1113 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 22:57:43 +00:00
bellard
032a8c9e35 help fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1112 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 22:56:44 +00:00
bellard
a7dfe172fa IDE standby fix for Linux 2.6 guest - segfault fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1111 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 20:27:55 +00:00
bellard
7fe48483cd monitor fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1110 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 18:08:01 +00:00
bellard
8e3a9fd280 monitor fixes (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1109 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 17:32:58 +00:00
bellard
d75d9f6be9 SDL Audio support and SB16 fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1108 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 17:20:54 +00:00
bellard
769bec7271 IDE fix for NT4 (Ben Pfaf)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1107 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:48:57 +00:00
bellard
655aa52a90 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1106 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:48:17 +00:00
bellard
ba6c23778c cmos init for IDE (Ben Pfaf)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1105 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:47:59 +00:00
bellard
4b19ec0c2b spelling fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1104 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:44:33 +00:00
bellard
e388818682 BSD getopt fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1103 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-09 16:44:06 +00:00
bellard
02d2c54cd3 windows fixes (Gregory Alexander)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1102 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 23:27:35 +00:00
bellard
890fa6bebb floppy fixes (initial patch by Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1101 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 23:10:29 +00:00
bellard
a4c4785b93 floppy fix from Volker Ruppert
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1100 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-07 21:27:06 +00:00
bellard
7993f8bc51 sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1099 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-04 23:42:21 +00:00
bellard
8d5f07fa3b sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1098 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-04 21:23:09 +00:00
bellard
023fcb9507 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1097 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 21:48:00 +00:00
bellard
a5ba1ca608 BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1096 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 21:47:33 +00:00
bellard
b769d8fef6 removed access_type hack
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1095 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 15:07:13 +00:00
bellard
32ff25bf68 ctrl-alt is the default grab key - reset modifiers when toggling grab state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1094 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 14:33:54 +00:00
bellard
f98593103b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1093 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 14:33:10 +00:00
bellard
30ca2aab8e ne2000 savevm support (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1092 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:56:00 +00:00
bellard
8a8a608f6e use memset() (Daniel Egger)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1091 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:36:49 +00:00
bellard
d63d307f6e -loadvm and -full-screen options
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1090 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 13:29:03 +00:00
bellard
487be8a1a7 hack for bootp support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1089 c046a42c-6fe2-441c-8c8c-71466251a162
2004-10-03 11:44:41 +00:00
bellard
2518bd0dc2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1088 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:35:13 +00:00
bellard
e95c8d51c2 full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1087 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:22:08 +00:00
bellard
4971b827da pointer arith fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1086 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:19:55 +00:00
bellard
420557e898 full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1085 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:13:50 +00:00
bellard
6d5e216de9 SPARC fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1084 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 22:04:13 +00:00
bellard
e8af50a30e full system SPARC emulation (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1083 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 21:55:55 +00:00
bellard
525d67bcc8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1082 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 18:58:48 +00:00
bellard
d981b88344 give a new address at DHCPREQUEST too (useful if the OS remembers its IP address
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1081 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-30 18:57:28 +00:00
bellard
4a4883b84d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1080 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 22:47:43 +00:00
bellard
16c460b154 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1079 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:56:51 +00:00
bellard
0ecf89aae3 level triggered IRQ fix (Steve Wormley)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1078 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:55:52 +00:00
bellard
28d34b8246 zlib.h is an external header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1077 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:30:43 +00:00
bellard
3c56521b70 cloop driver (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1076 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:29:14 +00:00
bellard
096b7ea42b win32 load_kernel() fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1075 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:19:16 +00:00
bellard
d5a8f07c52 no data exec support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1074 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-29 21:15:28 +00:00
bellard
345fbaa3ca removed unused prototype
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1073 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:36:08 +00:00
bellard
1d96905d76 fixed stdio write
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1072 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:34:39 +00:00
bellard
99679ececc removed warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1071 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:33:56 +00:00
bellard
eb45f5fec4 prototype fixed
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1070 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:33:09 +00:00
bellard
b86bda5bb1 adde TLB dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1069 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:32:46 +00:00
bellard
e2731add29 fixed block close() method prototype
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1068 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-18 19:32:11 +00:00
bellard
c9a621176e memory leak fix (Juergen Keil)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1067 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:42:51 +00:00
bellard
cf720db33a uname fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1066 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:41:39 +00:00
bellard
29e619b1e8 uname + sysctl fix (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1065 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:41:04 +00:00
bellard
6f28fb86c9 zero file case (Paul Brook)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1064 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:39:32 +00:00
bellard
c94c8d6499 win32 + Mac OS X compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1063 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:37:34 +00:00
bellard
01038d2a76 monitor fix (Derek Fawcus)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1062 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-13 21:36:46 +00:00
bellard
03ffbb69a8 smb config fix for NT
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1061 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-06 00:14:04 +00:00
bellard
a3d4af03bb allow inetd like program exec
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1060 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 23:10:26 +00:00
bellard
9d728e8c4e smb support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1059 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 23:09:03 +00:00
bellard
36d54d15e1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1058 c046a42c-6fe2-441c-8c8c-71466251a162
2004-09-05 16:04:16 +00:00
bellard
c4dfa5b7be removed duplicated option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1057 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-29 13:10:18 +00:00
bellard
75c2380584 fixed image creation with base filename
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1056 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-27 21:28:58 +00:00
bellard
7c08dbf325 endianness fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1055 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 22:30:56 +00:00
bellard
9bf05444b2 port redirection support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1054 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 22:12:49 +00:00
bellard
a3504c87ca removed gettimeofday usage
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1053 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 20:55:44 +00:00
bellard
7143c62c95 vmdk 3 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1052 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-25 20:50:14 +00:00
bellard
4e8b5da233 MULSCC fix (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1051 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 22:06:03 +00:00
bellard
c7f746434f TFTP support (Magnus Damm)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1050 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:57:12 +00:00
bellard
60e336dbb8 serial interrupt fix (Hampa Hug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1049 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:55:28 +00:00
bellard
8d11df9e5a multiple serial port support - terminal init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1048 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:13:40 +00:00
bellard
05d5818c5c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1047 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-24 21:12:04 +00:00
bellard
cabf23c380 bound instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1046 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-15 14:51:07 +00:00
bellard
e82d8ade13 fixed bound memory reference
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1045 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-15 14:47:30 +00:00
bellard
d2bfb39ad2 use the kernel sigaction syscall to avoid relying on glibc one
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1044 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 22:09:30 +00:00
bellard
3611a29c09 -fno-gcse option for opcodes to use asm macros with gcc >= 3.3 on i386 (Piotr Krysik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1043 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:42:45 +00:00
bellard
0f6e3eb211 enabled asm memory helpers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1042 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:37:41 +00:00
bellard
57d1a2b62c win32 port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1041 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:15:11 +00:00
bellard
d5249393ef 64 bit file I/O by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1040 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-03 21:14:23 +00:00
bellard
11c0315f9b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1039 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 22:05:00 +00:00
bellard
a3fb0cf907 removed unneeded tools
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1038 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 22:00:34 +00:00
bellard
ea2384d36e new disk image layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1037 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:59:26 +00:00
bellard
e4d4fe3c34 AES crypto support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1036 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:54:53 +00:00
bellard
5905b2e5fd password input support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1035 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:53:26 +00:00
bellard
7e2515e87c separated readline from monitor code - added password input support - added output buffer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1034 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:52:19 +00:00
bellard
3d2cfdf169 output disassembled code to monitor console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1033 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:49:07 +00:00
bellard
6fcfafb742 console focus support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1032 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:48:30 +00:00
bellard
af8ffdfd2b byte swap functions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1031 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:48:12 +00:00
bellard
b932caba32 new disk image layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1030 c046a42c-6fe2-441c-8c8c-71466251a162
2004-08-01 21:46:49 +00:00
bellard
3eb2619fe5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1029 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 19:20:07 +00:00
bellard
3e11db9a0c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1028 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:47:14 +00:00
bellard
c6f37d0e4f virtual console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1027 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:39:50 +00:00
bellard
a0a821a4c0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1026 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:38:57 +00:00
bellard
49b3b9fb1a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1025 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:31:32 +00:00
bellard
e7f0ad58c1 virtual console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1024 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:28:59 +00:00
bellard
82c643ff50 char device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1023 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:28:13 +00:00
bellard
457831f4bc virtual console support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1022 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:22:33 +00:00
bellard
2571929a77 added qemu_strdup()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1021 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:21:57 +00:00
bellard
81d0912d2d completion support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1020 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:21:37 +00:00
bellard
d1d9f42119 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1019 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:20:55 +00:00
bellard
450e18b8b8 slirp for win32 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1018 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:20:11 +00:00
bellard
3db38e87a0 virtual console support - slirp for win32 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1017 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-14 17:19:55 +00:00
bellard
379ff53dc9 win32 compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1016 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 22:33:07 +00:00
bellard
ce93da6ffe win32 compile
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1015 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 21:21:31 +00:00
bellard
ee2654ac24 removed unused includes - BSD port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1014 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 21:11:45 +00:00
bellard
354ff22657 avoid warning
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1013 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:40:05 +00:00
bellard
6b65279459 comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1012 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:33:47 +00:00
bellard
12c28fed49 adb fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1011 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:26:20 +00:00
bellard
38f0b147a5 fixed ADB error reporting
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1010 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:16:00 +00:00
bellard
bec9d989db fixed register 0 usage - fixed mouse buttons
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1009 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 20:15:26 +00:00
bellard
cab84d9844 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1008 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 18:51:50 +00:00
bellard
1b039c09fe OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1007 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-12 18:39:45 +00:00
bellard
fbf59244b8 static build fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1005 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 18:18:19 +00:00
bellard
fa36761d7f ppc bios version 0.3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1004 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:57:29 +00:00
bellard
d08c49aae0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1003 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:40:19 +00:00
bellard
fcc941fe20 added .cvsignore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1002 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:28:35 +00:00
bellard
96bcd4f884 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1001 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:15 +00:00
bellard
e3371e62f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1000 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:02 +00:00
bellard
82eec0a174 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@999 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:22:18 +00:00
bellard
933dc6ebc4 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@998 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:33:29 +00:00
bellard
1e6cae953d comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@997 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:31:19 +00:00
bellard
6d463de2b3 removed stdout reference (not portable)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@996 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:28:48 +00:00
bellard
bbbc4663d1 removed unused definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@995 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:27:59 +00:00
bellard
02e1ec9bc4 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@994 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:15:39 +00:00
bellard
3df3f6fd7b odd memory access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@993 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 14:45:19 +00:00
bellard
2c6ab8329e load/save state support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@992 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:41:46 +00:00
bellard
675376f2b4 kbd save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@991 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:39:53 +00:00
bellard
15a34c6364 doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@990 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:26:26 +00:00
bellard
1bfe856eb2 Cirrus VGA is the default - 128 MB default memory - 800x600 default PPC resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@989 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:17:50 +00:00
bellard
7e71f16f9a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@988 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:16:21 +00:00
bellard
38a64f9dfe fixed b[l] decoding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@987 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:06:01 +00:00
bellard
e02aa6869e suppressed unused function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@986 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:04:21 +00:00
bellard
7db4eea691 removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@985 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 20:57:47 +00:00
bellard
b30d4608da 24 bpp fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@984 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:50:49 +00:00
bellard
81ca79911a 24 bpp mode fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@983 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:47:47 +00:00
bellard
e58d12ed5b Darwin patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@982 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 22:13:07 +00:00
bellard
d549f7d98f Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@981 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:47:44 +00:00
bellard
83fb7adf6c Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@980 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:25:26 +00:00
bellard
1d43a71773 forgot fclose()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@979 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:18:42 +00:00
bellard
ae184e4ab7 dac write index register is r/w - CR1D access fix (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@978 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:13:19 +00:00
bellard
e6eccb38eb dac write index register is r/w (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@977 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:12:26 +00:00
bellard
9da9886121 fixed case where ram < 16 MB
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@976 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 15:53:17 +00:00
bellard
a1968d7196 RT signal may not be a good idea
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@975 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 17:06:27 +00:00
bellard
7f5d44e0ff new Cirrus VGA BIOS from the LGPL'ed VGA BIOS project including VESA support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@974 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 15:02:13 +00:00
bellard
acf5feac80 hlt instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@973 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:58:58 +00:00
bellard
d187d4b218 configure BMDMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@972 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:55:10 +00:00
bellard
9808745072 BMDMA support - CDROM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@971 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:54:19 +00:00
bellard
02ba45c536 use RT signal for /dev/rtc - restore stdin flags (Bob Barry) - cpu save fix (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@970 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:46:23 +00:00
bellard
107db44327 consider that all archs have SMC (workaround)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@969 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:48:46 +00:00
bellard
dc5d0b3d1b disable buggy tb_invalidate_page_range()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@968 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:43:30 +00:00
bellard
7496f5266c cpu_single_env init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@967 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 10:56:50 +00:00
bellard
91d848ebf3 disable PCI device for PMAC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@966 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:48 +00:00
bellard
e2733d20b2 ADB fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@965 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:10 +00:00
bellard
637f6cd735 ppc bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@964 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:47 +00:00
bellard
638260eb8e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@963 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:19 +00:00
bellard
30468f786c added PCI bus - added IRQ support for PowerPC bridges - suppressed PREP PCI bios init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@962 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:45:35 +00:00
bellard
46e50e9d58 added PCI bus
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@961 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:43:00 +00:00
bellard
7c29d0c0cf dma init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@960 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:58:50 +00:00
bellard
514fb8c10e removed traces
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@959 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:57:45 +00:00
bellard
53c862a88e endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@958 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:56:45 +00:00
bellard
b6b8bd1819 ppc init fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@957 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:55:53 +00:00
bellard
fd0bbb12c3 cmdline init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@956 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:53:42 +00:00
bellard
f2aa58c6f4 UniNorth PCI bridge support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@955 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:52:24 +00:00
bellard
611493d966 openpic fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@954 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:50:43 +00:00
bellard
e1bb04f740 memory mapped NVRAM (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@953 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:49:53 +00:00
bellard
1ade1de223 pmac macio based ide support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@952 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:48:36 +00:00
bellard
b0bda528c3 high page register support for PPC PREP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@951 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:42 +00:00
bellard
819e712bfe cuda fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@950 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:13 +00:00
bellard
28b9b5af25 ppc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@949 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:35 +00:00
bellard
e9b137c2dd added -g option for OF initial resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@948 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:10 +00:00
bellard
95ea3fa19c added open pic for PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@947 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:44:21 +00:00
bellard
7587cf4401 accept bigger PC BIOSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@946 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:43:27 +00:00
bellard
7086749072 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@945 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:42:16 +00:00
bellard
63b7e03697 boot to top of 4GB space
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@944 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:38:54 +00:00
bellard
678f2df60f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@943 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:12:23 +00:00
bellard
9e57f14d60 added APM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@942 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:06:36 +00:00
bellard
987c1c6921 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@941 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:02:46 +00:00
bellard
ffddfee379 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@940 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:01:25 +00:00
bellard
a2f659ee48 new reset API - shutdown support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@939 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:00:26 +00:00
bellard
d7d02e3c3a new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@938 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:58:36 +00:00
bellard
bb0c6722b6 reset and shutdown support - PCI is now the default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@937 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:37:32 +00:00
bellard
979a54fb20 new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@936 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:36:04 +00:00
bellard
e4f9082b9a added system_reset command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@935 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:44 +00:00
bellard
d95dc32d13 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@934 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:26 +00:00
bellard
53ad66e8c3 print error messages if boot error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@933 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:35:07 +00:00
bellard
eba2af633f buffer overflow fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@932 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:23:39 +00:00
bellard
95ce326e5b buffer overflow fix - printf format fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@931 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:22:53 +00:00
bellard
a5448a7de5 sysinfo syscall (Francois Guimond)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@930 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:59:03 +00:00
bellard
9231944d96 sigset_t endianness fix in signal context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@929 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:58:13 +00:00
bellard
d69d1fa01a const fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@928 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:57:17 +00:00
bellard
05efe46eaa VMware 4 disk images support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@927 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-16 20:34:33 +00:00
bellard
dbda808a4a OpenPIC support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@926 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-15 21:38:40 +00:00
bellard
a049791855 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@925 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 19:33:16 +00:00
bellard
ea1c18022e fixed self modifying code in case of asynchronous interrupt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@924 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 18:56:36 +00:00
bellard
516633dc42 jump to gate fix (aka OS/2 Warp install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@923 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 15:20:01 +00:00
bellard
dc196a57e3 fixed 16 bit segment optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 13:26:14 +00:00
bellard
2a2820560d IDE ATA identify fix (aka FreeBSD 4.10 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@921 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 22:23:16 +00:00
bellard
665656a99b ffree test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@920 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:38:00 +00:00
bellard
658c8bdadc added ffree - added cpu log option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@919 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:35:12 +00:00
bellard
5fef40fb4d added ffree
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@918 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:34:10 +00:00
bellard
e69390cee7 pattern fill fixes and optimization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@917 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 23:12:09 +00:00
bellard
7f647cf68f IDE1 init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@916 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 21:28:36 +00:00
bellard
a130a41e69 interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@915 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:59:19 +00:00
bellard
78e127efdb set memory size to 4MB for 5446 - fixed memory size probe (aka Win2000 bug) - fixed interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@914 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:58:26 +00:00
bellard
ee38b4c813 fixed full screen refresh
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@913 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:56:42 +00:00
bellard
3440557b6d ioport read command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@912 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:55:58 +00:00
bellard
d329a6fb22 audip fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@911 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:58:31 +00:00
bellard
7ebb5e4139 debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@910 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:51:58 +00:00
bellard
57ccbabecb allow 32 but unaligned access (aka Win PCI network bug - initial patch by Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@909 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:45:42 +00:00
bellard
eb26db16d7 endianness functions for unaligned memory accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@908 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:43:57 +00:00
bellard
4c8732d71b cirrus blitter fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@907 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 19:46:45 +00:00
bellard
1cc98a5f04 hardware cursor depth = 15 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@906 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 16:06:33 +00:00
bellard
de9258a87f specific VGA BIOS for Cirrus VGA Card
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@905 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:50:03 +00:00
bellard
37f53b4c05 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@904 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:48:55 +00:00
bellard
a8aa669ba4 generic hardware cursor support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@903 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:17:19 +00:00
bellard
a5082316e9 hardware cursor support - fill with rop support - color expand and color expand with transparent support - various optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@902 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:16:19 +00:00
bellard
20ba3ae101 better to use different ID for ISA and PCI
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@901 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:50:58 +00:00
bellard
4c7634bcb3 init VGA with default config
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@900 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:49:26 +00:00
bellard
a21ae81d8a change ID to CLGD5446 - added solidfill support - fixed hidden dac access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@899 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 17:59:37 +00:00
bellard
aeb3c85f59 Cirrus fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@898 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 14:26:11 +00:00
bellard
1f04275ec1 -cirrusvga option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@897 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:46:47 +00:00
bellard
4e3e9d0b4d avoid using anonymous struct extension (not supported by all gcc 3.x)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@896 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:18:45 +00:00
bellard
358c640721 host bridge config fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@895 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:49:34 +00:00
bellard
e36f36e15f mmio support for vga registers - line offset fix - (aka XFree86 4.3.0 fixes)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@894 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:47:01 +00:00
bellard
7b17d41e96 Cirrus VGA display fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@893 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 11:06:28 +00:00
bellard
d6bfa22f72 Cirrus VGA emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@892 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:32:30 +00:00
bellard
e6e5ad80d8 Cirrus VGA emulation (initial patch by Suzu - heavily modified for easier merge)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@891 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:31:55 +00:00
bellard
798b0c25cc generic VGA API layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@890 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:30:49 +00:00
bellard
22a56b8a87 sdl keyboard fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@889 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 08:32:36 +00:00
bellard
44bbf73f92 dhcp packet size fix (aka pump fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@888 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 15:30:48 +00:00
bellard
00ffa62a91 added some keys
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@887 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:25:15 +00:00
bellard
de2200d36d fixed window switch - fixed caps lock and num lock - simplified keycodes (initial idea by Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@886 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:15:06 +00:00
bellard
710c15a2e9 lmsw fix (aka dos4gw bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@885 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:20:49 +00:00
bellard
443f1376bc slirp is enabled by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@884 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:13:20 +00:00
bellard
a3a91a355b sendkey command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@883 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:06:21 +00:00
bellard
ab2572d7ea added -fno-strict-aliasing
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@882 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 19:07:57 +00:00
bellard
267002cd28 CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@881 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:46:20 +00:00
bellard
63066f4f13 hid event handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@880 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:45:02 +00:00
bellard
caf9a12e9a CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@879 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:35:40 +00:00
bellard
1f62d9383f fixed PCI config default write permissions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@878 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 16:40:20 +00:00
bellard
7727994d21 support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@877 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:08:36 +00:00
bellard
8a8696a3c4 support for opaque data on memory I/Os - PCI ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@876 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:06:32 +00:00
bellard
8998028497 -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@875 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:04:03 +00:00
bellard
a4193c8a4b support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@874 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:01:43 +00:00
bellard
170c6f8705 header fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@873 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:53:17 +00:00
bellard
43f493afb4 more accurate emulation (do not depend on localtime() or gmtime()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@872 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:51:19 +00:00
bellard
ee22c2f7db -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@871 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:49:50 +00:00
bellard
be3edd9590 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@870 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:48:45 +00:00
bellard
023fe10d24 fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (untested, not enabled in cpuid)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:08:52 +00:00
bellard
f66723fab9 put ready it after write command (aka FreeBSD HD access fix) - access 16 mult sector count
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@868 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:04:25 +00:00
bellard
8cc43feffc compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@867 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 23:29:15 +00:00
bellard
09a79b4974 partial big endian fixes - change VESA VBE ports for non i386 targets to avoid unaligned accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@866 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:58:01 +00:00
bellard
642012017c PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@865 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:55:16 +00:00
bellard
2444ca413b trace fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@864 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:16:35 +00:00
bellard
77d4bc349a PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@863 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:13:53 +00:00
bellard
a2a444d6e0 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@862 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:34:16 +00:00
bellard
4b3686faee PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@861 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:18:12 +00:00
bellard
85c4adf65f PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@860 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:25:39 +00:00
bellard
b69fedff84 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@859 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:17:08 +00:00
bellard
5fd386f698 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@858 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:11:22 +00:00
bellard
0ced658970 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@857 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:06:12 +00:00
bellard
b415a4078d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@856 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:04:06 +00:00
bellard
f18ac341fe cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@855 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:00:55 +00:00
bellard
63ce9e0a42 pci empty device read fix - piix3 ide init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@854 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:12:03 +00:00
bellard
e1c485be84 use PIIX3 like IDE controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@853 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:46 +00:00
bellard
34e538ae5d added PIIX3 like IDE controller - PCI irq generation - SETFEATURES IDE command support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@852 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:26 +00:00
bellard
9995c51ffd pixx3 ide controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@851 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:09:22 +00:00
bellard
e58a7c24ac int13 cdrom 32 bit register update fix (aka FreeBSD CDROM boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@850 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:28:35 +00:00
bellard
777428f2d2 fixed 2.88 MB boot (aka FreeBSD 5.2.1 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@849 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:26:20 +00:00
bellard
5b60212f2a typos (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@848 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:41:05 +00:00
bellard
a00bad7ed4 default ram size define (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@847 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:39:06 +00:00
bellard
25b42e9d53 added missing copyright file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@846 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 18:30:22 +00:00
bellard
8d6c7eb896 receive status register support (aka GRUB netboot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@845 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:52:29 +00:00
bellard
7bf5be70f7 pci memory mapping fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@844 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:28:18 +00:00
bellard
fb9f944458 PCI BIOS fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@843 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:27:00 +00:00
bellard
92e873b996 support for non continuous RAM or ROM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@842 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 14:52:29 +00:00
bellard
9fddaa0c0c PowerPC merge: real time TB and decrementer - faster and simpler exception handling (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@841 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 12:59:32 +00:00
bellard
4a0fb71e67 irq statistics code (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@840 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 11:39:07 +00:00
bellard
274da6b24b 64 bit fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@839 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 21:56:27 +00:00
bellard
15aeac3805 PIC spurious irq support (aka Solaris install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@838 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 16:12:05 +00:00
bellard
28ab0e2edb added cpu_get_tsc()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@837 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 14:02:14 +00:00
bellard
b54ad0498e PIC reset fix (initial patch by Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@836 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:42:52 +00:00
bellard
4399059e4d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@835 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:24:37 +00:00
bellard
43003046cb BSD fix + ppc-softmmu support for win32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@834 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:23:39 +00:00
bellard
d157e205e9 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@833 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:22:36 +00:00
bellard
5f21aef2b0 suppressed unneeded header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@832 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:55 +00:00
bellard
829309c70c BSD fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@831 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:12 +00:00
bellard
c6a1c22ba6 fixed invalid includes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@830 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:10:49 +00:00
bellard
b71e95fc2c win32 patch (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@829 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:08:06 +00:00
bellard
04a3b84c83 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@828 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:51:57 +00:00
bellard
86e0c04896 info pci command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@827 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:49:21 +00:00
bellard
5ce276a11a VGA PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@826 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:48:53 +00:00
bellard
5768f5aca6 PCI interrupt support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@825 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:47:45 +00:00
bellard
1078f663ae dummy VGA PCI support - VGA font selection fix (Daniel Serpell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@824 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:46:38 +00:00
bellard
0ac32c8375 PCI interrupt support - PCI BIOS interrupt remapping - more accurate memory mapping - 'info pci' monitor command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@823 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:45:00 +00:00
bellard
4a9c9687c6 PCI irq support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@822 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:43:25 +00:00
bellard
73c11f630b cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@821 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:42:19 +00:00
bellard
660de33686 PIIX ELCR register support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@820 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:41:21 +00:00
bellard
69135b5c04 suppressed pci2isa.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@819 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:40:26 +00:00
bellard
69b910399a PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@818 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-18 23:05:28 +00:00
bellard
158156d13d -user-net is optional - EAGAIN fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@817 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:13:42 +00:00
bellard
e63c59cb34 ppc fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@816 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:05:06 +00:00
bellard
13ab5daa86 NVRAM fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@815 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:21:49 +00:00
bellard
ef792f9ddb added CPU_INTERRUPT_TIMER
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@814 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:19:32 +00:00
bellard
47cea614a1 vmdk2raw: convert VMware disk images to raw images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@813 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:06:42 +00:00
bellard
aedf53821f different serial number for each drive (initial patch by Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@812 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 19:56:47 +00:00
bellard
7f5e145212 BSR/BSF 'undefined behaviour' test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@811 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 16:02:40 +00:00
bellard
f528bfd45d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@810 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:57:26 +00:00
bellard
686f3f266b BSR/BSF undefined behaviour fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@809 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:56:04 +00:00
bellard
5b1214a48e int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@808 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:52:12 +00:00
bellard
3f433d2c87 int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@807 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 14:21:17 +00:00
bellard
1a084f3d51 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@806 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:34:49 +00:00
bellard
cd6f11693a custom option parsing to have same behavior on all OSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@805 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:02:20 +00:00
bellard
b939777cec floppy fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@804 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 22:07:40 +00:00
bellard
d6b86f4d85 -tun-fd option fix (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@803 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:59:20 +00:00
bellard
3a1bc175ea allow '-nics 0'
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@802 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:54:43 +00:00
bellard
db45c29a65 faster I/Os - default 16 bit I/O fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@801 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:50:26 +00:00
bellard
7d3505c55a bsd port (Markus Niemisto)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@800 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:32:15 +00:00
bellard
fd872598d8 primitive ioport debug - /dev/rtc fast timer support (needed for better simulation accuracy with Linux 2.4)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@799 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:11:15 +00:00
bellard
8cd0ac2fe1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@798 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:09:16 +00:00
bellard
7efa43875d better packaging support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@797 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 18:54:06 +00:00
bellard
44c513c4c9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@796 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:24:35 +00:00
bellard
2ee73ac3a8 division by zero FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@795 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:08:41 +00:00
bellard
28c3ee3fed cr0.ET fix (Win95 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@794 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:05:19 +00:00
bellard
f929aad6e3 MSDOS compatibility mode FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@793 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:03:41 +00:00
bellard
e309de25a6 SPECIFY command fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@792 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:01:23 +00:00
bellard
10d315a8f2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@791 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:00:00 +00:00
bellard
2b64948eb5 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@790 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 15:27:20 +00:00
bellard
1f50f8d1d4 better install
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@789 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 14:44:43 +00:00
bellard
a1b74fe8fe update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@788 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:26:35 +00:00
bellard
ed5fd2cce4 timer for READ_ID (win98 floppy fix) - simpler irq handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@787 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:14:18 +00:00
bellard
bee3290936 typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@786 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:50:02 +00:00
bellard
beddab753d arm load/store half word fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@785 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:36:10 +00:00
bellard
512176dbd8 fixed dhcp for windows client
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@784 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 03:14:47 +00:00
bellard
fb6cf1d09c fixed floppy reset (aka win98 floppy probe fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@783 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 02:04:17 +00:00
bellard
66201e2ddf ide slave fixes (aka Win98 CD-ROM detection fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@782 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 01:29:51 +00:00
bellard
ec844b96c0 pit fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@781 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 23:18:25 +00:00
bellard
f72e8ff4a6 utime fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@780 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 19:23:07 +00:00
bellard
b06eddd39d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@779 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:34:24 +00:00
bellard
6f51f6b593 keyboard irq generation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@778 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:23:55 +00:00
bellard
0294ffb9c8 disable grab if the window no longer has the focus (Windows case) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@777 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:15:15 +00:00
bellard
d8d8aa4e2c SDL static config fix (Roman Zippel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@776 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 20:14:07 +00:00
bellard
141253b254 Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@775 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 19:21:16 +00:00
bellard
646be93b4c Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@774 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:38:47 +00:00
bellard
26aa7d72cc isa memory remapping support (aka PPC PREP VGA support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@773 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:26:05 +00:00
bellard
8e9c4afe70 full screen support (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@772 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 19:33:40 +00:00
bellard
bbc9d34839 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@771 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 21:15:11 +00:00
bellard
a8c490cda5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@770 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:59:17 +00:00
bellard
4606bb3f06 copyright update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@769 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:58:11 +00:00
bellard
aaaa7df625 added temporary option -enable-audio
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@768 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:56:53 +00:00
bellard
9d4fb82e3c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@767 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:55:38 +00:00
bellard
9fafc9eaf0 avoid errno variable name
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@766 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:50:09 +00:00
bellard
1ef59d0acf ppc fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@765 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:48:05 +00:00
bellard
7fd7b91fac amd64 port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@764 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:46:45 +00:00
bellard
d927637dca init dummy net if tun/tap network error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@763 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:57 +00:00
bellard
4f2ac23784 amd64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@762 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:02 +00:00
bellard
f658b4db79 isa bridge endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@761 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:10:09 +00:00
bellard
0c4ad8dc2a ide endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@760 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:09:16 +00:00
bellard
165c6fc8ce more endianness macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@759 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:08:49 +00:00
bellard
2e12669a4c consistent use of target_ulong and target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@758 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:28:44 +00:00
bellard
52c00a5f15 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@757 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:27:03 +00:00
bellard
ab6d960ffa added target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@756 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:25:15 +00:00
bellard
fbf9eeb34d added cpu_resume_from_signal() - irq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@755 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:21:33 +00:00
bellard
046d6672e2 avoid unneeded casts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@754 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:15:35 +00:00
bellard
75dfaa1e64 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@753 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 19:04:19 +00:00
bellard
1115dde719 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@752 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:57:49 +00:00
bellard
57206fd42a more register values in monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@751 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:54:52 +00:00
bellard
4c27ba27c5 added 'info pic' - added 16/32 bit x86 instruction dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@750 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:05:08 +00:00
bellard
ba91cd80d5 fixed very unlikely irq bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@749 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:03:53 +00:00
bellard
6f1f31c069 ARM cache flush support (untested) - '-d' option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@748 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:00:45 +00:00
bellard
5467a72294 disabled S3 VGA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@747 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:59:00 +00:00
bellard
1b8eb456eb avoid error if too many sectors in non LBA mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@746 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:58:25 +00:00
bellard
d720b93d0b precise self modifying code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@745 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:57:43 +00:00
bellard
eeab3a558f dump A20 state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@744 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:46 +00:00
bellard
658138bcbc flush insn support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@743 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:08 +00:00
bellard
1190935d98 precise self modifying code test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@742 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:54:32 +00:00
bellard
bfbc9133eb 64 bit seek for win32 (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@741 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 14:43:10 +00:00
bellard
ad6a4837f8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@740 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:16:28 +00:00
bellard
039d3da365 added user mode libqemu usage example
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@739 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:11:51 +00:00
bellard
a7e61ed446 create slirp directory
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@738 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:46:47 +00:00
bellard
b5075d29a8 more imul tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@737 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:37:55 +00:00
bellard
91caaa612a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@736 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:36:13 +00:00
bellard
d64477afa1 imul imm8 fix - 0x82 opcode support (Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@735 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:34:25 +00:00
bellard
f6bac3809f fixed options definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@734 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:35:09 +00:00
bellard
f0cbd3ec9f initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:10:48 +00:00
bellard
7c1f25b46a probe static SDL link
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@732 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:02:08 +00:00
bellard
ee9dbb297d NE2000 fixes for windows (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@731 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:29:33 +00:00
bellard
c20709aa32 initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@730 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:27:19 +00:00
bellard
92cb7d5423 NT mouse fix (Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@729 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:17:49 +00:00
bellard
202a456a2b safer sb16 code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@728 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:09:02 +00:00
bellard
3294b949eb avoid segfault if transient invalid text resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@727 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:35:16 +00:00
bellard
2aebb3eb2b blanking support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@726 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:28:04 +00:00
bellard
95917e3f57 suppressed no longer needed vm86 segment hack (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@725 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:13:27 +00:00
bellard
f186904281 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@724 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:58:23 +00:00
bellard
c5df018e56 ppc: suppressed unneeded globals and headers - added explicit type for ppc nvram
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@723 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:54:52 +00:00
bellard
a541f297a3 PowerPC system emulation fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@722 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:39:29 +00:00
bellard
df475d18d8 fixed invalid command test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@721 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 19:07:27 +00:00
bellard
2f0c934ef9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@720 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:55:01 +00:00
bellard
fd836909df VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@719 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:54:42 +00:00
bellard
289e09e77b fixed keyboard random bug (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@718 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-10 19:04:48 +00:00
bellard
7ae9862745 ide select logic fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@717 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 22:13:51 +00:00
bellard
41b9be476c preserve partition table when using -linux option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@716 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:30:08 +00:00
bellard
52302d7274 fix the no device case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@715 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:01:17 +00:00
bellard
333190eb97 base memory size in cmos
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@714 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:51:30 +00:00
bellard
eccabc6ee0 vga 9 pixel wide text char fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@713 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:31:38 +00:00
bellard
bb058620c3 refuse write accesses in BIOS area (aka EMM386.EXE fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@712 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:21:16 +00:00
bellard
9eb153f18f dma clean up - added missing read accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@711 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 22:43:01 +00:00
bellard
aaba6c1516 win32: correct keycode remapping
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@710 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:30:16 +00:00
bellard
38e205a25b win32: do not use all cpu time
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@709 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:29:17 +00:00
bellard
e1a237441d port 92 access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@708 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-05 20:26:03 +00:00
bellard
57c3072482 fixing free
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@707 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:36:29 +00:00
bellard
73332e5ccd qemu fast fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@706 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:22:28 +00:00
bellard
1f673135ac doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@705 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 15:21:17 +00:00
bellard
aa455485c9 history support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@704 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 13:07:25 +00:00
bellard
9307c4c1d9 improved monitor: type check, expression evaluator, memory dump, disassembly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@703 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:57:25 +00:00
bellard
40c3bac35a win32 port (Kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@702 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:56:28 +00:00
bellard
6eaee46144 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@701 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:55:00 +00:00
bellard
0f2f112156 tun-fd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@700 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 09:37:47 +00:00
bellard
4721c45750 UIP update fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@699 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-03 12:27:31 +00:00
bellard
a6e022ad13 fixed SDL probing for cross compilation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@698 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:55:47 +00:00
bellard
702c651c4a added -macaddr option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@697 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:21:32 +00:00
bellard
1154e441aa avoid rounding problems
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@696 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:58:56 +00:00
bellard
e463b581ea rdtsc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@695 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:57:58 +00:00
bellard
11d9f695e7 win32 cross compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@694 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:55:59 +00:00
bellard
0c607d5728 win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@693 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:54:52 +00:00
bellard
67b915a5dd win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@692 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:37:16 +00:00
bellard
bb27c19087 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@691 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:05:07 +00:00
bellard
8a7ddc38a6 new timer API - new API to save/restore the virtual machine state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@690 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:00:16 +00:00
bellard
b0a21b5334 use new timer API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@689 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:58:38 +00:00
bellard
dff38e7b40 more precise RTC emulation (periodic timers + time updates)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@688 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:57:29 +00:00
bellard
1f1af9fd7f added cpu_get_fp80() and cpu_set_fp80()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@687 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:56:43 +00:00
bellard
858693c638 moved gdbstub to qemu - new asynchronous gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@686 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:52:07 +00:00
bellard
9b14bb04ca install fix (Rusty Russel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@685 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:43:34 +00:00
bellard
c101c49c54 added qemu-mkcow man page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@684 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:42:54 +00:00
bellard
4bb2fcc7c9 gcc 2.95.4 compile fix (Petter Reinholdtsen)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@683 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:38:57 +00:00
bellard
08cea4eef8 fixed ljmp and iret to TSS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@682 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:26:53 +00:00
bellard
883da8e219 task switch fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@681 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-24 00:50:26 +00:00
bellard
78ebca6e13 fixed IDE probe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@680 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:43 +00:00
bellard
5e2a644399 removed most of global context uses - removed unneeded abort() which cause problems during win95 hardware scan
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@679 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:11 +00:00
bellard
11774f549e protected lret x86 'bug' emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@678 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 18:28:57 +00:00
bellard
d9d849fc5d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@677 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:12:48 +00:00
bellard
e19e89a5d4 more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@676 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:08:23 +00:00
bellard
f193c7979c do not depend on thunk.h - more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@675 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:06:25 +00:00
bellard
3035f7ff83 use new directory layout
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@674 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:02:00 +00:00
bellard
4afa64828b fixed protected lret imm insn (one more OS/2 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@673 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:04:16 +00:00
bellard
c45c3d0059 write to both IDE drives - return 0 for not present drives
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@672 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:01:15 +00:00
bellard
baca51faff updated floppy driver: formatting code, disk geometry auto detect (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@671 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-19 23:05:34 +00:00
bellard
bc51c5c989 initial x86-64 host support (Gwenole Beauchesne)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@670 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:46:04 +00:00
bellard
5069146392 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@669 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:44:10 +00:00
bellard
59a983b921 device independent VGA screen dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@668 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:17:16 +00:00
bellard
4e463d8d50 tun-fd option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@667 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-16 00:02:58 +00:00
bellard
94fe4f9fa3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@666 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:49:05 +00:00
bellard
0fb48229a7 added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@665 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:48:47 +00:00
bellard
b41a2cd1e4 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@664 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:46:48 +00:00
bellard
c4b1fcc0f9 added I/O API - io port API change - added multiple network interface support - redirect serial port to a pseudo terminal if using graphical mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@663 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:44:30 +00:00
bellard
0f35920cd8 io port API change - removed dumb console redraw (not useful)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@662 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:42:10 +00:00
bellard
7d977de7e1 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@661 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:34 +00:00
bellard
07d898662d added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@660 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:12 +00:00
bellard
caed880216 removable device support - io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@659 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:40:43 +00:00
bellard
b338082b3f remoable device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@658 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:54 +00:00
bellard
9dc39cbae3 added a command line monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@657 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:27 +00:00
bellard
80cabfad16 separated more devices from emulator
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@656 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 12:20:30 +00:00
bellard
38ca2abc2e m68k compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@655 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-13 18:32:13 +00:00
bellard
73bdea1951 2.6 kernel compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@654 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-04 22:50:52 +00:00
bellard
00af2b2680 added cow.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@653 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-26 00:20:56 +00:00
bellard
a735aa3139 added precompiled linux boot sector
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@652 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:54:25 +00:00
bellard
6b2b6112f8 more FPU context save tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@651 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:34:07 +00:00
bellard
bf08806145 native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@650 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:33:36 +00:00
bellard
f9e92e973f use physical memory access functions for DMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@649 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:32:01 +00:00
bellard
8dc75d7535 moved DMA and SB16 outside timer (may break SB16)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@648 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:30:56 +00:00
bellard
03857e318e native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@647 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:26:33 +00:00
bellard
16f62432c4 DMA API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@646 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:25:55 +00:00
bellard
8b1f24b090 new physical memory access API (used by DMA accesses)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@645 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:38 +00:00
bellard
b448f2f36c new physical memory access API (used by DMA accesses) - code copy FP fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@644 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:04 +00:00
bellard
97eb5b14dc native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@643 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:19:55 +00:00
bellard
7eee2a509a CR0.MP/EM/TS support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@642 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:58 +00:00
bellard
42c3c0cced native FPU support (disabled)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@641 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:25 +00:00
bellard
9588b95a08 CR0.MP/EM/TS support - native fpu support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@640 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:55 +00:00
bellard
2edcdce334 fpu fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@639 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:06 +00:00
bellard
8853f86e1d shm support, more setsockopt and getsockopt calls, fds fix (initial patch by Paul McKerras)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@638 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:57:26 +00:00
bellard
e374bfa35b shm tests - disabled clone test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@637 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:54:18 +00:00
bellard
b88e4a9a3b small test optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@636 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:41:47 +00:00
bellard
537730b956 zero offset optimisation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@635 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:57 +00:00
bellard
edf779ffcc use kernel like macros for user access (will be useful someday to have a better error checking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@634 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:13 +00:00
bellard
121061dcdf O_DIRECT compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@633 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:56:01 +00:00
bellard
83d7396850 faster big endian accesses on i386 - big endian ldsw_raw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@632 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:53:50 +00:00
bellard
6b2d3e3c96 fixed blr/bctr cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@631 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:41:09 +00:00
bellard
e98a6e40a9 adding direct block chaining support - simplified branch code gen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@630 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:35:00 +00:00
bellard
28fbe299c3 lwarx fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@629 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:13:13 +00:00
bellard
297d8e6227 Fix check for lswi (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@628 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:11:27 +00:00
bellard
004bc62c28 update nip when processing exceptions (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@627 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:10:04 +00:00
bellard
ed1c0bcb0c use osdep.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@626 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:17:43 +00:00
bellard
22a46c55e4 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@625 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:13:24 +00:00
bellard
ea88812f4f added OS dependent functions (temporary as most functions are generic in fact)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@624 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:12:40 +00:00
bellard
58fe2f10f0 experimental code copy support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@623 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:11:32 +00:00
bellard
3a1d9b8bbb fixed lea exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@622 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:10:33 +00:00
bellard
0e4b179d33 experimental code copy support - fixed A20 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@621 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:08:32 +00:00
bellard
77fef8c148 experimental code copy support - added new Linux kernel loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@620 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:05:46 +00:00
bellard
59817ccb2c use qemu memory allocation - added dirty bit support when using host MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@619 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:01:13 +00:00
bellard
bf3e8bf11e experimental code copy support - CPU_INTERRUPT_EXITTB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@618 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:58:54 +00:00
bellard
9acbed0605 added CPU_INTERRUPT_EXITTB and code_copy_enabled
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@617 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:57:02 +00:00
bellard
cf98951b82 force boot sector feature
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@616 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:56:36 +00:00
bellard
f72b519c86 added osdep.o and nwfpe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@615 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:35 +00:00
bellard
07ce05eaa9 fast Linux boot support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@614 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:09 +00:00
bellard
b324e814a9 suppressed unused variables
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@613 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:54:14 +00:00
bellard
c69810559b arm nwfpe support - added code no-code-copy option - __preinit_array_start bug fix (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@612 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:49:03 +00:00
bellard
28c4f361ac arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@611 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:43 +00:00
bellard
3d57da2a70 suppressed dummy FPU ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@610 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:14 +00:00
bellard
00406dff19 added arm nwfpe support (initial patch by Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@609 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:43:58 +00:00
bellard
69de927c6c arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@608 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:40:43 +00:00
bellard
72cbca10e1 direct chaining support for SPARC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@607 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 20:30:05 +00:00
bellard
34f715e754 fixed WP semantics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@606 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-07 20:42:14 +00:00
bellard
cae61cef89 bochs vbe: virtual screen support and bank switch (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@605 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 23:58:08 +00:00
bellard
6411cfb6f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@604 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:57:09 +00:00
bellard
898712a85c sdl_cleanup fix (Martin Garton)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@603 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:56:42 +00:00
bellard
4fa0f5d292 added bochs VBE support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@602 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:47:52 +00:00
bellard
1ccde1cb94 added generic physical memory dirty bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@601 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:46:14 +00:00
bellard
ad08132319 added tlb_flush() flags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@600 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:39:42 +00:00
bellard
415e561f1d cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@599 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:37:12 +00:00
bellard
ee8b7021da temporary interrupt locking fix (need rework)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@598 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:35:10 +00:00
bellard
625976dac8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@597 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:30:47 +00:00
bellard
1ac157da77 more precise TLB invalidation - init cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@596 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:28:30 +00:00
bellard
64a595f26a cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@595 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:27:13 +00:00
bellard
3ad9a57e4f ide identify fix (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@594 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:55:47 +00:00
bellard
7f777bf385 fixed atapi error codes (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@593 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:37:48 +00:00
bellard
56bf1d37a0 SEEK_STAT bit ata reset fix (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@592 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:24:11 +00:00
bellard
c92b2e845f vga memory address fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@591 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-27 00:14:11 +00:00
bellard
68e73e391f clean tests dir
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@590 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:47:27 +00:00
bellard
c0637b3794 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@589 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:38:01 +00:00
bellard
e98c87213e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@588 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:26:12 +00:00
bellard
3d4b4c0f4b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@587 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:22:15 +00:00
bellard
8145122b08 correct NT flag behavior - zero ldt task switch bug fix - task switch thru call insn bug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@586 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:27:56 +00:00
bellard
7399c5a9be fixed eflags optimisations with string operation (aka linux 2.6.2rc1 fix) - removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@585 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:24:06 +00:00
bellard
10f0e412f8 combine PDE and PTE protections as in intel specs - added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@584 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:29:03 +00:00
bellard
4b7aba5173 correct NT flag behavior
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@583 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:27:58 +00:00
bellard
35b66fc4f9 correct target_ulong definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@582 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:26:06 +00:00
bellard
13eb76e091 virtual memory access for gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:23:36 +00:00
bellard
3cf1e035ba added TARGET_LONG_BITS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@580 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:19:09 +00:00
bellard
a6b025d37d added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@579 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:18:16 +00:00
bellard
edfcbd9937 added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@578 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:11:05 +00:00
bellard
612b477d48 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@577 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:10:18 +00:00
bellard
6c9bf8936a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@576 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:46:56 +00:00
bellard
bb551faa4a increased physical RAM limit to 2047 MB in soft MMU mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@575 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:42:26 +00:00
bellard
a136e5a8b1 ATAPI transfer size fix (NetBSD CDROM access fix) - added WIN_CHECKPOWERMODE1 - set error to zero in some cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@574 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-22 23:52:27 +00:00
bellard
4796f5e9bc interrupt to conforming segment fix (QNX boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@573 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 23:46:39 +00:00
bellard
3504fe171b 16 bit DMA fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@572 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 21:11:02 +00:00
bellard
ab1f142ba0 L4 fix for rep nop (should handle all cases)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@571 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:31:37 +00:00
bellard
4120b61d00 test at least one invalid lock op code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@570 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:29:34 +00:00
bellard
7f957d280b PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@569 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:19:48 +00:00
bellard
2be3bc02dd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@568 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:14:25 +00:00
bellard
c27357906a avoid exiting directly if file not found
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@567 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:55:23 +00:00
bellard
985a19d6d1 PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@566 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:49:57 +00:00
bellard
3f5dcc340c PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@565 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:44:01 +00:00
bellard
f09936ac82 ARM fcntl flag fixes (Lennert Buytenhek)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@564 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:39:25 +00:00
bellard
d030931173 automatic floppy boot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@563 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:35:25 +00:00
bellard
825bd5f8e5 temporary gcc 3.3 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@562 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:25:49 +00:00
bellard
bc0b1dc1eb sb16 patch (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@561 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:19:31 +00:00
bellard
630be16f6c alpha fix (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@560 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:06:47 +00:00
bellard
44a91cae10 suppressed cast to lvalue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@559 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:05:44 +00:00
bellard
d575b78aab more xadd tests - cmpxchg8b test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@558 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:57:29 +00:00
bellard
6e44ba7fa2 cmos return current date - current irq priority in PIC (L4 Pistachio support) - help fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@557 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:56:49 +00:00
bellard
6986f88c3f cast to return type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@556 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:53:18 +00:00
bellard
988578886e fixed tlb invalidation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@555 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:52:14 +00:00
bellard
c4c7e3e610 ppc code gen size fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@554 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:28 +00:00
bellard
b516f85ca8 simpler second page physical address test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@553 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:04 +00:00
bellard
1e4fe7cee2 fixed potential exception pb on cmpxchg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@552 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:44:40 +00:00
bellard
debf7a7c7e comments fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@551 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:43:36 +00:00
bellard
5a1388b6df xadd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@550 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:41:29 +00:00
bellard
777aca2fd3 fixed dirty bit support for 4M pages (L4 Pistachio fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@549 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:39:51 +00:00
bellard
69e5bc9068 generate read error if no image (win XP install boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@548 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:37:47 +00:00
bellard
c8135d9af6 fixed subtle bug: in some cases PG_DIRTY was not set correctly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@547 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-13 00:00:25 +00:00
bellard
9e62fd7f26 ppc support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@546 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 22:49:06 +00:00
bellard
8977f3c107 Floppy disk emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@545 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:09:06 +00:00
bellard
728c9fd5a9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@544 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:08:14 +00:00
bellard
bd49793889 use generic GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@543 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:06:41 +00:00
bellard
16d17fdb8e debug fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@542 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:50 +00:00
bellard
4487d0ac49 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@541 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:04 +00:00
bellard
7138fcfbf7 use CPUState
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@540 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:28 +00:00
bellard
c45886db19 PowerPC system emulation (Jocelyn Mayer) - PIC poll mode (Jocelyn Mayer) - use CPUState - Floppy support (Jocelyn Mayer) - command line debug (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@539 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:06 +00:00
bellard
ffa65c3b70 fcntl flags convertion (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@538 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:57:22 +00:00
bellard
2d603d2216 PowerPC support - float macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@537 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:56:24 +00:00
bellard
61190b14fc PowerPC update (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@536 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:54:31 +00:00
bellard
9886cc165a factorized GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@535 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:54 +00:00
bellard
ce09776be2 PowerPC System emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@534 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:18 +00:00
bellard
5be1a8e065 ppc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@533 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:51:58 +00:00
bellard
09683d3597 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@532 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:41 +00:00
bellard
590b7eed18 aalib support with SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@531 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:02 +00:00
bellard
af5ad10728 infer access type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@530 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:28:12 +00:00
bellard
ac9eb0731a suppressed explicit access type and use the exception routine to infer it from the micro operation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@529 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:26:24 +00:00
bellard
9a64fbe4d8 PowerPC system emulation (Jocelyn Mayer) - modified patch to use new TLB api
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@528 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 22:58:38 +00:00
bellard
efe160c502 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@527 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:28:47 +00:00
bellard
dc887a4dae make the bios be a ROM memory - glibc hacks for setvbuf and signals - correct century storage in CMOS emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@526 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:18:57 +00:00
bellard
b9f1950797 hack for target_ulong define
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@525 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:17:13 +00:00
bellard
e16c53fabb assembly soft MMU defines on i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@524 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:29 +00:00
bellard
8351d2d481 WHEEL defines may not be available in SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@523 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:01 +00:00
bellard
08785f48b7 updated so that PPC/ARM/SPARC executables are automatically launched when invoked
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@522 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:12:46 +00:00
bellard
75c6215f98 correct cpu state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@521 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:37 +00:00
bellard
6b136f9e8f CD-ROM detection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@520 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:12 +00:00
bellard
2ddbbd10de (temporary) only physical dump is possible in gdb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@519 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:07:27 +00:00
bellard
9fa3e85353 new generic TLB support - faster self modifying code support - added ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@518 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:06:42 +00:00
bellard
4390df5107 added support for direct patching on i386 host (faster emulation) - increased translation buffer size - added new TLB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@517 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:03:10 +00:00
bellard
ecd854fdb4 added support for direct patching on i386 host (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@516 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:45:05 +00:00
bellard
513b500f75 include stddef.h for size_t definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@515 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:44:08 +00:00
bellard
edf75d592c export more memory defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@514 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:30 +00:00
bellard
1376847f9f support for new TLB handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@513 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:01 +00:00
bellard
17348a7f5e waiting for TARGET_HAS_SMC patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@512 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:36:11 +00:00
bellard
4f31916ffb added raw/user/kernel memory accesses for shifts/adc/sbb/cmpxchg/push/pop (faster emulation) - make 'call Ev' exception safe - in/out dx fix - PE flag is static
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@511 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:35:00 +00:00
bellard
943144d91a added raw/user/kernel memory accesses (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@510 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:31:11 +00:00
bellard
34e01bbf07 fixed dx based protected in/outs (win98 install) - changed JUMP_TB2 branch number arg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@509 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:30:14 +00:00
bellard
7f1135b9a4 added stx_T1_A0 micro ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@508 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:28:06 +00:00
bellard
f68dd77007 fixed word bit operations with memory offset - suppressed push/pop micro operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@507 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:27:42 +00:00
bellard
436d8b892a correct value for ADDSEG is real mode (fixes GRUB boot) - update static protected mode state - use generic tlb_set_page()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@506 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:26:31 +00:00
bellard
dc6f57fd55 debug updates - page_unprotect() is no longer needed in softmmu case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@505 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:24:35 +00:00
bellard
65262d5738 added PE to static CPU state (avoids flushing translated code when swiching between protected and real mode) - moved memory defs to cpu-all.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@504 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:20:53 +00:00
bellard
773b93ee06 signal fix: update the host signal 'signal ignored' state to avoid unexpected -EINTR values (ash fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@503 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:15:59 +00:00
376 changed files with 179468 additions and 16984 deletions

29
.cvsignore Normal file
View File

@@ -0,0 +1,29 @@
arm-user
arm-softmmu
armeb-user
config-host.*
dyngen
i386
i386-softmmu
i386-user
ppc-softmmu
ppc64-softmmu
ppc-user
qemu-doc.html
qemu-tech.html
qemu.1
qemu.pod
qemu-img.1
qemu-img.pod
sparc-user
qemu-img
sparc-softmmu
x86_64-softmmu
sparc64-user
sparc64-softmmu
mips-softmmu
mipsel-softmmu
mips-user
mipsel-user
sh4-user
sh4-softmmu

216
Changelog
View File

@@ -1,3 +1,219 @@
version 0.8.1:
- USB tablet support (Brad Campbell, Anthony Liguori)
- win32 host serial support (Kazu)
- PC speaker support (Joachim Henke)
- IDE LBA48 support (Jens Axboe)
- SSE3 support
- Solaris port (Ben Taylor)
- Preliminary SH4 target (Samuel Tardieu)
- VNC server (Anthony Liguori)
- slirp fixes (Ed Swierk et al.)
- USB fixes
- ARM Versatile Platform Baseboard emulation (Paul Brook)
version 0.8.0:
- ARM system emulation: Arm Integrator/CP board with an arm1026ej-s
cpu (Paul Brook)
- SMP support
- Mac OS X cocoa improvements (Mike Kronenberg)
- Mac OS X CoreAudio driver (Mike Kronenberg)
- DirectSound driver (malc)
- ALSA audio driver (malc)
- new audio options: '-soundhw' and '-audio-help' (malc)
- ES1370 PCI audio device (malc)
- Initial USB support
- Linux host serial port access
- Linux host low level parallel port access
- New network emulation code supporting VLANs.
- MIPS and MIPSel User Linux emulation
- MIPS fixes to boot Linux (Daniel Jacobowitz)
- NX bit support
- Initial SPARC SMP support (Blue Swirl)
- Major overhaul of the virtual FAT driver for read/write support
(Johannes Schindelin)
version 0.7.2:
- x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
- merge self modifying code handling in dirty ram page mecanism.
- MIPS fixes (Ralf Baechle)
- better user net performances
version 0.7.1:
- read-only Virtual FAT support (Johannes Schindelin)
- Windows 2000 install disk full hack (original idea from Vladimir
N. Oleynik)
- VMDK disk image creation (Filip Navara)
- SPARC64 progress (Blue Swirl)
- initial MIPS support (Jocelyn mayer)
- MIPS improvements (Ralf Baechle)
- 64 bit fixes in user networking (initial patch by Gwenole Beauchesne)
- IOAPIC support (Filip Navara)
version 0.7.0:
- better BIOS translation and HDD geometry auto-detection
- user mode networking bug fix
- undocumented FPU ops support
- Cirrus VGA: support for 1280x1024x[8,15,16] modes
- 'pidfile' option
- .dmg disk image format support (Johannes Schindelin)
- keymaps support (initial patch by Johannes Schindelin)
- big endian ARM support (Lennert Buytenhek)
- added generic 64 bit target support
- x86_64 target support
- initial APIC support
- MMX/SSE/SSE2/PNI support
- PC parallel port support (Mark Jonckheere)
- initial SPARC64 support (Blue Swirl)
- SPARC target boots Linux (Blue Swirl)
- armv5te user mode support (Paul Brook)
- ARM VFP support (Paul Brook)
- ARM "Angel" semihosting syscalls (Paul Brook)
- user mode gdb stub support (Paul Brook)
- Samba 3 support
- initial Cocoa support (Pierre d'Herbemont)
- generic FPU emulation code
- Virtual PC read-only disk image support (Alex Beregszaszi)
version 0.6.1:
- Mac OS X port (Pierre d'Herbemont)
- Virtual console support
- Better monitor line edition
- New block device layer
- New 'qcow' growable disk image support with AES encryption and
transparent decompression
- VMware 3 and 4 read-only disk image support (untested)
- Support for up to 4 serial ports
- TFTP server support (Magnus Damm)
- Port redirection support in user mode networking
- Support for not executable data sections
- Compressed loop disk image support (Johannes Schindelin)
- Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve
Wormley)
- Fixed Fedora Core 2 problems (now you can run qemu without any
LD_ASSUME_KERNEL tricks on FC2)
- DHCP fix for Windows (accept DHCPREQUEST alone)
- SPARC system emulation (Blue Swirl)
- Automatic Samba configuration for host file access from Windows.
- '-loadvm' and '-full-screen' options
- ne2000 savevm support (Johannes Schindelin)
- Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to
the virtual consoles.
- BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert)
- Floppy fixes for NT4 and NT5 (Mike Nordell)
- NT4 IDE fixes (Ben Pfaf, Mike Nordell)
- SDL Audio support and SB16 fixes (malc)
- ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
- VGA font change fix
- VGA read-only CRTC register fix
version 0.6.0:
- minimalist FPU exception support (NetBSD FPU probe fix)
- cr0.ET fix (Win95 boot)
- *BSD port (Markus Niemisto)
- I/O access fix (signaled by Mark Jonckheere)
- IDE drives serial number fix (Mike Nordell)
- int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
- int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
- BSR/BSF "undefined behaviour" fix
- vmdk2raw: convert VMware disk images to raw images
- PCI support
- NE2K PCI support
- dummy VGA PCI support
- VGA font selection fix (Daniel Serpell)
- PIC reset fix (Hidemi KAWAI)
- PIC spurious irq support (aka Solaris install bug)
- added '-localtime' option
- Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu))
- APM and system shutdown support
- Fixed system reset
- Support for other PC BIOSes
- Initial PowerMac hardware emulation
- PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer)
- initial IDE BMDMA support (needed for Darwin x86)
- Set the default memory size for PC emulation to 128 MB
version 0.5.5:
- SDL full screen support (initial patch by malc)
- VGA support on PowerPC PREP
- VBE fixes (Matthew Mastracci)
- PIT fixes (aka Win98 hardware probe and "VGA slowness" bug)
- IDE master only fixes (aka Win98 CD-ROM probe bug)
- ARM load/store half word fix (Ulrich Hecht)
- FDC fixes for Win98
version 0.5.4:
- qemu-fast fixes
- BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell)
- keyboard/mouse fix (Mike Nordell)
- IDE fixes (Linux did not recognized slave drivers)
- VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
- QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer)
- User mode network stack
- imul imm8 fix + 0x82 opcode support (Hidemi KAWAI)
- precise self modifying code (aka BeOS install bug)
version 0.5.3:
- added Bochs VESA VBE support
- VGA memory map mode 3 access fix (OS/2 install fix)
- IDE fixes (Jens Axboe)
- CPU interrupt fixes
- fixed various TLB invalidation cases (NT install)
- fixed cr0.WP semantics (XP install)
- direct chaining support for SPARC and PowerPC (faster)
- ARM NWFPE support (initial patch by Ulrich Hecht)
- added specific x86 to x86 translator (close to native performance
in qemu-i386 and qemu-fast)
- shm syscalls support (Paul McKerras)
- added accurate CR0.MP/ME/TS emulation
- fixed DMA memory write access (Win95 boot floppy fix)
- graphical x86 linux loader
- command line monitor
- generic removable device support
- support of CD-ROM change
- multiple network interface support
- initial x86-64 host support (Gwenole Beauchesne)
- lret to outer priviledge fix (OS/2 install fix)
- task switch fixes (SkyOS boot)
- VM save/restore commands
- new timer API
- more precise RTC emulation (periodic timers + time updates)
- Win32 port (initial patch by Kazu)
version 0.5.2:
- improved soft MMU speed (assembly functions and specializing)
- improved multitasking speed by avoiding flushing TBs when
switching tasks
- improved qemu-fast speed
- improved self modifying code handling (big performance gain in
softmmu mode).
- fixed IO checking
- fixed CD-ROM detection (win98 install CD)
- fixed addseg real mode bug (GRUB boot fix)
- added ROM memory support (win98 boot)
- fixed 'call Ev' in case of paging exception
- updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically
when launching executables for the supported target CPUs.
- PowerPC system emulation update (Jocelyn Mayer)
- PC floppy emulation and DMA fixes (Jocelyn Mayer)
- polled mode for PIC (Jocelyn Mayer)
- fixed PTE dirty bit handling
- fixed xadd same reg bug
- fixed cmpxchg exception safeness
- access to virtual memory in gdb stub
- task gate and NT flag fixes
- eflags optimisation fix for string operations
version 0.5.1:
- float access fixes when using soft mmu

12
LICENSE Normal file
View File

@@ -0,0 +1,12 @@
The following points clarify the QEMU licenses:
1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
system emulator are released under the GNU Lesser General Public
License.
2) The Linux user mode QEMU emulator is released under the GNU General
Public License.
3) QEMU is a trademark of Fabrice Bellard.
Fabrice Bellard.

127
Makefile
View File

@@ -1,65 +1,108 @@
include config-host.mak
CFLAGS=-Wall -O2 -g
CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I.
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
endif
LDFLAGS=-g
LIBS=
DEFINES+=-D_GNU_SOURCE
TOOLS=qemu-mkcow
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
TOOLS=qemu-img$(EXESUF)
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
else
DOCS=
endif
all: dyngen $(TOOLS) qemu-doc.html qemu.1
all: dyngen$(EXESUF) $(TOOLS) $(DOCS)
for d in $(TARGET_DIRS); do \
make -C $$d $@ || exit 1 ; \
$(MAKE) -C $$d $@ || exit 1 ; \
done
qemu-mkcow: qemu-mkcow.o
$(HOST_CC) -o $@ $^ $(LIBS)
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)
dyngen: dyngen.o
$(HOST_CC) -o $@ $^ $(LIBS)
%.o: %.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
dyngen$(EXESUF): dyngen.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.a $(TOOLS) dyngen TAGS qemu.pod
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS *.pod *~ */*~
$(MAKE) -C tests clean
for d in $(TARGET_DIRS); do \
make -C $$d $@ || exit 1 ; \
$(MAKE) -C $$d $@ || exit 1 ; \
done
distclean: clean
rm -f config-host.mak config-host.h
rm -f config-host.mak config-host.h $(DOCS)
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
install: all
mkdir -p $(prefix)/bin
install -m 755 -s $(TOOLS) $(prefix)/bin
mkdir -p $(sharedir)
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin $(sharedir)
mkdir -p $(mandir)/man1
install qemu.1 $(mandir)/man1
KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \
ar de en-us fi fr-be hr it lv nl pl ru th \
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
install-doc: $(DOCS)
mkdir -p "$(DESTDIR)$(docdir)"
$(INSTALL) -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)$(docdir)"
ifndef CONFIG_WIN32
mkdir -p "$(DESTDIR)$(mandir)/man1"
$(INSTALL) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
endif
install: all $(if $(BUILD_DOCS),install-doc)
mkdir -p "$(DESTDIR)$(bindir)"
$(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 \
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
done
ifndef CONFIG_WIN32
mkdir -p "$(DESTDIR)$(datadir)/keymaps"
for x in $(KEYMAPS); do \
$(INSTALL) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
done
endif
for d in $(TARGET_DIRS); do \
make -C $$d $@ || exit 1 ; \
$(MAKE) -C $$d $@ || exit 1 ; \
done
# various test targets
test speed test2: all
make -C tests $@
$(MAKE) -C tests $@
TAGS:
etags *.[ch] tests/*.[ch]
cscope:
rm -f ./cscope.*
find . -name "*.[ch]" -print > ./cscope.files
cscope -b
# documentation
qemu-doc.html: qemu-doc.texi
%.html: %.texi
texi2html -monolithic -number $<
%.info: %.texi
makeinfo $< -o $@
%.dvi: %.texi
texi2dvi $<
qemu.1: qemu-doc.texi
./texi2pod.pl $< qemu.pod
$(SRC_PATH)/texi2pod.pl $< qemu.pod
pod2man --section=1 --center=" " --release=" " qemu.pod > $@
qemu-img.1: qemu-img.texi
$(SRC_PATH)/texi2pod.pl $< qemu-img.pod
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@
FILE=qemu-$(shell cat VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
@@ -72,13 +115,31 @@ tar:
# generate a binary distribution
tarbin:
( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
$(prefix)/bin/qemu $(prefix)/bin/qemu-fast \
$(prefix)/bin/qemu-i386 \
$(prefix)/bin/qemu-arm \
$(prefix)/bin/qemu-sparc \
$(sharedir)/bios.bin \
$(sharedir)/vgabios.bin \
$(mandir)/man1/qemu.1 )
$(bindir)/qemu \
$(bindir)/qemu-system-ppc \
$(bindir)/qemu-system-sparc \
$(bindir)/qemu-system-x86_64 \
$(bindir)/qemu-system-mips \
$(bindir)/qemu-system-mipsel \
$(bindir)/qemu-system-arm \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-armeb \
$(bindir)/qemu-sparc \
$(bindir)/qemu-ppc \
$(bindir)/qemu-mips \
$(bindir)/qemu-mipsel \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/video.x \
$(datadir)/proll.elf \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
ifneq ($(wildcard .depend),)
include .depend

View File

@@ -1,18 +1,48 @@
include config.mak
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH)
CFLAGS=-Wall -O2 -g
TARGET_BASE_ARCH:=$(TARGET_ARCH)
ifeq ($(TARGET_ARCH), x86_64)
TARGET_BASE_ARCH:=i386
endif
ifeq ($(TARGET_ARCH), ppc64)
TARGET_BASE_ARCH:=ppc
endif
ifeq ($(TARGET_ARCH), sparc64)
TARGET_BASE_ARCH:=sparc
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
ifdef CONFIG_USER_ONLY
VPATH+=:$(SRC_PATH)/linux-user
DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
endif
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
#CFLAGS+=-Werror
LDFLAGS=-g
LIBS=
DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH)
HELPER_CFLAGS=$(CFLAGS)
DYNGEN=../dyngen
DYNGEN=../dyngen$(EXESUF)
# user emulator name
QEMU_USER=qemu-$(TARGET_ARCH)
TARGET_ARCH2=$(TARGET_ARCH)
ifeq ($(TARGET_ARCH),arm)
ifeq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=armeb
endif
endif
ifeq ($(TARGET_ARCH),mips)
ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
TARGET_ARCH2=mipsel
endif
endif
QEMU_USER=qemu-$(TARGET_ARCH2)
# system emulator name
ifdef CONFIG_SOFTMMU
QEMU_SYSTEM=qemu
ifeq ($(TARGET_ARCH), i386)
QEMU_SYSTEM=qemu$(EXESUF)
else
QEMU_SYSTEM=qemu-system-$(TARGET_ARCH2)$(EXESUF)
endif
else
QEMU_SYSTEM=qemu-fast
endif
@@ -20,23 +50,11 @@ endif
ifdef CONFIG_USER_ONLY
PROGS=$(QEMU_USER)
else
ifeq ($(TARGET_ARCH), i386)
ifeq ($(ARCH), i386)
PROGS+=$(QEMU_SYSTEM)
ifndef CONFIG_SOFTMMU
CONFIG_STATIC=y
endif
endif
ifeq ($(ARCH), ppc)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif
endif
endif
endif # !CONFIG_USER_ONLY
ifdef CONFIG_STATIC
LDFLAGS+=-static
@@ -46,7 +64,7 @@ ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+= -falign-functions=0
OP_CFLAGS+= -falign-functions=0 -fno-gcse
else
OP_CFLAGS+= -malign-functions=0
endif
@@ -67,7 +85,13 @@ LDFLAGS+=-Wl,-shared
endif
endif
ifeq ($(ARCH),x86_64)
OP_CFLAGS=$(CFLAGS) -falign-functions=0
LDFLAGS+=-Wl,-T,$(SRC_PATH)/x86_64.ld
endif
ifeq ($(ARCH),ppc)
CFLAGS+= -D__powerpc__
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
endif
@@ -102,11 +126,13 @@ LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
endif
ifeq ($(ARCH),ia64)
CFLAGS += -mno-sdata
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
endif
ifeq ($(ARCH),arm)
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog -fno-omit-frame-pointer
LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
endif
@@ -120,10 +146,24 @@ ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
LIBS+=-lmx
endif
#########################################################
DEFINES+=-D_GNU_SOURCE
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS+=-lm
ifndef CONFIG_USER_ONLY
LIBS+=-lz
endif
ifdef CONFIG_WIN32
LIBS+=-lwinmm -lws2_32 -liphlpapi
endif
ifdef CONFIG_SOLARIS
LIBS+=-lsocket -lnsl -lresolv
endif
# profiling code
ifdef TARGET_GPROF
@@ -131,45 +171,94 @@ LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
endif
ifeq ($(TARGET_ARCH), arm)
OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
endif
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
# cpu emulator library
LIBOBJS=thunk.o exec.o translate-all.o cpu-exec.o gdbstub.o \
translate.o op.o
LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\
translate.o op.o
ifdef CONFIG_SOFTFLOAT
LIBOBJS+=fpu/softfloat.o
else
LIBOBJS+=fpu/softfloat-native.o
endif
DEFINES+=-I$(SRC_PATH)/fpu
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=helper.o helper2.o
ifeq ($(ARCH), i386)
LIBOBJS+=translate-copy.o
endif
endif
ifeq ($(TARGET_ARCH), ppc)
LIBOBJS+=helper.o
ifeq ($(TARGET_ARCH), x86_64)
LIBOBJS+=helper.o helper2.o
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_ARCH), mips)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), arm)
LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
LIBOBJS+= op_helper.o helper.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
USE_I386_DIS=y
endif
ifeq ($(findstring x86_64, $(TARGET_ARCH) $(ARCH)),x86_64)
USE_I386_DIS=y
endif
ifdef USE_I386_DIS
LIBOBJS+=i386-dis.o
endif
ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha)
LIBOBJS+=alpha-dis.o
endif
ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc)
LIBOBJS+=ppc-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_ARCH) $(ARCH)),sparc)
ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
LIBOBJS+=mips-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
LIBOBJS+=sparc-dis.o
endif
ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
LIBOBJS+=arm-dis.o
endif
ifeq ($(findstring m68k, $(TARGET_ARCH) $(ARCH)),m68k)
LIBOBJS+=m68k-dis.o
endif
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
LIBOBJS+=sh4-dis.o
endif
ifeq ($(ARCH),ia64)
OBJS += ia64-syscall.o
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o
endif
all: $(PROGS)
@@ -183,12 +272,100 @@ ifeq ($(ARCH),alpha)
endif
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o block.o ide.o vga.o sb16.o dma.o oss.o
VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o loader.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
ifdef CONFIG_WIN32
VL_OBJS+=tap-win32.o
endif
SOUND_HW = sb16.o es1370.o
AUDIODRV = audio.o noaudio.o wavaudio.o
ifdef CONFIG_SDL
AUDIODRV += sdlaudio.o
endif
ifdef CONFIG_OSS
AUDIODRV += ossaudio.o
endif
ifdef CONFIG_COREAUDIO
AUDIODRV += coreaudio.o
endif
ifdef CONFIG_ALSA
AUDIODRV += alsaaudio.o
LIBS += -lasound
endif
ifdef CONFIG_DSOUND
AUDIODRV += dsoundaudio.o
LIBS += -lole32 -ldxguid
endif
ifdef CONFIG_FMOD
AUDIODRV += fmodaudio.o
audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
LIBS += $(CONFIG_FMOD_LIB)
endif
ifdef CONFIG_ADLIB
SOUND_HW += fmopl.o adlib.o
endif
# USB layer
VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o
# PCI network cards
VL_OBJS+= ne2000.o rtl8139.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
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
DEFINES += -DHAS_AUDIO
endif
ifeq ($(TARGET_ARCH), mips)
VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.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+= fdc.o mc146818rtc.o serial.o m48t59.o
VL_OBJS+= cirrus_vga.o parallel.o
else
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
endif
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
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
ifdef CONFIG_SDL
VL_OBJS+=sdl.o
ifdef CONFIG_STATIC
SDL_LIBS:=$(SDL_STATIC_LIBS)
endif
VL_OBJS+=vnc.o
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
ifdef CONFIG_COREAUDIO
COCOA_LIBS+=-framework CoreAudio
endif
endif
ifdef CONFIG_SLIRP
DEFINES+=-I$(SRC_PATH)/slirp
SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
VL_LDFLAGS=
@@ -199,16 +376,47 @@ endif
ifndef CONFIG_SOFTMMU
VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
ifndef CONFIG_SOLARIS
VL_LIBS=-lutil
endif
endif
endif
ifdef TARGET_GPROF
vl.o: CFLAGS+=-p
VL_LDFLAGS+=-p
endif
ifeq ($(ARCH),ia64)
VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
endif
ifdef CONFIG_WIN32
SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS)
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
sdl.o: sdl.c
cocoa.o: cocoa.m
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
sdl.o: sdl.c keymaps.c sdl_keysym.h
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
vldepend: $(VL_OBJS:.o=.c)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
@@ -217,7 +425,9 @@ libqemu.a: $(LIBOBJS)
translate.o: translate.c gen-op.h opc.h cpu.h
translate-all.o: translate-all.c op.h opc.h cpu.h
translate-all.o: translate-all.c opc.h cpu.h
translate-op.o: translate-all.c op.h opc.h cpu.h
op.h: op.o $(DYNGEN)
$(DYNGEN) -o $@ $<
@@ -234,27 +444,63 @@ op.o: op.c
helper.o: helper.c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
ifeq ($(TARGET_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h
ifeq ($(TARGET_BASE_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
endif
ifeq ($(TARGET_ARCH), arm)
op.o: op.c op_template.h
pl110.o: pl110_template.h
endif
ifeq ($(TARGET_ARCH), sparc)
op.o: op.c op_template.h
ifeq ($(TARGET_BASE_ARCH), sparc)
op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h
magic_load.o: elf_op.h
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
op.o: op.c op_template.h op_mem.h
op_helper.o: op_helper_mem.h
translate.o: translate.c translate_init.c
endif
ifeq ($(TARGET_ARCH), mips)
op.o: op.c op_template.c op_mem.c
op_helper.o: op_helper_mem.c
endif
loader.o: loader.c elf_ops.h
ifeq ($(TARGET_ARCH), sh4)
op.o: op.c op_mem.c cpu.h
op_helper.o: op_helper.c exec.h cpu.h
helper.o: helper.c exec.h cpu.h
sh7750.o: sh7750.c sh7750_regs.h sh7750_regnames.h cpu.h
shix.o: shix.c sh7750_regs.h sh7750_regnames.h
sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
tc58128.o: tc58128.c
endif
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
%.o: %.S
$(CC) $(DEFINES) -c -o $@ $<
clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
install: all
install -m 755 -s $(PROGS) $(prefix)/bin
ifneq ($(PROGS),)
$(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
endif
ifneq ($(wildcard .depend),)
include .depend
endif
ifeq (1, 0)
audio.o sdlaudio.o dsoundaudio.o ossaudio.o wavaudio.o noaudio.o \
fmodaudio.o alsaaudio.o mixeng.o sb16.o es1370.o gus.o adlib.o: \
CFLAGS := $(CFLAGS) -Wall -Werror -W -Wsign-compare
endif

58
README
View File

@@ -1,61 +1,3 @@
The QEMU x86 emulator
---------------------
INSTALLATION
------------
Type
./configure
make
to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
supported target CPUs).
Type
make install
to install QEMU in /usr/local
Tested tool versions
--------------------
In order to compile QEMU succesfully, it is very important that you
have the right tools. The most important one is gcc. I cannot guaranty
that QEMU works if you do not use a tested gcc version. Look at
'configure' and 'Makefile' if you want to make a different gcc
version work.
host gcc binutils glibc linux distribution
----------------------------------------------------------------------
x86 2.95.2 2.13.2 2.1.3 2.4.18
3.2 2.13.2 2.1.3 2.4.18
2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3
3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9
PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq
3.2
Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0
Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0
ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0
[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
for gcc version >= 3.3.
[2] Linux >= 2.4.20 is necessary for precise exception support
(untested).
[3] 2.4.9-ac10-rmk2-np1-cerf2
[4] gcc 2.95.x generates invalid code when using too many register
variables. You must use gcc 3.x on PowerPC.
Documentation
-------------
Read the documentation in qemu-doc.html.
Fabrice Bellard.

63
TODO
View File

@@ -1,32 +1,61 @@
short term:
----------
- support variable tsc freq
- cpu_interrupt() win32/SMP fix
- 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)
- see undefined flags for BTx insn
- user/kernel PUSHL/POPL in helper.c
- keyboard output buffer filling timing emulation
- verify tb_flush() with a20 and TLBs
- cmos clock update and timers
- return UD exception if LOCK prefix incorrectly used
- test ldt limit < 7 ?
- tests for each target CPU
- optimize FPU operations (evaluate x87 stack pointer statically) and
fix cr0.TS emulation
- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
- sysenter/sysexit emulation
- 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)
lower priority:
--------------
ppc specific:
------------
- TLB invalidate not needed if msr_pr changes
- SPR_ENCODE() not useful
- enable shift optimizations ?
linux-user specific:
-------------------
- add IPC syscalls
- SMP support
- use -msoft-float on ARM
- use kernel traps for unaligned accesses on ARM ?
- handle rare page fault cases (in particular if page fault in heplers or
- handle rare page fault cases (in particular if page fault in helpers or
in syscall emulation code).
- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit
issues, fix 16 bit uid issues)
- use page_unprotect_range in every suitable syscall to handle all
cases of self modifying code.
- use gcc as a backend to generate better code (easy to do by using
op-i386.c operations as local inline functions).
- add SSE2/MMX operations
- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
- use kernel traps for unaligned accesses on ARM ?
lower priority:
--------------
- int15 ah=86: use better timing
- suppress shift_mem ops
- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
- optimize FPU operations (evaluate x87 stack pointer statically)
- use -msoft-float on ARM

View File

@@ -1 +1 @@
0.5.1
0.8.1

431
a.out.h Normal file
View File

@@ -0,0 +1,431 @@
/* a.out.h
Copyright 1997, 1998, 1999, 2001 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _A_OUT_H_
#define _A_OUT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define COFF_IMAGE_WITH_PE
#define COFF_LONG_SECTION_NAMES
/*** coff information for Intel 386/486. */
/********************** FILE HEADER **********************/
struct external_filehdr {
short f_magic; /* magic number */
short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
short f_opthdr; /* sizeof(optional hdr) */
short f_flags; /* flags */
};
/* Bits for f_flags:
* F_RELFLG relocation info stripped from file
* F_EXEC file is executable (no unresolved external references)
* F_LNNO line numbers stripped from file
* F_LSYMS local symbols stripped from file
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
*/
#define F_RELFLG (0x0001)
#define F_EXEC (0x0002)
#define F_LNNO (0x0004)
#define F_LSYMS (0x0008)
#define I386MAGIC 0x14c
#define I386PTXMAGIC 0x154
#define I386AIXMAGIC 0x175
/* This is Lynx's all-platform magic number for executables. */
#define LYNXCOFFMAGIC 0415
#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \
&& (x).f_magic != I386AIXMAGIC \
&& (x).f_magic != I386PTXMAGIC \
&& (x).f_magic != LYNXCOFFMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER"=
**********************/
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of data used for this file=
*/
}
AOUTHDR;
#define AOUTSZ 28
#define AOUTHDRSZ 28
#define OMAGIC 0404 /* object files, eg as output */
#define ZMAGIC 0413 /* demand load format, eg normal ld output */
#define STMAGIC 0401 /* target shlib */
#define SHMAGIC 0443 /* host shlib */
/* define some NT default values */
/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
#define NT_SECTION_ALIGNMENT 0x1000
#define NT_FILE_ALIGNMENT 0x200
#define NT_DEF_RESERVE 0x100000
#define NT_DEF_COMMIT 0x1000
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
unsigned long s_paddr; /* physical address, offset
of last addr in scn */
unsigned long s_vaddr; /* virtual address */
unsigned long s_size; /* section size */
unsigned long s_scnptr; /* file ptr to raw data for section */
unsigned long s_relptr; /* file ptr to relocation */
unsigned long s_lnnoptr; /* file ptr to line numbers */
unsigned short s_nreloc; /* number of relocation entries */
unsigned short s_nlnno; /* number of line number entries*/
unsigned long s_flags; /* flags */
};
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _COMMENT ".comment"
#define _LIB ".lib"
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */
unsigned long l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct __attribute__((packed)) external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
unsigned long e_zeroes;
unsigned long e_offset;
} e;
} e;
unsigned long e_value;
unsigned short e_scnum;
unsigned short e_type;
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (0xf)
#define N_TMASK (0x30)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
unsigned long x_tagndx; /* str, un, or enum tag indx */
union {
struct {
unsigned short x_lnno; /* declaration line number */
unsigned short x_size; /* str/union/array size */
} x_lnsz;
unsigned long x_fsize; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
unsigned long x_lnnoptr;/* ptr to fcn line # */
unsigned long x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
unsigned short x_tvndx; /* tv index */
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
unsigned long x_zeroes;
unsigned long x_offset;
} x_n;
} x_file;
struct {
unsigned long x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
unsigned long x_checksum; /* section COMDAT checksum */
unsigned short x_associated;/* COMDAT associated section index */
char x_comdat[1]; /* COMDAT selection number */
} x_scn;
struct {
unsigned long x_tvfill; /* tv fill value */
unsigned short x_tvlen; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define _ETEXT "etext"
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_type[2];
};
#define RELOC struct external_reloc
#define RELSZ 10
/* end of coff/i386.h */
/* PE COFF header information */
#ifndef _PE_H
#define _PE_H
/* NT specific file attributes */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
/* additional flags to be set for section headers to allow the NT loader to
read and write to the section data (to replace the addresses of data in
dlls for one thing); also to execute the section in .text's case=
*/
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
/*
* Section characteristics added for ppc-nt
*/
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
/* COMDAT selection codes. */
#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */
#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */
#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */
#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */
/* Magic values that are true for all dos/nt implementations */
#define DOSMAGIC 0x5a4d
#define NT_SIGNATURE 0x00004550
/* NT allows long filenames, we want to accommodate this. This may break
some of the bfd functions */
#undef FILNMLEN
#define FILNMLEN 18 /* # characters in a file name */
#ifdef COFF_IMAGE_WITH_PE
/* The filehdr is only weired in images */
#undef FILHDR
struct external_PE_filehdr
{
/* DOS header fields */
unsigned short e_magic; /* Magic number, 0x5a4d */
unsigned short e_cblp; /* Bytes on last page of file, 0x90 */
unsigned short e_cp; /* Pages in file, 0x3 */
unsigned short e_crlc; /* Relocations, 0x0 */
unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */
unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */
unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */
unsigned short e_ss; /* Initial (relative) SS value, 0x0 */
unsigned short e_sp; /* Initial SP value, 0xb8 */
unsigned short e_csum; /* Checksum, 0x0 */
unsigned short e_ip; /* Initial IP value, 0x0 */
unsigned short e_cs; /* Initial (relative) CS value, 0x0 */
unsigned short e_lfarlc; /* File address of relocation table, 0x40 */
unsigned short e_ovno; /* Overlay number, 0x0 */
char e_res[4][2]; /* Reserved words, all 0x0 */
unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */
unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */
char e_res2[10][2]; /* Reserved words, all 0x0 */
unsigned long e_lfanew; /* File address of new exe header, 0x80 */
char dos_message[16][4]; /* other stuff, always follow DOS header */
unsigned int nt_signature; /* required NT signature, 0x4550 */
/* From standard header */
unsigned short f_magic; /* magic number */
unsigned short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
#define FILHDR struct external_PE_filehdr
#undef FILHSZ
#define FILHSZ 152
#endif
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of all data used for this file */
/* NT extra fields; see internal.h for descriptions */
unsigned long ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
char Reserved1[4];
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
unsigned long SizeOfStackReserve;
unsigned long SizeOfStackCommit;
unsigned long SizeOfHeapReserve;
unsigned long SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEAOUTHDR;
#undef AOUTSZ
#define AOUTSZ (AOUTHDRSZ + 196)
#undef E_FILNMLEN
#define E_FILNMLEN 18 /* # characters in a file name */
#endif
/* end of coff/pe.h */
#define DT_NON (0) /* no derived type */
#define DT_PTR (1) /* pointer */
#define DT_FCN (2) /* function */
#define DT_ARY (3) /* array */
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
#ifdef __cplusplus
}
#endif
#endif /* _A_OUT_H_ */

1317
aes.c Normal file

File diff suppressed because it is too large Load Diff

26
aes.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef QEMU_AES_H
#define QEMU_AES_H
#define AES_MAXNR 14
#define AES_BLOCK_SIZE 16
struct aes_key_st {
uint32_t rd_key[4 *(AES_MAXNR + 1)];
int rounds;
};
typedef struct aes_key_st AES_KEY;
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void AES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
unsigned char *ivec, const int enc);
#endif

View File

@@ -23,9 +23,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include <stdio.h>
#include "dis-asm.h"
#define ATTRIBUTE_UNUSED __attribute__((unused))
#define _(x) x
/* The opcode table is an array of struct alpha_opcode. */
struct alpha_opcode

View File

@@ -1556,6 +1556,11 @@ print_insn_arm (pc, info)
}
is_thumb = force_thumb;
if (pc & 1)
{
is_thumb = 1;
pc &= ~(bfd_vma) 1;
}
#if 0
if (!is_thumb && info->symbols != NULL)

981
audio/alsaaudio.c Normal file
View File

@@ -0,0 +1,981 @@
/*
* QEMU ALSA audio driver
*
* Copyright (c) 2005 Vassili Karpov (malc)
*
* 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 <alsa/asoundlib.h>
#include "vl.h"
#define AUDIO_CAP "alsa"
#include "audio_int.h"
typedef struct ALSAVoiceOut {
HWVoiceOut hw;
void *pcm_buf;
snd_pcm_t *handle;
} ALSAVoiceOut;
typedef struct ALSAVoiceIn {
HWVoiceIn hw;
snd_pcm_t *handle;
void *pcm_buf;
} ALSAVoiceIn;
static struct {
int size_in_usec_in;
int size_in_usec_out;
const char *pcm_name_in;
const char *pcm_name_out;
unsigned int buffer_size_in;
unsigned int period_size_in;
unsigned int buffer_size_out;
unsigned int period_size_out;
unsigned int threshold;
int buffer_size_in_overriden;
int period_size_in_overriden;
int buffer_size_out_overriden;
int period_size_out_overriden;
int verbose;
} conf = {
#ifdef HIGH_LATENCY
.size_in_usec_in = 1,
.size_in_usec_out = 1,
#endif
.pcm_name_out = "hw:0,0",
.pcm_name_in = "hw:0,0",
#ifdef HIGH_LATENCY
.buffer_size_in = 400000,
.period_size_in = 400000 / 4,
.buffer_size_out = 400000,
.period_size_out = 400000 / 4,
#else
#define DEFAULT_BUFFER_SIZE 1024
#define DEFAULT_PERIOD_SIZE 256
.buffer_size_in = DEFAULT_BUFFER_SIZE * 4,
.period_size_in = DEFAULT_PERIOD_SIZE * 4,
.buffer_size_out = DEFAULT_BUFFER_SIZE,
.period_size_out = DEFAULT_PERIOD_SIZE,
.buffer_size_in_overriden = 0,
.buffer_size_out_overriden = 0,
.period_size_in_overriden = 0,
.period_size_out_overriden = 0,
#endif
.threshold = 0,
.verbose = 0
};
struct alsa_params_req {
int freq;
audfmt_e fmt;
int nchannels;
unsigned int buffer_size;
unsigned int period_size;
};
struct alsa_params_obt {
int freq;
audfmt_e fmt;
int nchannels;
snd_pcm_uframes_t samples;
};
static void GCC_FMT_ATTR (2, 3) alsa_logerr (int err, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
}
static void GCC_FMT_ATTR (3, 4) alsa_logerr2 (
int err,
const char *typ,
const char *fmt,
...
)
{
va_list ap;
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n", snd_strerror (err));
}
static void alsa_anal_close (snd_pcm_t **handlep)
{
int err = snd_pcm_close (*handlep);
if (err) {
alsa_logerr (err, "Failed to close PCM handle %p\n", *handlep);
}
*handlep = NULL;
}
static int alsa_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int aud_to_alsafmt (audfmt_e fmt)
{
switch (fmt) {
case AUD_FMT_S8:
return SND_PCM_FORMAT_S8;
case AUD_FMT_U8:
return SND_PCM_FORMAT_U8;
case AUD_FMT_S16:
return SND_PCM_FORMAT_S16_LE;
case AUD_FMT_U16:
return SND_PCM_FORMAT_U16_LE;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
#ifdef DEBUG_AUDIO
abort ();
#endif
return SND_PCM_FORMAT_U8;
}
}
static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
{
switch (alsafmt) {
case SND_PCM_FORMAT_S8:
*endianness = 0;
*fmt = AUD_FMT_S8;
break;
case SND_PCM_FORMAT_U8:
*endianness = 0;
*fmt = AUD_FMT_U8;
break;
case SND_PCM_FORMAT_S16_LE:
*endianness = 0;
*fmt = AUD_FMT_S16;
break;
case SND_PCM_FORMAT_U16_LE:
*endianness = 0;
*fmt = AUD_FMT_U16;
break;
case SND_PCM_FORMAT_S16_BE:
*endianness = 1;
*fmt = AUD_FMT_S16;
break;
case SND_PCM_FORMAT_U16_BE:
*endianness = 1;
*fmt = AUD_FMT_U16;
break;
default:
dolog ("Unrecognized audio format %d\n", alsafmt);
return -1;
}
return 0;
}
#if defined DEBUG_MISMATCHES || defined DEBUG
static void alsa_dump_info (struct alsa_params_req *req,
struct alsa_params_obt *obt)
{
dolog ("parameter | requested value | obtained value\n");
dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
dolog ("channels | %10d | %10d\n",
req->nchannels, obt->nchannels);
dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
dolog ("============================================\n");
dolog ("requested: buffer size %d period size %d\n",
req->buffer_size, req->period_size);
dolog ("obtained: samples %ld\n", obt->samples);
}
#endif
static void alsa_set_threshold (snd_pcm_t *handle, snd_pcm_uframes_t threshold)
{
int err;
snd_pcm_sw_params_t *sw_params;
snd_pcm_sw_params_alloca (&sw_params);
err = snd_pcm_sw_params_current (handle, sw_params);
if (err < 0) {
dolog ("Could not fully initialize DAC\n");
alsa_logerr (err, "Failed to get current software parameters\n");
return;
}
err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, threshold);
if (err < 0) {
dolog ("Could not fully initialize DAC\n");
alsa_logerr (err, "Failed to set software threshold to %ld\n",
threshold);
return;
}
err = snd_pcm_sw_params (handle, sw_params);
if (err < 0) {
dolog ("Could not fully initialize DAC\n");
alsa_logerr (err, "Failed to set software parameters\n");
return;
}
}
static int alsa_open (int in, struct alsa_params_req *req,
struct alsa_params_obt *obt, snd_pcm_t **handlep)
{
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
int err, freq, nchannels;
const char *pcm_name = in ? conf.pcm_name_in : conf.pcm_name_out;
unsigned int period_size, buffer_size;
snd_pcm_uframes_t obt_buffer_size;
const char *typ = in ? "ADC" : "DAC";
freq = req->freq;
period_size = req->period_size;
buffer_size = req->buffer_size;
nchannels = req->nchannels;
snd_pcm_hw_params_alloca (&hw_params);
err = snd_pcm_open (
&handle,
pcm_name,
in ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
SND_PCM_NONBLOCK
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to open `%s':\n", pcm_name);
return -1;
}
err = snd_pcm_hw_params_any (handle, hw_params);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to initialize hardware parameters\n");
goto err;
}
err = snd_pcm_hw_params_set_access (
handle,
hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set access type\n");
goto err;
}
err = snd_pcm_hw_params_set_format (handle, hw_params, req->fmt);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set format %d\n", req->fmt);
goto err;
}
err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &freq, 0);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set frequency %d\n", req->freq);
goto err;
}
err = snd_pcm_hw_params_set_channels_near (
handle,
hw_params,
&nchannels
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set number of channels %d\n",
req->nchannels);
goto err;
}
if (nchannels != 1 && nchannels != 2) {
alsa_logerr2 (err, typ,
"Can not handle obtained number of channels %d\n",
nchannels);
goto err;
}
if (!((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out))) {
if (!buffer_size) {
buffer_size = DEFAULT_BUFFER_SIZE;
period_size= DEFAULT_PERIOD_SIZE;
}
}
if (buffer_size) {
if ((in && conf.size_in_usec_in) || (!in && conf.size_in_usec_out)) {
if (period_size) {
err = snd_pcm_hw_params_set_period_time_near (
handle,
hw_params,
&period_size,
0
);
if (err < 0) {
alsa_logerr2 (err, typ,
"Failed to set period time %d\n",
req->period_size);
goto err;
}
}
err = snd_pcm_hw_params_set_buffer_time_near (
handle,
hw_params,
&buffer_size,
0
);
if (err < 0) {
alsa_logerr2 (err, typ,
"Failed to set buffer time %d\n",
req->buffer_size);
goto err;
}
}
else {
int dir;
snd_pcm_uframes_t minval;
if (period_size) {
minval = period_size;
dir = 0;
err = snd_pcm_hw_params_get_period_size_min (
hw_params,
&minval,
&dir
);
if (err < 0) {
alsa_logerr (
err,
"Could not get minmal period size for %s\n",
typ
);
}
else {
if (period_size < minval) {
if ((in && conf.period_size_in_overriden)
|| (!in && conf.period_size_out_overriden)) {
dolog ("%s period size(%d) is less "
"than minmal period size(%ld)\n",
typ,
period_size,
minval);
}
period_size = minval;
}
}
err = snd_pcm_hw_params_set_period_size (
handle,
hw_params,
period_size,
0
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set period size %d\n",
req->period_size);
goto err;
}
}
minval = buffer_size;
err = snd_pcm_hw_params_get_buffer_size_min (
hw_params,
&minval
);
if (err < 0) {
alsa_logerr (err, "Could not get minmal buffer size for %s\n",
typ);
}
else {
if (buffer_size < minval) {
if ((in && conf.buffer_size_in_overriden)
|| (!in && conf.buffer_size_out_overriden)) {
dolog (
"%s buffer size(%d) is less "
"than minimal buffer size(%ld)\n",
typ,
buffer_size,
minval
);
}
buffer_size = minval;
}
}
err = snd_pcm_hw_params_set_buffer_size (
handle,
hw_params,
buffer_size
);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to set buffer size %d\n",
req->buffer_size);
goto err;
}
}
}
else {
dolog ("warning: Buffer size is not set\n");
}
err = snd_pcm_hw_params (handle, hw_params);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to apply audio parameters\n");
goto err;
}
err = snd_pcm_hw_params_get_buffer_size (hw_params, &obt_buffer_size);
if (err < 0) {
alsa_logerr2 (err, typ, "Failed to get buffer size\n");
goto err;
}
err = snd_pcm_prepare (handle);
if (err < 0) {
alsa_logerr2 (err, typ, "Could not prepare handle %p\n", handle);
goto err;
}
if (!in && conf.threshold) {
snd_pcm_uframes_t threshold;
int bytes_per_sec;
bytes_per_sec = freq
<< (nchannels == 2)
<< (req->fmt == AUD_FMT_S16 || req->fmt == AUD_FMT_U16);
threshold = (conf.threshold * bytes_per_sec) / 1000;
alsa_set_threshold (handle, threshold);
}
obt->fmt = req->fmt;
obt->nchannels = nchannels;
obt->freq = freq;
obt->samples = obt_buffer_size;
*handlep = handle;
#if defined DEBUG_MISMATCHES || defined DEBUG
if (obt->fmt != req->fmt ||
obt->nchannels != req->nchannels ||
obt->freq != req->freq) {
dolog ("Audio paramters mismatch for %s\n", typ);
alsa_dump_info (req, obt);
}
#endif
#ifdef DEBUG
alsa_dump_info (req, obt);
#endif
return 0;
err:
alsa_anal_close (&handle);
return -1;
}
static int alsa_recover (snd_pcm_t *handle)
{
int err = snd_pcm_prepare (handle);
if (err < 0) {
alsa_logerr (err, "Failed to prepare handle %p\n", handle);
return -1;
}
return 0;
}
static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
{
snd_pcm_sframes_t avail;
avail = snd_pcm_avail_update (handle);
if (avail < 0) {
if (avail == -EPIPE) {
if (!alsa_recover (handle)) {
avail = snd_pcm_avail_update (handle);
}
}
if (avail < 0) {
alsa_logerr (avail,
"Could not obtain number of available frames\n");
return -1;
}
}
return avail;
}
static int alsa_run_out (HWVoiceOut *hw)
{
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
int rpos, live, decr;
int samples;
uint8_t *dst;
st_sample_t *src;
snd_pcm_sframes_t avail;
live = audio_pcm_hw_get_live_out (hw);
if (!live) {
return 0;
}
avail = alsa_get_avail (alsa->handle);
if (avail < 0) {
dolog ("Could not get number of available playback frames\n");
return 0;
}
decr = audio_MIN (live, avail);
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int len = audio_MIN (samples, left_till_end_samples);
snd_pcm_sframes_t written;
src = hw->mix_buf + rpos;
dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
hw->clip (dst, src, len);
while (len) {
written = snd_pcm_writei (alsa->handle, dst, len);
if (written <= 0) {
switch (written) {
case 0:
if (conf.verbose) {
dolog ("Failed to write %d frames (wrote zero)\n", len);
}
goto exit;
case -EPIPE:
if (alsa_recover (alsa->handle)) {
alsa_logerr (written, "Failed to write %d frames\n",
len);
goto exit;
}
if (conf.verbose) {
dolog ("Recovering from playback xrun\n");
}
continue;
case -EAGAIN:
goto exit;
default:
alsa_logerr (written, "Failed to write %d frames to %p\n",
len, dst);
goto exit;
}
}
mixeng_clear (src, written);
rpos = (rpos + written) % hw->samples;
samples -= written;
len -= written;
dst = advance (dst, written << hw->info.shift);
src += written;
}
}
exit:
hw->rpos = rpos;
return decr;
}
static void alsa_fini_out (HWVoiceOut *hw)
{
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
ldebug ("alsa_fini\n");
alsa_anal_close (&alsa->handle);
if (alsa->pcm_buf) {
qemu_free (alsa->pcm_buf);
alsa->pcm_buf = NULL;
}
}
static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
{
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
audfmt_e effective_fmt;
int endianness;
int err;
snd_pcm_t *handle;
audsettings_t obt_as;
req.fmt = aud_to_alsafmt (as->fmt);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_out;
req.buffer_size = conf.buffer_size_out;
if (alsa_open (0, &req, &obt, &handle)) {
return -1;
}
err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
if (err) {
alsa_anal_close (&handle);
return -1;
}
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
hw->samples = obt.samples;
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
if (!alsa->pcm_buf) {
dolog ("Could not allocate DAC buffer (%d samples, each %d bytes)\n",
hw->samples, 1 << hw->info.shift);
alsa_anal_close (&handle);
return -1;
}
alsa->handle = handle;
return 0;
}
static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
{
int err;
if (pause) {
err = snd_pcm_drop (handle);
if (err < 0) {
alsa_logerr (err, "Could not stop %s\n", typ);
return -1;
}
}
else {
err = snd_pcm_prepare (handle);
if (err < 0) {
alsa_logerr (err, "Could not prepare handle for %s\n", typ);
return -1;
}
}
return 0;
}
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
return alsa_voice_ctl (alsa->handle, "playback", 0);
case VOICE_DISABLE:
ldebug ("disabling voice\n");
return alsa_voice_ctl (alsa->handle, "playback", 1);
}
return -1;
}
static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
{
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
struct alsa_params_req req;
struct alsa_params_obt obt;
int endianness;
int err;
audfmt_e effective_fmt;
snd_pcm_t *handle;
audsettings_t obt_as;
req.fmt = aud_to_alsafmt (as->fmt);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_in;
req.buffer_size = conf.buffer_size_in;
if (alsa_open (1, &req, &obt, &handle)) {
return -1;
}
err = alsa_to_audfmt (obt.fmt, &effective_fmt, &endianness);
if (err) {
alsa_anal_close (&handle);
return -1;
}
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
hw->samples = obt.samples;
alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
if (!alsa->pcm_buf) {
dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
hw->samples, 1 << hw->info.shift);
alsa_anal_close (&handle);
return -1;
}
alsa->handle = handle;
return 0;
}
static void alsa_fini_in (HWVoiceIn *hw)
{
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
alsa_anal_close (&alsa->handle);
if (alsa->pcm_buf) {
qemu_free (alsa->pcm_buf);
alsa->pcm_buf = NULL;
}
}
static int alsa_run_in (HWVoiceIn *hw)
{
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
int hwshift = hw->info.shift;
int i;
int live = audio_pcm_hw_get_live_in (hw);
int dead = hw->samples - live;
int decr;
struct {
int add;
int len;
} bufs[2] = {
{ hw->wpos, 0 },
{ 0, 0 }
};
snd_pcm_sframes_t avail;
snd_pcm_uframes_t read_samples = 0;
if (!dead) {
return 0;
}
avail = alsa_get_avail (alsa->handle);
if (avail < 0) {
dolog ("Could not get number of captured frames\n");
return 0;
}
if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) {
avail = hw->samples;
}
decr = audio_MIN (dead, avail);
if (!decr) {
return 0;
}
if (hw->wpos + decr > hw->samples) {
bufs[0].len = (hw->samples - hw->wpos);
bufs[1].len = (decr - (hw->samples - hw->wpos));
}
else {
bufs[0].len = decr;
}
for (i = 0; i < 2; ++i) {
void *src;
st_sample_t *dst;
snd_pcm_sframes_t nread;
snd_pcm_uframes_t len;
len = bufs[i].len;
src = advance (alsa->pcm_buf, bufs[i].add << hwshift);
dst = hw->conv_buf + bufs[i].add;
while (len) {
nread = snd_pcm_readi (alsa->handle, src, len);
if (nread <= 0) {
switch (nread) {
case 0:
if (conf.verbose) {
dolog ("Failed to read %ld frames (read zero)\n", len);
}
goto exit;
case -EPIPE:
if (alsa_recover (alsa->handle)) {
alsa_logerr (nread, "Failed to read %ld frames\n", len);
goto exit;
}
if (conf.verbose) {
dolog ("Recovering from capture xrun\n");
}
continue;
case -EAGAIN:
goto exit;
default:
alsa_logerr (
nread,
"Failed to read %ld frames from %p\n",
len,
src
);
goto exit;
}
}
hw->conv (dst, src, nread, &nominal_volume);
src = advance (src, nread << hwshift);
dst += nread;
read_samples += nread;
len -= nread;
}
}
exit:
hw->wpos = (hw->wpos + read_samples) % hw->samples;
return read_samples;
}
static int alsa_read (SWVoiceIn *sw, void *buf, int size)
{
return audio_pcm_sw_read (sw, buf, size);
}
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
return alsa_voice_ctl (alsa->handle, "capture", 0);
case VOICE_DISABLE:
ldebug ("disabling voice\n");
return alsa_voice_ctl (alsa->handle, "capture", 1);
}
return -1;
}
static void *alsa_audio_init (void)
{
return &conf;
}
static void alsa_audio_fini (void *opaque)
{
(void) opaque;
}
static struct audio_option alsa_options[] = {
{"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
"DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
"DAC period size", &conf.period_size_out_overriden, 0},
{"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
"DAC buffer size", &conf.buffer_size_out_overriden, 0},
{"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
"ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
"ADC period size", &conf.period_size_in_overriden, 0},
{"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
"ADC buffer size", &conf.buffer_size_in_overriden, 0},
{"THRESHOLD", AUD_OPT_INT, &conf.threshold,
"(undocumented)", NULL, 0},
{"DAC_DEV", AUD_OPT_STR, &conf.pcm_name_out,
"DAC device name (for instance dmix)", NULL, 0},
{"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
"ADC device name", NULL, 0},
{"VERBOSE", AUD_OPT_BOOL, &conf.verbose,
"Behave in a more verbose way", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
static struct audio_pcm_ops alsa_pcm_ops = {
alsa_init_out,
alsa_fini_out,
alsa_run_out,
alsa_write,
alsa_ctl_out,
alsa_init_in,
alsa_fini_in,
alsa_run_in,
alsa_read,
alsa_ctl_in
};
struct audio_driver alsa_audio_driver = {
INIT_FIELD (name = ) "alsa",
INIT_FIELD (descr = ) "ALSA http://www.alsa-project.org",
INIT_FIELD (options = ) alsa_options,
INIT_FIELD (init = ) alsa_audio_init,
INIT_FIELD (fini = ) alsa_audio_fini,
INIT_FIELD (pcm_ops = ) &alsa_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) INT_MAX,
INIT_FIELD (max_voices_in = ) INT_MAX,
INIT_FIELD (voice_size_out = ) sizeof (ALSAVoiceOut),
INIT_FIELD (voice_size_in = ) sizeof (ALSAVoiceIn)
};

1481
audio/audio.c Normal file

File diff suppressed because it is too large Load Diff

133
audio/audio.h Normal file
View File

@@ -0,0 +1,133 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* 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.
*/
#ifndef QEMU_AUDIO_H
#define QEMU_AUDIO_H
#include "sys-queue.h"
typedef void (*audio_callback_fn_t) (void *opaque, int avail);
typedef enum {
AUD_FMT_U8,
AUD_FMT_S8,
AUD_FMT_U16,
AUD_FMT_S16
} audfmt_e;
typedef struct {
int freq;
int nchannels;
audfmt_e fmt;
} audsettings_t;
typedef struct AudioState AudioState;
typedef struct SWVoiceOut SWVoiceOut;
typedef struct SWVoiceIn SWVoiceIn;
typedef struct QEMUSoundCard {
AudioState *audio;
char *name;
LIST_ENTRY (QEMUSoundCard) entries;
} QEMUSoundCard;
typedef struct QEMUAudioTimeStamp {
uint64_t old_ts;
} QEMUAudioTimeStamp;
void AUD_vlog (const char *cap, const char *fmt, va_list ap);
void AUD_log (const char *cap, const char *fmt, ...)
#ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 2, 3)))
#endif
;
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);
SWVoiceOut *AUD_open_out (
QEMUSoundCard *card,
SWVoiceOut *sw,
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
audsettings_t *settings,
int sw_endian
);
void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
int AUD_write (SWVoiceOut *sw, void *pcm_buf, int size);
int AUD_get_buffer_size_out (SWVoiceOut *sw);
void AUD_set_active_out (SWVoiceOut *sw, int on);
int AUD_is_active_out (SWVoiceOut *sw);
void AUD_init_time_stamp_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, QEMUAudioTimeStamp *ts);
SWVoiceIn *AUD_open_in (
QEMUSoundCard *card,
SWVoiceIn *sw,
const char *name,
void *callback_opaque,
audio_callback_fn_t callback_fn,
audsettings_t *settings,
int sw_endian
);
void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
int AUD_read (SWVoiceIn *sw, void *pcm_buf, int size);
void AUD_set_active_in (SWVoiceIn *sw, int on);
int AUD_is_active_in (SWVoiceIn *sw);
void AUD_init_time_stamp_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
uint64_t AUD_get_elapsed_usec_in (SWVoiceIn *sw, QEMUAudioTimeStamp *ts);
static inline void *advance (void *p, int incr)
{
uint8_t *d = p;
return (d + incr);
}
uint32_t popcount (uint32_t u);
inline uint32_t lsbindex (uint32_t u);
#ifdef __GNUC__
#define audio_MIN(a, b) ( __extension__ ({ \
__typeof (a) ta = a; \
__typeof (b) tb = b; \
((ta)>(tb)?(tb):(ta)); \
}))
#define audio_MAX(a, b) ( __extension__ ({ \
__typeof (a) ta = a; \
__typeof (b) tb = b; \
((ta)<(tb)?(tb):(ta)); \
}))
#else
#define audio_MIN(a, b) ((a)>(b)?(b):(a))
#define audio_MAX(a, b) ((a)<(b)?(b):(a))
#endif
#endif /* audio.h */

268
audio/audio_int.h Normal file
View File

@@ -0,0 +1,268 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* 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.
*/
#ifndef QEMU_AUDIO_INT_H
#define QEMU_AUDIO_INT_H
#ifdef CONFIG_COREAUDIO
#define FLOAT_MIXENG
/* #define RECIPROCAL */
#endif
#include "mixeng.h"
struct audio_pcm_ops;
typedef enum {
AUD_OPT_INT,
AUD_OPT_FMT,
AUD_OPT_STR,
AUD_OPT_BOOL
} audio_option_tag_e;
struct audio_option {
const char *name;
audio_option_tag_e tag;
void *valp;
const char *descr;
int *overridenp;
int overriden;
};
struct audio_callback {
void *opaque;
audio_callback_fn_t fn;
};
struct audio_pcm_info {
int bits;
int sign;
int freq;
int nchannels;
int align;
int shift;
int bytes_per_second;
int swap_endian;
};
typedef struct HWVoiceOut {
int enabled;
int pending_disable;
int valid;
struct audio_pcm_info info;
f_sample *clip;
int rpos;
uint64_t ts_helper;
st_sample_t *mix_buf;
int samples;
LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
struct audio_pcm_ops *pcm_ops;
LIST_ENTRY (HWVoiceOut) entries;
} HWVoiceOut;
typedef struct HWVoiceIn {
int enabled;
struct audio_pcm_info info;
t_sample *conv;
int wpos;
int total_samples_captured;
uint64_t ts_helper;
st_sample_t *conv_buf;
int samples;
LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
struct audio_pcm_ops *pcm_ops;
LIST_ENTRY (HWVoiceIn) entries;
} HWVoiceIn;
struct SWVoiceOut {
struct audio_pcm_info info;
t_sample *conv;
int64_t ratio;
st_sample_t *buf;
void *rate;
int total_hw_samples_mixed;
int active;
int empty;
HWVoiceOut *hw;
char *name;
volume_t vol;
struct audio_callback callback;
LIST_ENTRY (SWVoiceOut) entries;
};
struct SWVoiceIn {
int active;
struct audio_pcm_info info;
int64_t ratio;
void *rate;
int total_hw_samples_acquired;
st_sample_t *buf;
f_sample *clip;
HWVoiceIn *hw;
char *name;
volume_t vol;
struct audio_callback callback;
LIST_ENTRY (SWVoiceIn) entries;
};
struct audio_driver {
const char *name;
const char *descr;
struct audio_option *options;
void *(*init) (void);
void (*fini) (void *);
struct audio_pcm_ops *pcm_ops;
int can_be_default;
int max_voices_out;
int max_voices_in;
int voice_size_out;
int voice_size_in;
};
struct audio_pcm_ops {
int (*init_out)(HWVoiceOut *hw, audsettings_t *as);
void (*fini_out)(HWVoiceOut *hw);
int (*run_out) (HWVoiceOut *hw);
int (*write) (SWVoiceOut *sw, void *buf, int size);
int (*ctl_out) (HWVoiceOut *hw, int cmd, ...);
int (*init_in) (HWVoiceIn *hw, audsettings_t *as);
void (*fini_in) (HWVoiceIn *hw);
int (*run_in) (HWVoiceIn *hw);
int (*read) (SWVoiceIn *sw, void *buf, int size);
int (*ctl_in) (HWVoiceIn *hw, int cmd, ...);
};
struct AudioState {
struct audio_driver *drv;
void *drv_opaque;
QEMUTimer *ts;
LIST_HEAD (card_head, QEMUSoundCard) card_head;
LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;
LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;
int nb_hw_voices_out;
int nb_hw_voices_in;
};
extern struct audio_driver no_audio_driver;
extern struct audio_driver oss_audio_driver;
extern struct audio_driver sdl_audio_driver;
extern struct audio_driver wav_audio_driver;
extern struct audio_driver fmod_audio_driver;
extern struct audio_driver alsa_audio_driver;
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_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int len);
int audio_pcm_hw_get_live_in (HWVoiceIn *hw);
int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int len);
int audio_pcm_hw_get_live_out (HWVoiceOut *hw);
int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live);
int audio_bug (const char *funcname, int cond);
void *audio_calloc (const char *funcname, int nmemb, size_t size);
#define VOICE_ENABLE 1
#define VOICE_DISABLE 2
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
#define GCC_FMT_ATTR(n, m) __attribute__ ((__format__ (__printf__, n, m)))
#else
#define GCC_ATTR /**/
#define INIT_FIELD(f) /**/
#define GCC_FMT_ATTR(n, m)
#endif
static void GCC_ATTR dolog (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
}
#ifdef DEBUG
static void GCC_ATTR ldebug (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
}
#else
#if defined NDEBUG && defined __GNUC__
#define ldebug(...)
#elif defined NDEBUG && defined _MSC_VER
#define ldebug __noop
#else
static void GCC_ATTR ldebug (const char *fmt, ...)
{
(void) fmt;
}
#endif
#endif
#undef GCC_ATTR
#define AUDIO_STRINGIFY_(n) #n
#define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
#if defined _MSC_VER || defined __GNUC__
#define AUDIO_FUNC __FUNCTION__
#else
#define AUDIO_FUNC __FILE__ ":" AUDIO_STRINGIFY (__LINE__)
#endif
#endif /* audio_int.h */

565
audio/audio_template.h Normal file
View File

@@ -0,0 +1,565 @@
/*
* QEMU Audio subsystem header
*
* Copyright (c) 2005 Vassili Karpov (malc)
*
* 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.
*/
#ifdef DAC
#define NAME "playback"
#define HWBUF hw->mix_buf
#define TYPE out
#define HW HWVoiceOut
#define SW SWVoiceOut
#else
#define NAME "capture"
#define TYPE in
#define HW HWVoiceIn
#define SW SWVoiceIn
#define HWBUF hw->conv_buf
#endif
static void glue (audio_init_nb_voices_, TYPE) (
AudioState *s,
struct audio_driver *drv
)
{
int max_voices = glue (drv->max_voices_, TYPE);
int voice_size = glue (drv->voice_size_, TYPE);
if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
if (!max_voices) {
#ifdef DAC
dolog ("Driver `%s' does not support " NAME "\n", drv->name);
#endif
}
else {
dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
drv->name,
glue (s->nb_hw_voices_, TYPE),
max_voices);
}
glue (s->nb_hw_voices_, TYPE) = max_voices;
}
if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) {
dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
drv->name, max_voices);
glue (s->nb_hw_voices_, TYPE) = 0;
}
if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) {
dolog ("drv=`%s' voice_size=%d max_voices=0\n",
drv->name, voice_size);
}
}
static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
{
if (HWBUF) {
qemu_free (HWBUF);
}
HWBUF = NULL;
}
static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
{
HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
if (!HWBUF) {
dolog ("Could not allocate " NAME " buffer (%d samples)\n",
hw->samples);
return -1;
}
return 0;
}
static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
{
if (sw->buf) {
qemu_free (sw->buf);
}
if (sw->rate) {
st_rate_stop (sw->rate);
}
sw->buf = NULL;
sw->rate = NULL;
}
static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
{
int samples;
#ifdef DAC
samples = sw->hw->samples;
#else
samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
#endif
sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t));
if (!sw->buf) {
dolog ("Could not allocate buffer for `%s' (%d samples)\n",
SW_NAME (sw), samples);
return -1;
}
#ifdef DAC
sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
#else
sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
#endif
if (!sw->rate) {
qemu_free (sw->buf);
sw->buf = NULL;
return -1;
}
return 0;
}
static int glue (audio_pcm_sw_init_, TYPE) (
SW *sw,
HW *hw,
const char *name,
audsettings_t *as,
int endian
)
{
int err;
audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian));
sw->hw = hw;
sw->active = 0;
#ifdef DAC
sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
sw->total_hw_samples_mixed = 0;
sw->empty = 1;
#else
sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
#endif
#ifdef DAC
sw->conv = mixeng_conv
#else
sw->clip = mixeng_clip
#endif
[sw->info.nchannels == 2]
[sw->info.sign]
[sw->info.swap_endian]
[sw->info.bits == 16];
sw->name = qemu_strdup (name);
err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
if (err) {
qemu_free (sw->name);
sw->name = NULL;
}
return err;
}
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
{
glue (audio_pcm_sw_free_resources_, TYPE) (sw);
if (sw->name) {
qemu_free (sw->name);
sw->name = NULL;
}
}
static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
{
LIST_INSERT_HEAD (&hw->sw_head, sw, entries);
}
static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
{
LIST_REMOVE (sw, entries);
}
static void glue (audio_pcm_hw_gc_, TYPE) (AudioState *s, HW **hwp)
{
HW *hw = *hwp;
if (!hw->sw_head.lh_first) {
LIST_REMOVE (hw, entries);
glue (s->nb_hw_voices_, TYPE) += 1;
glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
glue (hw->pcm_ops->fini_, TYPE) (hw);
qemu_free (hw);
*hwp = NULL;
}
}
static HW *glue (audio_pcm_hw_find_any_, TYPE) (AudioState *s, HW *hw)
{
return hw ? hw->entries.le_next : s->glue (hw_head_, TYPE).lh_first;
}
static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw)
{
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
if (hw->enabled) {
return hw;
}
}
return NULL;
}
static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
AudioState *s,
HW *hw,
audsettings_t *as
)
{
while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (s, hw))) {
if (audio_pcm_info_eq (&hw->info, as)) {
return hw;
}
}
return NULL;
}
static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
{
HW *hw;
struct audio_driver *drv = s->drv;
if (!glue (s->nb_hw_voices_, TYPE)) {
return NULL;
}
if (audio_bug (AUDIO_FUNC, !drv)) {
dolog ("No host audio driver\n");
return NULL;
}
if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) {
dolog ("Host audio driver without pcm_ops\n");
return NULL;
}
hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
if (!hw) {
dolog ("Can not allocate voice `%s' size %d\n",
drv->name, glue (drv->voice_size_, TYPE));
return NULL;
}
hw->pcm_ops = drv->pcm_ops;
LIST_INIT (&hw->sw_head);
if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
goto err0;
}
if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
dolog ("hw->samples=%d\n", hw->samples);
goto err1;
}
#ifdef DAC
hw->clip = mixeng_clip
#else
hw->conv = mixeng_conv
#endif
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endian]
[hw->info.bits == 16];
if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
goto err1;
}
LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
glue (s->nb_hw_voices_, TYPE) -= 1;
return hw;
err1:
glue (hw->pcm_ops->fini_, TYPE) (hw);
err0:
qemu_free (hw);
return NULL;
}
static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as)
{
HW *hw;
if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
if (hw) {
return hw;
}
}
hw = glue (audio_pcm_hw_find_specific_, TYPE) (s, NULL, as);
if (hw) {
return hw;
}
hw = glue (audio_pcm_hw_add_new_, TYPE) (s, as);
if (hw) {
return hw;
}
return glue (audio_pcm_hw_find_any_, TYPE) (s, NULL);
}
static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
AudioState *s,
const char *sw_name,
audsettings_t *as,
int sw_endian
)
{
SW *sw;
HW *hw;
audsettings_t hw_as;
if (glue (conf.fixed_, TYPE).enabled) {
hw_as = glue (conf.fixed_, TYPE).settings;
}
else {
hw_as = *as;
}
sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
if (!sw) {
dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
sw_name ? sw_name : "unknown", sizeof (*sw));
goto err1;
}
hw = glue (audio_pcm_hw_add_, TYPE) (s, &hw_as);
if (!hw) {
goto err2;
}
glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) {
goto err3;
}
return sw;
err3:
glue (audio_pcm_hw_del_sw_, TYPE) (sw);
glue (audio_pcm_hw_gc_, TYPE) (s, &hw);
err2:
qemu_free (sw);
err1:
return NULL;
}
static void glue (audio_close_, TYPE) (AudioState *s, SW *sw)
{
glue (audio_pcm_sw_fini_, TYPE) (sw);
glue (audio_pcm_hw_del_sw_, TYPE) (sw);
glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw);
qemu_free (sw);
}
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
{
if (sw) {
if (audio_bug (AUDIO_FUNC, !card || !card->audio)) {
dolog ("card=%p card->audio=%p\n",
card, card ? card->audio : NULL);
return;
}
glue (audio_close_, TYPE) (card->audio, sw);
}
}
SW *glue (AUD_open_, TYPE) (
QEMUSoundCard *card,
SW *sw,
const char *name,
void *callback_opaque ,
audio_callback_fn_t callback_fn,
audsettings_t *as,
int sw_endian
)
{
AudioState *s;
#ifdef DAC
int live = 0;
SW *old_sw = NULL;
#endif
ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
name, as->freq, as->nchannels, as->fmt);
if (audio_bug (AUDIO_FUNC,
!card || !card->audio || !name || !callback_fn || !as)) {
dolog ("card=%p card->audio=%p name=%p callback_fn=%p as=%p\n",
card, card ? card->audio : NULL, name, callback_fn, as);
goto fail;
}
s = card->audio;
if (audio_bug (AUDIO_FUNC, audio_validate_settigs (as))) {
audio_print_settings (as);
goto fail;
}
if (audio_bug (AUDIO_FUNC, !s->drv)) {
dolog ("Can not open `%s' (no host audio driver)\n", name);
goto fail;
}
if (sw && audio_pcm_info_eq (&sw->info, as)) {
return sw;
}
#ifdef DAC
if (conf.plive && sw && (!sw->active && !sw->empty)) {
live = sw->total_hw_samples_mixed;
#ifdef DEBUG_PLIVE
dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
dolog ("Old %s freq %d, bits %d, channels %d\n",
SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
dolog ("New %s freq %d, bits %d, channels %d\n",
name,
freq,
(fmt == AUD_FMT_S16 || fmt == AUD_FMT_U16) ? 16 : 8,
nchannels);
#endif
if (live) {
old_sw = sw;
old_sw->callback.fn = NULL;
sw = NULL;
}
}
#endif
if (!glue (conf.fixed_, TYPE).enabled && sw) {
glue (AUD_close_, TYPE) (card, sw);
sw = NULL;
}
if (sw) {
HW *hw = sw->hw;
if (!hw) {
dolog ("Internal logic error voice `%s' has no hardware store\n",
SW_NAME (sw));
goto fail;
}
glue (audio_pcm_sw_fini_, TYPE) (sw);
if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) {
goto fail;
}
}
else {
sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian);
if (!sw) {
dolog ("Failed to create voice `%s'\n", name);
return NULL;
}
}
if (sw) {
sw->vol = nominal_volume;
sw->callback.fn = callback_fn;
sw->callback.opaque = callback_opaque;
#ifdef DAC
if (live) {
int mixed =
(live << old_sw->info.shift)
* old_sw->info.bytes_per_second
/ sw->info.bytes_per_second;
#ifdef DEBUG_PLIVE
dolog ("Silence will be mixed %d\n", mixed);
#endif
sw->total_hw_samples_mixed += mixed;
}
#endif
#ifdef DEBUG_AUDIO
dolog ("%s\n", name);
audio_pcm_print_info ("hw", &sw->hw->info);
audio_pcm_print_info ("sw", &sw->info);
#endif
}
return sw;
fail:
glue (AUD_close_, TYPE) (card, sw);
return NULL;
}
int glue (AUD_is_active_, TYPE) (SW *sw)
{
return sw ? sw->active : 0;
}
void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
{
if (!sw) {
return;
}
ts->old_ts = sw->hw->ts_helper;
}
uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
{
uint64_t delta, cur_ts, old_ts;
if (!sw) {
return 0;
}
cur_ts = sw->hw->ts_helper;
old_ts = ts->old_ts;
/* dolog ("cur %lld old %lld\n", cur_ts, old_ts); */
if (cur_ts >= old_ts) {
delta = cur_ts - old_ts;
}
else {
delta = UINT64_MAX - old_ts + cur_ts;
}
if (!delta) {
return 0;
}
return (delta * sw->hw->info.freq) / 1000000;
}
#undef TYPE
#undef HW
#undef SW
#undef HWBUF
#undef NAME

564
audio/coreaudio.c Normal file
View File

@@ -0,0 +1,564 @@
/*
* QEMU OS X CoreAudio audio driver
*
* Copyright (c) 2005 Mike Kronenberg
*
* 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 <CoreAudio/CoreAudio.h>
#include <string.h> /* strerror */
#include <pthread.h> /* pthread_X */
#include "vl.h"
#define AUDIO_CAP "coreaudio"
#include "audio_int.h"
struct {
int buffer_frames;
int nbuffers;
int isAtexit;
} conf = {
.buffer_frames = 512,
.nbuffers = 4,
.isAtexit = 0
};
typedef struct coreaudioVoiceOut {
HWVoiceOut hw;
pthread_mutex_t mutex;
int isAtexit;
AudioDeviceID outputDeviceID;
UInt32 audioDevicePropertyBufferFrameSize;
AudioStreamBasicDescription outputStreamBasicDescription;
int live;
int decr;
int rpos;
} coreaudioVoiceOut;
static void coreaudio_logstatus (OSStatus status)
{
char *str = "BUG";
switch(status) {
case kAudioHardwareNoError:
str = "kAudioHardwareNoError";
break;
case kAudioHardwareNotRunningError:
str = "kAudioHardwareNotRunningError";
break;
case kAudioHardwareUnspecifiedError:
str = "kAudioHardwareUnspecifiedError";
break;
case kAudioHardwareUnknownPropertyError:
str = "kAudioHardwareUnknownPropertyError";
break;
case kAudioHardwareBadPropertySizeError:
str = "kAudioHardwareBadPropertySizeError";
break;
case kAudioHardwareIllegalOperationError:
str = "kAudioHardwareIllegalOperationError";
break;
case kAudioHardwareBadDeviceError:
str = "kAudioHardwareBadDeviceError";
break;
case kAudioHardwareBadStreamError:
str = "kAudioHardwareBadStreamError";
break;
case kAudioHardwareUnsupportedOperationError:
str = "kAudioHardwareUnsupportedOperationError";
break;
case kAudioDeviceUnsupportedFormatError:
str = "kAudioDeviceUnsupportedFormatError";
break;
case kAudioDevicePermissionsError:
str = "kAudioDevicePermissionsError";
break;
default:
AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
return;
}
AUD_log (AUDIO_CAP, "Reason: %s\n", str);
}
static void GCC_FMT_ATTR (2, 3) coreaudio_logerr (
OSStatus status,
const char *fmt,
...
)
{
va_list ap;
va_start (ap, fmt);
AUD_log (AUDIO_CAP, fmt, ap);
va_end (ap);
coreaudio_logstatus (status);
}
static void GCC_FMT_ATTR (3, 4) coreaudio_logerr2 (
OSStatus status,
const char *typ,
const char *fmt,
...
)
{
va_list ap;
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
coreaudio_logstatus (status);
}
static inline UInt32 isPlaying (AudioDeviceID outputDeviceID)
{
OSStatus status;
UInt32 result = 0;
UInt32 propertySize = sizeof(outputDeviceID);
status = AudioDeviceGetProperty(
outputDeviceID, 0, 0,
kAudioDevicePropertyDeviceIsRunning, &propertySize, &result);
if (status != kAudioHardwareNoError) {
coreaudio_logerr(status,
"Could not determine whether Device is playing\n");
}
return result;
}
static void coreaudio_atexit (void)
{
conf.isAtexit = 1;
}
static int coreaudio_lock (coreaudioVoiceOut *core, const char *fn_name)
{
int err;
err = pthread_mutex_lock (&core->mutex);
if (err) {
dolog ("Could not lock voice for %s\nReason: %s\n",
fn_name, strerror (err));
return -1;
}
return 0;
}
static int coreaudio_unlock (coreaudioVoiceOut *core, const char *fn_name)
{
int err;
err = pthread_mutex_unlock (&core->mutex);
if (err) {
dolog ("Could not unlock voice for %s\nReason: %s\n",
fn_name, strerror (err));
return -1;
}
return 0;
}
static int coreaudio_run_out (HWVoiceOut *hw)
{
int live, decr;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
if (coreaudio_lock (core, "coreaudio_run_out")) {
return 0;
}
live = audio_pcm_hw_get_live_out (hw);
if (core->decr > live) {
ldebug ("core->decr %d live %d core->live %d\n",
core->decr,
live,
core->live);
}
decr = audio_MIN (core->decr, live);
core->decr -= decr;
core->live = live - decr;
hw->rpos = core->rpos;
coreaudio_unlock (core, "coreaudio_run_out");
return decr;
}
/* callback to feed audiooutput buffer */
static OSStatus audioDeviceIOProc(
AudioDeviceID inDevice,
const AudioTimeStamp* inNow,
const AudioBufferList* inInputData,
const AudioTimeStamp* inInputTime,
AudioBufferList* outOutputData,
const AudioTimeStamp* inOutputTime,
void* hwptr)
{
UInt32 frame, frameCount;
float *out = outOutputData->mBuffers[0].mData;
HWVoiceOut *hw = hwptr;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
int rpos, live;
st_sample_t *src;
#ifndef FLOAT_MIXENG
#ifdef RECIPROCAL
const float scale = 1.f / UINT_MAX;
#else
const float scale = UINT_MAX;
#endif
#endif
if (coreaudio_lock (core, "audioDeviceIOProc")) {
inInputTime = 0;
return 0;
}
frameCount = core->audioDevicePropertyBufferFrameSize;
live = core->live;
/* if there are not enough samples, set signal and return */
if (live < frameCount) {
inInputTime = 0;
coreaudio_unlock (core, "audioDeviceIOProc(empty)");
return 0;
}
rpos = core->rpos;
src = hw->mix_buf + rpos;
/* fill buffer */
for (frame = 0; frame < frameCount; frame++) {
#ifdef FLOAT_MIXENG
*out++ = src[frame].l; /* left channel */
*out++ = src[frame].r; /* right channel */
#else
#ifdef RECIPROCAL
*out++ = src[frame].l * scale; /* left channel */
*out++ = src[frame].r * scale; /* right channel */
#else
*out++ = src[frame].l / scale; /* left channel */
*out++ = src[frame].r / scale; /* right channel */
#endif
#endif
}
/* cleanup */
mixeng_clear (src, frameCount);
rpos = (rpos + frameCount) % hw->samples;
core->decr += frameCount;
core->rpos = rpos;
coreaudio_unlock (core, "audioDeviceIOProc");
return 0;
}
static int coreaudio_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
{
OSStatus status;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
UInt32 propertySize;
int err;
int bits = 8;
int endianess = 0;
const char *typ = "playback";
AudioValueRange frameRange;
/* create mutex */
err = pthread_mutex_init(&core->mutex, NULL);
if (err) {
dolog("Could not create mutex\nReason: %s\n", strerror (err));
return -1;
}
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)
);
/* open default output device */
propertySize = sizeof(core->outputDeviceID);
status = AudioHardwareGetProperty(
kAudioHardwarePropertyDefaultOutputDevice,
&propertySize,
&core->outputDeviceID);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get default output Device\n");
return -1;
}
if (core->outputDeviceID == kAudioDeviceUnknown) {
dolog ("Could not initialize %s - Unknown Audiodevice\n", typ);
return -1;
}
/* get minimum and maximum buffer frame sizes */
propertySize = sizeof(frameRange);
status = AudioDeviceGetProperty(
core->outputDeviceID,
0,
0,
kAudioDevicePropertyBufferFrameSizeRange,
&propertySize,
&frameRange);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get device buffer frame range\n");
return -1;
}
if (frameRange.mMinimum > conf.buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMinimum;
dolog ("warning: Upsizing Buffer Frames to %f\n", frameRange.mMinimum);
}
else if (frameRange.mMaximum < conf.buffer_frames) {
core->audioDevicePropertyBufferFrameSize = (UInt32) frameRange.mMaximum;
dolog ("warning: Downsizing Buffer Frames to %f\n", frameRange.mMaximum);
}
else {
core->audioDevicePropertyBufferFrameSize = conf.buffer_frames;
}
/* set Buffer Frame Size */
propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
status = AudioDeviceSetProperty(
core->outputDeviceID,
NULL,
0,
false,
kAudioDevicePropertyBufferFrameSize,
propertySize,
&core->audioDevicePropertyBufferFrameSize);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not set device buffer frame size %ld\n",
core->audioDevicePropertyBufferFrameSize);
return -1;
}
/* get Buffer Frame Size */
propertySize = sizeof(core->audioDevicePropertyBufferFrameSize);
status = AudioDeviceGetProperty(
core->outputDeviceID,
0,
false,
kAudioDevicePropertyBufferFrameSize,
&propertySize,
&core->audioDevicePropertyBufferFrameSize);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get device buffer frame size\n");
return -1;
}
hw->samples = conf.nbuffers * core->audioDevicePropertyBufferFrameSize;
/* get StreamFormat */
propertySize = sizeof(core->outputStreamBasicDescription);
status = AudioDeviceGetProperty(
core->outputDeviceID,
0,
false,
kAudioDevicePropertyStreamFormat,
&propertySize,
&core->outputStreamBasicDescription);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ,
"Could not get Device Stream properties\n");
core->outputDeviceID = kAudioDeviceUnknown;
return -1;
}
/* set Samplerate */
core->outputStreamBasicDescription.mSampleRate = (Float64) as->freq;
propertySize = sizeof(core->outputStreamBasicDescription);
status = AudioDeviceSetProperty(
core->outputDeviceID,
0,
0,
0,
kAudioDevicePropertyStreamFormat,
propertySize,
&core->outputStreamBasicDescription);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not set samplerate %d\n",
as->freq);
core->outputDeviceID = kAudioDeviceUnknown;
return -1;
}
/* set Callback */
status = AudioDeviceAddIOProc(core->outputDeviceID, audioDeviceIOProc, hw);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not set IOProc\n");
core->outputDeviceID = kAudioDeviceUnknown;
return -1;
}
/* start Playback */
if (!isPlaying(core->outputDeviceID)) {
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr2 (status, typ, "Could not start playback\n");
AudioDeviceRemoveIOProc(core->outputDeviceID, audioDeviceIOProc);
core->outputDeviceID = kAudioDeviceUnknown;
return -1;
}
}
return 0;
}
static void coreaudio_fini_out (HWVoiceOut *hw)
{
OSStatus status;
int err;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
if (!conf.isAtexit) {
/* stop playback */
if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not stop playback\n");
}
}
/* remove callback */
status = AudioDeviceRemoveIOProc(core->outputDeviceID,
audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not remove IOProc\n");
}
}
core->outputDeviceID = kAudioDeviceUnknown;
/* destroy mutex */
err = pthread_mutex_destroy(&core->mutex);
if (err) {
dolog("Could not destroy mutex\nReason: %s\n", strerror (err));
}
}
static int coreaudio_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
OSStatus status;
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
switch (cmd) {
case VOICE_ENABLE:
/* start playback */
if (!isPlaying(core->outputDeviceID)) {
status = AudioDeviceStart(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not resume playback\n");
}
}
break;
case VOICE_DISABLE:
/* stop playback */
if (!conf.isAtexit) {
if (isPlaying(core->outputDeviceID)) {
status = AudioDeviceStop(core->outputDeviceID, audioDeviceIOProc);
if (status != kAudioHardwareNoError) {
coreaudio_logerr (status, "Could not pause playback\n");
}
}
}
break;
}
return 0;
}
static void *coreaudio_audio_init (void)
{
atexit(coreaudio_atexit);
return &coreaudio_audio_init;
}
static void coreaudio_audio_fini (void *opaque)
{
(void) opaque;
}
static struct audio_option coreaudio_options[] = {
{"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_frames,
"Size of the buffer in frames", NULL, 0},
{"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers,
"Number of buffers", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
static struct audio_pcm_ops coreaudio_pcm_ops = {
coreaudio_init_out,
coreaudio_fini_out,
coreaudio_run_out,
coreaudio_write,
coreaudio_ctl_out,
NULL,
NULL,
NULL,
NULL,
NULL
};
struct audio_driver coreaudio_audio_driver = {
INIT_FIELD (name = ) "coreaudio",
INIT_FIELD (descr = )
"CoreAudio http://developer.apple.com/audio/coreaudio.html",
INIT_FIELD (options = ) coreaudio_options,
INIT_FIELD (init = ) coreaudio_audio_init,
INIT_FIELD (fini = ) coreaudio_audio_fini,
INIT_FIELD (pcm_ops = ) &coreaudio_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) 1,
INIT_FIELD (max_voices_in = ) 0,
INIT_FIELD (voice_size_out = ) sizeof (coreaudioVoiceOut),
INIT_FIELD (voice_size_in = ) 0
};

282
audio/dsound_template.h Normal file
View File

@@ -0,0 +1,282 @@
/*
* QEMU DirectSound audio driver header
*
* Copyright (c) 2005 Vassili Karpov (malc)
*
* 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.
*/
#ifdef DSBTYPE_IN
#define NAME "capture buffer"
#define TYPE in
#define IFACE IDirectSoundCaptureBuffer
#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
#define FIELD dsound_capture_buffer
#else
#define NAME "playback buffer"
#define TYPE out
#define IFACE IDirectSoundBuffer
#define BUFPTR LPDIRECTSOUNDBUFFER
#define FIELD dsound_buffer
#endif
static int glue (dsound_unlock_, TYPE) (
BUFPTR buf,
LPVOID p1,
LPVOID p2,
DWORD blen1,
DWORD blen2
)
{
HRESULT hr;
hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not unlock " NAME "\n");
return -1;
}
return 0;
}
static int glue (dsound_lock_, TYPE) (
BUFPTR buf,
struct audio_pcm_info *info,
DWORD pos,
DWORD len,
LPVOID *p1p,
LPVOID *p2p,
DWORD *blen1p,
DWORD *blen2p,
int entire
)
{
HRESULT hr;
int i;
LPVOID p1 = NULL, p2 = NULL;
DWORD blen1 = 0, blen2 = 0;
for (i = 0; i < conf.lock_retries; ++i) {
hr = glue (IFACE, _Lock) (
buf,
pos,
len,
&p1,
&blen1,
&p2,
&blen2,
(entire
#ifdef DSBTYPE_IN
? DSCBLOCK_ENTIREBUFFER
#else
? DSBLOCK_ENTIREBUFFER
#endif
: 0)
);
if (FAILED (hr)) {
#ifndef DSBTYPE_IN
if (hr == DSERR_BUFFERLOST) {
if (glue (dsound_restore_, TYPE) (buf)) {
dsound_logerr (hr, "Could not lock " NAME "\n");
goto fail;
}
continue;
}
#endif
dsound_logerr (hr, "Could not lock " NAME "\n");
goto fail;
}
break;
}
if (i == conf.lock_retries) {
dolog ("%d attempts to lock " NAME " failed\n", i);
goto fail;
}
if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
dolog ("DirectSound returned misaligned buffer %ld %ld\n",
blen1, blen2);
glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
goto fail;
}
if (!p1 && blen1) {
dolog ("warning: !p1 && blen1=%ld\n", blen1);
blen1 = 0;
}
if (!p2 && blen2) {
dolog ("warning: !p2 && blen2=%ld\n", blen2);
blen2 = 0;
}
*p1p = p1;
*p2p = p2;
*blen1p = blen1;
*blen2p = blen2;
return 0;
fail:
*p1p = NULL - 1;
*p2p = NULL - 1;
*blen1p = -1;
*blen2p = -1;
return -1;
}
#ifdef DSBTYPE_IN
static void dsound_fini_in (HWVoiceIn *hw)
#else
static void dsound_fini_out (HWVoiceOut *hw)
#endif
{
HRESULT hr;
#ifdef DSBTYPE_IN
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
#else
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
#endif
if (ds->FIELD) {
hr = glue (IFACE, _Stop) (ds->FIELD);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not stop " NAME "\n");
}
hr = glue (IFACE, _Release) (ds->FIELD);
if (FAILED (hr)) {
dsound_logerr (hr, "Could not release " NAME "\n");
}
ds->FIELD = NULL;
}
}
#ifdef DSBTYPE_IN
static int dsound_init_in (HWVoiceIn *hw, audsettings_t *as)
#else
static int dsound_init_out (HWVoiceOut *hw, audsettings_t *as)
#endif
{
int err;
HRESULT hr;
dsound *s = &glob_dsound;
WAVEFORMATEX wfx;
audsettings_t obt_as;
#ifdef DSBTYPE_IN
const char *typ = "ADC";
DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
DSCBUFFERDESC bd;
DSCBCAPS bc;
#else
const char *typ = "DAC";
DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
DSBUFFERDESC bd;
DSBCAPS bc;
#endif
err = waveformat_from_audio_settings (&wfx, as);
if (err) {
return -1;
}
memset (&bd, 0, sizeof (bd));
bd.dwSize = sizeof (bd);
bd.lpwfxFormat = &wfx;
#ifdef DSBTYPE_IN
bd.dwBufferBytes = conf.bufsize_in;
hr = IDirectSoundCapture_CreateCaptureBuffer (
s->dsound_capture,
&bd,
&ds->dsound_capture_buffer,
NULL
);
#else
bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
bd.dwBufferBytes = conf.bufsize_out;
hr = IDirectSound_CreateSoundBuffer (
s->dsound,
&bd,
&ds->dsound_buffer,
NULL
);
#endif
if (FAILED (hr)) {
dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
return -1;
}
hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
if (FAILED (hr)) {
dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
goto fail0;
}
#ifdef DEBUG_DSOUND
dolog (NAME "\n");
print_wave_format (&wfx);
#endif
memset (&bc, 0, sizeof (bc));
bc.dwSize = sizeof (bc);
hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
if (FAILED (hr)) {
dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
goto fail0;
}
err = waveformat_to_audio_settings (&wfx, &obt_as);
if (err) {
goto fail0;
}
ds->first_time = 1;
audio_pcm_init_info (&hw->info, &obt_as, audio_need_to_swap_endian (0));
if (bc.dwBufferBytes & hw->info.align) {
dolog (
"GetCaps returned misaligned buffer size %ld, alignment %d\n",
bc.dwBufferBytes, hw->info.align + 1
);
}
hw->samples = bc.dwBufferBytes >> hw->info.shift;
#ifdef DEBUG_DSOUND
dolog ("caps %ld, desc %ld\n",
bc.dwBufferBytes, bd.dwBufferBytes);
dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
#endif
return 0;
fail0:
glue (dsound_fini_, TYPE) (hw);
return -1;
}
#undef NAME
#undef TYPE
#undef IFACE
#undef BUFPTR
#undef FIELD

1076
audio/dsoundaudio.c Normal file

File diff suppressed because it is too large Load Diff

683
audio/fmodaudio.c Normal file
View File

@@ -0,0 +1,683 @@
/*
* QEMU FMOD audio driver
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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 <fmod.h>
#include <fmod_errors.h>
#include "vl.h"
#define AUDIO_CAP "fmod"
#include "audio_int.h"
typedef struct FMODVoiceOut {
HWVoiceOut hw;
unsigned int old_pos;
FSOUND_SAMPLE *fmod_sample;
int channel;
} FMODVoiceOut;
typedef struct FMODVoiceIn {
HWVoiceIn hw;
FSOUND_SAMPLE *fmod_sample;
} FMODVoiceIn;
static struct {
const char *drvname;
int nb_samples;
int freq;
int nb_channels;
int bufsize;
int threshold;
int broken_adc;
} conf = {
NULL,
2048 * 2,
44100,
2,
0,
0,
0
};
static void GCC_FMT_ATTR (1, 2) fmod_logerr (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n",
FMOD_ErrorString (FSOUND_GetError ()));
}
static void GCC_FMT_ATTR (2, 3) fmod_logerr2 (
const char *typ,
const char *fmt,
...
)
{
va_list ap;
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n",
FMOD_ErrorString (FSOUND_GetError ()));
}
static int fmod_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static void fmod_clear_sample (FMODVoiceOut *fmd)
{
HWVoiceOut *hw = &fmd->hw;
int status;
void *p1 = 0, *p2 = 0;
unsigned int len1 = 0, len2 = 0;
status = FSOUND_Sample_Lock (
fmd->fmod_sample,
0,
hw->samples << hw->info.shift,
&p1,
&p2,
&len1,
&len2
);
if (!status) {
fmod_logerr ("Failed to lock sample\n");
return;
}
if ((len1 & hw->info.align) || (len2 & hw->info.align)) {
dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
len1, len2, hw->info.align + 1);
goto fail;
}
if ((len1 + len2) - (hw->samples << hw->info.shift)) {
dolog ("Lock returned incomplete length %d, %d\n",
len1 + len2, hw->samples << hw->info.shift);
goto fail;
}
audio_pcm_info_clear_buf (&hw->info, p1, hw->samples);
fail:
status = FSOUND_Sample_Unlock (fmd->fmod_sample, p1, p2, len1, len2);
if (!status) {
fmod_logerr ("Failed to unlock sample\n");
}
}
static void fmod_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
{
int src_len1 = dst_len;
int src_len2 = 0;
int pos = hw->rpos + dst_len;
st_sample_t *src1 = hw->mix_buf + hw->rpos;
st_sample_t *src2 = NULL;
if (pos > hw->samples) {
src_len1 = hw->samples - hw->rpos;
src2 = hw->mix_buf;
src_len2 = dst_len - src_len1;
pos = src_len2;
}
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;
}
static int fmod_unlock_sample (FSOUND_SAMPLE *sample, void *p1, void *p2,
unsigned int blen1, unsigned int blen2)
{
int status = FSOUND_Sample_Unlock (sample, p1, p2, blen1, blen2);
if (!status) {
fmod_logerr ("Failed to unlock sample\n");
return -1;
}
return 0;
}
static int fmod_lock_sample (
FSOUND_SAMPLE *sample,
struct audio_pcm_info *info,
int pos,
int len,
void **p1,
void **p2,
unsigned int *blen1,
unsigned int *blen2
)
{
int status;
status = FSOUND_Sample_Lock (
sample,
pos << info->shift,
len << info->shift,
p1,
p2,
blen1,
blen2
);
if (!status) {
fmod_logerr ("Failed to lock sample\n");
return -1;
}
if ((*blen1 & info->align) || (*blen2 & info->align)) {
dolog ("Lock returned misaligned length %d, %d, alignment %d\n",
*blen1, *blen2, info->align + 1);
fmod_unlock_sample (sample, *p1, *p2, *blen1, *blen2);
*p1 = NULL - 1;
*p2 = NULL - 1;
*blen1 = ~0U;
*blen2 = ~0U;
return -1;
}
if (!*p1 && *blen1) {
dolog ("warning: !p1 && blen1=%d\n", *blen1);
*blen1 = 0;
}
if (!p2 && *blen2) {
dolog ("warning: !p2 && blen2=%d\n", *blen2);
*blen2 = 0;
}
return 0;
}
static int fmod_run_out (HWVoiceOut *hw)
{
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
int live, decr;
void *p1 = 0, *p2 = 0;
unsigned int blen1 = 0, blen2 = 0;
unsigned int len1 = 0, len2 = 0;
int nb_live;
live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
if (!live) {
return 0;
}
if (!hw->pending_disable
&& nb_live
&& (conf.threshold && live <= conf.threshold)) {
ldebug ("live=%d nb_live=%d\n", live, nb_live);
return 0;
}
decr = live;
if (fmd->channel >= 0) {
int len = decr;
int old_pos = fmd->old_pos;
int ppos = FSOUND_GetCurrentPosition (fmd->channel);
if (ppos == old_pos || !ppos) {
return 0;
}
if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
len = ppos - old_pos;
}
else {
if ((old_pos > ppos) && ((old_pos + len) > (ppos + hw->samples))) {
len = hw->samples - old_pos + ppos;
}
}
decr = len;
if (audio_bug (AUDIO_FUNC, decr < 0)) {
dolog ("decr=%d live=%d ppos=%d old_pos=%d len=%d\n",
decr, live, ppos, old_pos, len);
return 0;
}
}
if (!decr) {
return 0;
}
if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
fmd->old_pos, decr,
&p1, &p2,
&blen1, &blen2)) {
return 0;
}
len1 = blen1 >> hw->info.shift;
len2 = blen2 >> hw->info.shift;
ldebug ("%p %p %d %d %d %d\n", p1, p2, len1, len2, blen1, blen2);
decr = len1 + len2;
if (p1 && len1) {
fmod_write_sample (hw, p1, len1);
}
if (p2 && len2) {
fmod_write_sample (hw, p2, len2);
}
fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
fmd->old_pos = (fmd->old_pos + decr) % hw->samples;
return decr;
}
static int aud_to_fmodfmt (audfmt_e fmt, int stereo)
{
int mode = FSOUND_LOOP_NORMAL;
switch (fmt) {
case AUD_FMT_S8:
mode |= FSOUND_SIGNED | FSOUND_8BITS;
break;
case AUD_FMT_U8:
mode |= FSOUND_UNSIGNED | FSOUND_8BITS;
break;
case AUD_FMT_S16:
mode |= FSOUND_SIGNED | FSOUND_16BITS;
break;
case AUD_FMT_U16:
mode |= FSOUND_UNSIGNED | FSOUND_16BITS;
break;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
#ifdef DEBUG_FMOD
abort ();
#endif
mode |= FSOUND_8BITS;
}
mode |= stereo ? FSOUND_STEREO : FSOUND_MONO;
return mode;
}
static void fmod_fini_out (HWVoiceOut *hw)
{
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
if (fmd->fmod_sample) {
FSOUND_Sample_Free (fmd->fmod_sample);
fmd->fmod_sample = 0;
if (fmd->channel >= 0) {
FSOUND_StopSound (fmd->channel);
}
}
}
static int fmod_init_out (HWVoiceOut *hw, audsettings_t *as)
{
int bits16, mode, channel;
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
fmd->fmod_sample = FSOUND_Sample_Alloc (
FSOUND_FREE, /* index */
conf.nb_samples, /* length */
mode, /* mode */
as->freq, /* freq */
255, /* volume */
128, /* pan */
255 /* priority */
);
if (!fmd->fmod_sample) {
fmod_logerr2 ("DAC", "Failed to allocate FMOD sample\n");
return -1;
}
channel = FSOUND_PlaySoundEx (FSOUND_FREE, fmd->fmod_sample, 0, 1);
if (channel < 0) {
fmod_logerr2 ("DAC", "Failed to start playing sound\n");
FSOUND_Sample_Free (fmd->fmod_sample);
return -1;
}
fmd->channel = channel;
/* FMOD always operates on little endian frames? */
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
}
static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
int status;
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
switch (cmd) {
case VOICE_ENABLE:
fmod_clear_sample (fmd);
status = FSOUND_SetPaused (fmd->channel, 0);
if (!status) {
fmod_logerr ("Failed to resume channel %d\n", fmd->channel);
}
break;
case VOICE_DISABLE:
status = FSOUND_SetPaused (fmd->channel, 1);
if (!status) {
fmod_logerr ("Failed to pause channel %d\n", fmd->channel);
}
break;
}
return 0;
}
static int fmod_init_in (HWVoiceIn *hw, audsettings_t *as)
{
int bits16, mode;
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
if (conf.broken_adc) {
return -1;
}
mode = aud_to_fmodfmt (as->fmt, as->nchannels == 2 ? 1 : 0);
fmd->fmod_sample = FSOUND_Sample_Alloc (
FSOUND_FREE, /* index */
conf.nb_samples, /* length */
mode, /* mode */
as->freq, /* freq */
255, /* volume */
128, /* pan */
255 /* priority */
);
if (!fmd->fmod_sample) {
fmod_logerr2 ("ADC", "Failed to allocate FMOD sample\n");
return -1;
}
/* FMOD always operates on little endian frames? */
audio_pcm_init_info (&hw->info, as, audio_need_to_swap_endian (0));
bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
}
static void fmod_fini_in (HWVoiceIn *hw)
{
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
if (fmd->fmod_sample) {
FSOUND_Record_Stop ();
FSOUND_Sample_Free (fmd->fmod_sample);
fmd->fmod_sample = 0;
}
}
static int fmod_run_in (HWVoiceIn *hw)
{
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
int hwshift = hw->info.shift;
int live, dead, new_pos, len;
unsigned int blen1 = 0, blen2 = 0;
unsigned int len1, len2;
unsigned int decr;
void *p1, *p2;
live = audio_pcm_hw_get_live_in (hw);
dead = hw->samples - live;
if (!dead) {
return 0;
}
new_pos = FSOUND_Record_GetPosition ();
if (new_pos < 0) {
fmod_logerr ("Could not get recording position\n");
return 0;
}
len = audio_ring_dist (new_pos, hw->wpos, hw->samples);
if (!len) {
return 0;
}
len = audio_MIN (len, dead);
if (fmod_lock_sample (fmd->fmod_sample, &fmd->hw.info,
hw->wpos, len,
&p1, &p2,
&blen1, &blen2)) {
return 0;
}
len1 = blen1 >> hwshift;
len2 = blen2 >> hwshift;
decr = len1 + len2;
if (p1 && blen1) {
hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
}
if (p2 && len2) {
hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
}
fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
hw->wpos = (hw->wpos + decr) % hw->samples;
return decr;
}
static struct {
const char *name;
int type;
} drvtab[] = {
{"none", FSOUND_OUTPUT_NOSOUND},
#ifdef _WIN32
{"winmm", FSOUND_OUTPUT_WINMM},
{"dsound", FSOUND_OUTPUT_DSOUND},
{"a3d", FSOUND_OUTPUT_A3D},
{"asio", FSOUND_OUTPUT_ASIO},
#endif
#ifdef __linux__
{"oss", FSOUND_OUTPUT_OSS},
{"alsa", FSOUND_OUTPUT_ALSA},
{"esd", FSOUND_OUTPUT_ESD},
#endif
#ifdef __APPLE__
{"mac", FSOUND_OUTPUT_MAC},
#endif
#if 0
{"xbox", FSOUND_OUTPUT_XBOX},
{"ps2", FSOUND_OUTPUT_PS2},
{"gcube", FSOUND_OUTPUT_GC},
#endif
{"none-realtime", FSOUND_OUTPUT_NOSOUND_NONREALTIME}
};
static void *fmod_audio_init (void)
{
size_t i;
double ver;
int status;
int output_type = -1;
const char *drv = conf.drvname;
ver = FSOUND_GetVersion ();
if (ver < FMOD_VERSION) {
dolog ("Wrong FMOD version %f, need at least %f\n", ver, FMOD_VERSION);
return NULL;
}
#ifdef __linux__
if (ver < 3.75) {
dolog ("FMOD before 3.75 has bug preventing ADC from working\n"
"ADC will be disabled.\n");
conf.broken_adc = 1;
}
#endif
if (drv) {
int found = 0;
for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
if (!strcmp (drv, drvtab[i].name)) {
output_type = drvtab[i].type;
found = 1;
break;
}
}
if (!found) {
dolog ("Unknown FMOD driver `%s'\n", drv);
dolog ("Valid drivers:\n");
for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
dolog (" %s\n", drvtab[i].name);
}
}
}
if (output_type != -1) {
status = FSOUND_SetOutput (output_type);
if (!status) {
fmod_logerr ("FSOUND_SetOutput(%d) failed\n", output_type);
return NULL;
}
}
if (conf.bufsize) {
status = FSOUND_SetBufferSize (conf.bufsize);
if (!status) {
fmod_logerr ("FSOUND_SetBufferSize (%d) failed\n", conf.bufsize);
}
}
status = FSOUND_Init (conf.freq, conf.nb_channels, 0);
if (!status) {
fmod_logerr ("FSOUND_Init failed\n");
return NULL;
}
return &conf;
}
static int fmod_read (SWVoiceIn *sw, void *buf, int size)
{
return audio_pcm_sw_read (sw, buf, size);
}
static int fmod_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
int status;
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
switch (cmd) {
case VOICE_ENABLE:
status = FSOUND_Record_StartSample (fmd->fmod_sample, 1);
if (!status) {
fmod_logerr ("Failed to start recording\n");
}
break;
case VOICE_DISABLE:
status = FSOUND_Record_Stop ();
if (!status) {
fmod_logerr ("Failed to stop recording\n");
}
break;
}
return 0;
}
static void fmod_audio_fini (void *opaque)
{
(void) opaque;
FSOUND_Close ();
}
static struct audio_option fmod_options[] = {
{"DRV", AUD_OPT_STR, &conf.drvname,
"FMOD driver", NULL, 0},
{"FREQ", AUD_OPT_INT, &conf.freq,
"Default frequency", NULL, 0},
{"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
"Buffer size in samples", NULL, 0},
{"CHANNELS", AUD_OPT_INT, &conf.nb_channels,
"Number of default channels (1 - mono, 2 - stereo)", NULL, 0},
{"BUFSIZE", AUD_OPT_INT, &conf.bufsize,
"(undocumented)", NULL, 0},
#if 0
{"THRESHOLD", AUD_OPT_INT, &conf.threshold,
"(undocumented)"},
#endif
{NULL, 0, NULL, NULL, NULL, 0}
};
static struct audio_pcm_ops fmod_pcm_ops = {
fmod_init_out,
fmod_fini_out,
fmod_run_out,
fmod_write,
fmod_ctl_out,
fmod_init_in,
fmod_fini_in,
fmod_run_in,
fmod_read,
fmod_ctl_in
};
struct audio_driver fmod_audio_driver = {
INIT_FIELD (name = ) "fmod",
INIT_FIELD (descr = ) "FMOD 3.xx http://www.fmod.org",
INIT_FIELD (options = ) fmod_options,
INIT_FIELD (init = ) fmod_audio_init,
INIT_FIELD (fini = ) fmod_audio_fini,
INIT_FIELD (pcm_ops = ) &fmod_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) INT_MAX,
INIT_FIELD (max_voices_in = ) INT_MAX,
INIT_FIELD (voice_size_out = ) sizeof (FMODVoiceOut),
INIT_FIELD (voice_size_in = ) sizeof (FMODVoiceIn)
};

277
audio/mixeng.c Normal file
View File

@@ -0,0 +1,277 @@
/*
* QEMU Mixing engine
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
* Copyright (c) 1998 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"
#define AUDIO_CAP "mixeng"
#include "audio_int.h"
#define NOVOL
/* 8 bit */
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
/* Signed 8 bit */
#define IN_T int8_t
#define IN_MIN SCHAR_MIN
#define IN_MAX SCHAR_MAX
#define SIGNED
#define SHIFT 8
#include "mixeng_template.h"
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef SHIFT
/* Unsigned 8 bit */
#define IN_T uint8_t
#define IN_MIN 0
#define IN_MAX UCHAR_MAX
#define SHIFT 8
#include "mixeng_template.h"
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef SHIFT
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
/* Signed 16 bit */
#define IN_T int16_t
#define IN_MIN SHRT_MIN
#define IN_MAX SHRT_MAX
#define SIGNED
#define SHIFT 16
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap16 (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef SHIFT
#define IN_T uint16_t
#define IN_MIN 0
#define IN_MAX USHRT_MAX
#define SHIFT 16
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap16 (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#undef IN_MAX
#undef IN_MIN
#undef IN_T
#undef SHIFT
t_sample *mixeng_conv[2][2][2][2] = {
{
{
{
conv_natural_uint8_t_to_mono,
conv_natural_uint16_t_to_mono
},
{
conv_natural_uint8_t_to_mono,
conv_swap_uint16_t_to_mono
}
},
{
{
conv_natural_int8_t_to_mono,
conv_natural_int16_t_to_mono
},
{
conv_natural_int8_t_to_mono,
conv_swap_int16_t_to_mono
}
}
},
{
{
{
conv_natural_uint8_t_to_stereo,
conv_natural_uint16_t_to_stereo
},
{
conv_natural_uint8_t_to_stereo,
conv_swap_uint16_t_to_stereo
}
},
{
{
conv_natural_int8_t_to_stereo,
conv_natural_int16_t_to_stereo
},
{
conv_natural_int8_t_to_stereo,
conv_swap_int16_t_to_stereo
}
}
}
};
f_sample *mixeng_clip[2][2][2][2] = {
{
{
{
clip_natural_uint8_t_from_mono,
clip_natural_uint16_t_from_mono
},
{
clip_natural_uint8_t_from_mono,
clip_swap_uint16_t_from_mono
}
},
{
{
clip_natural_int8_t_from_mono,
clip_natural_int16_t_from_mono
},
{
clip_natural_int8_t_from_mono,
clip_swap_int16_t_from_mono
}
}
},
{
{
{
clip_natural_uint8_t_from_stereo,
clip_natural_uint16_t_from_stereo
},
{
clip_natural_uint8_t_from_stereo,
clip_swap_uint16_t_from_stereo
}
},
{
{
clip_natural_int8_t_from_stereo,
clip_natural_int16_t_from_stereo
},
{
clip_natural_int8_t_from_stereo,
clip_swap_int16_t_from_stereo
}
}
}
};
/*
* August 21, 1998
* Copyright 1998 Fabrice Bellard.
*
* [Rewrote completly the code of Lance Norskog And Sundry
* Contributors with a more efficient algorithm.]
*
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice must be maintained.
* Lance Norskog And Sundry Contributors are not responsible for
* the consequences of using this software.
*/
/*
* Sound Tools rate change effect file.
*/
/*
* Linear Interpolation.
*
* The use of fractional increment allows us to use no buffer. It
* avoid the problems at the end of the buffer we had with the old
* method which stored a possibly big buffer of size
* lcm(in_rate,out_rate).
*
* Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
* the input & output frequencies are equal, a delay of one sample is
* introduced. Limited to processing 32-bit count worth of samples.
*
* 1 << FRAC_BITS evaluating to zero in several places. Changed with
* an (unsigned long) cast to make it safe. MarkMLl 2/1/99
*/
/* Private data */
struct rate {
uint64_t opos;
uint64_t opos_inc;
uint32_t ipos; /* position in the input stream (integer) */
st_sample_t ilast; /* last sample in the input stream */
};
/*
* Prepare processing.
*/
void *st_rate_start (int inrate, int outrate)
{
struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
if (!rate) {
dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
return NULL;
}
rate->opos = 0;
/* increment */
rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
rate->ipos = 0;
rate->ilast.l = 0;
rate->ilast.r = 0;
return rate;
}
#define NAME st_rate_flow_mix
#define OP(a, b) a += b
#include "rate_template.h"
#define NAME st_rate_flow
#define OP(a, b) a = b
#include "rate_template.h"
void st_rate_stop (void *opaque)
{
qemu_free (opaque);
}
void mixeng_clear (st_sample_t *buf, int len)
{
memset (buf, 0, len * sizeof (st_sample_t));
}

51
audio/mixeng.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* QEMU Mixing engine header
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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.
*/
#ifndef QEMU_MIXENG_H
#define QEMU_MIXENG_H
#ifdef FLOAT_MIXENG
typedef float real_t;
typedef struct { int mute; real_t r; real_t l; } volume_t;
typedef struct { real_t l; real_t r; } st_sample_t;
#else
typedef struct { int mute; int64_t r; int64_t l; } volume_t;
typedef struct { int64_t l; int64_t r; } st_sample_t;
#endif
typedef void (t_sample) (st_sample_t *dst, const void *src,
int samples, volume_t *vol);
typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
extern t_sample *mixeng_conv[2][2][2][2];
extern f_sample *mixeng_clip[2][2][2][2];
void *st_rate_start (int inrate, int outrate);
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp);
void st_rate_flow_mix (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp);
void st_rate_stop (void *opaque);
void mixeng_clear (st_sample_t *buf, int len);
#endif /* mixeng.h */

177
audio/mixeng_template.h Normal file
View File

@@ -0,0 +1,177 @@
/*
* QEMU Mixing engine
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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.
*/
/*
* Tusen tack till Mike Nordell
* dec++'ified by Dscho
*/
#ifndef SIGNED
#define HALF (IN_MAX >> 1)
#endif
#ifdef NOVOL
#define VOL(a, b) a
#else
#ifdef FLOAT_MIXENG
#define VOL(a, b) ((a) * (b))
#else
#define VOL(a, b) ((a) * (b)) >> 32
#endif
#endif
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
#ifdef FLOAT_MIXENG
static real_t inline glue (conv_, ET) (IN_T v)
{
IN_T nv = ENDIAN_CONVERT (v);
#ifdef RECIPROCAL
#ifdef SIGNED
return nv * (1.f / (real_t) (IN_MAX - IN_MIN));
#else
return (nv - HALF) * (1.f / (real_t) IN_MAX);
#endif
#else /* !RECIPROCAL */
#ifdef SIGNED
return nv / (real_t) (IN_MAX - IN_MIN);
#else
return (nv - HALF) / (real_t) IN_MAX;
#endif
#endif
}
static IN_T inline glue (clip_, ET) (real_t v)
{
if (v >= 0.5) {
return IN_MAX;
}
else if (v < -0.5) {
return IN_MIN;
}
#ifdef SIGNED
return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN)));
#else
return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
#endif
}
#else /* !FLOAT_MIXENG */
static inline int64_t glue (conv_, ET) (IN_T v)
{
IN_T nv = ENDIAN_CONVERT (v);
#ifdef SIGNED
return ((int64_t) nv) << (32 - SHIFT);
#else
return ((int64_t) nv - HALF) << (32 - SHIFT);
#endif
}
static inline IN_T glue (clip_, ET) (int64_t v)
{
if (v >= 0x7f000000) {
return IN_MAX;
}
else if (v < -2147483648LL) {
return IN_MIN;
}
#ifdef SIGNED
return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT)));
#else
return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF));
#endif
}
#endif
static void glue (glue (conv_, ET), _to_stereo)
(st_sample_t *dst, const void *src, int samples, volume_t *vol)
{
st_sample_t *out = dst;
IN_T *in = (IN_T *) src;
#ifndef NOVOL
if (vol->mute) {
mixeng_clear (dst, samples);
return;
}
#else
(void) vol;
#endif
while (samples--) {
out->l = VOL (glue (conv_, ET) (*in++), vol->l);
out->r = VOL (glue (conv_, ET) (*in++), vol->r);
out += 1;
}
}
static void glue (glue (conv_, ET), _to_mono)
(st_sample_t *dst, const void *src, int samples, volume_t *vol)
{
st_sample_t *out = dst;
IN_T *in = (IN_T *) src;
#ifndef NOVOL
if (vol->mute) {
mixeng_clear (dst, samples);
return;
}
#else
(void) vol;
#endif
while (samples--) {
out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
out->r = out->l;
out += 1;
in += 1;
}
}
static void glue (glue (clip_, ET), _from_stereo)
(void *dst, const st_sample_t *src, int samples)
{
const st_sample_t *in = src;
IN_T *out = (IN_T *) dst;
while (samples--) {
*out++ = glue (clip_, ET) (in->l);
*out++ = glue (clip_, ET) (in->r);
in += 1;
}
}
static void glue (glue (clip_, ET), _from_mono)
(void *dst, const st_sample_t *src, int samples)
{
const st_sample_t *in = src;
IN_T *out = (IN_T *) dst;
while (samples--) {
*out++ = glue (clip_, ET) (in->l + in->r);
in += 1;
}
}
#undef ET
#undef HALF
#undef VOL

170
audio/noaudio.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* QEMU Timer based audio emulation
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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"
#define AUDIO_CAP "noaudio"
#include "audio_int.h"
typedef struct NoVoiceOut {
HWVoiceOut hw;
int64_t old_ticks;
} NoVoiceOut;
typedef struct NoVoiceIn {
HWVoiceIn hw;
int64_t old_ticks;
} NoVoiceIn;
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;
}
live = audio_pcm_hw_get_live_out (&no->hw);
if (!live) {
return 0;
}
no->old_ticks = now;
decr = audio_MIN (live, samples);
hw->rpos = (hw->rpos + decr) % hw->samples;
return decr;
}
static int no_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int no_init_out (HWVoiceOut *hw, audsettings_t *as)
{
audio_pcm_init_info (&hw->info, as, 0);
hw->samples = 1024;
return 0;
}
static void no_fini_out (HWVoiceOut *hw)
{
(void) hw;
}
static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static int no_init_in (HWVoiceIn *hw, audsettings_t *as)
{
audio_pcm_init_info (&hw->info, as, 0);
hw->samples = 1024;
return 0;
}
static void no_fini_in (HWVoiceIn *hw)
{
(void) 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;
bytes = audio_MIN (bytes, INT_MAX);
samples = bytes >> hw->info.shift;
samples = audio_MIN (samples, dead);
return samples;
}
static int no_read (SWVoiceIn *sw, void *buf, int size)
{
int samples = size >> sw->info.shift;
int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
int to_clear = audio_MIN (samples, total);
audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
return to_clear;
}
static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static void *no_audio_init (void)
{
return &no_audio_init;
}
static void no_audio_fini (void *opaque)
{
(void) opaque;
}
static struct audio_pcm_ops no_pcm_ops = {
no_init_out,
no_fini_out,
no_run_out,
no_write,
no_ctl_out,
no_init_in,
no_fini_in,
no_run_in,
no_read,
no_ctl_in
};
struct audio_driver no_audio_driver = {
INIT_FIELD (name = ) "none",
INIT_FIELD (descr = ) "Timer based audio emulation",
INIT_FIELD (options = ) NULL,
INIT_FIELD (init = ) no_audio_init,
INIT_FIELD (fini = ) no_audio_fini,
INIT_FIELD (pcm_ops = ) &no_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) INT_MAX,
INIT_FIELD (max_voices_in = ) INT_MAX,
INIT_FIELD (voice_size_out = ) sizeof (NoVoiceOut),
INIT_FIELD (voice_size_in = ) sizeof (NoVoiceIn)
};

762
audio/ossaudio.c Normal file
View File

@@ -0,0 +1,762 @@
/*
* QEMU OSS audio driver
*
* Copyright (c) 2003-2005 Vassili Karpov (malc)
*
* 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 <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include "vl.h"
#define AUDIO_CAP "oss"
#include "audio_int.h"
typedef struct OSSVoiceOut {
HWVoiceOut hw;
void *pcm_buf;
int fd;
int nfrags;
int fragsize;
int mmapped;
int old_optr;
} OSSVoiceOut;
typedef struct OSSVoiceIn {
HWVoiceIn hw;
void *pcm_buf;
int fd;
int nfrags;
int fragsize;
int old_optr;
} OSSVoiceIn;
static struct {
int try_mmap;
int nfrags;
int fragsize;
const char *devpath_out;
const char *devpath_in;
} conf = {
.try_mmap = 0,
.nfrags = 4,
.fragsize = 4096,
.devpath_out = "/dev/dsp",
.devpath_in = "/dev/dsp"
};
struct oss_params {
int freq;
audfmt_e fmt;
int nchannels;
int nfrags;
int fragsize;
};
static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
}
static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
int err,
const char *typ,
const char *fmt,
...
)
{
va_list ap;
AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
}
static void oss_anal_close (int *fdp)
{
int err = close (*fdp);
if (err) {
oss_logerr (errno, "Failed to close file(fd=%d)\n", *fdp);
}
*fdp = -1;
}
static int oss_write (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int aud_to_ossfmt (audfmt_e fmt)
{
switch (fmt) {
case AUD_FMT_S8:
return AFMT_S8;
case AUD_FMT_U8:
return AFMT_U8;
case AUD_FMT_S16:
return AFMT_S16_LE;
case AUD_FMT_U16:
return AFMT_U16_LE;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
#ifdef DEBUG_AUDIO
abort ();
#endif
return AFMT_U8;
}
}
static int oss_to_audfmt (int ossfmt, audfmt_e *fmt, int *endianness)
{
switch (ossfmt) {
case AFMT_S8:
*endianness =0;
*fmt = AUD_FMT_S8;
break;
case AFMT_U8:
*endianness = 0;
*fmt = AUD_FMT_U8;
break;
case AFMT_S16_LE:
*endianness = 0;
*fmt = AUD_FMT_S16;
break;
case AFMT_U16_LE:
*endianness = 0;
*fmt = AUD_FMT_U16;
break;
case AFMT_S16_BE:
*endianness = 1;
*fmt = AUD_FMT_S16;
break;
case AFMT_U16_BE:
*endianness = 1;
*fmt = AUD_FMT_U16;
break;
default:
dolog ("Unrecognized audio format %d\n", ossfmt);
return -1;
}
return 0;
}
#if defined DEBUG_MISMATCHES || defined DEBUG
static void oss_dump_info (struct oss_params *req, struct oss_params *obt)
{
dolog ("parameter | requested value | obtained value\n");
dolog ("format | %10d | %10d\n", req->fmt, obt->fmt);
dolog ("channels | %10d | %10d\n",
req->nchannels, obt->nchannels);
dolog ("frequency | %10d | %10d\n", req->freq, obt->freq);
dolog ("nfrags | %10d | %10d\n", req->nfrags, obt->nfrags);
dolog ("fragsize | %10d | %10d\n",
req->fragsize, obt->fragsize);
}
#endif
static int oss_open (int in, struct oss_params *req,
struct oss_params *obt, int *pfd)
{
int fd;
int mmmmssss;
audio_buf_info abinfo;
int fmt, freq, nchannels;
const char *dspname = in ? conf.devpath_in : conf.devpath_out;
const char *typ = in ? "ADC" : "DAC";
fd = open (dspname, (in ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
if (-1 == fd) {
oss_logerr2 (errno, typ, "Failed to open `%s'\n", dspname);
return -1;
}
freq = req->freq;
nchannels = req->nchannels;
fmt = req->fmt;
if (ioctl (fd, SNDCTL_DSP_SAMPLESIZE, &fmt)) {
oss_logerr2 (errno, typ, "Failed to set sample size %d\n", req->fmt);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &nchannels)) {
oss_logerr2 (errno, typ, "Failed to set number of channels %d\n",
req->nchannels);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_SPEED, &freq)) {
oss_logerr2 (errno, typ, "Failed to set frequency %d\n", req->freq);
goto err;
}
if (ioctl (fd, SNDCTL_DSP_NONBLOCK)) {
oss_logerr2 (errno, typ, "Failed to set non-blocking mode\n");
goto err;
}
mmmmssss = (req->nfrags << 16) | lsbindex (req->fragsize);
if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)) {
oss_logerr2 (errno, typ, "Failed to set buffer length (%d, %d)\n",
req->nfrags, req->fragsize);
goto err;
}
if (ioctl (fd, in ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) {
oss_logerr2 (errno, typ, "Failed to get buffer length\n");
goto err;
}
obt->fmt = fmt;
obt->nchannels = nchannels;
obt->freq = freq;
obt->nfrags = abinfo.fragstotal;
obt->fragsize = abinfo.fragsize;
*pfd = fd;
#ifdef DEBUG_MISMATCHES
if ((req->fmt != obt->fmt) ||
(req->nchannels != obt->nchannels) ||
(req->freq != obt->freq) ||
(req->fragsize != obt->fragsize) ||
(req->nfrags != obt->nfrags)) {
dolog ("Audio parameters mismatch\n");
oss_dump_info (req, obt);
}
#endif
#ifdef DEBUG
oss_dump_info (req, obt);
#endif
return 0;
err:
oss_anal_close (&fd);
return -1;
}
static int oss_run_out (HWVoiceOut *hw)
{
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
int err, rpos, live, decr;
int samples;
uint8_t *dst;
st_sample_t *src;
struct audio_buf_info abinfo;
struct count_info cntinfo;
int bufsize;
live = audio_pcm_hw_get_live_out (hw);
if (!live) {
return 0;
}
bufsize = hw->samples << hw->info.shift;
if (oss->mmapped) {
int bytes;
err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, &cntinfo);
if (err < 0) {
oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
return 0;
}
if (cntinfo.ptr == oss->old_optr) {
if (abs (hw->samples - live) < 64) {
dolog ("warning: Overrun\n");
}
return 0;
}
if (cntinfo.ptr > oss->old_optr) {
bytes = cntinfo.ptr - oss->old_optr;
}
else {
bytes = bufsize + cntinfo.ptr - oss->old_optr;
}
decr = audio_MIN (bytes >> hw->info.shift, live);
}
else {
err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, &abinfo);
if (err < 0) {
oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
return 0;
}
if (abinfo.bytes < 0 || abinfo.bytes > bufsize) {
ldebug ("warning: Invalid available size, size=%d bufsize=%d\n",
abinfo.bytes, bufsize);
return 0;
}
decr = audio_MIN (abinfo.bytes >> hw->info.shift, live);
if (!decr) {
return 0;
}
}
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
src = hw->mix_buf + rpos;
dst = advance (oss->pcm_buf, rpos << hw->info.shift);
hw->clip (dst, src, convert_samples);
if (!oss->mmapped) {
int written;
written = write (oss->fd, dst, convert_samples << hw->info.shift);
/* XXX: follow errno recommendations ? */
if (written == -1) {
oss_logerr (
errno,
"Failed to write %d bytes of audio data from %p\n",
convert_samples << hw->info.shift,
dst
);
continue;
}
if (written != convert_samples << hw->info.shift) {
int wsamples = written >> hw->info.shift;
int wbytes = wsamples << hw->info.shift;
if (wbytes != written) {
dolog ("warning: Misaligned write %d (requested %d), "
"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;
}
if (oss->mmapped) {
oss->old_optr = cntinfo.ptr;
}
hw->rpos = rpos;
return decr;
}
static void oss_fini_out (HWVoiceOut *hw)
{
int err;
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
ldebug ("oss_fini\n");
oss_anal_close (&oss->fd);
if (oss->pcm_buf) {
if (oss->mmapped) {
err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
if (err) {
oss_logerr (errno, "Failed to unmap buffer %p, size %d\n",
oss->pcm_buf, hw->samples << hw->info.shift);
}
}
else {
qemu_free (oss->pcm_buf);
}
oss->pcm_buf = NULL;
}
}
static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
{
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
struct oss_params req, obt;
int endianness;
int err;
int fd;
audfmt_e effective_fmt;
audsettings_t obt_as;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.fragsize = conf.fragsize;
req.nfrags = conf.nfrags;
if (oss_open (0, &req, &obt, &fd)) {
return -1;
}
err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
if (err) {
oss_anal_close (&fd);
return -1;
}
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
if (obt.nfrags * obt.fragsize & hw->info.align) {
dolog ("warning: Misaligned DAC buffer, size %d, alignment %d\n",
obt.nfrags * obt.fragsize, hw->info.align + 1);
}
hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
oss->mmapped = 0;
if (conf.try_mmap) {
oss->pcm_buf = mmap (
0,
hw->samples << hw->info.shift,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
0
);
if (oss->pcm_buf == MAP_FAILED) {
oss_logerr (errno, "Failed to map %d bytes of DAC\n",
hw->samples << hw->info.shift);
} else {
int err;
int trig = 0;
if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
}
else {
trig = PCM_ENABLE_OUTPUT;
if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
oss_logerr (
errno,
"SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
);
}
else {
oss->mmapped = 1;
}
}
if (!oss->mmapped) {
err = munmap (oss->pcm_buf, hw->samples << hw->info.shift);
if (err) {
oss_logerr (errno, "Failed to unmap buffer %p size %d\n",
oss->pcm_buf, hw->samples << hw->info.shift);
}
}
}
}
if (!oss->mmapped) {
oss->pcm_buf = audio_calloc (
AUDIO_FUNC,
hw->samples,
1 << hw->info.shift
);
if (!oss->pcm_buf) {
dolog (
"Could not allocate DAC buffer (%d samples, each %d bytes)\n",
hw->samples,
1 << hw->info.shift
);
oss_anal_close (&fd);
return -1;
}
}
oss->fd = fd;
return 0;
}
static int oss_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
int trig;
OSSVoiceOut *oss = (OSSVoiceOut *) hw;
if (!oss->mmapped) {
return 0;
}
switch (cmd) {
case VOICE_ENABLE:
ldebug ("enabling voice\n");
audio_pcm_info_clear_buf (&hw->info, oss->pcm_buf, hw->samples);
trig = PCM_ENABLE_OUTPUT;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
oss_logerr (
errno,
"SNDCTL_DSP_SETTRIGGER PCM_ENABLE_OUTPUT failed\n"
);
return -1;
}
break;
case VOICE_DISABLE:
ldebug ("disabling voice\n");
trig = 0;
if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) {
oss_logerr (errno, "SNDCTL_DSP_SETTRIGGER 0 failed\n");
return -1;
}
break;
}
return 0;
}
static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
struct oss_params req, obt;
int endianness;
int err;
int fd;
audfmt_e effective_fmt;
audsettings_t obt_as;
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.fragsize = conf.fragsize;
req.nfrags = conf.nfrags;
if (oss_open (1, &req, &obt, &fd)) {
return -1;
}
err = oss_to_audfmt (obt.fmt, &effective_fmt, &endianness);
if (err) {
oss_anal_close (&fd);
return -1;
}
obt_as.freq = obt.freq;
obt_as.nchannels = obt.nchannels;
obt_as.fmt = effective_fmt;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianness)
);
oss->nfrags = obt.nfrags;
oss->fragsize = obt.fragsize;
if (obt.nfrags * obt.fragsize & hw->info.align) {
dolog ("warning: Misaligned ADC buffer, size %d, alignment %d\n",
obt.nfrags * obt.fragsize, hw->info.align + 1);
}
hw->samples = (obt.nfrags * obt.fragsize) >> hw->info.shift;
oss->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
if (!oss->pcm_buf) {
dolog ("Could not allocate ADC buffer (%d samples, each %d bytes)\n",
hw->samples, 1 << hw->info.shift);
oss_anal_close (&fd);
return -1;
}
oss->fd = fd;
return 0;
}
static void oss_fini_in (HWVoiceIn *hw)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
oss_anal_close (&oss->fd);
if (oss->pcm_buf) {
qemu_free (oss->pcm_buf);
oss->pcm_buf = NULL;
}
}
static int oss_run_in (HWVoiceIn *hw)
{
OSSVoiceIn *oss = (OSSVoiceIn *) hw;
int hwshift = hw->info.shift;
int i;
int live = audio_pcm_hw_get_live_in (hw);
int dead = hw->samples - live;
size_t read_samples = 0;
struct {
int add;
int len;
} bufs[2] = {
{ hw->wpos, 0 },
{ 0, 0 }
};
if (!dead) {
return 0;
}
if (hw->wpos + dead > hw->samples) {
bufs[0].len = (hw->samples - hw->wpos) << hwshift;
bufs[1].len = (dead - (hw->samples - hw->wpos)) << hwshift;
}
else {
bufs[0].len = dead << hwshift;
}
for (i = 0; i < 2; ++i) {
ssize_t nread;
if (bufs[i].len) {
void *p = advance (oss->pcm_buf, bufs[i].add << hwshift);
nread = read (oss->fd, p, bufs[i].len);
if (nread > 0) {
if (nread & hw->info.align) {
dolog ("warning: Misaligned read %zd (requested %d), "
"alignment %d\n", nread, bufs[i].add << hwshift,
hw->info.align + 1);
}
read_samples += nread >> hwshift;
hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
&nominal_volume);
}
if (bufs[i].len - nread) {
if (nread == -1) {
switch (errno) {
case EINTR:
case EAGAIN:
break;
default:
oss_logerr (
errno,
"Failed to read %d bytes of audio (to %p)\n",
bufs[i].len, p
);
break;
}
}
break;
}
}
}
hw->wpos = (hw->wpos + read_samples) % hw->samples;
return read_samples;
}
static int oss_read (SWVoiceIn *sw, void *buf, int size)
{
return audio_pcm_sw_read (sw, buf, size);
}
static int oss_ctl_in (HWVoiceIn *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static void *oss_audio_init (void)
{
return &conf;
}
static void oss_audio_fini (void *opaque)
{
(void) opaque;
}
static struct audio_option oss_options[] = {
{"FRAGSIZE", AUD_OPT_INT, &conf.fragsize,
"Fragment size in bytes", NULL, 0},
{"NFRAGS", AUD_OPT_INT, &conf.nfrags,
"Number of fragments", NULL, 0},
{"MMAP", AUD_OPT_BOOL, &conf.try_mmap,
"Try using memory mapped access", NULL, 0},
{"DAC_DEV", AUD_OPT_STR, &conf.devpath_out,
"Path to DAC device", NULL, 0},
{"ADC_DEV", AUD_OPT_STR, &conf.devpath_in,
"Path to ADC device", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
static struct audio_pcm_ops oss_pcm_ops = {
oss_init_out,
oss_fini_out,
oss_run_out,
oss_write,
oss_ctl_out,
oss_init_in,
oss_fini_in,
oss_run_in,
oss_read,
oss_ctl_in
};
struct audio_driver oss_audio_driver = {
INIT_FIELD (name = ) "oss",
INIT_FIELD (descr = ) "OSS http://www.opensound.com",
INIT_FIELD (options = ) oss_options,
INIT_FIELD (init = ) oss_audio_init,
INIT_FIELD (fini = ) oss_audio_fini,
INIT_FIELD (pcm_ops = ) &oss_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) INT_MAX,
INIT_FIELD (max_voices_in = ) INT_MAX,
INIT_FIELD (voice_size_out = ) sizeof (OSSVoiceOut),
INIT_FIELD (voice_size_in = ) sizeof (OSSVoiceIn)
};

111
audio/rate_template.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* QEMU Mixing engine
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
* Copyright (c) 1998 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.
*/
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
void NAME (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
int *isamp, int *osamp)
{
struct rate *rate = opaque;
st_sample_t *istart, *iend;
st_sample_t *ostart, *oend;
st_sample_t ilast, icur, out;
#ifdef FLOAT_MIXENG
real_t t;
#else
int64_t t;
#endif
ilast = rate->ilast;
istart = ibuf;
iend = ibuf + *isamp;
ostart = obuf;
oend = obuf + *osamp;
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].r, ibuf[i].r);
}
*isamp = n;
*osamp = n;
return;
}
while (obuf < oend) {
/* Safety catch to make sure we have input samples. */
if (ibuf >= iend) {
break;
}
/* read as many input samples so that ipos > opos */
while (rate->ipos <= (rate->opos >> 32)) {
ilast = *ibuf++;
rate->ipos++;
/* See if we finished the input buffer yet */
if (ibuf >= iend) {
goto the_end;
}
}
icur = *ibuf;
/* interpolate */
#ifdef FLOAT_MIXENG
#ifdef RECIPROCAL
t = (rate->opos & UINT_MAX) * (1.f / UINT_MAX);
#else
t = (rate->opos & UINT_MAX) / (real_t) UINT_MAX;
#endif
out.l = (ilast.l * (1.0 - t)) + icur.l * t;
out.r = (ilast.r * (1.0 - t)) + icur.r * t;
#else
t = rate->opos & 0xffffffff;
out.l = (ilast.l * ((int64_t) UINT_MAX - t) + icur.l * t) >> 32;
out.r = (ilast.r * ((int64_t) UINT_MAX - t) + icur.r * t) >> 32;
#endif
/* output sample & increment position */
OP (obuf->l, out.l);
OP (obuf->r, out.r);
obuf += 1;
rate->opos += rate->opos_inc;
}
the_end:
*isamp = ibuf - istart;
*osamp = obuf - ostart;
rate->ilast = ilast;
}
#undef NAME
#undef OP

437
audio/sdlaudio.c Normal file
View File

@@ -0,0 +1,437 @@
/*
* QEMU SDL audio driver
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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 <SDL.h>
#include <SDL_thread.h>
#include "vl.h"
#define AUDIO_CAP "sdl"
#include "audio_int.h"
typedef struct SDLVoiceOut {
HWVoiceOut hw;
int live;
int rpos;
int decr;
} SDLVoiceOut;
static struct {
int nb_samples;
} conf = {
1024
};
struct SDLAudioState {
int exit;
SDL_mutex *mutex;
SDL_sem *sem;
int initialized;
} glob_sdl;
typedef struct SDLAudioState SDLAudioState;
static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
AUD_vlog (AUDIO_CAP, fmt, ap);
va_end (ap);
AUD_log (AUDIO_CAP, "Reason: %s\n", SDL_GetError ());
}
static int sdl_lock (SDLAudioState *s, const char *forfn)
{
if (SDL_LockMutex (s->mutex)) {
sdl_logerr ("SDL_LockMutex for %s failed\n", forfn);
return -1;
}
return 0;
}
static int sdl_unlock (SDLAudioState *s, const char *forfn)
{
if (SDL_UnlockMutex (s->mutex)) {
sdl_logerr ("SDL_UnlockMutex for %s failed\n", forfn);
return -1;
}
return 0;
}
static int sdl_post (SDLAudioState *s, const char *forfn)
{
if (SDL_SemPost (s->sem)) {
sdl_logerr ("SDL_SemPost for %s failed\n", forfn);
return -1;
}
return 0;
}
static int sdl_wait (SDLAudioState *s, const char *forfn)
{
if (SDL_SemWait (s->sem)) {
sdl_logerr ("SDL_SemWait for %s failed\n", forfn);
return -1;
}
return 0;
}
static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
{
if (sdl_unlock (s, forfn)) {
return -1;
}
return sdl_post (s, forfn);
}
static int aud_to_sdlfmt (audfmt_e fmt, int *shift)
{
switch (fmt) {
case AUD_FMT_S8:
*shift = 0;
return AUDIO_S8;
case AUD_FMT_U8:
*shift = 0;
return AUDIO_U8;
case AUD_FMT_S16:
*shift = 1;
return AUDIO_S16LSB;
case AUD_FMT_U16:
*shift = 1;
return AUDIO_U16LSB;
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
#ifdef DEBUG_AUDIO
abort ();
#endif
return AUDIO_U8;
}
}
static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
{
switch (sdlfmt) {
case AUDIO_S8:
*endianess = 0;
*fmt = AUD_FMT_S8;
break;
case AUDIO_U8:
*endianess = 0;
*fmt = AUD_FMT_U8;
break;
case AUDIO_S16LSB:
*endianess = 0;
*fmt = AUD_FMT_S16;
break;
case AUDIO_U16LSB:
*endianess = 0;
*fmt = AUD_FMT_U16;
break;
case AUDIO_S16MSB:
*endianess = 1;
*fmt = AUD_FMT_S16;
break;
case AUDIO_U16MSB:
*endianess = 1;
*fmt = AUD_FMT_U16;
break;
default:
dolog ("Unrecognized SDL audio format %d\n", sdlfmt);
return -1;
}
return 0;
}
static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
{
int status;
status = SDL_OpenAudio (req, obt);
if (status) {
sdl_logerr ("SDL_OpenAudio failed\n");
}
return status;
}
static void sdl_close (SDLAudioState *s)
{
if (s->initialized) {
sdl_lock (s, "sdl_close");
s->exit = 1;
sdl_unlock_and_post (s, "sdl_close");
SDL_PauseAudio (1);
SDL_CloseAudio ();
s->initialized = 0;
}
}
static void sdl_callback (void *opaque, Uint8 *buf, int len)
{
SDLVoiceOut *sdl = opaque;
SDLAudioState *s = &glob_sdl;
HWVoiceOut *hw = &sdl->hw;
int samples = len >> hw->info.shift;
if (s->exit) {
return;
}
while (samples) {
int to_mix, decr;
/* dolog ("in callback samples=%d\n", samples); */
sdl_wait (s, "sdl_callback");
if (s->exit) {
return;
}
if (sdl_lock (s, "sdl_callback")) {
return;
}
if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) {
dolog ("sdl->live=%d hw->samples=%d\n",
sdl->live, hw->samples);
return;
}
if (!sdl->live) {
goto again;
}
/* dolog ("in callback live=%d\n", live); */
to_mix = audio_MIN (samples, sdl->live);
decr = to_mix;
while (to_mix) {
int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
st_sample_t *src = hw->mix_buf + hw->rpos;
/* 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;
}
samples -= decr;
sdl->live -= decr;
sdl->decr += decr;
again:
if (sdl_unlock (s, "sdl_callback")) {
return;
}
}
/* dolog ("done len=%d\n", len); */
}
static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
static int sdl_run_out (HWVoiceOut *hw)
{
int decr, live;
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
SDLAudioState *s = &glob_sdl;
if (sdl_lock (s, "sdl_callback")) {
return 0;
}
live = audio_pcm_hw_get_live_out (hw);
if (sdl->decr > live) {
ldebug ("sdl->decr %d live %d sdl->live %d\n",
sdl->decr,
live,
sdl->live);
}
decr = audio_MIN (sdl->decr, live);
sdl->decr -= decr;
sdl->live = live - decr;
hw->rpos = sdl->rpos;
if (sdl->live > 0) {
sdl_unlock_and_post (s, "sdl_callback");
}
else {
sdl_unlock (s, "sdl_callback");
}
return decr;
}
static void sdl_fini_out (HWVoiceOut *hw)
{
(void) hw;
sdl_close (&glob_sdl);
}
static int sdl_init_out (HWVoiceOut *hw, audsettings_t *as)
{
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
SDLAudioState *s = &glob_sdl;
SDL_AudioSpec req, obt;
int shift;
int endianess;
int err;
audfmt_e effective_fmt;
audsettings_t obt_as;
shift <<= as->nchannels == 2;
req.freq = as->freq;
req.format = aud_to_sdlfmt (as->fmt, &shift);
req.channels = as->nchannels;
req.samples = conf.nb_samples;
req.callback = sdl_callback;
req.userdata = sdl;
if (sdl_open (&req, &obt)) {
return -1;
}
err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess);
if (err) {
sdl_close (s);
return -1;
}
obt_as.freq = obt.freq;
obt_as.nchannels = obt.channels;
obt_as.fmt = effective_fmt;
audio_pcm_init_info (
&hw->info,
&obt_as,
audio_need_to_swap_endian (endianess)
);
hw->samples = obt.samples;
s->initialized = 1;
s->exit = 0;
SDL_PauseAudio (0);
return 0;
}
static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
(void) hw;
switch (cmd) {
case VOICE_ENABLE:
SDL_PauseAudio (0);
break;
case VOICE_DISABLE:
SDL_PauseAudio (1);
break;
}
return 0;
}
static void *sdl_audio_init (void)
{
SDLAudioState *s = &glob_sdl;
if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
sdl_logerr ("SDL failed to initialize audio subsystem\n");
return NULL;
}
s->mutex = SDL_CreateMutex ();
if (!s->mutex) {
sdl_logerr ("Failed to create SDL mutex\n");
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
s->sem = SDL_CreateSemaphore (0);
if (!s->sem) {
sdl_logerr ("Failed to create SDL semaphore\n");
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
return NULL;
}
return s;
}
static void sdl_audio_fini (void *opaque)
{
SDLAudioState *s = opaque;
sdl_close (s);
SDL_DestroySemaphore (s->sem);
SDL_DestroyMutex (s->mutex);
SDL_QuitSubSystem (SDL_INIT_AUDIO);
}
static struct audio_option sdl_options[] = {
{"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
"Size of SDL buffer in samples", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
static struct audio_pcm_ops sdl_pcm_ops = {
sdl_init_out,
sdl_fini_out,
sdl_run_out,
sdl_write_out,
sdl_ctl_out,
NULL,
NULL,
NULL,
NULL,
NULL
};
struct audio_driver sdl_audio_driver = {
INIT_FIELD (name = ) "sdl",
INIT_FIELD (descr = ) "SDL http://www.libsdl.org",
INIT_FIELD (options = ) sdl_options,
INIT_FIELD (init = ) sdl_audio_init,
INIT_FIELD (fini = ) sdl_audio_fini,
INIT_FIELD (pcm_ops = ) &sdl_pcm_ops,
INIT_FIELD (can_be_default = ) 1,
INIT_FIELD (max_voices_out = ) 1,
INIT_FIELD (max_voices_in = ) 0,
INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut),
INIT_FIELD (voice_size_in = ) 0
};

241
audio/sys-queue.h Normal file
View File

@@ -0,0 +1,241 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.3 (Berkeley) 12/13/93
*/
#ifndef _SYS_QUEUE_H
#define _SYS_QUEUE_H 1
/*
* This file defines three types of data structures: lists, tail queues,
* and circular queues.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list after
* an existing element or at the head of the list. A list may only be
* traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list after
* an existing element, at the head of the list, or at the end of the
* list. A tail queue may only be traversed in the forward direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#define LIST_INIT(head) { \
(head)->lh_first = NULL; \
}
#define LIST_INSERT_AFTER(listelm, elm, field) { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
}
#define LIST_INSERT_HEAD(head, elm, field) { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
}
#define LIST_REMOVE(elm, field) { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
}
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
}
#define TAILQ_INSERT_HEAD(head, elm, field) { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
}
#define TAILQ_INSERT_TAIL(head, elm, field) { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
}
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
}
#define TAILQ_REMOVE(head, elm, field) { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
}
/*
* Circular queue definitions.
*/
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) { \
(head)->cqh_first = (void *)(head); \
(head)->cqh_last = (void *)(head); \
}
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
}
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
}
#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = (void *)(head); \
if ((head)->cqh_last == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
}
#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
(elm)->field.cqe_next = (void *)(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
}
#define CIRCLEQ_REMOVE(head, elm, field) { \
if ((elm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
}
#endif /* sys/queue.h */

255
audio/wavaudio.c Normal file
View File

@@ -0,0 +1,255 @@
/*
* QEMU WAV audio driver
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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"
#define AUDIO_CAP "wav"
#include "audio_int.h"
typedef struct WAVVoiceOut {
HWVoiceOut hw;
QEMUFile *f;
int64_t old_ticks;
void *pcm_buf;
int total_samples;
} WAVVoiceOut;
static struct {
audsettings_t settings;
const char *wav_path;
} conf = {
{
44100,
2,
AUD_FMT_S16
},
"qemu.wav"
};
static int wav_run_out (HWVoiceOut *hw)
{
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
int rpos, live, decr, samples;
uint8_t *dst;
st_sample_t *src;
int64_t now = qemu_get_clock (vm_clock);
int64_t ticks = now - wav->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;
}
live = audio_pcm_hw_get_live_out (hw);
if (!live) {
return 0;
}
wav->old_ticks = now;
decr = audio_MIN (live, samples);
samples = decr;
rpos = hw->rpos;
while (samples) {
int left_till_end_samples = hw->samples - rpos;
int convert_samples = audio_MIN (samples, left_till_end_samples);
src = hw->mix_buf + rpos;
dst = advance (wav->pcm_buf, rpos << hw->info.shift);
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;
wav->total_samples += convert_samples;
}
hw->rpos = rpos;
return decr;
}
static int wav_write_out (SWVoiceOut *sw, void *buf, int len)
{
return audio_pcm_sw_write (sw, buf, len);
}
/* 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 int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
{
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
int bits16 = 0, stereo = 0;
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 wav_as = conf.settings;
(void) as;
stereo = wav_as.nchannels == 2;
switch (wav_as.fmt) {
case AUD_FMT_S8:
case AUD_FMT_U8:
bits16 = 0;
break;
case AUD_FMT_S16:
case AUD_FMT_U16:
bits16 = 1;
break;
}
hdr[34] = bits16 ? 0x10 : 0x08;
audio_pcm_init_info (&hw->info, &wav_as, audio_need_to_swap_endian (0));
hw->samples = 1024;
wav->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
if (!wav->pcm_buf) {
dolog ("Could not allocate buffer (%d bytes)\n",
hw->samples << hw->info.shift);
return -1;
}
le_store (hdr + 22, hw->info.nchannels, 2);
le_store (hdr + 24, hw->info.freq, 4);
le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
le_store (hdr + 32, 1 << (bits16 + stereo), 2);
wav->f = fopen (conf.wav_path, "wb");
if (!wav->f) {
dolog ("Failed to open wave file `%s'\nReason: %s\n",
conf.wav_path, strerror (errno));
qemu_free (wav->pcm_buf);
wav->pcm_buf = NULL;
return -1;
}
qemu_put_buffer (wav->f, hdr, sizeof (hdr));
return 0;
}
static void wav_fini_out (HWVoiceOut *hw)
{
WAVVoiceOut *wav = (WAVVoiceOut *) hw;
uint8_t rlen[4];
uint8_t dlen[4];
uint32_t datalen = wav->total_samples << hw->info.shift;
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);
wav->f = NULL;
qemu_free (wav->pcm_buf);
wav->pcm_buf = NULL;
}
static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)
{
(void) hw;
(void) cmd;
return 0;
}
static void *wav_audio_init (void)
{
return &conf;
}
static void wav_audio_fini (void *opaque)
{
(void) opaque;
ldebug ("wav_fini");
}
struct audio_option wav_options[] = {
{"FREQUENCY", AUD_OPT_INT, &conf.settings.freq,
"Frequency", NULL, 0},
{"FORMAT", AUD_OPT_FMT, &conf.settings.fmt,
"Format", NULL, 0},
{"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.settings.nchannels,
"Number of channels (1 - mono, 2 - stereo)", NULL, 0},
{"PATH", AUD_OPT_STR, &conf.wav_path,
"Path to wave file", NULL, 0},
{NULL, 0, NULL, NULL, NULL, 0}
};
struct audio_pcm_ops wav_pcm_ops = {
wav_init_out,
wav_fini_out,
wav_run_out,
wav_write_out,
wav_ctl_out,
NULL,
NULL,
NULL,
NULL,
NULL
};
struct audio_driver wav_audio_driver = {
INIT_FIELD (name = ) "wav",
INIT_FIELD (descr = )
"WAV renderer http://wikipedia.org/wiki/WAV",
INIT_FIELD (options = ) wav_options,
INIT_FIELD (init = ) wav_audio_init,
INIT_FIELD (fini = ) wav_audio_fini,
INIT_FIELD (pcm_ops = ) &wav_pcm_ops,
INIT_FIELD (can_be_default = ) 0,
INIT_FIELD (max_voices_out = ) 1,
INIT_FIELD (max_voices_in = ) 0,
INIT_FIELD (voice_size_out = ) sizeof (WAVVoiceOut),
INIT_FIELD (voice_size_in = ) 0
};

224
block-bochs.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* Block driver for the various disk image formats used by Bochs
* Currently only for "growing" type in read-only mode
*
* Copyright (c) 2005 Alex Beregszaszi
*
* 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"
#include "block_int.h"
/**************************************************************/
#define HEADER_MAGIC "Bochs Virtual HD Image"
#define HEADER_VERSION 0x00010000
#define HEADER_SIZE 512
#define REDOLOG_TYPE "Redolog"
#define GROWING_TYPE "Growing"
// not allocated: 0xffffffff
// always little-endian
struct bochs_header {
char magic[32]; // "Bochs Virtual HD Image"
char type[16]; // "Redolog"
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
uint32_t version;
uint32_t header; // size of header
union {
struct {
uint32_t catalog; // num of entries
uint32_t bitmap; // bitmap size
uint32_t extent; // extent size
uint64_t disk; // disk size
char padding[HEADER_SIZE - 64 - 8 - 20];
} redolog;
char padding[HEADER_SIZE - 64 - 8];
} extra;
};
typedef struct BDRVBochsState {
int fd;
uint32_t *catalog_bitmap;
int catalog_size;
int data_offset;
int bitmap_blocks;
int extent_blocks;
int extent_size;
} BDRVBochsState;
static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const struct bochs_header *bochs = (const void *)buf;
if (buf_size < HEADER_SIZE)
return 0;
if (!strcmp(bochs->magic, HEADER_MAGIC) &&
!strcmp(bochs->type, REDOLOG_TYPE) &&
!strcmp(bochs->subtype, GROWING_TYPE) &&
(le32_to_cpu(bochs->version) == HEADER_VERSION))
return 100;
return 0;
}
static int bochs_open(BlockDriverState *bs, const char *filename)
{
BDRVBochsState *s = bs->opaque;
int fd, i;
struct bochs_header bochs;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
bs->read_only = 1; // no write support yet
s->fd = fd;
if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
goto fail;
}
if (strcmp(bochs.magic, HEADER_MAGIC) ||
strcmp(bochs.type, REDOLOG_TYPE) ||
strcmp(bochs.subtype, GROWING_TYPE) ||
(le32_to_cpu(bochs.version) != HEADER_VERSION)) {
goto fail;
}
bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
s->catalog_size = le32_to_cpu(bochs.extra.redolog.catalog);
s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
if (!s->catalog_bitmap)
goto fail;
if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
s->catalog_size * 4)
goto fail;
for (i = 0; i < s->catalog_size; i++)
le32_to_cpus(&s->catalog_bitmap[i]);
s->data_offset = le32_to_cpu(bochs.header) + (s->catalog_size * 4);
s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
return 0;
fail:
close(fd);
return -1;
}
static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
BDRVBochsState *s = bs->opaque;
int64_t offset = sector_num * 512;
int64_t extent_index, extent_offset, bitmap_offset, block_offset;
char bitmap_entry;
// seek to sector
extent_index = offset / s->extent_size;
extent_offset = (offset % s->extent_size) / 512;
if (s->catalog_bitmap[extent_index] == 0xffffffff)
{
// fprintf(stderr, "page not allocated [%x - %x:%x]\n",
// sector_num, extent_index, extent_offset);
return -1; // not allocated
}
bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
(s->extent_blocks + s->bitmap_blocks));
block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
// fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
// sector_num, extent_index, extent_offset,
// le32_to_cpu(s->catalog_bitmap[extent_index]),
// bitmap_offset, block_offset);
// read in bitmap for current extent
lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
read(s->fd, &bitmap_entry, 1);
if (!((bitmap_entry >> (extent_offset % 8)) & 1))
{
// fprintf(stderr, "sector (%x) in bitmap not allocated\n",
// sector_num);
return -1; // not allocated
}
lseek(s->fd, block_offset, SEEK_SET);
return 0;
}
static int bochs_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVBochsState *s = bs->opaque;
int ret;
while (nb_sectors > 0) {
if (!seek_to_sector(bs, sector_num))
{
ret = read(s->fd, buf, 512);
if (ret != 512)
return -1;
}
else
memset(buf, 0, 512);
nb_sectors--;
sector_num++;
buf += 512;
}
return 0;
}
static void bochs_close(BlockDriverState *bs)
{
BDRVBochsState *s = bs->opaque;
qemu_free(s->catalog_bitmap);
close(s->fd);
}
BlockDriver bdrv_bochs = {
"bochs",
sizeof(BDRVBochsState),
bochs_probe,
bochs_open,
bochs_read,
NULL,
bochs_close,
};

169
block-cloop.c Normal file
View File

@@ -0,0 +1,169 @@
/*
* QEMU Block driver for CLOOP images
*
* Copyright (c) 2004 Johannes E. Schindelin
*
* 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"
#include "block_int.h"
#include <zlib.h>
typedef struct BDRVCloopState {
int fd;
uint32_t block_size;
uint32_t n_blocks;
uint64_t* offsets;
uint32_t sectors_per_block;
uint32_t current_block;
uint8_t *compressed_block;
uint8_t *uncompressed_block;
z_stream zstream;
} BDRVCloopState;
static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const char* magic_version_2_0="#!/bin/sh\n"
"#V2.0 Format\n"
"modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
int length=strlen(magic_version_2_0);
if(length>buf_size)
length=buf_size;
if(!memcmp(magic_version_2_0,buf,length))
return 2;
return 0;
}
static int cloop_open(BlockDriverState *bs, const char *filename)
{
BDRVCloopState *s = bs->opaque;
uint32_t offsets_size,max_compressed_block_size=1,i;
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (s->fd < 0)
return -1;
bs->read_only = 1;
/* read header */
if(lseek(s->fd,128,SEEK_SET)<0) {
cloop_close:
close(s->fd);
return -1;
}
if(read(s->fd,&s->block_size,4)<4)
goto cloop_close;
s->block_size=be32_to_cpu(s->block_size);
if(read(s->fd,&s->n_blocks,4)<4)
goto cloop_close;
s->n_blocks=be32_to_cpu(s->n_blocks);
/* read offsets */
offsets_size=s->n_blocks*sizeof(uint64_t);
if(!(s->offsets=(uint64_t*)malloc(offsets_size)))
goto cloop_close;
if(read(s->fd,s->offsets,offsets_size)<offsets_size)
goto cloop_close;
for(i=0;i<s->n_blocks;i++) {
s->offsets[i]=be64_to_cpu(s->offsets[i]);
if(i>0) {
uint32_t size=s->offsets[i]-s->offsets[i-1];
if(size>max_compressed_block_size)
max_compressed_block_size=size;
}
}
/* initialize zlib engine */
if(!(s->compressed_block = malloc(max_compressed_block_size+1)))
goto cloop_close;
if(!(s->uncompressed_block = malloc(s->block_size)))
goto cloop_close;
if(inflateInit(&s->zstream) != Z_OK)
goto cloop_close;
s->current_block=s->n_blocks;
s->sectors_per_block = s->block_size/512;
bs->total_sectors = s->n_blocks*s->sectors_per_block;
return 0;
}
static inline int cloop_read_block(BDRVCloopState *s,int block_num)
{
if(s->current_block != block_num) {
int ret;
uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
lseek(s->fd, s->offsets[block_num], SEEK_SET);
ret = read(s->fd, s->compressed_block, bytes);
if (ret != bytes)
return -1;
s->zstream.next_in = s->compressed_block;
s->zstream.avail_in = bytes;
s->zstream.next_out = s->uncompressed_block;
s->zstream.avail_out = s->block_size;
ret = inflateReset(&s->zstream);
if(ret != Z_OK)
return -1;
ret = inflate(&s->zstream, Z_FINISH);
if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
return -1;
s->current_block = block_num;
}
return 0;
}
static int cloop_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCloopState *s = bs->opaque;
int i;
for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
block_num=(sector_num+i)/s->sectors_per_block;
if(cloop_read_block(s, block_num) != 0)
return -1;
memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
}
return 0;
}
static void cloop_close(BlockDriverState *bs)
{
BDRVCloopState *s = bs->opaque;
close(s->fd);
if(s->n_blocks>0)
free(s->offsets);
free(s->compressed_block);
free(s->uncompressed_block);
inflateEnd(&s->zstream);
}
BlockDriver bdrv_cloop = {
"cloop",
sizeof(BDRVCloopState),
cloop_probe,
cloop_open,
cloop_read,
NULL,
cloop_close,
};

264
block-cow.c Normal file
View File

@@ -0,0 +1,264 @@
/*
* Block driver for the COW format
*
* Copyright (c) 2004 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.
*/
#ifndef _WIN32
#include "vl.h"
#include "block_int.h"
#include <sys/mman.h>
/**************************************************************/
/* COW block driver using file system holes */
/* user mode linux compatible COW file */
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
#define COW_VERSION 2
struct cow_header_v2 {
uint32_t magic;
uint32_t version;
char backing_file[1024];
int32_t mtime;
uint64_t size;
uint32_t sectorsize;
};
typedef struct BDRVCowState {
int fd;
uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
int cow_bitmap_size;
int64_t cow_sectors_offset;
} BDRVCowState;
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const struct cow_header_v2 *cow_header = (const void *)buf;
if (buf_size >= sizeof(struct cow_header_v2) &&
be32_to_cpu(cow_header->magic) == COW_MAGIC &&
be32_to_cpu(cow_header->version) == COW_VERSION)
return 100;
else
return 0;
}
static int cow_open(BlockDriverState *bs, const char *filename)
{
BDRVCowState *s = bs->opaque;
int fd;
struct cow_header_v2 cow_header;
int64_t size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
s->fd = fd;
/* see if it is a cow image */
if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
goto fail;
}
if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
be32_to_cpu(cow_header.version) != COW_VERSION) {
goto fail;
}
/* cow image found */
size = be64_to_cpu(cow_header.size);
bs->total_sectors = size / 512;
pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
#if 0
if (cow_header.backing_file[0] != '\0') {
if (stat(cow_header.backing_file, &st) != 0) {
fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
goto fail;
}
if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
goto fail;
}
fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
if (fd < 0)
goto fail;
bs->fd = fd;
}
#endif
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
if (s->cow_bitmap_addr == MAP_FAILED)
goto fail;
s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
return 0;
fail:
close(fd);
return -1;
}
static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
{
bitmap[bitnum / 8] |= (1 << (bitnum%8));
}
static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
{
return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
}
/* Return true if first block has been changed (ie. current version is
* in COW file). Set the number of continuous blocks for which that
* is true. */
static inline int is_changed(uint8_t *bitmap,
int64_t sector_num, int nb_sectors,
int *num_same)
{
int changed;
if (!bitmap || nb_sectors == 0) {
*num_same = nb_sectors;
return 0;
}
changed = is_bit_set(bitmap, sector_num);
for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
if (is_bit_set(bitmap, sector_num + *num_same) != changed)
break;
}
return changed;
}
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVCowState *s = bs->opaque;
return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
}
static int cow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, n;
while (nb_sectors > 0) {
if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
} else {
memset(buf, 0, n * 512);
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int cow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, i;
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = write(s->fd, buf, nb_sectors * 512);
if (ret != nb_sectors * 512)
return -1;
for (i = 0; i < nb_sectors; i++)
cow_set_bit(s->cow_bitmap, sector_num + i);
return 0;
}
static void cow_close(BlockDriverState *bs)
{
BDRVCowState *s = bs->opaque;
munmap(s->cow_bitmap_addr, s->cow_bitmap_size);
close(s->fd);
}
static int cow_create(const char *filename, int64_t image_sectors,
const char *image_filename, int flags)
{
int fd, cow_fd;
struct cow_header_v2 cow_header;
struct stat st;
if (flags)
return -ENOTSUP;
cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (cow_fd < 0)
return -1;
memset(&cow_header, 0, sizeof(cow_header));
cow_header.magic = cpu_to_be32(COW_MAGIC);
cow_header.version = cpu_to_be32(COW_VERSION);
if (image_filename) {
fd = open(image_filename, O_RDONLY | O_BINARY);
if (fd < 0) {
close(cow_fd);
return -1;
}
if (fstat(fd, &st) != 0) {
close(fd);
return -1;
}
close(fd);
cow_header.mtime = cpu_to_be32(st.st_mtime);
realpath(image_filename, cow_header.backing_file);
}
cow_header.sectorsize = cpu_to_be32(512);
cow_header.size = cpu_to_be64(image_sectors * 512);
write(cow_fd, &cow_header, sizeof(cow_header));
/* resize to include at least all the bitmap */
ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
close(cow_fd);
return 0;
}
BlockDriver bdrv_cow = {
"cow",
sizeof(BDRVCowState),
cow_probe,
cow_open,
cow_read,
cow_write,
cow_close,
cow_create,
cow_is_allocated,
};
#endif

297
block-dmg.c Normal file
View File

@@ -0,0 +1,297 @@
/*
* QEMU Block driver for DMG images
*
* Copyright (c) 2004 Johannes E. Schindelin
*
* 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"
#include "block_int.h"
#include "bswap.h"
#include <zlib.h>
typedef struct BDRVDMGState {
int fd;
/* each chunk contains a certain number of sectors,
* offsets[i] is the offset in the .dmg file,
* lengths[i] is the length of the compressed chunk,
* sectors[i] is the sector beginning at offsets[i],
* sectorcounts[i] is the number of sectors in that chunk,
* the sectors array is ordered
* 0<=i<n_chunks */
uint32_t n_chunks;
uint32_t* types;
uint64_t* offsets;
uint64_t* lengths;
uint64_t* sectors;
uint64_t* sectorcounts;
uint32_t current_chunk;
uint8_t *compressed_chunk;
uint8_t *uncompressed_chunk;
z_stream zstream;
} BDRVDMGState;
static int dmg_probe(const uint8_t *buf, int buf_size, const char *filename)
{
int len=strlen(filename);
if(len>4 && !strcmp(filename+len-4,".dmg"))
return 2;
return 0;
}
static off_t read_off(int fd)
{
uint64_t buffer;
if(read(fd,&buffer,8)<8)
return 0;
return be64_to_cpu(buffer);
}
static off_t read_uint32(int fd)
{
uint32_t buffer;
if(read(fd,&buffer,4)<4)
return 0;
return be32_to_cpu(buffer);
}
static int dmg_open(BlockDriverState *bs, const char *filename)
{
BDRVDMGState *s = bs->opaque;
off_t info_begin,info_end,last_in_offset,last_out_offset;
uint32_t count;
uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (s->fd < 0)
return -1;
bs->read_only = 1;
s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
/* read offset of info blocks */
if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
dmg_close:
close(s->fd);
/* open raw instead */
bs->drv=&bdrv_raw;
return bs->drv->bdrv_open(bs,filename);
}
info_begin=read_off(s->fd);
if(info_begin==0)
goto dmg_close;
if(lseek(s->fd,info_begin,SEEK_SET)<0)
goto dmg_close;
if(read_uint32(s->fd)!=0x100)
goto dmg_close;
if((count = read_uint32(s->fd))==0)
goto dmg_close;
info_end = info_begin+count;
if(lseek(s->fd,0xf8,SEEK_CUR)<0)
goto dmg_close;
/* read offsets */
last_in_offset = last_out_offset = 0;
while(lseek(s->fd,0,SEEK_CUR)<info_end) {
uint32_t type;
count = read_uint32(s->fd);
if(count==0)
goto dmg_close;
type = read_uint32(s->fd);
if(type!=0x6d697368 || count<244)
lseek(s->fd,count-4,SEEK_CUR);
else {
int new_size, chunk_count;
if(lseek(s->fd,200,SEEK_CUR)<0)
goto dmg_close;
chunk_count = (count-204)/40;
new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
s->types = realloc(s->types, new_size/2);
s->offsets = realloc(s->offsets, new_size);
s->lengths = realloc(s->lengths, new_size);
s->sectors = realloc(s->sectors, new_size);
s->sectorcounts = realloc(s->sectorcounts, new_size);
for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
s->types[i] = read_uint32(s->fd);
if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
if(s->types[i]==0xffffffff) {
last_in_offset = s->offsets[i-1]+s->lengths[i-1];
last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1];
}
chunk_count--;
i--;
if(lseek(s->fd,36,SEEK_CUR)<0)
goto dmg_close;
continue;
}
read_uint32(s->fd);
s->sectors[i] = last_out_offset+read_off(s->fd);
s->sectorcounts[i] = read_off(s->fd);
s->offsets[i] = last_in_offset+read_off(s->fd);
s->lengths[i] = read_off(s->fd);
if(s->lengths[i]>max_compressed_size)
max_compressed_size = s->lengths[i];
if(s->sectorcounts[i]>max_sectors_per_chunk)
max_sectors_per_chunk = s->sectorcounts[i];
}
s->n_chunks+=chunk_count;
}
}
/* initialize zlib engine */
if(!(s->compressed_chunk = malloc(max_compressed_size+1)))
goto dmg_close;
if(!(s->uncompressed_chunk = malloc(512*max_sectors_per_chunk)))
goto dmg_close;
if(inflateInit(&s->zstream) != Z_OK)
goto dmg_close;
s->current_chunk = s->n_chunks;
return 0;
}
static inline int is_sector_in_chunk(BDRVDMGState* s,
uint32_t chunk_num,int sector_num)
{
if(chunk_num>=s->n_chunks || s->sectors[chunk_num]>sector_num ||
s->sectors[chunk_num]+s->sectorcounts[chunk_num]<=sector_num)
return 0;
else
return -1;
}
static inline uint32_t search_chunk(BDRVDMGState* s,int sector_num)
{
/* binary search */
uint32_t chunk1=0,chunk2=s->n_chunks,chunk3;
while(chunk1!=chunk2) {
chunk3 = (chunk1+chunk2)/2;
if(s->sectors[chunk3]>sector_num)
chunk2 = chunk3;
else if(s->sectors[chunk3]+s->sectorcounts[chunk3]>sector_num)
return chunk3;
else
chunk1 = chunk3;
}
return s->n_chunks; /* error */
}
static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
{
if(!is_sector_in_chunk(s,s->current_chunk,sector_num)) {
int ret;
uint32_t chunk = search_chunk(s,sector_num);
if(chunk>=s->n_chunks)
return -1;
s->current_chunk = s->n_chunks;
switch(s->types[chunk]) {
case 0x80000005: { /* zlib compressed */
int i;
ret = lseek(s->fd, s->offsets[chunk], SEEK_SET);
if(ret<0)
return -1;
/* we need to buffer, because only the chunk as whole can be
* inflated. */
i=0;
do {
ret = read(s->fd, s->compressed_chunk+i, s->lengths[chunk]-i);
if(ret<0 && errno==EINTR)
ret=0;
i+=ret;
} while(ret>=0 && ret+i<s->lengths[chunk]);
if (ret != s->lengths[chunk])
return -1;
s->zstream.next_in = s->compressed_chunk;
s->zstream.avail_in = s->lengths[chunk];
s->zstream.next_out = s->uncompressed_chunk;
s->zstream.avail_out = 512*s->sectorcounts[chunk];
ret = inflateReset(&s->zstream);
if(ret != Z_OK)
return -1;
ret = inflate(&s->zstream, Z_FINISH);
if(ret != Z_STREAM_END || s->zstream.total_out != 512*s->sectorcounts[chunk])
return -1;
break; }
case 1: /* copy */
ret = read(s->fd, s->uncompressed_chunk, s->lengths[chunk]);
if (ret != s->lengths[chunk])
return -1;
break;
case 2: /* zero */
memset(s->uncompressed_chunk, 0, 512*s->sectorcounts[chunk]);
break;
}
s->current_chunk = chunk;
}
return 0;
}
static int dmg_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVDMGState *s = bs->opaque;
int i;
for(i=0;i<nb_sectors;i++) {
uint32_t sector_offset_in_chunk;
if(dmg_read_chunk(s, sector_num+i) != 0)
return -1;
sector_offset_in_chunk = sector_num+i-s->sectors[s->current_chunk];
memcpy(buf+i*512,s->uncompressed_chunk+sector_offset_in_chunk*512,512);
}
return 0;
}
static void dmg_close(BlockDriverState *bs)
{
BDRVDMGState *s = bs->opaque;
close(s->fd);
if(s->n_chunks>0) {
free(s->types);
free(s->offsets);
free(s->lengths);
free(s->sectors);
free(s->sectorcounts);
}
free(s->compressed_chunk);
free(s->uncompressed_chunk);
inflateEnd(&s->zstream);
}
BlockDriver bdrv_dmg = {
"dmg",
sizeof(BDRVDMGState),
dmg_probe,
dmg_open,
dmg_read,
NULL,
dmg_close,
};

710
block-qcow.c Normal file
View File

@@ -0,0 +1,710 @@
/*
* Block driver for the QCOW format
*
* Copyright (c) 2004 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"
#include "block_int.h"
#include <zlib.h>
#include "aes.h"
/**************************************************************/
/* QEMU COW block driver with compression and encryption support */
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
#define QCOW_VERSION 1
#define QCOW_CRYPT_NONE 0
#define QCOW_CRYPT_AES 1
#define QCOW_OFLAG_COMPRESSED (1LL << 63)
typedef struct QCowHeader {
uint32_t magic;
uint32_t version;
uint64_t backing_file_offset;
uint32_t backing_file_size;
uint32_t mtime;
uint64_t size; /* in bytes */
uint8_t cluster_bits;
uint8_t l2_bits;
uint32_t crypt_method;
uint64_t l1_table_offset;
} QCowHeader;
#define L2_CACHE_SIZE 16
typedef struct BDRVQcowState {
int fd;
int cluster_bits;
int cluster_size;
int cluster_sectors;
int l2_bits;
int l2_size;
int l1_size;
uint64_t cluster_offset_mask;
uint64_t l1_table_offset;
uint64_t *l1_table;
uint64_t *l2_cache;
uint64_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
uint8_t *cluster_cache;
uint8_t *cluster_data;
uint64_t cluster_cache_offset;
uint32_t crypt_method; /* current crypt method, 0 if no key yet */
uint32_t crypt_method_header;
AES_KEY aes_encrypt_key;
AES_KEY aes_decrypt_key;
} BDRVQcowState;
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
if (buf_size >= sizeof(QCowHeader) &&
be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
be32_to_cpu(cow_header->version) == QCOW_VERSION)
return 100;
else
return 0;
}
static int qcow_open(BlockDriverState *bs, const char *filename)
{
BDRVQcowState *s = bs->opaque;
int fd, len, i, shift;
QCowHeader header;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
s->fd = fd;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
be32_to_cpus(&header.magic);
be32_to_cpus(&header.version);
be64_to_cpus(&header.backing_file_offset);
be32_to_cpus(&header.backing_file_size);
be32_to_cpus(&header.mtime);
be64_to_cpus(&header.size);
be32_to_cpus(&header.crypt_method);
be64_to_cpus(&header.l1_table_offset);
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
goto fail;
if (header.size <= 1 || header.cluster_bits < 9)
goto fail;
if (header.crypt_method > QCOW_CRYPT_AES)
goto fail;
s->crypt_method_header = header.crypt_method;
if (s->crypt_method_header)
bs->encrypted = 1;
s->cluster_bits = header.cluster_bits;
s->cluster_size = 1 << s->cluster_bits;
s->cluster_sectors = 1 << (s->cluster_bits - 9);
s->l2_bits = header.l2_bits;
s->l2_size = 1 << s->l2_bits;
bs->total_sectors = header.size / 512;
s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1;
/* read the level 1 table */
shift = s->cluster_bits + s->l2_bits;
s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
s->l1_table_offset = header.l1_table_offset;
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
if (!s->l1_table)
goto fail;
lseek(fd, s->l1_table_offset, SEEK_SET);
if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
for(i = 0;i < s->l1_size; i++) {
be64_to_cpus(&s->l1_table[i]);
}
/* alloc L2 cache */
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
if (!s->l2_cache)
goto fail;
s->cluster_cache = qemu_malloc(s->cluster_size);
if (!s->cluster_cache)
goto fail;
s->cluster_data = qemu_malloc(s->cluster_size);
if (!s->cluster_data)
goto fail;
s->cluster_cache_offset = -1;
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
if (len > 1023)
len = 1023;
lseek(fd, header.backing_file_offset, SEEK_SET);
if (read(fd, bs->backing_file, len) != len)
goto fail;
bs->backing_file[len] = '\0';
}
return 0;
fail:
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(fd);
return -1;
}
static int qcow_set_key(BlockDriverState *bs, const char *key)
{
BDRVQcowState *s = bs->opaque;
uint8_t keybuf[16];
int len, i;
memset(keybuf, 0, 16);
len = strlen(key);
if (len > 16)
len = 16;
/* XXX: we could compress the chars to 7 bits to increase
entropy */
for(i = 0;i < len;i++) {
keybuf[i] = key[i];
}
s->crypt_method = s->crypt_method_header;
if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
return -1;
if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
return -1;
#if 0
/* test */
{
uint8_t in[16];
uint8_t out[16];
uint8_t tmp[16];
for(i=0;i<16;i++)
in[i] = i;
AES_encrypt(in, tmp, &s->aes_encrypt_key);
AES_decrypt(tmp, out, &s->aes_decrypt_key);
for(i = 0; i < 16; i++)
printf(" %02x", tmp[i]);
printf("\n");
for(i = 0; i < 16; i++)
printf(" %02x", out[i]);
printf("\n");
}
#endif
return 0;
}
/* The crypt function is compatible with the linux cryptoloop
algorithm for < 4 GB images. NOTE: out_buf == in_buf is
supported */
static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
uint8_t *out_buf, const uint8_t *in_buf,
int nb_sectors, int enc,
const AES_KEY *key)
{
union {
uint64_t ll[2];
uint8_t b[16];
} ivec;
int i;
for(i = 0; i < nb_sectors; i++) {
ivec.ll[0] = cpu_to_le64(sector_num);
ivec.ll[1] = 0;
AES_cbc_encrypt(in_buf, out_buf, 512, key,
ivec.b, enc);
sector_num++;
in_buf += 512;
out_buf += 512;
}
}
/* 'allocate' is:
*
* 0 to not allocate.
*
* 1 to allocate a normal cluster (for sector indexes 'n_start' to
* 'n_end')
*
* 2 to allocate a compressed cluster of size
* 'compressed_size'. 'compressed_size' must be > 0 and <
* cluster_size
*
* return 0 if not allocated.
*/
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate,
int compressed_size,
int n_start, int n_end)
{
BDRVQcowState *s = bs->opaque;
int min_index, i, j, l1_index, l2_index;
uint64_t l2_offset, *l2_table, cluster_offset, tmp;
uint32_t min_count;
int new_l2_table;
l1_index = offset >> (s->l2_bits + s->cluster_bits);
l2_offset = s->l1_table[l1_index];
new_l2_table = 0;
if (!l2_offset) {
if (!allocate)
return 0;
/* allocate a new l2 entry */
l2_offset = lseek(s->fd, 0, SEEK_END);
/* round to cluster size */
l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset;
tmp = cpu_to_be64(l2_offset);
lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
new_l2_table = 1;
}
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
l2_table = s->l2_cache + (i << s->l2_bits);
goto found;
}
}
/* not found: load a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
l2_table = s->l2_cache + (min_index << s->l2_bits);
lseek(s->fd, l2_offset, SEEK_SET);
if (new_l2_table) {
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
} else {
if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
if (!cluster_offset ||
((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
if (!allocate)
return 0;
/* allocate a new cluster */
if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
(n_end - n_start) < s->cluster_sectors) {
/* if the cluster is already compressed, we must
decompress it in the case it is not completely
overwritten */
if (decompress_cluster(s, cluster_offset) < 0)
return 0;
cluster_offset = lseek(s->fd, 0, SEEK_END);
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
/* write the cluster content */
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, s->cluster_cache, s->cluster_size) !=
s->cluster_size)
return -1;
} else {
cluster_offset = lseek(s->fd, 0, SEEK_END);
if (allocate == 1) {
/* round to cluster size */
cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
ftruncate(s->fd, cluster_offset + s->cluster_size);
/* if encrypted, we must initialize the cluster
content which won't be written */
if (s->crypt_method &&
(n_end - n_start) < s->cluster_sectors) {
uint64_t start_sect;
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
memset(s->cluster_data + 512, 0xaa, 512);
for(i = 0; i < s->cluster_sectors; i++) {
if (i < n_start || i >= n_end) {
encrypt_sectors(s, start_sect + i,
s->cluster_data,
s->cluster_data + 512, 1, 1,
&s->aes_encrypt_key);
lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
if (write(s->fd, s->cluster_data, 512) != 512)
return -1;
}
}
}
} else {
cluster_offset |= QCOW_OFLAG_COMPRESSED |
(uint64_t)compressed_size << (63 - s->cluster_bits);
}
}
/* update L2 table */
tmp = cpu_to_be64(cluster_offset);
l2_table[l2_index] = tmp;
lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
return cluster_offset;
}
static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVQcowState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
*pnum = n;
return (cluster_offset != 0);
}
static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
const uint8_t *buf, int buf_size)
{
z_stream strm1, *strm = &strm1;
int ret, out_len;
memset(strm, 0, sizeof(*strm));
strm->next_in = (uint8_t *)buf;
strm->avail_in = buf_size;
strm->next_out = out_buf;
strm->avail_out = out_buf_size;
ret = inflateInit2(strm, -12);
if (ret != Z_OK)
return -1;
ret = inflate(strm, Z_FINISH);
out_len = strm->next_out - out_buf;
if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
out_len != out_buf_size) {
inflateEnd(strm);
return -1;
}
inflateEnd(strm);
return 0;
}
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
{
int ret, csize;
uint64_t coffset;
coffset = cluster_offset & s->cluster_offset_mask;
if (s->cluster_cache_offset != coffset) {
csize = cluster_offset >> (63 - s->cluster_bits);
csize &= (s->cluster_size - 1);
lseek(s->fd, coffset, SEEK_SET);
ret = read(s->fd, s->cluster_data, csize);
if (ret != csize)
return -1;
if (decompress_buffer(s->cluster_cache, s->cluster_size,
s->cluster_data, csize) < 0) {
return -1;
}
s->cluster_cache_offset = coffset;
}
return 0;
}
static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
if (decompress_cluster(s, cluster_offset) < 0)
return -1;
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
if (s->crypt_method) {
encrypt_sectors(s, sector_num, buf, buf, n, 0,
&s->aes_decrypt_key);
}
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
index_in_cluster,
index_in_cluster + n);
if (!cluster_offset)
return -1;
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
ret = write(s->fd, s->cluster_data, n * 512);
} else {
ret = write(s->fd, buf, n * 512);
}
if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
s->cluster_cache_offset = -1; /* disable compressed cache */
return 0;
}
static void qcow_close(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
qemu_free(s->cluster_cache);
qemu_free(s->cluster_data);
close(s->fd);
}
static int qcow_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd, header_size, backing_filename_len, l1_size, i, shift;
QCowHeader header;
char backing_filename[1024];
uint64_t tmp;
struct stat st;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0)
return -1;
memset(&header, 0, sizeof(header));
header.magic = cpu_to_be32(QCOW_MAGIC);
header.version = cpu_to_be32(QCOW_VERSION);
header.size = cpu_to_be64(total_size * 512);
header_size = sizeof(header);
backing_filename_len = 0;
if (backing_file) {
if (strcmp(backing_file, "fat:")) {
const char *p;
/* XXX: this is a hack: we do not attempt to check for URL
like syntax */
p = strchr(backing_file, ':');
if (p && (p - backing_file) >= 2) {
/* URL like but exclude "c:" like filenames */
pstrcpy(backing_filename, sizeof(backing_filename),
backing_file);
} else {
realpath(backing_file, backing_filename);
if (stat(backing_filename, &st) != 0) {
return -1;
}
}
header.backing_file_offset = cpu_to_be64(header_size);
backing_filename_len = strlen(backing_filename);
header.backing_file_size = cpu_to_be32(backing_filename_len);
header_size += backing_filename_len;
} else
backing_file = NULL;
header.mtime = cpu_to_be32(st.st_mtime);
header.cluster_bits = 9; /* 512 byte cluster to avoid copying
unmodifyed sectors */
header.l2_bits = 12; /* 32 KB L2 tables */
} else {
header.cluster_bits = 12; /* 4 KB clusters */
header.l2_bits = 9; /* 4 KB L2 tables */
}
header_size = (header_size + 7) & ~7;
shift = header.cluster_bits + header.l2_bits;
l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;
header.l1_table_offset = cpu_to_be64(header_size);
if (flags) {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
} else {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
}
/* write all the data */
write(fd, &header, sizeof(header));
if (backing_file) {
write(fd, backing_filename, backing_filename_len);
}
lseek(fd, header_size, SEEK_SET);
tmp = 0;
for(i = 0;i < l1_size; i++) {
write(fd, &tmp, sizeof(tmp));
}
close(fd);
return 0;
}
int qcow_make_empty(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
uint32_t l1_length = s->l1_size * sizeof(uint64_t);
memset(s->l1_table, 0, l1_length);
lseek(s->fd, s->l1_table_offset, SEEK_SET);
if (write(s->fd, s->l1_table, l1_length) < 0)
return -1;
ftruncate(s->fd, s->l1_table_offset + l1_length);
memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
return 0;
}
int qcow_get_cluster_size(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
if (bs->drv != &bdrv_qcow)
return -1;
return s->cluster_size;
}
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf)
{
BDRVQcowState *s = bs->opaque;
z_stream strm;
int ret, out_len;
uint8_t *out_buf;
uint64_t cluster_offset;
if (bs->drv != &bdrv_qcow)
return -1;
out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
if (!out_buf)
return -1;
/* best compression, small window, no zlib header */
memset(&strm, 0, sizeof(strm));
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
Z_DEFLATED, -12,
9, Z_DEFAULT_STRATEGY);
if (ret != 0) {
qemu_free(out_buf);
return -1;
}
strm.avail_in = s->cluster_size;
strm.next_in = (uint8_t *)buf;
strm.avail_out = s->cluster_size;
strm.next_out = out_buf;
ret = deflate(&strm, Z_FINISH);
if (ret != Z_STREAM_END && ret != Z_OK) {
qemu_free(out_buf);
deflateEnd(&strm);
return -1;
}
out_len = strm.next_out - out_buf;
deflateEnd(&strm);
if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
/* could not compress: write normal cluster */
qcow_write(bs, sector_num, buf, s->cluster_sectors);
} else {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
cluster_offset &= s->cluster_offset_mask;
lseek(s->fd, cluster_offset, SEEK_SET);
if (write(s->fd, out_buf, out_len) != out_len) {
qemu_free(out_buf);
return -1;
}
}
qemu_free(out_buf);
return 0;
}
BlockDriver bdrv_qcow = {
"qcow",
sizeof(BDRVQcowState),
qcow_probe,
qcow_open,
qcow_read,
qcow_write,
qcow_close,
qcow_create,
qcow_is_allocated,
qcow_set_key,
qcow_make_empty
};

439
block-vmdk.c Normal file
View File

@@ -0,0 +1,439 @@
/*
* Block driver for the VMDK format
*
* Copyright (c) 2004 Fabrice Bellard
* Copyright (c) 2005 Filip Navara
*
* 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"
#include "block_int.h"
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
typedef struct {
uint32_t version;
uint32_t flags;
uint32_t disk_sectors;
uint32_t granularity;
uint32_t l1dir_offset;
uint32_t l1dir_size;
uint32_t file_sectors;
uint32_t cylinders;
uint32_t heads;
uint32_t sectors_per_track;
} VMDK3Header;
typedef struct {
uint32_t version;
uint32_t flags;
int64_t capacity;
int64_t granularity;
int64_t desc_offset;
int64_t desc_size;
int32_t num_gtes_per_gte;
int64_t rgd_offset;
int64_t gd_offset;
int64_t grain_offset;
char filler[1];
char check_bytes[4];
} __attribute__((packed)) VMDK4Header;
#define L2_CACHE_SIZE 16
typedef struct BDRVVmdkState {
int fd;
int64_t l1_table_offset;
int64_t l1_backup_table_offset;
uint32_t *l1_table;
uint32_t *l1_backup_table;
unsigned int l1_size;
uint32_t l1_entry_sectors;
unsigned int l2_size;
uint32_t *l2_cache;
uint32_t l2_cache_offsets[L2_CACHE_SIZE];
uint32_t l2_cache_counts[L2_CACHE_SIZE];
unsigned int cluster_sectors;
} BDRVVmdkState;
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
if (buf_size < 4)
return 0;
magic = be32_to_cpu(*(uint32_t *)buf);
if (magic == VMDK3_MAGIC ||
magic == VMDK4_MAGIC)
return 100;
else
return 0;
}
static int vmdk_open(BlockDriverState *bs, const char *filename)
{
BDRVVmdkState *s = bs->opaque;
int fd, i;
uint32_t magic;
int l1_size;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
bs->read_only = 1;
}
if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
goto fail;
magic = be32_to_cpu(magic);
if (magic == VMDK3_MAGIC) {
VMDK3Header header;
if (read(fd, &header, sizeof(header)) !=
sizeof(header))
goto fail;
s->cluster_sectors = le32_to_cpu(header.granularity);
s->l2_size = 1 << 9;
s->l1_size = 1 << 6;
bs->total_sectors = le32_to_cpu(header.disk_sectors);
s->l1_table_offset = le32_to_cpu(header.l1dir_offset) << 9;
s->l1_backup_table_offset = 0;
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
} else if (magic == VMDK4_MAGIC) {
VMDK4Header header;
if (read(fd, &header, sizeof(header)) != sizeof(header))
goto fail;
bs->total_sectors = le64_to_cpu(header.capacity);
s->cluster_sectors = le64_to_cpu(header.granularity);
s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
if (s->l1_entry_sectors <= 0)
goto fail;
s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
} else {
goto fail;
}
/* read the L1 table */
l1_size = s->l1_size * sizeof(uint32_t);
s->l1_table = qemu_malloc(l1_size);
if (!s->l1_table)
goto fail;
if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
goto fail;
if (read(fd, s->l1_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_table[i]);
}
if (s->l1_backup_table_offset) {
s->l1_backup_table = qemu_malloc(l1_size);
if (!s->l1_backup_table)
goto fail;
if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
goto fail;
if (read(fd, s->l1_backup_table, l1_size) != l1_size)
goto fail;
for(i = 0; i < s->l1_size; i++) {
le32_to_cpus(&s->l1_backup_table[i]);
}
}
s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
if (!s->l2_cache)
goto fail;
s->fd = fd;
return 0;
fail:
qemu_free(s->l1_backup_table);
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(fd);
return -1;
}
static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t offset, int allocate)
{
BDRVVmdkState *s = bs->opaque;
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
uint32_t min_count, *l2_table, tmp;
uint64_t cluster_offset;
l1_index = (offset >> 9) / s->l1_entry_sectors;
if (l1_index >= s->l1_size)
return 0;
l2_offset = s->l1_table[l1_index];
if (!l2_offset)
return 0;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (l2_offset == s->l2_cache_offsets[i]) {
/* increment the hit count */
if (++s->l2_cache_counts[i] == 0xffffffff) {
for(j = 0; j < L2_CACHE_SIZE; j++) {
s->l2_cache_counts[j] >>= 1;
}
}
l2_table = s->l2_cache + (i * s->l2_size);
goto found;
}
}
/* not found: load a new entry in the least used one */
min_index = 0;
min_count = 0xffffffff;
for(i = 0; i < L2_CACHE_SIZE; i++) {
if (s->l2_cache_counts[i] < min_count) {
min_count = s->l2_cache_counts[i];
min_index = i;
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
if (!cluster_offset) {
if (!allocate)
return 0;
cluster_offset = lseek(s->fd, 0, SEEK_END);
ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
cluster_offset >>= 9;
/* update L2 table */
tmp = cpu_to_le32(cluster_offset);
l2_table[l2_index] = tmp;
lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
/* update backup L2 table */
if (s->l1_backup_table_offset != 0) {
l2_offset = s->l1_backup_table[l1_index];
lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
}
cluster_offset <<= 9;
return cluster_offset;
}
static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVVmdkState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
*pnum = n;
return (cluster_offset != 0);
}
static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
if (!cluster_offset) {
memset(buf, 0, 512 * n);
} else {
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
}
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
if (!cluster_offset)
return -1;
lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
ret = write(s->fd, buf, n * 512);
if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
buf += n * 512;
}
return 0;
}
static int vmdk_create(const char *filename, int64_t total_size,
const char *backing_file, int flags)
{
int fd, i;
VMDK4Header header;
uint32_t tmp, magic, grains, gd_size, gt_size, gt_count;
char *desc_template =
"# Disk DescriptorFile\n"
"version=1\n"
"CID=%x\n"
"parentCID=ffffffff\n"
"createType=\"monolithicSparse\"\n"
"\n"
"# Extent description\n"
"RW %lu SPARSE \"%s\"\n"
"\n"
"# The Disk Data Base \n"
"#DDB\n"
"\n"
"ddb.virtualHWVersion = \"3\"\n"
"ddb.geometry.cylinders = \"%lu\"\n"
"ddb.geometry.heads = \"16\"\n"
"ddb.geometry.sectors = \"63\"\n"
"ddb.adapterType = \"ide\"\n";
char desc[1024];
const char *real_filename, *temp_str;
/* XXX: add support for backing file */
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
0644);
if (fd < 0)
return -1;
magic = cpu_to_be32(VMDK4_MAGIC);
memset(&header, 0, sizeof(header));
header.version = cpu_to_le32(1);
header.flags = cpu_to_le32(3); /* ?? */
header.capacity = cpu_to_le64(total_size);
header.granularity = cpu_to_le64(128);
header.num_gtes_per_gte = cpu_to_le32(512);
grains = (total_size + header.granularity - 1) / header.granularity;
gt_size = ((header.num_gtes_per_gte * sizeof(uint32_t)) + 511) >> 9;
gt_count = (grains + header.num_gtes_per_gte - 1) / header.num_gtes_per_gte;
gd_size = (gt_count * sizeof(uint32_t) + 511) >> 9;
header.desc_offset = 1;
header.desc_size = 20;
header.rgd_offset = header.desc_offset + header.desc_size;
header.gd_offset = header.rgd_offset + gd_size + (gt_size * gt_count);
header.grain_offset =
((header.gd_offset + gd_size + (gt_size * gt_count) +
header.granularity - 1) / header.granularity) *
header.granularity;
header.desc_offset = cpu_to_le64(header.desc_offset);
header.desc_size = cpu_to_le64(header.desc_size);
header.rgd_offset = cpu_to_le64(header.rgd_offset);
header.gd_offset = cpu_to_le64(header.gd_offset);
header.grain_offset = cpu_to_le64(header.grain_offset);
header.check_bytes[0] = 0xa;
header.check_bytes[1] = 0x20;
header.check_bytes[2] = 0xd;
header.check_bytes[3] = 0xa;
/* write all the data */
write(fd, &magic, sizeof(magic));
write(fd, &header, sizeof(header));
ftruncate(fd, header.grain_offset << 9);
/* write grain directory */
lseek(fd, le64_to_cpu(header.rgd_offset) << 9, SEEK_SET);
for (i = 0, tmp = header.rgd_offset + gd_size;
i < gt_count; i++, tmp += gt_size)
write(fd, &tmp, sizeof(tmp));
/* write backup grain directory */
lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
for (i = 0, tmp = header.gd_offset + gd_size;
i < gt_count; i++, tmp += gt_size)
write(fd, &tmp, sizeof(tmp));
/* compose the descriptor */
real_filename = filename;
if ((temp_str = strrchr(real_filename, '\\')) != NULL)
real_filename = temp_str + 1;
if ((temp_str = strrchr(real_filename, '/')) != NULL)
real_filename = temp_str + 1;
if ((temp_str = strrchr(real_filename, ':')) != NULL)
real_filename = temp_str + 1;
sprintf(desc, desc_template, time(NULL), (unsigned long)total_size,
real_filename, total_size / (63 * 16));
/* write the descriptor */
lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
write(fd, desc, strlen(desc));
close(fd);
return 0;
}
static void vmdk_close(BlockDriverState *bs)
{
BDRVVmdkState *s = bs->opaque;
qemu_free(s->l1_table);
qemu_free(s->l2_cache);
close(s->fd);
}
BlockDriver bdrv_vmdk = {
"vmdk",
sizeof(BDRVVmdkState),
vmdk_probe,
vmdk_open,
vmdk_read,
vmdk_write,
vmdk_close,
vmdk_create,
vmdk_is_allocated,
};

242
block-vpc.c Normal file
View File

@@ -0,0 +1,242 @@
/*
* Block driver for Conectix/Microsoft Virtual PC images
*
* Copyright (c) 2005 Alex Beregszaszi
*
* 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"
#include "block_int.h"
/**************************************************************/
#define HEADER_SIZE 512
//#define CACHE
// always big-endian
struct vpc_subheader {
char magic[8]; // "conectix" / "cxsparse"
union {
struct {
uint32_t unk1[2];
uint32_t unk2; // always zero?
uint32_t subheader_offset;
uint32_t unk3; // some size?
char creator[4]; // "vpc "
uint16_t major;
uint16_t minor;
char guest[4]; // "Wi2k"
uint32_t unk4[7];
uint8_t vnet_id[16]; // virtual network id, purpose unknown
// next 16 longs are used, but dunno the purpose
// next 6 longs unknown, following 7 long maybe a serial
char padding[HEADER_SIZE - 84];
} main;
struct {
uint32_t unk1[2]; // all bits set
uint32_t unk2; // always zero?
uint32_t pagetable_offset;
uint32_t unk3;
uint32_t pagetable_entries; // 32bit/entry
uint32_t pageentry_size; // 512*8*512
uint32_t nb_sectors;
char padding[HEADER_SIZE - 40];
} sparse;
char padding[HEADER_SIZE - 8];
} type;
};
typedef struct BDRVVPCState {
int fd;
int pagetable_entries;
uint32_t *pagetable;
uint32_t pageentry_size;
#ifdef CACHE
uint8_t *pageentry_u8;
uint32_t *pageentry_u32;
uint16_t *pageentry_u16;
uint64_t last_bitmap;
#endif
} BDRVVPCState;
static int vpc_probe(const uint8_t *buf, int buf_size, const char *filename)
{
if (buf_size >= 8 && !strncmp(buf, "conectix", 8))
return 100;
return 0;
}
static int vpc_open(BlockDriverState *bs, const char *filename)
{
BDRVVPCState *s = bs->opaque;
int fd, i;
struct vpc_subheader header;
fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
if (fd < 0) {
fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
if (fd < 0)
return -1;
}
bs->read_only = 1; // no write support yet
s->fd = fd;
if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
goto fail;
if (strncmp(header.magic, "conectix", 8))
goto fail;
lseek(s->fd, be32_to_cpu(header.type.main.subheader_offset), SEEK_SET);
if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
goto fail;
if (strncmp(header.magic, "cxsparse", 8))
goto fail;
bs->total_sectors = ((uint64_t)be32_to_cpu(header.type.sparse.pagetable_entries) *
be32_to_cpu(header.type.sparse.pageentry_size)) / 512;
lseek(s->fd, be32_to_cpu(header.type.sparse.pagetable_offset), SEEK_SET);
s->pagetable_entries = be32_to_cpu(header.type.sparse.pagetable_entries);
s->pagetable = qemu_malloc(s->pagetable_entries * 4);
if (!s->pagetable)
goto fail;
if (read(s->fd, s->pagetable, s->pagetable_entries * 4) !=
s->pagetable_entries * 4)
goto fail;
for (i = 0; i < s->pagetable_entries; i++)
be32_to_cpus(&s->pagetable[i]);
s->pageentry_size = be32_to_cpu(header.type.sparse.pageentry_size);
#ifdef CACHE
s->pageentry_u8 = qemu_malloc(512);
if (!s->pageentry_u8)
goto fail;
s->pageentry_u32 = s->pageentry_u8;
s->pageentry_u16 = s->pageentry_u8;
s->last_pagetable = -1;
#endif
return 0;
fail:
close(fd);
return -1;
}
static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
{
BDRVVPCState *s = bs->opaque;
uint64_t offset = sector_num * 512;
uint64_t bitmap_offset, block_offset;
uint32_t pagetable_index, pageentry_index;
pagetable_index = offset / s->pageentry_size;
pageentry_index = (offset % s->pageentry_size) / 512;
if (pagetable_index > s->pagetable_entries || s->pagetable[pagetable_index] == 0xffffffff)
return -1; // not allocated
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",
// sector_num, pagetable_index, pageentry_index,
// bitmap_offset, block_offset);
// disabled by reason
#if 0
#ifdef CACHE
if (bitmap_offset != s->last_bitmap)
{
lseek(s->fd, bitmap_offset, SEEK_SET);
s->last_bitmap = bitmap_offset;
// Scary! Bitmap is stored as big endian 32bit entries,
// while we used to look it up byte by byte
read(s->fd, s->pageentry_u8, 512);
for (i = 0; i < 128; i++)
be32_to_cpus(&s->pageentry_u32[i]);
}
if ((s->pageentry_u8[pageentry_index / 8] >> (pageentry_index % 8)) & 1)
return -1;
#else
lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
read(s->fd, &bitmap_entry, 1);
if ((bitmap_entry >> (pageentry_index % 8)) & 1)
return -1; // not allocated
#endif
#endif
lseek(s->fd, block_offset, SEEK_SET);
return 0;
}
static int vpc_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVPCState *s = bs->opaque;
int ret;
while (nb_sectors > 0) {
if (!seek_to_sector(bs, sector_num))
{
ret = read(s->fd, buf, 512);
if (ret != 512)
return -1;
}
else
memset(buf, 0, 512);
nb_sectors--;
sector_num++;
buf += 512;
}
return 0;
}
static void vpc_close(BlockDriverState *bs)
{
BDRVVPCState *s = bs->opaque;
qemu_free(s->pagetable);
#ifdef CACHE
qemu_free(s->pageentry_u8);
#endif
close(s->fd);
}
BlockDriver bdrv_vpc = {
"vpc",
sizeof(BDRVVPCState),
vpc_probe,
vpc_open,
vpc_read,
NULL,
vpc_close,
};

2807
block-vvfat.c Normal file

File diff suppressed because it is too large Load Diff

957
block.c

File diff suppressed because it is too large Load Diff

80
block_int.h Normal file
View File

@@ -0,0 +1,80 @@
/*
* QEMU System Emulator block driver
*
* Copyright (c) 2003 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.
*/
#ifndef BLOCK_INT_H
#define BLOCK_INT_H
struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename);
int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum);
int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
int (*bdrv_make_empty)(BlockDriverState *bs);
struct BlockDriver *next;
};
struct BlockDriverState {
int64_t total_sectors;
int read_only; /* if true, the media is read only */
int inserted; /* if true, the media is present */
int removable; /* if true, the media can be removed */
int locked; /* if true, the media cannot temporarily be ejected */
int encrypted; /* if true, the media is encrypted */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void *change_opaque;
BlockDriver *drv;
void *opaque;
int boot_sector_enabled;
uint8_t boot_sector_data[512];
char filename[1024];
char backing_file[1024]; /* if non zero, the image is a diff of
this file image */
int is_temporary;
BlockDriverState *backing_hd;
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
int type;
char device_name[32];
BlockDriverState *next;
};
void get_tmp_filename(char *filename, int size);
#endif /* BLOCK_INT_H */

134
bswap.h
View File

@@ -43,14 +43,6 @@
#endif /* !HAVE_BYTESWAP_H */
#if defined(__alpha__) || defined (__ia64__)
#define HOST_LONG_BITS 64
#else
#define HOST_LONG_BITS 32
#endif
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
@@ -81,4 +73,130 @@ static inline void bswap64s(uint64_t *s)
*s = bswap64(*s);
}
#if defined(WORDS_BIGENDIAN)
#define be_bswap(v, size) (v)
#define le_bswap(v, size) bswap ## size(v)
#define be_bswaps(v, size)
#define le_bswaps(p, size) *p = bswap ## size(*p);
#else
#define le_bswap(v, size) (v)
#define be_bswap(v, size) bswap ## size(v)
#define le_bswaps(v, size)
#define be_bswaps(p, size) *p = bswap ## size(*p);
#endif
#define CPU_CONVERT(endian, size, type)\
static inline type endian ## size ## _to_cpu(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline type cpu_to_ ## endian ## size(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline void endian ## size ## _to_cpus(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline void cpu_to_ ## endian ## size ## s(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline type endian ## size ## _to_cpup(const type *p)\
{\
return endian ## size ## _to_cpu(*p);\
}\
\
static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
{\
*p = cpu_to_ ## endian ## size(v);\
}
CPU_CONVERT(be, 16, uint16_t)
CPU_CONVERT(be, 32, uint32_t)
CPU_CONVERT(be, 64, uint64_t)
CPU_CONVERT(le, 16, uint16_t)
CPU_CONVERT(le, 32, uint32_t)
CPU_CONVERT(le, 64, uint64_t)
/* unaligned versions (optimized for frequent unaligned accesses)*/
#if defined(__i386__) || defined(__powerpc__)
#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
#define le16_to_cpupu(p) le16_to_cpup(p)
#define le32_to_cpupu(p) le32_to_cpup(p)
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
#else
static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
}
static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
p1[2] = v >> 16;
p1[3] = v >> 24;
}
static inline uint16_t le16_to_cpupu(const uint16_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8);
}
static inline uint32_t le32_to_cpupu(const uint32_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
}
static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 8;
p1[1] = v;
}
static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 24;
p1[1] = v >> 16;
p1[2] = v >> 8;
p1[3] = v;
}
#endif
#ifdef WORDS_BIGENDIAN
#define cpu_to_32wu cpu_to_be32wu
#else
#define cpu_to_32wu cpu_to_le32wu
#endif
#undef le_bswap
#undef be_bswap
#undef le_bswaps
#undef be_bswaps
#endif /* BSWAP_H */

911
cocoa.m Normal file
View File

@@ -0,0 +1,911 @@
/*
* QEMU Cocoa display driver
*
* Copyright (c) 2005 Pierre d'Herbemont
* many code/inspiration from SDL 1.2 code (LGPL)
*
* 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.
*/
/*
Todo : x miniaturize window
x center the window
- save window position
- handle keyboard event
- handle mouse event
- non 32 bpp support
- full screen
- mouse focus
x simple graphical prompt to demo
- better graphical prompt
*/
#import <Cocoa/Cocoa.h>
#include "vl.h"
NSWindow *window = NULL;
NSQuickDrawView *qd_view = NULL;
int gArgc;
char **gArgv;
DisplayState current_ds;
int grab = 0;
int modifiers_state[256];
/* main defined in qemu/vl.c */
int qemu_main(int argc, char **argv);
/* To deal with miniaturization */
@interface QemuWindow : NSWindow
{ }
@end
/*
------------------------------------------------------
Qemu Video Driver
------------------------------------------------------
*/
/*
------------------------------------------------------
cocoa_update
------------------------------------------------------
*/
static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
{
//printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
/* Use QDFlushPortBuffer() to flush content to display */
RgnHandle dirty = NewRgn ();
RgnHandle temp = NewRgn ();
SetEmptyRgn (dirty);
/* Build the region of dirty rectangles */
MacSetRectRgn (temp, x, y,
x + w, y + h);
MacUnionRgn (dirty, temp, dirty);
/* Flush the dirty region */
QDFlushPortBuffer ( [ qd_view qdPort ], dirty );
DisposeRgn (dirty);
DisposeRgn (temp);
}
/*
------------------------------------------------------
cocoa_resize
------------------------------------------------------
*/
static void cocoa_resize(DisplayState *ds, int w, int h)
{
const int device_bpp = 32;
static void *screen_pixels;
static int screen_pitch;
NSRect contentRect;
//printf("resizing to %d %d\n", w, h);
contentRect = NSMakeRect (0, 0, w, h);
if(window)
{
[window close];
[window release];
}
window = [ [ QemuWindow alloc ] initWithContentRect:contentRect
styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask
backing:NSBackingStoreBuffered defer:NO];
if(!window)
{
fprintf(stderr, "(cocoa) can't create window\n");
exit(1);
}
if(qd_view)
[qd_view release];
qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
if(!qd_view)
{
fprintf(stderr, "(cocoa) can't create qd_view\n");
exit(1);
}
[ window setAcceptsMouseMovedEvents:YES ];
[ window setTitle:@"Qemu" ];
[ window setReleasedWhenClosed:NO ];
/* Set screen to black */
[ window setBackgroundColor: [NSColor blackColor] ];
/* set window position */
[ window center ];
[ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
[ [ window contentView ] addSubview:qd_view ];
[ qd_view release ];
[ window makeKeyAndOrderFront:nil ];
/* Careful here, the window seems to have to be onscreen to do that */
LockPortBits ( [ qd_view qdPort ] );
screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) );
screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) );
UnlockPortBits ( [ qd_view qdPort ] );
{
int vOffset = [ window frame ].size.height -
[ qd_view frame ].size.height - [ qd_view frame ].origin.y;
int hOffset = [ qd_view frame ].origin.x;
screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
}
ds->data = screen_pixels;
ds->linesize = screen_pitch;
ds->depth = device_bpp;
ds->width = w;
ds->height = h;
current_ds = *ds;
}
/*
------------------------------------------------------
keymap conversion
------------------------------------------------------
*/
int keymap[] =
{
// SdlI macI macH SdlH 104xtH 104xtC sdl
30, // 0 0x00 0x1e A QZ_a
31, // 1 0x01 0x1f S QZ_s
32, // 2 0x02 0x20 D QZ_d
33, // 3 0x03 0x21 F QZ_f
35, // 4 0x04 0x23 H QZ_h
34, // 5 0x05 0x22 G QZ_g
44, // 6 0x06 0x2c Z QZ_z
45, // 7 0x07 0x2d X QZ_x
46, // 8 0x08 0x2e C QZ_c
47, // 9 0x09 0x2f V QZ_v
0, // 10 0x0A Undefined
48, // 11 0x0B 0x30 B QZ_b
16, // 12 0x0C 0x10 Q QZ_q
17, // 13 0x0D 0x11 W QZ_w
18, // 14 0x0E 0x12 E QZ_e
19, // 15 0x0F 0x13 R QZ_r
21, // 16 0x10 0x15 Y QZ_y
20, // 17 0x11 0x14 T QZ_t
2, // 18 0x12 0x02 1 QZ_1
3, // 19 0x13 0x03 2 QZ_2
4, // 20 0x14 0x04 3 QZ_3
5, // 21 0x15 0x05 4 QZ_4
7, // 22 0x16 0x07 6 QZ_6
6, // 23 0x17 0x06 5 QZ_5
13, // 24 0x18 0x0d = QZ_EQUALS
10, // 25 0x19 0x0a 9 QZ_9
8, // 26 0x1A 0x08 7 QZ_7
12, // 27 0x1B 0x0c - QZ_MINUS
9, // 28 0x1C 0x09 8 QZ_8
11, // 29 0x1D 0x0b 0 QZ_0
27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET
24, // 31 0x1F 0x18 O QZ_o
22, // 32 0x20 0x16 U QZ_u
26, // 33 0x21 0x1a [ QZ_LEFTBRACKET
23, // 34 0x22 0x17 I QZ_i
25, // 35 0x23 0x19 P QZ_p
28, // 36 0x24 0x1c ENTER QZ_RETURN
38, // 37 0x25 0x26 L QZ_l
36, // 38 0x26 0x24 J QZ_j
40, // 39 0x27 0x28 ' QZ_QUOTE
37, // 40 0x28 0x25 K QZ_k
39, // 41 0x29 0x27 ; QZ_SEMICOLON
43, // 42 0x2A 0x2b \ QZ_BACKSLASH
51, // 43 0x2B 0x33 , QZ_COMMA
53, // 44 0x2C 0x35 / QZ_SLASH
49, // 45 0x2D 0x31 N QZ_n
50, // 46 0x2E 0x32 M QZ_m
52, // 47 0x2F 0x34 . QZ_PERIOD
15, // 48 0x30 0x0f TAB QZ_TAB
57, // 49 0x31 0x39 SPACE QZ_SPACE
41, // 50 0x32 0x29 ` QZ_BACKQUOTE
14, // 51 0x33 0x0e BKSP QZ_BACKSPACE
0, // 52 0x34 Undefined
1, // 53 0x35 0x01 ESC QZ_ESCAPE
0, // 54 0x36 QZ_RMETA
0, // 55 0x37 QZ_LMETA
42, // 56 0x38 0x2a L SHFT QZ_LSHIFT
58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK
56, // 58 0x3A 0x38 L ALT QZ_LALT
29, // 59 0x3B 0x1d L CTRL QZ_LCTRL
54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT
184,// 61 0x3D 0xb8 E0,38 R ALT QZ_RALT
157,// 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL
0, // 63 0x3F Undefined
0, // 64 0x40 Undefined
0, // 65 0x41 Undefined
0, // 66 0x42 Undefined
55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY
0, // 68 0x44 Undefined
78, // 69 0x45 0x4e KP + QZ_KP_PLUS
0, // 70 0x46 Undefined
69, // 71 0x47 0x45 NUM QZ_NUMLOCK
0, // 72 0x48 Undefined
0, // 73 0x49 Undefined
0, // 74 0x4A Undefined
181,// 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE
152,// 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER
0, // 77 0x4D undefined
74, // 78 0x4E 0x4a KP - QZ_KP_MINUS
0, // 79 0x4F Undefined
0, // 80 0x50 Undefined
0, // 81 0x51 QZ_KP_EQUALS
82, // 82 0x52 0x52 KP 0 QZ_KP0
79, // 83 0x53 0x4f KP 1 QZ_KP1
80, // 84 0x54 0x50 KP 2 QZ_KP2
81, // 85 0x55 0x51 KP 3 QZ_KP3
75, // 86 0x56 0x4b KP 4 QZ_KP4
76, // 87 0x57 0x4c KP 5 QZ_KP5
77, // 88 0x58 0x4d KP 6 QZ_KP6
71, // 89 0x59 0x47 KP 7 QZ_KP7
0, // 90 0x5A Undefined
72, // 91 0x5B 0x48 KP 8 QZ_KP8
73, // 92 0x5C 0x49 KP 9 QZ_KP9
0, // 93 0x5D Undefined
0, // 94 0x5E Undefined
0, // 95 0x5F Undefined
63, // 96 0x60 0x3f F5 QZ_F5
64, // 97 0x61 0x40 F6 QZ_F6
65, // 98 0x62 0x41 F7 QZ_F7
61, // 99 0x63 0x3d F3 QZ_F3
66, // 100 0x64 0x42 F8 QZ_F8
67, // 101 0x65 0x43 F9 QZ_F9
0, // 102 0x66 Undefined
87, // 103 0x67 0x57 F11 QZ_F11
0, // 104 0x68 Undefined
183,// 105 0x69 0xb7 QZ_PRINT
0, // 106 0x6A Undefined
70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK
0, // 108 0x6C Undefined
68, // 109 0x6D 0x44 F10 QZ_F10
0, // 110 0x6E Undefined
88, // 111 0x6F 0x58 F12 QZ_F12
0, // 112 0x70 Undefined
110,// 113 0x71 0x0 QZ_PAUSE
210,// 114 0x72 0xd2 E0,52 INSERT QZ_INSERT
199,// 115 0x73 0xc7 E0,47 HOME QZ_HOME
201,// 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP
211,// 117 0x75 0xd3 E0,53 DELETE QZ_DELETE
62, // 118 0x76 0x3e F4 QZ_F4
207,// 119 0x77 0xcf E0,4f END QZ_END
60, // 120 0x78 0x3c F2 QZ_F2
209,// 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN
59, // 122 0x7A 0x3b F1 QZ_F1
203,// 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT
205,// 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT
208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN
200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP
/* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
/*
219 // 0xdb e0,5b L GUI
220 // 0xdc e0,5c R GUI
221 // 0xdd e0,5d APPS
// E0,2A,E0,37 PRNT SCRN
// E1,1D,45,E1,9D,C5 PAUSE
83 // 0x53 0x53 KP .
// ACPI Scan Codes
222 // 0xde E0, 5E Power
223 // 0xdf E0, 5F Sleep
227 // 0xe3 E0, 63 Wake
// Windows Multimedia Scan Codes
153 // 0x99 E0, 19 Next Track
144 // 0x90 E0, 10 Previous Track
164 // 0xa4 E0, 24 Stop
162 // 0xa2 E0, 22 Play/Pause
160 // 0xa0 E0, 20 Mute
176 // 0xb0 E0, 30 Volume Up
174 // 0xae E0, 2E Volume Down
237 // 0xed E0, 6D Media Select
236 // 0xec E0, 6C E-Mail
161 // 0xa1 E0, 21 Calculator
235 // 0xeb E0, 6B My Computer
229 // 0xe5 E0, 65 WWW Search
178 // 0xb2 E0, 32 WWW Home
234 // 0xea E0, 6A WWW Back
233 // 0xe9 E0, 69 WWW Forward
232 // 0xe8 E0, 68 WWW Stop
231 // 0xe7 E0, 67 WWW Refresh
230 // 0xe6 E0, 66 WWW Favorites
*/
};
int cocoa_keycode_to_qemu(int keycode)
{
if((sizeof(keymap)/sizeof(int)) <= keycode)
{
printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
return 0;
}
return keymap[keycode];
}
/*
------------------------------------------------------
cocoa_refresh
------------------------------------------------------
*/
static void cocoa_refresh(DisplayState *ds)
{
//printf("cocoa_refresh \n");
NSDate *distantPast;
NSEvent *event;
NSAutoreleasePool *pool;
pool = [ [ NSAutoreleasePool alloc ] init ];
distantPast = [ NSDate distantPast ];
vga_hw_update();
do {
event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
inMode: NSDefaultRunLoopMode dequeue:YES ];
if (event != nil) {
switch ([event type]) {
case NSFlagsChanged:
{
int keycode = cocoa_keycode_to_qemu([event keyCode]);
if (keycode)
{
if (keycode == 58 || keycode == 69) {
/* emulate caps lock and num lock keydown and keyup */
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | 0x80);
} else if (is_graphic_console()) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (modifiers_state[keycode] == 0) {
/* keydown */
kbd_put_keycode(keycode & 0x7f);
modifiers_state[keycode] = 1;
} else {
/* keyup */
kbd_put_keycode(keycode | 0x80);
modifiers_state[keycode] = 0;
}
}
}
/* release Mouse grab when pressing ctrl+alt */
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask))
{
[window setTitle: @"QEMU"];
[NSCursor unhide];
CGAssociateMouseAndMouseCursorPosition ( TRUE );
grab = 0;
}
}
break;
case NSKeyDown:
{
int keycode = cocoa_keycode_to_qemu([event keyCode]);
/* handle command Key Combos */
if ([event modifierFlags] & NSCommandKeyMask) {
switch ([event keyCode]) {
/* quit */
case 12: /* q key */
/* switch to windowed View */
exit(0);
return;
}
}
/* handle control + alt Key Combos */
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
switch (keycode) {
/* toggle Monitor */
case 0x02 ... 0x0a: /* '1' to '9' keys */
console_select(keycode - 0x02);
break;
}
} else {
/* handle standard key events */
if (is_graphic_console()) {
if (keycode & 0x80) //check bit for e0 in front
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
/* handle monitor key events */
} else {
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;
}
}
}
}
break;
case NSKeyUp:
{
int keycode = cocoa_keycode_to_qemu([event keyCode]);
if (is_graphic_console()) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
}
}
break;
case NSMouseMoved:
if (grab) {
int dx = [event deltaX];
int dy = [event deltaY];
int dz = [event deltaZ];
int buttons = 0;
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
case NSLeftMouseDown:
if (grab) {
int buttons = 0;
/* leftclick+command simulates rightclick */
if ([event modifierFlags] & NSCommandKeyMask) {
buttons |= MOUSE_EVENT_RBUTTON;
} else {
buttons |= MOUSE_EVENT_LBUTTON;
}
kbd_mouse_event(0, 0, 0, buttons);
} else {
[NSApp sendEvent: event];
}
break;
case NSLeftMouseDragged:
if (grab) {
int dx = [event deltaX];
int dy = [event deltaY];
int dz = [event deltaZ];
int buttons = 0;
if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) { //leftclick+command simulates rightclick
buttons |= MOUSE_EVENT_RBUTTON;
} else {
buttons |= MOUSE_EVENT_LBUTTON;
}
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
case NSLeftMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
} else {
[window setTitle: @"QEMU (Press ctrl + alt to release Mouse)"];
[NSCursor hide];
CGAssociateMouseAndMouseCursorPosition ( FALSE );
grab = 1;
//[NSApp sendEvent: event];
}
break;
case NSRightMouseDown:
if (grab) {
int buttons = 0;
buttons |= MOUSE_EVENT_RBUTTON;
kbd_mouse_event(0, 0, 0, buttons);
} else {
[NSApp sendEvent: event];
}
break;
case NSRightMouseDragged:
if (grab) {
int dx = [event deltaX];
int dy = [event deltaY];
int dz = [event deltaZ];
int buttons = 0;
buttons |= MOUSE_EVENT_RBUTTON;
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
case NSRightMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
} else {
[NSApp sendEvent: event];
}
break;
case NSOtherMouseDragged:
if (grab) {
int dx = [event deltaX];
int dy = [event deltaY];
int dz = [event deltaZ];
int buttons = 0;
buttons |= MOUSE_EVENT_MBUTTON;
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
case NSOtherMouseDown:
if (grab) {
int buttons = 0;
buttons |= MOUSE_EVENT_MBUTTON;
kbd_mouse_event(0, 0, 0, buttons);
} else {
[NSApp sendEvent:event];
}
break;
case NSOtherMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
} else {
[NSApp sendEvent: event];
}
break;
case NSScrollWheel:
if (grab) {
int dz = [event deltaY];
kbd_mouse_event(0, 0, -dz, 0);
}
break;
default: [NSApp sendEvent:event];
}
}
} while(event != nil);
}
/*
------------------------------------------------------
cocoa_cleanup
------------------------------------------------------
*/
static void cocoa_cleanup(void)
{
}
/*
------------------------------------------------------
cocoa_display_init
------------------------------------------------------
*/
void cocoa_display_init(DisplayState *ds, int full_screen)
{
ds->dpy_update = cocoa_update;
ds->dpy_resize = cocoa_resize;
ds->dpy_refresh = cocoa_refresh;
cocoa_resize(ds, 640, 400);
atexit(cocoa_cleanup);
}
/*
------------------------------------------------------
Interface with Cocoa
------------------------------------------------------
*/
/*
------------------------------------------------------
QemuWindow
Some trick from SDL to use miniwindow
------------------------------------------------------
*/
static void QZ_SetPortAlphaOpaque ()
{
/* Assume 32 bit if( bpp == 32 )*/
if ( 1 ) {
uint32_t *pixels = (uint32_t*) current_ds.data;
uint32_t rowPixels = current_ds.linesize / 4;
uint32_t i, j;
for (i = 0; i < current_ds.height; i++)
for (j = 0; j < current_ds.width; j++) {
pixels[ (i * rowPixels) + j ] |= 0xFF000000;
}
}
}
@implementation QemuWindow
- (void)miniaturize:(id)sender
{
/* make the alpha channel opaque so anim won't have holes in it */
QZ_SetPortAlphaOpaque ();
[ super miniaturize:sender ];
}
- (void)display
{
/*
This method fires just before the window deminaturizes from the Dock.
We'll save the current visible surface, let the window manager redraw any
UI elements, and restore the SDL surface. This way, no expose event
is required, and the deminiaturize works perfectly.
*/
/* make sure pixels are fully opaque */
QZ_SetPortAlphaOpaque ();
/* save current visible SDL surface */
[ self cacheImageInRect:[ qd_view frame ] ];
/* let the window manager redraw controls, border, etc */
[ super display ];
/* restore visible SDL surface */
[ self restoreCachedImage ];
}
@end
/*
------------------------------------------------------
QemuCocoaGUIController
NSApp's delegate - indeed main object
------------------------------------------------------
*/
@interface QemuCocoaGUIController : NSObject
{
}
- (void)applicationDidFinishLaunching: (NSNotification *) note;
- (void)applicationWillTerminate:(NSNotification *)aNotification;
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
@end
@implementation QemuCocoaGUIController
/* Called when the internal event loop has just started running */
- (void)applicationDidFinishLaunching: (NSNotification *) note
{
/* Display an open dialog box if no argument were passed or
if qemu was launched from the finder ( the Finder passes "-psn" ) */
if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
{
NSOpenPanel *op = [[NSOpenPanel alloc] init];
cocoa_resize(&current_ds, 640, 400);
[op setPrompt:@"Boot image"];
[op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
[op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
modalForWindow:window modalDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
else
{
/* or Launch Qemu, with the global args */
[self startEmulationWithArgc:gArgc argv:gArgv];
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
printf("Application will terminate\n");
qemu_system_shutdown_request();
/* In order to avoid a crash */
exit(0);
}
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
if(returnCode == NSCancelButton)
{
exit(0);
}
if(returnCode == NSOKButton)
{
char *bin = "qemu";
char *img = (char*)[ [ sheet filename ] cString];
char **argv = (char**)malloc( sizeof(char*)*3 );
asprintf(&argv[0], "%s", bin);
asprintf(&argv[1], "-hda");
asprintf(&argv[2], "%s", img);
printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
[self startEmulationWithArgc:3 argv:(char**)argv];
}
}
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
{
int status;
/* Launch Qemu */
printf("starting qemu...\n");
status = qemu_main (argc, argv);
exit(status);
}
@end
/*
------------------------------------------------------
Application Creation
------------------------------------------------------
*/
/* Dock Connection */
typedef struct CPSProcessSerNum
{
UInt32 lo;
UInt32 hi;
} CPSProcessSerNum;
extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
/* Menu Creation */
static void setApplicationMenu(void)
{
/* warning: this code is very odd */
NSMenu *appleMenu;
NSMenuItem *menuItem;
NSString *title;
NSString *appName;
appName = @"Qemu";
appleMenu = [[NSMenu alloc] initWithTitle:@""];
/* Add menu items */
title = [@"About " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
[appleMenu addItem:[NSMenuItem separatorItem]];
title = [@"Hide " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
[appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
[appleMenu addItem:[NSMenuItem separatorItem]];
title = [@"Quit " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
/* Put menu into the menubar */
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
[menuItem setSubmenu:appleMenu];
[[NSApp mainMenu] addItem:menuItem];
/* Tell the application object that this is now the application menu */
[NSApp setAppleMenu:appleMenu];
/* Finally give up our references to the objects */
[appleMenu release];
[menuItem release];
}
/* Create a window menu */
static void setupWindowMenu(void)
{
NSMenu *windowMenu;
NSMenuItem *windowMenuItem;
NSMenuItem *menuItem;
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
/* "Minimize" item */
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
[windowMenu addItem:menuItem];
[menuItem release];
/* Put menu into the menubar */
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
[windowMenuItem setSubmenu:windowMenu];
[[NSApp mainMenu] addItem:windowMenuItem];
/* Tell the application object that this is now the window menu */
[NSApp setWindowsMenu:windowMenu];
/* Finally give up our references to the objects */
[windowMenu release];
[windowMenuItem release];
}
static void CustomApplicationMain (argc, argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QemuCocoaGUIController *gui_controller;
CPSProcessSerNum PSN;
[NSApplication sharedApplication];
if (!CPSGetCurrentProcess(&PSN))
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
if (!CPSSetFrontProcess(&PSN))
[NSApplication sharedApplication];
/* Set up the menubar */
[NSApp setMainMenu:[[NSMenu alloc] init]];
setApplicationMenu();
setupWindowMenu();
/* Create SDLMain and make it the app delegate */
gui_controller = [[QemuCocoaGUIController alloc] init];
[NSApp setDelegate:gui_controller];
/* Start the main event loop */
[NSApp run];
[gui_controller release];
[pool release];
}
/* Real main of qemu-cocoa */
int main(int argc, char **argv)
{
gArgc = argc;
gArgv = argv;
CustomApplicationMain (argc, argv);
return 0;
}

698
configure vendored
View File

@@ -17,7 +17,7 @@ TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
# default parameters
prefix="/usr/local"
prefix=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_prefix=""
@@ -25,14 +25,18 @@ cc="gcc"
host_cc="gcc"
ar="ar"
make="make"
install="install"
strip="strip"
cpu=`uname -m`
target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user"
target_list=""
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC)
cpu="i386"
;;
armv4l)
armv*b)
cpu="armv4b"
;;
armv*l)
cpu="armv4l"
;;
alpha)
@@ -47,7 +51,7 @@ case "$cpu" in
s390)
cpu="s390"
;;
sparc)
sparc|sun4[muv])
cpu="sparc"
;;
sparc64)
@@ -59,73 +63,135 @@ case "$cpu" in
m68k)
cpu="m68k"
;;
x86_64|amd64)
cpu="x86_64"
;;
*)
cpu="unknown"
;;
esac
gprof="no"
bigendian="no"
mingw32="no"
EXESUF=""
gdbstub="yes"
slirp="yes"
adlib="no"
oss="no"
dsound="no"
coreaudio="no"
alsa="no"
fmod="no"
fmod_lib=""
fmod_inc=""
bsd="no"
linux="no"
kqemu="no"
profiler="no"
kernel_path=""
cocoa="no"
check_gfx="yes"
check_gcc="yes"
softmmu="yes"
user="no"
build_docs="no"
# OS specific
targetos=`uname -s`
case $targetos in
*) ;;
CYGWIN*)
mingw32="yes"
CFLAGS="-O2 -mno-cygwin"
;;
MINGW32*)
mingw32="yes"
;;
FreeBSD)
bsd="yes"
oss="yes"
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
kqemu="yes"
fi
;;
NetBSD)
bsd="yes"
oss="yes"
;;
OpenBSD)
bsd="yes"
oss="yes"
;;
Darwin)
bsd="yes"
darwin="yes"
;;
SunOS)
solaris="yes"
;;
*)
oss="yes"
linux="yes"
user="yes"
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
kqemu="yes"
fi
;;
esac
##########################################
# SDL probe
cat > $TMPC << EOF
#include <SDL.h>
#undef main /* We don't want SDL to override our main() */
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
sdl_too_old=no
sdl=no
if $cc -o $TMPE `sdl-config --cflags` $TMPC `sdl-config --libs` 2> /dev/null ; then
_sdlversion=`sdl-config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
sdl=yes
if [ "$bsd" = "yes" ] ; then
if [ "$darwin" != "yes" ] ; then
make="gmake"
fi
fi
if [ "$solaris" = "yes" ] ; then
make="gmake"
install="ginstall"
solarisrev=`uname -r | cut -f2 -d.`
fi
# find source path
# XXX: we assume an absolute path is given when launching configure,
# except in './configure' case.
source_path=${0%configure}
source_path=${source_path%/}
source_path_used="yes"
if test -z "$source_path" -o "$source_path" = "." ; then
source_path=`dirname "$0"`
if [ -z "$source_path" ]; then
source_path=`pwd`
else
source_path=`cd "$source_path"; pwd`
fi
if test "$source_path" = `pwd` ; then
source_path_used="no"
else
source_path_used="yes"
fi
for opt do
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
case "$opt" in
--prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
--help|-h) show_help=yes
;;
--interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2`
--prefix=*) prefix="$optarg"
;;
--source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
--interp-prefix=*) interp_prefix="$optarg"
;;
--cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
--source-path=*) source_path="$optarg"
source_path_used="yes"
;;
--cc=*) cc=`echo $opt | cut -d '=' -f 2`
--cross-prefix=*) cross_prefix="$optarg"
;;
--make=*) make=`echo $opt | cut -d '=' -f 2`
--cc=*) cc="$optarg"
;;
--extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
--host-cc=*) host_cc="$optarg"
;;
--extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
--make=*) make="$optarg"
;;
--extra-libs=*) extralibs=${opt#--extra-libs=}
--install=*) install="$optarg"
;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
--extra-cflags=*) CFLAGS="$optarg"
;;
--target-list=*) target_list=${opt#--target-list=}
--extra-ldflags=*) LDFLAGS="$optarg"
;;
--cpu=*) cpu="$optarg"
;;
--target-list=*) target_list="$optarg"
;;
--enable-gprof) gprof="yes"
;;
@@ -133,6 +199,44 @@ for opt do
;;
--disable-sdl) sdl="no"
;;
--enable-coreaudio) coreaudio="yes"
;;
--enable-alsa) alsa="yes"
;;
--enable-dsound) dsound="yes"
;;
--enable-fmod) fmod="yes"
;;
--fmod-lib=*) fmod_lib="$optarg"
;;
--fmod-inc=*) fmod_inc="$optarg"
;;
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
;;
--disable-slirp) slirp="no"
;;
--enable-adlib) adlib="yes"
;;
--disable-kqemu) kqemu="no"
;;
--enable-profiler) profiler="yes"
;;
--kernel-path=*) kernel_path="$optarg"
;;
--enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
;;
--disable-gfx-check) check_gfx="no"
;;
--disable-gcc-check) check_gcc="no"
;;
--disable-system) softmmu="no"
;;
--enable-system) softmmu="yes"
;;
--disable-user) user="no"
;;
--enable-user) user="yes"
;;
esac
done
@@ -141,49 +245,7 @@ if test -z "$CFLAGS"; then
CFLAGS="-O2"
fi
cc="${cross_prefix}${cc}"
ar="${cross_prefix}${ar}"
strip="${cross_prefix}${strip}"
if test -z "$cross_prefix" ; then
# ---
# big/little endian test
cat > $TMPC << EOF
#include <inttypes.h>
int main(int argc, char ** argv){
volatile uint32_t i=0x01234567;
return (*((uint8_t*)(&i))) == 0x67;
}
EOF
if $cc -o $TMPE $TMPC 2>/dev/null ; then
$TMPE && bigendian="yes"
else
echo big/little test failed
fi
else
# if cross compiling, cannot launch a program, so make a static guess
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then
bigendian="yes"
fi
fi
# check gcc options support
cat > $TMPC <<EOF
int main(void) {
}
EOF
have_gcc3_options="no"
if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
have_gcc3_options="yes"
fi
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
if test x"$show_help" = x"yes" ; then
cat << EOF
Usage: configure [options]
@@ -197,50 +259,317 @@ echo " --interp-prefix=PREFIX where to find shared libraries, etc."
echo " use %M for cpu name [$interp_prefix]"
echo " --target-list=LIST set target list [$target_list]"
echo ""
echo "kqemu kernel acceleration support:"
echo " --disable-kqemu disable kqemu support"
echo " --kernel-path=PATH set the kernel path (configure probes it)"
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
echo " --host-cc=CC use C compiler CC [$host_cc] for dyngen etc."
echo " --make=MAKE use specified make [$make]"
echo " --install=INSTALL use specified install [$install]"
echo " --static enable static build [$static]"
echo " --enable-cocoa enable COCOA (Mac OS X only)"
echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
echo " --enable-adlib enable Adlib emulation"
echo " --enable-coreaudio enable Coreaudio audio driver"
echo " --enable-alsa enable ALSA audio driver"
echo " --enable-fmod enable FMOD audio driver"
echo " --enabled-dsound enable DirectSound audio driver"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
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 ""
echo "NOTE: The object files are build at the place where configure is launched"
exit 1
fi
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
fi
if test "$mingw32" = "yes" ; then
linux="no"
EXESUF=".exe"
gdbstub="no"
oss="no"
if [ "$cpu" = "i386" ] ; then
kqemu="yes"
fi
fi
#
# Solaris specific configure tool chain decisions
#
if test "$solaris" = "yes" ; then
#
# gcc for solaris 10/fcs in /usr/sfw/bin doesn't compile qemu correctly
# override the check with --disable-gcc-check
#
if test "$solarisrev" -eq 10 -a "$check_gcc" = "yes" ; then
solgcc=`which $cc`
if test "$solgcc" = "/usr/sfw/bin/gcc" ; then
echo "Solaris 10/FCS gcc in /usr/sfw/bin will not compiled qemu correctly."
echo "please get gcc-3.4.3 or later, from www.blastwave.org using pkg-get -i gcc3"
echo "or get the latest patch from SunSolve for gcc"
exit 1
fi
fi
solinst=`which $install 2> /dev/null | /usr/bin/grep -v "no $install in"`
if test -z "$solinst" ; then
echo "Solaris install program not found. Use --install=/usr/ucb/install or"
echo "install fileutils from www.blastwave.org using pkg-get -i fileutils"
echo "to get ginstall which is used by default (which lives in /opt/csw/bin)"
exit 1
fi
if test "$solinst" = "/usr/sbin/install" ; then
echo "Error: Solaris /usr/sbin/install is not an appropriate install program."
echo "try ginstall from the GNU fileutils available from www.blastwave.org"
echo "using pkg-get -i fileutils, or use --install=/usr/ucb/install"
exit 1
fi
sol_ar=`which ar 2> /dev/null | /usr/bin/grep -v "no ar in"`
if test -z "$sol_ar" ; then
echo "Error: No path includes ar"
if test -f /usr/ccs/bin/ar ; then
echo "Add /usr/ccs/bin to your path and rerun configure"
fi
exit 1
fi
fi
if test -z "$target_list" ; then
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
fi
# the following are Linux specific
if [ "$user" = "yes" ] ; then
target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
fi
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
fi
if test -z "$target_list" ; then
echo "No targets enabled"
exit 1
fi
if test -z "$cross_prefix" ; then
# ---
# big/little endian test
cat > $TMPC << EOF
#include <inttypes.h>
int main(int argc, char ** argv){
volatile uint32_t i=0x01234567;
return (*((uint8_t*)(&i))) == 0x67;
}
EOF
if $cc -o $TMPE $TMPC 2>/dev/null ; then
$TMPE && bigendian="yes"
else
echo big/little test failed
fi
else
# if cross compiling, cannot launch a program, so make a static guess
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
bigendian="yes"
fi
fi
# host long bits test
hostlongbits="32"
if test "$cpu" = "sparc64" -o "$cpu" = "ia64" -o "$cpu" = "x86_64" -o "$cpu" = "alpha"; then
hostlongbits="64"
fi
# check gcc options support
cat > $TMPC <<EOF
int main(void) {
}
EOF
have_gcc3_options="no"
if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
have_gcc3_options="yes"
fi
# Check for gcc4, error if pre-gcc4
if test "$check_gcc" = "yes" ; then
cat > $TMPC <<EOF
#if __GNUC__ < 4
#error gcc3
#endif
int main(){return 0;}
EOF
if $cc -o $TMPO $TMPC 2>/dev/null ; then
echo "ERROR: \"$cc\" looks like gcc 4.x"
echo "QEMU is known to have problems when compiled with gcc 4.x"
echo "It is recommended that you use gcc 3.x to build QEMU"
echo "To use this compiler anyway, configure with --disable-gcc-check"
exit 1;
fi
fi
##########################################
# SDL probe
sdl_too_old=no
if test -z "$sdl" ; then
sdl_config="sdl-config"
sdl=no
sdl_static=no
if test "$mingw32" = "yes" -a ! -z "$cross_prefix" ; then
# win32 cross compilation case
sdl_config="i386-mingw32msvc-sdl-config"
sdl=yes
else
# normal SDL probe
cat > $TMPC << EOF
#include <SDL.h>
#undef main /* We don't want SDL to override our main() */
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /dev/null ; then
_sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
sdl=yes
fi
# static link with sdl ?
if test "$sdl" = "yes" ; then
aa="no"
`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
sdl_static_libs=`$sdl_config --static-libs`
if [ "$aa" = "yes" ] ; then
sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
fi
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then
sdl_static=yes
fi
fi # static link
fi # sdl compile test
fi # cross compilation
fi # -z $sdl
# Check if tools are available to build documentation.
if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
build_docs="yes"
fi
if test "$mingw32" = "yes" ; then
if test -z "$prefix" ; then
prefix="/c/Program Files/Qemu"
fi
mandir="$prefix"
datadir="$prefix"
docdir="$prefix"
bindir="$prefix"
else
if test -z "$prefix" ; then
prefix="/usr/local"
fi
mandir="$prefix/share/man"
sharedir="$prefix/share/qemu"
datadir="$prefix/share/qemu"
docdir="$prefix/share/doc/qemu"
bindir="$prefix/bin"
fi
echo "Install prefix $prefix"
echo "BIOS directory $datadir"
echo "binary directory $bindir"
if test "$mingw32" = "no" ; then
echo "Manual directory $mandir"
echo "BIOS directory $sharedir"
echo "ELF interp prefix $interp_prefix"
fi
echo "Source path $source_path"
echo "C compiler $cc"
echo "Host C compiler $host_cc"
echo "make $make"
echo "install $install"
echo "host CPU $cpu"
echo "host big endian $bigendian"
echo "target list $target_list"
echo "gprof enabled $gprof"
echo "profiler $profiler"
echo "static build $static"
echo "SDL support $sdl"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support"
if test "$darwin" = "yes" ; then
echo "Cocoa support $cocoa"
fi
echo "SDL support $sdl"
if test "$sdl" != "no" ; then
echo "SDL static link $sdl_static"
fi
echo "mingw32 support $mingw32"
echo "Adlib support $adlib"
echo "CoreAudio support $coreaudio"
echo "ALSA support $alsa"
echo "DSound support $dsound"
if test "$fmod" = "yes"; then
if test -z $fmod_lib || test -z $fmod_inc; then
echo
echo "Error: You must specify path to FMOD library and headers"
echo "Example: --fmod-inc=/path/include/fmod --fmod-lib=/path/lib/libfmod-3.74.so"
echo
exit 1
fi
fmod_support=" (lib='$fmod_lib' include='$fmod_inc')"
else
fmod_support=""
fi
echo "FMOD support $fmod $fmod_support"
echo "kqemu support $kqemu"
echo "Documentation $build_docs"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
fi
#if test "$sdl_static" = "no"; then
# echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output"
#fi
config_mak="config-host.mak"
config_h="config-host.h"
echo "Creating $config_mak and $config_h"
#echo "Creating $config_mak and $config_h"
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "# Configured with: $0 $@" >> $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "prefix=$prefix" >> $config_mak
echo "bindir=$bindir" >> $config_mak
echo "mandir=$mandir" >> $config_mak
echo "sharedir=$sharedir" >> $config_mak
echo "#define CONFIG_QEMU_SHAREDIR \"$sharedir\"" >> $config_h
echo "datadir=$datadir" >> $config_mak
echo "docdir=$docdir" >> $config_mak
echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
echo "MAKE=$make" >> $config_mak
echo "INSTALL=$install" >> $config_mak
echo "CC=$cc" >> $config_mak
if test "$have_gcc3_options" = "yes" ; then
echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
@@ -250,9 +579,16 @@ echo "AR=$ar" >> $config_mak
echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
if test "$cpu" = "i386" ; then
echo "ARCH=i386" >> $config_mak
echo "#define HOST_I386 1" >> $config_h
elif test "$cpu" = "x86_64" ; then
echo "ARCH=x86_64" >> $config_mak
echo "#define HOST_X86_64 1" >> $config_h
elif test "$cpu" = "armv4b" ; then
echo "ARCH=arm" >> $config_mak
echo "#define HOST_ARM 1" >> $config_h
elif test "$cpu" = "armv4l" ; then
echo "ARCH=arm" >> $config_mak
echo "#define HOST_ARM 1" >> $config_h
@@ -278,8 +614,8 @@ elif test "$cpu" = "ia64" ; then
echo "ARCH=ia64" >> $config_mak
echo "#define HOST_IA64 1" >> $config_h
elif test "$cpu" = "m68k" ; then
echo "ARCH=m68k" >> config.mak
echo "#define HOST_M68K 1" >> $TMPH
echo "ARCH=m68k" >> $config_mak
echo "#define HOST_M68K 1" >> $config_h
else
echo "Unsupported CPU"
exit 1
@@ -288,7 +624,25 @@ if test "$bigendian" = "yes" ; then
echo "WORDS_BIGENDIAN=yes" >> $config_mak
echo "#define WORDS_BIGENDIAN 1" >> $config_h
fi
echo "#define HAVE_BYTESWAP_H 1" >> $config_h
echo "#define HOST_LONG_BITS $hostlongbits" >> $config_h
if test "$mingw32" = "yes" ; then
echo "CONFIG_WIN32=yes" >> $config_mak
echo "#define CONFIG_WIN32 1" >> $config_h
elif test -f "/usr/include/byteswap.h" ; then
echo "#define HAVE_BYTESWAP_H 1" >> $config_h
fi
if test "$darwin" = "yes" ; then
echo "CONFIG_DARWIN=yes" >> $config_mak
echo "#define CONFIG_DARWIN 1" >> $config_h
fi
if test "$solaris" = "yes" ; then
echo "CONFIG_SOLARIS=yes" >> $config_mak
echo "#define HOST_SOLARIS $solarisrev" >> $config_h
fi
if test "$gdbstub" = "yes" ; then
echo "CONFIG_GDBSTUB=yes" >> $config_mak
echo "#define CONFIG_GDBSTUB 1" >> $config_h
fi
if test "$gprof" = "yes" ; then
echo "TARGET_GPROF=yes" >> $config_mak
echo "#define HAVE_GPROF 1" >> $config_h
@@ -297,32 +651,71 @@ if test "$static" = "yes" ; then
echo "CONFIG_STATIC=yes" >> $config_mak
echo "#define CONFIG_STATIC 1" >> $config_h
fi
if test "$sdl" = "yes" ; then
echo "CONFIG_SDL=yes" >> $config_mak
echo "#define CONFIG_SDL 1" >> $config_h
echo "SDL_LIBS=`sdl-config --libs`" >> $config_mak
echo "SDL_STATIC_LIBS=`sdl-config --static-libs`" >> $config_mak
echo "SDL_CFLAGS=`sdl-config --cflags`" >> $config_mak
if test $profiler = "yes" ; then
echo "#define CONFIG_PROFILER 1" >> $config_h
fi
echo -n "VERSION=" >>$config_mak
head $source_path/VERSION >>$config_mak
echo "" >>$config_mak
echo -n "#define QEMU_VERSION \"" >> $config_h
head $source_path/VERSION >> $config_h
echo "\"" >> $config_h
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=yes" >> $config_mak
echo "#define CONFIG_SLIRP 1" >> $config_h
fi
if test "$adlib" = "yes" ; then
echo "CONFIG_ADLIB=yes" >> $config_mak
echo "#define CONFIG_ADLIB 1" >> $config_h
fi
if test "$oss" = "yes" ; then
echo "CONFIG_OSS=yes" >> $config_mak
echo "#define CONFIG_OSS 1" >> $config_h
fi
if test "$coreaudio" = "yes" ; then
echo "CONFIG_COREAUDIO=yes" >> $config_mak
echo "#define CONFIG_COREAUDIO 1" >> $config_h
fi
if test "$alsa" = "yes" ; then
echo "CONFIG_ALSA=yes" >> $config_mak
echo "#define CONFIG_ALSA 1" >> $config_h
fi
if test "$dsound" = "yes" ; then
echo "CONFIG_DSOUND=yes" >> $config_mak
echo "#define CONFIG_DSOUND 1" >> $config_h
fi
if test "$fmod" = "yes" ; then
echo "CONFIG_FMOD=yes" >> $config_mak
echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
echo "#define CONFIG_FMOD 1" >> $config_h
fi
qemu_version=`head $source_path/VERSION`
echo "VERSION=$qemu_version" >>$config_mak
echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
echo "SRC_PATH=$source_path" >> $config_mak
if [ "$source_path_used" = "yes" ]; then
echo "VPATH=$source_path" >> $config_mak
fi
echo "TARGET_DIRS=$target_list" >> $config_mak
if [ "$build_docs" = "yes" ] ; then
echo "BUILD_DOCS=yes" >> $config_mak
fi
for target in $target_list; do
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
echo "#define O_LARGEFILE 0" >> $config_h
echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h
echo "#define _BSD 1" >> $config_h
fi
for target in $target_list; do
target_dir="$target"
config_mak=$target_dir/config.mak
config_h=$target_dir/config.h
target_cpu=`echo $target | cut -d '-' -f 1`
target_bigendian="no"
[ "$target_cpu" = "armeb" ] && target_bigendian=yes
[ "$target_cpu" = "sparc" ] && target_bigendian=yes
[ "$target_cpu" = "sparc64" ] && target_bigendian=yes
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
[ "$target_cpu" = "mips" ] && target_bigendian=yes
target_softmmu="no"
if expr $target : '.*-softmmu' > /dev/null ; then
target_softmmu="yes"
@@ -332,10 +725,31 @@ if expr $target : '.*-user' > /dev/null ; then
target_user_only="yes"
fi
echo "Creating $config_mak, $config_h and $target_dir/Makefile"
if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
-a "$sdl" = "no" -a "$cocoa" = "no" ; then
echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
echo "To build QEMU without graphical output configure with --disable-gfx-check"
echo "Note that this will disable all output from the virtual graphics card."
exit 1;
fi
#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
mkdir -p $target_dir
ln -sf $source_path/Makefile.target $target_dir/Makefile
mkdir -p $target_dir/fpu
if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
mkdir -p $target_dir/nwfpe
fi
if test "$target_user_only" = "no" ; then
mkdir -p $target_dir/slirp
fi
#
# don't use ln -sf as not all "ln -sf" over write the file/link
#
rm -f $target_dir/Makefile
ln -s $source_path/Makefile.target $target_dir/Makefile
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
@@ -351,7 +765,10 @@ if test "$target_cpu" = "i386" ; then
echo "TARGET_ARCH=i386" >> $config_mak
echo "#define TARGET_ARCH \"i386\"" >> $config_h
echo "#define TARGET_I386 1" >> $config_h
elif test "$target_cpu" = "arm" ; then
if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "i386" ; then
echo "#define USE_KQEMU 1" >> $config_h
fi
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
@@ -359,10 +776,36 @@ elif test "$target_cpu" = "sparc" ; then
echo "TARGET_ARCH=sparc" >> $config_mak
echo "#define TARGET_ARCH \"sparc\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
elif test "$target_cpu" = "sparc64" ; then
echo "TARGET_ARCH=sparc64" >> $config_mak
echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
echo "#define TARGET_SPARC64 1" >> $config_h
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
elif test "$target_cpu" = "ppc64" ; then
echo "TARGET_ARCH=ppc64" >> $config_mak
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
elif test "$target_cpu" = "x86_64" ; then
echo "TARGET_ARCH=x86_64" >> $config_mak
echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
echo "#define TARGET_I386 1" >> $config_h
echo "#define TARGET_X86_64 1" >> $config_h
if test $kqemu = "yes" -a "$target_softmmu" = "yes" -a $cpu = "x86_64" ; then
echo "#define USE_KQEMU 1" >> $config_h
fi
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 "TARGET_ARCH=sh4" >> $config_mak
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
echo "#define TARGET_SH4 1" >> $config_h
else
echo "Unsupported target CPU"
exit 1
@@ -380,6 +823,39 @@ 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
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
fi
# sdl defines
if test "$target_user_only" = "no"; then
if test "$target_softmmu" = "no" -o "$static" = "yes"; then
sdl1=$sdl_static
else
sdl1=$sdl
fi
if test "$sdl1" = "yes" ; then
echo "#define CONFIG_SDL 1" >> $config_h
echo "CONFIG_SDL=yes" >> $config_mak
if test "$target_softmmu" = "no" -o "$static" = "yes"; then
echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
else
echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
fi
if [ "${aa}" = "yes" ] ; then
echo "SDL_CFLAGS=`$sdl_config --cflags` `aalib-config --cflags`" >> $config_mak
else
echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
fi
fi
fi
if test "$cocoa" = "yes" ; then
echo "#define CONFIG_COCOA 1" >> $config_h
echo "CONFIG_COCOA=yes" >> $config_mak
fi
done # for target in $targets
# build tree in object directory if source path is different from current one
@@ -389,8 +865,10 @@ if test "$source_path_used" = "yes" ; then
for dir in $DIRS ; do
mkdir -p $dir
done
# remove the link and recreate it, as not all "ln -sf" overwrite the link
for f in $FILES ; do
ln -sf $source_path/$f $f
rm -f $f
ln -s $source_path/$f $f
done
fi

1008
console.c Normal file

File diff suppressed because it is too large Load Diff

751
cpu-all.h
View File

@@ -37,18 +37,99 @@
* TARGET_WORDS_BIGENDIAN : same for target cpu
*/
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
#include "bswap.h"
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif
#ifdef BSWAP_NEEDED
static inline uint16_t tswap16(uint16_t s)
{
return bswap16(s);
}
static inline uint32_t tswap32(uint32_t s)
{
return bswap32(s);
}
static inline uint64_t tswap64(uint64_t s)
{
return bswap64(s);
}
static inline void tswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void tswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void tswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#else
static inline uint16_t tswap16(uint16_t s)
{
return s;
}
static inline uint32_t tswap32(uint32_t s)
{
return s;
}
static inline uint64_t tswap64(uint64_t s)
{
return s;
}
static inline void tswap16s(uint16_t *s)
{
}
static inline void tswap32s(uint32_t *s)
{
}
static inline void tswap64s(uint64_t *s)
{
}
#endif
#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
#define bswaptls(s) bswap32s(s)
#else
#define tswapl(s) tswap64(s)
#define tswapls(s) tswap64s((uint64_t *)(s))
#define bswaptls(s) bswap64s(s)
#endif
/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
endian ! */
typedef union {
double d;
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
float64 d;
#if defined(WORDS_BIGENDIAN) \
|| (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
struct {
uint32_t lower;
uint32_t upper;
uint32_t lower;
} l;
#else
struct {
uint32_t upper;
uint32_t lower;
uint32_t upper;
} l;
#endif
uint64_t ll;
@@ -56,17 +137,50 @@ typedef union {
/* CPU memory access without any memory or io remapping */
static inline int ldub_raw(void *ptr)
/*
* the generic syntax for the memory accesses is:
*
* load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
*
* store: st{type}{size}{endian}_{access_type}(ptr, val)
*
* type is:
* (empty): integer access
* f : float access
*
* sign is:
* (empty): for floats or 32 bit size
* u : unsigned
* s : signed
*
* size is:
* b: 8 bits
* w: 16 bits
* l: 32 bits
* q: 64 bits
*
* endian is:
* (empty): target cpu endianness or 8 bit access
* r : reversed target cpu endianness (not implemented yet)
* be : big endian (not implemented yet)
* le : little endian (not implemented yet)
*
* access_type is:
* raw : host memory access
* user : user mode access using soft MMU
* kernel : kernel mode access using soft MMU
*/
static inline int ldub_p(void *ptr)
{
return *(uint8_t *)ptr;
}
static inline int ldsb_raw(void *ptr)
static inline int ldsb_p(void *ptr)
{
return *(int8_t *)ptr;
}
static inline void stb_raw(void *ptr, int v)
static inline void stb_p(void *ptr, int v)
{
*(uint8_t *)ptr = v;
}
@@ -74,10 +188,10 @@ static inline void stb_raw(void *ptr, int v)
/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
kernel handles unaligned load/stores may give better results, but
it is a system wide setting : bad */
#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
#if defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
/* conservative code for little endian unaligned accesses */
static inline int lduw_raw(void *ptr)
static inline int lduw_le_p(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -89,7 +203,7 @@ static inline int lduw_raw(void *ptr)
#endif
}
static inline int ldsw_raw(void *ptr)
static inline int ldsw_le_p(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -101,7 +215,7 @@ static inline int ldsw_raw(void *ptr)
#endif
}
static inline int ldl_raw(void *ptr)
static inline int ldl_le_p(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -113,16 +227,16 @@ static inline int ldl_raw(void *ptr)
#endif
}
static inline uint64_t ldq_raw(void *ptr)
static inline uint64_t ldq_le_p(void *ptr)
{
uint8_t *p = ptr;
uint32_t v1, v2;
v1 = ldl_raw(p);
v2 = ldl_raw(p + 4);
v1 = ldl_le_p(p);
v2 = ldl_le_p(p + 4);
return v1 | ((uint64_t)v2 << 32);
}
static inline void stw_raw(void *ptr, int v)
static inline void stw_le_p(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
@@ -133,7 +247,7 @@ static inline void stw_raw(void *ptr, int v)
#endif
}
static inline void stl_raw(void *ptr, int v)
static inline void stl_le_p(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
@@ -146,201 +260,367 @@ static inline void stl_raw(void *ptr, int v)
#endif
}
static inline void stq_raw(void *ptr, uint64_t v)
static inline void stq_le_p(void *ptr, uint64_t v)
{
uint8_t *p = ptr;
stl_raw(p, (uint32_t)v);
stl_raw(p + 4, v >> 32);
stl_le_p(p, (uint32_t)v);
stl_le_p(p + 4, v >> 32);
}
/* float access */
static inline float ldfl_raw(void *ptr)
static inline float32 ldfl_le_p(void *ptr)
{
union {
float f;
float32 f;
uint32_t i;
} u;
u.i = ldl_raw(ptr);
u.i = ldl_le_p(ptr);
return u.f;
}
static inline void stfl_raw(void *ptr, float v)
static inline void stfl_le_p(void *ptr, float32 v)
{
union {
float f;
float32 f;
uint32_t i;
} u;
u.f = v;
stl_raw(ptr, u.i);
stl_le_p(ptr, u.i);
}
static inline double ldfq_raw(void *ptr)
static inline float64 ldfq_le_p(void *ptr)
{
CPU_DoubleU u;
u.l.lower = ldl_raw(ptr);
u.l.upper = ldl_raw(ptr + 4);
u.l.lower = ldl_le_p(ptr);
u.l.upper = ldl_le_p(ptr + 4);
return u.d;
}
static inline void stfq_raw(void *ptr, double v)
static inline void stfq_le_p(void *ptr, float64 v)
{
CPU_DoubleU u;
u.d = v;
stl_raw(ptr, u.l.lower);
stl_raw(ptr + 4, u.l.upper);
}
#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
static inline int lduw_raw(void *ptr)
{
uint8_t *b = (uint8_t *) ptr;
return (b[0]<<8|b[1]);
}
static inline int ldsw_raw(void *ptr)
{
int8_t *b = (int8_t *) ptr;
return (b[0]<<8|b[1]);
}
static inline int ldl_raw(void *ptr)
{
uint8_t *b = (uint8_t *) ptr;
return (b[0]<<24|b[1]<<16|b[2]<<8|b[3]);
}
static inline uint64_t ldq_raw(void *ptr)
{
uint32_t a,b;
a = ldl_raw(ptr);
b = ldl_raw(ptr+4);
return (((uint64_t)a<<32)|b);
}
static inline void stw_raw(void *ptr, int v)
{
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 8;
d[1] = v;
}
static inline void stl_raw(void *ptr, int v)
{
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 24;
d[1] = v >> 16;
d[2] = v >> 8;
d[3] = v;
}
static inline void stq_raw(void *ptr, uint64_t v)
{
stl_raw(ptr, v >> 32);
stl_raw(ptr + 4, v);
}
/* float access */
static inline float ldfl_raw(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl_raw(ptr);
return u.f;
}
static inline void stfl_raw(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl_raw(ptr, u.i);
}
static inline double ldfq_raw(void *ptr)
{
CPU_DoubleU u;
u.l.upper = ldl_raw(ptr);
u.l.lower = ldl_raw(ptr + 4);
return u.d;
}
static inline void stfq_raw(void *ptr, double v)
{
CPU_DoubleU u;
u.d = v;
stl_raw(ptr, u.l.upper);
stl_raw(ptr + 4, u.l.lower);
stl_le_p(ptr, u.l.lower);
stl_le_p(ptr + 4, u.l.upper);
}
#else
static inline int lduw_raw(void *ptr)
static inline int lduw_le_p(void *ptr)
{
return *(uint16_t *)ptr;
}
static inline int ldsw_raw(void *ptr)
static inline int ldsw_le_p(void *ptr)
{
return *(int16_t *)ptr;
}
static inline int ldl_raw(void *ptr)
static inline int ldl_le_p(void *ptr)
{
return *(uint32_t *)ptr;
}
static inline uint64_t ldq_raw(void *ptr)
static inline uint64_t ldq_le_p(void *ptr)
{
return *(uint64_t *)ptr;
}
static inline void stw_raw(void *ptr, int v)
static inline void stw_le_p(void *ptr, int v)
{
*(uint16_t *)ptr = v;
}
static inline void stl_raw(void *ptr, int v)
static inline void stl_le_p(void *ptr, int v)
{
*(uint32_t *)ptr = v;
}
static inline void stq_raw(void *ptr, uint64_t v)
static inline void stq_le_p(void *ptr, uint64_t v)
{
*(uint64_t *)ptr = v;
}
/* float access */
static inline float ldfl_raw(void *ptr)
static inline float32 ldfl_le_p(void *ptr)
{
return *(float *)ptr;
return *(float32 *)ptr;
}
static inline double ldfq_raw(void *ptr)
static inline float64 ldfq_le_p(void *ptr)
{
return *(double *)ptr;
return *(float64 *)ptr;
}
static inline void stfl_raw(void *ptr, float v)
static inline void stfl_le_p(void *ptr, float32 v)
{
*(float *)ptr = v;
*(float32 *)ptr = v;
}
static inline void stfq_raw(void *ptr, double v)
static inline void stfq_le_p(void *ptr, float64 v)
{
*(double *)ptr = v;
*(float64 *)ptr = v;
}
#endif
#if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
static inline int lduw_be_p(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return val;
#else
uint8_t *b = (uint8_t *) ptr;
return ((b[0] << 8) | b[1]);
#endif
}
static inline int ldsw_be_p(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return (int16_t)val;
#else
uint8_t *b = (uint8_t *) ptr;
return (int16_t)((b[0] << 8) | b[1]);
#endif
}
static inline int ldl_be_p(void *ptr)
{
#if defined(__i386__) || defined(__x86_64__)
int val;
asm volatile ("movl %1, %0\n"
"bswap %0\n"
: "=r" (val)
: "m" (*(uint32_t *)ptr));
return val;
#else
uint8_t *b = (uint8_t *) ptr;
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#endif
}
static inline uint64_t ldq_be_p(void *ptr)
{
uint32_t a,b;
a = ldl_be_p(ptr);
b = ldl_be_p(ptr+4);
return (((uint64_t)a<<32)|b);
}
static inline void stw_be_p(void *ptr, int v)
{
#if defined(__i386__)
asm volatile ("xchgb %b0, %h0\n"
"movw %w0, %1\n"
: "=q" (v)
: "m" (*(uint16_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 8;
d[1] = v;
#endif
}
static inline void stl_be_p(void *ptr, int v)
{
#if defined(__i386__) || defined(__x86_64__)
asm volatile ("bswap %0\n"
"movl %0, %1\n"
: "=r" (v)
: "m" (*(uint32_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 24;
d[1] = v >> 16;
d[2] = v >> 8;
d[3] = v;
#endif
}
static inline void stq_be_p(void *ptr, uint64_t v)
{
stl_be_p(ptr, v >> 32);
stl_be_p(ptr + 4, v);
}
/* float access */
static inline float32 ldfl_be_p(void *ptr)
{
union {
float32 f;
uint32_t i;
} u;
u.i = ldl_be_p(ptr);
return u.f;
}
static inline void stfl_be_p(void *ptr, float32 v)
{
union {
float32 f;
uint32_t i;
} u;
u.f = v;
stl_be_p(ptr, u.i);
}
static inline float64 ldfq_be_p(void *ptr)
{
CPU_DoubleU u;
u.l.upper = ldl_be_p(ptr);
u.l.lower = ldl_be_p(ptr + 4);
return u.d;
}
static inline void stfq_be_p(void *ptr, float64 v)
{
CPU_DoubleU u;
u.d = v;
stl_be_p(ptr, u.l.upper);
stl_be_p(ptr + 4, u.l.lower);
}
#else
static inline int lduw_be_p(void *ptr)
{
return *(uint16_t *)ptr;
}
static inline int ldsw_be_p(void *ptr)
{
return *(int16_t *)ptr;
}
static inline int ldl_be_p(void *ptr)
{
return *(uint32_t *)ptr;
}
static inline uint64_t ldq_be_p(void *ptr)
{
return *(uint64_t *)ptr;
}
static inline void stw_be_p(void *ptr, int v)
{
*(uint16_t *)ptr = v;
}
static inline void stl_be_p(void *ptr, int v)
{
*(uint32_t *)ptr = v;
}
static inline void stq_be_p(void *ptr, uint64_t v)
{
*(uint64_t *)ptr = v;
}
/* float access */
static inline float32 ldfl_be_p(void *ptr)
{
return *(float32 *)ptr;
}
static inline float64 ldfq_be_p(void *ptr)
{
return *(float64 *)ptr;
}
static inline void stfl_be_p(void *ptr, float32 v)
{
*(float32 *)ptr = v;
}
static inline void stfq_be_p(void *ptr, float64 v)
{
*(float64 *)ptr = v;
}
#endif
/* target CPU memory access functions */
#if defined(TARGET_WORDS_BIGENDIAN)
#define lduw_p(p) lduw_be_p(p)
#define ldsw_p(p) ldsw_be_p(p)
#define ldl_p(p) ldl_be_p(p)
#define ldq_p(p) ldq_be_p(p)
#define ldfl_p(p) ldfl_be_p(p)
#define ldfq_p(p) ldfq_be_p(p)
#define stw_p(p, v) stw_be_p(p, v)
#define stl_p(p, v) stl_be_p(p, v)
#define stq_p(p, v) stq_be_p(p, v)
#define stfl_p(p, v) stfl_be_p(p, v)
#define stfq_p(p, v) stfq_be_p(p, v)
#else
#define lduw_p(p) lduw_le_p(p)
#define ldsw_p(p) ldsw_le_p(p)
#define ldl_p(p) ldl_le_p(p)
#define ldq_p(p) ldq_le_p(p)
#define ldfl_p(p) ldfl_le_p(p)
#define ldfq_p(p) ldfq_le_p(p)
#define stw_p(p, v) stw_le_p(p, v)
#define stl_p(p, v) stl_le_p(p, v)
#define stq_p(p, v) stq_le_p(p, v)
#define stfl_p(p, v) stfl_le_p(p, v)
#define stfq_p(p, v) stfq_le_p(p, v)
#endif
/* MMU memory access macros */
#if defined(CONFIG_USER_ONLY)
/* On some host systems the guest address space is reserved on the host.
* This allows the guest address space to be offset to a convenient location.
*/
//#define GUEST_BASE 0x20000000
#define GUEST_BASE 0
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
#define h2g(x) ((target_ulong)(x - GUEST_BASE))
#define saddr(x) g2h(x)
#define laddr(x) g2h(x)
#else /* !CONFIG_USER_ONLY */
/* NOTE: we use double casts if pointers and target_ulong have
different sizes */
#define saddr(x) (uint8_t *)(long)(x)
#define laddr(x) (uint8_t *)(long)(x)
#endif
#define ldub_raw(p) ldub_p(laddr((p)))
#define ldsb_raw(p) ldsb_p(laddr((p)))
#define lduw_raw(p) lduw_p(laddr((p)))
#define ldsw_raw(p) ldsw_p(laddr((p)))
#define ldl_raw(p) ldl_p(laddr((p)))
#define ldq_raw(p) ldq_p(laddr((p)))
#define ldfl_raw(p) ldfl_p(laddr((p)))
#define ldfq_raw(p) ldfq_p(laddr((p)))
#define stb_raw(p, v) stb_p(saddr((p)), v)
#define stw_raw(p, v) stw_p(saddr((p)), v)
#define stl_raw(p, v) stl_p(saddr((p)), v)
#define stq_raw(p, v) stq_p(saddr((p)), v)
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
@@ -387,12 +667,13 @@ static inline void stfq_raw(void *ptr, double v)
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
extern unsigned long real_host_page_size;
extern unsigned long host_page_bits;
extern unsigned long host_page_size;
extern unsigned long host_page_mask;
/* ??? These should be the larger of unsigned long and target_ulong. */
extern unsigned long qemu_real_host_page_size;
extern unsigned long qemu_host_page_bits;
extern unsigned long qemu_host_page_size;
extern unsigned long qemu_host_page_mask;
#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
/* same as PROT_xxx */
#define PAGE_READ 0x0001
@@ -405,9 +686,9 @@ extern unsigned long host_page_mask;
#define PAGE_WRITE_ORG 0x0010
void page_dump(FILE *f);
int page_get_flags(unsigned long address);
void page_set_flags(unsigned long start, unsigned long end, int flags);
void page_unprotect_range(uint8_t *data, unsigned long data_size);
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_unprotect_range(target_ulong data, target_ulong data_size);
#define SINGLE_CPU_DEFINES
#ifdef SINGLE_CPU_DEFINES
@@ -418,7 +699,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_x86_init
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#define cpu_interrupt cpu_x86_interrupt
#define cpu_signal_handler cpu_x86_signal_handler
#elif defined(TARGET_ARM)
@@ -427,7 +707,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_arm_init
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_interrupt cpu_arm_interrupt
#define cpu_signal_handler cpu_arm_signal_handler
#elif defined(TARGET_SPARC)
@@ -436,7 +715,6 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_sparc_init
#define cpu_exec cpu_sparc_exec
#define cpu_gen_code cpu_sparc_gen_code
#define cpu_interrupt cpu_sparc_interrupt
#define cpu_signal_handler cpu_sparc_signal_handler
#elif defined(TARGET_PPC)
@@ -445,9 +723,22 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_ppc_init
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_interrupt cpu_ppc_interrupt
#define cpu_signal_handler cpu_ppc_signal_handler
#elif defined(TARGET_MIPS)
#define CPUState CPUMIPSState
#define cpu_init cpu_mips_init
#define cpu_exec cpu_mips_exec
#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
#elif defined(TARGET_SH4)
#define CPUState CPUSH4State
#define cpu_init cpu_sh4_init
#define cpu_exec cpu_sh4_exec
#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
#else
#error unsupported target CPU
@@ -456,37 +747,173 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#endif /* SINGLE_CPU_DEFINES */
#define DEFAULT_GDBSTUB_PORT 1234
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
void cpu_abort(CPUState *env, const char *fmt, ...);
extern CPUState *first_cpu;
extern CPUState *cpu_single_env;
extern int code_copy_enabled;
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
int cpu_breakpoint_insert(CPUState *env, uint32_t pc);
int cpu_breakpoint_remove(CPUState *env, uint32_t pc);
int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
void cpu_single_step(CPUState *env, int enabled);
void cpu_reset(CPUState *s);
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
#define CPU_LOG_TB_OUT_ASM (1 << 0)
#define CPU_LOG_TB_IN_ASM (1 << 1)
#define CPU_LOG_TB_OP (1 << 2)
#define CPU_LOG_TB_OP_OPT (1 << 3)
#define CPU_LOG_INT (1 << 4)
#define CPU_LOG_EXEC (1 << 5)
#define CPU_LOG_PCALL (1 << 6)
#define CPU_LOG_IOPORT (1 << 7)
#define CPU_LOG_TB_CPU (1 << 8)
/* define log items */
typedef struct CPULogItem {
int mask;
const char *name;
const char *help;
} CPULogItem;
extern CPULogItem cpu_log_items[];
#define CPU_LOG_ALL 1
void cpu_set_log(int log_flags);
void cpu_set_log_filename(const char *filename);
int cpu_str_to_log_mask(const char *str);
/* IO ports API */
/* NOTE: as these functions may be even used when there is an isa
brige on non x86 targets, we always defined them */
#ifndef NO_CPU_IO_DEFS
void cpu_outb(CPUState *env, int addr, int val);
void cpu_outw(CPUState *env, int addr, int val);
void cpu_outl(CPUState *env, int addr, int val);
int cpu_inb(CPUState *env, int addr);
int cpu_inw(CPUState *env, int addr);
int cpu_inl(CPUState *env, int addr);
#endif
/* memory API */
typedef void CPUWriteMemoryFunc(uint32_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(uint32_t addr);
extern int phys_ram_size;
extern int phys_ram_fd;
extern uint8_t *phys_ram_base;
extern uint8_t *phys_ram_dirty;
void cpu_register_physical_memory(unsigned long start_addr, unsigned long size,
long phys_offset);
/* physical memory access */
#define TLB_INVALID_MASK (1 << 3)
#define IO_MEM_SHIFT 4
#define IO_MEM_NB_ENTRIES (1 << (TARGET_PAGE_BITS - IO_MEM_SHIFT))
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
#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 */
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
void cpu_register_physical_memory(target_phys_addr_t start_addr,
unsigned long size,
unsigned long phys_offset);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write);
CPUWriteMemoryFunc **mem_write,
void *opaque);
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
/* gdb stub API */
extern int gdbstub_fd;
CPUState *cpu_gdbstub_get_env(void *opaque);
int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port);
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
uint32_t ldub_phys(target_phys_addr_t addr);
uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
#define VGA_DIRTY_FLAG 0x01
#define CODE_DIRTY_FLAG 0x02
/* read dirty bit (return 0 or 1) */
static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
{
return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
}
static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
int dirty_flags)
{
return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
}
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
{
phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
}
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
int dirty_flags);
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)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
return val;
}
extern int64_t kqemu_time, kqemu_time_start;
extern int64_t qemu_time, qemu_time_start;
extern int64_t tlb_flush_time;
extern int64_t kqemu_exec_count;
extern int64_t dev_time;
extern int64_t kqemu_ret_int_count;
extern int64_t kqemu_ret_excp_count;
extern int64_t kqemu_ret_intr_count;
#endif
#endif /* CPU_ALL_H */

View File

@@ -22,14 +22,66 @@
#include "config.h"
#include <setjmp.h>
#include <inttypes.h>
#include "osdep.h"
#define EXCP_INTERRUPT 256 /* async interruption */
#define EXCP_HLT 257 /* hlt instruction reached */
#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
#endif
#ifndef TARGET_PHYS_ADDR_BITS
#if TARGET_LONG_BITS >= HOST_LONG_BITS
#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
#else
#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS
#endif
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
/* target_ulong is the type of a virtual address */
#if TARGET_LONG_SIZE == 4
typedef int32_t target_long;
typedef uint32_t target_ulong;
#define TARGET_FMT_lx "%08x"
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#define TARGET_FMT_lx "%016llx"
#else
#error TARGET_LONG_SIZE undefined
#endif
/* target_phys_addr_t is the type of a physical address (its size can
be different from 'target_ulong'). We have sizeof(target_phys_addr)
= max(sizeof(unsigned long),
sizeof(size_of_target_physical_address)) because we must pass a
host pointer to memory operations in some cases */
#if TARGET_PHYS_ADDR_BITS == 32
typedef uint32_t target_phys_addr_t;
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
#else
#error TARGET_PHYS_ADDR_BITS undefined
#endif
/* address in the RAM (different from a physical address) */
typedef unsigned long ram_addr_t;
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
#define EXCP_INTERRUPT 0x10000 /* async interruption */
#define EXCP_HLT 0x10001 /* hlt instruction reached */
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
#define MAX_BREAKPOINTS 32
#define CPU_TLB_SIZE 256
#define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
#define CPU_TLB_BITS 8
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
typedef struct CPUTLBEntry {
/* bit 31 to TARGET_PAGE_BITS : virtual address
@@ -38,9 +90,36 @@ typedef struct CPUTLBEntry {
bit 3 : indicates that the entry is invalid
bit 2..0 : zero
*/
uint32_t address;
target_ulong addr_read;
target_ulong addr_write;
target_ulong addr_code;
/* addend to virtual address to get physical address */
uint32_t addend;
target_phys_addr_t addend;
} CPUTLBEntry;
#define CPU_COMMON \
struct TranslationBlock *current_tb; /* currently executing TB */ \
/* soft mmu support */ \
/* in order to avoid passing too many arguments to the memory \
write helpers, we store some rarely used information in the CPU \
context) */ \
unsigned long mem_write_pc; /* host pc at which the memory was \
written */ \
target_ulong mem_write_vaddr; /* target virtual addr at which the \
memory was written */ \
/* 0 = kernel, 1 = user */ \
CPUTLBEntry tlb_table[2][CPU_TLB_SIZE]; \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
\
/* from this point: preserved by CPU reset */ \
/* ice debug support */ \
target_ulong breakpoints[MAX_BREAKPOINTS]; \
int nb_breakpoints; \
int singlestep_enabled; \
\
void *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
/* user data */ \
void *opaque;
#endif

1096
cpu-exec.c

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,7 @@
#ifndef DIS_ASM_H
#define DIS_ASM_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
@@ -16,7 +17,11 @@
#define PARAMS(x) x
typedef void *PTR;
typedef uint64_t bfd_vma;
typedef int64_t bfd_signed_vma;
typedef uint8_t bfd_byte;
#define sprintf_vma(s,x) sprintf (s, "%0" PRIx64, x)
#define BFD64
enum bfd_flavour {
bfd_target_unknown_flavour,
@@ -51,6 +56,17 @@ enum bfd_architecture
#define bfd_mach_m68030 5
#define bfd_mach_m68040 6
#define bfd_mach_m68060 7
#define bfd_mach_cpu32 8
#define bfd_mach_mcf5200 9
#define bfd_mach_mcf5206e 10
#define bfd_mach_mcf5307 11
#define bfd_mach_mcf5407 12
#define bfd_mach_mcf528x 13
#define bfd_mach_mcfv4e 14
#define bfd_mach_mcf521x 15
#define bfd_mach_mcf5249 16
#define bfd_mach_mcf547x 17
#define bfd_mach_mcf548x 18
bfd_arch_vax, /* DEC Vax */
bfd_arch_i960, /* Intel 960 */
/* The order of the following is important.
@@ -105,6 +121,9 @@ enum bfd_architecture
bfd_arch_i386, /* Intel 386 */
#define bfd_mach_i386_i386 0
#define bfd_mach_i386_i8086 1
#define bfd_mach_i386_i386_intel_syntax 2
#define bfd_mach_x86_64 3
#define bfd_mach_x86_64_intel_syntax 4
bfd_arch_we32k, /* AT&T WE32xxx */
bfd_arch_tahoe, /* CCI/Harris Tahoe */
bfd_arch_i860, /* Intel 860 */
@@ -118,6 +137,24 @@ enum bfd_architecture
#define bfd_mach_h8300h 2
#define bfd_mach_h8300s 3
bfd_arch_powerpc, /* PowerPC */
#define bfd_mach_ppc 0
#define bfd_mach_ppc64 1
#define bfd_mach_ppc_403 403
#define bfd_mach_ppc_403gc 4030
#define bfd_mach_ppc_505 505
#define bfd_mach_ppc_601 601
#define bfd_mach_ppc_602 602
#define bfd_mach_ppc_603 603
#define bfd_mach_ppc_ec603e 6031
#define bfd_mach_ppc_604 604
#define bfd_mach_ppc_620 620
#define bfd_mach_ppc_630 630
#define bfd_mach_ppc_750 750
#define bfd_mach_ppc_860 860
#define bfd_mach_ppc_a35 35
#define bfd_mach_ppc_rs64ii 642
#define bfd_mach_ppc_rs64iii 643
#define bfd_mach_ppc_7400 7400
bfd_arch_rs6000, /* IBM RS/6000 */
bfd_arch_hppa, /* HP PA RISC */
bfd_arch_d10v, /* Mitsubishi D10V */
@@ -126,10 +163,23 @@ enum bfd_architecture
#define bfd_mach_z8002 2
bfd_arch_h8500, /* Hitachi H8/500 */
bfd_arch_sh, /* Hitachi SH */
#define bfd_mach_sh 0
#define bfd_mach_sh 1
#define bfd_mach_sh2 0x20
#define bfd_mach_sh_dsp 0x2d
#define bfd_mach_sh2a 0x2a
#define bfd_mach_sh2a_nofpu 0x2b
#define bfd_mach_sh2e 0x2e
#define bfd_mach_sh3 0x30
#define bfd_mach_sh3_nommu 0x31
#define bfd_mach_sh3_dsp 0x3d
#define bfd_mach_sh3e 0x3e
#define bfd_mach_sh4 0x40
#define bfd_mach_sh4_nofpu 0x41
#define bfd_mach_sh4_nommu_nofpu 0x42
#define bfd_mach_sh4a 0x4a
#define bfd_mach_sh4a_nofpu 0x4b
#define bfd_mach_sh4al_dsp 0x4d
#define bfd_mach_sh5 0x50
bfd_arch_alpha, /* Dec Alpha */
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_2 1
@@ -391,11 +441,15 @@ extern int generic_symbol_at_address
(INFO).insn_info_valid = 0
#define _(x) x
#define ATTRIBUTE_UNUSED __attribute__((unused))
/* from libbfd */
bfd_vma bfd_getl32 (const bfd_byte *addr);
bfd_vma bfd_getb32 (const bfd_byte *addr);
bfd_vma bfd_getl16 (const bfd_byte *addr);
bfd_vma bfd_getb16 (const bfd_byte *addr);
typedef enum bfd_boolean {false, true} boolean;
typedef boolean bfd_boolean;
#endif /* ! defined (DIS_ASM_H) */

339
disas.c
View File

@@ -1,17 +1,15 @@
/* General "disassemble this chunk" code. Used for debugging. */
#include "config.h"
#include "dis-asm.h"
#include "disas.h"
#include "elf.h"
#include <errno.h>
#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *syminfos = NULL;
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
@@ -30,23 +28,20 @@ buffer_read_memory (memaddr, myaddr, length, info)
return 0;
}
#if !defined(CONFIG_USER_ONLY)
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
static int
target_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
target_read_memory (bfd_vma memaddr,
bfd_byte *myaddr,
int length,
struct disassemble_info *info)
{
int i;
for(i = 0; i < length; i++) {
myaddr[i] = ldub_code((void *)((long)memaddr + i));
myaddr[i] = ldub_code(memaddr + i);
}
return 0;
}
#endif
/* Print an error message. We can assume that this is in response to
an error return from buffer_read_memory. */
@@ -78,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%llx", addr);
}
/* Just return the given address. */
@@ -113,74 +108,168 @@ bfd_vma bfd_getb32 (const bfd_byte *addr)
return (bfd_vma) v;
}
/* Disassemble this for me please... (debugging). 'flags' is only used
for i386: non zero means 16 bit code */
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
bfd_vma bfd_getl16 (const bfd_byte *addr)
{
uint8_t *pc;
unsigned long v;
v = (unsigned long) addr[0];
v |= (unsigned long) addr[1] << 8;
return (bfd_vma) v;
}
bfd_vma bfd_getb16 (const bfd_byte *addr)
{
unsigned long v;
v = (unsigned long) addr[0] << 24;
v |= (unsigned long) addr[1] << 16;
return (bfd_vma) v;
}
#ifdef TARGET_ARM
static int
print_insn_thumb1(bfd_vma pc, disassemble_info *info)
{
return print_insn_arm(pc | 1, info);
}
#endif
/* Disassemble this for me please... (debugging). 'flags' has teh following
values:
i386 - nonzero means 16 bit code
arm - nonzero means thumb code
ppc - nonzero means little endian
other targets - unused
*/
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
{
target_ulong pc;
int count;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
#if !defined(CONFIG_USER_ONLY)
if (!is_host) {
disasm_info.read_memory_func = target_read_memory;
}
disasm_info.read_memory_func = target_read_memory;
disasm_info.buffer_vma = code;
disasm_info.buffer_length = size;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
if (flags)
print_insn = print_insn_thumb1;
else
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
disasm_info.mach = bfd_mach_sparc_v9b;
#endif
#elif defined(TARGET_PPC)
if (flags)
disasm_info.endian = BFD_ENDIAN_LITTLE;
#ifdef TARGET_PPC64
disasm_info.mach = bfd_mach_ppc64;
#else
disasm_info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
print_insn = print_insn_big_mips;
#else
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#else
fprintf(out, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", code);
return;
#endif
for (pc = code; pc < code + size; pc += count) {
fprintf(out, "0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &disasm_info);
#if 0
{
int i;
uint8_t b;
fprintf(out, " {");
for(i = 0; i < count; i++) {
target_read_memory(pc + i, &b, 1, &disasm_info);
fprintf(out, " %02x", b);
}
fprintf(out, " }");
}
#endif
fprintf(out, "\n");
if (count < 0)
break;
}
}
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size)
{
unsigned long pc;
int count;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
disasm_info.buffer = code;
disasm_info.buffer_vma = (unsigned long)code;
disasm_info.buffer_length = size;
if (is_host) {
#ifdef WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#ifdef __i386__
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#if defined(__i386__)
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(__x86_64__)
disasm_info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
#elif defined(__powerpc__)
print_insn = print_insn_ppc;
print_insn = print_insn_ppc;
#elif defined(__alpha__)
print_insn = print_insn_alpha;
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
print_insn = print_insn_sparc;
#elif defined(__arm__)
print_insn = print_insn_arm;
print_insn = print_insn_arm;
#elif defined(__MIPSEB__)
print_insn = print_insn_big_mips;
#elif defined(__MIPSEL__)
print_insn = print_insn_little_mips;
#elif defined(__m68k__)
print_insn = print_insn_m68k;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
fprintf(out, "0x%lx: Asm output not supported on this arch\n",
(long) code);
return;
#endif
} else {
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (!flags)
disasm_info.mach = bfd_mach_i386_i386;
else
disasm_info.mach = bfd_mach_i386_i8086;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
print_insn = print_insn_ppc;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
#endif
}
for (pc = code; pc < (uint8_t *)code + size; pc += count) {
fprintf(out, "0x%08lx: ", (long)pc);
for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
fprintf(out, "0x%08lx: ", pc);
#ifdef __arm__
/* since data are included in the code, it is better to
display code data too */
@@ -188,7 +277,7 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
}
#endif
count = print_insn((unsigned long)pc, &disasm_info);
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
break;
@@ -196,23 +285,129 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
}
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(void *orig_addr)
const char *lookup_symbol(target_ulong orig_addr)
{
unsigned int i;
/* Hack, because we know this is x86. */
Elf32_Sym *sym = disas_symtab;
Elf32_Sym *sym;
struct syminfo *s;
target_ulong addr;
for (s = syminfos; s; s = s->next) {
sym = s->disas_symtab;
for (i = 0; i < s->disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
for (i = 0; i < disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return disas_strtab + sym[i].st_name;
addr = sym[i].st_value;
#ifdef TARGET_ARM
/* The bottom address bit marks a Thumb symbol. */
addr &= ~(target_ulong)1;
#endif
if (orig_addr >= addr
&& orig_addr < addr + sym[i].st_size)
return s->disas_strtab + sym[i].st_name;
}
}
return "";
}
#if !defined(CONFIG_USER_ONLY)
void term_vprintf(const char *fmt, va_list ap);
void term_printf(const char *fmt, ...);
static int monitor_disas_is_physical;
static CPUState *monitor_disas_env;
static int
monitor_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
if (monitor_disas_is_physical) {
cpu_physical_memory_rw(memaddr, myaddr, length, 0);
} else {
cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
}
return 0;
}
static int monitor_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
term_vprintf(fmt, ap);
va_end(ap);
return 0;
}
void monitor_disas(CPUState *env,
target_ulong pc, int nb_insn, int is_physical, int flags)
{
int count, i;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
INIT_DISASSEMBLE_INFO(disasm_info, NULL, monitor_fprintf);
monitor_disas_env = env;
monitor_disas_is_physical = is_physical;
disasm_info.read_memory_func = monitor_read_memory;
disasm_info.buffer_vma = pc;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
disasm_info.mach = bfd_mach_ppc64;
#else
disasm_info.mach = bfd_mach_ppc;
#endif
print_insn = print_insn_ppc;
#elif defined(TARGET_MIPS)
#ifdef TARGET_WORDS_BIGENDIAN
print_insn = print_insn_big_mips;
#else
print_insn = print_insn_little_mips;
#endif
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
#else
term_printf("0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", pc);
return;
#endif
for(i = 0; i < nb_insn; i++) {
term_printf("0x" TARGET_FMT_lx ": ", pc);
count = print_insn(pc, &disasm_info);
term_printf("\n");
if (count < 0)
break;
pc += count;
}
}
#endif

17
disas.h
View File

@@ -2,13 +2,20 @@
#define _QEMU_DISAS_H
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags);
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
void monitor_disas(CPUState *env,
target_ulong pc, int nb_insn, int is_physical, int flags);
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(void *orig_addr);
const char *lookup_symbol(target_ulong orig_addr);
/* Filled in by elfload.c. Simplistic, but will do for now. */
extern unsigned int disas_num_syms;
extern void *disas_symtab; /* FIXME: includes are a mess --RR */
extern const char *disas_strtab;
extern struct syminfo {
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *next;
} *syminfos;
#endif /* _QEMU_DISAS_H */

View File

@@ -20,15 +20,41 @@
#if !defined(__DYNGEN_EXEC_H__)
#define __DYNGEN_EXEC_H__
/* prevent Solaris from trying to typedef FILE in gcc's
include/floatingpoint.h which will conflict with the
definition down below */
#ifdef __sun__
#define _FILEDEFED
#endif
/* NOTE: standard headers should be used with special care at this
point because host CPU registers are used as global variables. Some
host headers do not allow that. */
#include <stddef.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
/* 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
/* 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
with /usr/include/sys/int_types.h, line 75 */
#ifndef __sun__
typedef signed char int8_t;
#endif
typedef signed short int16_t;
typedef signed int int32_t;
#if defined (__x86_64__) || defined(__ia64)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#endif
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
@@ -43,21 +69,11 @@ typedef signed long long int64_t;
#define UINT32_MAX (4294967295U)
#define UINT64_MAX ((uint64_t)(18446744073709551615))
#define bswap32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
typedef struct FILE FILE;
extern int fprintf(FILE *, const char *, ...);
extern int printf(const char *, ...);
#undef NULL
#define NULL 0
#include <fenv.h>
#ifdef __i386__
#define AREG0 "ebp"
@@ -65,6 +81,14 @@ extern int printf(const char *, ...);
#define AREG2 "esi"
#define AREG3 "edi"
#endif
#ifdef __x86_64__
#define AREG0 "rbp"
#define AREG1 "rbx"
#define AREG2 "r12"
#define AREG3 "r13"
//#define AREG4 "r14"
//#define AREG5 "r15"
#endif
#ifdef __powerpc__
#define AREG0 "r27"
#define AREG1 "r24"
@@ -136,10 +160,10 @@ extern int printf(const char *, ...);
#define AREG4 "%d5"
#endif
#ifdef __ia64__
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
#define AREG3 "r26"
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
#endif
/* force GCC to generate only one epilog at the end of the function */
@@ -161,7 +185,7 @@ extern int printf(const char *, ...);
#define __hidden
#endif
#ifdef __alpha__
#if defined(__alpha__)
/* Suggested by Richard Henderson. This will result in code like
ldah $0,__op_param1($29) !gprelhigh
lda $0,__op_param1($0) !gprellow
@@ -174,35 +198,57 @@ extern int __op_param3 __hidden;
#define PARAM2 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param2)); _r; })
#define PARAM3 ({ int _r; asm("" : "=r"(_r) : "0" (&__op_param3)); _r; })
#else
#if defined(__APPLE__)
static int __op_param1, __op_param2, __op_param3;
#else
extern int __op_param1, __op_param2, __op_param3;
#endif
#define PARAM1 ((long)(&__op_param1))
#define PARAM2 ((long)(&__op_param2))
#define PARAM3 ((long)(&__op_param3))
#endif
#endif /* !defined(__alpha__) */
extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#if defined(_WIN32) || defined(__APPLE__)
#define ASM_NAME(x) "_" #x
#else
#define ASM_NAME(x) #x
#endif
#ifdef __i386__
#define EXIT_TB() asm volatile ("ret")
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __x86_64__
#define EXIT_TB() asm volatile ("ret")
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __powerpc__
#define EXIT_TB() asm volatile ("blr")
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __s390__
#define EXIT_TB() asm volatile ("br %r14")
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __alpha__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __ia64__
#define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
#define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \
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")
#endif
#ifdef __arm__
#define EXIT_TB() asm volatile ("b exec_loop")
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
#endif
#ifdef __mc68000
#define EXIT_TB() asm volatile ("rts")

9
dyngen-op.h Normal file
View File

@@ -0,0 +1,9 @@
static inline int gen_new_label(void)
{
return nb_gen_labels++;
}
static inline void gen_set_label(int n)
{
gen_labels[n] = gen_opc_ptr - gen_opc_buf;
}

2986
dyngen.c

File diff suppressed because it is too large Load Diff

233
dyngen.h
View File

@@ -19,6 +19,7 @@
*/
int __op_param1, __op_param2, __op_param3;
int __op_gen_label1, __op_gen_label2, __op_gen_label3;
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
@@ -27,6 +28,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
}
#endif
#ifdef __x86_64__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __s390__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
@@ -36,6 +43,11 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
#ifdef __ia64__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
while (start < stop) {
asm volatile ("fc %0" :: "r"(start));
start += 32;
}
asm volatile (";;sync.i;;srlz.i;;");
}
#endif
@@ -47,7 +59,7 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
p = start & ~(MIN_CACHE_LINE_SIZE - 1);
start &= ~(MIN_CACHE_LINE_SIZE - 1);
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
@@ -198,5 +210,220 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
#endif /* __arm__ */
#ifdef __ia64
/* Patch instruction with "val" where "mask" has 1 bits. */
static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
{
uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
# define insn_mask ((1UL << 41) - 1)
unsigned long shift;
b0 = b[0]; b1 = b[1];
shift = 5 + 41 * (insn_addr % 16); /* 5 template, 3 x 41-bit insns */
if (shift >= 64) {
m1 = mask << (shift - 64);
v1 = val << (shift - 64);
} else {
m0 = mask << shift; m1 = mask >> (64 - shift);
v0 = val << shift; v1 = val >> (64 - shift);
b[0] = (b0 & ~m0) | (v0 & m0);
}
b[1] = (b1 & ~m1) | (v1 & m1);
}
static inline void ia64_patch_imm60 (uint64_t insn_addr, uint64_t val)
{
ia64_patch(insn_addr,
0x011ffffe000UL,
( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
| ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */));
ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
}
static inline void ia64_imm64 (void *insn, uint64_t val)
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
uint64_t insn_addr = (uint64_t) insn & ~3UL;
ia64_patch(insn_addr + 2,
0x01fffefe000UL,
( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
| ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */
| ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */)
);
ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
}
static inline void ia64_imm60b (void *insn, uint64_t val)
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
uint64_t insn_addr = (uint64_t) insn & ~3UL;
if (val + ((uint64_t) 1 << 59) >= (1UL << 60))
fprintf(stderr, "%s: value %ld out of IMM60 range\n",
__FUNCTION__, (int64_t) val);
ia64_patch_imm60(insn_addr + 2, val);
}
static inline void ia64_imm22 (void *insn, uint64_t val)
{
if (val + (1 << 21) >= (1 << 22))
fprintf(stderr, "%s: value %li out of IMM22 range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x01fffcfe000UL,
( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
| ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
}
/* Like ia64_imm22(), but also clear bits 20-21. For addl, this has
the effect of turning "addl rX=imm22,rY" into "addl
rX=imm22,r0". */
static inline void ia64_imm22_r0 (void *insn, uint64_t val)
{
if (val + (1 << 21) >= (1 << 22))
fprintf(stderr, "%s: value %li out of IMM22 range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x01fffcfe000UL | (0x3UL << 20),
( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
| ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
}
static inline void ia64_imm21b (void *insn, uint64_t val)
{
if (val + (1 << 20) >= (1 << 21))
fprintf(stderr, "%s: value %li out of IMM21b range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x11ffffe000UL,
( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
| ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
}
static inline void ia64_nop_b (void *insn)
{
ia64_patch((uint64_t) insn, (1UL << 41) - 1, 2UL << 37);
}
static inline void ia64_ldxmov(void *insn, uint64_t val)
{
if (val + (1 << 21) < (1 << 22))
ia64_patch((uint64_t) insn, 0x1fff80fe000UL, 8UL << 37);
}
static inline int ia64_patch_ltoff(void *insn, uint64_t val,
int relaxable)
{
if (relaxable && (val + (1 << 21) < (1 << 22))) {
ia64_imm22_r0(insn, val);
return 0;
}
return 1;
}
struct ia64_fixup {
struct ia64_fixup *next;
void *addr; /* address that needs to be patched */
long value;
};
#define IA64_PLT(insn, plt_index) \
do { \
struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
fixup->next = plt_fixes; \
plt_fixes = fixup; \
fixup->addr = (insn); \
fixup->value = (plt_index); \
plt_offset[(plt_index)] = 1; \
} while (0)
#define IA64_LTOFF(insn, val, relaxable) \
do { \
if (ia64_patch_ltoff(insn, val, relaxable)) { \
struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
fixup->next = ltoff_fixes; \
ltoff_fixes = fixup; \
fixup->addr = (insn); \
fixup->value = (val); \
} \
} while (0)
static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
struct ia64_fixup *ltoff_fixes,
uint64_t gp,
struct ia64_fixup *plt_fixes,
int num_plts,
unsigned long *plt_target,
unsigned int *plt_offset)
{
static const uint8_t plt_bundle[] = {
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; movl r1=GP */
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0
};
uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start, *vp;
struct ia64_fixup *fixup;
unsigned int offset = 0;
struct fdesc {
long ip;
long gp;
} *fdesc;
int i;
if (plt_fixes) {
plt_start = gen_code_ptr;
for (i = 0; i < num_plts; ++i) {
if (plt_offset[i]) {
plt_offset[i] = offset;
offset += sizeof(plt_bundle);
fdesc = (struct fdesc *) plt_target[i];
memcpy(gen_code_ptr, plt_bundle, sizeof(plt_bundle));
ia64_imm64 (gen_code_ptr + 0x02, fdesc->gp);
ia64_imm60b(gen_code_ptr + 0x12,
(fdesc->ip - (long) (gen_code_ptr + 0x10)) >> 4);
gen_code_ptr += sizeof(plt_bundle);
}
}
for (fixup = plt_fixes; fixup; fixup = fixup->next)
ia64_imm21b(fixup->addr,
((long) plt_start + plt_offset[fixup->value]
- ((long) fixup->addr & ~0xf)) >> 4);
}
got_start = gen_code_ptr;
/* First, create the GOT: */
for (fixup = ltoff_fixes; fixup; fixup = fixup->next) {
/* first check if we already have this value in the GOT: */
for (vp = got_start; vp < gen_code_ptr; ++vp)
if (*(uint64_t *) vp == fixup->value)
break;
if (vp == gen_code_ptr) {
/* Nope, we need to put the value in the GOT: */
*(uint64_t *) vp = fixup->value;
gen_code_ptr += 8;
}
ia64_imm22(fixup->addr, (long) vp - gp);
}
/* Keep code ptr aligned. */
if ((long) gen_code_ptr & 15)
gen_code_ptr += 8;
*gen_code_pp = gen_code_ptr;
}
#endif

18
elf.h
View File

@@ -31,11 +31,29 @@ typedef int64_t Elf64_Sxword;
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
#define PT_MIPS_REGINFO 0x70000000
#define PT_MIPS_OPTIONS 0x70000001
/* Flags in the e_flags field of the header */
/* MIPS architecture level. */
#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
#define EF_MIPS_ARCH_32 0x50000000 /* MIPS32 code. */
#define EF_MIPS_ARCH_64 0x60000000 /* MIPS64 code. */
/* The ABI of a file. */
#define EF_MIPS_ABI_O32 0x00001000 /* O32 ABI. */
#define EF_MIPS_ABI_O64 0x00002000 /* O32 extended for 64 bit. */
#define EF_MIPS_NOREORDER 0x00000001
#define EF_MIPS_PIC 0x00000002
#define EF_MIPS_CPIC 0x00000004
#define EF_MIPS_ABI2 0x00000020
#define EF_MIPS_OPTIONS_FIRST 0x00000080
#define EF_MIPS_32BITMODE 0x00000100
#define EF_MIPS_ABI 0x0000f000
#define EF_MIPS_ARCH 0xf0000000
/* These constants define the different elf file types */

205
elf_ops.h Normal file
View File

@@ -0,0 +1,205 @@
static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
{
bswap16s(&ehdr->e_type); /* Object file type */
bswap16s(&ehdr->e_machine); /* Architecture */
bswap32s(&ehdr->e_version); /* Object file version */
bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
bswap32s(&ehdr->e_flags); /* Processor-specific flags */
bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
bswap16s(&ehdr->e_phnum); /* Program header table entry count */
bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
bswap16s(&ehdr->e_shnum); /* Section header table entry count */
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
}
static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
{
bswap32s(&phdr->p_type); /* Segment type */
bswapSZs(&phdr->p_offset); /* Segment file offset */
bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
bswapSZs(&phdr->p_paddr); /* Segment physical address */
bswapSZs(&phdr->p_filesz); /* Segment size in file */
bswapSZs(&phdr->p_memsz); /* Segment size in memory */
bswap32s(&phdr->p_flags); /* Segment flags */
bswapSZs(&phdr->p_align); /* Segment alignment */
}
static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
{
bswap32s(&shdr->sh_name);
bswap32s(&shdr->sh_type);
bswapSZs(&shdr->sh_flags);
bswapSZs(&shdr->sh_addr);
bswapSZs(&shdr->sh_offset);
bswapSZs(&shdr->sh_size);
bswap32s(&shdr->sh_link);
bswap32s(&shdr->sh_info);
bswapSZs(&shdr->sh_addralign);
bswapSZs(&shdr->sh_entsize);
}
static void glue(bswap_sym, SZ)(struct elf_sym *sym)
{
bswap32s(&sym->st_name);
bswapSZs(&sym->st_value);
bswapSZs(&sym->st_size);
bswap16s(&sym->st_shndx);
}
static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
int n, int type)
{
int i;
for(i=0;i<n;i++) {
if (shdr_table[i].sh_type == type)
return shdr_table + i;
}
return NULL;
}
static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
{
struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
struct elf_sym *syms = NULL;
#if (SZ == 64)
struct elf32_sym *syms32 = NULL;
#endif
struct syminfo *s;
int nsyms, i;
char *str = NULL;
shdr_table = load_at(fd, ehdr->e_shoff,
sizeof(struct elf_shdr) * ehdr->e_shnum);
if (!shdr_table)
return -1;
if (must_swab) {
for (i = 0; i < ehdr->e_shnum; i++) {
glue(bswap_shdr, SZ)(shdr_table + i);
}
}
symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
if (!symtab)
goto fail;
syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
if (!syms)
goto fail;
nsyms = symtab->sh_size / sizeof(struct elf_sym);
#if (SZ == 64)
syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
#endif
for (i = 0; i < nsyms; i++) {
if (must_swab)
glue(bswap_sym, SZ)(&syms[i]);
#if (SZ == 64)
syms32[i].st_name = syms[i].st_name;
syms32[i].st_info = syms[i].st_info;
syms32[i].st_other = syms[i].st_other;
syms32[i].st_shndx = syms[i].st_shndx;
syms32[i].st_value = syms[i].st_value & 0xffffffff;
syms32[i].st_size = syms[i].st_size & 0xffffffff;
#endif
}
/* String table */
if (symtab->sh_link >= ehdr->e_shnum)
goto fail;
strtab = &shdr_table[symtab->sh_link];
str = load_at(fd, strtab->sh_offset, strtab->sh_size);
if (!str)
goto fail;
/* Commit */
s = qemu_mallocz(sizeof(*s));
#if (SZ == 64)
s->disas_symtab = syms32;
qemu_free(syms);
#else
s->disas_symtab = syms;
#endif
s->disas_num_syms = nsyms;
s->disas_strtab = str;
s->next = syminfos;
syminfos = s;
qemu_free(shdr_table);
return 0;
fail:
#if (SZ == 64)
qemu_free(syms32);
#endif
qemu_free(syms);
qemu_free(str);
qemu_free(shdr_table);
return -1;
}
int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
int must_swab, uint64_t *pentry)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size;
elf_word mem_size, addr;
uint8_t *data = NULL;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto fail;
if (must_swab) {
glue(bswap_ehdr, SZ)(&ehdr);
}
if (pentry)
*pentry = (uint64_t)ehdr.e_entry;
glue(load_symbols, SZ)(&ehdr, fd, must_swab);
size = ehdr.e_phnum * sizeof(phdr[0]);
lseek(fd, ehdr.e_phoff, SEEK_SET);
phdr = qemu_mallocz(size);
if (!phdr)
goto fail;
if (read(fd, phdr, size) != size)
goto fail;
if (must_swab) {
for(i = 0; i < ehdr.e_phnum; i++) {
ph = &phdr[i];
glue(bswap_phdr, SZ)(ph);
}
}
total_size = 0;
for(i = 0; i < ehdr.e_phnum; i++) {
ph = &phdr[i];
if (ph->p_type == PT_LOAD) {
mem_size = ph->p_memsz;
/* XXX: avoid allocating */
data = qemu_mallocz(mem_size);
if (ph->p_filesz > 0) {
if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
goto fail;
if (read(fd, data, ph->p_filesz) != ph->p_filesz)
goto fail;
}
addr = ph->p_vaddr + virt_to_phys_addend;
cpu_physical_memory_write_rom(addr, data, mem_size);
total_size += mem_size;
qemu_free(data);
data = NULL;
}
}
qemu_free(phdr);
return total_size;
fail:
qemu_free(data);
qemu_free(phdr);
return -1;
}

View File

@@ -28,7 +28,7 @@
#define tostring(s) #s
#endif
#if GCC_MAJOR < 3
#if __GNUC__ < 3
#define __builtin_expect(x, n) (x)
#endif
@@ -55,10 +55,20 @@ struct TranslationBlock;
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
extern long gen_labels[OPC_BUF_SIZE];
extern int nb_gen_labels;
extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
extern target_ulong gen_opc_jump_pc[2];
extern uint32_t gen_opc_hflags[OPC_BUF_SIZE];
typedef void (GenOpFunc)(void);
typedef void (GenOpFunc1)(long);
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
#if defined(TARGET_I386)
void optimize_flags_init(void);
@@ -74,37 +84,102 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc);
void cpu_exec_init(void);
int page_unprotect(unsigned long address);
void tb_invalidate_page(unsigned long address);
void tlb_flush_page(CPUState *env, uint32_t addr);
void tlb_flush_page_write(CPUState *env, uint32_t addr);
void tlb_flush(CPUState *env);
CPUState *env, unsigned long searched_pc,
void *puc);
int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state_copy(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_exec_init(CPUState *env);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
int is_cpu_write_access);
void tb_invalidate_page_range(target_ulong start, target_ulong end);
void tlb_flush_page(CPUState *env, target_ulong addr);
void tlb_flush(CPUState *env, int flush_global);
int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu);
static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu)
{
if (prot & PAGE_READ)
prot |= PAGE_EXEC;
return tlb_set_page_exec(env, vaddr, paddr, prot, is_user, is_softmmu);
}
#define CODE_GEN_MAX_SIZE 65536
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
#define CODE_GEN_HASH_BITS 15
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
/* maximum total translate dcode allocated */
#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
/* NOTE: the translated code area cannot be too big because on some
archs the range of "fast" function calls is limited. Here is a
summary of the ranges:
i386 : signed 32 bits
arm : signed 26 bits
ppc : signed 24 bits
sparc : signed 32 bits
alpha : signed 23 bits
*/
#if defined(__alpha__)
#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
#elif defined(__ia64)
#define CODE_GEN_BUFFER_SIZE (4 * 1024 * 1024) /* range of addl */
#elif defined(__powerpc__)
#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
#else
#define CODE_GEN_BUFFER_SIZE (16 * 1024 * 1024)
#endif
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
#if defined(__powerpc__)
/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
according to the host CPU */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 128
#else
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
#if defined(__powerpc__)
#define USE_DIRECT_JUMP
#endif
#if defined(__i386__) && !defined(_WIN32)
#define USE_DIRECT_JUMP
#endif
typedef struct TranslationBlock {
unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */
unsigned long cs_base; /* CS base for this block */
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
unsigned int flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */
#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */
#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
uint8_t *tc_ptr; /* pointer to the translated code */
struct TranslationBlock *hash_next; /* next matching block */
struct TranslationBlock *page_next[2]; /* next blocks in even/odd page */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
target_ulong page_addr[2];
/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
@@ -121,46 +196,29 @@ typedef struct TranslationBlock {
struct TranslationBlock *jmp_first;
} TranslationBlock;
static inline unsigned int tb_hash_func(unsigned long pc)
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
{
return pc & (CODE_GEN_HASH_SIZE - 1);
return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
}
TranslationBlock *tb_alloc(unsigned long pc);
void tb_flush(CPUState *env);
void tb_link(TranslationBlock *tb);
static inline unsigned int tb_phys_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
TranslationBlock *tb_alloc(target_ulong pc);
void tb_flush(CPUState *env);
void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2);
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
extern uint8_t *code_gen_ptr;
/* find a translation block in the translation cache. If not found,
return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
unsigned long pc,
unsigned long cs_base,
unsigned int flags)
{
TranslationBlock **ptb, *tb;
unsigned int h;
h = tb_hash_func(pc);
ptb = &tb_hash[h];
for(;;) {
tb = *ptb;
if (!tb)
break;
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
return tb;
ptb = &tb->hash_next;
}
*pptb = ptb;
return NULL;
}
#if defined(USE_DIRECT_JUMP)
#if defined(__powerpc__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
uint32_t val, *ptr;
@@ -177,6 +235,14 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#elif defined(__i386__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
/* patch the branch destination */
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
/* no need to flush icache explicitely */
}
#endif
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
@@ -221,72 +287,76 @@ TranslationBlock *tb_find_pc(unsigned long pc_ptr);
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#if defined(_WIN32)
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".section .text\n"
#elif defined(__APPLE__)
#define ASM_DATA_SECTION ".data\n"
#define ASM_PREVIOUS_SECTION ".text\n"
#else
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".previous\n"
#endif
#define ASM_OP_LABEL_NAME(n, opname) \
ASM_NAME(__op_label) #n "." ASM_NAME(opname)
#if defined(__powerpc__)
/* on PowerPC we patch the jump instruction directly */
#define JUMP_TB(opname, tbparam, n, eip)\
/* we patch the jump instruction directly */
#define GOTO_TB(opname, tbparam, n)\
do {\
asm volatile (".section \".data\"\n"\
"__op_label" #n "." stringify(opname) ":\n"\
asm volatile (ASM_DATA_SECTION\
ASM_OP_LABEL_NAME(n, opname) ":\n"\
".long 1f\n"\
".previous\n"\
"b __op_jmp" #n "\n"\
ASM_PREVIOUS_SECTION \
"b " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
EXIT_TB();\
} while (0)
#define JUMP_TB2(opname, tbparam, n)\
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
/* we patch the jump instruction directly */
#define GOTO_TB(opname, tbparam, n)\
do {\
asm volatile ("b __op_jmp%0\n" : : "i" (n + 2));\
asm volatile (".section .data\n"\
ASM_OP_LABEL_NAME(n, opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"jmp " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
} while (0)
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define JUMP_TB(opname, tbparam, n, eip)\
#define GOTO_TB(opname, tbparam, n)\
do {\
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
static void __attribute__((unused)) *__op_label ## n \
__asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n:\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
dummy_label ## n:\
EXIT_TB();\
} while (0)
/* second jump to same destination 'n' */
#define JUMP_TB2(opname, tbparam, n)\
do {\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n: ;\
dummy_label ## n: ;\
} while (0)
#endif
/* physical memory access */
#define IO_MEM_NB_ENTRIES 256
#define TLB_INVALID_MASK (1 << 3)
#define IO_MEM_SHIFT 4
#define IO_MEM_UNASSIGNED (1 << IO_MEM_SHIFT)
unsigned long physpage_find(unsigned long page);
extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"0: lwarx %0,0,%1\n"
" xor. %0,%3,%0\n"
" bne 1f\n"
" stwcx. %2,0,%1\n"
" bne- 0b\n"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
@@ -298,14 +368,26 @@ static inline int testandset (int *p)
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
long int readval = 0;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
: "+m" (*p), "+a" (readval)
: "r" (1)
: "cc");
return readval;
}
#endif
#ifdef __x86_64__
static inline int testandset (int *p)
{
long int readval = 0;
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
: "+m" (*p), "+a" (readval)
: "r" (1)
: "cc");
return readval;
}
#endif
@@ -376,7 +458,16 @@ static inline int testandset (int *p)
: "=r" (ret)
: "m" (p)
: "cc","memory");
return ret == 0;
return ret;
}
#endif
#ifdef __ia64
#include <ia64intrin.h>
static inline int testandset (int *p)
{
return __sync_lock_test_and_set (p, 1);
}
#endif
@@ -418,9 +509,9 @@ extern spinlock_t tb_lock;
extern int tb_invalidated_flag;
#if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
#if !defined(CONFIG_USER_ONLY)
void tlb_fill(unsigned long addr, int is_write, int is_user,
void tlb_fill(target_ulong addr, int is_write, int is_user,
void *retaddr);
#define ACCESS_TYPE 3
@@ -436,8 +527,79 @@ void tlb_fill(unsigned long addr, int is_write, int is_user,
#define DATA_SIZE 4
#include "softmmu_header.h"
#define DATA_SIZE 8
#include "softmmu_header.h"
#undef ACCESS_TYPE
#undef MEMSUFFIX
#undef env
#endif
#if defined(CONFIG_USER_ONLY)
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
return addr;
}
#else
/* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it
is the offset relative to phys_ram_base */
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
int is_user, index, pd;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
#if defined(TARGET_I386)
is_user = ((env->hflags & HF_CPL_MASK) == 3);
#elif defined (TARGET_PPC)
is_user = msr_pr;
#elif defined (TARGET_MIPS)
is_user = ((env->hflags & MIPS_HFLAG_MODE) == MIPS_HFLAG_UM);
#elif defined (TARGET_SPARC)
is_user = (env->psrs == 0);
#elif defined (TARGET_ARM)
is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
#elif defined (TARGET_SH4)
is_user = ((env->sr & SR_MD) == 0);
#else
#error unimplemented CPU
#endif
if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
(addr & TARGET_PAGE_MASK), 0)) {
ldub_code(addr);
}
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM) {
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;
}
#endif
#ifdef USE_KQEMU
#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
int kqemu_init(CPUState *env);
int kqemu_cpu_exec(CPUState *env);
void kqemu_flush_page(CPUState *env, target_ulong addr);
void kqemu_flush(CPUState *env, int global);
void kqemu_set_notdirty(CPUState *env, ram_addr_t ram_addr);
void kqemu_modify_page(CPUState *env, ram_addr_t ram_addr);
void kqemu_cpu_interrupt(CPUState *env);
void kqemu_record_dump(void);
static inline int kqemu_is_ok(CPUState *env)
{
return(env->kqemu_enabled &&
(env->cr[0] & CR0_PE_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK) &&
(env->eflags & IF_MASK) &&
!(env->eflags & VM_MASK) &&
(env->kqemu_enabled == 2 ||
((env->hflags & HF_CPL_MASK) == 3 &&
(env->eflags & IOPL_MASK) != IOPL_MASK)));
}
#endif

2144
exec.c

File diff suppressed because it is too large Load Diff

720
fpu/softfloat-macros.h Normal file
View File

@@ -0,0 +1,720 @@
/*============================================================================
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 32, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
{
bits32 z;
if ( count == 0 ) {
z = a;
}
else if ( count < 32 ) {
z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
}
else {
z = ( a != 0 );
}
*zPtr = z;
}
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 64, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
{
bits64 z;
if ( count == 0 ) {
z = a;
}
else if ( count < 64 ) {
z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
}
else {
z = ( a != 0 );
}
*zPtr = z;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
| _plus_ the number of bits given in `count'. The shifted result is at most
| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
| bits shifted off form a second 64-bit result as follows: The _last_ bit
| shifted off is the most-significant bit of the extra result, and the other
| 63 bits of the extra result are all zero if and only if _all_but_the_last_
| bits shifted off were all zero. This extra result is stored in the location
| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0' and `a1' are considered to form
| a fixed-point value with binary point between `a0' and `a1'. This fixed-
| point value is shifted right by the number of bits given in `count', and
| the integer part of the result is returned at the location pointed to by
| `z0Ptr'. The fractional part of the result may be slightly corrupted as
| described above, and is returned at the location pointed to by `z1Ptr'.)
*----------------------------------------------------------------------------*/
INLINE void
shift64ExtraRightJamming(
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
{
bits64 z0, z1;
int8 negCount = ( - count ) & 63;
if ( count == 0 ) {
z1 = a1;
z0 = a0;
}
else if ( count < 64 ) {
z1 = ( a0<<negCount ) | ( a1 != 0 );
z0 = a0>>count;
}
else {
if ( count == 64 ) {
z1 = a0 | ( a1 != 0 );
}
else {
z1 = ( ( a0 | a1 ) != 0 );
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' can be arbitrarily large; in particular, if `count' is greater
| than 128, the result will be 0. The result is broken into two 64-bit pieces
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shift128Right(
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
{
bits64 z0, z1;
int8 negCount = ( - count ) & 63;
if ( count == 0 ) {
z1 = a1;
z0 = a0;
}
else if ( count < 64 ) {
z1 = ( a0<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. If any nonzero bits are shifted off, they
| are ``jammed'' into the least significant bit of the result by setting the
| least significant bit to 1. The value of `count' can be arbitrarily large;
| in particular, if `count' is greater than 128, the result will be either
| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
| nonzero. The result is broken into two 64-bit pieces which are stored at
| the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shift128RightJamming(
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
{
bits64 z0, z1;
int8 negCount = ( - count ) & 63;
if ( count == 0 ) {
z1 = a1;
z0 = a0;
}
else if ( count < 64 ) {
z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
z0 = a0>>count;
}
else {
if ( count == 64 ) {
z1 = a0 | ( a1 != 0 );
}
else if ( count < 128 ) {
z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
}
else {
z1 = ( ( a0 | a1 ) != 0 );
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
| by 64 _plus_ the number of bits given in `count'. The shifted result is
| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
| off form a third 64-bit result as follows: The _last_ bit shifted off is
| the most-significant bit of the extra result, and the other 63 bits of the
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
| were all zero. This extra result is stored in the location pointed to by
| `z2Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0', `a1', and `a2' are considered
| to form a fixed-point value with binary point between `a1' and `a2'. This
| fixed-point value is shifted right by the number of bits given in `count',
| and the integer part of the result is returned at the locations pointed to
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
| corrupted as described above, and is returned at the location pointed to by
| `z2Ptr'.)
*----------------------------------------------------------------------------*/
INLINE void
shift128ExtraRightJamming(
bits64 a0,
bits64 a1,
bits64 a2,
int16 count,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2;
int8 negCount = ( - count ) & 63;
if ( count == 0 ) {
z2 = a2;
z1 = a1;
z0 = a0;
}
else {
if ( count < 64 ) {
z2 = a1<<negCount;
z1 = ( a0<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
if ( count == 64 ) {
z2 = a1;
z1 = a0;
}
else {
a2 |= a1;
if ( count < 128 ) {
z2 = a0<<negCount;
z1 = a0>>( count & 63 );
}
else {
z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
z1 = 0;
}
}
z0 = 0;
}
z2 |= ( a2 != 0 );
}
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' must be less than 64. The result is broken into two 64-bit
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shortShift128Left(
bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
{
*z1Ptr = a1<<count;
*z0Ptr =
( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
}
/*----------------------------------------------------------------------------
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
| by the number of bits given in `count'. Any bits shifted off are lost.
| The value of `count' must be less than 64. The result is broken into three
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
| `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shortShift192Left(
bits64 a0,
bits64 a1,
bits64 a2,
int16 count,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2;
int8 negCount;
z2 = a2<<count;
z1 = a1<<count;
z0 = a0<<count;
if ( 0 < count ) {
negCount = ( ( - count ) & 63 );
z1 |= a2>>negCount;
z0 |= a1>>negCount;
}
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
| any carry out is lost. The result is broken into two 64-bit pieces which
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
add128(
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
{
bits64 z1;
z1 = a1 + b1;
*z1Ptr = z1;
*z0Ptr = a0 + b0 + ( z1 < a1 );
}
/*----------------------------------------------------------------------------
| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
| modulo 2^192, so any carry out is lost. The result is broken into three
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
| `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
add192(
bits64 a0,
bits64 a1,
bits64 a2,
bits64 b0,
bits64 b1,
bits64 b2,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2;
int8 carry0, carry1;
z2 = a2 + b2;
carry1 = ( z2 < a2 );
z1 = a1 + b1;
carry0 = ( z1 < a1 );
z0 = a0 + b0;
z1 += carry1;
z0 += ( z1 < carry1 );
z0 += carry0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
| 2^128, so any borrow out (carry out) is lost. The result is broken into two
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
| `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
sub128(
bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
{
*z1Ptr = a1 - b1;
*z0Ptr = a0 - b0 - ( a1 < b1 );
}
/*----------------------------------------------------------------------------
| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
| result is broken into three 64-bit pieces which are stored at the locations
| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
sub192(
bits64 a0,
bits64 a1,
bits64 a2,
bits64 b0,
bits64 b1,
bits64 b2,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2;
int8 borrow0, borrow1;
z2 = a2 - b2;
borrow1 = ( a2 < b2 );
z1 = a1 - b1;
borrow0 = ( a1 < b1 );
z0 = a0 - b0;
z0 -= ( z1 < borrow1 );
z1 -= borrow1;
z0 -= borrow0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
| into two 64-bit pieces which are stored at the locations pointed to by
| `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
{
bits32 aHigh, aLow, bHigh, bLow;
bits64 z0, zMiddleA, zMiddleB, z1;
aLow = a;
aHigh = a>>32;
bLow = b;
bHigh = b>>32;
z1 = ( (bits64) aLow ) * bLow;
zMiddleA = ( (bits64) aLow ) * bHigh;
zMiddleB = ( (bits64) aHigh ) * bLow;
z0 = ( (bits64) aHigh ) * bHigh;
zMiddleA += zMiddleB;
z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
zMiddleA <<= 32;
z1 += zMiddleA;
z0 += ( z1 < zMiddleA );
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
| `b' to obtain a 192-bit product. The product is broken into three 64-bit
| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
| `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
mul128By64To192(
bits64 a0,
bits64 a1,
bits64 b,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr
)
{
bits64 z0, z1, z2, more1;
mul64To128( a1, b, &z1, &z2 );
mul64To128( a0, b, &z0, &more1 );
add128( z0, more1, 0, z1, &z0, &z1 );
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
| product. The product is broken into four 64-bit pieces which are stored at
| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
mul128To256(
bits64 a0,
bits64 a1,
bits64 b0,
bits64 b1,
bits64 *z0Ptr,
bits64 *z1Ptr,
bits64 *z2Ptr,
bits64 *z3Ptr
)
{
bits64 z0, z1, z2, z3;
bits64 more1, more2;
mul64To128( a1, b1, &z2, &z3 );
mul64To128( a1, b0, &z1, &more2 );
add128( z1, more2, 0, z2, &z1, &z2 );
mul64To128( a0, b0, &z0, &more1 );
add128( z0, more1, 0, z1, &z0, &z1 );
mul64To128( a0, b1, &more1, &more2 );
add128( more1, more2, 0, z2, &more1, &z2 );
add128( z0, z1, 0, more1, &z0, &z1 );
*z3Ptr = z3;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Returns an approximation to the 64-bit integer quotient obtained by dividing
| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
| divisor `b' must be at least 2^63. If q is the exact quotient truncated
| toward zero, the approximation returned lies between q and q + 2 inclusive.
| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
| unsigned integer is returned.
*----------------------------------------------------------------------------*/
static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
{
bits64 b0, b1;
bits64 rem0, rem1, term0, term1;
bits64 z;
if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
b0 = b>>32;
z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
mul64To128( b, z, &term0, &term1 );
sub128( a0, a1, term0, term1, &rem0, &rem1 );
while ( ( (sbits64) rem0 ) < 0 ) {
z -= LIT64( 0x100000000 );
b1 = b<<32;
add128( rem0, rem1, b0, b1, &rem0, &rem1 );
}
rem0 = ( rem0<<32 ) | ( rem1>>32 );
z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
return z;
}
/*----------------------------------------------------------------------------
| Returns an approximation to the square root of the 32-bit significand given
| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
| `aExp' (the least significant bit) is 1, the integer returned approximates
| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
| case, the approximation returned lies strictly within +/-2 of the exact
| value.
*----------------------------------------------------------------------------*/
static bits32 estimateSqrt32( int16 aExp, bits32 a )
{
static const bits16 sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
};
static const bits16 sqrtEvenAdjustments[] = {
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
};
int8 index;
bits32 z;
index = ( a>>27 ) & 15;
if ( aExp & 1 ) {
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
z = ( ( a / z )<<14 ) + ( z<<15 );
a >>= 1;
}
else {
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
z = a / z + z;
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
}
return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
static int8 countLeadingZeros32( bits32 a )
{
static const int8 countLeadingZerosHigh[] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int8 shiftCount;
shiftCount = 0;
if ( a < 0x10000 ) {
shiftCount += 16;
a <<= 16;
}
if ( a < 0x1000000 ) {
shiftCount += 8;
a <<= 8;
}
shiftCount += countLeadingZerosHigh[ a>>24 ];
return shiftCount;
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 64 is returned.
*----------------------------------------------------------------------------*/
static int8 countLeadingZeros64( bits64 a )
{
int8 shiftCount;
shiftCount = 0;
if ( a < ( (bits64) 1 )<<32 ) {
shiftCount += 32;
}
else {
a >>= 32;
}
shiftCount += countLeadingZeros32( a );
return shiftCount;
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
{
return ( a0 == b0 ) && ( a1 == b1 );
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
{
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
| returns 0.
*----------------------------------------------------------------------------*/
INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
{
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
| not equal to the 128-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
{
return ( a0 != b0 ) || ( a1 != b1 );
}

363
fpu/softfloat-native.c Normal file
View File

@@ -0,0 +1,363 @@
/* Native implementation of soft float functions. Only a single status
context is supported */
#include "softfloat.h"
#include <math.h>
void set_float_rounding_mode(int val STATUS_PARAM)
{
STATUS(float_rounding_mode) = val;
#if defined(_BSD) && !defined(__APPLE__)
fpsetround(val);
#elif defined(__arm__)
/* nothing to do */
#else
fesetround(val);
#endif
}
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM)
{
STATUS(floatx80_rounding_precision) = val;
}
#endif
#if defined(_BSD)
#define lrint(d) ((long)rint(d))
#define llrint(d) ((long long)rint(d))
#endif
#if defined(__powerpc__)
/* correct (but slow) PowerPC rint() (glibc version is incorrect) */
double qemu_rint(double x)
{
double y = 4503599627370496.0;
if (fabs(x) >= y)
return x;
if (x < 0)
y = -y;
y = (x + y) - y;
if (y == 0.0)
y = copysign(y, x);
return y;
}
#define rint qemu_rint
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32(int v STATUS_PARAM)
{
return (float32)v;
}
float64 int32_to_float64(int v STATUS_PARAM)
{
return (float64)v;
}
#ifdef FLOATX80
floatx80 int32_to_floatx80(int v STATUS_PARAM)
{
return (floatx80)v;
}
#endif
float32 int64_to_float32( int64_t v STATUS_PARAM)
{
return (float32)v;
}
float64 int64_to_float64( int64_t v STATUS_PARAM)
{
return (float64)v;
}
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64_t v STATUS_PARAM)
{
return (floatx80)v;
}
#endif
/* XXX: this code implements the x86 behaviour, not the IEEE one. */
#if HOST_LONG_BITS == 32
static inline int long_to_int32(long a)
{
return a;
}
#else
static inline int long_to_int32(long a)
{
if (a != (int32_t)a)
a = 0x80000000;
return a;
}
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 a STATUS_PARAM)
{
return long_to_int32(lrintf(a));
}
int float32_to_int32_round_to_zero( float32 a STATUS_PARAM)
{
return (int)a;
}
int64_t float32_to_int64( float32 a STATUS_PARAM)
{
return llrintf(a);
}
int64_t float32_to_int64_round_to_zero( float32 a STATUS_PARAM)
{
return (int64_t)a;
}
float64 float32_to_float64( float32 a STATUS_PARAM)
{
return a;
}
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 a STATUS_PARAM)
{
return a;
}
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int( float32 a STATUS_PARAM)
{
return rintf(a);
}
float32 float32_rem( float32 a, float32 b STATUS_PARAM)
{
return remainderf(a, b);
}
float32 float32_sqrt( float32 a STATUS_PARAM)
{
return sqrtf(a);
}
char float32_compare( float32 a, float32 b STATUS_PARAM )
{
if (a < b) {
return -1;
} else if (a == b) {
return 0;
} else if (a > b) {
return 1;
} else {
return 2;
}
}
char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
} else if (a == b) {
return 0;
} else if (isgreater(a, b)) {
return 1;
} else {
return 2;
}
}
char float32_is_signaling_nan( float32 a1)
{
float32u u;
uint32_t a;
u.f = a1;
a = u.i;
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 a STATUS_PARAM)
{
return long_to_int32(lrint(a));
}
int float64_to_int32_round_to_zero( float64 a STATUS_PARAM)
{
return (int)a;
}
int64_t float64_to_int64( float64 a STATUS_PARAM)
{
return llrint(a);
}
int64_t float64_to_int64_round_to_zero( float64 a STATUS_PARAM)
{
return (int64_t)a;
}
float32 float64_to_float32( float64 a STATUS_PARAM)
{
return a;
}
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 a STATUS_PARAM)
{
return a;
}
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 a STATUS_PARAM)
{
return a;
}
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 a STATUS_PARAM )
{
#if defined(__arm__)
switch(STATUS(float_rounding_mode)) {
default:
case float_round_nearest_even:
asm("rndd %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_down:
asm("rnddm %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_up:
asm("rnddp %0, %1" : "=f" (a) : "f"(a));
break;
case float_round_to_zero:
asm("rnddz %0, %1" : "=f" (a) : "f"(a));
break;
}
#else
return rint(a);
#endif
}
float64 float64_rem( float64 a, float64 b STATUS_PARAM)
{
return remainder(a, b);
}
float64 float64_sqrt( float64 a STATUS_PARAM)
{
return sqrt(a);
}
char float64_compare( float64 a, float64 b STATUS_PARAM )
{
if (a < b) {
return -1;
} else if (a == b) {
return 0;
} else if (a > b) {
return 1;
} else {
return 2;
}
}
char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
} else if (a == b) {
return 0;
} else if (isgreater(a, b)) {
return 1;
} else {
return 2;
}
}
char float64_is_signaling_nan( float64 a1)
{
float64u u;
uint64_t a;
u.f = a1;
a = u.i;
return
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 a STATUS_PARAM)
{
return long_to_int32(lrintl(a));
}
int floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM)
{
return (int)a;
}
int64_t floatx80_to_int64( floatx80 a STATUS_PARAM)
{
return llrintl(a);
}
int64_t floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM)
{
return (int64_t)a;
}
float32 floatx80_to_float32( floatx80 a STATUS_PARAM)
{
return a;
}
float64 floatx80_to_float64( floatx80 a STATUS_PARAM)
{
return a;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
{
return rintl(a);
}
floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM)
{
return remainderl(a, b);
}
floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM)
{
return sqrtl(a);
}
char floatx80_compare( floatx80 a, floatx80 b STATUS_PARAM )
{
if (a < b) {
return -1;
} else if (a == b) {
return 0;
} else if (a > b) {
return 1;
} else {
return 2;
}
}
char floatx80_compare_quiet( floatx80 a, floatx80 b STATUS_PARAM )
{
if (isless(a, b)) {
return -1;
} else if (a == b) {
return 0;
} else if (isgreater(a, b)) {
return 1;
} else {
return 2;
}
}
char floatx80_is_signaling_nan( floatx80 a1)
{
floatx80u u;
u.f = a1;
return ( ( u.i.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( u.i.low<<1 );
}
#endif

359
fpu/softfloat-native.h Normal file
View File

@@ -0,0 +1,359 @@
/* Native implementation of soft float functions */
#include <math.h>
#if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
#include <ieeefp.h>
#define fabsf(f) ((float)fabs(f))
#else
#include <fenv.h>
#endif
/*
* Define some C99-7.12.3 classification macros and
* some C99-.12.4 for Solaris systems OS less than 10,
* or Solaris 10 systems running GCC 3.x or less.
* Solaris 10 with GCC4 does not need these macros as they
* are defined in <iso/math_c99.h> with a compiler directive
*/
#if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ( ( HOST_SOLARIS >= 10 ) && ( __GNUC__ <= 4) ))
/*
* C99 7.12.3 classification macros
* and
* C99 7.12.14 comparison macros
*
* ... do not work on Solaris 10 using GNU CC 3.4.x.
* Try to workaround the missing / broken C99 math macros.
*/
#define isnormal(x) (fpclass(x) >= FP_NZERO)
#define isgreater(x, y) ((!unordered(x, y)) && ((x) > (y)))
#define isgreaterequal(x, y) ((!unordered(x, y)) && ((x) >= (y)))
#define isless(x, y) ((!unordered(x, y)) && ((x) < (y)))
#define islessequal(x, y) ((!unordered(x, y)) && ((x) <= (y)))
#define isunordered(x,y) unordered(x, y)
#endif
typedef float float32;
typedef double float64;
#ifdef FLOATX80
typedef long double floatx80;
#endif
typedef union {
float32 f;
uint32_t i;
} float32u;
typedef union {
float64 f;
uint64_t i;
} float64u;
#ifdef FLOATX80
typedef union {
floatx80 f;
struct {
uint64_t low;
uint16_t high;
} i;
} floatx80u;
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
#if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
enum {
float_round_nearest_even = FP_RN,
float_round_down = FP_RM,
float_round_up = FP_RP,
float_round_to_zero = FP_RZ
};
#elif defined(__arm__)
enum {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
float_round_to_zero = 3
};
#else
enum {
float_round_nearest_even = FE_TONEAREST,
float_round_down = FE_DOWNWARD,
float_round_up = FE_UPWARD,
float_round_to_zero = FE_TOWARDZERO
};
#endif
typedef struct float_status {
signed char float_rounding_mode;
#ifdef FLOATX80
signed char floatx80_rounding_precision;
#endif
} float_status;
void set_float_rounding_mode(int val STATUS_PARAM);
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32( int STATUS_PARAM);
float64 int32_to_float64( int STATUS_PARAM);
#ifdef FLOATX80
floatx80 int32_to_floatx80( int STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 int32_to_float128( int STATUS_PARAM);
#endif
float32 int64_to_float32( int64_t STATUS_PARAM);
float64 int64_to_float64( int64_t STATUS_PARAM);
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 int64_to_float128( int64_t STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 STATUS_PARAM);
int float32_to_int32_round_to_zero( float32 STATUS_PARAM);
int64_t float32_to_int64( float32 STATUS_PARAM);
int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM);
float64 float32_to_float64( float32 STATUS_PARAM);
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 STATUS_PARAM);
#endif
#ifdef FLOAT128
float128 float32_to_float128( float32 STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int( float32 STATUS_PARAM);
INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
{
return a + b;
}
INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
{
return a - b;
}
INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
{
return a * b;
}
INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
{
return a / b;
}
float32 float32_rem( float32, float32 STATUS_PARAM);
float32 float32_sqrt( float32 STATUS_PARAM);
INLINE char float32_eq( float32 a, float32 b STATUS_PARAM)
{
return a == b;
}
INLINE char float32_le( float32 a, float32 b STATUS_PARAM)
{
return a <= b;
}
INLINE char float32_lt( float32 a, float32 b STATUS_PARAM)
{
return a < b;
}
INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char float32_unordered( float32 a, float32 b STATUS_PARAM)
{
return isunordered(a, b);
}
char float32_compare( float32, float32 STATUS_PARAM );
char float32_compare_quiet( float32, float32 STATUS_PARAM );
char float32_is_signaling_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
return fabsf(a);
}
INLINE float32 float32_chs(float32 a)
{
return -a;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 STATUS_PARAM );
int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
int64_t float64_to_int64( float64 STATUS_PARAM );
int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
float32 float64_to_float32( float64 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 STATUS_PARAM );
INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
{
return a + b;
}
INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
{
return a - b;
}
INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
{
return a * b;
}
INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
{
return a / b;
}
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
INLINE char float64_eq( float64 a, float64 b STATUS_PARAM)
{
return a == b;
}
INLINE char float64_le( float64 a, float64 b STATUS_PARAM)
{
return a <= b;
}
INLINE char float64_lt( float64 a, float64 b STATUS_PARAM)
{
return a < b;
}
INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char float64_unordered( float64 a, float64 b STATUS_PARAM)
{
return isunordered(a, b);
}
char float64_compare( float64, float64 STATUS_PARAM );
char float64_compare_quiet( float64, float64 STATUS_PARAM );
char float64_is_signaling_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
return fabs(a);
}
INLINE float64 float64_chs(float64 a)
{
return -a;
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 STATUS_PARAM );
int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
float32 floatx80_to_float32( floatx80 STATUS_PARAM );
float64 floatx80_to_float64( floatx80 STATUS_PARAM );
#ifdef FLOAT128
float128 floatx80_to_float128( floatx80 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
{
return a + b;
}
INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
{
return a - b;
}
INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
{
return a * b;
}
INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
{
return a / b;
}
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
{
return a == b;
}
INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b;
}
INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
{
return a < b;
}
INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
{
return a <= b && a >= b;
}
INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return islessequal(a, b);
}
INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
{
return isless(a, b);
}
INLINE char floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
{
return isunordered(a, b);
}
char floatx80_compare( floatx80, floatx80 STATUS_PARAM );
char floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_is_signaling_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
return fabsl(a);
}
INLINE floatx80 floatx80_chs(floatx80 a)
{
return -a;
}
#endif

464
fpu/softfloat-specialize.h Normal file
View File

@@ -0,0 +1,464 @@
/*============================================================================
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Underflow tininess-detection mode, statically initialized to default value.
| (The declaration in `softfloat.h' must match the `int8' type here.)
*----------------------------------------------------------------------------*/
int8 float_detect_tininess = float_tininess_after_rounding;
/*----------------------------------------------------------------------------
| Raises the exceptions specified by `flags'. Floating-point traps can be
| defined here if desired. It is currently not possible for such a trap
| to substitute a result value. If traps are not implemented, this routine
| should be simply `float_exception_flags |= flags;'.
*----------------------------------------------------------------------------*/
void float_raise( int8 flags STATUS_PARAM )
{
STATUS(float_exception_flags) |= flags;
}
/*----------------------------------------------------------------------------
| Internal canonical NaN format.
*----------------------------------------------------------------------------*/
typedef struct {
flag sign;
bits64 high, low;
} commonNaNT;
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
#define float32_default_nan 0xFFC00000
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_nan( float32 a )
{
return ( 0xFF000000 < (bits32) ( a<<1 ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_signaling_nan( float32 a )
{
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
{
commonNaNT z;
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
z.sign = a>>31;
z.low = 0;
z.high = ( (bits64) a )<<41;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the single-
| precision floating-point format.
*----------------------------------------------------------------------------*/
static float32 commonNaNToFloat32( commonNaNT a )
{
return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
}
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float32_is_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
bIsNaN = float32_is_nan( b );
bIsSignalingNaN = float32_is_signaling_nan( b );
a |= 0x00400000;
b |= 0x00400000;
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
return ( a < b ) ? a : b;
}
else {
return b;
}
}
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
#define float64_default_nan LIT64( 0xFFF8000000000000 )
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_nan( float64 a )
{
return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_signaling_nan( float64 a )
{
return
( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
}
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
{
commonNaNT z;
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
z.sign = a>>63;
z.low = 0;
z.high = a<<12;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the double-
| precision floating-point format.
*----------------------------------------------------------------------------*/
static float64 commonNaNToFloat64( commonNaNT a )
{
return
( ( (bits64) a.sign )<<63 )
| LIT64( 0x7FF8000000000000 )
| ( a.high>>12 );
}
/*----------------------------------------------------------------------------
| Takes two double-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float64_is_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
bIsNaN = float64_is_nan( b );
bIsSignalingNaN = float64_is_signaling_nan( b );
a |= LIT64( 0x0008000000000000 );
b |= LIT64( 0x0008000000000000 );
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
return ( a < b ) ? a : b;
}
else {
return b;
}
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN. The
| `high' and `low' values hold the most- and least-significant bits,
| respectively.
*----------------------------------------------------------------------------*/
#define floatx80_default_nan_high 0xFFFF
#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag floatx80_is_nan( floatx80 a )
{
return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag floatx80_is_signaling_nan( floatx80 a )
{
bits64 aLow;
aLow = a.low & ~ LIT64( 0x4000000000000000 );
return
( ( a.high & 0x7FFF ) == 0x7FFF )
&& (bits64) ( aLow<<1 )
&& ( a.low == aLow );
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
{
commonNaNT z;
if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
z.sign = a.high>>15;
z.low = 0;
z.high = a.low<<1;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the extended
| double-precision floating-point format.
*----------------------------------------------------------------------------*/
static floatx80 commonNaNToFloatx80( commonNaNT a )
{
floatx80 z;
z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
return z;
}
/*----------------------------------------------------------------------------
| Takes two extended double-precision floating-point values `a' and `b', one
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = floatx80_is_nan( a );
aIsSignalingNaN = floatx80_is_signaling_nan( a );
bIsNaN = floatx80_is_nan( b );
bIsSignalingNaN = floatx80_is_signaling_nan( b );
a.low |= LIT64( 0xC000000000000000 );
b.low |= LIT64( 0xC000000000000000 );
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( a.low < b.low ) return b;
if ( b.low < a.low ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
}
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN. The `high' and
| `low' values hold the most- and least-significant bits, respectively.
*----------------------------------------------------------------------------*/
#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
#define float128_default_nan_low LIT64( 0x0000000000000000 )
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float128_is_nan( float128 a )
{
return
( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
&& ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float128_is_signaling_nan( float128 a )
{
return
( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
&& ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
}
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
{
commonNaNT z;
if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
z.sign = a.high>>63;
shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the quadruple-
| precision floating-point format.
*----------------------------------------------------------------------------*/
static float128 commonNaNToFloat128( commonNaNT a )
{
float128 z;
shift128Right( a.high, a.low, 16, &z.high, &z.low );
z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
return z;
}
/*----------------------------------------------------------------------------
| Takes two quadruple-precision floating-point values `a' and `b', one of
| which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float128_is_nan( a );
aIsSignalingNaN = float128_is_signaling_nan( a );
bIsNaN = float128_is_nan( b );
bIsSignalingNaN = float128_is_signaling_nan( b );
a.high |= LIT64( 0x0000800000000000 );
b.high |= LIT64( 0x0000800000000000 );
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN | ! bIsNaN ) return a;
returnLargerSignificand:
if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
}
}
#endif

5320
fpu/softfloat.c Normal file

File diff suppressed because it is too large Load Diff

398
fpu/softfloat.h Normal file
View File

@@ -0,0 +1,398 @@
/*============================================================================
This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
#ifndef SOFTFLOAT_H
#define SOFTFLOAT_H
#include <inttypes.h>
#include "config.h"
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines the most convenient type that holds
| integers of at least as many bits as specified. For example, `uint8' should
| be the most convenient type that can hold unsigned integers of as many as
| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most
| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
| to the same as `int'.
*----------------------------------------------------------------------------*/
typedef char flag;
typedef uint8_t uint8;
typedef int8_t int8;
typedef int uint16;
typedef int int16;
typedef unsigned int uint32;
typedef signed int int32;
typedef uint64_t uint64;
typedef int64_t int64;
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines a type that holds integers
| of _exactly_ the number of bits specified. For instance, for most
| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
| `unsigned short int' and `signed short int' (or `short int'), respectively.
*----------------------------------------------------------------------------*/
typedef uint8_t bits8;
typedef int8_t sbits8;
typedef uint16_t bits16;
typedef int16_t sbits16;
typedef uint32_t bits32;
typedef int32_t sbits32;
typedef uint64_t bits64;
typedef int64_t sbits64;
#define LIT64( a ) a##LL
#define INLINE static inline
/*----------------------------------------------------------------------------
| The macro `FLOATX80' must be defined to enable the extended double-precision
| floating-point format `floatx80'. If this macro is not defined, the
| `floatx80' type will not be defined, and none of the functions that either
| input or output the `floatx80' type will be defined. The same applies to
| the `FLOAT128' macro and the quadruple-precision format `float128'.
*----------------------------------------------------------------------------*/
#ifdef CONFIG_SOFTFLOAT
/* bit exact soft float support */
#define FLOATX80
#define FLOAT128
#else
/* native float support */
#if (defined(__i386__) || defined(__x86_64__)) && !defined(_BSD)
#define FLOATX80
#endif
#endif /* !CONFIG_SOFTFLOAT */
#define STATUS_PARAM , float_status *status
#define STATUS(field) status->field
#define STATUS_VAR , status
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point ordering relations
*----------------------------------------------------------------------------*/
enum {
float_relation_less = -1,
float_relation_equal = 0,
float_relation_greater = 1,
float_relation_unordered = 2
};
#ifdef CONFIG_SOFTFLOAT
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types.
*----------------------------------------------------------------------------*/
typedef uint32_t float32;
typedef uint64_t float64;
#ifdef FLOATX80
typedef struct {
uint64_t low;
uint16_t high;
} floatx80;
#endif
#ifdef FLOAT128
typedef struct {
#ifdef WORDS_BIGENDIAN
uint64_t high, low;
#else
uint64_t low, high;
#endif
} float128;
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point underflow tininess-detection mode.
*----------------------------------------------------------------------------*/
enum {
float_tininess_after_rounding = 0,
float_tininess_before_rounding = 1
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
enum {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
float_round_to_zero = 3
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point exception flags.
*----------------------------------------------------------------------------*/
enum {
float_flag_invalid = 1,
float_flag_divbyzero = 4,
float_flag_overflow = 8,
float_flag_underflow = 16,
float_flag_inexact = 32
};
typedef struct float_status {
signed char float_detect_tininess;
signed char float_rounding_mode;
signed char float_exception_flags;
#ifdef FLOATX80
signed char floatx80_rounding_precision;
#endif
} float_status;
void set_float_rounding_mode(int val STATUS_PARAM);
void set_float_exception_flags(int val STATUS_PARAM);
INLINE int get_float_exception_flags(float_status *status)
{
return STATUS(float_exception_flags);
}
#ifdef FLOATX80
void set_floatx80_rounding_precision(int val STATUS_PARAM);
#endif
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software IEC/IEEE floating-point
| exception flags.
*----------------------------------------------------------------------------*/
void float_raise( int8 flags STATUS_PARAM);
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32( int STATUS_PARAM );
float64 int32_to_float64( int STATUS_PARAM );
float32 uint32_to_float32( unsigned int STATUS_PARAM );
float64 uint32_to_float64( unsigned int STATUS_PARAM );
#ifdef FLOATX80
floatx80 int32_to_floatx80( int STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 int32_to_float128( int STATUS_PARAM );
#endif
float32 int64_to_float32( int64_t STATUS_PARAM );
float64 int64_to_float64( int64_t STATUS_PARAM );
#ifdef FLOATX80
floatx80 int64_to_floatx80( int64_t STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 int64_to_float128( int64_t STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int float32_to_int32( float32 STATUS_PARAM );
int float32_to_int32_round_to_zero( float32 STATUS_PARAM );
unsigned int float32_to_uint32( float32 STATUS_PARAM );
unsigned int float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
int64_t float32_to_int64( float32 STATUS_PARAM );
int64_t float32_to_int64_round_to_zero( float32 STATUS_PARAM );
float64 float32_to_float64( float32 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float32_to_float128( float32 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int( float32 STATUS_PARAM );
float32 float32_add( float32, float32 STATUS_PARAM );
float32 float32_sub( float32, float32 STATUS_PARAM );
float32 float32_mul( float32, float32 STATUS_PARAM );
float32 float32_div( float32, float32 STATUS_PARAM );
float32 float32_rem( float32, float32 STATUS_PARAM );
float32 float32_sqrt( float32 STATUS_PARAM );
char float32_eq( float32, float32 STATUS_PARAM );
char float32_le( float32, float32 STATUS_PARAM );
char float32_lt( float32, float32 STATUS_PARAM );
char float32_eq_signaling( float32, float32 STATUS_PARAM );
char float32_le_quiet( float32, float32 STATUS_PARAM );
char float32_lt_quiet( float32, float32 STATUS_PARAM );
char float32_compare( float32, float32 STATUS_PARAM );
char float32_compare_quiet( float32, float32 STATUS_PARAM );
char float32_is_signaling_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
return a & 0x7fffffff;
}
INLINE float32 float32_chs(float32 a)
{
return a ^ 0x80000000;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
int float64_to_int32( float64 STATUS_PARAM );
int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
unsigned int float64_to_uint32( float64 STATUS_PARAM );
unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
int64_t float64_to_int64( float64 STATUS_PARAM );
int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
float32 float64_to_float32( float64 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float64_to_floatx80( float64 STATUS_PARAM );
#endif
#ifdef FLOAT128
float128 float64_to_float128( float64 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 STATUS_PARAM );
float64 float64_add( float64, float64 STATUS_PARAM );
float64 float64_sub( float64, float64 STATUS_PARAM );
float64 float64_mul( float64, float64 STATUS_PARAM );
float64 float64_div( float64, float64 STATUS_PARAM );
float64 float64_rem( float64, float64 STATUS_PARAM );
float64 float64_sqrt( float64 STATUS_PARAM );
char float64_eq( float64, float64 STATUS_PARAM );
char float64_le( float64, float64 STATUS_PARAM );
char float64_lt( float64, float64 STATUS_PARAM );
char float64_eq_signaling( float64, float64 STATUS_PARAM );
char float64_le_quiet( float64, float64 STATUS_PARAM );
char float64_lt_quiet( float64, float64 STATUS_PARAM );
char float64_compare( float64, float64 STATUS_PARAM );
char float64_compare_quiet( float64, float64 STATUS_PARAM );
char float64_is_signaling_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
return a & 0x7fffffffffffffffLL;
}
INLINE float64 float64_chs(float64 a)
{
return a ^ 0x8000000000000000LL;
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
int floatx80_to_int32( floatx80 STATUS_PARAM );
int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
int64_t floatx80_to_int64( floatx80 STATUS_PARAM );
int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
float32 floatx80_to_float32( floatx80 STATUS_PARAM );
float64 floatx80_to_float64( floatx80 STATUS_PARAM );
#ifdef FLOAT128
float128 floatx80_to_float128( floatx80 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
floatx80 floatx80_add( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sub( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
char floatx80_eq( floatx80, floatx80 STATUS_PARAM );
char floatx80_le( floatx80, floatx80 STATUS_PARAM );
char floatx80_lt( floatx80, floatx80 STATUS_PARAM );
char floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
char floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
char floatx80_is_signaling_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
a.high &= 0x7fff;
return a;
}
INLINE floatx80 floatx80_chs(floatx80 a)
{
a.high ^= 0x8000;
return a;
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision conversion routines.
*----------------------------------------------------------------------------*/
int float128_to_int32( float128 STATUS_PARAM );
int float128_to_int32_round_to_zero( float128 STATUS_PARAM );
int64_t float128_to_int64( float128 STATUS_PARAM );
int64_t float128_to_int64_round_to_zero( float128 STATUS_PARAM );
float32 float128_to_float32( float128 STATUS_PARAM );
float64 float128_to_float64( float128 STATUS_PARAM );
#ifdef FLOATX80
floatx80 float128_to_floatx80( float128 STATUS_PARAM );
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision operations.
*----------------------------------------------------------------------------*/
float128 float128_round_to_int( float128 STATUS_PARAM );
float128 float128_add( float128, float128 STATUS_PARAM );
float128 float128_sub( float128, float128 STATUS_PARAM );
float128 float128_mul( float128, float128 STATUS_PARAM );
float128 float128_div( float128, float128 STATUS_PARAM );
float128 float128_rem( float128, float128 STATUS_PARAM );
float128 float128_sqrt( float128 STATUS_PARAM );
char float128_eq( float128, float128 STATUS_PARAM );
char float128_le( float128, float128 STATUS_PARAM );
char float128_lt( float128, float128 STATUS_PARAM );
char float128_eq_signaling( float128, float128 STATUS_PARAM );
char float128_le_quiet( float128, float128 STATUS_PARAM );
char float128_lt_quiet( float128, float128 STATUS_PARAM );
char float128_is_signaling_nan( float128 );
INLINE float128 float128_abs(float128 a)
{
a.high &= 0x7fffffffffffffffLL;
return a;
}
INLINE float128 float128_chs(float128 a)
{
a.high ^= 0x8000000000000000LL;
return a;
}
#endif
#else /* CONFIG_SOFTFLOAT */
#include "softfloat-native.h"
#endif /* !CONFIG_SOFTFLOAT */
#endif /* !SOFTFLOAT_H */

1066
gdbstub.c

File diff suppressed because it is too large Load Diff

12
gdbstub.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef GDBSTUB_H
#define GDBSTUB_H
#define DEFAULT_GDBSTUB_PORT 1234
#ifdef CONFIG_USER_ONLY
int gdb_handlesig (CPUState *, int);
void gdb_exit(CPUState *, int);
#endif
int gdbserver_start(int);
#endif

410
hw/adb.c Normal file
View File

@@ -0,0 +1,410 @@
/*
* QEMU ADB support
*
* Copyright (c) 2004 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"
/* ADB commands */
#define ADB_BUSRESET 0x00
#define ADB_FLUSH 0x01
#define ADB_WRITEREG 0x08
#define ADB_READREG 0x0c
/* ADB device commands */
#define ADB_CMD_SELF_TEST 0xff
#define ADB_CMD_CHANGE_ID 0xfe
#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
/* ADB default device IDs (upper 4 bits of ADB command byte) */
#define ADB_DONGLE 1
#define ADB_KEYBOARD 2
#define ADB_MOUSE 3
#define ADB_TABLET 4
#define ADB_MODEM 5
#define ADB_MISC 7
/* error codes */
#define ADB_RET_NOTPRESENT (-2)
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
{
ADBDevice *d;
int devaddr, cmd, i;
cmd = buf[0] & 0xf;
if (cmd == ADB_BUSRESET) {
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devreset) {
d->devreset(d);
}
}
return 0;
}
devaddr = buf[0] >> 4;
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devaddr == devaddr) {
return d->devreq(d, obuf, buf, len);
}
}
return ADB_RET_NOTPRESENT;
}
/* XXX: move that to cuda ? */
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
ADBDevice *d;
int olen, i;
uint8_t buf[1];
olen = 0;
for(i = 0; i < s->nb_devices; i++) {
if (s->poll_index >= s->nb_devices)
s->poll_index = 0;
d = &s->devices[s->poll_index];
buf[0] = ADB_READREG | (d->devaddr << 4);
olen = adb_request(s, obuf + 1, buf, 1);
/* if there is data, we poll again the same device */
if (olen > 0) {
obuf[0] = buf[0];
olen++;
break;
}
s->poll_index++;
}
return olen;
}
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
ADBDeviceReset *devreset,
void *opaque)
{
ADBDevice *d;
if (s->nb_devices >= MAX_ADB_DEVICES)
return NULL;
d = &s->devices[s->nb_devices++];
d->bus = s;
d->devaddr = devaddr;
d->devreq = devreq;
d->devreset = devreset;
d->opaque = opaque;
return d;
}
/***************************************************************/
/* Keyboard ADB device */
typedef struct KBDState {
uint8_t data[128];
int rptr, wptr, count;
} KBDState;
static const uint8_t pc_to_adb_keycode[256] = {
0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static void adb_kbd_put_keycode(void *opaque, int keycode)
{
ADBDevice *d = opaque;
KBDState *s = d->opaque;
if (s->count < sizeof(s->data)) {
s->data[s->wptr] = keycode;
if (++s->wptr == sizeof(s->data))
s->wptr = 0;
s->count++;
}
}
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
{
static int ext_keycode;
KBDState *s = d->opaque;
int adb_keycode, keycode;
int olen;
olen = 0;
for(;;) {
if (s->count == 0)
break;
keycode = s->data[s->rptr];
if (++s->rptr == sizeof(s->data))
s->rptr = 0;
s->count--;
if (keycode == 0xe0) {
ext_keycode = 1;
} else {
if (ext_keycode)
adb_keycode = pc_to_adb_keycode[keycode | 0x80];
else
adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
obuf[0] = adb_keycode | (keycode & 0x80);
/* NOTE: could put a second keycode if needed */
obuf[1] = 0xff;
olen = 2;
ext_keycode = 0;
break;
}
}
return olen;
}
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
KBDState *s = d->opaque;
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
/* flush keyboard fifo */
s->wptr = s->rptr = s->count = 0;
return 0;
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
/* LED status */
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
d->handler = buf[2];
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 0:
olen = adb_kbd_poll(d, obuf);
break;
case 1:
break;
case 2:
obuf[0] = 0x00; /* XXX: check this */
obuf[1] = 0x07; /* led status */
olen = 2;
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
static int adb_kbd_reset(ADBDevice *d)
{
KBDState *s = d->opaque;
d->handler = 1;
d->devaddr = ADB_KEYBOARD;
memset(s, 0, sizeof(KBDState));
return 0;
}
void adb_kbd_init(ADBBusState *bus)
{
ADBDevice *d;
KBDState *s;
s = qemu_mallocz(sizeof(KBDState));
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request,
adb_kbd_reset, s);
adb_kbd_reset(d);
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}
/***************************************************************/
/* Mouse ADB device */
typedef struct MouseState {
int buttons_state, last_buttons_state;
int dx, dy, dz;
} MouseState;
static void adb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
ADBDevice *d = opaque;
MouseState *s = d->opaque;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
}
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
MouseState *s = d->opaque;
int dx, dy;
if (s->last_buttons_state == s->buttons_state &&
s->dx == 0 && s->dy == 0)
return 0;
dx = s->dx;
if (dx < -63)
dx = -63;
else if (dx > 63)
dx = 63;
dy = s->dy;
if (dy < -63)
dy = -63;
else if (dy > 63)
dy = 63;
s->dx -= dx;
s->dy -= dy;
s->last_buttons_state = s->buttons_state;
dx &= 0x7f;
dy &= 0x7f;
if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
dy |= 0x80;
if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
dx |= 0x80;
obuf[0] = dy;
obuf[1] = dx;
return 2;
}
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
MouseState *s = d->opaque;
int cmd, reg, olen;
if ((buf[0] & 0x0f) == ADB_FLUSH) {
/* flush mouse fifo */
s->buttons_state = s->last_buttons_state;
s->dx = 0;
s->dy = 0;
s->dz = 0;
return 0;
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 0:
olen = adb_mouse_poll(d, obuf);
break;
case 1:
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
static int adb_mouse_reset(ADBDevice *d)
{
MouseState *s = d->opaque;
d->handler = 2;
d->devaddr = ADB_MOUSE;
memset(s, 0, sizeof(MouseState));
return 0;
}
void adb_mouse_init(ADBBusState *bus)
{
ADBDevice *d;
MouseState *s;
s = qemu_mallocz(sizeof(MouseState));
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
adb_mouse_reset, s);
adb_mouse_reset(d);
qemu_add_mouse_event_handler(adb_mouse_event, d, 0);
}

341
hw/adlib.c Normal file
View File

@@ -0,0 +1,341 @@
/*
* QEMU Proxy for OPL2/3 emulation by MAME team
*
* Copyright (c) 2004-2005 Vassili Karpov (malc)
*
* 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 <assert.h>
#include "vl.h"
#define ADLIB_KILL_TIMERS 1
#define dolog(...) AUD_log ("adlib", __VA_ARGS__)
#ifdef DEBUG
#define ldebug(...) dolog (__VA_ARGS__)
#else
#define ldebug(...)
#endif
#ifdef HAS_YMF262
#include "ymf262.h"
void YMF262UpdateOneQEMU (int which, INT16 *dst, int length);
#define SHIFT 2
#else
#include "fmopl.h"
#define SHIFT 1
#endif
#define IO_READ_PROTO(name) \
uint32_t name (void *opaque, uint32_t nport)
#define IO_WRITE_PROTO(name) \
void name (void *opaque, uint32_t nport, uint32_t val)
static struct {
int port;
int freq;
} conf = {0x220, 44100};
typedef struct {
QEMUSoundCard card;
int ticking[2];
int enabled;
int active;
int bufpos;
#ifdef DEBUG
int64_t exp[2];
#endif
int16_t *mixbuf;
uint64_t dexp[2];
SWVoiceOut *voice;
int left, pos, samples;
QEMUAudioTimeStamp ats;
#ifndef HAS_YMF262
FM_OPL *opl;
#endif
} AdlibState;
static AdlibState glob_adlib;
static void adlib_stop_opl_timer (AdlibState *s, size_t n)
{
#ifdef HAS_YMF262
YMF262TimerOver (0, n);
#else
OPLTimerOver (s->opl, n);
#endif
s->ticking[n] = 0;
}
static void adlib_kill_timers (AdlibState *s)
{
size_t i;
for (i = 0; i < 2; ++i) {
if (s->ticking[i]) {
uint64_t delta;
delta = AUD_get_elapsed_usec_out (s->voice, &s->ats);
ldebug (
"delta = %f dexp = %f expired => %d\n",
delta / 1000000.0,
s->dexp[i] / 1000000.0,
delta >= s->dexp[i]
);
if (ADLIB_KILL_TIMERS || delta >= s->dexp[i]) {
adlib_stop_opl_timer (s, i);
AUD_init_time_stamp_out (s->voice, &s->ats);
}
}
}
}
static IO_WRITE_PROTO(adlib_write)
{
AdlibState *s = opaque;
int a = nport & 3;
int status;
s->active = 1;
AUD_set_active_out (s->voice, 1);
adlib_kill_timers (s);
#ifdef HAS_YMF262
status = YMF262Write (0, a, val);
#else
status = OPLWrite (s->opl, a, val);
#endif
}
static IO_READ_PROTO(adlib_read)
{
AdlibState *s = opaque;
uint8_t data;
int a = nport & 3;
adlib_kill_timers (s);
#ifdef HAS_YMF262
data = YMF262Read (0, a);
#else
data = OPLRead (s->opl, a);
#endif
return data;
}
static void timer_handler (int c, double interval_Sec)
{
AdlibState *s = &glob_adlib;
unsigned n = c & 1;
#ifdef DEBUG
double interval;
int64_t exp;
#endif
if (interval_Sec == 0.0) {
s->ticking[n] = 0;
return;
}
s->ticking[n] = 1;
#ifdef DEBUG
interval = ticks_per_sec * interval_Sec;
exp = qemu_get_clock (vm_clock) + interval;
s->exp[n] = exp;
#endif
s->dexp[n] = interval_Sec * 1000000.0;
AUD_init_time_stamp_out (s->voice, &s->ats);
}
static int write_audio (AdlibState *s, int samples)
{
int net = 0;
int pos = s->pos;
while (samples) {
int nbytes, wbytes, wsampl;
nbytes = samples << SHIFT;
wbytes = AUD_write (
s->voice,
s->mixbuf + (pos << (SHIFT - 1)),
nbytes
);
if (wbytes) {
wsampl = wbytes >> SHIFT;
samples -= wsampl;
pos = (pos + wsampl) % s->samples;
net += wsampl;
}
else {
break;
}
}
return net;
}
static void adlib_callback (void *opaque, int free)
{
AdlibState *s = opaque;
int samples, net = 0, to_play, written;
samples = free >> SHIFT;
if (!(s->active && s->enabled) || !samples) {
return;
}
to_play = audio_MIN (s->left, samples);
while (to_play) {
written = write_audio (s, to_play);
if (written) {
s->left -= written;
samples -= written;
to_play -= written;
s->pos = (s->pos + written) % s->samples;
}
else {
return;
}
}
samples = audio_MIN (samples, s->samples - s->pos);
if (!samples) {
return;
}
#ifdef HAS_YMF262
YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
#else
YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
#endif
while (samples) {
written = write_audio (s, samples);
if (written) {
net += written;
samples -= written;
s->pos = (s->pos + written) % s->samples;
}
else {
s->left = samples;
return;
}
}
}
static void Adlib_fini (AdlibState *s)
{
#ifdef HAS_YMF262
YMF262Shutdown ();
#else
if (s->opl) {
OPLDestroy (s->opl);
s->opl = NULL;
}
#endif
if (s->mixbuf) {
qemu_free (s->mixbuf);
}
s->active = 0;
s->enabled = 0;
AUD_remove_card (&s->card);
}
int Adlib_init (AudioState *audio)
{
AdlibState *s = &glob_adlib;
audsettings_t as;
if (!audio) {
dolog ("No audio state\n");
return -1;
}
#ifdef HAS_YMF262
if (YMF262Init (1, 14318180, conf.freq)) {
dolog ("YMF262Init %d failed\n", conf.freq);
return -1;
}
else {
YMF262SetTimerHandler (0, timer_handler, 0);
s->enabled = 1;
}
#else
s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
if (!s->opl) {
dolog ("OPLCreate %d failed\n", conf.freq);
return -1;
}
else {
OPLSetTimerHandler (s->opl, timer_handler, 0);
s->enabled = 1;
}
#endif
as.freq = conf.freq;
as.nchannels = SHIFT;
as.fmt = AUD_FMT_S16;
AUD_register_card (audio, "adlib", &s->card);
s->voice = AUD_open_out (
&s->card,
s->voice,
"adlib",
s,
adlib_callback,
&as,
0 /* XXX: little endian? */
);
if (!s->voice) {
Adlib_fini (s);
return -1;
}
s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT;
s->mixbuf = qemu_mallocz (s->samples << SHIFT);
if (!s->mixbuf) {
dolog ("Could not allocate mixing buffer, %d samples (each %d bytes)\n",
s->samples, 1 << SHIFT);
Adlib_fini (s);
return -1;
}
register_ioport_read (0x388, 4, 1, adlib_read, s);
register_ioport_write (0x388, 4, 1, adlib_write, s);
register_ioport_read (conf.port, 4, 1, adlib_read, s);
register_ioport_write (conf.port, 4, 1, adlib_write, s);
register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
return 0;
}

1042
hw/apic.c Normal file

File diff suppressed because it is too large Load Diff

105
hw/arm_boot.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* ARM kernel loader.
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GPL.
*/
#include "vl.h"
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
#define INITRD_LOAD_ADDR 0x00800000
/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */
static uint32_t bootloader[] = {
0xe3a00000, /* mov r0, #0 */
0xe3a01000, /* mov r1, #0x?? */
0xe3811c00, /* orr r1, r1, #0x??00 */
0xe59f2000, /* ldr r2, [pc, #0] */
0xe59ff000, /* ldr pc, [pc, #0] */
0, /* Address of kernel args. Set by integratorcp_init. */
0 /* Kernel entry point. Set by integratorcp_init. */
};
static void set_kernel_args(uint32_t ram_size, int initrd_size,
const char *kernel_cmdline)
{
uint32_t *p;
p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
/* ATAG_CORE */
stl_raw(p++, 5);
stl_raw(p++, 0x54410001);
stl_raw(p++, 1);
stl_raw(p++, 0x1000);
stl_raw(p++, 0);
/* ATAG_MEM */
stl_raw(p++, 4);
stl_raw(p++, 0x54410002);
stl_raw(p++, ram_size);
stl_raw(p++, 0);
if (initrd_size) {
/* ATAG_INITRD2 */
stl_raw(p++, 4);
stl_raw(p++, 0x54420005);
stl_raw(p++, INITRD_LOAD_ADDR);
stl_raw(p++, initrd_size);
}
if (kernel_cmdline && *kernel_cmdline) {
/* ATAG_CMDLINE */
int cmdline_size;
cmdline_size = strlen(kernel_cmdline);
memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
cmdline_size = (cmdline_size >> 2) + 1;
stl_raw(p++, cmdline_size + 2);
stl_raw(p++, 0x54410009);
p += cmdline_size;
}
/* ATAG_END */
stl_raw(p++, 0);
stl_raw(p++, 0);
}
void arm_load_kernel(int ram_size, const char *kernel_filename,
const char *kernel_cmdline, const char *initrd_filename,
int board_id)
{
int kernel_size;
int initrd_size;
int n;
/* Load the kernel. */
if (!kernel_filename) {
fprintf(stderr, "Kernel image must be specified\n");
exit(1);
}
kernel_size = load_image(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
exit(1);
}
if (initrd_filename) {
initrd_size = load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initrd '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_size = 0;
}
bootloader[1] |= board_id & 0xff;
bootloader[2] |= (board_id >> 8) & 0xff;
bootloader[5] = KERNEL_ARGS_ADDR;
bootloader[6] = KERNEL_LOAD_ADDR;
for (n = 0; n < sizeof(bootloader) / 4; n++)
stl_raw(phys_ram_base + (n * 4), bootloader[n]);
set_kernel_args(ram_size, initrd_size, kernel_cmdline);
}

73
hw/arm_pic.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* Generic ARM Programmable Interrupt Controller support.
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the LGPL
*/
#include "vl.h"
#include "arm_pic.h"
/* Stub functions for hardware that doesn't exist. */
void pic_set_irq(int irq, int level)
{
cpu_abort(cpu_single_env, "pic_set_irq");
}
void pic_info(void)
{
}
void irq_info(void)
{
}
void pic_set_irq_new(void *opaque, int irq, int level)
{
arm_pic_handler *p = (arm_pic_handler *)opaque;
/* Call the real handler. */
(*p)(opaque, irq, level);
}
/* Model the IRQ/FIQ CPU interrupt lines as a two input interrupt controller.
Input 0 is IRQ and input 1 is FIQ. */
typedef struct
{
arm_pic_handler handler;
CPUState *cpu_env;
} arm_pic_cpu_state;
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
arm_pic_cpu_state *s = (arm_pic_cpu_state *)opaque;
switch (irq) {
case ARM_PIC_CPU_IRQ:
if (level)
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
else
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
break;
case ARM_PIC_CPU_FIQ:
if (level)
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
else
cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
break;
default:
cpu_abort(s->cpu_env, "arm_pic_cpu_handler: Bad interrput line %d\n",
irq);
}
}
void *arm_pic_init_cpu(CPUState *env)
{
arm_pic_cpu_state *s;
s = (arm_pic_cpu_state *)malloc(sizeof(arm_pic_cpu_state));
s->handler = arm_pic_cpu_handler;
s->cpu_env = env;
return s;
}

27
hw/arm_pic.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* Generic ARM Programmable Interrupt Controller support.
*
* Copyright (c) 2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the LGPL.
*
* Arm hardware uses a wide variety of interrupt handling hardware.
* This provides a generic framework for connecting interrupt sources and
* inputs.
*/
#ifndef ARM_INTERRUPT_H
#define ARM_INTERRUPT_H 1
/* The first element of an individual PIC state structures should
be a pointer to the handler routine. */
typedef void (*arm_pic_handler)(void *opaque, int irq, int level);
/* The CPU is also modeled as an interrupt controller. */
#define ARM_PIC_CPU_IRQ 0
#define ARM_PIC_CPU_FIQ 1
void *arm_pic_init_cpu(CPUState *env);
#endif /* !ARM_INTERRUPT_H */

383
hw/arm_timer.c Normal file
View File

@@ -0,0 +1,383 @@
/*
* ARM PrimeCell Timer modules.
*
* Copyright (c) 2005-2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GPL.
*/
#include "vl.h"
#include "arm_pic.h"
/* Common timer implementation. */
#define TIMER_CTRL_ONESHOT (1 << 0)
#define TIMER_CTRL_32BIT (1 << 1)
#define TIMER_CTRL_DIV1 (0 << 2)
#define TIMER_CTRL_DIV16 (1 << 2)
#define TIMER_CTRL_DIV256 (2 << 2)
#define TIMER_CTRL_IE (1 << 5)
#define TIMER_CTRL_PERIODIC (1 << 6)
#define TIMER_CTRL_ENABLE (1 << 7)
typedef struct {
int64_t next_time;
int64_t expires;
int64_t loaded;
QEMUTimer *timer;
uint32_t control;
uint32_t count;
uint32_t limit;
int raw_freq;
int freq;
int int_level;
void *pic;
int irq;
} arm_timer_state;
/* Calculate the new expiry time of the given timer. */
static void arm_timer_reload(arm_timer_state *s)
{
int64_t delay;
s->loaded = s->expires;
delay = muldiv64(s->count, ticks_per_sec, s->freq);
if (delay == 0)
delay = 1;
s->expires += delay;
}
/* Check all active timers, and schedule the next timer interrupt. */
static void arm_timer_update(arm_timer_state *s, int64_t now)
{
int64_t next;
/* Ignore disabled timers. */
if ((s->control & TIMER_CTRL_ENABLE) == 0)
return;
/* Ignore expired one-shot timers. */
if (s->count == 0 && (s->control & TIMER_CTRL_ONESHOT))
return;
if (s->expires - now <= 0) {
/* Timer has expired. */
s->int_level = 1;
if (s->control & TIMER_CTRL_ONESHOT) {
/* One-shot. */
s->count = 0;
} else {
if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
/* Free running. */
if (s->control & TIMER_CTRL_32BIT)
s->count = 0xffffffff;
else
s->count = 0xffff;
} else {
/* Periodic. */
s->count = s->limit;
}
}
}
while (s->expires - now <= 0) {
arm_timer_reload(s);
}
/* Update interrupts. */
if (s->int_level && (s->control & TIMER_CTRL_IE)) {
pic_set_irq_new(s->pic, s->irq, 1);
} else {
pic_set_irq_new(s->pic, s->irq, 0);
}
next = now;
if (next - s->expires < 0)
next = s->expires;
/* Schedule the next timer interrupt. */
if (next == now) {
qemu_del_timer(s->timer);
s->next_time = 0;
} else if (next != s->next_time) {
qemu_mod_timer(s->timer, next);
s->next_time = next;
}
}
/* Return the current value of the timer. */
static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
{
int64_t elapsed;
int64_t period;
if (s->count == 0)
return 0;
if ((s->control & TIMER_CTRL_ENABLE) == 0)
return s->count;
elapsed = now - s->loaded;
period = s->expires - s->loaded;
/* If the timer should have expired then return 0. This can happen
when the host timer signal doesnt occur immediately. It's better to
have a timer appear to sit at zero for a while than have it wrap
around before the guest interrupt is raised. */
/* ??? Could we trigger the interrupt here? */
if (elapsed > period)
return 0;
/* We need to calculate count * elapsed / period without overfowing.
Scale both elapsed and period so they fit in a 32-bit int. */
while (period != (int32_t)period) {
period >>= 1;
elapsed >>= 1;
}
return ((uint64_t)s->count * (uint64_t)(int32_t)elapsed)
/ (int32_t)period;
}
uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
{
arm_timer_state *s = (arm_timer_state *)opaque;
switch (offset >> 2) {
case 0: /* TimerLoad */
case 6: /* TimerBGLoad */
return s->limit;
case 1: /* TimerValue */
return arm_timer_getcount(s, qemu_get_clock(vm_clock));
case 2: /* TimerControl */
return s->control;
case 4: /* TimerRIS */
return s->int_level;
case 5: /* TimerMIS */
if ((s->control & TIMER_CTRL_IE) == 0)
return 0;
return s->int_level;
default:
cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n", offset);
return 0;
}
}
static void arm_timer_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
arm_timer_state *s = (arm_timer_state *)opaque;
int64_t now;
now = qemu_get_clock(vm_clock);
switch (offset >> 2) {
case 0: /* TimerLoad */
s->limit = value;
s->count = value;
s->expires = now;
arm_timer_reload(s);
break;
case 1: /* TimerValue */
/* ??? Linux seems to want to write to this readonly register.
Ignore it. */
break;
case 2: /* TimerControl */
if (s->control & TIMER_CTRL_ENABLE) {
/* Pause the timer if it is running. This may cause some
inaccuracy dure to rounding, but avoids a whole lot of other
messyness. */
s->count = arm_timer_getcount(s, now);
}
s->control = value;
s->freq = s->raw_freq;
/* ??? Need to recalculate expiry time after changing divisor. */
switch ((value >> 2) & 3) {
case 1: s->freq >>= 4; break;
case 2: s->freq >>= 8; break;
}
if (s->control & TIMER_CTRL_ENABLE) {
/* Restart the timer if still enabled. */
s->expires = now;
arm_timer_reload(s);
}
break;
case 3: /* TimerIntClr */
s->int_level = 0;
break;
case 6: /* TimerBGLoad */
s->limit = value;
break;
default:
cpu_abort (cpu_single_env, "arm_timer_write: Bad offset %x\n", offset);
}
arm_timer_update(s, now);
}
static void arm_timer_tick(void *opaque)
{
int64_t now;
now = qemu_get_clock(vm_clock);
arm_timer_update((arm_timer_state *)opaque, now);
}
static void *arm_timer_init(uint32_t freq, void *pic, int irq)
{
arm_timer_state *s;
s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
s->pic = pic;
s->irq = irq;
s->raw_freq = s->freq = 1000000;
s->control = TIMER_CTRL_IE;
s->count = 0xffffffff;
s->timer = qemu_new_timer(vm_clock, arm_timer_tick, s);
/* ??? Save/restore. */
return s;
}
/* ARM PrimeCell SP804 dual timer module.
Docs for this device don't seem to be publicly available. This
implementation is based on gueswork, the linux kernel sources and the
Integrator/CP timer modules. */
typedef struct {
/* Include a pseudo-PIC device to merge the two interrupt sources. */
arm_pic_handler handler;
void *timer[2];
int level[2];
uint32_t base;
/* The output PIC device. */
void *pic;
int irq;
} sp804_state;
static void sp804_set_irq(void *opaque, int irq, int level)
{
sp804_state *s = (sp804_state *)opaque;
s->level[irq] = level;
pic_set_irq_new(s->pic, s->irq, s->level[0] || s->level[1]);
}
static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
{
sp804_state *s = (sp804_state *)opaque;
/* ??? Don't know the PrimeCell ID for this device. */
offset -= s->base;
if (offset < 0x20) {
return arm_timer_read(s->timer[0], offset);
} else {
return arm_timer_read(s->timer[1], offset - 0x20);
}
}
static void sp804_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
sp804_state *s = (sp804_state *)opaque;
offset -= s->base;
if (offset < 0x20) {
arm_timer_write(s->timer[0], offset, value);
} else {
arm_timer_write(s->timer[1], offset - 0x20, value);
}
}
static CPUReadMemoryFunc *sp804_readfn[] = {
sp804_read,
sp804_read,
sp804_read
};
static CPUWriteMemoryFunc *sp804_writefn[] = {
sp804_write,
sp804_write,
sp804_write
};
void sp804_init(uint32_t base, void *pic, int irq)
{
int iomemtype;
sp804_state *s;
s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
s->handler = sp804_set_irq;
s->base = base;
s->pic = pic;
s->irq = irq;
/* ??? The timers are actually configurable between 32kHz and 1MHz, but
we don't implement that. */
s->timer[0] = arm_timer_init(1000000, s, 0);
s->timer[1] = arm_timer_init(1000000, s, 1);
iomemtype = cpu_register_io_memory(0, sp804_readfn,
sp804_writefn, s);
cpu_register_physical_memory(base, 0x00000fff, iomemtype);
/* ??? Save/restore. */
}
/* Integrator/CP timer module. */
typedef struct {
void *timer[3];
uint32_t base;
} icp_pit_state;
static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
{
icp_pit_state *s = (icp_pit_state *)opaque;
int n;
/* ??? Don't know the PrimeCell ID for this device. */
offset -= s->base;
n = offset >> 8;
if (n > 3)
cpu_abort(cpu_single_env, "sp804_read: Bad timer %d\n", n);
return arm_timer_read(s->timer[n], offset & 0xff);
}
static void icp_pit_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
icp_pit_state *s = (icp_pit_state *)opaque;
int n;
offset -= s->base;
n = offset >> 8;
if (n > 3)
cpu_abort(cpu_single_env, "sp804_write: Bad timer %d\n", n);
arm_timer_write(s->timer[n], offset & 0xff, value);
}
static CPUReadMemoryFunc *icp_pit_readfn[] = {
icp_pit_read,
icp_pit_read,
icp_pit_read
};
static CPUWriteMemoryFunc *icp_pit_writefn[] = {
icp_pit_write,
icp_pit_write,
icp_pit_write
};
void icp_pit_init(uint32_t base, void *pic, int irq)
{
int iomemtype;
icp_pit_state *s;
s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
s->base = base;
/* Timer 0 runs at the system clock speed (40MHz). */
s->timer[0] = arm_timer_init(40000000, pic, irq);
/* The other two timers run at 1MHz. */
s->timer[1] = arm_timer_init(1000000, pic, irq + 1);
s->timer[2] = arm_timer_init(1000000, pic, irq + 2);
iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
icp_pit_writefn, s);
cpu_register_physical_memory(base, 0x00000fff, iomemtype);
/* ??? Save/restore. */
}

3193
hw/cirrus_vga.c Normal file

File diff suppressed because it is too large Load Diff

78
hw/cirrus_vga_rop.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 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.
*/
static void
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst++;
src++;
}
dst += dstpitch;
src += srcpitch;
}
}
static void
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch += bltwidth;
srcpitch += bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst--;
src--;
}
dst += dstpitch;
src += srcpitch;
}
}
#define DEPTH 8
#include "cirrus_vga_rop2.h"
#define DEPTH 16
#include "cirrus_vga_rop2.h"
#define DEPTH 24
#include "cirrus_vga_rop2.h"
#define DEPTH 32
#include "cirrus_vga_rop2.h"
#undef ROP_NAME
#undef ROP_OP

281
hw/cirrus_vga_rop2.h Normal file
View File

@@ -0,0 +1,281 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 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.
*/
#if DEPTH == 8
#define PUTPIXEL() ROP_OP(d[0], col)
#elif DEPTH == 16
#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
#elif DEPTH == 24
#define PUTPIXEL() ROP_OP(d[0], col); \
ROP_OP(d[1], (col >> 8)); \
ROP_OP(d[2], (col >> 16))
#elif DEPTH == 32
#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
#else
#error unsupported DEPTH
#endif
static void
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, pattern_y, pattern_pitch, pattern_x;
unsigned int col;
const uint8_t *src1;
#if DEPTH == 24
int skipleft = s->gr[0x2f] & 0x1f;
#else
int skipleft = (s->gr[0x2f] & 0x07) * (DEPTH / 8);
#endif
#if DEPTH == 8
pattern_pitch = 8;
#elif DEPTH == 16
pattern_pitch = 16;
#else
pattern_pitch = 32;
#endif
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
pattern_x = skipleft;
d = dst + skipleft;
src1 = src + pattern_y * pattern_pitch;
for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) {
#if DEPTH == 8
col = src1[pattern_x];
pattern_x = (pattern_x + 1) & 7;
#elif DEPTH == 16
col = ((uint16_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 2) & 15;
#elif DEPTH == 24
{
const uint8_t *src2 = src1 + pattern_x * 3;
col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
pattern_x = (pattern_x + 1) & 7;
}
#else
col = ((uint32_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 4) & 31;
#endif
PUTPIXEL();
d += (DEPTH / 8);
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
/* NOTE: srcpitch is ignored */
static void
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y;
unsigned bits, bits_xor;
unsigned int col;
unsigned bitmask;
unsigned index;
#if DEPTH == 24
int dstskipleft = s->gr[0x2f] & 0x1f;
int srcskipleft = dstskipleft / 3;
#else
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++ ^ bits_xor;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++ ^ bits_xor;
}
index = (bits & bitmask);
if (index) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y;
unsigned bits;
unsigned int col;
unsigned bitmask;
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
col = colors[!!(bits & bitmask)];
PUTPIXEL();
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits, bits_xor;
unsigned int col;
#if DEPTH == 24
int dstskipleft = s->gr[0x2f] & 0x1f;
int srcskipleft = dstskipleft / 3;
#else
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
#endif
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y] ^ bits_xor;
bitpos = 7 - srcskipleft;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
if ((bits >> bitpos) & 1) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits;
unsigned int col;
int srcskipleft = s->gr[0x2f] & 0x07;
int dstskipleft = srcskipleft * (DEPTH / 8);
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y];
bitpos = 7 - srcskipleft;
d = dst + dstskipleft;
for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) {
col = colors[(bits >> bitpos) & 1];
PUTPIXEL();
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
(CirrusVGAState *s,
uint8_t *dst, int dst_pitch,
int width, int height)
{
uint8_t *d, *d1;
uint32_t col;
int x, y;
col = s->cirrus_blt_fgcol;
d1 = dst;
for(y = 0; y < height; y++) {
d = d1;
for(x = 0; x < width; x += (DEPTH / 8)) {
PUTPIXEL();
d += (DEPTH / 8);
}
d1 += dst_pitch;
}
}
#undef DEPTH
#undef PUTPIXEL

656
hw/cuda.c Normal file
View File

@@ -0,0 +1,656 @@
/*
* QEMU CUDA support
*
* Copyright (c) 2004 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"
/* XXX: implement all timer modes */
//#define DEBUG_CUDA
//#define DEBUG_CUDA_PACKET
/* Bits in B data register: all active low */
#define TREQ 0x08 /* Transfer request (input) */
#define TACK 0x10 /* Transfer acknowledge (output) */
#define TIP 0x20 /* Transfer in progress (output) */
/* Bits in ACR */
#define SR_CTRL 0x1c /* Shift register control bits */
#define SR_EXT 0x0c /* Shift on external clock */
#define SR_OUT 0x10 /* Shift out if 1 */
/* Bits in IFR and IER */
#define IER_SET 0x80 /* set bits in IER */
#define IER_CLR 0 /* clear bits in IER */
#define SR_INT 0x04 /* Shift register full/empty */
#define T1_INT 0x40 /* Timer 1 interrupt */
#define T2_INT 0x20 /* Timer 2 interrupt */
/* Bits in ACR */
#define T1MODE 0xc0 /* Timer 1 mode */
#define T1MODE_CONT 0x40 /* continuous interrupts */
/* commands (1st byte) */
#define ADB_PACKET 0
#define CUDA_PACKET 1
#define ERROR_PACKET 2
#define TIMER_PACKET 3
#define POWER_PACKET 4
#define MACIIC_PACKET 5
#define PMU_PACKET 6
/* CUDA commands (2nd byte) */
#define CUDA_WARM_START 0x0
#define CUDA_AUTOPOLL 0x1
#define CUDA_GET_6805_ADDR 0x2
#define CUDA_GET_TIME 0x3
#define CUDA_GET_PRAM 0x7
#define CUDA_SET_6805_ADDR 0x8
#define CUDA_SET_TIME 0x9
#define CUDA_POWERDOWN 0xa
#define CUDA_POWERUP_TIME 0xb
#define CUDA_SET_PRAM 0xc
#define CUDA_MS_RESET 0xd
#define CUDA_SEND_DFAC 0xe
#define CUDA_BATTERY_SWAP_SENSE 0x10
#define CUDA_RESET_SYSTEM 0x11
#define CUDA_SET_IPL 0x12
#define CUDA_FILE_SERVER_FLAG 0x13
#define CUDA_SET_AUTO_RATE 0x14
#define CUDA_GET_AUTO_RATE 0x16
#define CUDA_SET_DEVICE_LIST 0x19
#define CUDA_GET_DEVICE_LIST 0x1a
#define CUDA_SET_ONE_SECOND_MODE 0x1b
#define CUDA_SET_POWER_MESSAGES 0x21
#define CUDA_GET_SET_IIC 0x22
#define CUDA_WAKEUP 0x23
#define CUDA_TIMER_TICKLE 0x24
#define CUDA_COMBINED_FORMAT_IIC 0x25
#define CUDA_TIMER_FREQ (4700000 / 6)
#define CUDA_ADB_POLL_FREQ 50
/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
#define RTC_OFFSET 2082844800
typedef struct CUDATimer {
int index;
uint16_t latch;
uint16_t counter_value; /* counter value at load time */
int64_t load_time;
int64_t next_irq_time;
QEMUTimer *timer;
} CUDATimer;
typedef struct CUDAState {
/* cuda registers */
uint8_t b; /* B-side data */
uint8_t a; /* A-side data */
uint8_t dirb; /* B-side direction (1=output) */
uint8_t dira; /* A-side direction (1=output) */
uint8_t sr; /* Shift register */
uint8_t acr; /* Auxiliary control register */
uint8_t pcr; /* Peripheral control register */
uint8_t ifr; /* Interrupt flag register */
uint8_t ier; /* Interrupt enable register */
uint8_t anh; /* A-side data, no handshake */
CUDATimer timers[2];
uint8_t last_b; /* last value of B register */
uint8_t last_acr; /* last value of B register */
int data_in_size;
int data_in_index;
int data_out_index;
SetIRQFunc *set_irq;
int irq;
void *irq_opaque;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
QEMUTimer *adb_poll_timer;
} CUDAState;
static CUDAState cuda_state;
ADBBusState adb_bus;
static void cuda_update(CUDAState *s);
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time);
static void cuda_update_irq(CUDAState *s)
{
if (s->ifr & s->ier & (SR_INT | T1_INT)) {
s->set_irq(s->irq_opaque, s->irq, 1);
} else {
s->set_irq(s->irq_opaque, s->irq, 0);
}
}
static unsigned int get_counter(CUDATimer *s)
{
int64_t d;
unsigned int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (s->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (s->counter_value + 1)) {
counter = (s->counter_value - d) & 0xffff;
} else {
counter = (d - (s->counter_value + 1)) % (s->latch + 2);
counter = (s->latch - counter) & 0xffff;
}
} else {
counter = (s->counter_value - d) & 0xffff;
}
return counter;
}
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
#ifdef DEBUG_CUDA
printf("cuda: T%d.counter=%d\n",
1 + (ti->timer == NULL), val);
#endif
ti->load_time = qemu_get_clock(vm_clock);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
{
int64_t d, next_time;
unsigned int counter;
/* current counter value */
d = muldiv64(current_time - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (s->counter_value + 1)) {
counter = (s->counter_value - d) & 0xffff;
} else {
counter = (d - (s->counter_value + 1)) % (s->latch + 2);
counter = (s->latch - counter) & 0xffff;
}
/* Note: we consider the irq is raised on 0 */
if (counter == 0xffff) {
next_time = d + s->latch + 1;
} else if (counter == 0) {
next_time = d + s->latch + 2;
} else {
next_time = d + counter;
}
#if 0
#ifdef DEBUG_CUDA
printf("latch=%d counter=%lld delta_next=%lld\n",
s->latch, d, next_time - d);
#endif
#endif
next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
s->load_time;
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time)
{
if (!ti->timer)
return;
if ((s->acr & T1MODE) != T1MODE_CONT) {
qemu_del_timer(ti->timer);
} else {
ti->next_irq_time = get_next_irq_time(ti, current_time);
qemu_mod_timer(ti->timer, ti->next_irq_time);
}
}
static void cuda_timer1(void *opaque)
{
CUDAState *s = opaque;
CUDATimer *ti = &s->timers[0];
cuda_timer_update(s, ti, ti->next_irq_time);
s->ifr |= T1_INT;
cuda_update_irq(s);
}
static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
{
CUDAState *s = opaque;
uint32_t val;
addr = (addr >> 9) & 0xf;
switch(addr) {
case 0:
val = s->b;
break;
case 1:
val = s->a;
break;
case 2:
val = s->dirb;
break;
case 3:
val = s->dira;
break;
case 4:
val = get_counter(&s->timers[0]) & 0xff;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case 5:
val = get_counter(&s->timers[0]) >> 8;
cuda_update_irq(s);
break;
case 6:
val = s->timers[0].latch & 0xff;
break;
case 7:
/* XXX: check this */
val = (s->timers[0].latch >> 8) & 0xff;
break;
case 8:
val = get_counter(&s->timers[1]) & 0xff;
s->ifr &= ~T2_INT;
break;
case 9:
val = get_counter(&s->timers[1]) >> 8;
break;
case 10:
val = s->sr;
s->ifr &= ~SR_INT;
cuda_update_irq(s);
break;
case 11:
val = s->acr;
break;
case 12:
val = s->pcr;
break;
case 13:
val = s->ifr;
if (s->ifr & s->ier)
val |= 0x80;
break;
case 14:
val = s->ier | 0x80;
break;
default:
case 15:
val = s->anh;
break;
}
#ifdef DEBUG_CUDA
if (addr != 13 || val != 0)
printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
#endif
return val;
}
static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
CUDAState *s = opaque;
addr = (addr >> 9) & 0xf;
#ifdef DEBUG_CUDA
printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
#endif
switch(addr) {
case 0:
s->b = val;
cuda_update(s);
break;
case 1:
s->a = val;
break;
case 2:
s->dirb = val;
break;
case 3:
s->dira = val;
break;
case 4:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 5:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
s->ifr &= ~T1_INT;
set_counter(s, &s->timers[0], s->timers[0].latch);
break;
case 6:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 7:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
s->ifr &= ~T1_INT;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 8:
s->timers[1].latch = val;
set_counter(s, &s->timers[1], val);
break;
case 9:
set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
break;
case 10:
s->sr = val;
break;
case 11:
s->acr = val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
cuda_update(s);
break;
case 12:
s->pcr = val;
break;
case 13:
/* reset bits */
s->ifr &= ~val;
cuda_update_irq(s);
break;
case 14:
if (val & IER_SET) {
/* set bits */
s->ier |= val & 0x7f;
} else {
/* reset bits */
s->ier &= ~val;
}
cuda_update_irq(s);
break;
default:
case 15:
s->anh = val;
break;
}
}
/* NOTE: TIP and TREQ are negated */
static void cuda_update(CUDAState *s)
{
int packet_received, len;
packet_received = 0;
if (!(s->b & TIP)) {
/* transfer requested from host */
if (s->acr & SR_OUT) {
/* data output */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
if (s->data_out_index < sizeof(s->data_out)) {
#ifdef DEBUG_CUDA
printf("cuda: send: %02x\n", s->sr);
#endif
s->data_out[s->data_out_index++] = s->sr;
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
} else {
if (s->data_in_index < s->data_in_size) {
/* data input */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
s->sr = s->data_in[s->data_in_index++];
#ifdef DEBUG_CUDA
printf("cuda: recv: %02x\n", s->sr);
#endif
/* indicate end of transfer */
if (s->data_in_index >= s->data_in_size) {
s->b = (s->b | TREQ);
}
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
}
} else {
/* no transfer requested: handle sync case */
if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
/* update TREQ state each time TACK change state */
if (s->b & TACK)
s->b = (s->b | TREQ);
else
s->b = (s->b & ~TREQ);
s->ifr |= SR_INT;
cuda_update_irq(s);
} else {
if (!(s->last_b & TIP)) {
/* handle end of host to cuda transfert */
packet_received = (s->data_out_index > 0);
/* always an IRQ at the end of transfert */
s->ifr |= SR_INT;
cuda_update_irq(s);
}
/* signal if there is data to read */
if (s->data_in_index < s->data_in_size) {
s->b = (s->b & ~TREQ);
}
}
}
s->last_acr = s->acr;
s->last_b = s->b;
/* NOTE: cuda_receive_packet_from_host() can call cuda_update()
recursively */
if (packet_received) {
len = s->data_out_index;
s->data_out_index = 0;
cuda_receive_packet_from_host(s, s->data_out, len);
}
}
static void cuda_send_packet_to_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_send_packet_to_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
memcpy(s->data_in, data, len);
s->data_in_size = len;
s->data_in_index = 0;
cuda_update(s);
s->ifr |= SR_INT;
cuda_update_irq(s);
}
static void cuda_adb_poll(void *opaque)
{
CUDAState *s = opaque;
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_poll(&adb_bus, obuf + 2);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x40; /* polled data */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
}
static void cuda_receive_packet(CUDAState *s,
const uint8_t *data, int len)
{
uint8_t obuf[16];
int ti, autopoll;
switch(data[0]) {
case CUDA_AUTOPOLL:
autopoll = (data[1] != 0);
if (autopoll != s->autopoll) {
s->autopoll = autopoll;
if (autopoll) {
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
} else {
qemu_del_timer(s->adb_poll_timer);
}
}
obuf[0] = CUDA_PACKET;
obuf[1] = data[1];
cuda_send_packet_to_host(s, obuf, 2);
break;
case CUDA_GET_TIME:
case CUDA_SET_TIME:
/* XXX: add time support ? */
ti = time(NULL) + RTC_OFFSET;
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
obuf[3] = ti >> 24;
obuf[4] = ti >> 16;
obuf[5] = ti >> 8;
obuf[6] = ti;
cuda_send_packet_to_host(s, obuf, 7);
break;
case CUDA_FILE_SERVER_FLAG:
case CUDA_SET_DEVICE_LIST:
case CUDA_SET_AUTO_RATE:
case CUDA_SET_POWER_MESSAGES:
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
cuda_send_packet_to_host(s, obuf, 2);
break;
case CUDA_POWERDOWN:
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
cuda_send_packet_to_host(s, obuf, 2);
qemu_system_shutdown_request();
break;
default:
break;
}
}
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_receive_packet_from_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
switch(data[0]) {
case ADB_PACKET:
{
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x00;
} else {
/* error */
obuf[0] = ADB_PACKET;
obuf[1] = -olen;
olen = 0;
}
cuda_send_packet_to_host(s, obuf, olen + 2);
}
break;
case CUDA_PACKET:
cuda_receive_packet(s, data + 1, len - 1);
break;
}
}
static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *cuda_write[] = {
&cuda_writeb,
&cuda_writew,
&cuda_writel,
};
static CPUReadMemoryFunc *cuda_read[] = {
&cuda_readb,
&cuda_readw,
&cuda_readl,
};
int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
{
CUDAState *s = &cuda_state;
int cuda_mem_index;
s->set_irq = set_irq;
s->irq_opaque = irq_opaque;
s->irq = irq;
s->timers[0].index = 0;
s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
s->timers[0].latch = 0xffff;
set_counter(s, &s->timers[0], 0xffff);
s->timers[1].index = 1;
s->timers[1].latch = 0;
// s->ier = T1_INT | SR_INT;
s->ier = 0;
set_counter(s, &s->timers[1], 0xffff);
s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
return cuda_mem_index;
}

502
hw/dma.c
View File

@@ -1,8 +1,8 @@
/*
* QEMU DMA emulation
*
* Copyright (c) 2003 Vassili Karpov (malc)
*
*
* Copyright (c) 2003-2004 Vassili Karpov (malc)
*
* 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
@@ -21,14 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "vl.h"
#include "cpu.h"
#define log(...) fprintf (stderr, "dma: " __VA_ARGS__)
/* #define DEBUG_DMA */
#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
#ifdef DEBUG_DMA
#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
@@ -39,7 +36,6 @@
#define ldebug(...)
#endif
#define MEM_REAL(addr) ((addr)+(uint32_t)(phys_ram_base))
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
struct dma_regs {
@@ -47,10 +43,11 @@ struct dma_regs {
uint16_t base[2];
uint8_t mode;
uint8_t page;
uint8_t pageh;
uint8_t dack;
uint8_t eop;
DMA_read_handler read_handler;
DMA_misc_handler misc_handler;
DMA_transfer_handler transfer_handler;
void *opaque;
};
#define ADDR 0
@@ -61,141 +58,153 @@ static struct dma_cont {
uint8_t command;
uint8_t mask;
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
} dma_controllers[2];
enum {
CMD_MEMORY_TO_MEMORY = 0x01,
CMD_FIXED_ADDRESS = 0x02,
CMD_BLOCK_CONTROLLER = 0x04,
CMD_COMPRESSED_TIME = 0x08,
CMD_CYCLIC_PRIORITY = 0x10,
CMD_EXTENDED_WRITE = 0x20,
CMD_LOW_DREQ = 0x40,
CMD_LOW_DACK = 0x80,
CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
| CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
| CMD_LOW_DREQ | CMD_LOW_DACK
CMD_MEMORY_TO_MEMORY = 0x01,
CMD_FIXED_ADDRESS = 0x02,
CMD_BLOCK_CONTROLLER = 0x04,
CMD_COMPRESSED_TIME = 0x08,
CMD_CYCLIC_PRIORITY = 0x10,
CMD_EXTENDED_WRITE = 0x20,
CMD_LOW_DREQ = 0x40,
CMD_LOW_DACK = 0x80,
CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
| CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
| CMD_LOW_DREQ | CMD_LOW_DACK
};
static void write_page (struct CPUX86State *env, uint32_t nport, uint32_t data)
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
static void write_page (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
int ncont;
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
ncont = nport > 0x87;
ichan = channels[nport - 0x80 - (ncont << 3)];
ichan = channels[nport & 7];
if (-1 == ichan) {
log ("invalid channel %#x %#x\n", nport, data);
dolog ("invalid channel %#x %#x\n", nport, data);
return;
}
dma_controllers[ncont].regs[ichan].page = data;
d->regs[ichan].page = data;
}
static void init_chan (int ncont, int ichan)
static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel %#x %#x\n", nport, data);
return;
}
d->regs[ichan].pageh = data;
}
static uint32_t read_page (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].page;
}
static uint32_t read_pageh (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
dolog ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].pageh;
}
static inline void init_chan (struct dma_cont *d, int ichan)
{
struct dma_regs *r;
r = dma_controllers[ncont].regs + ichan;
r->now[ADDR] = r->base[0] << ncont;
r = d->regs + ichan;
r->now[ADDR] = r->base[ADDR] << d->dshift;
r->now[COUNT] = 0;
}
static inline int getff (int ncont)
static inline int getff (struct dma_cont *d)
{
int ff;
ff = dma_controllers[ncont].flip_flop;
dma_controllers[ncont].flip_flop = !ff;
ff = d->flip_flop;
d->flip_flop = !ff;
return ff;
}
static uint32_t read_chan (struct CPUX86State *env, uint32_t nport)
static uint32_t read_chan (void *opaque, uint32_t nport)
{
int ff;
int ncont, ichan, nreg;
struct dma_cont *d = opaque;
int ichan, nreg, iport, ff, val, dir;
struct dma_regs *r;
int val;
ncont = nport > 7;
ichan = (nport >> (1 + ncont)) & 3;
nreg = (nport >> ncont) & 1;
r = dma_controllers[ncont].regs + ichan;
ff = getff (ncont);
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
dir = ((r->mode >> 5) & 1) ? -1 : 1;
ff = getff (d);
if (nreg)
val = (r->base[COUNT] << ncont) - r->now[COUNT];
val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
else
val = r->now[ADDR] + r->now[COUNT];
val = r->now[ADDR] + r->now[COUNT] * dir;
return (val >> (ncont + (ff << 3))) & 0xff;
ldebug ("read_chan %#x -> %d\n", iport, val);
return (val >> (d->dshift + (ff << 3))) & 0xff;
}
static void write_chan (uint32_t nport, int size, uint32_t data)
static void write_chan (void *opaque, uint32_t nport, uint32_t data)
{
int ncont, ichan, nreg;
struct dma_cont *d = opaque;
int iport, ichan, nreg;
struct dma_regs *r;
ncont = nport > 7;
ichan = (nport >> (1 + ncont)) & 3;
nreg = (nport >> ncont) & 1;
r = dma_controllers[ncont].regs + ichan;
if (2 == size) {
r->base[nreg] = data;
init_chan (ncont, ichan);
}
else {
if (getff (ncont)) {
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (ncont, ichan);
}
else {
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
if (getff (d)) {
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (d, ichan);
} else {
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
}
static void write_chanb (struct CPUX86State *env, uint32_t nport, uint32_t data)
static void write_cont (void *opaque, uint32_t nport, uint32_t data)
{
write_chan (nport, 1, data);
}
static void write_chanw (struct CPUX86State *env, uint32_t nport, uint32_t data)
{
write_chan (nport, 2, data);
}
static void write_cont (struct CPUX86State *env, uint32_t nport, uint32_t data)
{
int iport, ichan, ncont;
struct dma_cont *d;
ncont = nport > 0xf;
ichan = -1;
d = dma_controllers + ncont;
if (ncont) {
iport = ((nport - 0xd0) >> 1) + 8;
}
else {
iport = nport;
}
struct dma_cont *d = opaque;
int iport, ichan = 0;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 8: /* command */
if (data && (data | CMD_NOT_SUPPORTED)) {
log ("command %#x not supported\n", data);
goto error;
case 0x08: /* command */
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
dolog ("command %#x not supported\n", data);
return;
}
d->command = data;
break;
case 9:
case 0x09:
ichan = data & 3;
if (data & 4) {
d->status |= 1 << (ichan + 4);
@@ -206,69 +215,85 @@ static void write_cont (struct CPUX86State *env, uint32_t nport, uint32_t data)
d->status &= ~(1 << ichan);
break;
case 0xa: /* single mask */
case 0x0a: /* single mask */
if (data & 4)
d->mask |= 1 << (data & 3);
else
d->mask &= ~(1 << (data & 3));
break;
case 0xb: /* mode */
case 0x0b: /* mode */
{
#ifdef DMA_DEBUG
int op;
int ai;
int dir;
int opmode;
ichan = data & 3;
#ifdef DEBUG_DMA
{
int op, ai, dir, opmode;
op = (data >> 2) & 3;
ai = (data >> 4) & 1;
dir = (data >> 5) & 1;
opmode = (data >> 6) & 3;
ichan = val & 3;
op = (val >> 2) & 3;
ai = (val >> 4) & 1;
dir = (val >> 5) & 1;
opmode = (val >> 6) & 3;
linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
ichan, op, ai, dir, opmode);
linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
ichan, op, ai, dir, opmode);
}
#endif
d->regs[ichan].mode = data;
break;
}
case 0xc: /* clear flip flop */
case 0x0c: /* clear flip flop */
d->flip_flop = 0;
break;
case 0xd: /* reset */
case 0x0d: /* reset */
d->flip_flop = 0;
d->mask = ~0;
d->status = 0;
d->command = 0;
break;
case 0xe: /* clear mask for all channels */
case 0x0e: /* clear mask for all channels */
d->mask = 0;
break;
case 0xf: /* write mask for all channels */
case 0x0f: /* write mask for all channels */
d->mask = data;
break;
default:
log ("dma: unknown iport %#x\n", iport);
goto error;
dolog ("unknown iport %#x\n", iport);
break;
}
#ifdef DMA_DEBUG
#ifdef DEBUG_DMA
if (0xc != iport) {
linfo ("nport %#06x, ncont %d, ichan % 2d, val %#06x\n",
nport, d != dma_controllers, ichan, data);
linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
nport, ichan, data);
}
#endif
return;
}
error:
abort ();
static uint32_t read_cont (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int iport, val;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 0x08: /* status */
val = d->status;
d->status &= 0xf0;
break;
case 0x0f: /* mask */
val = d->mask;
break;
default:
val = 0;
break;
}
ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
return val;
}
int DMA_get_channel_mode (int nchan)
@@ -298,42 +323,34 @@ void DMA_release_DREQ (int nchan)
static void channel_run (int ncont, int ichan)
{
struct dma_regs *r;
int n;
int irq;
uint32_t addr;
/* int ai, dir; */
struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
#ifdef DEBUG_DMA
int dir, opmode;
dir = (r->mode >> 5) & 1;
opmode = (r->mode >> 6) & 3;
if (dir) {
dolog ("DMA in address decrement mode\n");
}
if (opmode != 1) {
dolog ("DMA not in single mode select %#x\n", opmode);
}
#endif
r = dma_controllers[ncont].regs + ichan;
/* ai = r->mode & 16; */
/* dir = r->mode & 32 ? -1 : 1; */
addr = MEM_REAL ((r->page << 16) | r->now[ADDR]);
irq = -1;
n = r->read_handler (addr, (r->base[COUNT] << ncont) + (1 << ncont), &irq);
n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
r->now[COUNT], (r->base[COUNT] + 1) << ncont);
r->now[COUNT] = n;
ldebug ("dma_pos %d irq %d size %d\n",
n, irq, (r->base[1] << ncont) + (1 << ncont));
if (-1 != irq) {
pic_set_irq (irq, 1);
}
ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
}
void DMA_run (void)
{
static int in_dma;
struct dma_cont *d;
int icont, ichan;
if (in_dma) {
log ("attempt to re-enter dma\n");
return;
}
in_dma = 1;
d = dma_controllers;
for (icont = 0; icont < 2; icont++, d++) {
@@ -346,12 +363,11 @@ void DMA_run (void)
channel_run (icont, ichan);
}
}
in_dma = 0;
}
void DMA_register_channel (int nchan,
DMA_read_handler read_handler,
DMA_misc_handler misc_handler)
DMA_transfer_handler transfer_handler,
void *opaque)
{
struct dma_regs *r;
int ichan, ncont;
@@ -360,36 +376,162 @@ void DMA_register_channel (int nchan,
ichan = nchan & 3;
r = dma_controllers[ncont].regs + ichan;
r->read_handler = read_handler;
r->misc_handler = misc_handler;
r->transfer_handler = transfer_handler;
r->opaque = opaque;
}
void DMA_init (void)
int DMA_read_memory (int nchan, void *buf, int pos, int len)
{
int i;
int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
for (i = 0; i < 8; i++) {
register_ioport_write (i, 1, write_chanb, 1);
register_ioport_write (i, 1, write_chanw, 2);
if (r->mode & 0x20) {
int i;
uint8_t *p = buf;
register_ioport_write (0xc0 + (i << 1), 1, write_chanb, 1);
register_ioport_write (0xc0 + (i << 1), 1, write_chanw, 2);
register_ioport_read (i, 1, read_chan, 1);
register_ioport_read (0xc0 + (i << 1), 1, read_chan, 2);
cpu_physical_memory_read (addr - pos - len, buf, len);
/* What about 16bit transfers? */
for (i = 0; i < len >> 1; i++) {
uint8_t b = p[len - i - 1];
p[i] = b;
}
}
else
cpu_physical_memory_read (addr + pos, buf, len);
for (i = 0; i < LENOFA (page_port_list); i++) {
register_ioport_write (page_port_list[i] + 0x80, 1, write_page, 1);
register_ioport_write (page_port_list[i] + 0x88, 1, write_page, 1);
}
for (i = 0; i < 8; i++) {
register_ioport_write (i + 8, 1, write_cont, 1);
register_ioport_write (0xd0 + (i << 1), 1, write_cont, 1);
}
write_cont (NULL, 0xd, 0);
write_cont (NULL, 0xdd, 0);
return len;
}
int DMA_write_memory (int nchan, void *buf, int pos, int len)
{
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (r->mode & 0x20) {
int i;
uint8_t *p = buf;
cpu_physical_memory_write (addr - pos - len, buf, len);
/* What about 16bit transfers? */
for (i = 0; i < len; i++) {
uint8_t b = p[len - i - 1];
p[i] = b;
}
}
else
cpu_physical_memory_write (addr + pos, buf, len);
return len;
}
/* request the emulator to transfer a new DMA memory block ASAP */
void DMA_schedule(int nchan)
{
CPUState *env = cpu_single_env;
if (env)
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
}
static void dma_reset(void *opaque)
{
struct dma_cont *d = opaque;
write_cont (d, (0x0d << d->dshift), 0);
}
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base)
{
const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
int i;
d->dshift = dshift;
for (i = 0; i < 8; i++) {
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
}
for (i = 0; i < LENOFA (page_port_list); i++) {
register_ioport_write (page_base + page_port_list[i], 1, 1,
write_page, d);
register_ioport_read (page_base + page_port_list[i], 1, 1,
read_page, d);
if (pageh_base >= 0) {
register_ioport_write (pageh_base + page_port_list[i], 1, 1,
write_pageh, d);
register_ioport_read (pageh_base + page_port_list[i], 1, 1,
read_pageh, d);
}
}
for (i = 0; i < 8; i++) {
register_ioport_write (base + ((i + 8) << dshift), 1, 1,
write_cont, d);
register_ioport_read (base + ((i + 8) << dshift), 1, 1,
read_cont, d);
}
qemu_register_reset(dma_reset, d);
dma_reset(d);
}
static void dma_save (QEMUFile *f, void *opaque)
{
struct dma_cont *d = opaque;
int i;
/* qemu_put_8s (f, &d->status); */
qemu_put_8s (f, &d->command);
qemu_put_8s (f, &d->mask);
qemu_put_8s (f, &d->flip_flop);
qemu_put_be32s (f, &d->dshift);
for (i = 0; i < 4; ++i) {
struct dma_regs *r = &d->regs[i];
qemu_put_be32s (f, &r->now[0]);
qemu_put_be32s (f, &r->now[1]);
qemu_put_be16s (f, &r->base[0]);
qemu_put_be16s (f, &r->base[1]);
qemu_put_8s (f, &r->mode);
qemu_put_8s (f, &r->page);
qemu_put_8s (f, &r->pageh);
qemu_put_8s (f, &r->dack);
qemu_put_8s (f, &r->eop);
}
}
static int dma_load (QEMUFile *f, void *opaque, int version_id)
{
struct dma_cont *d = opaque;
int i;
if (version_id != 1)
return -EINVAL;
/* qemu_get_8s (f, &d->status); */
qemu_get_8s (f, &d->command);
qemu_get_8s (f, &d->mask);
qemu_get_8s (f, &d->flip_flop);
qemu_get_be32s (f, &d->dshift);
for (i = 0; i < 4; ++i) {
struct dma_regs *r = &d->regs[i];
qemu_get_be32s (f, &r->now[0]);
qemu_get_be32s (f, &r->now[1]);
qemu_get_be16s (f, &r->base[0]);
qemu_get_be16s (f, &r->base[1]);
qemu_get_8s (f, &r->mode);
qemu_get_8s (f, &r->page);
qemu_get_8s (f, &r->pageh);
qemu_get_8s (f, &r->dack);
qemu_get_8s (f, &r->eop);
}
return 0;
}
void DMA_init (int high_page_enable)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
high_page_enable ? 0x480 : -1);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
high_page_enable ? 0x488 : -1);
register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
}

1062
hw/es1370.c Normal file

File diff suppressed because it is too large Load Diff

747
hw/esp.c Normal file
View File

@@ -0,0 +1,747 @@
/*
* QEMU ESP emulation
*
* Copyright (c) 2005-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"
/* debug ESP card */
//#define DEBUG_ESP
#ifdef DEBUG_ESP
#define DPRINTF(fmt, args...) \
do { printf("ESP: " fmt , ##args); } while (0)
#define pic_set_irq(irq, level) \
do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#define ESPDMA_REGS 4
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
#define ESP_MAXREG 0x3f
#define TI_BUFSZ 1024*1024 // XXX
#define DMA_VER 0xa0000000
#define DMA_INTR 1
#define DMA_INTREN 0x10
#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];
uint8_t wregs[ESP_MAXREG];
int irq;
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 dma;
ESPDMAFunc *dma_cb;
int64_t offset, len;
int target;
};
#define STAT_DO 0x00
#define STAT_DI 0x01
#define STAT_CD 0x02
#define STAT_ST 0x03
#define STAT_MI 0x06
#define STAT_MO 0x07
#define STAT_TC 0x10
#define STAT_IN 0x80
#define INTR_FC 0x08
#define INTR_BS 0x10
#define INTR_DC 0x20
#define INTR_RST 0x80
#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)
{
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);
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);
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
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;
}
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;
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;
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;
}
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)
{
uint32_t dmaptr, dmalen;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
DPRINTF("Transfer status len %d\n", dmalen);
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);
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_rptr = 0;
s->ti_wptr = 0;
s->rregs[7] = dmalen;
}
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
}
static const uint8_t okbuf[] = {0, 0};
static void handle_ti(ESPState *s)
{
uint32_t dmaptr, dmalen;
unsigned int i;
dmalen = s->wregs[0] | (s->wregs[1] << 8);
DPRINTF("Transfer Information len %d\n", dmalen);
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++) {
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;
}
s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
s->rregs[5] = INTR_BS;
s->rregs[6] = 0;
s->espdmaregs[0] |= DMA_INTR;
} else {
s->ti_size = dmalen;
s->ti_rptr = 0;
s->ti_wptr = 0;
s->rregs[7] = dmalen;
}
pic_set_irq(s->irq, 1);
}
static void esp_reset(void *opaque)
{
ESPState *s = opaque;
memset(s->rregs, 0, ESP_MAXREG);
memset(s->wregs, 0, ESP_MAXREG);
s->rregs[0x0e] = 0x4; // Indicate fas100a
memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
s->ti_size = 0;
s->ti_rptr = 0;
s->ti_wptr = 0;
s->ti_dir = 0;
s->dma = 0;
s->dma_cb = NULL;
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESP_MAXREG) >> 2;
DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
switch (saddr) {
case 2:
// FIFO
if (s->ti_size > 0) {
s->ti_size--;
s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
pic_set_irq(s->irq, 1);
}
if (s->ti_size == 0) {
s->ti_rptr = 0;
s->ti_wptr = 0;
}
break;
case 5:
// interrupt
// Clear status bits except TC
s->rregs[4] &= STAT_TC;
pic_set_irq(s->irq, 0);
s->espdmaregs[0] &= ~DMA_INTR;
break;
default:
break;
}
return s->rregs[saddr];
}
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESP_MAXREG) >> 2;
DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
switch (saddr) {
case 0:
case 1:
s->rregs[saddr] = val;
break;
case 2:
// FIFO
s->ti_size++;
s->ti_buf[s->ti_wptr++] = val & 0xff;
break;
case 3:
s->rregs[saddr] = val;
// Command
if (val & 0x80) {
s->dma = 1;
} else {
s->dma = 0;
}
switch(val & 0x7f) {
case 0:
DPRINTF("NOP (%2.2x)\n", val);
break;
case 1:
DPRINTF("Flush FIFO (%2.2x)\n", val);
//s->ti_size = 0;
s->rregs[5] = INTR_FC;
s->rregs[6] = 0;
break;
case 2:
DPRINTF("Chip reset (%2.2x)\n", val);
esp_reset(s);
break;
case 3:
DPRINTF("Bus reset (%2.2x)\n", val);
s->rregs[5] = INTR_RST;
if (!(s->wregs[8] & 0x40)) {
s->espdmaregs[0] |= DMA_INTR;
pic_set_irq(s->irq, 1);
}
break;
case 0x10:
handle_ti(s);
break;
case 0x11:
DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
dma_write(s, okbuf, 2);
break;
case 0x12:
DPRINTF("Message Accepted (%2.2x)\n", val);
dma_write(s, okbuf, 2);
s->rregs[5] = INTR_DC;
s->rregs[6] = 0;
break;
case 0x1a:
DPRINTF("Set ATN (%2.2x)\n", val);
break;
case 0x42:
handle_satn(s);
break;
case 0x43:
DPRINTF("Set ATN & stop (%2.2x)\n", val);
handle_satn(s);
break;
default:
DPRINTF("Unhandled ESP command (%2.2x)\n", val);
break;
}
break;
case 4 ... 7:
break;
case 8:
s->rregs[saddr] = val;
break;
case 9 ... 10:
break;
case 11:
s->rregs[saddr] = val & 0x15;
break;
case 12 ... 15:
s->rregs[saddr] = val;
break;
default:
break;
}
s->wregs[saddr] = val;
}
static CPUReadMemoryFunc *esp_mem_read[3] = {
esp_mem_readb,
esp_mem_readb,
esp_mem_readb,
};
static CPUWriteMemoryFunc *esp_mem_write[3] = {
esp_mem_writeb,
esp_mem_writeb,
esp_mem_writeb,
};
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
return s->espdmaregs[saddr];
}
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
switch (saddr) {
case 0:
if (!(val & DMA_INTREN))
pic_set_irq(s->irq, 0);
if (val & 0x80) {
esp_reset(s);
} else if (val & 0x40) {
val &= ~0x40;
} else if (val == 0)
val = 0x40;
val &= 0x0fffffff;
val |= DMA_VER;
break;
case 1:
s->espdmaregs[0] = DMA_LOADED;
break;
default:
break;
}
s->espdmaregs[saddr] = val;
}
static CPUReadMemoryFunc *espdma_mem_read[3] = {
espdma_mem_readl,
espdma_mem_readl,
espdma_mem_readl,
};
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
espdma_mem_writel,
espdma_mem_writel,
espdma_mem_writel,
};
static void esp_save(QEMUFile *f, void *opaque)
{
ESPState *s = opaque;
unsigned int i;
qemu_put_buffer(f, s->rregs, ESP_MAXREG);
qemu_put_buffer(f, s->wregs, ESP_MAXREG);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < ESPDMA_REGS; i++)
qemu_put_be32s(f, &s->espdmaregs[i]);
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);
}
static int esp_load(QEMUFile *f, void *opaque, int version_id)
{
ESPState *s = opaque;
unsigned int i;
if (version_id != 1)
return -EINVAL;
qemu_get_buffer(f, s->rregs, ESP_MAXREG);
qemu_get_buffer(f, s->wregs, ESP_MAXREG);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < ESPDMA_REGS; i++)
qemu_get_be32s(f, &s->espdmaregs[i]);
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);
return 0;
}
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
{
ESPState *s;
int esp_io_memory, espdma_io_memory;
s = qemu_mallocz(sizeof(ESPState));
if (!s)
return;
s->bd = bd;
s->irq = irq;
esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
esp_reset(s);
register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
qemu_register_reset(esp_reset, s);
}

1757
hw/fdc.c Normal file

File diff suppressed because it is too large Load Diff

1390
hw/fmopl.c Normal file

File diff suppressed because it is too large Load Diff

174
hw/fmopl.h Normal file
View File

@@ -0,0 +1,174 @@
#ifndef __FMOPL_H_
#define __FMOPL_H_
/* --- select emulation chips --- */
#define BUILD_YM3812 (HAS_YM3812)
//#define BUILD_YM3526 (HAS_YM3526)
//#define BUILD_Y8950 (HAS_Y8950)
/* --- system optimize --- */
/* select bit size of output : 8 or 16 */
#define OPL_OUTPUT_BIT 16
/* compiler dependence */
#ifndef OSD_CPU_H
#define OSD_CPU_H
typedef unsigned char UINT8; /* unsigned 8bit */
typedef unsigned short UINT16; /* unsigned 16bit */
typedef unsigned int UINT32; /* unsigned 32bit */
typedef signed char INT8; /* signed 8bit */
typedef signed short INT16; /* signed 16bit */
typedef signed int INT32; /* signed 32bit */
#endif
#if (OPL_OUTPUT_BIT==16)
typedef INT16 OPLSAMPLE;
#endif
#if (OPL_OUTPUT_BIT==8)
typedef unsigned char OPLSAMPLE;
#endif
#if BUILD_Y8950
#include "ymdeltat.h"
#endif
typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
typedef void (*OPL_IRQHANDLER)(int param,int irq);
typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
/* !!!!! here is private section , do not access there member direct !!!!! */
#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
#define OPL_TYPE_IO 0x08 /* I/O port */
/* Saving is necessary for member of the 'R' mark for suspend/resume */
/* ---------- OPL one of slot ---------- */
typedef struct fm_opl_slot {
INT32 TL; /* total level :TL << 8 */
INT32 TLL; /* adjusted now TL */
UINT8 KSR; /* key scale rate :(shift down bit) */
INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
INT32 SL; /* sustin level :SL_TALBE[SL] */
INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
UINT8 ksl; /* keyscale level :(shift down bits) */
UINT8 ksr; /* key scale rate :kcode>>KSR */
UINT32 mul; /* multiple :ML_TABLE[ML] */
UINT32 Cnt; /* frequency count : */
UINT32 Incr; /* frequency step : */
/* envelope generator state */
UINT8 eg_typ; /* envelope type flag */
UINT8 evm; /* envelope phase */
INT32 evc; /* envelope counter */
INT32 eve; /* envelope counter end point */
INT32 evs; /* envelope counter step */
INT32 evsa; /* envelope step for AR :AR[ksr] */
INT32 evsd; /* envelope step for DR :DR[ksr] */
INT32 evsr; /* envelope step for RR :RR[ksr] */
/* LFO */
UINT8 ams; /* ams flag */
UINT8 vib; /* vibrate flag */
/* wave selector */
INT32 **wavetable;
}OPL_SLOT;
/* ---------- OPL one of channel ---------- */
typedef struct fm_opl_channel {
OPL_SLOT SLOT[2];
UINT8 CON; /* connection type */
UINT8 FB; /* feed back :(shift down bit) */
INT32 *connect1; /* slot1 output pointer */
INT32 *connect2; /* slot2 output pointer */
INT32 op1_out[2]; /* slot1 output for selfeedback */
/* phase generator state */
UINT32 block_fnum; /* block+fnum : */
UINT8 kcode; /* key code : KeyScaleCode */
UINT32 fc; /* Freq. Increment base */
UINT32 ksl_base; /* KeyScaleLevel Base step */
UINT8 keyon; /* key on/off flag */
} OPL_CH;
/* OPL state */
typedef struct fm_opl_f {
UINT8 type; /* chip type */
int clock; /* master clock (Hz) */
int rate; /* sampling rate (Hz) */
double freqbase; /* frequency base */
double TimerBase; /* Timer base time (==sampling time) */
UINT8 address; /* address register */
UINT8 status; /* status flag */
UINT8 statusmask; /* status mask */
UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
/* Timer */
int T[2]; /* timer counter */
UINT8 st[2]; /* timer enable */
/* FM channel slots */
OPL_CH *P_CH; /* pointer of CH */
int max_ch; /* maximum channel */
/* Rythm sention */
UINT8 rythm; /* Rythm mode , key flag */
#if BUILD_Y8950
/* Delta-T ADPCM unit (Y8950) */
YM_DELTAT *deltat; /* DELTA-T ADPCM */
#endif
/* Keyboard / I/O interface unit (Y8950) */
UINT8 portDirection;
UINT8 portLatch;
OPL_PORTHANDLER_R porthandler_r;
OPL_PORTHANDLER_W porthandler_w;
int port_param;
OPL_PORTHANDLER_R keyboardhandler_r;
OPL_PORTHANDLER_W keyboardhandler_w;
int keyboard_param;
/* time tables */
INT32 AR_TABLE[75]; /* atttack rate tables */
INT32 DR_TABLE[75]; /* decay rate tables */
UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
/* LFO */
INT32 *ams_table;
INT32 *vib_table;
INT32 amsCnt;
INT32 amsIncr;
INT32 vibCnt;
INT32 vibIncr;
/* wave selector enable flag */
UINT8 wavesel;
/* external event callback handler */
OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
int TimerParam; /* TIMER parameter */
OPL_IRQHANDLER IRQHandler; /* IRQ handler */
int IRQParam; /* IRQ parameter */
OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
int UpdateParam; /* stream update parameter */
} FM_OPL;
/* ---------- Generic interface section ---------- */
#define OPL_TYPE_YM3526 (0)
#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
FM_OPL *OPLCreate(int type, int clock, int rate);
void OPLDestroy(FM_OPL *OPL);
void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
/* Y8950 port handlers */
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
void OPLResetChip(FM_OPL *OPL);
int OPLWrite(FM_OPL *OPL,int a,int v);
unsigned char OPLRead(FM_OPL *OPL,int a);
int OPLTimerOver(FM_OPL *OPL,int c);
/* YM3626/YM3812 local section */
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
#endif

168
hw/heathrow_pic.c Normal file
View File

@@ -0,0 +1,168 @@
/*
* Heathrow PIC support (standard PowerMac PIC)
*
* Copyright (c) 2005 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"
//#define DEBUG
typedef struct HeathrowPIC {
uint32_t events;
uint32_t mask;
uint32_t levels;
uint32_t level_triggered;
} HeathrowPIC;
struct HeathrowPICS {
HeathrowPIC pics[2];
};
static inline int check_irq(HeathrowPIC *pic)
{
return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask;
}
/* update the CPU irq state */
static void heathrow_pic_update(HeathrowPICS *s)
{
if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD);
} else {
cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD);
}
}
static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
HeathrowPICS *s = opaque;
HeathrowPIC *pic;
unsigned int n;
value = bswap32(value);
#ifdef DEBUG
printf("pic_writel: %08x: %08x\n",
addr, value);
#endif
n = ((addr & 0xfff) - 0x10) >> 4;
if (n >= 2)
return;
pic = &s->pics[n];
switch(addr & 0xf) {
case 0x04:
pic->mask = value;
heathrow_pic_update(s);
break;
case 0x08:
/* do not reset level triggered IRQs */
value &= ~pic->level_triggered;
pic->events &= ~value;
heathrow_pic_update(s);
break;
default:
break;
}
}
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
{
HeathrowPICS *s = opaque;
HeathrowPIC *pic;
unsigned int n;
uint32_t value;
n = ((addr & 0xfff) - 0x10) >> 4;
if (n >= 2) {
value = 0;
} else {
pic = &s->pics[n];
switch(addr & 0xf) {
case 0x0:
value = pic->events;
break;
case 0x4:
value = pic->mask;
break;
case 0xc:
value = pic->levels;
break;
default:
value = 0;
break;
}
}
#ifdef DEBUG
printf("pic_readl: %08x: %08x\n",
addr, value);
#endif
value = bswap32(value);
return value;
}
static CPUWriteMemoryFunc *pic_write[] = {
&pic_writel,
&pic_writel,
&pic_writel,
};
static CPUReadMemoryFunc *pic_read[] = {
&pic_readl,
&pic_readl,
&pic_readl,
};
void heathrow_pic_set_irq(void *opaque, int num, int level)
{
HeathrowPICS *s = opaque;
HeathrowPIC *pic;
unsigned int irq_bit;
#if defined(DEBUG)
{
static int last_level[64];
if (last_level[num] != level) {
printf("set_irq: num=0x%02x level=%d\n", num, level);
last_level[num] = level;
}
}
#endif
pic = &s->pics[1 - (num >> 5)];
irq_bit = 1 << (num & 0x1f);
if (level) {
pic->events |= irq_bit & ~pic->level_triggered;
pic->levels |= irq_bit;
} else {
pic->levels &= ~irq_bit;
}
heathrow_pic_update(s);
}
HeathrowPICS *heathrow_pic_init(int *pmem_index)
{
HeathrowPICS *s;
s = qemu_mallocz(sizeof(HeathrowPICS));
s->pics[0].level_triggered = 0;
s->pics[1].level_triggered = 0x1ff00000;
*pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s);
return s;
}

482
hw/i8254.c Normal file
View File

@@ -0,0 +1,482 @@
/*
* QEMU 8253/8254 interval timer emulation
*
* Copyright (c) 2003-2004 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"
//#define DEBUG_PIT
#define RW_STATE_LSB 1
#define RW_STATE_MSB 2
#define RW_STATE_WORD0 3
#define RW_STATE_WORD1 4
typedef struct PITChannelState {
int count; /* can be 65536 */
uint16_t latched_count;
uint8_t count_latched;
uint8_t status_latched;
uint8_t status;
uint8_t read_state;
uint8_t write_state;
uint8_t write_latch;
uint8_t rw_mode;
uint8_t mode;
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
int irq;
} PITChannelState;
struct PITState {
PITChannelState channels[3];
};
static PITState pit_state;
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
static int pit_get_count(PITChannelState *s)
{
uint64_t d;
int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
case 0:
case 1:
case 4:
case 5:
counter = (s->count - d) & 0xffff;
break;
case 3:
/* XXX: may be incorrect for odd counts */
counter = s->count - ((2 * d) % s->count);
break;
default:
counter = s->count - (d % s->count);
break;
}
return counter;
}
/* get pit output bit */
static int pit_get_out1(PITChannelState *s, int64_t current_time)
{
uint64_t d;
int out;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
out = (d >= s->count);
break;
case 1:
out = (d < s->count);
break;
case 2:
if ((d % s->count) == 0 && d != 0)
out = 1;
else
out = 0;
break;
case 3:
out = (d % s->count) < ((s->count + 1) >> 1);
break;
case 4:
case 5:
out = (d == s->count);
break;
}
return out;
}
int pit_get_out(PITState *pit, int channel, int64_t current_time)
{
PITChannelState *s = &pit->channels[channel];
return pit_get_out1(s, current_time);
}
/* return -1 if no transition will occur. */
static int64_t pit_get_next_transition_time(PITChannelState *s,
int64_t current_time)
{
uint64_t d, next_time, base;
int period2;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
case 1:
if (d < s->count)
next_time = s->count;
else
return -1;
break;
case 2:
base = (d / s->count) * s->count;
if ((d - base) == 0 && d != 0)
next_time = base + s->count;
else
next_time = base + s->count + 1;
break;
case 3:
base = (d / s->count) * s->count;
period2 = ((s->count + 1) >> 1);
if ((d - base) < period2)
next_time = base + period2;
else
next_time = base + s->count;
break;
case 4:
case 5:
if (d < s->count)
next_time = s->count;
else if (d == s->count)
next_time = s->count + 1;
else
return -1;
break;
}
/* convert to timer units */
next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
/* fix potential rounding problems */
/* XXX: better solution: use a clock at PIT_FREQ Hz */
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
/* val must be 0 or 1 */
void pit_set_gate(PITState *pit, int channel, int val)
{
PITChannelState *s = &pit->channels[channel];
switch(s->mode) {
default:
case 0:
case 4:
/* XXX: just disable/enable counting */
break;
case 1:
case 5:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
break;
case 2:
case 3:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
/* XXX: disable/enable counting */
break;
}
s->gate = val;
}
int pit_get_gate(PITState *pit, int channel)
{
PITChannelState *s = &pit->channels[channel];
return s->gate;
}
int pit_get_initial_count(PITState *pit, int channel)
{
PITChannelState *s = &pit->channels[channel];
return s->count;
}
int pit_get_mode(PITState *pit, int channel)
{
PITChannelState *s = &pit->channels[channel];
return s->mode;
}
static inline void pit_load_count(PITChannelState *s, int val)
{
if (val == 0)
val = 0x10000;
s->count_load_time = qemu_get_clock(vm_clock);
s->count = val;
pit_irq_timer_update(s, s->count_load_time);
}
/* if already latched, do not latch again */
static void pit_latch_count(PITChannelState *s)
{
if (!s->count_latched) {
s->latched_count = pit_get_count(s);
s->count_latched = s->rw_mode;
}
}
static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PITState *pit = opaque;
int channel, access;
PITChannelState *s;
addr &= 3;
if (addr == 3) {
channel = val >> 6;
if (channel == 3) {
/* read back command */
for(channel = 0; channel < 3; channel++) {
s = &pit->channels[channel];
if (val & (2 << channel)) {
if (!(val & 0x20)) {
pit_latch_count(s);
}
if (!(val & 0x10) && !s->status_latched) {
/* status latch */
/* XXX: add BCD and null count */
s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
(s->rw_mode << 4) |
(s->mode << 1) |
s->bcd;
s->status_latched = 1;
}
}
}
} else {
s = &pit->channels[channel];
access = (val >> 4) & 3;
if (access == 0) {
pit_latch_count(s);
} else {
s->rw_mode = access;
s->read_state = access;
s->write_state = access;
s->mode = (val >> 1) & 7;
s->bcd = val & 1;
/* XXX: update irq timer ? */
}
}
} else {
s = &pit->channels[addr];
switch(s->write_state) {
default:
case RW_STATE_LSB:
pit_load_count(s, val);
break;
case RW_STATE_MSB:
pit_load_count(s, val << 8);
break;
case RW_STATE_WORD0:
s->write_latch = val;
s->write_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
pit_load_count(s, s->write_latch | (val << 8));
s->write_state = RW_STATE_WORD0;
break;
}
}
}
static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
{
PITState *pit = opaque;
int ret, count;
PITChannelState *s;
addr &= 3;
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;
ret = s->status;
} else if (s->count_latched) {
switch(s->count_latched) {
default:
case RW_STATE_LSB:
ret = s->latched_count & 0xff;
s->count_latched = 0;
break;
case RW_STATE_MSB:
ret = s->latched_count >> 8;
s->count_latched = 0;
break;
case RW_STATE_WORD0:
ret = s->latched_count & 0xff;
s->count_latched = RW_STATE_MSB;
break;
}
} else {
switch(s->read_state) {
default:
case RW_STATE_LSB:
count = pit_get_count(s);
ret = count & 0xff;
break;
case RW_STATE_MSB:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
break;
case RW_STATE_WORD0:
count = pit_get_count(s);
ret = count & 0xff;
s->read_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
s->read_state = RW_STATE_WORD0;
break;
}
}
return ret;
}
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
{
int64_t expire_time;
int irq_level;
if (!s->irq_timer)
return;
expire_time = pit_get_next_transition_time(s, current_time);
irq_level = pit_get_out1(s, current_time);
pic_set_irq(s->irq, irq_level);
#ifdef DEBUG_PIT
printf("irq_level=%d next_delay=%f\n",
irq_level,
(double)(expire_time - current_time) / ticks_per_sec);
#endif
s->next_transition_time = expire_time;
if (expire_time != -1)
qemu_mod_timer(s->irq_timer, expire_time);
else
qemu_del_timer(s->irq_timer);
}
static void pit_irq_timer(void *opaque)
{
PITChannelState *s = opaque;
pit_irq_timer_update(s, s->next_transition_time);
}
static void pit_save(QEMUFile *f, void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_put_be32s(f, &s->count);
qemu_put_be16s(f, &s->latched_count);
qemu_put_8s(f, &s->count_latched);
qemu_put_8s(f, &s->status_latched);
qemu_put_8s(f, &s->status);
qemu_put_8s(f, &s->read_state);
qemu_put_8s(f, &s->write_state);
qemu_put_8s(f, &s->write_latch);
qemu_put_8s(f, &s->rw_mode);
qemu_put_8s(f, &s->mode);
qemu_put_8s(f, &s->bcd);
qemu_put_8s(f, &s->gate);
qemu_put_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_put_be64s(f, &s->next_transition_time);
qemu_put_timer(f, s->irq_timer);
}
}
}
static int pit_load(QEMUFile *f, void *opaque, int version_id)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
if (version_id != 1)
return -EINVAL;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_get_be32s(f, &s->count);
qemu_get_be16s(f, &s->latched_count);
qemu_get_8s(f, &s->count_latched);
qemu_get_8s(f, &s->status_latched);
qemu_get_8s(f, &s->status);
qemu_get_8s(f, &s->read_state);
qemu_get_8s(f, &s->write_state);
qemu_get_8s(f, &s->write_latch);
qemu_get_8s(f, &s->rw_mode);
qemu_get_8s(f, &s->mode);
qemu_get_8s(f, &s->bcd);
qemu_get_8s(f, &s->gate);
qemu_get_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_get_be64s(f, &s->next_transition_time);
qemu_get_timer(f, s->irq_timer);
}
}
return 0;
}
static void pit_reset(void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0;i < 3; i++) {
s = &pit->channels[i];
s->mode = 3;
s->gate = (i != 2);
pit_load_count(s, 0);
}
}
PITState *pit_init(int base, int irq)
{
PITState *pit = &pit_state;
PITChannelState *s;
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
s->irq = irq;
register_savevm("i8254", base, 1, pit_save, pit_load, pit);
qemu_register_reset(pit_reset, pit);
register_ioport_write(base, 4, 1, pit_ioport_write, pit);
register_ioport_read(base, 3, 1, pit_ioport_read, pit);
pit_reset(pit);
return pit;
}

561
hw/i8259.c Normal file
View File

@@ -0,0 +1,561 @@
/*
* QEMU 8259 interrupt controller emulation
*
* Copyright (c) 2003-2004 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"
/* debug PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
typedef struct PicState {
uint8_t last_irr; /* edge detection */
uint8_t irr; /* interrupt request register */
uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* highest irq priority */
uint8_t irq_base;
uint8_t read_reg_select;
uint8_t poll;
uint8_t special_mask;
uint8_t init_state;
uint8_t auto_eoi;
uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
uint8_t init4; /* true if 4 byte init */
uint8_t elcr; /* PIIX edge/trigger selection*/
uint8_t elcr_mask;
PicState2 *pics_state;
} PicState;
struct PicState2 {
/* 0 is master pic, 1 is slave pic */
/* XXX: better separation between the two pics */
PicState pics[2];
IRQRequestFunc *irq_request;
void *irq_request_opaque;
/* IOAPIC callback support */
SetIRQFunc *alt_irq_func;
void *alt_irq_opaque;
};
#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
#ifdef DEBUG_IRQ_COUNT
static uint64_t irq_count[16];
#endif
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
{
int mask;
mask = 1 << irq;
if (s->elcr & mask) {
/* level triggered */
if (level) {
s->irr |= mask;
s->last_irr |= mask;
} else {
s->irr &= ~mask;
s->last_irr &= ~mask;
}
} else {
/* edge triggered */
if (level) {
if ((s->last_irr & mask) == 0)
s->irr |= mask;
s->last_irr |= mask;
} else {
s->last_irr &= ~mask;
}
}
}
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
static inline int get_priority(PicState *s, int mask)
{
int priority;
if (mask == 0)
return 8;
priority = 0;
while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
priority++;
return priority;
}
/* return the pic wanted interrupt. return -1 if none */
static int pic_get_irq(PicState *s)
{
int mask, cur_priority, priority;
mask = s->irr & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8)
return -1;
/* compute current priority. If special fully nested mode on the
master, the IRQ coming from the slave is not taken into account
for the priority computation. */
mask = s->isr;
if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
mask &= ~(1 << 2);
cur_priority = get_priority(s, mask);
if (priority < cur_priority) {
/* higher priority found: an irq should be generated */
return (priority + s->priority_add) & 7;
} else {
return -1;
}
}
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
/* XXX: should not export it, but it is needed for an APIC kludge */
void pic_update_irq(PicState2 *s)
{
int irq2, irq;
/* first look at slave pic */
irq2 = pic_get_irq(&s->pics[1]);
if (irq2 >= 0) {
/* if irq request by slave pic, signal master PIC */
pic_set_irq1(&s->pics[0], 2, 1);
pic_set_irq1(&s->pics[0], 2, 0);
}
/* look at requested irq */
irq = pic_get_irq(&s->pics[0]);
if (irq >= 0) {
#if defined(DEBUG_PIC)
{
int i;
for(i = 0; i < 2; i++) {
printf("pic%d: imr=%x irr=%x padd=%d\n",
i, s->pics[i].imr, s->pics[i].irr,
s->pics[i].priority_add);
}
}
printf("pic: cpu_interrupt\n");
#endif
s->irq_request(s->irq_request_opaque, 1);
}
}
#ifdef DEBUG_IRQ_LATENCY
int64_t irq_time[16];
#endif
void pic_set_irq_new(void *opaque, int irq, int level)
{
PicState2 *s = opaque;
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
if (level != irq_level[irq]) {
#if defined(DEBUG_PIC)
printf("pic_set_irq: irq=%d level=%d\n", irq, level);
#endif
irq_level[irq] = level;
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
irq_count[irq]++;
#endif
}
#endif
#ifdef DEBUG_IRQ_LATENCY
if (level) {
irq_time[irq] = qemu_get_clock(vm_clock);
}
#endif
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
/* used for IOAPIC irqs */
if (s->alt_irq_func)
s->alt_irq_func(s->alt_irq_opaque, irq, level);
pic_update_irq(s);
}
/* obsolete function */
void pic_set_irq(int irq, int level)
{
pic_set_irq_new(isa_pic, irq, level);
}
/* acknowledge interrupt 'irq' */
static inline void pic_intack(PicState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi)
s->priority_add = (irq + 1) & 7;
} else {
s->isr |= (1 << irq);
}
/* We don't clear a level sensitive interrupt here */
if (!(s->elcr & (1 << irq)))
s->irr &= ~(1 << irq);
}
int pic_read_irq(PicState2 *s)
{
int irq, irq2, intno;
irq = pic_get_irq(&s->pics[0]);
if (irq >= 0) {
pic_intack(&s->pics[0], irq);
if (irq == 2) {
irq2 = pic_get_irq(&s->pics[1]);
if (irq2 >= 0) {
pic_intack(&s->pics[1], irq2);
} else {
/* spurious IRQ on slave controller */
irq2 = 7;
}
intno = s->pics[1].irq_base + irq2;
irq = irq2 + 8;
} else {
intno = s->pics[0].irq_base + irq;
}
} else {
/* spurious IRQ on host controller */
irq = 7;
intno = s->pics[0].irq_base + irq;
}
pic_update_irq(s);
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
(double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec);
#endif
#if defined(DEBUG_PIC)
printf("pic_interrupt: irq=%d\n", irq);
#endif
return intno;
}
static void pic_reset(void *opaque)
{
PicState *s = opaque;
s->last_irr = 0;
s->irr = 0;
s->imr = 0;
s->isr = 0;
s->priority_add = 0;
s->irq_base = 0;
s->read_reg_select = 0;
s->poll = 0;
s->special_mask = 0;
s->init_state = 0;
s->auto_eoi = 0;
s->rotate_on_auto_eoi = 0;
s->special_fully_nested_mode = 0;
s->init4 = 0;
/* Note: ELCR is not reset */
}
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
int priority, cmd, irq;
#ifdef DEBUG_PIC
printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
#endif
addr &= 1;
if (addr == 0) {
if (val & 0x10) {
/* init */
pic_reset(s);
/* deassert a pending interrupt */
s->pics_state->irq_request(s->pics_state->irq_request_opaque, 0);
s->init_state = 1;
s->init4 = val & 1;
if (val & 0x02)
hw_error("single mode not supported");
if (val & 0x08)
hw_error("level sensitive irq not supported");
} else if (val & 0x08) {
if (val & 0x04)
s->poll = 1;
if (val & 0x02)
s->read_reg_select = val & 1;
if (val & 0x40)
s->special_mask = (val >> 5) & 1;
} else {
cmd = val >> 5;
switch(cmd) {
case 0:
case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break;
case 1: /* end of interrupt */
case 5:
priority = get_priority(s, s->isr);
if (priority != 8) {
irq = (priority + s->priority_add) & 7;
s->isr &= ~(1 << irq);
if (cmd == 5)
s->priority_add = (irq + 1) & 7;
pic_update_irq(s->pics_state);
}
break;
case 3:
irq = val & 7;
s->isr &= ~(1 << irq);
pic_update_irq(s->pics_state);
break;
case 6:
s->priority_add = (val + 1) & 7;
pic_update_irq(s->pics_state);
break;
case 7:
irq = val & 7;
s->isr &= ~(1 << irq);
s->priority_add = (irq + 1) & 7;
pic_update_irq(s->pics_state);
break;
default:
/* no operation */
break;
}
}
} else {
switch(s->init_state) {
case 0:
/* normal mode */
s->imr = val;
pic_update_irq(s->pics_state);
break;
case 1:
s->irq_base = val & 0xf8;
s->init_state = 2;
break;
case 2:
if (s->init4) {
s->init_state = 3;
} else {
s->init_state = 0;
}
break;
case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
s->auto_eoi = (val >> 1) & 1;
s->init_state = 0;
break;
}
}
}
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
{
int ret;
ret = pic_get_irq(s);
if (ret >= 0) {
if (addr1 >> 7) {
s->pics_state->pics[0].isr &= ~(1 << 2);
s->pics_state->pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
s->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq(s->pics_state);
} else {
ret = 0x07;
pic_update_irq(s->pics_state);
}
return ret;
}
static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
unsigned int addr;
int ret;
addr = addr1;
addr &= 1;
if (s->poll) {
ret = pic_poll_read(s, addr1);
s->poll = 0;
} else {
if (addr == 0) {
if (s->read_reg_select)
ret = s->isr;
else
ret = s->irr;
} else {
ret = s->imr;
}
}
#ifdef DEBUG_PIC
printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
#endif
return ret;
}
/* memory mapped interrupt status */
/* XXX: may be the same than pic_read_irq() */
uint32_t pic_intack_read(PicState2 *s)
{
int ret;
ret = pic_poll_read(&s->pics[0], 0x00);
if (ret == 2)
ret = pic_poll_read(&s->pics[1], 0x80) + 8;
/* Prepare for ISR read */
s->pics[0].read_reg_select = 1;
return ret;
}
static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
s->elcr = val & s->elcr_mask;
}
static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
return s->elcr;
}
static void pic_save(QEMUFile *f, void *opaque)
{
PicState *s = opaque;
qemu_put_8s(f, &s->last_irr);
qemu_put_8s(f, &s->irr);
qemu_put_8s(f, &s->imr);
qemu_put_8s(f, &s->isr);
qemu_put_8s(f, &s->priority_add);
qemu_put_8s(f, &s->irq_base);
qemu_put_8s(f, &s->read_reg_select);
qemu_put_8s(f, &s->poll);
qemu_put_8s(f, &s->special_mask);
qemu_put_8s(f, &s->init_state);
qemu_put_8s(f, &s->auto_eoi);
qemu_put_8s(f, &s->rotate_on_auto_eoi);
qemu_put_8s(f, &s->special_fully_nested_mode);
qemu_put_8s(f, &s->init4);
qemu_put_8s(f, &s->elcr);
}
static int pic_load(QEMUFile *f, void *opaque, int version_id)
{
PicState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->last_irr);
qemu_get_8s(f, &s->irr);
qemu_get_8s(f, &s->imr);
qemu_get_8s(f, &s->isr);
qemu_get_8s(f, &s->priority_add);
qemu_get_8s(f, &s->irq_base);
qemu_get_8s(f, &s->read_reg_select);
qemu_get_8s(f, &s->poll);
qemu_get_8s(f, &s->special_mask);
qemu_get_8s(f, &s->init_state);
qemu_get_8s(f, &s->auto_eoi);
qemu_get_8s(f, &s->rotate_on_auto_eoi);
qemu_get_8s(f, &s->special_fully_nested_mode);
qemu_get_8s(f, &s->init4);
qemu_get_8s(f, &s->elcr);
return 0;
}
/* XXX: add generic master/slave system */
static void pic_init1(int io_addr, int elcr_addr, PicState *s)
{
register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
if (elcr_addr >= 0) {
register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
}
register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
qemu_register_reset(pic_reset, s);
}
void pic_info(void)
{
int i;
PicState *s;
if (!isa_pic)
return;
for(i=0;i<2;i++) {
s = &isa_pic->pics[i];
term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
i, s->irr, s->imr, s->isr, s->priority_add,
s->irq_base, s->read_reg_select, s->elcr,
s->special_fully_nested_mode);
}
}
void irq_info(void)
{
#ifndef DEBUG_IRQ_COUNT
term_printf("irq statistic code not compiled.\n");
#else
int i;
int64_t count;
term_printf("IRQ statistics:\n");
for (i = 0; i < 16; i++) {
count = irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
}
#endif
}
PicState2 *pic_init(IRQRequestFunc *irq_request, void *irq_request_opaque)
{
PicState2 *s;
s = qemu_mallocz(sizeof(PicState2));
if (!s)
return NULL;
pic_init1(0x20, 0x4d0, &s->pics[0]);
pic_init1(0xa0, 0x4d1, &s->pics[1]);
s->pics[0].elcr_mask = 0xf8;
s->pics[1].elcr_mask = 0xde;
s->irq_request = irq_request;
s->irq_request_opaque = irq_request_opaque;
s->pics[0].pics_state = s;
s->pics[1].pics_state = s;
return s;
}
void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
void *alt_irq_opaque)
{
s->alt_irq_func = alt_irq_func;
s->alt_irq_opaque = alt_irq_opaque;
}

1670
hw/ide.c

File diff suppressed because it is too large Load Diff

546
hw/integratorcp.c Normal file
View File

@@ -0,0 +1,546 @@
/*
* ARM Integrator CP System emulation.
*
* Copyright (c) 2005-2006 CodeSourcery.
* Written by Paul Brook
*
* This code is licenced under the GPL
*/
#include "vl.h"
#include "arm_pic.h"
void DMA_run (void)
{
}
typedef struct {
uint32_t flash_offset;
uint32_t cm_osc;
uint32_t cm_ctrl;
uint32_t cm_lock;
uint32_t cm_auxosc;
uint32_t cm_sdram;
uint32_t cm_init;
uint32_t cm_flags;
uint32_t cm_nvflags;
uint32_t int_level;
uint32_t irq_enabled;
uint32_t fiq_enabled;
} integratorcm_state;
static uint8_t integrator_spd[128] = {
128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
};
static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
{
integratorcm_state *s = (integratorcm_state *)opaque;
offset -= 0x10000000;
if (offset >= 0x100 && offset < 0x200) {
/* CM_SPD */
if (offset >= 0x180)
return 0;
return integrator_spd[offset >> 2];
}
switch (offset >> 2) {
case 0: /* CM_ID */
return 0x411a3001;
case 1: /* CM_PROC */
return 0;
case 2: /* CM_OSC */
return s->cm_osc;
case 3: /* CM_CTRL */
return s->cm_ctrl;
case 4: /* CM_STAT */
return 0x00100000;
case 5: /* CM_LOCK */
if (s->cm_lock == 0xa05f) {
return 0x1a05f;
} else {
return s->cm_lock;
}
case 6: /* CM_LMBUSCNT */
/* ??? High frequency timer. */
cpu_abort(cpu_single_env, "integratorcm_read: CM_LMBUSCNT");
case 7: /* CM_AUXOSC */
return s->cm_auxosc;
case 8: /* CM_SDRAM */
return s->cm_sdram;
case 9: /* CM_INIT */
return s->cm_init;
case 10: /* CM_REFCT */
/* ??? High frequency timer. */
cpu_abort(cpu_single_env, "integratorcm_read: CM_REFCT");
case 12: /* CM_FLAGS */
return s->cm_flags;
case 14: /* CM_NVFLAGS */
return s->cm_nvflags;
case 16: /* CM_IRQ_STAT */
return s->int_level & s->irq_enabled;
case 17: /* CM_IRQ_RSTAT */
return s->int_level;
case 18: /* CM_IRQ_ENSET */
return s->irq_enabled;
case 20: /* CM_SOFT_INTSET */
return s->int_level & 1;
case 24: /* CM_FIQ_STAT */
return s->int_level & s->fiq_enabled;
case 25: /* CM_FIQ_RSTAT */
return s->int_level;
case 26: /* CM_FIQ_ENSET */
return s->fiq_enabled;
case 32: /* CM_VOLTAGE_CTL0 */
case 33: /* CM_VOLTAGE_CTL1 */
case 34: /* CM_VOLTAGE_CTL2 */
case 35: /* CM_VOLTAGE_CTL3 */
/* ??? Voltage control unimplemented. */
return 0;
default:
cpu_abort (cpu_single_env,
"integratorcm_read: Unimplemented offset 0x%x\n", offset);
return 0;
}
}
static void integratorcm_do_remap(integratorcm_state *s, int flash)
{
if (flash) {
cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
} else {
cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
}
//??? tlb_flush (cpu_single_env, 1);
}
static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
{
if (value & 8) {
cpu_abort(cpu_single_env, "Board reset\n");
}
if ((s->cm_init ^ value) & 4) {
integratorcm_do_remap(s, (value & 4) == 0);
}
if ((s->cm_init ^ value) & 1) {
printf("Green LED %s\n", (value & 1) ? "on" : "off");
}
s->cm_init = (s->cm_init & ~ 5) | (value ^ 5);
}
static void integratorcm_update(integratorcm_state *s)
{
/* ??? The CPU irq/fiq is raised when either the core module or base PIC
are active. */
if (s->int_level & (s->irq_enabled | s->fiq_enabled))
cpu_abort(cpu_single_env, "Core module interrupt\n");
}
static void integratorcm_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
integratorcm_state *s = (integratorcm_state *)opaque;
offset -= 0x10000000;
switch (offset >> 2) {
case 2: /* CM_OSC */
if (s->cm_lock == 0xa05f)
s->cm_osc = value;
break;
case 3: /* CM_CTRL */
integratorcm_set_ctrl(s, value);
break;
case 5: /* CM_LOCK */
s->cm_lock = value & 0xffff;
break;
case 7: /* CM_AUXOSC */
if (s->cm_lock == 0xa05f)
s->cm_auxosc = value;
break;
case 8: /* CM_SDRAM */
s->cm_sdram = value;
break;
case 9: /* CM_INIT */
/* ??? This can change the memory bus frequency. */
s->cm_init = value;
break;
case 12: /* CM_FLAGSS */
s->cm_flags |= value;
break;
case 13: /* CM_FLAGSC */
s->cm_flags &= ~value;
break;
case 14: /* CM_NVFLAGSS */
s->cm_nvflags |= value;
break;
case 15: /* CM_NVFLAGSS */
s->cm_nvflags &= ~value;
break;
case 18: /* CM_IRQ_ENSET */
s->irq_enabled |= value;
integratorcm_update(s);
break;
case 19: /* CM_IRQ_ENCLR */
s->irq_enabled &= ~value;
integratorcm_update(s);
break;
case 20: /* CM_SOFT_INTSET */
s->int_level |= (value & 1);
integratorcm_update(s);
break;
case 21: /* CM_SOFT_INTCLR */
s->int_level &= ~(value & 1);
integratorcm_update(s);
break;
case 26: /* CM_FIQ_ENSET */
s->fiq_enabled |= value;
integratorcm_update(s);
break;
case 27: /* CM_FIQ_ENCLR */
s->fiq_enabled &= ~value;
integratorcm_update(s);
break;
case 32: /* CM_VOLTAGE_CTL0 */
case 33: /* CM_VOLTAGE_CTL1 */
case 34: /* CM_VOLTAGE_CTL2 */
case 35: /* CM_VOLTAGE_CTL3 */
/* ??? Voltage control unimplemented. */
break;
default:
cpu_abort (cpu_single_env,
"integratorcm_write: Unimplemented offset 0x%x\n", offset);
break;
}
}
/* Integrator/CM control registers. */
static CPUReadMemoryFunc *integratorcm_readfn[] = {
integratorcm_read,
integratorcm_read,
integratorcm_read
};
static CPUWriteMemoryFunc *integratorcm_writefn[] = {
integratorcm_write,
integratorcm_write,
integratorcm_write
};
static void integratorcm_init(int memsz, uint32_t flash_offset)
{
int iomemtype;
integratorcm_state *s;
s = (integratorcm_state *)qemu_mallocz(sizeof(integratorcm_state));
s->cm_osc = 0x01000048;
/* ??? What should the high bits of this value be? */
s->cm_auxosc = 0x0007feff;
s->cm_sdram = 0x00011122;
if (memsz >= 256) {
integrator_spd[31] = 64;
s->cm_sdram |= 0x10;
} else if (memsz >= 128) {
integrator_spd[31] = 32;
s->cm_sdram |= 0x0c;
} else if (memsz >= 64) {
integrator_spd[31] = 16;
s->cm_sdram |= 0x08;
} else if (memsz >= 32) {
integrator_spd[31] = 4;
s->cm_sdram |= 0x04;
} else {
integrator_spd[31] = 2;
}
memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
s->cm_init = 0x00000112;
s->flash_offset = flash_offset;
iomemtype = cpu_register_io_memory(0, integratorcm_readfn,
integratorcm_writefn, s);
cpu_register_physical_memory(0x10000000, 0x007fffff, iomemtype);
integratorcm_do_remap(s, 1);
/* ??? Save/restore. */
}
/* Integrator/CP hardware emulation. */
/* Primary interrupt controller. */
typedef struct icp_pic_state
{
arm_pic_handler handler;
uint32_t base;
uint32_t level;
uint32_t irq_enabled;
uint32_t fiq_enabled;
void *parent;
int parent_irq;
int parent_fiq;
} icp_pic_state;
static void icp_pic_update(icp_pic_state *s)
{
uint32_t flags;
if (s->parent_irq != -1) {
flags = (s->level & s->irq_enabled);
pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
}
if (s->parent_fiq != -1) {
flags = (s->level & s->fiq_enabled);
pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
}
}
static void icp_pic_set_irq(void *opaque, int irq, int level)
{
icp_pic_state *s = (icp_pic_state *)opaque;
if (level)
s->level |= 1 << irq;
else
s->level &= ~(1 << irq);
icp_pic_update(s);
}
static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
{
icp_pic_state *s = (icp_pic_state *)opaque;
offset -= s->base;
switch (offset >> 2) {
case 0: /* IRQ_STATUS */
return s->level & s->irq_enabled;
case 1: /* IRQ_RAWSTAT */
return s->level;
case 2: /* IRQ_ENABLESET */
return s->irq_enabled;
case 4: /* INT_SOFTSET */
return s->level & 1;
case 8: /* FRQ_STATUS */
return s->level & s->fiq_enabled;
case 9: /* FRQ_RAWSTAT */
return s->level;
case 10: /* FRQ_ENABLESET */
return s->fiq_enabled;
case 3: /* IRQ_ENABLECLR */
case 5: /* INT_SOFTCLR */
case 11: /* FRQ_ENABLECLR */
default:
printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
return 0;
}
}
static void icp_pic_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
icp_pic_state *s = (icp_pic_state *)opaque;
offset -= s->base;
switch (offset >> 2) {
case 2: /* IRQ_ENABLESET */
s->irq_enabled |= value;
break;
case 3: /* IRQ_ENABLECLR */
s->irq_enabled &= ~value;
break;
case 4: /* INT_SOFTSET */
if (value & 1)
pic_set_irq_new(s, 0, 1);
break;
case 5: /* INT_SOFTCLR */
if (value & 1)
pic_set_irq_new(s, 0, 0);
break;
case 10: /* FRQ_ENABLESET */
s->fiq_enabled |= value;
break;
case 11: /* FRQ_ENABLECLR */
s->fiq_enabled &= ~value;
break;
case 0: /* IRQ_STATUS */
case 1: /* IRQ_RAWSTAT */
case 8: /* FRQ_STATUS */
case 9: /* FRQ_RAWSTAT */
default:
printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
return;
}
icp_pic_update(s);
}
static CPUReadMemoryFunc *icp_pic_readfn[] = {
icp_pic_read,
icp_pic_read,
icp_pic_read
};
static CPUWriteMemoryFunc *icp_pic_writefn[] = {
icp_pic_write,
icp_pic_write,
icp_pic_write
};
static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
int parent_irq, int parent_fiq)
{
icp_pic_state *s;
int iomemtype;
s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
if (!s)
return NULL;
s->handler = icp_pic_set_irq;
s->base = base;
s->parent = parent;
s->parent_irq = parent_irq;
s->parent_fiq = parent_fiq;
iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
icp_pic_writefn, s);
cpu_register_physical_memory(base, 0x007fffff, iomemtype);
/* ??? Save/restore. */
return s;
}
/* CP control registers. */
typedef struct {
uint32_t base;
} icp_control_state;
static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
{
icp_control_state *s = (icp_control_state *)opaque;
offset -= s->base;
switch (offset >> 2) {
case 0: /* CP_IDFIELD */
return 0x41034003;
case 1: /* CP_FLASHPROG */
return 0;
case 2: /* CP_INTREG */
return 0;
case 3: /* CP_DECODE */
return 0x11;
default:
cpu_abort (cpu_single_env, "icp_control_read: Bad offset %x\n", offset);
return 0;
}
}
static void icp_control_write(void *opaque, target_phys_addr_t offset,
uint32_t value)
{
icp_control_state *s = (icp_control_state *)opaque;
offset -= s->base;
switch (offset >> 2) {
case 1: /* CP_FLASHPROG */
case 2: /* CP_INTREG */
case 3: /* CP_DECODE */
/* Nothing interesting implemented yet. */
break;
default:
cpu_abort (cpu_single_env, "icp_control_write: Bad offset %x\n", offset);
}
}
static CPUReadMemoryFunc *icp_control_readfn[] = {
icp_control_read,
icp_control_read,
icp_control_read
};
static CPUWriteMemoryFunc *icp_control_writefn[] = {
icp_control_write,
icp_control_write,
icp_control_write
};
static void icp_control_init(uint32_t base)
{
int iomemtype;
icp_control_state *s;
s = (icp_control_state *)qemu_mallocz(sizeof(icp_control_state));
iomemtype = cpu_register_io_memory(0, icp_control_readfn,
icp_control_writefn, s);
cpu_register_physical_memory(base, 0x007fffff, iomemtype);
s->base = base;
/* ??? Save/restore. */
}
/* Board init. */
static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename, uint32_t cpuid)
{
CPUState *env;
uint32_t bios_offset;
icp_pic_state *pic;
void *cpu_pic;
env = cpu_init();
cpu_arm_set_model(env, cpuid);
bios_offset = ram_size + vga_ram_size;
/* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
/* ??? RAM shoud repeat to fill physical memory space. */
/* SDRAM at address zero*/
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* And again at address 0x80000000 */
cpu_register_physical_memory(0x80000000, ram_size, IO_MEM_RAM);
integratorcm_init(ram_size >> 20, bios_offset);
cpu_pic = arm_pic_init_cpu(env);
pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
icp_pic_init(0xca000000, pic, 26, -1);
icp_pit_init(0x13000000, pic, 5);
pl011_init(0x16000000, pic, 1, serial_hds[0]);
pl011_init(0x17000000, pic, 2, serial_hds[1]);
icp_control_init(0xcb000000);
pl050_init(0x18000000, pic, 3, 0);
pl050_init(0x19000000, pic, 4, 1);
if (nd_table[0].vlan) {
if (nd_table[0].model == NULL
|| strcmp(nd_table[0].model, "smc91c111") == 0) {
smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
exit (1);
}
}
pl110_init(ds, 0xc0000000, pic, 22, 0);
arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
initrd_filename, 0x113);
}
static void integratorcp926_init(int ram_size, int vga_ram_size,
int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename, ARM_CPUID_ARM926);
}
static void integratorcp1026_init(int ram_size, int vga_ram_size,
int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename, ARM_CPUID_ARM1026);
}
QEMUMachine integratorcp926_machine = {
"integratorcp926",
"ARM Integrator/CP (ARM926EJ-S)",
integratorcp926_init,
};
QEMUMachine integratorcp1026_machine = {
"integratorcp1026",
"ARM Integrator/CP (ARM1026EJ-S)",
integratorcp1026_init,
};

258
hw/iommu.c Normal file
View File

@@ -0,0 +1,258 @@
/*
* QEMU SPARC iommu emulation
*
* Copyright (c) 2003-2005 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"
/* debug iommu */
//#define DEBUG_IOMMU
#ifdef DEBUG_IOMMU
#define DPRINTF(fmt, args...) \
do { printf("IOMMU: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#define IOMMU_NREGS (3*4096/4)
#define IOMMU_CTRL (0x0000 >> 2)
#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
#define IOMMU_VERSION 0x04000000
#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
#define IOMMU_CTRL_MASK 0x0000001d
#define IOMMU_BASE (0x0004 >> 2)
#define IOMMU_BASE_MASK 0x07fffc00
#define IOMMU_TLBFLUSH (0x0014 >> 2)
#define IOMMU_TLBFLUSH_MASK 0xffffffff
#define IOMMU_PGFLUSH (0x0018 >> 2)
#define IOMMU_PGFLUSH_MASK 0xffffffff
#define IOMMU_SBCFG0 (0x1010 >> 2) /* SBUS configration per-slot */
#define IOMMU_SBCFG1 (0x1014 >> 2) /* SBUS configration per-slot */
#define IOMMU_SBCFG2 (0x1018 >> 2) /* SBUS configration per-slot */
#define IOMMU_SBCFG3 (0x101c >> 2) /* SBUS configration per-slot */
#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
produced by this device as pure
physical. */
#define IOMMU_SBCFG_MASK 0x00010003
#define IOMMU_ARBEN (0x2000 >> 2) /* SBUS arbitration enable */
#define IOMMU_ARBEN_MASK 0x001f0000
#define IOMMU_MID 0x00000008
/* The format of an iopte in the page tables */
#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
#define IOPTE_WRITE 0x00000004 /* Writeable */
#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
#define IOPTE_WAZ 0x00000001 /* Write as zeros */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (PAGE_SIZE - 1)
typedef struct IOMMUState {
uint32_t addr;
uint32_t regs[IOMMU_NREGS];
uint32_t iostart;
} IOMMUState;
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
{
IOMMUState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
DPRINTF("read reg[%d] = %x\n", saddr, s->regs[saddr]);
return s->regs[saddr];
break;
}
return 0;
}
static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
IOMMUState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
DPRINTF("write reg[%d] = %x\n", saddr, val);
switch (saddr) {
case IOMMU_CTRL:
switch (val & IOMMU_CTRL_RNGE) {
case IOMMU_RNGE_16MB:
s->iostart = 0xff000000;
break;
case IOMMU_RNGE_32MB:
s->iostart = 0xfe000000;
break;
case IOMMU_RNGE_64MB:
s->iostart = 0xfc000000;
break;
case IOMMU_RNGE_128MB:
s->iostart = 0xf8000000;
break;
case IOMMU_RNGE_256MB:
s->iostart = 0xf0000000;
break;
case IOMMU_RNGE_512MB:
s->iostart = 0xe0000000;
break;
case IOMMU_RNGE_1GB:
s->iostart = 0xc0000000;
break;
default:
case IOMMU_RNGE_2GB:
s->iostart = 0x80000000;
break;
}
DPRINTF("iostart = %x\n", s->iostart);
s->regs[saddr] = ((val & IOMMU_CTRL_MASK) | IOMMU_VERSION);
break;
case IOMMU_BASE:
s->regs[saddr] = val & IOMMU_BASE_MASK;
break;
case IOMMU_TLBFLUSH:
DPRINTF("tlb flush %x\n", val);
s->regs[saddr] = val & IOMMU_TLBFLUSH_MASK;
break;
case IOMMU_PGFLUSH:
DPRINTF("page flush %x\n", val);
s->regs[saddr] = val & IOMMU_PGFLUSH_MASK;
break;
case IOMMU_SBCFG0:
case IOMMU_SBCFG1:
case IOMMU_SBCFG2:
case IOMMU_SBCFG3:
s->regs[saddr] = val & IOMMU_SBCFG_MASK;
break;
case IOMMU_ARBEN:
// XXX implement SBus probing: fault when reading unmapped
// addresses, fault cause and address stored to MMU/IOMMU
s->regs[saddr] = (val & IOMMU_ARBEN_MASK) | IOMMU_MID;
break;
default:
s->regs[saddr] = val;
break;
}
}
static CPUReadMemoryFunc *iommu_mem_read[3] = {
iommu_mem_readw,
iommu_mem_readw,
iommu_mem_readw,
};
static CPUWriteMemoryFunc *iommu_mem_write[3] = {
iommu_mem_writew,
iommu_mem_writew,
iommu_mem_writew,
};
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
{
IOMMUState *s = opaque;
uint32_t iopte, pa, tmppte;
iopte = s->regs[1] << 4;
addr &= ~s->iostart;
iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
pa = ldl_phys(iopte);
tmppte = pa;
pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, tmppte);
return pa;
}
static void iommu_save(QEMUFile *f, void *opaque)
{
IOMMUState *s = opaque;
int i;
qemu_put_be32s(f, &s->addr);
for (i = 0; i < IOMMU_NREGS; i++)
qemu_put_be32s(f, &s->regs[i]);
qemu_put_be32s(f, &s->iostart);
}
static int iommu_load(QEMUFile *f, void *opaque, int version_id)
{
IOMMUState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->addr);
for (i = 0; i < IOMMU_NREGS; i++)
qemu_put_be32s(f, &s->regs[i]);
qemu_get_be32s(f, &s->iostart);
return 0;
}
static void iommu_reset(void *opaque)
{
IOMMUState *s = opaque;
memset(s->regs, 0, IOMMU_NREGS * 4);
s->iostart = 0;
s->regs[0] = IOMMU_VERSION;
}
void *iommu_init(uint32_t addr)
{
IOMMUState *s;
int iommu_io_memory;
s = qemu_mallocz(sizeof(IOMMUState));
if (!s)
return NULL;
s->addr = addr;
iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
cpu_register_physical_memory(addr, IOMMU_NREGS * 4, iommu_io_memory);
register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
qemu_register_reset(iommu_reset, s);
return s;
}

462
hw/lance.c Normal file
View File

@@ -0,0 +1,462 @@
/*
* QEMU Lance emulation
*
* Copyright (c) 2003-2005 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"
/* debug LANCE card */
//#define DEBUG_LANCE
#ifdef DEBUG_LANCE
#define DPRINTF(fmt, args...) \
do { printf("LANCE: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
#endif
#define LE_CSR0 0
#define LE_CSR1 1
#define LE_CSR2 2
#define LE_CSR3 3
#define LE_NREGS (LE_CSR3 + 1)
#define LE_MAXREG LE_CSR3
#define LE_RDP 0
#define LE_RAP 1
#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
#define LE_C0_MERR 0x0800 /* ME: Memory error */
#define LE_C0_RINT 0x0400 /* Received interrupt */
#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
#define LE_C0_INTR 0x0080 /* Interrupt or error */
#define LE_C0_INEA 0x0040 /* Interrupt enable */
#define LE_C0_RXON 0x0020 /* Receiver on */
#define LE_C0_TXON 0x0010 /* Transmitter on */
#define LE_C0_TDMD 0x0008 /* Transmitter demand */
#define LE_C0_STOP 0x0004 /* Stop the card */
#define LE_C0_STRT 0x0002 /* Start the card */
#define LE_C0_INIT 0x0001 /* Init the card */
#define LE_C3_BSWP 0x4 /* SWAP */
#define LE_C3_ACON 0x2 /* ALE Control */
#define LE_C3_BCON 0x1 /* Byte control */
/* Receive message descriptor 1 */
#define LE_R1_OWN 0x80 /* Who owns the entry */
#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
#define LE_R1_FRA 0x20 /* FRA: Frame error */
#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
#define LE_R1_CRC 0x08 /* CRC error */
#define LE_R1_BUF 0x04 /* BUF: Buffer error */
#define LE_R1_SOP 0x02 /* Start of packet */
#define LE_R1_EOP 0x01 /* End of packet */
#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T1_OWN 0x80 /* Lance owns the packet */
#define LE_T1_ERR 0x40 /* Error summary */
#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
#define LE_T1_EONE 0x08 /* Error: one retry needed */
#define LE_T1_EDEF 0x04 /* Error: deferred */
#define LE_T1_SOP 0x02 /* Start of packet */
#define LE_T1_EOP 0x01 /* End of packet */
#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
#define LE_T3_BUF 0x8000 /* Buffer error */
#define LE_T3_UFL 0x4000 /* Error underflow */
#define LE_T3_LCOL 0x1000 /* Error late collision */
#define LE_T3_CLOS 0x0800 /* Error carrier loss */
#define LE_T3_RTY 0x0400 /* Error retry */
#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
#define PKT_BUF_SZ 1544
#define RX_BUFF_SIZE PKT_BUF_SZ
#define TX_BUFF_SIZE PKT_BUF_SZ
struct lance_rx_desc {
unsigned short rmd0; /* low address of packet */
unsigned char rmd1_bits; /* descriptor bits */
unsigned char rmd1_hadr; /* high address of packet */
short length; /* This length is 2s complement (negative)!
* Buffer length
*/
unsigned short mblength; /* This is the actual number of bytes received */
};
struct lance_tx_desc {
unsigned short tmd0; /* low address of packet */
unsigned char tmd1_bits; /* descriptor bits */
unsigned char tmd1_hadr; /* high address of packet */
short length; /* Length is 2s complement (negative)! */
unsigned short misc;
};
/* The LANCE initialization block, described in databook. */
/* On the Sparc, this block should be on a DMA region */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
unsigned char phys_addr[6]; /* Physical ethernet address */
unsigned filter[2]; /* Multicast filter. */
/* Receive and transmit ring base, along with extra bits. */
unsigned short rx_ptr; /* receive descriptor addr */
unsigned short rx_len; /* receive len and high addr */
unsigned short tx_ptr; /* transmit descriptor addr */
unsigned short tx_len; /* transmit len and high addr */
/* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
struct lance_rx_desc brx_ring[RX_RING_SIZE];
struct lance_tx_desc btx_ring[TX_RING_SIZE];
char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
char pad[2]; /* align rx_buf for copy_and_sum(). */
char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
};
#define LEDMA_REGS 4
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
typedef struct LANCEState {
VLANClientState *vc;
uint8_t macaddr[6]; /* init mac address */
uint32_t leptr;
uint16_t addr;
uint16_t regs[LE_NREGS];
uint8_t phys[6]; /* mac address */
int irq;
unsigned int rxptr, txptr;
uint32_t ledmaregs[LEDMA_REGS];
} LANCEState;
static void lance_send(void *opaque);
static void lance_reset(void *opaque)
{
LANCEState *s = opaque;
memcpy(s->phys, s->macaddr, 6);
s->rxptr = 0;
s->txptr = 0;
memset(s->regs, 0, LE_NREGS * 2);
s->regs[LE_CSR0] = LE_C0_STOP;
memset(s->ledmaregs, 0, LEDMA_REGS * 4);
}
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]);
return s->regs[s->addr];
case LE_RAP:
DPRINTF("read areg = %4.4x\n", s->addr);
return s->addr;
default:
DPRINTF("read unknown(%d)\n", saddr>>1);
break;
}
return 0;
}
static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LANCEState *s = opaque;
uint32_t saddr;
uint16_t reg;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val);
switch(s->addr) {
case LE_CSR0:
if (val & LE_C0_STOP) {
s->regs[LE_CSR0] = LE_C0_STOP;
break;
}
reg = s->regs[LE_CSR0];
// 1 = clear for some bits
reg &= ~(val & 0x7f00);
// generated bits
reg &= ~(LE_C0_ERR | LE_C0_INTR);
if (reg & 0x7100)
reg |= LE_C0_ERR;
if (reg & 0x7f00)
reg |= LE_C0_INTR;
// direct bit
reg &= ~LE_C0_INEA;
reg |= val & LE_C0_INEA;
// exclusive bits
if (val & LE_C0_INIT) {
reg |= LE_C0_IDON | LE_C0_INIT;
reg &= ~LE_C0_STOP;
}
else if (val & LE_C0_STRT) {
reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
reg &= ~LE_C0_STOP;
}
s->regs[LE_CSR0] = reg;
break;
case LE_CSR1:
s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
s->regs[s->addr] = val;
break;
case LE_CSR2:
s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
s->regs[s->addr] = val;
break;
case LE_CSR3:
s->regs[s->addr] = val;
break;
}
break;
case LE_RAP:
DPRINTF("write areg = %4.4x\n", val);
if (val < LE_NREGS)
s->addr = val;
break;
default:
DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val);
break;
}
lance_send(s);
}
static CPUReadMemoryFunc *lance_mem_read[3] = {
lance_mem_readw,
lance_mem_readw,
lance_mem_readw,
};
static CPUWriteMemoryFunc *lance_mem_write[3] = {
lance_mem_writew,
lance_mem_writew,
lance_mem_writew,
};
#define MIN_BUF_SIZE 60
static int lance_can_receive(void *opaque)
{
return 1;
}
static void lance_receive(void *opaque, const uint8_t *buf, int size)
{
LANCEState *s = opaque;
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_rxptr;
uint16_t temp16;
uint8_t temp8;
DPRINTF("receive size %d\n", size);
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
old_rxptr = s->rxptr;
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
if (temp8 == (LE_R1_OWN)) {
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
temp16 = size + 4;
bswap16s(&temp16);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2);
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
temp8 = LE_R1_POK;
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
if (s->regs[LE_CSR0] & LE_C0_INEA)
pic_set_irq(s->irq, 1);
DPRINTF("got packet, len %d\n", size);
return;
}
}
}
static void lance_send(void *opaque)
{
LANCEState *s = opaque;
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_txptr;
uint16_t temp16;
uint8_t temp8;
char pkt_buf[PKT_BUF_SZ];
DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]);
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
return;
ib = (void *) iommu_translate(dmaptr);
DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring);
old_txptr = s->txptr;
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
if (temp8 == (LE_T1_POK|LE_T1_OWN)) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2);
bswap16s(&temp16);
temp16 = (~temp16) + 1;
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16);
DPRINTF("sending packet, len %d\n", temp16);
qemu_send_packet(s->vc, pkt_buf, temp16);
temp8 = LE_T1_POK;
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1);
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
}
}
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
}
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr & LEDMA_MAXADDR) >> 2;
return s->ledmaregs[saddr];
}
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr & LEDMA_MAXADDR) >> 2;
s->ledmaregs[saddr] = val;
}
static CPUReadMemoryFunc *ledma_mem_read[3] = {
ledma_mem_readl,
ledma_mem_readl,
ledma_mem_readl,
};
static CPUWriteMemoryFunc *ledma_mem_write[3] = {
ledma_mem_writel,
ledma_mem_writel,
ledma_mem_writel,
};
static void lance_save(QEMUFile *f, void *opaque)
{
LANCEState *s = opaque;
int i;
qemu_put_be32s(f, &s->leptr);
qemu_put_be16s(f, &s->addr);
for (i = 0; i < LE_NREGS; i ++)
qemu_put_be16s(f, &s->regs[i]);
qemu_put_buffer(f, s->phys, 6);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_put_be32s(f, &s->ledmaregs[i]);
}
static int lance_load(QEMUFile *f, void *opaque, int version_id)
{
LANCEState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->leptr);
qemu_get_be16s(f, &s->addr);
for (i = 0; i < LE_NREGS; i ++)
qemu_get_be16s(f, &s->regs[i]);
qemu_get_buffer(f, s->phys, 6);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_get_be32s(f, &s->ledmaregs[i]);
return 0;
}
void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
{
LANCEState *s;
int lance_io_memory, ledma_io_memory;
s = qemu_mallocz(sizeof(LANCEState));
if (!s)
return;
s->irq = irq;
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
cpu_register_physical_memory(leaddr, 4, lance_io_memory);
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
memcpy(s->macaddr, nd->macaddr, 6);
lance_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
s->macaddr[0],
s->macaddr[1],
s->macaddr[2],
s->macaddr[3],
s->macaddr[4],
s->macaddr[5]);
register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
qemu_register_reset(lance_reset, s);
}

608
hw/m48t59.c Normal file
View File

@@ -0,0 +1,608 @@
/*
* QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
*
* Copyright (c) 2003-2005 Jocelyn Mayer
*
* 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"
#include "m48t59.h"
//#define DEBUG_NVRAM
#if defined(DEBUG_NVRAM)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
/*
* The M48T08 and M48T59 chips are very similar. The newer '59 has
* alarm and a watchdog timer and related control registers. In the
* PPC platform there is also a nvram lock function.
*/
struct m48t59_t {
/* Model parameters */
int type; // 8 = m48t08, 59 = m48t59
/* Hardware parameters */
int IRQ;
int mem_index;
uint32_t mem_base;
uint32_t io_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* Alarm & watchdog */
time_t alarm;
struct QEMUTimer *alrm_timer;
struct QEMUTimer *wd_timer;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
/* Fake timer functions */
/* Generic helpers for BCD */
static inline uint8_t toBCD (uint8_t value)
{
return (((value / 10) % 10) << 4) | (value % 10);
}
static inline uint8_t fromBCD (uint8_t BCD)
{
return ((BCD >> 4) * 10) + (BCD & 0x0F);
}
/* RTC management helpers */
static void get_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t t;
t = time(NULL) + NVRAM->time_offset;
#ifdef _WIN32
memcpy(tm,localtime(&t),sizeof(*tm));
#else
localtime_r (&t, tm) ;
#endif
}
static void set_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t now, new_time;
new_time = mktime(tm);
now = time(NULL);
NVRAM->time_offset = new_time - now;
}
/* Alarm management */
static void alarm_cb (void *opaque)
{
struct tm tm, tm_now;
uint64_t next_time;
m48t59_t *NVRAM = opaque;
pic_set_irq(NVRAM->IRQ, 1);
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a month */
get_time(NVRAM, &tm_now);
memcpy(&tm, &tm_now, sizeof(struct tm));
tm.tm_mon++;
if (tm.tm_mon == 13) {
tm.tm_mon = 1;
tm.tm_year++;
}
next_time = mktime(&tm);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a day */
next_time = 24 * 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once an hour */
next_time = 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a minute */
next_time = 60 + mktime(&tm_now);
} else {
/* Repeat once a second */
next_time = 1 + mktime(&tm_now);
}
qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
pic_set_irq(NVRAM->IRQ, 0);
}
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
{
#ifdef _WIN32
memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
#else
localtime_r (&NVRAM->alarm, tm);
#endif
}
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
{
NVRAM->alarm = mktime(tm);
if (NVRAM->alrm_timer != NULL) {
qemu_del_timer(NVRAM->alrm_timer);
NVRAM->alrm_timer = NULL;
}
if (NVRAM->alarm - time(NULL) > 0)
qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
/* Watchdog management */
static void watchdog_cb (void *opaque)
{
m48t59_t *NVRAM = opaque;
NVRAM->buffer[0x1FF0] |= 0x80;
if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40;
/* May it be a hw CPU Reset instead ? */
qemu_system_reset_request();
} else {
pic_set_irq(NVRAM->IRQ, 1);
pic_set_irq(NVRAM->IRQ, 0);
}
}
static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
{
uint64_t interval; /* in 1/16 seconds */
if (NVRAM->wd_timer != NULL) {
qemu_del_timer(NVRAM->wd_timer);
NVRAM->wd_timer = NULL;
}
NVRAM->buffer[0x1FF0] &= ~0x80;
if (value != 0) {
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
((interval * 1000) >> 4));
}
}
/* Direct access to NVRAM */
void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val)
{
struct tm tm;
int tmp;
if (addr > 0x1FF8 && addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, addr, val);
if (NVRAM->type == 8 &&
(addr >= 0x1ff0 && addr <= 0x1ff7))
goto do_write;
switch (addr) {
case 0x1FF0:
/* flags register : read-only */
break;
case 0x1FF1:
/* unused */
break;
case 0x1FF2:
/* alarm seconds */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_sec = tmp;
NVRAM->buffer[0x1FF2] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF3:
/* alarm minutes */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_min = tmp;
NVRAM->buffer[0x1FF3] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF4:
/* alarm hours */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_alarm(NVRAM, &tm);
tm.tm_hour = tmp;
NVRAM->buffer[0x1FF4] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF5:
/* alarm date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_alarm(NVRAM, &tm);
tm.tm_mday = tmp;
NVRAM->buffer[0x1FF5] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF6:
/* interrupts */
NVRAM->buffer[0x1FF6] = val;
break;
case 0x1FF7:
/* watchdog */
NVRAM->buffer[0x1FF7] = val;
set_up_watchdog(NVRAM, val);
break;
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0;
}
}
NVRAM->buffer[0x1FF9] = val & 0x80;
break;
case 0x1FFA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
NVRAM->buffer[0x1FFC] = val & 0x40;
break;
case 0x1FFD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm);
}
break;
case 0x1FFF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
default:
/* Check lock registers state */
if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
break;
if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
break;
do_write:
if (addr < NVRAM->size) {
NVRAM->buffer[addr] = val & 0xFF;
}
break;
}
}
uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr)
{
struct tm tm;
uint32_t retval = 0xFF;
if (NVRAM->type == 8 &&
(addr >= 0x1ff0 && addr <= 0x1ff7))
goto do_read;
switch (addr) {
case 0x1FF0:
/* flags register */
goto do_read;
case 0x1FF1:
/* unused */
retval = 0;
break;
case 0x1FF2:
/* alarm seconds */
goto do_read;
case 0x1FF3:
/* alarm minutes */
goto do_read;
case 0x1FF4:
/* alarm hours */
goto do_read;
case 0x1FF5:
/* alarm date */
goto do_read;
case 0x1FF6:
/* interrupts */
goto do_read;
case 0x1FF7:
/* A read resets the watchdog */
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read;
case 0x1FF8:
/* control */
goto do_read;
case 0x1FF9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
/* day of the week / century */
get_time(NVRAM, &tm);
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
break;
case 0x1FFD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
if (addr >= 0x20 && addr <= 0x2F && (NVRAM->lock & 1))
break;
if (addr >= 0x30 && addr <= 0x3F && (NVRAM->lock & 2))
break;
do_read:
if (addr < NVRAM->size) {
retval = NVRAM->buffer[addr];
}
break;
}
if (addr > 0x1FF9 && addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
return retval;
}
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
{
NVRAM->addr = addr;
}
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
{
NVRAM->lock ^= 1 << lock;
}
/* IO access to NVRAM */
static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
NVRAM->addr |= val;
break;
case 1:
NVRAM->addr &= ~0xFF00;
NVRAM->addr |= val << 8;
break;
case 3:
m48t59_write(NVRAM, val, NVRAM->addr);
NVRAM->addr = 0x0000;
break;
default:
break;
}
}
static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->io_base;
switch (addr) {
case 3:
retval = m48t59_read(NVRAM, NVRAM->addr);
break;
default:
retval = -1;
break;
}
NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
return retval;
}
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
m48t59_write(NVRAM, addr, value & 0xff);
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
m48t59_write(NVRAM, addr, (value >> 8) & 0xff);
m48t59_write(NVRAM, addr + 1, value & 0xff);
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
m48t59_write(NVRAM, addr, (value >> 24) & 0xff);
m48t59_write(NVRAM, addr + 1, (value >> 16) & 0xff);
m48t59_write(NVRAM, addr + 2, (value >> 8) & 0xff);
m48t59_write(NVRAM, addr + 3, value & 0xff);
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->mem_base;
retval = m48t59_read(NVRAM, addr);
return retval;
}
static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->mem_base;
retval = m48t59_read(NVRAM, addr) << 8;
retval |= m48t59_read(NVRAM, addr + 1);
return retval;
}
static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->mem_base;
retval = m48t59_read(NVRAM, addr) << 24;
retval |= m48t59_read(NVRAM, addr + 1) << 16;
retval |= m48t59_read(NVRAM, addr + 2) << 8;
retval |= m48t59_read(NVRAM, addr + 3);
return retval;
}
static CPUWriteMemoryFunc *nvram_write[] = {
&nvram_writeb,
&nvram_writew,
&nvram_writel,
};
static CPUReadMemoryFunc *nvram_read[] = {
&nvram_readb,
&nvram_readw,
&nvram_readl,
};
/* Initialisation routine */
m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
uint32_t io_base, uint16_t size,
int type)
{
m48t59_t *s;
s = qemu_mallocz(sizeof(m48t59_t));
if (!s)
return NULL;
s->buffer = qemu_mallocz(size);
if (!s->buffer) {
qemu_free(s);
return NULL;
}
s->IRQ = IRQ;
s->size = size;
s->mem_base = mem_base;
s->io_base = io_base;
s->addr = 0;
s->type = type;
if (io_base != 0) {
register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
}
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
}
if (type == 59) {
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
}
s->lock = 0;
return s;
}

13
hw/m48t59.h Normal file
View File

@@ -0,0 +1,13 @@
#if !defined (__M48T59_H__)
#define __M48T59_H__
typedef struct m48t59_t m48t59_t;
void m48t59_write (m48t59_t *NVRAM, uint32_t addr, uint32_t val);
uint32_t m48t59_read (m48t59_t *NVRAM, uint32_t addr);
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
m48t59_t *m48t59_init (int IRQ, target_ulong mem_base,
uint32_t io_base, uint16_t size,
int type);
#endif /* !defined (__M48T59_H__) */

463
hw/mc146818rtc.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* QEMU MC146818 RTC emulation
*
* Copyright (c) 2003-2004 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"
//#define DEBUG_CMOS
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
#define RTC_MINUTES 2
#define RTC_MINUTES_ALARM 3
#define RTC_HOURS 4
#define RTC_HOURS_ALARM 5
#define RTC_ALARM_DONT_CARE 0xC0
#define RTC_DAY_OF_WEEK 6
#define RTC_DAY_OF_MONTH 7
#define RTC_MONTH 8
#define RTC_YEAR 9
#define RTC_REG_A 10
#define RTC_REG_B 11
#define RTC_REG_C 12
#define RTC_REG_D 13
#define REG_A_UIP 0x80
#define REG_B_SET 0x80
#define REG_B_PIE 0x40
#define REG_B_AIE 0x20
#define REG_B_UIE 0x10
struct RTCState {
uint8_t cmos_data[128];
uint8_t cmos_index;
struct tm current_tm;
int irq;
/* periodic timer */
QEMUTimer *periodic_timer;
int64_t next_periodic_time;
/* second update */
int64_t next_second_time;
QEMUTimer *second_timer;
QEMUTimer *second_timer2;
};
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
static void rtc_timer_update(RTCState *s, int64_t current_time)
{
int period_code, period;
int64_t cur_clock, next_irq_clock;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
if (period_code != 0 &&
(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
if (period_code <= 2)
period_code += 7;
/* period in 32 Khz cycles */
period = 1 << (period_code - 1);
/* compute 32 khz clock */
cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
next_irq_clock = (cur_clock & ~(period - 1)) + period;
s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
} else {
qemu_del_timer(s->periodic_timer);
}
}
static void rtc_periodic_timer(void *opaque)
{
RTCState *s = opaque;
rtc_timer_update(s, s->next_periodic_time);
s->cmos_data[RTC_REG_C] |= 0xc0;
pic_set_irq(s->irq, 1);
}
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
RTCState *s = opaque;
if ((addr & 1) == 0) {
s->cmos_index = data & 0x7f;
} else {
#ifdef DEBUG_CMOS
printf("cmos: write index=0x%02x val=0x%02x\n",
s->cmos_index, data);
#endif
switch(s->cmos_index) {
case RTC_SECONDS_ALARM:
case RTC_MINUTES_ALARM:
case RTC_HOURS_ALARM:
/* XXX: not supported */
s->cmos_data[s->cmos_index] = data;
break;
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
s->cmos_data[s->cmos_index] = data;
/* if in set mode, do not update the time */
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_set_time(s);
}
break;
case RTC_REG_A:
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_B:
if (data & REG_B_SET) {
/* set mode: reset UIP mode */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
data &= ~REG_B_UIE;
} else {
/* if disabling set mode, update the time */
if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
rtc_set_time(s);
}
}
s->cmos_data[RTC_REG_B] = data;
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_C:
case RTC_REG_D:
/* cannot write to them */
break;
default:
s->cmos_data[s->cmos_index] = data;
break;
}
}
}
static inline int to_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a / 10) << 4) | (a % 10);
}
}
static inline int from_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a >> 4) * 10) + (a & 0x0f);
}
}
static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
(s->cmos_data[RTC_HOURS] & 0x80)) {
tm->tm_hour += 12;
}
tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
}
static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
if (s->cmos_data[RTC_REG_B] & 0x02) {
/* 24 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
} else {
/* 12 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
if (tm->tm_hour >= 12)
s->cmos_data[RTC_HOURS] |= 0x80;
}
s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
}
/* month is between 0 and 11. */
static int get_days_in_month(int month, int year)
{
static const int days_tab[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int d;
if ((unsigned )month >= 12)
return 31;
d = days_tab[month];
if (month == 1) {
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
d++;
}
return d;
}
/* update 'tm' to the next second */
static void rtc_next_second(struct tm *tm)
{
int days_in_month;
tm->tm_sec++;
if ((unsigned)tm->tm_sec >= 60) {
tm->tm_sec = 0;
tm->tm_min++;
if ((unsigned)tm->tm_min >= 60) {
tm->tm_min = 0;
tm->tm_hour++;
if ((unsigned)tm->tm_hour >= 24) {
tm->tm_hour = 0;
/* next day */
tm->tm_wday++;
if ((unsigned)tm->tm_wday >= 7)
tm->tm_wday = 0;
days_in_month = get_days_in_month(tm->tm_mon,
tm->tm_year + 1900);
tm->tm_mday++;
if (tm->tm_mday < 1) {
tm->tm_mday = 1;
} else if (tm->tm_mday > days_in_month) {
tm->tm_mday = 1;
tm->tm_mon++;
if (tm->tm_mon >= 12) {
tm->tm_mon = 0;
tm->tm_year++;
}
}
}
}
}
}
static void rtc_update_second(void *opaque)
{
RTCState *s = opaque;
int64_t delay;
/* if the oscillator is not in normal operation, we do not update */
if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
} else {
rtc_next_second(&s->current_tm);
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
/* update in progress bit */
s->cmos_data[RTC_REG_A] |= REG_A_UIP;
}
/* should be 244 us = 8 / 32768 seconds, but currently the
timers do not have the necessary resolution. */
delay = (ticks_per_sec * 1) / 100;
if (delay < 1)
delay = 1;
qemu_mod_timer(s->second_timer2,
s->next_second_time + delay);
}
}
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_copy_date(s);
}
/* check alarm */
if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
pic_set_irq(s->irq, 1);
}
}
/* update ended interrupt */
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
s->cmos_data[RTC_REG_C] |= 0x90;
pic_set_irq(s->irq, 1);
}
/* clear update in progress bit */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
}
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
{
RTCState *s = opaque;
int ret;
if ((addr & 1) == 0) {
return 0xff;
} else {
switch(s->cmos_index) {
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_A:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
pic_set_irq(s->irq, 0);
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = s->cmos_data[s->cmos_index];
break;
}
#ifdef DEBUG_CMOS
printf("cmos: read index=0x%02x val=0x%02x\n",
s->cmos_index, ret);
#endif
return ret;
}
}
void rtc_set_memory(RTCState *s, int addr, int val)
{
if (addr >= 0 && addr <= 127)
s->cmos_data[addr] = val;
}
void rtc_set_date(RTCState *s, const struct tm *tm)
{
s->current_tm = *tm;
rtc_copy_date(s);
}
static void rtc_save(QEMUFile *f, void *opaque)
{
RTCState *s = opaque;
qemu_put_buffer(f, s->cmos_data, 128);
qemu_put_8s(f, &s->cmos_index);
qemu_put_be32s(f, &s->current_tm.tm_sec);
qemu_put_be32s(f, &s->current_tm.tm_min);
qemu_put_be32s(f, &s->current_tm.tm_hour);
qemu_put_be32s(f, &s->current_tm.tm_wday);
qemu_put_be32s(f, &s->current_tm.tm_mday);
qemu_put_be32s(f, &s->current_tm.tm_mon);
qemu_put_be32s(f, &s->current_tm.tm_year);
qemu_put_timer(f, s->periodic_timer);
qemu_put_be64s(f, &s->next_periodic_time);
qemu_put_be64s(f, &s->next_second_time);
qemu_put_timer(f, s->second_timer);
qemu_put_timer(f, s->second_timer2);
}
static int rtc_load(QEMUFile *f, void *opaque, int version_id)
{
RTCState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_buffer(f, s->cmos_data, 128);
qemu_get_8s(f, &s->cmos_index);
qemu_get_be32s(f, &s->current_tm.tm_sec);
qemu_get_be32s(f, &s->current_tm.tm_min);
qemu_get_be32s(f, &s->current_tm.tm_hour);
qemu_get_be32s(f, &s->current_tm.tm_wday);
qemu_get_be32s(f, &s->current_tm.tm_mday);
qemu_get_be32s(f, &s->current_tm.tm_mon);
qemu_get_be32s(f, &s->current_tm.tm_year);
qemu_get_timer(f, s->periodic_timer);
qemu_get_be64s(f, &s->next_periodic_time);
qemu_get_be64s(f, &s->next_second_time);
qemu_get_timer(f, s->second_timer);
qemu_get_timer(f, s->second_timer2);
return 0;
}
RTCState *rtc_init(int base, int irq)
{
RTCState *s;
s = qemu_mallocz(sizeof(RTCState));
if (!s)
return NULL;
s->irq = irq;
s->cmos_data[RTC_REG_A] = 0x26;
s->cmos_data[RTC_REG_B] = 0x02;
s->cmos_data[RTC_REG_C] = 0x00;
s->cmos_data[RTC_REG_D] = 0x80;
s->periodic_timer = qemu_new_timer(vm_clock,
rtc_periodic_timer, s);
s->second_timer = qemu_new_timer(vm_clock,
rtc_update_second, s);
s->second_timer2 = qemu_new_timer(vm_clock,
rtc_update_second2, s);
s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
register_ioport_write(base, 2, 1, cmos_ioport_write, s);
register_ioport_read(base, 2, 1, cmos_ioport_read, s);
register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
return s;
}

295
hw/mips_r4k.c Normal file
View File

@@ -0,0 +1,295 @@
#include "vl.h"
#define BIOS_FILENAME "mips_bios.bin"
//#define BIOS_FILENAME "system.bin"
#define KERNEL_LOAD_ADDR 0x80010000
#define INITRD_LOAD_ADDR 0x80800000
#define VIRT_TO_PHYS_ADDEND (-0x80000000LL)
extern FILE *logfile;
static PITState *pit;
static void pic_irq_request(void *opaque, int level)
{
CPUState *env = first_cpu;
if (level) {
env->CP0_Cause |= 0x00000400;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
} else {
env->CP0_Cause &= ~0x00000400;
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
}
void cpu_mips_irqctrl_init (void)
{
}
/* XXX: do not use a global */
uint32_t cpu_mips_get_random (CPUState *env)
{
static uint32_t seed = 0;
uint32_t idx;
seed = seed * 314159 + 1;
idx = (seed >> 16) % (MIPS_TLB_NB - env->CP0_Wired) + env->CP0_Wired;
return idx;
}
/* MIPS R4K timer */
uint32_t cpu_mips_get_count (CPUState *env)
{
return env->CP0_Count +
(uint32_t)muldiv64(qemu_get_clock(vm_clock),
100 * 1000 * 1000, ticks_per_sec);
}
static void cpu_mips_update_count (CPUState *env, uint32_t count,
uint32_t compare)
{
uint64_t now, next;
uint32_t tmp;
tmp = count;
if (count == compare)
tmp++;
now = qemu_get_clock(vm_clock);
next = now + muldiv64(compare - tmp, ticks_per_sec, 100 * 1000 * 1000);
if (next == now)
next++;
#if 0
if (logfile) {
fprintf(logfile, "%s: 0x%08llx %08x %08x => 0x%08llx\n",
__func__, now, count, compare, next - now);
}
#endif
/* Store new count and compare registers */
env->CP0_Compare = compare;
env->CP0_Count =
count - (uint32_t)muldiv64(now, 100 * 1000 * 1000, ticks_per_sec);
/* Adjust timer */
qemu_mod_timer(env->timer, next);
}
void cpu_mips_store_count (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, value, env->CP0_Compare);
}
void cpu_mips_store_compare (CPUState *env, uint32_t value)
{
cpu_mips_update_count(env, cpu_mips_get_count(env), value);
env->CP0_Cause &= ~0x00008000;
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
static void mips_timer_cb (void *opaque)
{
CPUState *env;
env = opaque;
#if 0
if (logfile) {
fprintf(logfile, "%s\n", __func__);
}
#endif
cpu_mips_update_count(env, cpu_mips_get_count(env), env->CP0_Compare);
env->CP0_Cause |= 0x00008000;
cpu_interrupt(env, CPU_INTERRUPT_HARD);
}
void cpu_mips_clock_init (CPUState *env)
{
env->timer = qemu_new_timer(vm_clock, &mips_timer_cb, env);
env->CP0_Compare = 0;
cpu_mips_update_count(env, 1, 0);
}
static void io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
cpu_outb(NULL, addr & 0xffff, value);
}
static uint32_t io_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inb(NULL, addr & 0xffff);
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
static void io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
cpu_outw(NULL, addr & 0xffff, value);
}
static uint32_t io_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inw(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap16(ret);
#endif
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
static void io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, value);
#endif
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
cpu_outl(NULL, addr & 0xffff, value);
}
static uint32_t io_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t ret = cpu_inl(NULL, addr & 0xffff);
#ifdef TARGET_WORDS_BIGENDIAN
ret = bswap32(ret);
#endif
#if 0
if (logfile)
fprintf(logfile, "%s: addr %08x val %08x\n", __func__, addr, ret);
#endif
return ret;
}
CPUWriteMemoryFunc *io_write[] = {
&io_writeb,
&io_writew,
&io_writel,
};
CPUReadMemoryFunc *io_read[] = {
&io_readb,
&io_readw,
&io_readl,
};
void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename)
{
char buf[1024];
int64_t entry = 0;
unsigned long bios_offset;
int io_memory;
int ret;
CPUState *env;
long kernel_size;
env = cpu_init();
register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* Try to load a BIOS image. If this fails, we continue regardless,
but initialize the hardware ourselves. When a kernel gets
preloaded we also initialize the hardware, since the BIOS wasn't
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",
buf);
}
kernel_size = 0;
if (kernel_filename) {
kernel_size = load_elf(kernel_filename, VIRT_TO_PHYS_ADDEND, &entry);
if (kernel_size >= 0)
env->PC = entry;
else {
kernel_size = load_image(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
env->PC = KERNEL_LOAD_ADDR;
}
/* load initrd */
if (initrd_filename) {
if (load_image(initrd_filename,
phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND)
== (target_ulong) -1) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
/* Store command line. */
strcpy (phys_ram_base + (16 << 20) - 256, kernel_cmdline);
/* FIXME: little endian support */
*(int *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678);
*(int *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size);
}
/* Init internal devices */
cpu_mips_clock_init(env);
cpu_mips_irqctrl_init();
/* Register 64 KB of ISA IO space at 0x14000000 */
io_memory = cpu_register_io_memory(0, io_read, io_write, NULL);
cpu_register_physical_memory(0x14000000, 0x00010000, io_memory);
isa_mem_base = 0x10000000;
isa_pic = pic_init(pic_irq_request, env);
pit = pit_init(0x40, 0);
serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);
vga_initialize(NULL, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
if (nd_table[0].vlan) {
if (nd_table[0].model == NULL
|| strcmp(nd_table[0].model, "ne2k_isa") == 0) {
isa_ne2000_init(0x300, 9, &nd_table[0]);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
exit (1);
}
}
}
QEMUMachine mips_machine = {
"mips",
"mips r4k platform",
mips_r4k_init,
};

816
hw/ne2000.c Normal file
View File

@@ -0,0 +1,816 @@
/*
* QEMU NE2000 emulation
*
* Copyright (c) 2003-2004 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"
/* debug NE2000 card */
//#define DEBUG_NE2000
#define MAX_ETH_FRAME_SIZE 1514
#define E8390_CMD 0x00 /* The command register (for all pages) */
/* Page 0 register offsets. */
#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
#define EN0_TSR 0x04 /* Transmit status reg RD */
#define EN0_TPSR 0x04 /* Transmit starting page WR */
#define EN0_NCR 0x05 /* Number of collision reg RD */
#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
#define EN0_FIFO 0x06 /* FIFO RD */
#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
#define EN0_RTL8029ID0 0x0a /* Realtek ID byte #1 RD */
#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
#define EN0_RTL8029ID1 0x0b /* Realtek ID byte #2 RD */
#define EN0_RSR 0x0c /* rx status reg RD */
#define EN0_RXCR 0x0c /* RX configuration reg WR */
#define EN0_TXCR 0x0d /* TX configuration reg WR */
#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
#define EN0_DCFG 0x0e /* Data configuration reg WR */
#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
#define EN0_IMR 0x0f /* Interrupt mask reg WR */
#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
#define EN1_PHYS 0x11
#define EN1_CURPAG 0x17
#define EN1_MULT 0x18
#define EN2_STARTPG 0x21 /* Starting page of ring bfr RD */
#define EN2_STOPPG 0x22 /* Ending page +1 of ring bfr RD */
#define EN3_CONFIG0 0x33
#define EN3_CONFIG1 0x34
#define EN3_CONFIG2 0x35
#define EN3_CONFIG3 0x36
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
#define E8390_TRANS 0x04 /* Transmit a frame */
#define E8390_RREAD 0x08 /* Remote read */
#define E8390_RWRITE 0x10 /* Remote write */
#define E8390_NODMA 0x20 /* Remote DMA */
#define E8390_PAGE0 0x00 /* Select page chip registers */
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
/* Bits in EN0_ISR - Interrupt status register */
#define ENISR_RX 0x01 /* Receiver, no error */
#define ENISR_TX 0x02 /* Transmitter, no error */
#define ENISR_RX_ERR 0x04 /* Receiver, with error */
#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
#define ENISR_COUNTERS 0x20 /* Counters need emptying */
#define ENISR_RDC 0x40 /* remote dma complete */
#define ENISR_RESET 0x80 /* Reset completed */
#define ENISR_ALL 0x3f /* Interrupts we will enable */
/* Bits in received packet status byte and EN0_RSR*/
#define ENRSR_RXOK 0x01 /* Received a good packet */
#define ENRSR_CRC 0x02 /* CRC error */
#define ENRSR_FAE 0x04 /* frame alignment error */
#define ENRSR_FO 0x08 /* FIFO overrun */
#define ENRSR_MPA 0x10 /* missed pkt */
#define ENRSR_PHY 0x20 /* physical/multicast address */
#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
#define ENRSR_DEF 0x80 /* deferring */
/* Transmitted packet status, EN0_TSR. */
#define ENTSR_PTX 0x01 /* Packet transmitted without error */
#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
#define ENTSR_COL 0x04 /* The transmit collided at least once. */
#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
#define NE2000_PMEM_SIZE (32*1024)
#define NE2000_PMEM_START (16*1024)
#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START)
#define NE2000_MEM_SIZE NE2000_PMEM_END
typedef struct NE2000State {
uint8_t cmd;
uint32_t start;
uint32_t stop;
uint8_t boundary;
uint8_t tsr;
uint8_t tpsr;
uint16_t tcnt;
uint16_t rcnt;
uint32_t rsar;
uint8_t rsr;
uint8_t rxcr;
uint8_t isr;
uint8_t dcfg;
uint8_t imr;
uint8_t phys[6]; /* mac address */
uint8_t curpag;
uint8_t mult[8]; /* multicast mask array */
int irq;
PCIDevice *pci_dev;
VLANClientState *vc;
uint8_t macaddr[6];
uint8_t mem[NE2000_MEM_SIZE];
} NE2000State;
static void ne2000_reset(NE2000State *s)
{
int i;
s->isr = ENISR_RESET;
memcpy(s->mem, s->macaddr, 6);
s->mem[14] = 0x57;
s->mem[15] = 0x57;
/* duplicate prom data */
for(i = 15;i >= 0; i--) {
s->mem[2 * i] = s->mem[i];
s->mem[2 * i + 1] = s->mem[i];
}
}
static void ne2000_update_irq(NE2000State *s)
{
int isr;
isr = (s->isr & s->imr) & 0x7f;
#if defined(DEBUG_NE2000)
printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
s->irq, isr ? 1 : 0, s->isr, s->imr);
#endif
if (s->irq == 16) {
/* PCI irq */
pci_set_irq(s->pci_dev, 0, (isr != 0));
} else {
/* ISA irq */
pic_set_irq(s->irq, (isr != 0));
}
}
#define POLYNOMIAL 0x04c11db6
/* From FreeBSD */
/* XXX: optimize */
static int compute_mcast_idx(const uint8_t *ep)
{
uint32_t crc;
int carry, i, j;
uint8_t b;
crc = 0xffffffff;
for (i = 0; i < 6; i++) {
b = *ep++;
for (j = 0; j < 8; j++) {
carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
crc <<= 1;
b >>= 1;
if (carry)
crc = ((crc ^ POLYNOMIAL) | carry);
}
}
return (crc >> 26);
}
static int ne2000_buffer_full(NE2000State *s)
{
int avail, index, boundary;
index = s->curpag << 8;
boundary = s->boundary << 8;
if (index < boundary)
avail = boundary - index;
else
avail = (s->stop - s->start) - (index - boundary);
if (avail < (MAX_ETH_FRAME_SIZE + 4))
return 1;
return 0;
}
static int ne2000_can_receive(void *opaque)
{
NE2000State *s = opaque;
if (s->cmd & E8390_STOP)
return 1;
return !ne2000_buffer_full(s);
}
#define MIN_BUF_SIZE 60
static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
{
NE2000State *s = opaque;
uint8_t *p;
int total_len, next, avail, len, index, mcast_idx;
uint8_t buf1[60];
static const uint8_t broadcast_macaddr[6] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#if defined(DEBUG_NE2000)
printf("NE2000: received len=%d\n", size);
#endif
if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
return;
/* XXX: check this */
if (s->rxcr & 0x10) {
/* promiscuous: receive all */
} else {
if (!memcmp(buf, broadcast_macaddr, 6)) {
/* broadcast address */
if (!(s->rxcr & 0x04))
return;
} else if (buf[0] & 0x01) {
/* multicast */
if (!(s->rxcr & 0x08))
return;
mcast_idx = compute_mcast_idx(buf);
if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))))
return;
} else if (s->mem[0] == buf[0] &&
s->mem[2] == buf[1] &&
s->mem[4] == buf[2] &&
s->mem[6] == buf[3] &&
s->mem[8] == buf[4] &&
s->mem[10] == buf[5]) {
/* match */
} else {
return;
}
}
/* if too small buffer, then expand it */
if (size < MIN_BUF_SIZE) {
memcpy(buf1, buf, size);
memset(buf1 + size, 0, MIN_BUF_SIZE - size);
buf = buf1;
size = MIN_BUF_SIZE;
}
index = s->curpag << 8;
/* 4 bytes for header */
total_len = size + 4;
/* address for next packet (4 bytes for CRC) */
next = index + ((total_len + 4 + 255) & ~0xff);
if (next >= s->stop)
next -= (s->stop - s->start);
/* prepare packet header */
p = s->mem + index;
s->rsr = ENRSR_RXOK; /* receive status */
/* XXX: check this */
if (buf[0] & 0x01)
s->rsr |= ENRSR_PHY;
p[0] = s->rsr;
p[1] = next >> 8;
p[2] = total_len;
p[3] = total_len >> 8;
index += 4;
/* write packet data */
while (size > 0) {
avail = s->stop - index;
len = size;
if (len > avail)
len = avail;
memcpy(s->mem + index, buf, len);
buf += len;
index += len;
if (index == s->stop)
index = s->start;
size -= len;
}
s->curpag = next >> 8;
/* now we can signal we have receive something */
s->isr |= ENISR_RX;
ne2000_update_irq(s);
}
static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
int offset, page, index;
addr &= 0xf;
#ifdef DEBUG_NE2000
printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
#endif
if (addr == E8390_CMD) {
/* control register */
s->cmd = val;
if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
s->isr &= ~ENISR_RESET;
/* test specific case: zero length transfert */
if ((val & (E8390_RREAD | E8390_RWRITE)) &&
s->rcnt == 0) {
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
}
if (val & E8390_TRANS) {
index = (s->tpsr << 8);
/* XXX: next 2 lines are a hack to make netware 3.11 work */
if (index >= NE2000_PMEM_END)
index -= NE2000_PMEM_SIZE;
/* fail safe: check range on the transmitted length */
if (index + s->tcnt <= NE2000_PMEM_END) {
qemu_send_packet(s->vc, s->mem + index, s->tcnt);
}
/* signal end of transfert */
s->tsr = ENTSR_PTX;
s->isr |= ENISR_TX;
s->cmd &= ~E8390_TRANS;
ne2000_update_irq(s);
}
}
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_STARTPG:
s->start = val << 8;
break;
case EN0_STOPPG:
s->stop = val << 8;
break;
case EN0_BOUNDARY:
s->boundary = val;
break;
case EN0_IMR:
s->imr = val;
ne2000_update_irq(s);
break;
case EN0_TPSR:
s->tpsr = val;
break;
case EN0_TCNTLO:
s->tcnt = (s->tcnt & 0xff00) | val;
break;
case EN0_TCNTHI:
s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
break;
case EN0_RSARLO:
s->rsar = (s->rsar & 0xff00) | val;
break;
case EN0_RSARHI:
s->rsar = (s->rsar & 0x00ff) | (val << 8);
break;
case EN0_RCNTLO:
s->rcnt = (s->rcnt & 0xff00) | val;
break;
case EN0_RCNTHI:
s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
break;
case EN0_RXCR:
s->rxcr = val;
break;
case EN0_DCFG:
s->dcfg = val;
break;
case EN0_ISR:
s->isr &= ~(val & 0x7f);
ne2000_update_irq(s);
break;
case EN1_PHYS ... EN1_PHYS + 5:
s->phys[offset - EN1_PHYS] = val;
break;
case EN1_CURPAG:
s->curpag = val;
break;
case EN1_MULT ... EN1_MULT + 7:
s->mult[offset - EN1_MULT] = val;
break;
}
}
}
static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int offset, page, ret;
addr &= 0xf;
if (addr == E8390_CMD) {
ret = s->cmd;
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_TSR:
ret = s->tsr;
break;
case EN0_BOUNDARY:
ret = s->boundary;
break;
case EN0_ISR:
ret = s->isr;
break;
case EN0_RSARLO:
ret = s->rsar & 0x00ff;
break;
case EN0_RSARHI:
ret = s->rsar >> 8;
break;
case EN1_PHYS ... EN1_PHYS + 5:
ret = s->phys[offset - EN1_PHYS];
break;
case EN1_CURPAG:
ret = s->curpag;
break;
case EN1_MULT ... EN1_MULT + 7:
ret = s->mult[offset - EN1_MULT];
break;
case EN0_RSR:
ret = s->rsr;
break;
case EN2_STARTPG:
ret = s->start >> 8;
break;
case EN2_STOPPG:
ret = s->stop >> 8;
break;
case EN0_RTL8029ID0:
ret = 0x50;
break;
case EN0_RTL8029ID1:
ret = 0x43;
break;
case EN3_CONFIG0:
ret = 0; /* 10baseT media */
break;
case EN3_CONFIG2:
ret = 0x40; /* 10baseT active */
break;
case EN3_CONFIG3:
ret = 0x40; /* Full duplex */
break;
default:
ret = 0x00;
break;
}
}
#ifdef DEBUG_NE2000
printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
#endif
return ret;
}
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
uint32_t val)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
s->mem[addr] = val;
}
}
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
*(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
}
}
static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
}
}
static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return s->mem[addr];
} else {
return 0xff;
}
}
static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le16_to_cpu(*(uint16_t *)(s->mem + addr));
} else {
return 0xffff;
}
}
static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le32_to_cpupu((uint32_t *)(s->mem + addr));
} else {
return 0xffffffff;
}
}
static inline void ne2000_dma_update(NE2000State *s, int len)
{
s->rsar += len;
/* wrap */
/* XXX: check what to do if rsar > stop */
if (s->rsar == s->stop)
s->rsar = s->start;
if (s->rcnt <= len) {
s->rcnt = 0;
/* signal end of transfert */
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
} else {
s->rcnt -= len;
}
}
static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic write val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
if (s->dcfg & 0x01) {
/* 16 bit access */
ne2000_mem_writew(s, s->rsar, val);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ne2000_mem_writeb(s, s->rsar, val);
ne2000_dma_update(s, 1);
}
}
static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
if (s->dcfg & 0x01) {
/* 16 bit access */
ret = ne2000_mem_readw(s, s->rsar);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ret = ne2000_mem_readb(s, s->rsar);
ne2000_dma_update(s, 1);
}
#ifdef DEBUG_NE2000
printf("NE2000: asic read val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic writel val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
/* 32 bit access */
ne2000_mem_writel(s, s->rsar, val);
ne2000_dma_update(s, 4);
}
static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
/* 32 bit access */
ret = ne2000_mem_readl(s, s->rsar);
ne2000_dma_update(s, 4);
#ifdef DEBUG_NE2000
printf("NE2000: asic readl val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
/* nothing to do (end of reset pulse) */
}
static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
ne2000_reset(s);
return 0;
}
static void ne2000_save(QEMUFile* f,void* opaque)
{
NE2000State* s=(NE2000State*)opaque;
qemu_put_8s(f, &s->rxcr);
qemu_put_8s(f, &s->cmd);
qemu_put_be32s(f, &s->start);
qemu_put_be32s(f, &s->stop);
qemu_put_8s(f, &s->boundary);
qemu_put_8s(f, &s->tsr);
qemu_put_8s(f, &s->tpsr);
qemu_put_be16s(f, &s->tcnt);
qemu_put_be16s(f, &s->rcnt);
qemu_put_be32s(f, &s->rsar);
qemu_put_8s(f, &s->rsr);
qemu_put_8s(f, &s->isr);
qemu_put_8s(f, &s->dcfg);
qemu_put_8s(f, &s->imr);
qemu_put_buffer(f, s->phys, 6);
qemu_put_8s(f, &s->curpag);
qemu_put_buffer(f, s->mult, 8);
qemu_put_be32s(f, &s->irq);
qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
}
static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
{
NE2000State* s=(NE2000State*)opaque;
if (version_id == 2) {
qemu_get_8s(f, &s->rxcr);
} else if (version_id == 1) {
s->rxcr = 0x0c;
} else {
return -EINVAL;
}
qemu_get_8s(f, &s->cmd);
qemu_get_be32s(f, &s->start);
qemu_get_be32s(f, &s->stop);
qemu_get_8s(f, &s->boundary);
qemu_get_8s(f, &s->tsr);
qemu_get_8s(f, &s->tpsr);
qemu_get_be16s(f, &s->tcnt);
qemu_get_be16s(f, &s->rcnt);
qemu_get_be32s(f, &s->rsar);
qemu_get_8s(f, &s->rsr);
qemu_get_8s(f, &s->isr);
qemu_get_8s(f, &s->dcfg);
qemu_get_8s(f, &s->imr);
qemu_get_buffer(f, s->phys, 6);
qemu_get_8s(f, &s->curpag);
qemu_get_buffer(f, s->mult, 8);
qemu_get_be32s(f, &s->irq);
qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
return 0;
}
void isa_ne2000_init(int base, int irq, NICInfo *nd)
{
NE2000State *s;
s = qemu_mallocz(sizeof(NE2000State));
if (!s)
return;
register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
s->irq = irq;
memcpy(s->macaddr, nd->macaddr, 6);
ne2000_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
ne2000_can_receive, s);
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
s->macaddr[0],
s->macaddr[1],
s->macaddr[2],
s->macaddr[3],
s->macaddr[4],
s->macaddr[5]);
register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
}
/***********************************************************/
/* PCI NE2000 definitions */
typedef struct PCINE2000State {
PCIDevice dev;
NE2000State ne2000;
} PCINE2000State;
static void ne2000_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
PCINE2000State *d = (PCINE2000State *)pci_dev;
NE2000State *s = &d->ne2000;
register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
{
PCINE2000State *d;
NE2000State *s;
uint8_t *pci_conf;
d = (PCINE2000State *)pci_register_device(bus,
"NE2000", sizeof(PCINE2000State),
-1,
NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = 0xec; // Realtek 8029
pci_conf[0x01] = 0x10;
pci_conf[0x02] = 0x29;
pci_conf[0x03] = 0x80;
pci_conf[0x0a] = 0x00; // ethernet network controller
pci_conf[0x0b] = 0x02;
pci_conf[0x0e] = 0x00; // header_type
pci_conf[0x3d] = 1; // interrupt pin 0
pci_register_io_region(&d->dev, 0, 0x100,
PCI_ADDRESS_SPACE_IO, ne2000_map);
s = &d->ne2000;
s->irq = 16; // PCI interrupt
s->pci_dev = (PCIDevice *)d;
memcpy(s->macaddr, nd->macaddr, 6);
ne2000_reset(s);
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
ne2000_can_receive, s);
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
"ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
s->macaddr[0],
s->macaddr[1],
s->macaddr[2],
s->macaddr[3],
s->macaddr[4],
s->macaddr[5]);
/* XXX: instance number ? */
register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s);
register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
&d->dev);
}

1027
hw/openpic.c Normal file

File diff suppressed because it is too large Load Diff

183
hw/parallel.c Normal file
View File

@@ -0,0 +1,183 @@
/*
* QEMU Parallel PORT emulation
*
* Copyright (c) 2003-2005 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"
//#define DEBUG_PARALLEL
/*
* These are the definitions for the Printer Status Register
*/
#define PARA_STS_BUSY 0x80 /* Busy complement */
#define PARA_STS_ACK 0x40 /* Acknowledge */
#define PARA_STS_PAPER 0x20 /* Out of paper */
#define PARA_STS_ONLINE 0x10 /* Online */
#define PARA_STS_ERROR 0x08 /* Error complement */
/*
* These are the definitions for the Printer Control Register
*/
#define PARA_CTR_INTEN 0x10 /* IRQ Enable */
#define PARA_CTR_SELECT 0x08 /* Select In complement */
#define PARA_CTR_INIT 0x04 /* Initialize Printer complement */
#define PARA_CTR_AUTOLF 0x02 /* Auto linefeed complement */
#define PARA_CTR_STROBE 0x01 /* Strobe complement */
struct ParallelState {
uint8_t data;
uint8_t status; /* read only register */
uint8_t control;
int irq;
int irq_pending;
CharDriverState *chr;
int hw_driver;
};
static void parallel_update_irq(ParallelState *s)
{
if (s->irq_pending)
pic_set_irq(s->irq, 1);
else
pic_set_irq(s->irq, 0);
}
static void parallel_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
ParallelState *s = opaque;
addr &= 7;
#ifdef DEBUG_PARALLEL
printf("parallel: write addr=0x%02x val=0x%02x\n", addr, val);
#endif
switch(addr) {
case 0:
if (s->hw_driver) {
s->data = val;
qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &s->data);
} else {
s->data = val;
parallel_update_irq(s);
}
break;
case 2:
if (s->hw_driver) {
s->control = val;
qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &s->control);
} else {
if ((val & PARA_CTR_INIT) == 0 ) {
s->status = PARA_STS_BUSY;
s->status |= PARA_STS_ACK;
s->status |= PARA_STS_ONLINE;
s->status |= PARA_STS_ERROR;
}
else if (val & PARA_CTR_SELECT) {
if (val & PARA_CTR_STROBE) {
s->status &= ~PARA_STS_BUSY;
if ((s->control & PARA_CTR_STROBE) == 0)
qemu_chr_write(s->chr, &s->data, 1);
} else {
if (s->control & PARA_CTR_INTEN) {
s->irq_pending = 1;
}
}
}
parallel_update_irq(s);
s->control = val;
}
break;
}
}
static uint32_t parallel_ioport_read(void *opaque, uint32_t addr)
{
ParallelState *s = opaque;
uint32_t ret = 0xff;
addr &= 7;
switch(addr) {
case 0:
if (s->hw_driver) {
qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &s->data);
}
ret = s->data;
break;
case 1:
if (s->hw_driver) {
qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &s->status);
ret = s->status;
} else {
ret = s->status;
s->irq_pending = 0;
if ((s->status & PARA_STS_BUSY) == 0 && (s->control & PARA_CTR_STROBE) == 0) {
/* XXX Fixme: wait 5 microseconds */
if (s->status & PARA_STS_ACK)
s->status &= ~PARA_STS_ACK;
else {
/* XXX Fixme: wait 5 microseconds */
s->status |= PARA_STS_ACK;
s->status |= PARA_STS_BUSY;
}
}
parallel_update_irq(s);
}
break;
case 2:
if (s->hw_driver) {
qemu_chr_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &s->control);
}
ret = s->control;
break;
}
#ifdef DEBUG_PARALLEL
printf("parallel: read addr=0x%02x val=0x%02x\n", addr, ret);
#endif
return ret;
}
/* If fd is zero, it means that the parallel device uses the console */
ParallelState *parallel_init(int base, int irq, CharDriverState *chr)
{
ParallelState *s;
uint8_t dummy;
s = qemu_mallocz(sizeof(ParallelState));
if (!s)
return NULL;
s->chr = chr;
s->hw_driver = 0;
if (qemu_chr_ioctl(chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0)
s->hw_driver = 1;
s->irq = irq;
s->data = 0;
s->status = PARA_STS_BUSY;
s->status |= PARA_STS_ACK;
s->status |= PARA_STS_ONLINE;
s->status |= PARA_STS_ERROR;
s->control = PARA_CTR_SELECT;
s->control |= PARA_CTR_INIT;
register_ioport_write(base, 8, 1, parallel_ioport_write, s);
register_ioport_read(base, 8, 1, parallel_ioport_read, s);
return s;
}

882
hw/pc.c Normal file
View File

@@ -0,0 +1,882 @@
/*
* QEMU PC System Emulator
*
* Copyright (c) 2003-2004 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"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
#define BIOS_FILENAME "bios.bin"
#define VGABIOS_FILENAME "vgabios.bin"
#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
#define LINUX_BOOT_FILENAME "linux_boot.bin"
#define KERNEL_LOAD_ADDR 0x00100000
#define INITRD_LOAD_ADDR 0x00600000
#define KERNEL_PARAMS_ADDR 0x00090000
#define KERNEL_CMDLINE_ADDR 0x00099000
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)
{
}
/* MSDOS compatibility mode FPU exception support */
/* XXX: add IGNNE support */
void cpu_set_ferr(CPUX86State *s)
{
pic_set_irq(13, 1);
}
static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
{
pic_set_irq(13, 0);
}
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return qemu_get_clock(vm_clock);
}
/* IRQ handling */
int cpu_get_pic_interrupt(CPUState *env)
{
int intno;
intno = apic_get_interrupt(env);
if (intno >= 0) {
/* set irq request if a PIC irq is still pending */
/* XXX: improve that */
pic_update_irq(isa_pic);
return intno;
}
/* read the irq from the PIC */
intno = pic_read_irq(isa_pic);
return intno;
}
static void pic_irq_request(void *opaque, int level)
{
CPUState *env = opaque;
if (level)
cpu_interrupt(env, CPU_INTERRUPT_HARD);
else
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
/* PC cmos mappings */
#define REG_EQUIPMENT_BYTE 0x14
#define REG_IBM_CENTURY_BYTE 0x32
#define REG_IBM_PS2_CENTURY_BYTE 0x37
static inline int to_bcd(RTCState *s, int a)
{
return ((a / 10) << 4) | (a % 10);
}
static int cmos_get_fd_drive_type(int fd0)
{
int val;
switch (fd0) {
case 0:
/* 1.44 Mb 3"5 drive */
val = 4;
break;
case 1:
/* 2.88 Mb 3"5 drive */
val = 5;
break;
case 2:
/* 1.2 Mb 5"5 drive */
val = 2;
break;
default:
val = 0;
break;
}
return val;
}
static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
{
RTCState *s = rtc_state;
int cylinders, heads, sectors;
bdrv_get_geometry_hint(hd, &cylinders, &heads, &sectors);
rtc_set_memory(s, type_ofs, 47);
rtc_set_memory(s, info_ofs, cylinders);
rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
rtc_set_memory(s, info_ofs + 2, heads);
rtc_set_memory(s, info_ofs + 3, 0xff);
rtc_set_memory(s, info_ofs + 4, 0xff);
rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
rtc_set_memory(s, info_ofs + 6, cylinders);
rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
rtc_set_memory(s, info_ofs + 8, sectors);
}
/* hd_table must contain 4 block drivers */
static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
{
RTCState *s = rtc_state;
int val;
int fd0, fd1, nb;
time_t ti;
struct tm *tm;
int i;
/* set the CMOS date */
time(&ti);
if (rtc_utc)
tm = gmtime(&ti);
else
tm = localtime(&ti);
rtc_set_date(s, tm);
val = to_bcd(s, (tm->tm_year / 100) + 19);
rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
/* various important CMOS locations needed by PC/Bochs bios */
/* memory size */
val = 640; /* base memory in K */
rtc_set_memory(s, 0x15, val);
rtc_set_memory(s, 0x16, val >> 8);
val = (ram_size / 1024) - 1024;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x17, val);
rtc_set_memory(s, 0x18, val >> 8);
rtc_set_memory(s, 0x30, val);
rtc_set_memory(s, 0x31, val >> 8);
if (ram_size > (16 * 1024 * 1024))
val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
else
val = 0;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x34, val);
rtc_set_memory(s, 0x35, val >> 8);
switch(boot_device) {
case 'a':
case 'b':
rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
break;
default:
case 'c':
rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
break;
case 'd':
rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
break;
}
/* floppy type */
fd0 = fdctrl_get_drive_type(floppy_controller, 0);
fd1 = fdctrl_get_drive_type(floppy_controller, 1);
val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
rtc_set_memory(s, 0x10, val);
val = 0;
nb = 0;
if (fd0 < 3)
nb++;
if (fd1 < 3)
nb++;
switch (nb) {
case 0:
break;
case 1:
val |= 0x01; /* 1 drive, ready for boot */
break;
case 2:
val |= 0x41; /* 2 drives, ready for boot */
break;
}
val |= 0x02; /* FPU is there */
val |= 0x04; /* PS/2 mouse installed */
rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
/* hard drives */
rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
if (hd_table[0])
cmos_init_hd(0x19, 0x1b, hd_table[0]);
if (hd_table[1])
cmos_init_hd(0x1a, 0x24, hd_table[1]);
val = 0;
for (i = 0; i < 4; i++) {
if (hd_table[i]) {
int cylinders, heads, sectors, translation;
/* NOTE: bdrv_get_geometry_hint() returns the physical
geometry. It is always such that: 1 <= sects <= 63, 1
<= heads <= 16, 1 <= cylinders <= 16383. The BIOS
geometry can be different if a translation is done. */
translation = bdrv_get_translation_hint(hd_table[i]);
if (translation == BIOS_ATA_TRANSLATION_AUTO) {
bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
/* No translation. */
translation = 0;
} else {
/* LBA translation. */
translation = 1;
}
} else {
translation--;
}
val |= translation << (i * 2);
}
}
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)
{
/* XXX: send to all CPUs ? */
cpu_x86_set_a20(first_cpu, enable);
}
int ioport_get_a20(void)
{
return ((first_cpu->a20_mask >> 20) & 1);
}
static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
{
ioport_set_a20((val >> 1) & 1);
/* XXX: bit 0 is fast reset */
}
static uint32_t ioport92_read(void *opaque, uint32_t addr)
{
return ioport_get_a20() << 1;
}
/***********************************************************/
/* Bochs BIOS debug ports */
void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
{
static const char shutdown_str[8] = "Shutdown";
static int shutdown_index = 0;
switch(addr) {
/* Bochs BIOS messages */
case 0x400:
case 0x401:
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
exit(1);
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
case 0x8900:
/* same as Bochs power off */
if (val == shutdown_str[shutdown_index]) {
shutdown_index++;
if (shutdown_index == 8) {
shutdown_index = 0;
qemu_system_shutdown_request();
}
} else {
shutdown_index = 0;
}
break;
/* LGPL'ed VGA BIOS messages */
case 0x501:
case 0x502:
fprintf(stderr, "VGA BIOS panic, line %d\n", val);
exit(1);
case 0x500:
case 0x503:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
}
}
void bochs_bios_init(void)
{
register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
}
int load_kernel(const char *filename, uint8_t *addr,
uint8_t *real_addr)
{
int fd, size;
int setup_sects;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
/* load 16 bit code */
if (read(fd, real_addr, 512) != 512)
goto fail;
setup_sects = real_addr[0x1F1];
if (!setup_sects)
setup_sects = 4;
if (read(fd, real_addr + 512, setup_sects * 512) !=
setup_sects * 512)
goto fail;
/* load 32 bit code */
size = read(fd, addr, 16 * 1024 * 1024);
if (size < 0)
goto fail;
close(fd);
return size;
fail:
close(fd);
return -1;
}
static void main_cpu_reset(void *opaque)
{
CPUState *env = opaque;
cpu_reset(env);
}
/*************************************************/
static void putb(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*pp = q;
}
static void putstr(uint8_t **pp, const char *str)
{
uint8_t *q;
q = *pp;
while (*str)
*q++ = *str++;
*pp = q;
}
static void putle16(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*q++ = val >> 8;
*pp = q;
}
static void putle32(uint8_t **pp, int val)
{
uint8_t *q;
q = *pp;
*q++ = val;
*q++ = val >> 8;
*q++ = val >> 16;
*q++ = val >> 24;
*pp = q;
}
static int mpf_checksum(const uint8_t *data, int len)
{
int sum, i;
sum = 0;
for(i = 0; i < len; i++)
sum += data[i];
return sum & 0xff;
}
/* Build the Multi Processor table in the BIOS. Same values as Bochs. */
static void bios_add_mptable(uint8_t *bios_data)
{
uint8_t *mp_config_table, *q, *float_pointer_struct;
int ioapic_id, offset, i, len;
if (smp_cpus <= 1)
return;
mp_config_table = bios_data + 0xb000;
q = mp_config_table;
putstr(&q, "PCMP"); /* "PCMP signature */
putle16(&q, 0); /* table length (patched later) */
putb(&q, 4); /* spec rev */
putb(&q, 0); /* checksum (patched later) */
putstr(&q, "QEMUCPU "); /* OEM id */
putstr(&q, "0.1 "); /* vendor id */
putle32(&q, 0); /* OEM table ptr */
putle16(&q, 0); /* OEM table size */
putle16(&q, 20); /* entry count */
putle32(&q, 0xfee00000); /* local APIC addr */
putle16(&q, 0); /* ext table length */
putb(&q, 0); /* ext table checksum */
putb(&q, 0); /* reserved */
for(i = 0; i < smp_cpus; i++) {
putb(&q, 0); /* entry type = processor */
putb(&q, i); /* APIC id */
putb(&q, 0x11); /* local APIC version number */
if (i == 0)
putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */
else
putb(&q, 1); /* cpu flags: enabled */
putb(&q, 0); /* cpu signature */
putb(&q, 6);
putb(&q, 0);
putb(&q, 0);
putle16(&q, 0x201); /* feature flags */
putle16(&q, 0);
putle16(&q, 0); /* reserved */
putle16(&q, 0);
putle16(&q, 0);
putle16(&q, 0);
}
/* isa bus */
putb(&q, 1); /* entry type = bus */
putb(&q, 0); /* bus ID */
putstr(&q, "ISA ");
/* ioapic */
ioapic_id = smp_cpus;
putb(&q, 2); /* entry type = I/O APIC */
putb(&q, ioapic_id); /* apic ID */
putb(&q, 0x11); /* I/O APIC version number */
putb(&q, 1); /* enable */
putle32(&q, 0xfec00000); /* I/O APIC addr */
/* irqs */
for(i = 0; i < 16; i++) {
putb(&q, 3); /* entry type = I/O interrupt */
putb(&q, 0); /* interrupt type = vectored interrupt */
putb(&q, 0); /* flags: po=0, el=0 */
putb(&q, 0);
putb(&q, 0); /* source bus ID = ISA */
putb(&q, i); /* source bus IRQ */
putb(&q, ioapic_id); /* dest I/O APIC ID */
putb(&q, i); /* dest I/O APIC interrupt in */
}
/* patch length */
len = q - mp_config_table;
mp_config_table[4] = len;
mp_config_table[5] = len >> 8;
mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table);
/* align to 16 */
offset = q - bios_data;
offset = (offset + 15) & ~15;
float_pointer_struct = bios_data + offset;
/* floating pointer structure */
q = float_pointer_struct;
putstr(&q, "_MP_");
/* pointer to MP config table */
putle32(&q, mp_config_table - bios_data + 0x000f0000);
putb(&q, 1); /* length in 16 byte units */
putb(&q, 4); /* MP spec revision */
putb(&q, 0); /* checksum (patched later) */
putb(&q, 0); /* MP feature byte 1 */
putb(&q, 0);
putb(&q, 0);
putb(&q, 0);
putb(&q, 0);
float_pointer_struct[10] =
-mpf_checksum(float_pointer_struct, q - float_pointer_struct);
}
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
#define NE2000_NB_MAX 6
static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
#ifdef HAS_AUDIO
static void audio_init (PCIBus *pci_bus)
{
struct soundhw *c;
int audio_enabled = 0;
for (c = soundhw; !audio_enabled && c->name; ++c) {
audio_enabled = c->enabled;
}
if (audio_enabled) {
AudioState *s;
s = AUD_init ();
if (s) {
for (c = soundhw; c->name; ++c) {
if (c->enabled) {
if (c->isa) {
c->init.init_isa (s);
}
else {
if (pci_bus) {
c->init.init_pci (pci_bus, s);
}
}
}
}
}
}
}
#endif
static void pc_init_ne2k_isa(NICInfo *nd)
{
static int nb_ne2k = 0;
if (nb_ne2k == NE2000_NB_MAX)
return;
isa_ne2000_init(ne2000_io[nb_ne2k], ne2000_irq[nb_ne2k], nd);
nb_ne2k++;
}
/* PC hardware initialisation */
static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
const char *kernel_filename, const char *kernel_cmdline,
const char *initrd_filename,
int pci_enabled)
{
char buf[1024];
int ret, linux_boot, initrd_size, i;
unsigned long bios_offset, vga_bios_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
CPUState *env;
NICInfo *nd;
linux_boot = (kernel_filename != NULL);
/* init CPUs */
for(i = 0; i < smp_cpus; i++) {
env = cpu_init();
if (i != 0)
env->hflags |= HF_HALTED_MASK;
if (smp_cpus > 1) {
/* XXX: enable it in all cases */
env->cpuid_features |= CPUID_APIC;
}
register_savevm("cpu", i, 3, cpu_save, cpu_load, env);
qemu_register_reset(main_cpu_reset, env);
if (pci_enabled) {
apic_init(env);
}
}
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, 0);
/* BIOS load */
bios_offset = ram_size + vga_ram_size;
vga_bios_offset = bios_offset + 256 * 1024;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
bios_size = get_image_size(buf);
if (bios_size <= 0 ||
(bios_size % 65536) != 0 ||
bios_size > (256 * 1024)) {
goto bios_error;
}
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != bios_size) {
bios_error:
fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
exit(1);
}
if (bios_size == 65536) {
bios_add_mptable(phys_ram_base + bios_offset);
}
/* VGA BIOS load */
if (cirrus_vga_enabled) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
} else {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
}
ret = load_image(buf, phys_ram_base + vga_bios_offset);
/* setup basic memory access */
cpu_register_physical_memory(0xc0000, 0x10000,
vga_bios_offset | IO_MEM_ROM);
/* map the last 128KB of the BIOS in ISA space */
isa_bios_size = bios_size;
if (isa_bios_size > (128 * 1024))
isa_bios_size = 128 * 1024;
cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
IO_MEM_UNASSIGNED);
cpu_register_physical_memory(0x100000 - isa_bios_size,
isa_bios_size,
(bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
/* map all the bios at the top of memory */
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
bochs_bios_init();
if (linux_boot) {
uint8_t bootsect[512];
uint8_t old_bootsect[512];
if (bs_table[0] == NULL) {
fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
exit(1);
}
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
ret = load_image(buf, bootsect);
if (ret != sizeof(bootsect)) {
fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
buf);
exit(1);
}
if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
/* copy the MSDOS partition table */
memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
}
bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
/* now we can load the kernel */
ret = load_kernel(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR,
phys_ram_base + KERNEL_PARAMS_ADDR);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
initrd_size = 0;
if (initrd_filename) {
initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
if (initrd_size > 0) {
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
}
pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
kernel_cmdline);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
/* loader type */
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
}
if (pci_enabled) {
pci_bus = i440fx_init();
piix3_init(pci_bus);
} else {
pci_bus = NULL;
}
/* init basic PC hardware */
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
if (cirrus_vga_enabled) {
if (pci_enabled) {
pci_cirrus_vga_init(pci_bus,
ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
} else {
isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
} else {
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size, 0, 0);
}
rtc_state = rtc_init(0x70, 8);
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
if (pci_enabled) {
ioapic = ioapic_init();
}
isa_pic = pic_init(pic_irq_request, first_cpu);
pit = pit_init(0x40, 0);
pcspk_init(pit);
if (pci_enabled) {
pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
serial_init(&pic_set_irq_new, isa_pic,
serial_io[i], serial_irq[i], serial_hds[i]);
}
}
for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
if (parallel_hds[i]) {
parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]);
}
}
for(i = 0; i < nb_nics; i++) {
nd = &nd_table[i];
if (!nd->model) {
if (pci_enabled) {
nd->model = "ne2k_pci";
} else {
nd->model = "ne2k_isa";
}
}
if (strcmp(nd->model, "ne2k_isa") == 0) {
pc_init_ne2k_isa(nd);
} else if (pci_enabled) {
pci_nic_init(pci_bus, nd);
} else {
fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
exit(1);
}
}
if (pci_enabled) {
pci_piix3_ide_init(pci_bus, bs_table);
} else {
for(i = 0; i < 2; i++) {
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
bs_table[2 * i], bs_table[2 * i + 1]);
}
}
kbd_init();
DMA_init(0);
#ifdef HAS_AUDIO
audio_init(pci_enabled ? pci_bus : NULL);
#endif
floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
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);
}
/* must be done after all PCI devices are instanciated */
/* XXX: should be done in the Bochs BIOS */
if (pci_enabled) {
pci_bios_init();
}
}
static void pc_init_pci(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename,
int snapshot,
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename)
{
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
initrd_filename, 1);
}
static void pc_init_isa(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename,
int snapshot,
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename)
{
pc_init1(ram_size, vga_ram_size, boot_device,
ds, fd_filename, snapshot,
kernel_filename, kernel_cmdline,
initrd_filename, 0);
}
QEMUMachine pc_machine = {
"pc",
"Standard PC",
pc_init_pci,
};
QEMUMachine isapc_machine = {
"isapc",
"ISA-only PC",
pc_init_isa,
};

1855
hw/pci.c Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More